1 // license:BSD-3-Clause
2 // copyright-holders:Olivier Galibert
3 /*
4 Dreamcast video emulation
5 */
6
7 #include "emu.h"
8 #include "powervr2.h"
9 #include "includes/dc.h"
10
11 #include "cpu/sh/sh4.h"
12 #include "video/rgbutil.h"
13 #include "rendutil.h"
14
15
16 DEFINE_DEVICE_TYPE(POWERVR2, powervr2_device, "powervr2", "PowerVR 2")
17
ta_map(address_map & map)18 void powervr2_device::ta_map(address_map &map)
19 {
20 map(0x0000, 0x0003).r(FUNC(powervr2_device::id_r));
21 map(0x0004, 0x0007).r(FUNC(powervr2_device::revision_r));
22 map(0x0008, 0x000b).rw(FUNC(powervr2_device::softreset_r), FUNC(powervr2_device::softreset_w));
23 map(0x0014, 0x0017).w(FUNC(powervr2_device::startrender_w));
24 // 18 = test select
25 map(0x0020, 0x0023).rw(FUNC(powervr2_device::param_base_r), FUNC(powervr2_device::param_base_w));
26 map(0x002c, 0x002f).rw(FUNC(powervr2_device::region_base_r), FUNC(powervr2_device::region_base_w));
27 // 30 = span sort cfg
28 map(0x0040, 0x0043).rw(FUNC(powervr2_device::vo_border_col_r), FUNC(powervr2_device::vo_border_col_w));
29 map(0x0044, 0x0047).rw(FUNC(powervr2_device::fb_r_ctrl_r), FUNC(powervr2_device::fb_r_ctrl_w));
30 map(0x0048, 0x004b).rw(FUNC(powervr2_device::fb_w_ctrl_r), FUNC(powervr2_device::fb_w_ctrl_w));
31 map(0x004c, 0x004f).rw(FUNC(powervr2_device::fb_w_linestride_r), FUNC(powervr2_device::fb_w_linestride_w));
32 map(0x0050, 0x0053).rw(FUNC(powervr2_device::fb_r_sof1_r), FUNC(powervr2_device::fb_r_sof1_w));
33 map(0x0054, 0x0057).rw(FUNC(powervr2_device::fb_r_sof2_r), FUNC(powervr2_device::fb_r_sof2_w));
34 map(0x005c, 0x005f).rw(FUNC(powervr2_device::fb_r_size_r), FUNC(powervr2_device::fb_r_size_w));
35 map(0x0060, 0x0063).rw(FUNC(powervr2_device::fb_w_sof1_r), FUNC(powervr2_device::fb_w_sof1_w));
36 map(0x0064, 0x0067).rw(FUNC(powervr2_device::fb_w_sof2_r), FUNC(powervr2_device::fb_w_sof2_w));
37 map(0x0068, 0x006b).rw(FUNC(powervr2_device::fb_x_clip_r), FUNC(powervr2_device::fb_x_clip_w));
38 map(0x006c, 0x006f).rw(FUNC(powervr2_device::fb_y_clip_r), FUNC(powervr2_device::fb_y_clip_w));
39 // 74 = fpu_shad_scale
40 // 78 = fpu_cull_val
41 map(0x007c, 0x007f).rw(FUNC(powervr2_device::fpu_param_cfg_r), FUNC(powervr2_device::fpu_param_cfg_w));
42 // 80 = half_offset
43 // 84 = fpu_perp_val
44 // 88 = isp_backgnd_d
45 map(0x008c, 0x008f).rw(FUNC(powervr2_device::isp_backgnd_t_r), FUNC(powervr2_device::isp_backgnd_t_w));
46 // 98 = isp_feed_cfg
47 // a0 = sdram_refresh
48 // a4 = sdram_arb_cfg
49 // a8 = sdram_cfg
50 // b0 = fog_col_ram
51 // b4 = fog_col_vert
52 // b8 = fog_density
53 // bc = fog_clamp_max
54 // c0 = fog_clamp_min
55 // c4 = spg_trigger_pos
56 map(0x00c8, 0x00cb).rw(FUNC(powervr2_device::spg_hblank_int_r), FUNC(powervr2_device::spg_hblank_int_w));
57 map(0x00cc, 0x00cf).rw(FUNC(powervr2_device::spg_vblank_int_r), FUNC(powervr2_device::spg_vblank_int_w));
58 map(0x00d0, 0x00d3).rw(FUNC(powervr2_device::spg_control_r), FUNC(powervr2_device::spg_control_w));
59 map(0x00d4, 0x00d7).rw(FUNC(powervr2_device::spg_hblank_r), FUNC(powervr2_device::spg_hblank_w));
60 map(0x00d8, 0x00db).rw(FUNC(powervr2_device::spg_load_r), FUNC(powervr2_device::spg_load_w));
61 map(0x00dc, 0x00df).rw(FUNC(powervr2_device::spg_vblank_r), FUNC(powervr2_device::spg_vblank_w));
62 map(0x00e0, 0x00e3).rw(FUNC(powervr2_device::spg_width_r), FUNC(powervr2_device::spg_width_w));
63 map(0x00e4, 0x00e7).rw(FUNC(powervr2_device::text_control_r), FUNC(powervr2_device::text_control_w));
64 map(0x00e8, 0x00eb).rw(FUNC(powervr2_device::vo_control_r), FUNC(powervr2_device::vo_control_w));
65 map(0x00ec, 0x00ef).rw(FUNC(powervr2_device::vo_startx_r), FUNC(powervr2_device::vo_startx_w));
66 map(0x00f0, 0x00f3).rw(FUNC(powervr2_device::vo_starty_r), FUNC(powervr2_device::vo_starty_w));
67 // f4 = scaler_ctl
68 map(0x0108, 0x010b).rw(FUNC(powervr2_device::pal_ram_ctrl_r), FUNC(powervr2_device::pal_ram_ctrl_w));
69 map(0x010c, 0x010f).r(FUNC(powervr2_device::spg_status_r));
70 // 110 = fb_burstctrl
71 // 118 = y_coeff
72 // 11c = pt_alpha_ref
73
74 map(0x0124, 0x0127).rw(FUNC(powervr2_device::ta_ol_base_r), FUNC(powervr2_device::ta_ol_base_w));
75 map(0x0128, 0x012b).rw(FUNC(powervr2_device::ta_isp_base_r), FUNC(powervr2_device::ta_isp_base_w));
76 map(0x012c, 0x012f).rw(FUNC(powervr2_device::ta_ol_limit_r), FUNC(powervr2_device::ta_ol_limit_w));
77 map(0x0130, 0x0133).rw(FUNC(powervr2_device::ta_isp_limit_r), FUNC(powervr2_device::ta_isp_limit_w));
78 map(0x0134, 0x0137).r(FUNC(powervr2_device::ta_next_opb_r));
79 map(0x0138, 0x013b).r(FUNC(powervr2_device::ta_itp_current_r));
80 // 13c = ta_glob_tile_clip
81 map(0x0140, 0x0143).rw(FUNC(powervr2_device::ta_alloc_ctrl_r), FUNC(powervr2_device::ta_alloc_ctrl_w));
82 map(0x0144, 0x0147).rw(FUNC(powervr2_device::ta_list_init_r), FUNC(powervr2_device::ta_list_init_w));
83 map(0x0148, 0x014b).rw(FUNC(powervr2_device::ta_yuv_tex_base_r), FUNC(powervr2_device::ta_yuv_tex_base_w));
84 map(0x014c, 0x014f).rw(FUNC(powervr2_device::ta_yuv_tex_ctrl_r), FUNC(powervr2_device::ta_yuv_tex_ctrl_w));
85 map(0x0150, 0x0153).rw(FUNC(powervr2_device::ta_yuv_tex_cnt_r), FUNC(powervr2_device::ta_yuv_tex_cnt_w));
86 map(0x0160, 0x0163).w(FUNC(powervr2_device::ta_list_cont_w));
87 map(0x0164, 0x0167).rw(FUNC(powervr2_device::ta_next_opb_init_r), FUNC(powervr2_device::ta_next_opb_init_w));
88
89 map(0x0200, 0x03ff).rw(FUNC(powervr2_device::fog_table_r), FUNC(powervr2_device::fog_table_w));
90 map(0x1000, 0x1fff).rw(FUNC(powervr2_device::palette_r), FUNC(powervr2_device::palette_w));
91 }
92
pd_dma_map(address_map & map)93 void powervr2_device::pd_dma_map(address_map &map)
94 {
95 map(0x00, 0x03).rw(FUNC(powervr2_device::sb_pdstap_r), FUNC(powervr2_device::sb_pdstap_w));
96 map(0x04, 0x07).rw(FUNC(powervr2_device::sb_pdstar_r), FUNC(powervr2_device::sb_pdstar_w));
97 map(0x08, 0x0b).rw(FUNC(powervr2_device::sb_pdlen_r), FUNC(powervr2_device::sb_pdlen_w));
98 map(0x0c, 0x0f).rw(FUNC(powervr2_device::sb_pddir_r), FUNC(powervr2_device::sb_pddir_w));
99 map(0x10, 0x13).rw(FUNC(powervr2_device::sb_pdtsel_r), FUNC(powervr2_device::sb_pdtsel_w));
100 map(0x14, 0x17).rw(FUNC(powervr2_device::sb_pden_r), FUNC(powervr2_device::sb_pden_w));
101 map(0x18, 0x1b).rw(FUNC(powervr2_device::sb_pdst_r), FUNC(powervr2_device::sb_pdst_w));
102 map(0x80, 0x83).rw(FUNC(powervr2_device::sb_pdapro_r), FUNC(powervr2_device::sb_pdapro_w));
103 }
104
105 const int powervr2_device::pvr_parconfseq[] = {1,2,3,2,3,4,5,6,5,6,7,8,9,10,11,12,13,14,13,14,15,16,17,16,17,0,0,0,0,0,18,19,20,19,20,21,22,23,22,23};
106 const int powervr2_device::pvr_wordsvertex[24] = {8,8,8,8,8,16,16,8,8,8, 8, 8,8,8,8,8,16,16, 8,16,16,8,16,16};
107 const int powervr2_device::pvr_wordspolygon[24] = {8,8,8,8,8, 8, 8,8,8,8,16,16,8,8,8,8, 8, 8,16,16,16,8, 8, 8};
108
109 #define DEBUG_FIFO_POLY (0)
110 #define DEBUG_PVRTA 0
111 #define DEBUG_PVRDLIST (0)
112 #define DEBUG_PALRAM (0)
113 #define DEBUG_PVRCTRL (0)
114
clamp(int32_t in,int32_t min,int32_t max)115 inline int32_t powervr2_device::clamp(int32_t in, int32_t min, int32_t max)
116 {
117 if(in < min) return min;
118 if(in > max) return max;
119 return in;
120 }
121
122 // Perform a standard bilinear filter across four pixels
bilinear_filter(uint32_t c0,uint32_t c1,uint32_t c2,uint32_t c3,float u,float v)123 inline uint32_t powervr2_device::bilinear_filter(uint32_t c0, uint32_t c1, uint32_t c2, uint32_t c3, float u, float v)
124 {
125 const uint32_t ui = (u * 256.0f);
126 const uint32_t vi = (v * 256.0f);
127 return rgbaint_t::bilinear_filter(c0, c1, c3, c2, ui, vi);
128 }
129
130 // Multiply with alpha value in bits 31-24
bla(uint32_t c,uint32_t a)131 inline uint32_t powervr2_device::bla(uint32_t c, uint32_t a)
132 {
133 a = a >> 24;
134 return ((((c & 0xff00ff)*a) & 0xff00ff00) >> 8) | ((((c >> 8) & 0xff00ff)*a) & 0xff00ff00);
135 }
136
137 // Multiply with 1-alpha value in bits 31-24
blia(uint32_t c,uint32_t a)138 inline uint32_t powervr2_device::blia(uint32_t c, uint32_t a)
139 {
140 a = 0x100 - (a >> 24);
141 return ((((c & 0xff00ff)*a) & 0xff00ff00) >> 8) | ((((c >> 8) & 0xff00ff)*a) & 0xff00ff00);
142 }
143
144 // Per-component multiply with color value
blc(uint32_t c1,uint32_t c2)145 inline uint32_t powervr2_device::blc(uint32_t c1, uint32_t c2)
146 {
147 uint32_t cr =
148 (((c1 & 0x000000ff)*(c2 & 0x000000ff) & 0x0000ff00) >> 8) |
149 (((c1 & 0x0000ff00)*(c2 & 0x0000ff00) & 0xff000000) >> 16);
150 c1 >>= 16;
151 c2 >>= 16;
152 cr |=
153 (((c1 & 0x000000ff)*(c2 & 0x000000ff) & 0x0000ff00) << 8) |
154 (((c1 & 0x0000ff00)*(c2 & 0x0000ff00) & 0xff000000));
155 return cr;
156 }
157
158 // Per-component multiply with 1-color value
blic(uint32_t c1,uint32_t c2)159 inline uint32_t powervr2_device::blic(uint32_t c1, uint32_t c2)
160 {
161 uint32_t cr =
162 (((c1 & 0x000000ff)*(0x00100-(c2 & 0x000000ff)) & 0x0000ff00) >> 8) |
163 (((c1 & 0x0000ff00)*(0x10000-(c2 & 0x0000ff00)) & 0xff000000) >> 16);
164 c1 >>= 16;
165 c2 >>= 16;
166 cr |=
167 (((c1 & 0x000000ff)*(0x00100-(c2 & 0x000000ff)) & 0x0000ff00) << 8) |
168 (((c1 & 0x0000ff00)*(0x10000-(c2 & 0x0000ff00)) & 0xff000000));
169 return cr;
170 }
171
172 // Add two colors with saturation
bls(uint32_t c1,uint32_t c2)173 inline uint32_t powervr2_device::bls(uint32_t c1, uint32_t c2)
174 {
175 uint32_t cr1, cr2;
176 cr1 = (c1 & 0x00ff00ff) + (c2 & 0x00ff00ff);
177 if(cr1 & 0x0000ff00)
178 cr1 = (cr1 & 0xffff00ff) | 0x000000ff;
179 if(cr1 & 0xff000000)
180 cr1 = (cr1 & 0x00ffffff) | 0x00ff0000;
181
182 cr2 = ((c1 >> 8) & 0x00ff00ff) + ((c2 >> 8) & 0x00ff00ff);
183 if(cr2 & 0x0000ff00)
184 cr2 = (cr2 & 0xffff00ff) | 0x000000ff;
185 if(cr2 & 0xff000000)
186 cr2 = (cr2 & 0x00ffffff) | 0x00ff0000;
187 return cr1|(cr2 << 8);
188 }
189
190 /*
191 * Add two colors with saturation, not including the alpha channel
192 * The only difference between this function and bls is that bls does not
193 * ignore alpha. The alpha will be cleared to zero by this instruction
194 */
bls24(uint32_t c1,uint32_t c2)195 inline uint32_t powervr2_device::bls24(uint32_t c1, uint32_t c2)
196 {
197 uint32_t cr1, cr2;
198 cr1 = (c1 & 0x00ff00ff) + (c2 & 0x00ff00ff);
199 if(cr1 & 0x0000ff00)
200 cr1 = (cr1 & 0xffff00ff) | 0x000000ff;
201 if(cr1 & 0xff000000)
202 cr1 = (cr1 & 0x00ffffff) | 0x00ff0000;
203
204 cr2 = ((c1 >> 8) & 0x000000ff) + ((c2 >> 8) & 0x000000ff);
205 if(cr2 & 0x0000ff00)
206 cr2 = (cr2 & 0xffff00ff) | 0x000000ff;
207 return cr1|(cr2 << 8);
208 }
209
float_argb_to_packed_argb(float argb[4])210 inline uint32_t powervr2_device::float_argb_to_packed_argb(float argb[4]) {
211 int argb_int[4] = {
212 (int)(argb[0] * 256.0f),
213 (int)(argb[1] * 256.0f),
214 (int)(argb[2] * 256.0f),
215 (int)(argb[3] * 256.0f)
216 };
217
218 // clamp to [0, 255]
219 int idx;
220 for (idx = 0; idx < 4; idx++) {
221 if (argb_int[idx] < 0)
222 argb_int[idx] = 0;
223 else if (argb_int[idx] > 255)
224 argb_int[idx] = 255;
225 }
226
227 return (argb_int[0] << 24) | (argb_int[1] << 16) |
228 (argb_int[2] << 8) | argb_int[3];
229 }
230
packed_argb_to_float_argb(float dst[4],uint32_t in)231 inline void powervr2_device::packed_argb_to_float_argb(float dst[4], uint32_t in) {
232 dst[0] = (in >> 24) / 256.0f;
233 dst[1] = ((in >> 16) & 0xff) / 256.0f;
234 dst[2] = ((in >> 8) & 0xff) / 256.0f;
235 dst[3] = (in & 0xff) / 256.0f;
236 }
237
238 // All 64 blending modes, 3 top bits are source mode, 3 bottom bits are destination mode
bl00(uint32_t s,uint32_t d)239 uint32_t powervr2_device::bl00(uint32_t s, uint32_t d) { return 0; }
bl01(uint32_t s,uint32_t d)240 uint32_t powervr2_device::bl01(uint32_t s, uint32_t d) { return d; }
bl02(uint32_t s,uint32_t d)241 uint32_t powervr2_device::bl02(uint32_t s, uint32_t d) { return blc(d, s); }
bl03(uint32_t s,uint32_t d)242 uint32_t powervr2_device::bl03(uint32_t s, uint32_t d) { return blic(d, s); }
bl04(uint32_t s,uint32_t d)243 uint32_t powervr2_device::bl04(uint32_t s, uint32_t d) { return bla(d, s); }
bl05(uint32_t s,uint32_t d)244 uint32_t powervr2_device::bl05(uint32_t s, uint32_t d) { return blia(d, s); }
bl06(uint32_t s,uint32_t d)245 uint32_t powervr2_device::bl06(uint32_t s, uint32_t d) { return bla(d, d); }
bl07(uint32_t s,uint32_t d)246 uint32_t powervr2_device::bl07(uint32_t s, uint32_t d) { return blia(d, d); }
bl10(uint32_t s,uint32_t d)247 uint32_t powervr2_device::bl10(uint32_t s, uint32_t d) { return s; }
bl11(uint32_t s,uint32_t d)248 uint32_t powervr2_device::bl11(uint32_t s, uint32_t d) { return bls(s, d); }
bl12(uint32_t s,uint32_t d)249 uint32_t powervr2_device::bl12(uint32_t s, uint32_t d) { return bls(s, blc(s, d)); }
bl13(uint32_t s,uint32_t d)250 uint32_t powervr2_device::bl13(uint32_t s, uint32_t d) { return bls(s, blic(s, d)); }
bl14(uint32_t s,uint32_t d)251 uint32_t powervr2_device::bl14(uint32_t s, uint32_t d) { return bls(s, bla(d, s)); }
bl15(uint32_t s,uint32_t d)252 uint32_t powervr2_device::bl15(uint32_t s, uint32_t d) { return bls(s, blia(d, s)); }
bl16(uint32_t s,uint32_t d)253 uint32_t powervr2_device::bl16(uint32_t s, uint32_t d) { return bls(s, bla(d, d)); }
bl17(uint32_t s,uint32_t d)254 uint32_t powervr2_device::bl17(uint32_t s, uint32_t d) { return bls(s, blia(d, d)); }
bl20(uint32_t s,uint32_t d)255 uint32_t powervr2_device::bl20(uint32_t s, uint32_t d) { return blc(d, s); }
bl21(uint32_t s,uint32_t d)256 uint32_t powervr2_device::bl21(uint32_t s, uint32_t d) { return bls(blc(d, s), d); }
bl22(uint32_t s,uint32_t d)257 uint32_t powervr2_device::bl22(uint32_t s, uint32_t d) { return bls(blc(d, s), blc(s, d)); }
bl23(uint32_t s,uint32_t d)258 uint32_t powervr2_device::bl23(uint32_t s, uint32_t d) { return bls(blc(d, s), blic(s, d)); }
bl24(uint32_t s,uint32_t d)259 uint32_t powervr2_device::bl24(uint32_t s, uint32_t d) { return bls(blc(d, s), bla(d, s)); }
bl25(uint32_t s,uint32_t d)260 uint32_t powervr2_device::bl25(uint32_t s, uint32_t d) { return bls(blc(d, s), blia(d, s)); }
bl26(uint32_t s,uint32_t d)261 uint32_t powervr2_device::bl26(uint32_t s, uint32_t d) { return bls(blc(d, s), bla(d, d)); }
bl27(uint32_t s,uint32_t d)262 uint32_t powervr2_device::bl27(uint32_t s, uint32_t d) { return bls(blc(d, s), blia(d, d)); }
bl30(uint32_t s,uint32_t d)263 uint32_t powervr2_device::bl30(uint32_t s, uint32_t d) { return blic(d, s); }
bl31(uint32_t s,uint32_t d)264 uint32_t powervr2_device::bl31(uint32_t s, uint32_t d) { return bls(blic(d, s), d); }
bl32(uint32_t s,uint32_t d)265 uint32_t powervr2_device::bl32(uint32_t s, uint32_t d) { return bls(blic(d, s), blc(s, d)); }
bl33(uint32_t s,uint32_t d)266 uint32_t powervr2_device::bl33(uint32_t s, uint32_t d) { return bls(blic(d, s), blic(s, d)); }
bl34(uint32_t s,uint32_t d)267 uint32_t powervr2_device::bl34(uint32_t s, uint32_t d) { return bls(blic(d, s), bla(d, s)); }
bl35(uint32_t s,uint32_t d)268 uint32_t powervr2_device::bl35(uint32_t s, uint32_t d) { return bls(blic(d, s), blia(d, s)); }
bl36(uint32_t s,uint32_t d)269 uint32_t powervr2_device::bl36(uint32_t s, uint32_t d) { return bls(blic(d, s), bla(d, d)); }
bl37(uint32_t s,uint32_t d)270 uint32_t powervr2_device::bl37(uint32_t s, uint32_t d) { return bls(blic(d, s), blia(d, d)); }
bl40(uint32_t s,uint32_t d)271 uint32_t powervr2_device::bl40(uint32_t s, uint32_t d) { return bla(s, s); }
bl41(uint32_t s,uint32_t d)272 uint32_t powervr2_device::bl41(uint32_t s, uint32_t d) { return bls(bla(s, s), d); }
bl42(uint32_t s,uint32_t d)273 uint32_t powervr2_device::bl42(uint32_t s, uint32_t d) { return bls(bla(s, s), blc(s, d)); }
bl43(uint32_t s,uint32_t d)274 uint32_t powervr2_device::bl43(uint32_t s, uint32_t d) { return bls(bla(s, s), blic(s, d)); }
bl44(uint32_t s,uint32_t d)275 uint32_t powervr2_device::bl44(uint32_t s, uint32_t d) { return bls(bla(s, s), bla(d, s)); }
bl45(uint32_t s,uint32_t d)276 uint32_t powervr2_device::bl45(uint32_t s, uint32_t d) { return bls(bla(s, s), blia(d, s)); }
bl46(uint32_t s,uint32_t d)277 uint32_t powervr2_device::bl46(uint32_t s, uint32_t d) { return bls(bla(s, s), bla(d, d)); }
bl47(uint32_t s,uint32_t d)278 uint32_t powervr2_device::bl47(uint32_t s, uint32_t d) { return bls(bla(s, s), blia(d, d)); }
bl50(uint32_t s,uint32_t d)279 uint32_t powervr2_device::bl50(uint32_t s, uint32_t d) { return blia(s, s); }
bl51(uint32_t s,uint32_t d)280 uint32_t powervr2_device::bl51(uint32_t s, uint32_t d) { return bls(blia(s, s), d); }
bl52(uint32_t s,uint32_t d)281 uint32_t powervr2_device::bl52(uint32_t s, uint32_t d) { return bls(blia(s, s), blc(s, d)); }
bl53(uint32_t s,uint32_t d)282 uint32_t powervr2_device::bl53(uint32_t s, uint32_t d) { return bls(blia(s, s), blic(s, d)); }
bl54(uint32_t s,uint32_t d)283 uint32_t powervr2_device::bl54(uint32_t s, uint32_t d) { return bls(blia(s, s), bla(d, s)); }
bl55(uint32_t s,uint32_t d)284 uint32_t powervr2_device::bl55(uint32_t s, uint32_t d) { return bls(blia(s, s), blia(d, s)); }
bl56(uint32_t s,uint32_t d)285 uint32_t powervr2_device::bl56(uint32_t s, uint32_t d) { return bls(blia(s, s), bla(d, d)); }
bl57(uint32_t s,uint32_t d)286 uint32_t powervr2_device::bl57(uint32_t s, uint32_t d) { return bls(blia(s, s), blia(d, d)); }
bl60(uint32_t s,uint32_t d)287 uint32_t powervr2_device::bl60(uint32_t s, uint32_t d) { return bla(s, d); }
bl61(uint32_t s,uint32_t d)288 uint32_t powervr2_device::bl61(uint32_t s, uint32_t d) { return bls(bla(s, d), d); }
bl62(uint32_t s,uint32_t d)289 uint32_t powervr2_device::bl62(uint32_t s, uint32_t d) { return bls(bla(s, d), blc(s, d)); }
bl63(uint32_t s,uint32_t d)290 uint32_t powervr2_device::bl63(uint32_t s, uint32_t d) { return bls(bla(s, d), blic(s, d)); }
bl64(uint32_t s,uint32_t d)291 uint32_t powervr2_device::bl64(uint32_t s, uint32_t d) { return bls(bla(s, d), bla(d, s)); }
bl65(uint32_t s,uint32_t d)292 uint32_t powervr2_device::bl65(uint32_t s, uint32_t d) { return bls(bla(s, d), blia(d, s)); }
bl66(uint32_t s,uint32_t d)293 uint32_t powervr2_device::bl66(uint32_t s, uint32_t d) { return bls(bla(s, d), bla(d, d)); }
bl67(uint32_t s,uint32_t d)294 uint32_t powervr2_device::bl67(uint32_t s, uint32_t d) { return bls(bla(s, d), blia(d, d)); }
bl70(uint32_t s,uint32_t d)295 uint32_t powervr2_device::bl70(uint32_t s, uint32_t d) { return blia(s, d); }
bl71(uint32_t s,uint32_t d)296 uint32_t powervr2_device::bl71(uint32_t s, uint32_t d) { return bls(blia(s, d), d); }
bl72(uint32_t s,uint32_t d)297 uint32_t powervr2_device::bl72(uint32_t s, uint32_t d) { return bls(blia(s, d), blc(s, d)); }
bl73(uint32_t s,uint32_t d)298 uint32_t powervr2_device::bl73(uint32_t s, uint32_t d) { return bls(blia(s, d), blic(s, d)); }
bl74(uint32_t s,uint32_t d)299 uint32_t powervr2_device::bl74(uint32_t s, uint32_t d) { return bls(blia(s, d), bla(d, s)); }
bl75(uint32_t s,uint32_t d)300 uint32_t powervr2_device::bl75(uint32_t s, uint32_t d) { return bls(blia(s, d), blia(d, s)); }
bl76(uint32_t s,uint32_t d)301 uint32_t powervr2_device::bl76(uint32_t s, uint32_t d) { return bls(blia(s, d), bla(d, d)); }
bl77(uint32_t s,uint32_t d)302 uint32_t powervr2_device::bl77(uint32_t s, uint32_t d) { return bls(blia(s, d), blia(d, d)); }
303
304 uint32_t (*const powervr2_device::blend_functions[64])(uint32_t s, uint32_t d) = {
305 bl00, bl01, bl02, bl03, bl04, bl05, bl06, bl07,
306 bl10, bl11, bl12, bl13, bl14, bl15, bl16, bl17,
307 bl20, bl21, bl22, bl23, bl24, bl25, bl26, bl27,
308 bl30, bl31, bl32, bl33, bl34, bl35, bl36, bl37,
309 bl40, bl41, bl42, bl43, bl44, bl45, bl46, bl47,
310 bl50, bl51, bl52, bl53, bl54, bl55, bl56, bl57,
311 bl60, bl61, bl62, bl63, bl64, bl65, bl66, bl67,
312 bl70, bl71, bl72, bl73, bl74, bl75, bl76, bl77,
313 };
314
cv_1555(uint16_t c)315 inline uint32_t powervr2_device::cv_1555(uint16_t c)
316 {
317 return
318 (c & 0x8000 ? 0xff000000 : 0) |
319 ((c << 9) & 0x00f80000) | ((c << 4) & 0x00070000) |
320 ((c << 6) & 0x0000f800) | ((c << 1) & 0x00000700) |
321 ((c << 3) & 0x000000f8) | ((c >> 2) & 0x00000007);
322 }
323
cv_1555z(uint16_t c)324 inline uint32_t powervr2_device::cv_1555z(uint16_t c)
325 {
326 return
327 (c & 0x8000 ? 0xff000000 : 0) |
328 ((c << 9) & 0x00f80000) |
329 ((c << 6) & 0x0000f800) |
330 ((c << 3) & 0x000000f8);
331 }
332
cv_565(uint16_t c)333 inline uint32_t powervr2_device::cv_565(uint16_t c)
334 {
335 return
336 0xff000000 |
337 ((c << 8) & 0x00f80000) | ((c << 3) & 0x00070000) |
338 ((c << 5) & 0x0000fc00) | ((c >> 1) & 0x00000300) |
339 ((c << 3) & 0x000000f8) | ((c >> 2) & 0x00000007);
340 }
341
cv_565z(uint16_t c)342 inline uint32_t powervr2_device::cv_565z(uint16_t c)
343 {
344 return
345 0xff000000 |
346 ((c << 8) & 0x00f80000) |
347 ((c << 5) & 0x0000fc00) |
348 ((c << 3) & 0x000000f8);
349 }
350
cv_4444(uint16_t c)351 inline uint32_t powervr2_device::cv_4444(uint16_t c)
352 {
353 return
354 ((c << 16) & 0xf0000000) | ((c << 12) & 0x0f000000) |
355 ((c << 12) & 0x00f00000) | ((c << 8) & 0x000f0000) |
356 ((c << 8) & 0x0000f000) | ((c << 4) & 0x00000f00) |
357 ((c << 4) & 0x000000f0) | ((c ) & 0x0000000f);
358 }
359
cv_4444z(uint16_t c)360 inline uint32_t powervr2_device::cv_4444z(uint16_t c)
361 {
362 return
363 ((c << 16) & 0xf0000000) |
364 ((c << 12) & 0x00f00000) |
365 ((c << 8) & 0x0000f000) |
366 ((c << 4) & 0x000000f0);
367 }
368
cv_yuv(uint16_t c1,uint16_t c2,int x)369 inline uint32_t powervr2_device::cv_yuv(uint16_t c1, uint16_t c2, int x)
370 {
371 int u = 11*((c1 & 0xff) - 128);
372 int v = 11*((c2 & 0xff) - 128);
373 int y = (x & 1 ? c2 : c1) >> 8;
374 int r = y + v/8;
375 int g = y - u/32 - v/16;
376 int b = y + (3*u)/16;
377 r = r < 0 ? 0 : r > 255 ? 255 : r;
378 g = g < 0 ? 0 : g > 255 ? 255 : g;
379 b = b < 0 ? 0 : b > 255 ? 255 : b;
380 return 0xff000000 | (r << 16) | (g << 8) | b;
381 }
382
uv_wrap(float uv,int size)383 int powervr2_device::uv_wrap(float uv, int size)
384 {
385 int iuv = (int)uv;
386 return iuv & (size - 1);
387 }
uv_flip(float uv,int size)388 int powervr2_device::uv_flip(float uv, int size)
389 {
390 int iuv = (int)uv;
391 return ((iuv & size) ? ~iuv : iuv) & (size - 1);
392 }
uv_clamp(float uv,int size)393 int powervr2_device::uv_clamp(float uv, int size)
394 {
395 int iuv = (int)uv;
396 return (iuv > 0) ? (iuv < size) ? iuv : (size - 1) : 0;
397 }
398
tex_r_yuv_n(texinfo * t,float x,float y)399 uint32_t powervr2_device::tex_r_yuv_n(texinfo *t, float x, float y)
400 {
401 int xt = t->u_func(x, t->sizex);
402 int yt = t->v_func(y, t->sizey);
403 int addrp = t->address + (t->stride*yt + (xt & ~1))*2;
404 uint16_t c1 = *(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp));
405 uint16_t c2 = *(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp+2));
406 return cv_yuv(c1, c2, xt);
407 }
408
tex_r_yuv_tw(texinfo * t,float x,float y)409 uint32_t powervr2_device::tex_r_yuv_tw(texinfo *t, float x, float y)
410 {
411 int xt = t->u_func(x, t->sizex);
412 int yt = t->v_func(y, t->sizey);
413 int addrp = t->address + (dilated1[t->cd][xt & ~1] + dilated0[t->cd][yt]) * 2;
414 uint16_t c1 = *(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp));
415 uint16_t c2 = *(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp+4));
416 return cv_yuv(c1, c2, xt);
417 }
418
419 #if 0
420 uint32_t powervr2_device::tex_r_yuv_vq(texinfo *t, float x, float y)
421 {
422 int xt = t->u_func(x, t->sizex);
423 int yt = t->v_func(y, t->sizey);
424 int idx = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])];
425 int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2;
426 uint16_t c1 = *(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp));
427 uint16_t c2 = *(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp+4));
428 return cv_yuv(c1, c2, xt);
429 }
430 #endif
431
tex_r_1555_n(texinfo * t,float x,float y)432 uint32_t powervr2_device::tex_r_1555_n(texinfo *t, float x, float y)
433 {
434 int xt = t->u_func(x, t->sizex);
435 int yt = t->v_func(y, t->sizey);
436 int addrp = t->address + (t->stride*yt + xt) * 2;
437 return cv_1555z(*(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp)));
438 }
439
tex_r_1555_tw(texinfo * t,float x,float y)440 uint32_t powervr2_device::tex_r_1555_tw(texinfo *t, float x, float y)
441 {
442 int xt = t->u_func(x, t->sizex);
443 int yt = t->v_func(y, t->sizey);
444 int addrp = t->address + (dilated1[t->cd][xt] + dilated0[t->cd][yt]) * 2;
445 return cv_1555(*(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp)));
446 }
447
tex_r_1555_vq(texinfo * t,float x,float y)448 uint32_t powervr2_device::tex_r_1555_vq(texinfo *t, float x, float y)
449 {
450 int xt = t->u_func(x, t->sizex);
451 int yt = t->v_func(y, t->sizey);
452 int idx = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])];
453 int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2;
454 return cv_1555(*(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp)));
455 }
456
tex_r_565_n(texinfo * t,float x,float y)457 uint32_t powervr2_device::tex_r_565_n(texinfo *t, float x, float y)
458 {
459 int xt = t->u_func(x, t->sizex);
460 int yt = t->v_func(y, t->sizey);
461 int addrp = t->address + (t->stride*yt + xt) * 2;
462 return cv_565z(*(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp)));
463 }
464
tex_r_565_tw(texinfo * t,float x,float y)465 uint32_t powervr2_device::tex_r_565_tw(texinfo *t, float x, float y)
466 {
467 int xt = t->u_func(x, t->sizex);
468 int yt = t->v_func(y, t->sizey);
469 int addrp = t->address + (dilated1[t->cd][xt] + dilated0[t->cd][yt]) * 2;
470 return cv_565(*(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp)));
471 }
472
tex_r_565_vq(texinfo * t,float x,float y)473 uint32_t powervr2_device::tex_r_565_vq(texinfo *t, float x, float y)
474 {
475 int xt = t->u_func(x, t->sizex);
476 int yt = t->v_func(y, t->sizey);
477 int idx = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])];
478 int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2;
479 return cv_565(*(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp)));
480 }
481
tex_r_4444_n(texinfo * t,float x,float y)482 uint32_t powervr2_device::tex_r_4444_n(texinfo *t, float x, float y)
483 {
484 int xt = t->u_func(x, t->sizex);
485 int yt = t->v_func(y, t->sizey);
486 int addrp = t->address + (t->stride*yt + xt) * 2;
487 return cv_4444z(*(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp)));
488 }
489
tex_r_4444_tw(texinfo * t,float x,float y)490 uint32_t powervr2_device::tex_r_4444_tw(texinfo *t, float x, float y)
491 {
492 int xt = t->u_func(x, t->sizex);
493 int yt = t->v_func(y, t->sizey);
494 int addrp = t->address + (dilated1[t->cd][xt] + dilated0[t->cd][yt]) * 2;
495 return cv_4444(*(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp)));
496 }
497
tex_r_4444_vq(texinfo * t,float x,float y)498 uint32_t powervr2_device::tex_r_4444_vq(texinfo *t, float x, float y)
499 {
500 int xt = t->u_func(x, t->sizex);
501 int yt = t->v_func(y, t->sizey);
502 int idx = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])];
503 int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2;
504 return cv_4444(*(uint16_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + WORD_XOR_LE(addrp)));
505 }
506
tex_r_p4_1555_tw(texinfo * t,float x,float y)507 uint32_t powervr2_device::tex_r_p4_1555_tw(texinfo *t, float x, float y)
508 {
509 int xt = t->u_func(x, t->sizex);
510 int yt = t->v_func(y, t->sizey);
511 int off = dilated1[t->cd][xt] + dilated0[t->cd][yt];
512 int addrp = t->address + (off >> 1);
513 int c = ((reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf;
514 return cv_1555(palette[t->palbase + c]);
515 }
516
tex_r_p4_1555_vq(texinfo * t,float x,float y)517 uint32_t powervr2_device::tex_r_p4_1555_vq(texinfo *t, float x, float y)
518 {
519 int xt = t->u_func(x, t->sizex);
520 int yt = t->v_func(y, t->sizey);
521 int idx = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])];
522 int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3];
523 int c = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf;
524 return cv_1555(palette[t->palbase + c]);
525 }
526
tex_r_p4_565_tw(texinfo * t,float x,float y)527 uint32_t powervr2_device::tex_r_p4_565_tw(texinfo *t, float x, float y)
528 {
529 int xt = t->u_func(x, t->sizex);
530 int yt = t->v_func(y, t->sizey);
531 int off = dilated1[t->cd][xt] + dilated0[t->cd][yt];
532 int addrp = t->address + (off >> 1);
533 int c = ((reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf;
534 return cv_565(palette[t->palbase + c]);
535 }
536
tex_r_p4_565_vq(texinfo * t,float x,float y)537 uint32_t powervr2_device::tex_r_p4_565_vq(texinfo *t, float x, float y)
538 {
539 int xt = t->u_func(x, t->sizex);
540 int yt = t->v_func(y, t->sizey);
541 int idx = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])];
542 int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3];
543 int c = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf;
544 return cv_565(palette[t->palbase + c]);
545 }
546
tex_r_p4_4444_tw(texinfo * t,float x,float y)547 uint32_t powervr2_device::tex_r_p4_4444_tw(texinfo *t, float x, float y)
548 {
549 int xt = t->u_func(x, t->sizex);
550 int yt = t->v_func(y, t->sizey);
551 int off = dilated1[t->cd][xt] + dilated0[t->cd][yt];
552 int addrp = t->address + (off >> 1);
553 int c = ((reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf;
554 return cv_4444(palette[t->palbase + c]);
555 }
556
tex_r_p4_4444_vq(texinfo * t,float x,float y)557 uint32_t powervr2_device::tex_r_p4_4444_vq(texinfo *t, float x, float y)
558 {
559 int xt = t->u_func(x, t->sizex);
560 int yt = t->v_func(y, t->sizey);
561 int idx = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])];
562 int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3];
563 int c = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf;
564 return cv_4444(palette[t->palbase + c]);
565 }
566
tex_r_p4_8888_tw(texinfo * t,float x,float y)567 uint32_t powervr2_device::tex_r_p4_8888_tw(texinfo *t, float x, float y)
568 {
569 int xt = t->u_func(x, t->sizex);
570 int yt = t->v_func(y, t->sizey);
571 int off = dilated1[t->cd][xt] + dilated0[t->cd][yt];
572 int addrp = t->address + (off >> 1);
573 int c = ((reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf;
574 return palette[t->palbase + c];
575 }
576
tex_r_p4_8888_vq(texinfo * t,float x,float y)577 uint32_t powervr2_device::tex_r_p4_8888_vq(texinfo *t, float x, float y)
578 {
579 int xt = t->u_func(x, t->sizex);
580 int yt = t->v_func(y, t->sizey);
581 int idx = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])];
582 int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3];
583 int c = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf;
584 return palette[t->palbase + c];
585 }
586
tex_r_p8_1555_tw(texinfo * t,float x,float y)587 uint32_t powervr2_device::tex_r_p8_1555_tw(texinfo *t, float x, float y)
588 {
589 int xt = t->u_func(x, t->sizex);
590 int yt = t->v_func(y, t->sizey);
591 int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt];
592 int c = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)];
593 return cv_1555(palette[t->palbase + c]);
594 }
595
tex_r_p8_1555_vq(texinfo * t,float x,float y)596 uint32_t powervr2_device::tex_r_p8_1555_vq(texinfo *t, float x, float y)
597 {
598 int xt = t->u_func(x, t->sizex);
599 int yt = t->v_func(y, t->sizey);
600 int idx = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])];
601 int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3];
602 int c = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)];
603 return cv_1555(palette[t->palbase + c]);
604 }
605
tex_r_p8_565_tw(texinfo * t,float x,float y)606 uint32_t powervr2_device::tex_r_p8_565_tw(texinfo *t, float x, float y)
607 {
608 int xt = t->u_func(x, t->sizex);
609 int yt = t->v_func(y, t->sizey);
610 int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt];
611 int c = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)];
612 return cv_565(palette[t->palbase + c]);
613 }
614
tex_r_p8_565_vq(texinfo * t,float x,float y)615 uint32_t powervr2_device::tex_r_p8_565_vq(texinfo *t, float x, float y)
616 {
617 int xt = t->u_func(x, t->sizex);
618 int yt = t->v_func(y, t->sizey);
619 int idx = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])];
620 int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3];
621 int c = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)];
622 return cv_565(palette[t->palbase + c]);
623 }
624
tex_r_p8_4444_tw(texinfo * t,float x,float y)625 uint32_t powervr2_device::tex_r_p8_4444_tw(texinfo *t, float x, float y)
626 {
627 int xt = t->u_func(x, t->sizex);
628 int yt = t->v_func(y, t->sizey);
629 int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt];
630 int c = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)];
631 return cv_4444(palette[t->palbase + c]);
632 }
633
tex_r_p8_4444_vq(texinfo * t,float x,float y)634 uint32_t powervr2_device::tex_r_p8_4444_vq(texinfo *t, float x, float y)
635 {
636 int xt = t->u_func(x, t->sizex);
637 int yt = t->v_func(y, t->sizey);
638 int idx = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])];
639 int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3];
640 int c = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)];
641 return cv_4444(palette[t->palbase + c]);
642 }
643
tex_r_p8_8888_tw(texinfo * t,float x,float y)644 uint32_t powervr2_device::tex_r_p8_8888_tw(texinfo *t, float x, float y)
645 {
646 int xt = t->u_func(x, t->sizex);
647 int yt = t->v_func(y, t->sizey);
648 int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt];
649 int c = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)];
650 return palette[t->palbase + c];
651 }
652
tex_r_p8_8888_vq(texinfo * t,float x,float y)653 uint32_t powervr2_device::tex_r_p8_8888_vq(texinfo *t, float x, float y)
654 {
655 int xt = t->u_func(x, t->sizex);
656 int yt = t->v_func(y, t->sizey);
657 int idx = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])];
658 int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3];
659 int c = (reinterpret_cast<uint8_t *>(dc_texture_ram))[BYTE_XOR_LE(addrp)];
660 return palette[t->palbase + c];
661 }
662
663
tex_r_default(texinfo * t,float x,float y)664 uint32_t powervr2_device::tex_r_default(texinfo *t, float x, float y)
665 {
666 return ((int)x ^ (int)y) & 4 ? 0xffffff00 : 0xff0000ff;
667 }
668
tex_get_info(texinfo * t)669 void powervr2_device::tex_get_info(texinfo *t)
670 {
671 int miptype = 0;
672
673 t->textured = texture;
674
675 // not textured, abort.
676 // if (!t->textured) return;
677
678 t->address = textureaddress;
679 t->pf = pixelformat;
680 t->palette = 0;
681
682 t->mode = (vqcompressed<<1);
683
684 // scanorder is ignored for palettized textures (palettized textures are ALWAYS twiddled)
685 // (the same bits are used for palette select instead)
686 if ((t->pf == 5) || (t->pf == 6))
687 {
688 t->palette = paletteselector;
689 }
690 else
691 {
692 t->mode |= scanorder;
693 }
694
695 /* When scan order is 1 (non-twiddled) mipmap is ignored */
696 t->mipmapped = t->mode & 1 ? 0 : mipmapped;
697
698 // Mipmapped textures are always square, ignore v size
699 if (t->mipmapped)
700 {
701 t->sizes = (texturesizes & 0x38) | ((texturesizes & 0x38) >> 3);
702 }
703 else
704 {
705 t->sizes = texturesizes;
706 }
707
708 t->sizex = 1 << (3+((t->sizes >> 3) & 7));
709 t->sizey = 1 << (3+(t->sizes & 7));
710
711
712 /* Stride select is used only in the non-twiddled case */
713 t->stride = (t->mode & 1) && strideselect ? (text_control & 0x1f) << 5 : t->sizex;
714
715 t->blend_mode = blend_mode;
716 t->filter_mode = filtermode;
717
718 t->u_func = (clampuv & 2) ? &powervr2_device::uv_clamp : ((flipuv & 2) ? &powervr2_device::uv_flip : &powervr2_device::uv_wrap);
719 t->v_func = (clampuv & 1) ? &powervr2_device::uv_clamp : ((flipuv & 1) ? &powervr2_device::uv_flip : &powervr2_device::uv_wrap);
720
721 t->r = &powervr2_device::tex_r_default;
722 t->cd = dilatechose[t->sizes];
723 t->palbase = 0;
724 t->vqbase = t->address;
725 t->blend = use_alpha ? blend_functions[t->blend_mode] : bl10;
726
727 t->coltype = coltype;
728 t->tsinstruction = tsinstruction;
729
730 // fprintf(stderr, "tex %d %d %d %d\n", t->pf, t->mode, pal_ram_ctrl, t->mipmapped);
731 if(!t->textured)
732 {
733 t->r = nullptr;
734 }
735 else
736 {
737 switch(t->pf) {
738 case 0: // 1555
739 switch(t->mode) {
740 case 0: t->r = &powervr2_device::tex_r_1555_tw; miptype = 2; break;
741 case 1: t->r = &powervr2_device::tex_r_1555_n; miptype = 2; break;
742 case 2:
743 case 3: t->r = &powervr2_device::tex_r_1555_vq; miptype = 3; t->address += 0x800; break;
744
745 default:
746 //
747 break;
748 }
749 break;
750
751 case 1: // 565
752 switch(t->mode) {
753 case 0: t->r = &powervr2_device::tex_r_565_tw; miptype = 2; break;
754 case 1: t->r = &powervr2_device::tex_r_565_n; miptype = 2; break;
755 case 2:
756 case 3: t->r = &powervr2_device::tex_r_565_vq; miptype = 3; t->address += 0x800; break;
757
758 default:
759 //
760 break;
761 }
762 break;
763
764 case 2: // 4444
765 switch(t->mode) {
766 case 0: t->r = &powervr2_device::tex_r_4444_tw; miptype = 2; break;
767 case 1: t->r = &powervr2_device::tex_r_4444_n; miptype = 2; break;
768 case 2:
769 case 3: t->r = &powervr2_device::tex_r_4444_vq; miptype = 3; t->address += 0x800; break;
770
771 default:
772 //
773 break;
774 }
775 break;
776
777 case 3: // yuv422
778 switch(t->mode) {
779 case 0: t->r = &powervr2_device::tex_r_yuv_tw; miptype = -1; break;
780 case 1: t->r = &powervr2_device::tex_r_yuv_n; miptype = -1; break;
781 //default: t->r = &powervr2_device::tex_r_yuv_vq; miptype = -1; break;
782 }
783 break;
784
785 case 4: // bumpmap
786 break;
787
788 case 5: // 4bpp palette
789 t->palbase = (t->palette & 0x3f) << 4;
790 switch(t->mode) {
791 case 0: case 1:
792 miptype = 0;
793
794 switch(pal_ram_ctrl) {
795 case 0: t->r = &powervr2_device::tex_r_p4_1555_tw; break;
796 case 1: t->r = &powervr2_device::tex_r_p4_565_tw; break;
797 case 2: t->r = &powervr2_device::tex_r_p4_4444_tw; break;
798 case 3: t->r = &powervr2_device::tex_r_p4_8888_tw; break;
799 }
800 break;
801 case 2: case 3:
802 miptype = 3; // ?
803 switch(pal_ram_ctrl) {
804 case 0: t->r = &powervr2_device::tex_r_p4_1555_vq; t->address += 0x800; break;
805 case 1: t->r = &powervr2_device::tex_r_p4_565_vq; t->address += 0x800; break;
806 case 2: t->r = &powervr2_device::tex_r_p4_4444_vq; t->address += 0x800; break;
807 case 3: t->r = &powervr2_device::tex_r_p4_8888_vq; t->address += 0x800; break;
808 }
809 break;
810
811 default:
812 //
813 break;
814 }
815 break;
816
817 case 6: // 8bpp palette
818 t->palbase = (t->palette & 0x30) << 4;
819 switch(t->mode) {
820 case 0: case 1:
821 miptype = 1;
822
823 switch(pal_ram_ctrl) {
824 case 0: t->r = &powervr2_device::tex_r_p8_1555_tw; break;
825 case 1: t->r = &powervr2_device::tex_r_p8_565_tw; break;
826 case 2: t->r = &powervr2_device::tex_r_p8_4444_tw; break;
827 case 3: t->r = &powervr2_device::tex_r_p8_8888_tw; break;
828 }
829 break;
830 case 2: case 3:
831 miptype = 3; // ?
832 switch(pal_ram_ctrl) {
833 case 0: t->r = &powervr2_device::tex_r_p8_1555_vq; t->address += 0x800; break;
834 case 1: t->r = &powervr2_device::tex_r_p8_565_vq; t->address += 0x800; break;
835 case 2: t->r = &powervr2_device::tex_r_p8_4444_vq; t->address += 0x800; break;
836 case 3: t->r = &powervr2_device::tex_r_p8_8888_vq; t->address += 0x800; break;
837 }
838 break;
839
840 default:
841 //
842 break;
843 }
844 break;
845
846 case 9: // reserved
847 break;
848 }
849 }
850
851 if (t->mipmapped)
852 {
853 // full offset tables for reference,
854 // we don't do mipmapping, so don't use anything < 8x8
855 // first table is half-bytes
856
857 // 4BPP palette textures
858 // Texture size _4-bit_ offset value for starting address
859 // 1x1 0x00003
860 // 2x2 0x00004
861 // 4x4 0x00008
862 // 8x8 0x00018
863 // 16x16 0x00058
864 // 32x32 0x00158
865 // 64x64 0x00558
866 // 128x128 0x01558
867 // 256x256 0x05558
868 // 512x512 0x15558
869 // 1024x1024 0x55558
870
871 // 8BPP palette textures
872 // Texture size Byte offset value for starting address
873 // 1x1 0x00003
874 // 2x2 0x00004
875 // 4x4 0x00008
876 // 8x8 0x00018
877 // 16x16 0x00058
878 // 32x32 0x00158
879 // 64x64 0x00558
880 // 128x128 0x01558
881 // 256x256 0x05558
882 // 512x512 0x15558
883 // 1024x1024 0x55558
884
885 // Non-palette textures
886 // Texture size Byte offset value for starting address
887 // 1x1 0x00006
888 // 2x2 0x00008
889 // 4x4 0x00010
890 // 8x8 0x00030
891 // 16x16 0x000B0
892 // 32x32 0x002B0
893 // 64x64 0x00AB0
894 // 128x128 0x02AB0
895 // 256x256 0x0AAB0
896 // 512x512 0x2AAB0
897 // 1024x1024 0xAAAB0
898
899 // VQ textures
900 // Texture size Byte offset value for starting address
901 // 1x1 0x00000
902 // 2x2 0x00001
903 // 4x4 0x00002
904 // 8x8 0x00006
905 // 16x16 0x00016
906 // 32x32 0x00056
907 // 64x64 0x00156
908 // 128x128 0x00556
909 // 256x256 0x01556
910 // 512x512 0x05556
911 // 1024x1024 0x15556
912
913 static const int mipmap_4_8_offset[8] = { 0x00018, 0x00058, 0x00158, 0x00558, 0x01558, 0x05558, 0x15558, 0x55558 }; // 4bpp (4bit offset) / 8bpp (8bit offset)
914 static const int mipmap_np_offset[8] = { 0x00030, 0x000B0, 0x002B0, 0x00AB0, 0x02AB0, 0x0AAB0, 0x2AAB0, 0xAAAB0 }; // nonpalette textures
915 static const int mipmap_vq_offset[8] = { 0x00006, 0x00016, 0x00056, 0x00156, 0x00556, 0x01556, 0x05556, 0x15556 }; // vq textures
916
917 switch (miptype)
918 {
919 case 0: // 4bpp
920 //printf("4bpp\n");
921 t->address += mipmap_4_8_offset[(t->sizes)&7]>>1;
922 break;
923
924 case 1: // 8bpp
925 //printf("8bpp\n");
926 t->address += mipmap_4_8_offset[(t->sizes)&7];
927 break;
928
929 case 2: // nonpalette
930 //printf("np\n");
931 t->address += mipmap_np_offset[(t->sizes)&7];
932 break;
933
934 case 3: // vq
935 //printf("vq\n");
936 t->address += mipmap_vq_offset[(t->sizes)&7];
937 break;
938 }
939 }
940
941 }
942
id_r()943 uint32_t powervr2_device::id_r()
944 {
945 return 0x17fd11db;
946 }
947
revision_r()948 uint32_t powervr2_device::revision_r()
949 {
950 return 0x00000011;
951 }
952
softreset_r()953 uint32_t powervr2_device::softreset_r()
954 {
955 return softreset;
956 }
957
softreset_w(offs_t offset,uint32_t data,uint32_t mem_mask)958 void powervr2_device::softreset_w(offs_t offset, uint32_t data, uint32_t mem_mask)
959 {
960 COMBINE_DATA(&softreset);
961 if (softreset & 1) {
962 #if DEBUG_PVRTA
963 logerror("%s: TA soft reset\n", tag());
964 #endif
965 listtype_used=0;
966 }
967 if (softreset & 2) {
968 #if DEBUG_PVRTA
969 logerror("%s: Core Pipeline soft reset\n", tag());
970 #endif
971 if (start_render_received == 1) {
972 for (int a=0;a < NUM_BUFFERS;a++)
973 if (grab[a].busy == 1)
974 grab[a].busy = 0;
975
976 start_render_received = 0;
977 }
978 }
979 if (softreset & 4) {
980 #if DEBUG_PVRTA
981 logerror("%s: sdram I/F soft reset\n", tag());
982 #endif
983 }
984 }
985
startrender_w(address_space & space,uint32_t data)986 void powervr2_device::startrender_w(address_space &space, uint32_t data)
987 {
988 dc_state *state = machine().driver_data<dc_state>();
989 g_profiler.start(PROFILER_USER1);
990 #if DEBUG_PVRTA
991 logerror("%s: Start render, region=%08x, params=%08x\n", tag(), region_base, param_base);
992 #endif
993
994 // select buffer to draw using param_base
995 for (int a=0;a < NUM_BUFFERS;a++) {
996 if ((grab[a].ispbase == param_base) && (grab[a].valid == 1) && (grab[a].busy == 0)) {
997 grab[a].busy = 1;
998 renderselect = a;
999 start_render_received=1;
1000
1001
1002 grab[a].fbwsof1 = fb_w_sof1;
1003 grab[a].fbwsof2 = fb_w_sof2;
1004
1005 rectangle clip(0, 1023, 0, 1023);
1006
1007 // we've got a request to draw, so, draw to the accumulation buffer!
1008 // this should really be done for each tile!
1009 render_to_accumulation_buffer(*fake_accumulationbuffer_bitmap,clip);
1010
1011 /* copy the tiles to the framebuffer (really the rendering should be in this loop too) */
1012 int sizera = fpu_param_cfg & 0x200000 ? 6 : 5;
1013 int offsetra=region_base;
1014
1015 //printf("base is %08x\n", offsetra);
1016
1017 // sanity
1018 int sanitycount = 0;
1019 for (;;) {
1020 uint32_t st[6];
1021
1022 st[0]=space.read_dword((0x05000000+offsetra));
1023 st[1]=space.read_dword((0x05000004+offsetra)); // Opaque List Pointer
1024 st[2]=space.read_dword((0x05000008+offsetra)); // Opaque Modifier Volume List Pointer
1025 st[3]=space.read_dword((0x0500000c+offsetra)); // Translucent List Pointer
1026 st[4]=space.read_dword((0x05000010+offsetra)); // Translucent Modifier Volume List Pointer
1027
1028 if (sizera == 6) {
1029 st[5] = space.read_dword((0x05000014+offsetra)); // Punch Through List Pointer
1030 offsetra+=0x18;
1031 } else {
1032 st[5] = 0;
1033 offsetra+=0x14;
1034 }
1035
1036 {
1037 int x = ((st[0]&0x000000fc)>>2)*32;
1038 int y = ((st[0]&0x00003f00)>>8)*32;
1039 //printf("tiledata %08x %d %d - %08x %08x %08x %08x %08x\n",st[0],x,y,st[1],st[2],st[3],st[4],st[5]);
1040
1041 // should render to the accumulation buffer here using pointers we filled in when processing the data
1042 // sent to the TA. HOWEVER, we don't process the TA data and create the real format object lists, so
1043 // instead just use these co-ordinates to copy data from our fake full-screnen accumnulation buffer into
1044 // the framebuffer
1045
1046 pvr_accumulationbuffer_to_framebuffer(space, x,y);
1047 }
1048
1049 if (st[0] & 0x80000000)
1050 break;
1051
1052 sanitycount++;
1053 // prevent infinite loop if asked to process invalid data
1054 //if(sanitycount>2000)
1055 // break;
1056 }
1057 // printf("ISP START %d %d\n",sanitycount,screen().vpos());
1058 /* Fire ISP irq after a set amount of time TODO: timing of this */
1059 endofrender_timer_isp->adjust(state->m_maincpu->cycles_to_attotime(sanitycount*25 + 500000)); // hacky end of render delay for Capcom games, otherwise they works at ~1/10 speed
1060 break;
1061 }
1062 }
1063 }
1064
1065
param_base_r()1066 uint32_t powervr2_device::param_base_r()
1067 {
1068 return param_base;
1069 }
1070
param_base_w(offs_t offset,uint32_t data,uint32_t mem_mask)1071 void powervr2_device::param_base_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1072 {
1073 COMBINE_DATA(¶m_base);
1074 }
1075
region_base_r()1076 uint32_t powervr2_device::region_base_r()
1077 {
1078 return region_base;
1079 }
1080
region_base_w(offs_t offset,uint32_t data,uint32_t mem_mask)1081 void powervr2_device::region_base_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1082 {
1083 COMBINE_DATA(®ion_base);
1084 }
1085
vo_border_col_r()1086 uint32_t powervr2_device::vo_border_col_r()
1087 {
1088 return vo_border_col;
1089 }
1090
vo_border_col_w(offs_t offset,uint32_t data,uint32_t mem_mask)1091 void powervr2_device::vo_border_col_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1092 {
1093 COMBINE_DATA(&vo_border_col);
1094 }
1095
fb_r_ctrl_r()1096 uint32_t powervr2_device::fb_r_ctrl_r()
1097 {
1098 return fb_r_ctrl;
1099 }
1100
fb_r_ctrl_w(offs_t offset,uint32_t data,uint32_t mem_mask)1101 void powervr2_device::fb_r_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1102 {
1103 COMBINE_DATA(&fb_r_ctrl);
1104 }
1105
fb_w_ctrl_r()1106 uint32_t powervr2_device::fb_w_ctrl_r()
1107 {
1108 return fb_w_ctrl;
1109 }
1110
fb_w_ctrl_w(offs_t offset,uint32_t data,uint32_t mem_mask)1111 void powervr2_device::fb_w_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1112 {
1113 COMBINE_DATA(&fb_w_ctrl);
1114 }
1115
fb_w_linestride_r()1116 uint32_t powervr2_device::fb_w_linestride_r()
1117 {
1118 return fb_w_linestride;
1119 }
1120
fb_w_linestride_w(offs_t offset,uint32_t data,uint32_t mem_mask)1121 void powervr2_device::fb_w_linestride_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1122 {
1123 COMBINE_DATA(&fb_w_linestride);
1124 }
1125
fb_r_sof1_r()1126 uint32_t powervr2_device::fb_r_sof1_r()
1127 {
1128 return fb_r_sof1;
1129 }
1130
fb_r_sof1_w(offs_t offset,uint32_t data,uint32_t mem_mask)1131 void powervr2_device::fb_r_sof1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1132 {
1133 COMBINE_DATA(&fb_r_sof1);
1134 }
1135
fb_r_sof2_r()1136 uint32_t powervr2_device::fb_r_sof2_r()
1137 {
1138 return fb_r_sof2;
1139 }
1140
fb_r_sof2_w(offs_t offset,uint32_t data,uint32_t mem_mask)1141 void powervr2_device::fb_r_sof2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1142 {
1143 COMBINE_DATA(&fb_r_sof2);
1144 }
1145
fb_r_size_r()1146 uint32_t powervr2_device::fb_r_size_r()
1147 {
1148 return fb_r_size;
1149 }
1150
fb_r_size_w(offs_t offset,uint32_t data,uint32_t mem_mask)1151 void powervr2_device::fb_r_size_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1152 {
1153 COMBINE_DATA(&fb_r_size);
1154 }
1155
fb_w_sof1_r()1156 uint32_t powervr2_device::fb_w_sof1_r()
1157 {
1158 return fb_w_sof1;
1159 }
1160
fb_w_sof1_w(offs_t offset,uint32_t data,uint32_t mem_mask)1161 void powervr2_device::fb_w_sof1_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1162 {
1163 COMBINE_DATA(&fb_w_sof1);
1164 }
1165
fb_w_sof2_r()1166 uint32_t powervr2_device::fb_w_sof2_r()
1167 {
1168 return fb_w_sof2;
1169 }
1170
fb_w_sof2_w(offs_t offset,uint32_t data,uint32_t mem_mask)1171 void powervr2_device::fb_w_sof2_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1172 {
1173 COMBINE_DATA(&fb_w_sof2);
1174 }
1175
fb_x_clip_r()1176 uint32_t powervr2_device::fb_x_clip_r()
1177 {
1178 return fb_x_clip;
1179 }
1180
fb_x_clip_w(offs_t offset,uint32_t data,uint32_t mem_mask)1181 void powervr2_device::fb_x_clip_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1182 {
1183 COMBINE_DATA(&fb_x_clip);
1184 }
1185
fb_y_clip_r()1186 uint32_t powervr2_device::fb_y_clip_r()
1187 {
1188 return fb_y_clip;
1189 }
1190
fb_y_clip_w(offs_t offset,uint32_t data,uint32_t mem_mask)1191 void powervr2_device::fb_y_clip_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1192 {
1193 COMBINE_DATA(&fb_y_clip);
1194 }
1195
fpu_param_cfg_r()1196 uint32_t powervr2_device::fpu_param_cfg_r()
1197 {
1198 return fpu_param_cfg;
1199 }
1200
fpu_param_cfg_w(offs_t offset,uint32_t data,uint32_t mem_mask)1201 void powervr2_device::fpu_param_cfg_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1202 {
1203 COMBINE_DATA(&fpu_param_cfg);
1204 }
1205
isp_backgnd_t_r()1206 uint32_t powervr2_device::isp_backgnd_t_r()
1207 {
1208 return isp_backgnd_t;
1209 }
1210
isp_backgnd_t_w(offs_t offset,uint32_t data,uint32_t mem_mask)1211 void powervr2_device::isp_backgnd_t_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1212 {
1213 COMBINE_DATA(&isp_backgnd_t);
1214 }
1215
spg_hblank_int_r()1216 uint32_t powervr2_device::spg_hblank_int_r()
1217 {
1218 return spg_hblank_int;
1219 }
1220
spg_hblank_int_w(offs_t offset,uint32_t data,uint32_t mem_mask)1221 void powervr2_device::spg_hblank_int_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1222 {
1223 COMBINE_DATA(&spg_hblank_int);
1224 /* TODO: timer adjust */
1225 }
1226
spg_vblank_int_r()1227 uint32_t powervr2_device::spg_vblank_int_r()
1228 {
1229 return spg_vblank_int;
1230 }
1231
spg_vblank_int_w(offs_t offset,uint32_t data,uint32_t mem_mask)1232 void powervr2_device::spg_vblank_int_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1233 {
1234 COMBINE_DATA(&spg_vblank_int);
1235
1236 /* clear pending irqs and modify them with the updated ones */
1237 // vbin_timer->adjust(attotime::never);
1238 // vbout_timer->adjust(attotime::never);
1239
1240 // vbin_timer->adjust(screen().time_until_pos(spg_vblank_int & 0x3ff));
1241 // vbout_timer->adjust(screen().time_until_pos((spg_vblank_int >> 16) & 0x3ff));
1242 }
1243
spg_control_r()1244 uint32_t powervr2_device::spg_control_r()
1245 {
1246 return spg_control;
1247 }
1248
spg_control_w(offs_t offset,uint32_t data,uint32_t mem_mask)1249 void powervr2_device::spg_control_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1250 {
1251 COMBINE_DATA(&spg_control);
1252 update_screen_format();
1253
1254 if((spg_control & 0xc0) == 0xc0)
1255 popmessage("SPG undocumented pixel clock mode 11, contact MAME/MESSdev");
1256
1257 if((spg_control & 0xd0) == 0x10)
1258 popmessage("SPG enabled VGA mode with interlace, contact MAME/MESSdev");
1259 }
1260
spg_hblank_r()1261 uint32_t powervr2_device::spg_hblank_r()
1262 {
1263 return spg_hblank;
1264 }
1265
spg_hblank_w(offs_t offset,uint32_t data,uint32_t mem_mask)1266 void powervr2_device::spg_hblank_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1267 {
1268 COMBINE_DATA(&spg_hblank);
1269 update_screen_format();
1270 }
1271
spg_load_r()1272 uint32_t powervr2_device::spg_load_r()
1273 {
1274 return spg_load;
1275 }
1276
spg_load_w(offs_t offset,uint32_t data,uint32_t mem_mask)1277 void powervr2_device::spg_load_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1278 {
1279 COMBINE_DATA(&spg_load);
1280 update_screen_format();
1281 }
1282
spg_vblank_r()1283 uint32_t powervr2_device::spg_vblank_r()
1284 {
1285 return spg_vblank;
1286 }
1287
spg_vblank_w(offs_t offset,uint32_t data,uint32_t mem_mask)1288 void powervr2_device::spg_vblank_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1289 {
1290 COMBINE_DATA(&spg_vblank);
1291 update_screen_format();
1292 }
1293
spg_width_r()1294 uint32_t powervr2_device::spg_width_r()
1295 {
1296 return spg_width;
1297 }
1298
spg_width_w(offs_t offset,uint32_t data,uint32_t mem_mask)1299 void powervr2_device::spg_width_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1300 {
1301 COMBINE_DATA(&spg_width);
1302 update_screen_format();
1303 }
1304
text_control_r()1305 uint32_t powervr2_device::text_control_r()
1306 {
1307 return text_control;
1308 }
1309
text_control_w(offs_t offset,uint32_t data,uint32_t mem_mask)1310 void powervr2_device::text_control_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1311 {
1312 COMBINE_DATA(&text_control);
1313 }
1314
vo_control_r()1315 uint32_t powervr2_device::vo_control_r()
1316 {
1317 return vo_control;
1318 }
1319
vo_control_w(offs_t offset,uint32_t data,uint32_t mem_mask)1320 void powervr2_device::vo_control_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1321 {
1322 COMBINE_DATA(&vo_control);
1323 }
1324
vo_startx_r()1325 uint32_t powervr2_device::vo_startx_r()
1326 {
1327 return vo_startx;
1328 }
1329
vo_startx_w(offs_t offset,uint32_t data,uint32_t mem_mask)1330 void powervr2_device::vo_startx_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1331 {
1332 COMBINE_DATA(&vo_startx);
1333 update_screen_format();
1334 }
1335
vo_starty_r()1336 uint32_t powervr2_device::vo_starty_r()
1337 {
1338 return vo_starty;
1339 }
1340
vo_starty_w(offs_t offset,uint32_t data,uint32_t mem_mask)1341 void powervr2_device::vo_starty_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1342 {
1343 COMBINE_DATA(&vo_starty);
1344 update_screen_format();
1345 }
1346
pal_ram_ctrl_r()1347 uint32_t powervr2_device::pal_ram_ctrl_r()
1348 {
1349 return pal_ram_ctrl;
1350 }
1351
pal_ram_ctrl_w(offs_t offset,uint32_t data,uint32_t mem_mask)1352 void powervr2_device::pal_ram_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1353 {
1354 COMBINE_DATA(&pal_ram_ctrl);
1355 }
1356
spg_status_r()1357 uint32_t powervr2_device::spg_status_r()
1358 {
1359 uint32_t fieldnum = (screen().frame_number() & 1) ? 1 : 0;
1360 int32_t spg_hbstart = spg_hblank & 0x3ff;
1361 int32_t spg_hbend = (spg_hblank >> 16) & 0x3ff;
1362 int32_t spg_vbstart = spg_vblank & 0x3ff;
1363 int32_t spg_vbend = (spg_vblank >> 16) & 0x3ff;
1364
1365 uint32_t vsync = ((screen().vpos() >= spg_vbstart) || (screen().vpos() < spg_vbend)) ? 0 : 1;
1366 uint32_t hsync = ((screen().hpos() >= spg_hbstart) || (screen().hpos() < spg_hbend)) ? 0 : 1;
1367 /* FIXME: following is just a wild guess */
1368 uint32_t blank = ((screen().vpos() >= spg_vbstart) || (screen().vpos() < spg_vbend) |
1369 (screen().hpos() >= spg_hbstart) || (screen().hpos() < spg_hbend)) ? 0 : 1;
1370 if(vo_control & 4) { blank^=1; }
1371 if(vo_control & 2) { vsync^=1; }
1372 if(vo_control & 1) { hsync^=1; }
1373
1374 return (vsync << 13) | (hsync << 12) | (blank << 11) | (fieldnum << 10) | (screen().vpos() & 0x3ff);
1375 }
1376
1377
ta_ol_base_r()1378 uint32_t powervr2_device::ta_ol_base_r()
1379 {
1380 return ta_ol_base;
1381 }
1382
ta_ol_base_w(offs_t offset,uint32_t data,uint32_t mem_mask)1383 void powervr2_device::ta_ol_base_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1384 {
1385 COMBINE_DATA(&ta_ol_base);
1386 }
1387
ta_isp_base_r()1388 uint32_t powervr2_device::ta_isp_base_r()
1389 {
1390 return ta_isp_base;
1391 }
1392
ta_isp_base_w(offs_t offset,uint32_t data,uint32_t mem_mask)1393 void powervr2_device::ta_isp_base_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1394 {
1395 COMBINE_DATA(&ta_isp_base);
1396 }
1397
ta_ol_limit_r()1398 uint32_t powervr2_device::ta_ol_limit_r()
1399 {
1400 return ta_ol_limit;
1401 }
1402
ta_ol_limit_w(offs_t offset,uint32_t data,uint32_t mem_mask)1403 void powervr2_device::ta_ol_limit_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1404 {
1405 COMBINE_DATA(&ta_ol_limit);
1406 }
1407
ta_isp_limit_r()1408 uint32_t powervr2_device::ta_isp_limit_r()
1409 {
1410 return ta_isp_limit;
1411 }
1412
ta_isp_limit_w(offs_t offset,uint32_t data,uint32_t mem_mask)1413 void powervr2_device::ta_isp_limit_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1414 {
1415 COMBINE_DATA(&ta_isp_limit);
1416 }
1417
ta_next_opb_r()1418 uint32_t powervr2_device::ta_next_opb_r()
1419 {
1420 return ta_next_opb;
1421 }
1422
ta_itp_current_r()1423 uint32_t powervr2_device::ta_itp_current_r()
1424 {
1425 return ta_itp_current;
1426 }
1427
ta_alloc_ctrl_r()1428 uint32_t powervr2_device::ta_alloc_ctrl_r()
1429 {
1430 return ta_alloc_ctrl;
1431 }
1432
ta_alloc_ctrl_w(offs_t offset,uint32_t data,uint32_t mem_mask)1433 void powervr2_device::ta_alloc_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1434 {
1435 COMBINE_DATA(&ta_alloc_ctrl);
1436 }
1437
ta_list_init_r()1438 uint32_t powervr2_device::ta_list_init_r()
1439 {
1440 return 0; //bit 31 always return 0, a probable left-over in Crazy Taxi reads this and discards the read (?)
1441 }
1442
ta_list_init_w(uint32_t data)1443 void powervr2_device::ta_list_init_w(uint32_t data)
1444 {
1445 if(data & 0x80000000) {
1446 tafifo_pos=0;
1447 tafifo_mask=7;
1448 tafifo_vertexwords=8;
1449 tafifo_listtype= DISPLAY_LIST_NONE;
1450 #if DEBUG_PVRTA
1451 logerror("%s: list init ol=(%08x, %08x) isp=(%08x, %08x), alloc=%08x obp=%08x\n",
1452 tag(), ta_ol_base, ta_ol_limit, ta_isp_base, ta_isp_limit, ta_alloc_ctrl, ta_next_opb_init);
1453 #endif
1454 ta_next_opb = ta_next_opb_init;
1455 ta_itp_current = ta_isp_base;
1456 alloc_ctrl_OPB_Mode = ta_alloc_ctrl & 0x100000; // 0 up 1 down
1457 alloc_ctrl_PT_OPB = (4 << ((ta_alloc_ctrl >> 16) & 3)) & 0x38; // number of 32 bit words (0,8,16,32)
1458 alloc_ctrl_TM_OPB = (4 << ((ta_alloc_ctrl >> 12) & 3)) & 0x38;
1459 alloc_ctrl_T_OPB = (4 << ((ta_alloc_ctrl >> 8) & 3)) & 0x38;
1460 alloc_ctrl_OM_OPB = (4 << ((ta_alloc_ctrl >> 4) & 3)) & 0x38;
1461 alloc_ctrl_O_OPB = (4 << ((ta_alloc_ctrl >> 0) & 3)) & 0x38;
1462 listtype_used |= (1+4);
1463 // use ta_isp_base and select buffer for grab data
1464 grabsel = -1;
1465 // try to find already used buffer but not busy
1466 for (int a=0;a < NUM_BUFFERS;a++)
1467 if ((grab[a].ispbase == ta_isp_base) && (grab[a].busy == 0) && (grab[a].valid == 1)) {
1468 grabsel=a;
1469 break;
1470 }
1471
1472 // try a buffer not used yet
1473 if (grabsel < 0)
1474 for (int a=0;a < NUM_BUFFERS;a++)
1475 if (grab[a].valid == 0) {
1476 grabsel=a;
1477 break;
1478 }
1479
1480 // find a non busy buffer starting from the last one used
1481 if (grabsel < 0)
1482 for (int a=0;a < 3;a++)
1483 if (grab[(grabsellast+1+a) & 3].busy == 0) {
1484 grabsel=a;
1485 break;
1486 }
1487
1488 if (grabsel < 0)
1489 throw emu_fatalerror("powervr2_device::ta_list_init_w: TA grabber error B!");
1490 grabsellast=grabsel;
1491 grab[grabsel].ispbase=ta_isp_base;
1492 grab[grabsel].busy=0;
1493 grab[grabsel].valid=1;
1494 grab[grabsel].verts_size=0;
1495 for (int group = 0; group < DISPLAY_LIST_COUNT; group++) {
1496 grab[grabsel].groups[group].strips_size=0;
1497 }
1498
1499 g_profiler.stop();
1500 }
1501 }
1502
1503
ta_yuv_tex_base_r()1504 uint32_t powervr2_device::ta_yuv_tex_base_r()
1505 {
1506 return ta_yuv_tex_base;
1507 }
1508
ta_yuv_tex_base_w(offs_t offset,uint32_t data,uint32_t mem_mask)1509 void powervr2_device::ta_yuv_tex_base_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1510 {
1511 COMBINE_DATA(&ta_yuv_tex_base);
1512 logerror("%s: ta_yuv_tex_base = %08x\n", tag(), ta_yuv_tex_base);
1513
1514 ta_yuv_index = 0;
1515 ta_yuv_x = 0;
1516 ta_yuv_y = 0;
1517
1518 }
1519
ta_yuv_tex_ctrl_r()1520 uint32_t powervr2_device::ta_yuv_tex_ctrl_r()
1521 {
1522 return ta_yuv_tex_ctrl;
1523 }
1524
ta_yuv_tex_ctrl_w(offs_t offset,uint32_t data,uint32_t mem_mask)1525 void powervr2_device::ta_yuv_tex_ctrl_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1526 {
1527 COMBINE_DATA(&ta_yuv_tex_ctrl);
1528 ta_yuv_x_size = ((ta_yuv_tex_ctrl & 0x3f)+1)*16;
1529 ta_yuv_y_size = (((ta_yuv_tex_ctrl>>8) & 0x3f)+1)*16;
1530 logerror("%s: ta_yuv_tex_ctrl = %08x\n", tag(), ta_yuv_tex_ctrl);
1531 if(ta_yuv_tex_ctrl & 0x01010000)
1532 fatalerror("YUV with setting %08x",ta_yuv_tex_ctrl);
1533 }
1534
1535 #include "debugger.h"
1536 /* TODO */
ta_yuv_tex_cnt_r()1537 uint32_t powervr2_device::ta_yuv_tex_cnt_r()
1538 {
1539 machine().debug_break();
1540 return ta_yuv_tex_cnt;
1541 }
1542
ta_yuv_tex_cnt_w(offs_t offset,uint32_t data,uint32_t mem_mask)1543 void powervr2_device::ta_yuv_tex_cnt_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1544 {
1545 machine().debug_break();
1546 COMBINE_DATA(&ta_yuv_tex_cnt);
1547 }
1548
ta_list_cont_w(uint32_t data)1549 void powervr2_device::ta_list_cont_w(uint32_t data)
1550 {
1551 if(data & 0x80000000) {
1552 tafifo_listtype= DISPLAY_LIST_NONE; // no list being received
1553 listtype_used |= (1+4);
1554 }
1555 }
1556
ta_next_opb_init_r()1557 uint32_t powervr2_device::ta_next_opb_init_r()
1558 {
1559 return ta_next_opb_init;
1560 }
1561
ta_next_opb_init_w(offs_t offset,uint32_t data,uint32_t mem_mask)1562 void powervr2_device::ta_next_opb_init_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1563 {
1564 COMBINE_DATA(&ta_next_opb_init);
1565 }
1566
1567
fog_table_r(offs_t offset)1568 uint32_t powervr2_device::fog_table_r(offs_t offset)
1569 {
1570 return fog_table[offset];
1571 }
1572
fog_table_w(offs_t offset,uint32_t data,uint32_t mem_mask)1573 void powervr2_device::fog_table_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1574 {
1575 COMBINE_DATA(fog_table+offset);
1576 }
1577
palette_r(offs_t offset)1578 uint32_t powervr2_device::palette_r(offs_t offset)
1579 {
1580 return palette[offset];
1581 }
1582
palette_w(offs_t offset,uint32_t data,uint32_t mem_mask)1583 void powervr2_device::palette_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1584 {
1585 COMBINE_DATA(palette+offset);
1586 }
1587
update_screen_format()1588 void powervr2_device::update_screen_format()
1589 {
1590 /* 00=VGA 01=NTSC 10=PAL, 11=illegal/undocumented */
1591 const int spg_clks[4] = { 26944080, 13458568, 13462800, 26944080 };
1592 int32_t spg_hsize = spg_load & 0x3ff;
1593 int32_t spg_vsize = (spg_load >> 16) & 0x3ff;
1594 int32_t spg_hbstart = spg_hblank & 0x3ff;
1595 int32_t spg_hbend = (spg_hblank >> 16) & 0x3ff;
1596 int32_t spg_vbstart = spg_vblank & 0x3ff;
1597 int32_t spg_vbend = (spg_vblank >> 16) & 0x3ff;
1598 //int32_t vo_horz_start_pos = vo_startx & 0x3ff;
1599 //int32_t vo_vert_start_pos_f1 = vo_starty & 0x3ff;
1600 int pclk = spg_clks[(spg_control >> 6) & 3] * (((spg_control & 0x10) >> 4)+1);
1601
1602 attoseconds_t refresh = HZ_TO_ATTOSECONDS(pclk) * spg_hsize * spg_vsize;
1603
1604 rectangle visarea = screen().visible_area();
1605
1606 visarea.min_x = spg_hbend;
1607 visarea.max_x = spg_hbstart - 1;
1608 visarea.min_y = spg_vbend;
1609 visarea.max_y = spg_vbstart - 1;
1610
1611 // Sanitize
1612 if(visarea.max_x >= spg_hsize)
1613 visarea.max_x = spg_hsize-1;
1614 if(visarea.max_y >= spg_vsize)
1615 visarea.max_y = spg_vsize-1;
1616 if(visarea.min_x > visarea.max_x)
1617 visarea.min_x = visarea.max_x;
1618 if(visarea.min_y > visarea.max_y)
1619 visarea.min_y = visarea.max_y;
1620
1621 screen().configure(spg_hsize, spg_vsize, visarea, refresh );
1622 }
1623
1624
sb_pdstap_r()1625 uint32_t powervr2_device::sb_pdstap_r()
1626 {
1627 return sb_pdstap;
1628 }
1629
sb_pdstap_w(offs_t offset,uint32_t data,uint32_t mem_mask)1630 void powervr2_device::sb_pdstap_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1631 {
1632 COMBINE_DATA(&sb_pdstap);
1633 m_pvr_dma.pvr_addr = sb_pdstap;
1634 }
1635
sb_pdstar_r()1636 uint32_t powervr2_device::sb_pdstar_r()
1637 {
1638 return sb_pdstar;
1639 }
1640
sb_pdstar_w(offs_t offset,uint32_t data,uint32_t mem_mask)1641 void powervr2_device::sb_pdstar_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1642 {
1643 COMBINE_DATA(&sb_pdstar);
1644 m_pvr_dma.sys_addr = sb_pdstar;
1645 }
1646
sb_pdlen_r()1647 uint32_t powervr2_device::sb_pdlen_r()
1648 {
1649 return sb_pdlen;
1650 }
1651
sb_pdlen_w(offs_t offset,uint32_t data,uint32_t mem_mask)1652 void powervr2_device::sb_pdlen_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1653 {
1654 COMBINE_DATA(&sb_pdlen);
1655 m_pvr_dma.size = sb_pdlen;
1656 }
1657
sb_pddir_r()1658 uint32_t powervr2_device::sb_pddir_r()
1659 {
1660 return sb_pddir;
1661 }
1662
sb_pddir_w(offs_t offset,uint32_t data,uint32_t mem_mask)1663 void powervr2_device::sb_pddir_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1664 {
1665 COMBINE_DATA(&sb_pddir);
1666 m_pvr_dma.dir = sb_pddir;
1667 }
1668
sb_pdtsel_r()1669 uint32_t powervr2_device::sb_pdtsel_r()
1670 {
1671 return sb_pdtsel;
1672 }
1673
sb_pdtsel_w(offs_t offset,uint32_t data,uint32_t mem_mask)1674 void powervr2_device::sb_pdtsel_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1675 {
1676 COMBINE_DATA(&sb_pdtsel);
1677 m_pvr_dma.sel = sb_pdtsel & 1;
1678 }
1679
sb_pden_r()1680 uint32_t powervr2_device::sb_pden_r()
1681 {
1682 return sb_pden;
1683 }
1684
sb_pden_w(offs_t offset,uint32_t data,uint32_t mem_mask)1685 void powervr2_device::sb_pden_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1686 {
1687 COMBINE_DATA(&sb_pden);
1688 m_pvr_dma.flag = sb_pden & 1;
1689 }
1690
sb_pdst_r()1691 uint32_t powervr2_device::sb_pdst_r()
1692 {
1693 return sb_pdst;
1694 }
1695
sb_pdst_w(address_space & space,offs_t offset,uint32_t data,uint32_t mem_mask)1696 void powervr2_device::sb_pdst_w(address_space &space, offs_t offset, uint32_t data, uint32_t mem_mask)
1697 {
1698 COMBINE_DATA(&sb_pdst);
1699
1700 uint32_t old = m_pvr_dma.start & 1;
1701 m_pvr_dma.start = sb_pdst & 1;
1702
1703 if(((old & 1) == 0) && m_pvr_dma.flag && m_pvr_dma.start && ((m_pvr_dma.sel & 1) == 0)) // 0 -> 1
1704 pvr_dma_execute(space);
1705 }
1706
sb_pdapro_r()1707 uint32_t powervr2_device::sb_pdapro_r()
1708 {
1709 return sb_pdapro;
1710 }
1711
sb_pdapro_w(offs_t offset,uint32_t data,uint32_t mem_mask)1712 void powervr2_device::sb_pdapro_w(offs_t offset, uint32_t data, uint32_t mem_mask)
1713 {
1714 COMBINE_DATA(&sb_pdapro);
1715 }
1716
1717
TIMER_CALLBACK_MEMBER(powervr2_device::transfer_opaque_list_irq)1718 TIMER_CALLBACK_MEMBER(powervr2_device::transfer_opaque_list_irq)
1719 {
1720 // printf("OPLST %d\n",screen().vpos());
1721
1722 irq_cb(EOXFER_OPLST_IRQ);
1723 }
1724
TIMER_CALLBACK_MEMBER(powervr2_device::transfer_opaque_modifier_volume_list_irq)1725 TIMER_CALLBACK_MEMBER(powervr2_device::transfer_opaque_modifier_volume_list_irq)
1726 {
1727 // printf("OPMV %d\n",screen().vpos());
1728
1729 irq_cb(EOXFER_OPMV_IRQ);
1730 }
1731
TIMER_CALLBACK_MEMBER(powervr2_device::transfer_translucent_list_irq)1732 TIMER_CALLBACK_MEMBER(powervr2_device::transfer_translucent_list_irq)
1733 {
1734 // printf("TRLST %d\n",screen().vpos());
1735
1736 irq_cb(EOXFER_TRLST_IRQ);
1737 }
1738
TIMER_CALLBACK_MEMBER(powervr2_device::transfer_translucent_modifier_volume_list_irq)1739 TIMER_CALLBACK_MEMBER(powervr2_device::transfer_translucent_modifier_volume_list_irq)
1740 {
1741 // printf("TRMV %d\n",screen().vpos());
1742
1743 irq_cb(EOXFER_TRMV_IRQ);
1744 }
1745
TIMER_CALLBACK_MEMBER(powervr2_device::transfer_punch_through_list_irq)1746 TIMER_CALLBACK_MEMBER(powervr2_device::transfer_punch_through_list_irq)
1747 {
1748 // printf("PTLST %d\n",screen().vpos());
1749
1750 irq_cb(EOXFER_PTLST_IRQ);
1751 }
1752
process_ta_fifo()1753 void powervr2_device::process_ta_fifo()
1754 {
1755 /* first byte in the buffer is the Parameter Control Word
1756
1757 pppp pppp gggg gggg oooo oooo oooo oooo
1758
1759 p = para control
1760 g = group control
1761 o = object control
1762
1763 */
1764
1765 receiveddata *rd = &grab[grabsel];
1766
1767 // Para Control
1768 paracontrol=(tafifo_buff[0] >> 24) & 0xff;
1769 // 0 end of list
1770 // 1 user tile clip
1771 // 2 object list set
1772 // 3 reserved
1773 // 4 polygon/modifier volume
1774 // 5 sprite
1775 // 6 reserved
1776 // 7 vertex
1777 paratype=(paracontrol >> 5) & 7;
1778 endofstrip=(paracontrol >> 4) & 1;
1779 listtype=(paracontrol >> 0) & 7;
1780 if ((paratype >= 4) && (paratype <= 6))
1781 {
1782 global_paratype = paratype;
1783 // Group Control
1784 groupcontrol=(tafifo_buff[0] >> 16) & 0xff;
1785 groupen=(groupcontrol >> 7) & 1;
1786 striplen=(groupcontrol >> 2) & 3;
1787 userclip=(groupcontrol >> 0) & 3;
1788 // Obj Control
1789 objcontrol=(tafifo_buff[0] >> 0) & 0xffff;
1790 shadow=(objcontrol >> 7) & 1;
1791 volume=(objcontrol >> 6) & 1;
1792 coltype=(objcontrol >> 4) & 3;
1793 texture=(objcontrol >> 3) & 1;
1794 offset_color_enable=(objcontrol >> 2) & 1;
1795 gouraud=(objcontrol >> 1) & 1;
1796 uv16bit=(objcontrol >> 0) & 1;
1797 }
1798
1799 // check if we need 8 words more
1800 if (tafifo_mask == 7)
1801 {
1802 parameterconfig = pvr_parameterconfig[objcontrol & 0x3d];
1803 // decide number of words per vertex
1804 if (paratype == 7)
1805 {
1806 if ((global_paratype == 5) ||
1807 (tafifo_listtype == DISPLAY_LIST_OPAQUE_MOD) ||
1808 (tafifo_listtype == DISPLAY_LIST_TRANS_MOD))
1809 {
1810 tafifo_vertexwords = 16;
1811 }
1812 if (tafifo_vertexwords == 16)
1813 {
1814 tafifo_mask = 15;
1815 tafifo_pos = 8;
1816 return;
1817 }
1818 }
1819 // decide number of words when not a vertex
1820 tafifo_vertexwords=pvr_wordsvertex[parameterconfig];
1821 if ((paratype == 4) && ((listtype != 1) && (listtype != 3)))
1822 if (pvr_wordspolygon[parameterconfig] == 16)
1823 {
1824 tafifo_mask = 15;
1825 tafifo_pos = 8;
1826 return;
1827 }
1828 }
1829 bool have_16_byte_header = tafifo_mask != 7;
1830 tafifo_mask = 7;
1831
1832 // now we heve all the needed words
1833
1834 /*
1835 * load per-polygon colors if color type is 2 or 3 or parameter type is
1836 * 5 (quad). For color types 0 and 1, color is determined entirely on a
1837 * per-vertex basis.
1838 */
1839 if (paratype == 4)
1840 {
1841 switch (coltype) {
1842 case 2:
1843 if (offset_color_enable) {
1844 memcpy(poly_base_color, tafifo_buff + 8, 4 * sizeof(float));
1845 memcpy(poly_offs_color, tafifo_buff + 12, 4 * sizeof(float));
1846 } else {
1847 memcpy(poly_base_color, tafifo_buff + 4, 4 * sizeof(float));
1848 memset(poly_offs_color, 0, sizeof(poly_offs_color));
1849 }
1850 memcpy(poly_last_mode_2_base_color, poly_base_color, sizeof(poly_last_mode_2_base_color));
1851 break;
1852 case 3:
1853 memcpy(poly_base_color, poly_last_mode_2_base_color, sizeof(poly_base_color));
1854 memset(poly_offs_color, 0, sizeof(poly_offs_color));
1855 break;
1856 default:
1857 memset(poly_base_color, 0, sizeof(poly_base_color));
1858 memset(poly_offs_color, 0, sizeof(poly_offs_color));
1859 break;
1860 }
1861 } else if (paratype == 5) {
1862 packed_argb_to_float_argb(poly_base_color, tafifo_buff[4]);
1863 if (offset_color_enable) {
1864 packed_argb_to_float_argb(poly_offs_color, tafifo_buff[5]);
1865 } else {
1866 memset(poly_offs_color, 0, sizeof(poly_offs_color));
1867 }
1868 }
1869
1870 // here we should generate the data for the various tiles
1871 // for now, just interpret their meaning
1872 if (paratype == 0)
1873 { // end of list
1874 #if DEBUG_PVRDLIST
1875 osd_printf_verbose("Para Type 0 End of List\n");
1876 #endif
1877 /* Process transfer FIFO done irqs here */
1878 /* FIXME: timing of these */
1879 //printf("%d %d\n",tafifo_listtype,screen().vpos());
1880 switch (tafifo_listtype)
1881 {
1882 case DISPLAY_LIST_OPAQUE: machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(powervr2_device::transfer_opaque_list_irq), this)); break;
1883 case DISPLAY_LIST_OPAQUE_MOD: machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(powervr2_device::transfer_opaque_modifier_volume_list_irq), this)); break;
1884 case DISPLAY_LIST_TRANS: machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(powervr2_device::transfer_translucent_list_irq), this)); break;
1885 case DISPLAY_LIST_TRANS_MOD: machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(powervr2_device::transfer_translucent_modifier_volume_list_irq), this)); break;
1886 case DISPLAY_LIST_PUNCH_THROUGH: machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(powervr2_device::transfer_punch_through_list_irq), this)); break;
1887 }
1888 tafifo_listtype= DISPLAY_LIST_NONE; // no list being received
1889 listtype_used |= (2+8);
1890 }
1891 else if (paratype == 1)
1892 { // user tile clip
1893 #if DEBUG_PVRDLIST
1894 osd_printf_verbose("Para Type 1 User Tile Clip\n");
1895 osd_printf_verbose(" (%d , %d)-(%d , %d)\n", tafifo_buff[4], tafifo_buff[5], tafifo_buff[6], tafifo_buff[7]);
1896 #endif
1897 }
1898 else if (paratype == 2)
1899 { // object list set
1900 #if DEBUG_PVRDLIST
1901 osd_printf_verbose("Para Type 2 Object List Set at %08x\n", tafifo_buff[1]);
1902 osd_printf_verbose(" (%d , %d)-(%d , %d)\n", tafifo_buff[4], tafifo_buff[5], tafifo_buff[6], tafifo_buff[7]);
1903 #endif
1904 }
1905 else if (paratype == 3)
1906 {
1907 #if DEBUG_PVRDLIST
1908 osd_printf_verbose("Para Type %x Unknown!\n", tafifo_buff[0]);
1909 #endif
1910 }
1911 else
1912 { // global parameter or vertex parameter
1913 #if DEBUG_PVRDLIST
1914 osd_printf_verbose("Para Type %d", paratype);
1915 if (paratype == 7)
1916 osd_printf_verbose(" End of Strip %d", endofstrip);
1917 if (listtype_used & 3)
1918 osd_printf_verbose(" List Type %d", listtype);
1919 osd_printf_verbose("\n");
1920 #endif
1921
1922 // set type of list currently being received
1923 if ((paratype == 4) || (paratype == 5) || (paratype == 6))
1924 {
1925 if (tafifo_listtype < 0)
1926 {
1927 tafifo_listtype = listtype;
1928 }
1929 }
1930 listtype_used = listtype_used ^ (listtype_used & 3);
1931
1932 if ((paratype == 4) || (paratype == 5))
1933 { // quad or polygon
1934 depthcomparemode=(tafifo_buff[1] >> 29) & 7;
1935 cullingmode=(tafifo_buff[1] >> 27) & 3;
1936 zwritedisable=(tafifo_buff[1] >> 26) & 1;
1937 cachebypass=(tafifo_buff[1] >> 21) & 1;
1938 dcalcctrl=(tafifo_buff[1] >> 20) & 1;
1939 volumeinstruction=(tafifo_buff[1] >> 29) & 7;
1940
1941 //textureusize=1 << (3+((tafifo_buff[2] >> 3) & 7));
1942 //texturevsize=1 << (3+(tafifo_buff[2] & 7));
1943 texturesizes=tafifo_buff[2] & 0x3f;
1944 blend_mode = tafifo_buff[2] >> 26;
1945 srcselect=(tafifo_buff[2] >> 25) & 1;
1946 dstselect=(tafifo_buff[2] >> 24) & 1;
1947 fogcontrol=(tafifo_buff[2] >> 22) & 3;
1948 colorclamp=(tafifo_buff[2] >> 21) & 1;
1949 use_alpha = (tafifo_buff[2] >> 20) & 1;
1950 ignoretexalpha=(tafifo_buff[2] >> 19) & 1;
1951 flipuv=(tafifo_buff[2] >> 17) & 3;
1952 clampuv=(tafifo_buff[2] >> 15) & 3;
1953 filtermode=(tafifo_buff[2] >> 13) & 3;
1954 sstexture=(tafifo_buff[2] >> 12) & 1;
1955 mmdadjust=(tafifo_buff[2] >> 8) & 1;
1956 tsinstruction=(tafifo_buff[2] >> 6) & 3;
1957 if (texture == 1)
1958 {
1959 textureaddress=(tafifo_buff[3] & 0x1FFFFF) << 3;
1960 scanorder=(tafifo_buff[3] >> 26) & 1;
1961 pixelformat=(tafifo_buff[3] >> 27) & 7;
1962 mipmapped=(tafifo_buff[3] >> 31) & 1;
1963 vqcompressed=(tafifo_buff[3] >> 30) & 1;
1964 strideselect=(tafifo_buff[3] >> 25) & 1;
1965 paletteselector=(tafifo_buff[3] >> 21) & 0x3F;
1966 #if DEBUG_PVRDLIST
1967 osd_printf_verbose(" Texture at %08x format %d\n", (tafifo_buff[3] & 0x1FFFFF) << 3, pixelformat);
1968 #endif
1969 }
1970 if (paratype == 4)
1971 { // polygon or mv
1972 if ((tafifo_listtype == DISPLAY_LIST_OPAQUE_MOD) ||
1973 (tafifo_listtype == DISPLAY_LIST_TRANS_MOD))
1974 {
1975 #if DEBUG_PVRDLIST
1976 osd_printf_verbose(" Modifier Volume\n");
1977 #endif
1978 }
1979 else
1980 {
1981 #if DEBUG_PVRDLIST
1982 osd_printf_verbose(" Polygon\n");
1983 #endif
1984 }
1985 }
1986 if (paratype == 5)
1987 { // quad
1988 #if DEBUG_PVRDLIST
1989 osd_printf_verbose(" Sprite\n");
1990 #endif
1991 }
1992 }
1993
1994 if (paratype == 7)
1995 { // vertex
1996 if (tafifo_listtype < 0 || tafifo_listtype >= DISPLAY_LIST_COUNT) {
1997 logerror("PowerVR2 unrecognized list type %d\n", tafifo_listtype);
1998 return;
1999 }
2000 struct poly_group *grp = rd->groups + tafifo_listtype;
2001 if ((tafifo_listtype == DISPLAY_LIST_OPAQUE_MOD) ||
2002 (tafifo_listtype == DISPLAY_LIST_TRANS_MOD))
2003 {
2004 #if DEBUG_PVRDLIST
2005 osd_printf_verbose(" Vertex modifier volume");
2006 osd_printf_verbose(" A(%f,%f,%f) B(%f,%f,%f) C(%f,%f,%f)", u2f(tafifo_buff[1]), u2f(tafifo_buff[2]),
2007 u2f(tafifo_buff[3]), u2f(tafifo_buff[4]), u2f(tafifo_buff[5]), u2f(tafifo_buff[6]), u2f(tafifo_buff[7]),
2008 u2f(tafifo_buff[8]), u2f(tafifo_buff[9]));
2009 osd_printf_verbose("\n");
2010 #endif
2011 }
2012 else if (global_paratype == 5)
2013 {
2014 #if DEBUG_PVRDLIST
2015 osd_printf_verbose(" Vertex sprite");
2016 osd_printf_verbose(" A(%f,%f,%f) B(%f,%f,%f) C(%f,%f,%f) D(%f,%f,)", u2f(tafifo_buff[1]), u2f(tafifo_buff[2]),
2017 u2f(tafifo_buff[3]), u2f(tafifo_buff[4]), u2f(tafifo_buff[5]), u2f(tafifo_buff[6]), u2f(tafifo_buff[7]),
2018 u2f(tafifo_buff[8]), u2f(tafifo_buff[9]), u2f(tafifo_buff[10]), u2f(tafifo_buff[11]));
2019 osd_printf_verbose("\n");
2020 #endif
2021 if (texture == 1)
2022 {
2023 if (rd->verts_size <= (MAX_VERTS - 6) && grp->strips_size < MAX_STRIPS)
2024 {
2025 strip *ts;
2026 vert *tv = &rd->verts[rd->verts_size];
2027 tv[0].x = u2f(tafifo_buff[0x1]);
2028 tv[0].y = u2f(tafifo_buff[0x2]);
2029 tv[0].w = u2f(tafifo_buff[0x3]);
2030 tv[1].x = u2f(tafifo_buff[0x4]);
2031 tv[1].y = u2f(tafifo_buff[0x5]);
2032 tv[1].w = u2f(tafifo_buff[0x6]);
2033 tv[3].x = u2f(tafifo_buff[0x7]);
2034 tv[3].y = u2f(tafifo_buff[0x8]);
2035 tv[3].w = u2f(tafifo_buff[0x9]);
2036 tv[2].x = u2f(tafifo_buff[0xa]);
2037 tv[2].y = u2f(tafifo_buff[0xb]);
2038 tv[2].w = tv[0].w+tv[3].w-tv[1].w;
2039 tv[0].u = u2f(tafifo_buff[0xd] & 0xffff0000);
2040 tv[0].v = u2f(tafifo_buff[0xd] << 16);
2041 tv[1].u = u2f(tafifo_buff[0xe] & 0xffff0000);
2042 tv[1].v = u2f(tafifo_buff[0xe] << 16);
2043 tv[3].u = u2f(tafifo_buff[0xf] & 0xffff0000);
2044 tv[3].v = u2f(tafifo_buff[0xf] << 16);
2045 tv[2].u = tv[0].u+tv[3].u-tv[1].u;
2046 tv[2].v = tv[0].v+tv[3].v-tv[1].v;
2047
2048 int idx;
2049 for (idx = 0; idx < 4; idx++) {
2050 memcpy(tv[idx].b, poly_base_color,
2051 sizeof(tv[idx].b));
2052 memcpy(tv[idx].o, poly_offs_color,
2053 sizeof(tv[idx].o));
2054 }
2055
2056 ts = &grp->strips[grp->strips_size++];
2057 tex_get_info(&ts->ti);
2058 ts->svert = rd->verts_size;
2059 ts->evert = rd->verts_size + 3;
2060
2061 rd->verts_size += 4;
2062 }
2063 }
2064 }
2065 else if (global_paratype == 4)
2066 {
2067 #if DEBUG_PVRDLIST
2068 osd_printf_verbose(" Vertex polygon");
2069 osd_printf_verbose(" V(%f,%f,%f) T(%f,%f)", u2f(tafifo_buff[1]), u2f(tafifo_buff[2]), u2f(tafifo_buff[3]), u2f(tafifo_buff[4]), u2f(tafifo_buff[5]));
2070 osd_printf_verbose("\n");
2071 #endif
2072 if (rd->verts_size <= (MAX_VERTS - 6))
2073 {
2074 float vert_offset_color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
2075 float vert_base_color[4];
2076
2077 float base_intensity, offs_intensity;
2078
2079 switch (coltype) {
2080 case 0:
2081 // packed color
2082 packed_argb_to_float_argb(vert_base_color, tafifo_buff[6]);
2083 break;
2084 case 1:
2085 // floating-point color
2086 if (have_16_byte_header) {
2087 memcpy(vert_base_color, tafifo_buff + 8,
2088 sizeof(vert_base_color));
2089 memcpy(vert_offset_color, tafifo_buff + 12,
2090 sizeof(vert_offset_color));
2091 } else {
2092 memcpy(vert_base_color, tafifo_buff + 4,
2093 sizeof(vert_base_color));
2094 }
2095 break;
2096 case 2:
2097 case 3:
2098 /*
2099 * base/offset color were previously
2100 * specified on a per-polygon basis.
2101 * To get the per-vertex base and
2102 * offset colors, they are scaled by
2103 * per-vertex scalar values.
2104 */
2105 memcpy(&base_intensity, tafifo_buff + 6, sizeof(base_intensity));
2106 memcpy(&offs_intensity, tafifo_buff + 7, sizeof(offs_intensity));
2107 vert_base_color[0] = poly_base_color[0] * base_intensity;
2108 vert_base_color[1] = poly_base_color[1] * base_intensity;
2109 vert_base_color[2] = poly_base_color[2] * base_intensity;
2110 vert_base_color[3] = poly_base_color[3] * base_intensity;
2111 if (offset_color_enable) {
2112 vert_offset_color[0] = poly_offs_color[0] * offs_intensity;
2113 vert_offset_color[1] = poly_offs_color[1] * offs_intensity;
2114 vert_offset_color[2] = poly_offs_color[2] * offs_intensity;
2115 vert_offset_color[3] = poly_offs_color[3] * offs_intensity;
2116 }
2117 break;
2118 default:
2119 // This will never actually happen, coltype is 2-bits.
2120 logerror("line %d of %s - coltype is %d\n", coltype);
2121 memset(vert_base_color, 0, sizeof(vert_base_color));
2122 }
2123
2124 /* add a vertex to our list */
2125 /* this is used for 3d stuff, ie most of the graphics (see guilty gear, confidential mission, maze of the kings etc.) */
2126 /* -- this is also wildly inaccurate! */
2127 vert *tv = &rd->verts[rd->verts_size];
2128
2129 tv->x=u2f(tafifo_buff[1]);
2130 tv->y=u2f(tafifo_buff[2]);
2131 tv->w=u2f(tafifo_buff[3]);
2132 tv->u=u2f(tafifo_buff[4]);
2133 tv->v=u2f(tafifo_buff[5]);
2134 memcpy(tv->b, vert_base_color, sizeof(tv->b));
2135 memcpy(tv->o, vert_offset_color, sizeof(tv->o));
2136
2137 if(grp->strips_size < MAX_STRIPS &&
2138 ((!grp->strips_size) ||
2139 grp->strips[grp->strips_size-1].evert != -1))
2140 {
2141 strip *ts = &grp->strips[grp->strips_size++];
2142 tex_get_info(&ts->ti);
2143 ts->svert = rd->verts_size;
2144 ts->evert = -1;
2145 }
2146 if(endofstrip)
2147 grp->strips[grp->strips_size-1].evert = rd->verts_size;
2148 rd->verts_size++;
2149 }
2150 }
2151 }
2152 }
2153 }
2154
ta_fifo_poly_w(offs_t offset,uint64_t data,uint64_t mem_mask)2155 void powervr2_device::ta_fifo_poly_w(offs_t offset, uint64_t data, uint64_t mem_mask)
2156 {
2157 if (mem_mask == 0xffffffffffffffffU) // 64 bit
2158 {
2159 tafifo_buff[tafifo_pos]=(uint32_t)data;
2160 tafifo_buff[tafifo_pos+1]=(uint32_t)(data >> 32);
2161 #if DEBUG_FIFO_POLY
2162 osd_printf_debug("ta_fifo_poly_w: Unmapped write64 %08x = %x -> %08x %08x\n", 0x10000000+offset*8, data, tafifo_buff[tafifo_pos], tafifo_buff[tafifo_pos+1]);
2163 #endif
2164 tafifo_pos += 2;
2165 }
2166 else
2167 {
2168 osd_printf_debug("ta_fifo_poly_w: Unmapped write64 %08x = %x mask %x\n", 0x10000000+offset*8, data, mem_mask);
2169 }
2170
2171 tafifo_pos &= tafifo_mask;
2172
2173 // if the command is complete, process it
2174 if (tafifo_pos == 0)
2175 process_ta_fifo();
2176
2177 }
2178
TIMER_CALLBACK_MEMBER(powervr2_device::yuv_convert_end)2179 TIMER_CALLBACK_MEMBER(powervr2_device::yuv_convert_end)
2180 {
2181 irq_cb(EOXFER_YUV_IRQ);
2182 yuv_timer_end->adjust(attotime::never);
2183 }
2184
2185
ta_fifo_yuv_w(uint8_t data)2186 void powervr2_device::ta_fifo_yuv_w(uint8_t data)
2187 {
2188 dc_state *state = machine().driver_data<dc_state>();
2189 //printf("%08x %08x\n",ta_yuv_index++,ta_yuv_tex_ctrl);
2190
2191 //popmessage("YUV fifo write %08x %08x",ta_yuv_index,ta_yuv_tex_ctrl);
2192
2193 yuv_fifo[ta_yuv_index] = data;
2194 ta_yuv_index++;
2195
2196 if(ta_yuv_index == 0x180)
2197 {
2198 ta_yuv_index = 0;
2199 for(int y=0;y<16;y++)
2200 {
2201 for(int x=0;x<16;x+=2)
2202 {
2203 int dst_addr;
2204 int u,v,y0,y1;
2205
2206 dst_addr = ta_yuv_tex_base;
2207 dst_addr+= (ta_yuv_x+x)*2;
2208 dst_addr+= ((ta_yuv_y+y)*320*2);
2209
2210 u = yuv_fifo[0x00+(x>>1)+((y>>1)*8)];
2211 v = yuv_fifo[0x40+(x>>1)+((y>>1)*8)];
2212 y0 = yuv_fifo[0x80+((x&8) ? 0x40 : 0x00)+((y&8) ? 0x80 : 0x00)+(x&6)+((y&7)*8)];
2213 y1 = yuv_fifo[0x80+((x&8) ? 0x40 : 0x00)+((y&8) ? 0x80 : 0x00)+(x&6)+((y&7)*8)+1];
2214
2215 *(uint8_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + BYTE8_XOR_LE(dst_addr)) = u;
2216 *(uint8_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + BYTE8_XOR_LE(dst_addr+1)) = y0;
2217 *(uint8_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + BYTE8_XOR_LE(dst_addr+2)) = v;
2218 *(uint8_t *)((reinterpret_cast<uint8_t *>(dc_texture_ram)) + BYTE8_XOR_LE(dst_addr+3)) = y1;
2219 }
2220 }
2221
2222 ta_yuv_x+=16;
2223 if(ta_yuv_x == ta_yuv_x_size)
2224 {
2225 ta_yuv_x = 0;
2226 ta_yuv_y+=16;
2227 if(ta_yuv_y == ta_yuv_y_size)
2228 {
2229 ta_yuv_y = 0;
2230 /* TODO: timing */
2231 yuv_timer_end->adjust(state->m_maincpu->cycles_to_attotime((ta_yuv_x_size/16)*(ta_yuv_y_size/16)*0x180));
2232 }
2233 }
2234 }
2235 }
2236
2237 // SB_LMMODE0
ta_texture_directpath0_w(offs_t offset,uint64_t data,uint64_t mem_mask)2238 void powervr2_device::ta_texture_directpath0_w(offs_t offset, uint64_t data, uint64_t mem_mask)
2239 {
2240 // That's not in the pvr control address space, it's in g2's
2241 // int mode = pvrctrl_regs[SB_LMMODE0]&1;
2242 int mode = 0;
2243 if (mode&1)
2244 {
2245 printf("ta_texture_directpath0_w 32-bit access!\n");
2246 COMBINE_DATA(&dc_framebuffer_ram[offset]);
2247 }
2248 else
2249 {
2250 COMBINE_DATA(&dc_texture_ram[offset]);
2251 }
2252 }
2253
2254 // SB_LMMODE1
ta_texture_directpath1_w(offs_t offset,uint64_t data,uint64_t mem_mask)2255 void powervr2_device::ta_texture_directpath1_w(offs_t offset, uint64_t data, uint64_t mem_mask)
2256 {
2257 // That's not in the pvr control address space, it's in g2's
2258 // int mode = pvrctrl_regs[SB_LMMODE1]&1;
2259 int mode = 0;
2260 if (mode&1)
2261 {
2262 printf("ta_texture_directpath1_w 32-bit access!\n");
2263 COMBINE_DATA(&dc_framebuffer_ram[offset]);
2264 }
2265 else
2266 {
2267 COMBINE_DATA(&dc_texture_ram[offset]);
2268 }
2269 }
2270
2271 /* test video start */
dilate0(uint32_t value,int bits)2272 uint32_t powervr2_device::dilate0(uint32_t value,int bits) // dilate first "bits" bits in "value"
2273 {
2274 uint32_t x,m1,m2,m3;
2275 int a;
2276
2277 x = value;
2278 for (a=0;a < bits;a++)
2279 {
2280 m2 = 1 << (a << 1);
2281 m1 = m2 - 1;
2282 m3 = (~m1) << 1;
2283 x = (x & m1) + (x & m2) + ((x & m3) << 1);
2284 }
2285 return x;
2286 }
2287
dilate1(uint32_t value,int bits)2288 uint32_t powervr2_device::dilate1(uint32_t value,int bits) // dilate first "bits" bits in "value"
2289 {
2290 uint32_t x,m1,m2,m3;
2291 int a;
2292
2293 x = value;
2294 for (a=0;a < bits;a++)
2295 {
2296 m2 = 1 << (a << 1);
2297 m1 = m2 - 1;
2298 m3 = (~m1) << 1;
2299 x = (x & m1) + ((x & m2) << 1) + ((x & m3) << 1);
2300 }
2301 return x;
2302 }
2303
computedilated()2304 void powervr2_device::computedilated()
2305 {
2306 int a,b;
2307
2308 for (b=0;b <= 14;b++)
2309 for (a=0;a < 1024;a++) {
2310 dilated0[b][a]=dilate0(a,b);
2311 dilated1[b][a]=dilate1(a,b);
2312 }
2313 for (b=0;b <= 7;b++)
2314 for (a=0;a <= 7;a++)
2315 dilatechose[(b << 3) + a]=3+(a < b ? a : b);
2316 }
2317
sample_nontextured(texinfo * ti,float u,float v,uint32_t offset_color,uint32_t base_color)2318 inline uint32_t powervr2_device::sample_nontextured(texinfo *ti, float u, float v, uint32_t offset_color, uint32_t base_color)
2319 {
2320 return bls24(base_color, offset_color) | (base_color & 0xff000000);
2321 }
2322
2323 template <int tsinst, bool bilinear>
sample_textured(texinfo * ti,float u,float v,uint32_t offset_color,uint32_t base_color)2324 inline uint32_t powervr2_device::sample_textured(texinfo *ti, float u, float v, uint32_t offset_color, uint32_t base_color)
2325 {
2326 uint32_t tmp;
2327 uint32_t c = (this->*(ti->r))(ti, u, v);
2328 if (bilinear)
2329 {
2330 uint32_t c1 = (this->*(ti->r))(ti, u+1.0f, v);
2331 uint32_t c2 = (this->*(ti->r))(ti, u+1.0f, v+1.0f);
2332 uint32_t c3 = (this->*(ti->r))(ti, u, v+1.0f);
2333 c = bilinear_filter(c, c1, c2, c3, u, v);
2334 }
2335
2336 switch (tsinst) {
2337 case 0:
2338 // decal
2339 c = bls24(c, offset_color) | (c & 0xff000000);
2340 break;
2341 case 1:
2342 // modulate
2343 tmp = blc(c, base_color);
2344 tmp = bls24(tmp, offset_color);
2345 tmp |= c & 0xff000000;
2346 c = tmp;
2347 break;
2348 case 2:
2349 // decal with alpha
2350 tmp = bls24(bla(c, c), blia(base_color, c));
2351 c = bls24(tmp, offset_color) | (base_color & 0xff000000);
2352 break;
2353 case 3:
2354 // modulate with alpha
2355 tmp = blc(c, base_color);
2356 tmp = bls24(tmp, offset_color);
2357 tmp |= (((c >> 24) * (base_color >> 24)) >> 8) << 24;
2358 c = tmp;
2359 break;
2360 }
2361 return c;
2362 }
2363
2364 template <powervr2_device::pix_sample_fn sample_fn, int group_no>
render_hline(bitmap_rgb32 & bitmap,texinfo * ti,int y,float xl,float xr,float ul,float ur,float vl,float vr,float wl,float wr,float const bl_in[4],float const br_in[4],float const offl_in[4],float const offr_in[4])2365 inline void powervr2_device::render_hline(bitmap_rgb32 &bitmap, texinfo *ti, int y, float xl, float xr, float ul, float ur, float vl, float vr, float wl, float wr, float const bl_in[4], float const br_in[4], float const offl_in[4], float const offr_in[4])
2366 {
2367 int idx;
2368 int xxl, xxr;
2369 float dx, ddx, dudx, dvdx, dwdx;
2370 uint32_t *tdata;
2371 float *wbufline;
2372
2373 float bl[4], offl[4];
2374
2375 if(xr < 0 || xl >= 640)
2376 return;
2377
2378 xxl = round(xl);
2379 xxr = round(xr);
2380
2381 if(xxl == xxr)
2382 return;
2383
2384 memcpy(bl, bl_in, sizeof(bl));
2385 memcpy(offl, offl_in, sizeof(offl));
2386
2387 dx = xr-xl;
2388 float dx_recip = 1.0f / dx;
2389
2390 dudx = (ur-ul) * dx_recip;
2391 dvdx = (vr-vl) * dx_recip;
2392 dwdx = (wr-wl) * dx_recip;
2393
2394 float dbdx[4] = {
2395 (br_in[0] - bl[0]) * dx_recip,
2396 (br_in[1] - bl[1]) * dx_recip,
2397 (br_in[2] - bl[2]) * dx_recip,
2398 (br_in[3] - bl[3]) * dx_recip
2399 };
2400
2401 float dodx[4] = {
2402 (offr_in[0] - offl[0]) * dx_recip,
2403 (offr_in[1] - offl[1]) * dx_recip,
2404 (offr_in[2] - offl[2]) * dx_recip,
2405 (offr_in[3] - offl[3]) * dx_recip
2406 };
2407
2408 if(xxl < 0)
2409 xxl = 0;
2410 if(xxr > 640)
2411 xxr = 640;
2412
2413 // Target the pixel center
2414 ddx = xxl + 0.5f - xl;
2415 ul += ddx*dudx;
2416 vl += ddx*dvdx;
2417 wl += ddx*dwdx;
2418 for (idx = 0; idx < 4; idx++) {
2419 bl[idx] += ddx * dbdx[idx];
2420 offl[idx] += ddx * dodx[idx];
2421 }
2422
2423 tdata = &bitmap.pix(y, xxl);
2424 wbufline = &wbuffer[y][xxl];
2425
2426 while(xxl < xxr) {
2427 if((wl >= *wbufline)) {
2428 uint32_t c;
2429 float u = ul/wl;
2430 float v = vl/wl;
2431 uint32_t offset_color = float_argb_to_packed_argb(offl);
2432 uint32_t base_color = float_argb_to_packed_argb(bl);
2433 c = (this->*sample_fn)(ti, u, v, offset_color, base_color);
2434 if (group_no == DISPLAY_LIST_OPAQUE) {
2435 *tdata = c;
2436 *wbufline = wl;
2437 } else {
2438 if(c & 0xff000000) {
2439 *wbufline = wl;
2440 *tdata = ti->blend(c, *tdata);
2441 }
2442 }
2443 }
2444 wbufline++;
2445 tdata++;
2446
2447 ul += dudx;
2448 vl += dvdx;
2449 wl += dwdx;
2450 for (idx = 0; idx < 4; idx++) {
2451 bl[idx] += dbdx[idx];
2452 offl[idx] += dodx[idx];
2453 }
2454 xxl ++;
2455 }
2456 }
2457
2458 template <powervr2_device::pix_sample_fn sample_fn, int group_no>
render_span(bitmap_rgb32 & bitmap,texinfo * ti,float y0,float y1,float xl,float xr,float ul,float ur,float vl,float vr,float wl,float wr,float const bl_in[4],float const br_in[4],float const offl_in[4],float const offr_in[4],float dxldy,float dxrdy,float duldy,float durdy,float dvldy,float dvrdy,float dwldy,float dwrdy,float const dbldy[4],float const dbrdy[4],float const doldy[4],float const dordy[4])2459 inline void powervr2_device::render_span(bitmap_rgb32 &bitmap, texinfo *ti,
2460 float y0, float y1,
2461 float xl, float xr,
2462 float ul, float ur,
2463 float vl, float vr,
2464 float wl, float wr,
2465 float const bl_in[4], float const br_in[4],
2466 float const offl_in[4], float const offr_in[4],
2467 float dxldy, float dxrdy,
2468 float duldy, float durdy,
2469 float dvldy, float dvrdy,
2470 float dwldy, float dwrdy,
2471 float const dbldy[4], float const dbrdy[4],
2472 float const doldy[4], float const dordy[4])
2473 {
2474 int idx;
2475 float dy;
2476 int yy0, yy1;
2477
2478 if(y1 <= 0)
2479 return;
2480 if(y1 > 480)
2481 y1 = 480;
2482
2483 float bl[4], br[4], offl[4], offr[4];
2484 memcpy(bl, bl_in, sizeof(bl));
2485 memcpy(br, br_in, sizeof(br));
2486 memcpy(offl, offl_in, sizeof(offl));
2487 memcpy(offr, offr_in, sizeof(offr));
2488
2489 if(y0 < 0) {
2490 xl += -dxldy*y0;
2491 xr += -dxrdy*y0;
2492 ul += -duldy*y0;
2493 ur += -durdy*y0;
2494 vl += -dvldy*y0;
2495 vr += -dvrdy*y0;
2496 wl += -dwldy*y0;
2497 wr += -dwrdy*y0;
2498
2499 for (idx = 0; idx < 4; idx++) {
2500 bl[idx] += -dbldy[idx] * y0;
2501 br[idx] += -dbrdy[idx] * y0;
2502 offl[idx] += -doldy[idx] * y0;
2503 offr[idx] += -dordy[idx] * y0;
2504 }
2505 y0 = 0;
2506 }
2507
2508 yy0 = round(y0);
2509 yy1 = round(y1);
2510
2511 if((yy0 < 0 && y0 > 0) || (yy1 < 0 && y1 > 0)) //temp handling of int32 overflow, needed by hotd2/totd
2512 return;
2513
2514 dy = yy0+0.5f-y0;
2515
2516 if(0)
2517 fprintf(stderr, "%f %f %f %f -> %f %f | %f %f -> %f %f\n",
2518 (double) y0,
2519 (double) dy, (double) dxldy, (double) dxrdy, (double) (dy*dxldy), (double) (dy*dxrdy),
2520 (double) xl, (double) xr, (double) (xl + dy*dxldy), (double) (xr + dy*dxrdy));
2521 xl += dy*dxldy;
2522 xr += dy*dxrdy;
2523 ul += dy*duldy;
2524 ur += dy*durdy;
2525 vl += dy*dvldy;
2526 vr += dy*dvrdy;
2527 wl += dy*dwldy;
2528 wr += dy*dwrdy;
2529 for (idx = 0; idx < 4; idx++) {
2530 bl[idx] += dy * dbldy[idx];
2531 br[idx] += dy * dbrdy[idx];
2532 offl[idx] += dy * doldy[idx];
2533 offr[idx] += dy * dordy[idx];
2534 }
2535
2536 while(yy0 < yy1) {
2537 render_hline<sample_fn, group_no>(bitmap, ti, yy0, xl, xr, ul, ur, vl, vr, wl, wr, bl, br, offl, offr);
2538
2539 xl += dxldy;
2540 xr += dxrdy;
2541 ul += duldy;
2542 ur += durdy;
2543 vl += dvldy;
2544 vr += dvrdy;
2545 wl += dwldy;
2546 wr += dwrdy;
2547 for (idx = 0; idx < 4; idx++) {
2548 bl[idx] += dbldy[idx];
2549 br[idx] += dbrdy[idx];
2550 offl[idx] += doldy[idx];
2551 offr[idx] += dordy[idx];
2552 }
2553
2554 yy0 ++;
2555 }
2556 }
2557
sort_vertices(const vert * v,int * i0,int * i1,int * i2)2558 void powervr2_device::sort_vertices(const vert *v, int *i0, int *i1, int *i2)
2559 {
2560 float miny, maxy;
2561 int imin, imax, imid;
2562 miny = maxy = v[0].y;
2563 imin = imax = 0;
2564
2565 if(miny > v[1].y) {
2566 miny = v[1].y;
2567 imin = 1;
2568 } else if(maxy < v[1].y) {
2569 maxy = v[1].y;
2570 imax = 1;
2571 }
2572
2573 if(miny > v[2].y) {
2574 miny = v[2].y;
2575 imin = 2;
2576 } else if(maxy < v[2].y) {
2577 maxy = v[2].y;
2578 imax = 2;
2579 }
2580
2581 imid = (imin == 0 || imax == 0) ? (imin == 1 || imax == 1) ? 2 : 1 : 0;
2582
2583 *i0 = imin;
2584 *i1 = imid;
2585 *i2 = imax;
2586 }
2587
2588
2589 template <powervr2_device::pix_sample_fn sample_fn, int group_no>
render_tri_sorted(bitmap_rgb32 & bitmap,texinfo * ti,const vert * v0,const vert * v1,const vert * v2)2590 inline void powervr2_device::render_tri_sorted(bitmap_rgb32 &bitmap, texinfo *ti, const vert *v0, const vert *v1, const vert *v2)
2591 {
2592 float dy01, dy02, dy12;
2593
2594 float dx01dy, dx02dy, dx12dy, du01dy, du02dy, du12dy, dv01dy, dv02dy, dv12dy, dw01dy, dw02dy, dw12dy;
2595
2596 if(v0->y >= 480 || v2->y < 0)
2597 return;
2598
2599 float db01[4] = {
2600 v1->b[0] - v0->b[0],
2601 v1->b[1] - v0->b[1],
2602 v1->b[2] - v0->b[2],
2603 v1->b[3] - v0->b[3]
2604 };
2605
2606 float db02[4] = {
2607 v2->b[0] - v0->b[0],
2608 v2->b[1] - v0->b[1],
2609 v2->b[2] - v0->b[2],
2610 v2->b[3] - v0->b[3]
2611 };
2612
2613 float db12[4] = {
2614 v2->b[0] - v1->b[0],
2615 v2->b[1] - v1->b[1],
2616 v2->b[2] - v1->b[2],
2617 v2->b[3] - v1->b[3]
2618 };
2619
2620 float do01[4] = {
2621 v1->o[0] - v0->o[0],
2622 v1->o[1] - v0->o[1],
2623 v1->o[2] - v0->o[2],
2624 v1->o[3] - v0->o[3]
2625 };
2626
2627 float do02[4] = {
2628 v2->o[0] - v0->o[0],
2629 v2->o[1] - v0->o[1],
2630 v2->o[2] - v0->o[2],
2631 v2->o[3] - v0->o[3]
2632 };
2633
2634 float do12[4] = {
2635 v2->o[0] - v1->o[0],
2636 v2->o[1] - v1->o[1],
2637 v2->o[2] - v1->o[2],
2638 v2->o[3] - v1->o[3]
2639 };
2640
2641 dy01 = v1->y - v0->y;
2642 dy02 = v2->y - v0->y;
2643 dy12 = v2->y - v1->y;
2644
2645 float db01dy[4] = {
2646 dy01 ? db01[0]/dy01 : 0,
2647 dy01 ? db01[1]/dy01 : 0,
2648 dy01 ? db01[2]/dy01 : 0,
2649 dy01 ? db01[3]/dy01 : 0
2650 };
2651
2652 float db02dy[4] = {
2653 dy01 ? db02[0]/dy02 : 0,
2654 dy01 ? db02[1]/dy02 : 0,
2655 dy01 ? db02[2]/dy02 : 0,
2656 dy01 ? db02[3]/dy02 : 0
2657 };
2658
2659 float db12dy[4] = {
2660 dy01 ? db12[0]/dy12 : 0,
2661 dy01 ? db12[1]/dy12 : 0,
2662 dy01 ? db12[2]/dy12 : 0,
2663 dy01 ? db12[3]/dy12 : 0
2664 };
2665
2666 float do01dy[4] = {
2667 dy01 ? do01[0]/dy01 : 0,
2668 dy01 ? do01[1]/dy01 : 0,
2669 dy01 ? do01[2]/dy01 : 0,
2670 dy01 ? do01[3]/dy01 : 0
2671 };
2672
2673 float do02dy[4] = {
2674 dy01 ? do02[0]/dy02 : 0,
2675 dy01 ? do02[1]/dy02 : 0,
2676 dy01 ? do02[2]/dy02 : 0,
2677 dy01 ? do02[3]/dy02 : 0
2678 };
2679
2680 float do12dy[4] = {
2681 dy01 ? do12[0]/dy12 : 0,
2682 dy01 ? do12[1]/dy12 : 0,
2683 dy01 ? do12[2]/dy12 : 0,
2684 dy01 ? do12[3]/dy12 : 0
2685 };
2686
2687 dx01dy = dy01 ? (v1->x-v0->x)/dy01 : 0;
2688 dx02dy = dy02 ? (v2->x-v0->x)/dy02 : 0;
2689 dx12dy = dy12 ? (v2->x-v1->x)/dy12 : 0;
2690
2691 du01dy = dy01 ? (v1->u-v0->u)/dy01 : 0;
2692 du02dy = dy02 ? (v2->u-v0->u)/dy02 : 0;
2693 du12dy = dy12 ? (v2->u-v1->u)/dy12 : 0;
2694
2695 dv01dy = dy01 ? (v1->v-v0->v)/dy01 : 0;
2696 dv02dy = dy02 ? (v2->v-v0->v)/dy02 : 0;
2697 dv12dy = dy12 ? (v2->v-v1->v)/dy12 : 0;
2698
2699 dw01dy = dy01 ? (v1->w-v0->w)/dy01 : 0;
2700 dw02dy = dy02 ? (v2->w-v0->w)/dy02 : 0;
2701 dw12dy = dy12 ? (v2->w-v1->w)/dy12 : 0;
2702
2703 if(!dy01) {
2704 if(!dy12)
2705 return;
2706
2707 if(v1->x > v0->x)
2708 render_span<sample_fn, group_no>(bitmap, ti, v1->y, v2->y, v0->x, v1->x, v0->u, v1->u, v0->v, v1->v, v0->w, v1->w, v0->b, v1->b, v0->o, v1->o, dx02dy, dx12dy, du02dy, du12dy, dv02dy, dv12dy, dw02dy, dw12dy, db02dy, db12dy, do02dy, do12dy);
2709 else
2710 render_span<sample_fn, group_no>(bitmap, ti, v1->y, v2->y, v1->x, v0->x, v1->u, v0->u, v1->v, v0->v, v1->w, v0->w, v1->b, v0->b, v1->o, v0->o, dx12dy, dx02dy, du12dy, du02dy, dv12dy, dv02dy, dw12dy, dw02dy, db12dy, db02dy, do12dy, do02dy);
2711
2712 } else if(!dy12) {
2713 if(v2->x > v1->x)
2714 render_span<sample_fn, group_no>(bitmap, ti, v0->y, v1->y, v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o, dx01dy, dx02dy, du01dy, du02dy, dv01dy, dv02dy, dw01dy, dw02dy, db01dy, db02dy, do01dy, do02dy);
2715 else
2716 render_span<sample_fn, group_no>(bitmap, ti, v0->y, v1->y, v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o, dx02dy, dx01dy, du02dy, du01dy, dv02dy, dv01dy, dw02dy, dw01dy, db02dy, db01dy, do02dy, do01dy);
2717
2718 } else {
2719 float idk_b[4] = {
2720 v0->b[0] + db02dy[0] * dy01,
2721 v0->b[1] + db02dy[1] * dy01,
2722 v0->b[2] + db02dy[2] * dy01,
2723 v0->b[3] + db02dy[3] * dy01
2724 };
2725 float idk_o[4] = {
2726 v0->o[0] + do02dy[0] * dy01,
2727 v0->o[1] + do02dy[1] * dy01,
2728 v0->o[2] + do02dy[2] * dy01,
2729 v0->o[3] + do02dy[3] * dy01
2730 };
2731 if(dx01dy < dx02dy) {
2732 render_span<sample_fn, group_no>(bitmap, ti, v0->y, v1->y,
2733 v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o,
2734 dx01dy, dx02dy, du01dy, du02dy, dv01dy, dv02dy, dw01dy, dw02dy, db01dy, db02dy, do01dy, do02dy);
2735 render_span<sample_fn, group_no>(bitmap, ti, v1->y, v2->y,
2736 v1->x, v0->x + dx02dy*dy01, v1->u, v0->u + du02dy*dy01, v1->v, v0->v + dv02dy*dy01, v1->w, v0->w + dw02dy*dy01, v1->b, idk_b, v1->o, idk_o,
2737 dx12dy, dx02dy, du12dy, du02dy, dv12dy, dv02dy, dw12dy, dw02dy, db12dy, db02dy, do12dy, do02dy);
2738 } else {
2739 render_span<sample_fn, group_no>(bitmap, ti, v0->y, v1->y,
2740 v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, v0->b, v0->b, v0->o, v0->o,
2741 dx02dy, dx01dy, du02dy, du01dy, dv02dy, dv01dy, dw02dy, dw01dy, db02dy, db01dy, do02dy, do01dy);
2742 render_span<sample_fn, group_no>(bitmap, ti, v1->y, v2->y,
2743 v0->x + dx02dy*dy01, v1->x, v0->u + du02dy*dy01, v1->u, v0->v + dv02dy*dy01, v1->v, v0->w + dw02dy*dy01, v1->w, idk_b, v1->b, idk_o, v1->o,
2744 dx02dy, dx12dy, du02dy, du12dy, dv02dy, dv12dy, dw02dy, dw12dy, db02dy, db12dy, do02dy, do12dy);
2745 }
2746 }
2747 }
2748
2749 template <int group_no>
render_tri(bitmap_rgb32 & bitmap,texinfo * ti,const vert * v)2750 void powervr2_device::render_tri(bitmap_rgb32 &bitmap, texinfo *ti, const vert *v)
2751 {
2752 int i0, i1, i2;
2753
2754 sort_vertices(v, &i0, &i1, &i2);
2755
2756 bool textured = ti->textured;
2757 if (textured) {
2758 bool bilinear = (debug_dip_status & 1) &&
2759 (ti->filter_mode >= TEX_FILTER_BILINEAR);
2760 if (bilinear) {
2761 switch (ti->tsinstruction) {
2762 case 0:
2763 render_tri_sorted<&powervr2_device::sample_textured<0,true>, group_no>(bitmap, ti, v+i0, v+i1, v+i2);
2764 break;
2765 case 1:
2766 render_tri_sorted<&powervr2_device::sample_textured<1,true>, group_no>(bitmap, ti, v+i0, v+i1, v+i2);
2767 break;
2768 case 2:
2769 render_tri_sorted<&powervr2_device::sample_textured<2,true>, group_no>(bitmap, ti, v+i0, v+i1, v+i2);
2770 break;
2771 case 3:
2772 render_tri_sorted<&powervr2_device::sample_textured<3,true>, group_no>(bitmap, ti, v+i0, v+i1, v+i2);
2773 break;
2774 default:
2775 /*
2776 * This should be impossible because tsinstruction was previously
2777 * AND'd with 3
2778 */
2779 logerror("%s - tsinstruction is 0x%08x\n", (unsigned)ti->tsinstruction);
2780 render_tri_sorted<&powervr2_device::sample_nontextured, group_no>(bitmap, ti, v+i0, v+i1, v+i2);
2781 }
2782 } else {
2783 switch (ti->tsinstruction) {
2784 case 0:
2785 render_tri_sorted<&powervr2_device::sample_textured<0,false>, group_no>(bitmap, ti, v+i0, v+i1, v+i2);
2786 break;
2787 case 1:
2788 render_tri_sorted<&powervr2_device::sample_textured<1,false>, group_no>(bitmap, ti, v+i0, v+i1, v+i2);
2789 break;
2790 case 2:
2791 render_tri_sorted<&powervr2_device::sample_textured<2,false>, group_no>(bitmap, ti, v+i0, v+i1, v+i2);
2792 break;
2793 case 3:
2794 render_tri_sorted<&powervr2_device::sample_textured<3,false>, group_no>(bitmap, ti, v+i0, v+i1, v+i2);
2795 break;
2796 default:
2797 /*
2798 * This should be impossible because tsinstruction was previously
2799 * AND'd with 3
2800 */
2801 logerror("%s - tsinstruction is 0x%08x\n", (unsigned)ti->tsinstruction);
2802 render_tri_sorted<&powervr2_device::sample_nontextured, group_no>(bitmap, ti, v+i0, v+i1, v+i2);
2803 }
2804 }
2805 } else {
2806 render_tri_sorted<&powervr2_device::sample_nontextured, group_no>(bitmap, ti, v+i0, v+i1, v+i2);
2807 }
2808 }
2809
2810 template <int group_no>
render_group_to_accumulation_buffer(bitmap_rgb32 & bitmap,const rectangle & cliprect)2811 void powervr2_device::render_group_to_accumulation_buffer(bitmap_rgb32 &bitmap,const rectangle &cliprect)
2812 {
2813 #if 0
2814 int stride;
2815 uint16_t *bmpaddr16;
2816 uint32_t k;
2817 #endif
2818
2819
2820 if (renderselect < 0)
2821 return;
2822
2823 //printf("drawtest!\n");
2824
2825 int rs=renderselect;
2826
2827 struct poly_group *grp = grab[rs].groups + group_no;
2828
2829 int ns=grp->strips_size;
2830
2831 for (int cs=0;cs < ns;cs++)
2832 {
2833 strip *ts = &grp->strips[cs];
2834 int sv = ts->svert;
2835 int ev = ts->evert;
2836 int i;
2837 if(ev == -1)
2838 continue;
2839
2840 for(i=sv; i <= ev; i++)
2841 {
2842 vert *tv = grab[rs].verts + i;
2843 tv->u = tv->u * ts->ti.sizex * tv->w;
2844 tv->v = tv->v * ts->ti.sizey * tv->w;
2845 }
2846
2847 for(i=sv; i <= ev-2; i++)
2848 {
2849 if (!(debug_dip_status&0x2))
2850 render_tri<group_no>(bitmap, &ts->ti, grab[rs].verts + i);
2851
2852 }
2853 }
2854 }
2855
render_to_accumulation_buffer(bitmap_rgb32 & bitmap,const rectangle & cliprect)2856 void powervr2_device::render_to_accumulation_buffer(bitmap_rgb32 &bitmap, const rectangle &cliprect) {
2857 if (renderselect < 0)
2858 return;
2859
2860 memset(wbuffer, 0x00, sizeof(wbuffer));
2861
2862 dc_state *state = machine().driver_data<dc_state>();
2863 address_space &space = state->m_maincpu->space(AS_PROGRAM);
2864 uint32_t c=space.read_dword(0x05000000+((isp_backgnd_t & 0xfffff8)>>1)+(3+3)*4);
2865 bitmap.fill(c, cliprect);
2866
2867 // TODO: modifier volumes
2868 render_group_to_accumulation_buffer<DISPLAY_LIST_OPAQUE>(bitmap, cliprect);
2869 render_group_to_accumulation_buffer<DISPLAY_LIST_TRANS>(bitmap, cliprect);
2870 render_group_to_accumulation_buffer<DISPLAY_LIST_PUNCH_THROUGH>(bitmap, cliprect);
2871
2872 grab[renderselect].busy=0;
2873 }
2874
2875 // copies the accumulation buffer into the framebuffer, converting to the specified format
2876 // not accurate, ignores field stuff and just uses SOF1 for now
2877 // also ignores scale effects (can scale accumulation buffer to half size with filtering etc.)
2878 // also can specify dither etc.
2879 // basically, just a crude implementation!
2880
2881 /* 0555KRGB = 0 */
fb_convert_0555krgb_to_555rgb(address_space & space,int x,int y)2882 void powervr2_device::fb_convert_0555krgb_to_555rgb(address_space &space, int x,int y)
2883 {
2884 for (int ycnt=0;ycnt<32;ycnt++)
2885 {
2886 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2);
2887 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
2888
2889 for (int xcnt=0;xcnt<32;xcnt++)
2890 {
2891 // data starts in 8888 format, downsample it
2892 uint32_t data = src[xcnt];
2893 uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) |
2894 ((((data & 0x0000f800) >> 11)) << 5) |
2895 ((((data & 0x00f80000) >> 19)) << 10);
2896
2897 space.write_word(realwriteoffs+xcnt*2, newdat);
2898 }
2899 }
2900 }
2901
fb_convert_0555krgb_to_565rgb(address_space & space,int x,int y)2902 void powervr2_device::fb_convert_0555krgb_to_565rgb(address_space &space, int x,int y)
2903 {
2904 for (int ycnt=0;ycnt<32;ycnt++)
2905 {
2906 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2);
2907 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
2908
2909 for (int xcnt=0;xcnt<32;xcnt++)
2910 {
2911 // data starts in 8888 format, downsample it
2912 uint32_t data = src[xcnt];
2913 uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) |
2914 ((((data & 0x0000f800) >> 11)) << 5) |
2915 ((((data & 0x00f80000) >> 19)) << 11);
2916
2917 space.write_word(realwriteoffs+xcnt*2, newdat);
2918 }
2919 }
2920 }
2921
fb_convert_0555krgb_to_888rgb24(address_space & space,int x,int y)2922 void powervr2_device::fb_convert_0555krgb_to_888rgb24(address_space &space, int x,int y)
2923 {
2924 for (int ycnt=0;ycnt<32;ycnt++)
2925 {
2926 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*3);
2927 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
2928
2929 for (int xcnt=0;xcnt<32;xcnt++)
2930 {
2931 // data starts in 8888 format, downsample it
2932 uint32_t data = src[xcnt];
2933 uint32_t newdat = (data & 0xf8f8f8);
2934
2935 space.write_byte(realwriteoffs+xcnt*3+0, newdat >> 0);
2936 space.write_byte(realwriteoffs+xcnt*3+1, newdat >> 8);
2937 space.write_byte(realwriteoffs+xcnt*3+2, newdat >> 16);
2938 }
2939 }
2940 }
2941
fb_convert_0555krgb_to_888rgb32(address_space & space,int x,int y)2942 void powervr2_device::fb_convert_0555krgb_to_888rgb32(address_space &space, int x,int y)
2943 {
2944 for (int ycnt=0;ycnt<32;ycnt++)
2945 {
2946 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*4);
2947 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
2948
2949 for (int xcnt=0;xcnt<32;xcnt++)
2950 {
2951 // data starts in 8888 format, downsample it
2952 uint32_t data = src[xcnt];
2953 uint32_t newdat = (data & 0xf8f8f8);
2954
2955 space.write_dword(realwriteoffs+xcnt*4, newdat);
2956 }
2957 }
2958 }
2959
2960 /* 0565RGB = 1 */
fb_convert_0565rgb_to_555rgb(address_space & space,int x,int y)2961 void powervr2_device::fb_convert_0565rgb_to_555rgb(address_space &space, int x,int y)
2962 {
2963 for (int ycnt=0;ycnt<32;ycnt++)
2964 {
2965 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2);
2966 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
2967
2968 for (int xcnt=0;xcnt<32;xcnt++)
2969 {
2970 // data starts in 8888 format, downsample it
2971 uint32_t data = src[xcnt];
2972 uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) |
2973 ((((data & 0x0000fc00) >> 10)) << 5) |
2974 ((((data & 0x00f80000) >> 19)) << 10);
2975
2976 space.write_word(realwriteoffs+xcnt*2, newdat);
2977 }
2978 }
2979 }
2980
fb_convert_0565rgb_to_565rgb(address_space & space,int x,int y)2981 void powervr2_device::fb_convert_0565rgb_to_565rgb(address_space &space, int x,int y)
2982 {
2983 for (int ycnt=0;ycnt<32;ycnt++)
2984 {
2985 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2);
2986 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
2987
2988 for (int xcnt=0;xcnt<32;xcnt++)
2989 {
2990 // data starts in 8888 format, downsample it
2991 uint32_t data = src[xcnt];
2992 uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) |
2993 ((((data & 0x0000fc00) >> 10)) << 5) |
2994 ((((data & 0x00f80000) >> 19)) << 11);
2995
2996 space.write_word(realwriteoffs+xcnt*2, newdat);
2997 }
2998 }
2999 }
3000
fb_convert_0565rgb_to_888rgb24(address_space & space,int x,int y)3001 void powervr2_device::fb_convert_0565rgb_to_888rgb24(address_space &space, int x,int y)
3002 {
3003 for (int ycnt=0;ycnt<32;ycnt++)
3004 {
3005 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*3);
3006 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
3007
3008 for (int xcnt=0;xcnt<32;xcnt++)
3009 {
3010 // data starts in 8888 format, downsample it
3011 uint32_t data = src[xcnt];
3012 uint32_t newdat = (data & 0xf8fcf8);
3013
3014 space.write_byte(realwriteoffs+xcnt*3+0, newdat >> 0);
3015 space.write_byte(realwriteoffs+xcnt*3+1, newdat >> 8);
3016 space.write_byte(realwriteoffs+xcnt*3+2, newdat >> 16);
3017 }
3018 }
3019 }
3020
fb_convert_0565rgb_to_888rgb32(address_space & space,int x,int y)3021 void powervr2_device::fb_convert_0565rgb_to_888rgb32(address_space &space, int x,int y)
3022 {
3023 for (int ycnt=0;ycnt<32;ycnt++)
3024 {
3025 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*4);
3026 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
3027
3028 for (int xcnt=0;xcnt<32;xcnt++)
3029 {
3030 // data starts in 8888 format, downsample it
3031 uint32_t data = src[xcnt];
3032 uint32_t newdat = (data & 0xf8fcf8);
3033
3034 space.write_dword(realwriteoffs+xcnt*4, newdat);
3035 }
3036 }
3037 }
3038
3039 /* 1555ARGB = 3 */
fb_convert_1555argb_to_555rgb(address_space & space,int x,int y)3040 void powervr2_device::fb_convert_1555argb_to_555rgb(address_space &space, int x,int y)
3041 {
3042 for (int ycnt=0;ycnt<32;ycnt++)
3043 {
3044 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2);
3045 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
3046
3047 for (int xcnt=0;xcnt<32;xcnt++)
3048 {
3049 // data starts in 8888 format, downsample it
3050 uint32_t data = src[xcnt];
3051 uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) |
3052 ((((data & 0x0000f800) >> 11)) << 5) |
3053 ((((data & 0x00f80000) >> 19)) << 10);
3054
3055 space.write_word(realwriteoffs+xcnt*2, newdat);
3056 }
3057 }
3058 }
3059
fb_convert_1555argb_to_565rgb(address_space & space,int x,int y)3060 void powervr2_device::fb_convert_1555argb_to_565rgb(address_space &space, int x,int y)
3061 {
3062 for (int ycnt=0;ycnt<32;ycnt++)
3063 {
3064 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2);
3065 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
3066
3067 for (int xcnt=0;xcnt<32;xcnt++)
3068 {
3069 // data starts in 8888 format, downsample it
3070 uint32_t data = src[xcnt];
3071 uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) |
3072 ((((data & 0x0000f800) >> 11)) << 5) |
3073 ((((data & 0x00f80000) >> 19)) << 11);
3074
3075 space.write_word(realwriteoffs+xcnt*2, newdat);
3076 }
3077 }
3078 }
3079
fb_convert_1555argb_to_888rgb24(address_space & space,int x,int y)3080 void powervr2_device::fb_convert_1555argb_to_888rgb24(address_space &space, int x,int y)
3081 {
3082 for (int ycnt=0;ycnt<32;ycnt++)
3083 {
3084 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*3);
3085 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
3086
3087 for (int xcnt=0;xcnt<32;xcnt++)
3088 {
3089 // data starts in 8888 format, downsample it
3090 uint32_t data = src[xcnt];
3091 uint32_t newdat = (data & 0xf8f8f8);
3092
3093 space.write_byte(realwriteoffs+xcnt*3+0, newdat >> 0);
3094 space.write_byte(realwriteoffs+xcnt*3+1, newdat >> 8);
3095 space.write_byte(realwriteoffs+xcnt*3+2, newdat >> 16);
3096 }
3097 }
3098 }
3099
fb_convert_1555argb_to_888rgb32(address_space & space,int x,int y)3100 void powervr2_device::fb_convert_1555argb_to_888rgb32(address_space &space, int x,int y)
3101 {
3102 for (int ycnt=0;ycnt<32;ycnt++)
3103 {
3104 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*4);
3105 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
3106
3107 for (int xcnt=0;xcnt<32;xcnt++)
3108 {
3109 // data starts in 8888 format, downsample it
3110 uint32_t data = src[xcnt];
3111 uint32_t newdat = (data & 0xf8f8f8);
3112
3113 space.write_dword(realwriteoffs+xcnt*4, newdat);
3114 }
3115 }
3116 }
3117
3118 /* 888RGB = 4 */
fb_convert_888rgb_to_555rgb(address_space & space,int x,int y)3119 void powervr2_device::fb_convert_888rgb_to_555rgb(address_space &space, int x,int y)
3120 {
3121 for (int ycnt=0;ycnt<32;ycnt++)
3122 {
3123 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2);
3124 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
3125
3126 for (int xcnt=0;xcnt<32;xcnt++)
3127 {
3128 // data starts in 8888 format, downsample it
3129 uint32_t data = src[xcnt];
3130 uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) |
3131 ((((data & 0x0000f800) >> 11)) << 5) |
3132 ((((data & 0x00f80000) >> 16)) << 10);
3133
3134 space.write_word(realwriteoffs+xcnt*2, newdat);
3135 }
3136 }
3137 }
3138
fb_convert_888rgb_to_565rgb(address_space & space,int x,int y)3139 void powervr2_device::fb_convert_888rgb_to_565rgb(address_space &space, int x,int y)
3140 {
3141 for (int ycnt=0;ycnt<32;ycnt++)
3142 {
3143 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2);
3144 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
3145
3146 for (int xcnt=0;xcnt<32;xcnt++)
3147 {
3148 // data starts in 8888 format, downsample it
3149 uint32_t data = src[xcnt];
3150 uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) |
3151 ((((data & 0x0000fc00) >> 11)) << 5) |
3152 ((((data & 0x00f80000) >> 16)) << 11);
3153
3154 space.write_word(realwriteoffs+xcnt*2, newdat);
3155 }
3156 }
3157 }
3158
fb_convert_888rgb_to_888rgb24(address_space & space,int x,int y)3159 void powervr2_device::fb_convert_888rgb_to_888rgb24(address_space &space, int x,int y)
3160 {
3161 for (int ycnt=0;ycnt<32;ycnt++)
3162 {
3163 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*3);
3164 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
3165
3166 for (int xcnt=0;xcnt<32;xcnt++)
3167 {
3168 // data starts in 8888 format, downsample it
3169 uint32_t data = src[xcnt];
3170 uint32_t newdat = (data & 0xffffff);
3171
3172 space.write_byte(realwriteoffs+xcnt*3+0, newdat >> 0);
3173 space.write_byte(realwriteoffs+xcnt*3+1, newdat >> 8);
3174 space.write_byte(realwriteoffs+xcnt*3+2, newdat >> 16);
3175 }
3176 }
3177 }
3178
fb_convert_888rgb_to_888rgb32(address_space & space,int x,int y)3179 void powervr2_device::fb_convert_888rgb_to_888rgb32(address_space &space, int x,int y)
3180 {
3181 for (int ycnt=0;ycnt<32;ycnt++)
3182 {
3183 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*4);
3184 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
3185
3186 for (int xcnt=0;xcnt<32;xcnt++)
3187 {
3188 // data starts in 8888 format, downsample it
3189 uint32_t data = src[xcnt];
3190 uint32_t newdat = (data & 0xffffff);
3191
3192 space.write_dword(realwriteoffs+xcnt*4, newdat);
3193 }
3194 }
3195 }
3196
3197
3198 /* 8888ARGB = 6 */
fb_convert_8888argb_to_555rgb(address_space & space,int x,int y)3199 void powervr2_device::fb_convert_8888argb_to_555rgb(address_space &space, int x,int y)
3200 {
3201 for (int ycnt=0;ycnt<32;ycnt++)
3202 {
3203 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2);
3204 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
3205
3206 for (int xcnt=0;xcnt<32;xcnt++)
3207 {
3208 // data starts in 8888 format, downsample it
3209 uint32_t data = src[xcnt];
3210 uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) |
3211 ((((data & 0x0000f800) >> 11)) << 5) |
3212 ((((data & 0x00f80000) >> 16)) << 10);
3213
3214 space.write_word(realwriteoffs+xcnt*2, newdat);
3215 }
3216 }
3217 }
3218
fb_convert_8888argb_to_565rgb(address_space & space,int x,int y)3219 void powervr2_device::fb_convert_8888argb_to_565rgb(address_space &space, int x,int y)
3220 {
3221 for (int ycnt=0;ycnt<32;ycnt++)
3222 {
3223 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*2);
3224 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
3225
3226 for (int xcnt=0;xcnt<32;xcnt++)
3227 {
3228 // data starts in 8888 format, downsample it
3229 uint32_t data = src[xcnt];
3230 uint16_t newdat = ((((data & 0x000000f8) >> 3)) << 0) |
3231 ((((data & 0x0000fc00) >> 11)) << 5) |
3232 ((((data & 0x00f80000) >> 16)) << 11);
3233
3234 space.write_word(realwriteoffs+xcnt*2, newdat);
3235 }
3236 }
3237 }
3238
fb_convert_8888argb_to_888rgb24(address_space & space,int x,int y)3239 void powervr2_device::fb_convert_8888argb_to_888rgb24(address_space &space, int x,int y)
3240 {
3241 for (int ycnt=0;ycnt<32;ycnt++)
3242 {
3243 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*3);
3244 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
3245
3246 for (int xcnt=0;xcnt<32;xcnt++)
3247 {
3248 // data starts in 8888 format, downsample it
3249 uint32_t data = src[xcnt];
3250 uint32_t newdat = (data & 0xffffff);
3251
3252 space.write_byte(realwriteoffs+xcnt*3+0, newdat >> 0);
3253 space.write_byte(realwriteoffs+xcnt*3+1, newdat >> 8);
3254 space.write_byte(realwriteoffs+xcnt*3+2, newdat >> 16);
3255 }
3256 }
3257 }
3258
fb_convert_8888argb_to_888rgb32(address_space & space,int x,int y)3259 void powervr2_device::fb_convert_8888argb_to_888rgb32(address_space &space, int x,int y)
3260 {
3261 for (int ycnt=0;ycnt<32;ycnt++)
3262 {
3263 uint32_t realwriteoffs = 0x05000000 + fb_w_sof1 + (y+ycnt) * (fb_w_linestride<<3) + (x*4);
3264 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y+ycnt, x);
3265
3266 for (int xcnt=0;xcnt<32;xcnt++)
3267 {
3268 // data starts in 8888 format, downsample it
3269 uint32_t data = src[xcnt];
3270 uint32_t newdat = (data & 0xffffff);
3271
3272 space.write_dword(realwriteoffs+xcnt*4, newdat);
3273 }
3274 }
3275 }
3276
3277
3278 /*
3279
3280 0x0 0555 KRGB 16 bit (default) Bit 15 is the value of fb_kval 7.
3281 0x1 565 RGB 16 bit
3282 0x2 4444 ARGB 16 bit
3283 0x3 1555 ARGB 16 bit The alpha value is determined by comparison with the value of fb_alpha_threshold.
3284 0x4 888 RGB 24 bit packed
3285 0x5 0888 KRGB 32 bit K is the value of fk_kval.
3286 0x6 8888 ARGB 32 bit
3287 0x7 Setting prohibited.
3288
3289 */
3290
pvr_accumulationbuffer_to_framebuffer(address_space & space,int x,int y)3291 void powervr2_device::pvr_accumulationbuffer_to_framebuffer(address_space &space, int x,int y)
3292 {
3293 // the accumulation buffer is always 8888
3294 //
3295 // the standard format for the framebuffer appears to be 565
3296 // yes, this means colour data is lost in the conversion
3297
3298 uint8_t packmode = fb_w_ctrl & 0x7;
3299 uint8_t unpackmode = (fb_r_ctrl & 0x0000000c) >>2; // aka fb_depth
3300
3301 // popmessage("%02x %02x",packmode,unpackmode);
3302
3303 switch (packmode)
3304 {
3305 // used by ringout
3306 case 0x00: //0555 KRGB
3307 {
3308 switch(unpackmode)
3309 {
3310 case 0x00: fb_convert_0555krgb_to_555rgb(space,x,y); break;
3311 case 0x01: fb_convert_0555krgb_to_565rgb(space,x,y); break;
3312 case 0x02: fb_convert_0555krgb_to_888rgb24(space,x,y); break;
3313 case 0x03: fb_convert_0555krgb_to_888rgb32(space,x,y); break;
3314 }
3315 }
3316 break;
3317
3318 // used by cleoftp
3319 case 0x01: //565 RGB 16 bit
3320 {
3321 switch(unpackmode)
3322 {
3323 case 0x00: fb_convert_0565rgb_to_555rgb(space,x,y); break;
3324 case 0x01: fb_convert_0565rgb_to_565rgb(space,x,y); break;
3325 case 0x02: fb_convert_0565rgb_to_888rgb24(space,x,y); break;
3326 case 0x03: fb_convert_0565rgb_to_888rgb32(space,x,y); break;
3327 }
3328 }
3329 break;
3330
3331 case 0x02:
3332 printf("pvr_accumulationbuffer_to_framebuffer buffer to tile at %d,%d - unsupported pack mode %02x (4444 ARGB)\n",x,y,packmode);
3333 break;
3334
3335 case 0x03: // 1555 ARGB 16 bit
3336 {
3337 switch(unpackmode)
3338 {
3339 case 0x00: fb_convert_1555argb_to_555rgb(space,x,y); break;
3340 case 0x01: fb_convert_1555argb_to_565rgb(space,x,y); break;
3341 case 0x02: fb_convert_1555argb_to_888rgb24(space,x,y); break;
3342 case 0x03: fb_convert_1555argb_to_888rgb32(space,x,y); break;
3343 }
3344 }
3345 break;
3346
3347 // used by Suchie3
3348 case 0x04: // 888 RGB 24-bit
3349 {
3350 switch(unpackmode)
3351 {
3352 case 0x00: fb_convert_888rgb_to_555rgb(space,x,y); break;
3353 case 0x01: fb_convert_888rgb_to_565rgb(space,x,y); break;
3354 case 0x02: fb_convert_888rgb_to_888rgb24(space,x,y); break;
3355 case 0x03: fb_convert_888rgb_to_888rgb32(space,x,y); break;
3356 }
3357 }
3358 break;
3359
3360 case 0x05:
3361 printf("pvr_accumulationbuffer_to_framebuffer buffer to tile at %d,%d - unsupported pack mode %02x (0888 KGB 32-bit)\n",x,y,packmode);
3362 break;
3363
3364 case 0x06: // 8888 ARGB 32 bit
3365 {
3366 switch(unpackmode)
3367 {
3368 case 0x00: fb_convert_8888argb_to_555rgb(space,x,y); break;
3369 case 0x01: fb_convert_8888argb_to_565rgb(space,x,y); break;
3370 case 0x02: fb_convert_8888argb_to_888rgb24(space,x,y); break;
3371 case 0x03: fb_convert_8888argb_to_888rgb32(space,x,y); break;
3372 }
3373 }
3374 break;
3375
3376 case 0x07:
3377 printf("pvr_accumulationbuffer_to_framebuffer buffer to tile at %d,%d - unsupported pack mode %02x (Reserved! Don't Use!)\n",x,y,packmode);
3378 break;
3379 }
3380
3381
3382 }
3383
pvr_drawframebuffer(bitmap_rgb32 & bitmap,const rectangle & cliprect)3384 void powervr2_device::pvr_drawframebuffer(bitmap_rgb32 &bitmap,const rectangle &cliprect)
3385 {
3386 int dy,xi;
3387 uint8_t interlace_on = ((spg_control & 0x10) >> 4);
3388 int32_t ystart_f1 = (vo_starty & 0x3ff) << interlace_on;
3389 //int32_t ystart_f2 = (vo_starty >> 16) & 0x3ff;
3390 int32_t hstart = (vo_startx & 0x3ff);
3391 // rectangle fbclip;
3392
3393 uint8_t unpackmode = (fb_r_ctrl & 0x0000000c) >>2; // aka fb_depth
3394 uint8_t enable = (fb_r_ctrl & 0x00000001);
3395
3396 // ??
3397 if (!enable) return;
3398
3399 // only for rgb565 framebuffer
3400 xi=((fb_r_size & 0x3ff)+1) << 1;
3401 dy=((fb_r_size >> 10) & 0x3ff)+1;
3402
3403 dy++;
3404 dy*=2; // probably depends on interlace mode, fields etc...
3405
3406 // popmessage("%d %d %d %d %d",ystart_f1,ystart_f2,interlace_on,spg_vblank & 0x3ff,(spg_vblank >> 16) & 0x3ff);
3407
3408 #if 0
3409 fbclip.min_x = hstart;
3410 fbclip.min_y = ystart_f1;
3411 fbclip.max_x = hstart + (xi << ((vo_control & 0x100) >> 8));
3412 fbclip.max_y = ystart_f1 + dy;
3413
3414 popmessage("%d %d %d %d",fbclip.min_x,fbclip.min_y,fbclip.max_x,fbclip.max_y);
3415 #endif
3416
3417 switch (unpackmode)
3418 {
3419 case 0x00: // 0555 RGB 16-bit, Cleo Fortune Plus
3420 // should upsample back to 8-bit output using fb_concat
3421 for (int y=0;y <= dy;y++)
3422 {
3423 uint32_t addrp = fb_r_sof1+y*xi*2;
3424 if(vo_control & 0x100)
3425 {
3426 for (int x=0;x < xi;x++)
3427 {
3428 int res_x = x*2+0 + hstart;
3429 int res_y = y + ystart_f1;
3430
3431 uint32_t *fbaddr=&bitmap.pix(res_y, res_x);
3432 uint32_t c=*((reinterpret_cast<uint16_t *>(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1));
3433
3434 uint32_t b = (c & 0x001f) << 3;
3435 uint32_t g = (c & 0x03e0) >> 2;
3436 uint32_t r = (c & 0x7c00) >> 7;
3437
3438 if (cliprect.contains(res_x, res_y))
3439 *fbaddr = b | (g<<8) | (r<<16);
3440
3441 res_x = x*2+1 + hstart;
3442
3443 fbaddr=&bitmap.pix(res_y, res_x);
3444 if (cliprect.contains(res_x, res_y))
3445 *fbaddr = b | (g<<8) | (r<<16);
3446 addrp+=2;
3447 }
3448 }
3449 else
3450 {
3451 for (int x=0;x < xi;x++)
3452 {
3453 int res_x = x + hstart;
3454 int res_y = y + ystart_f1;
3455
3456 uint32_t *fbaddr=&bitmap.pix(res_y, res_x);
3457 uint32_t c=*((reinterpret_cast<uint16_t *>(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1));
3458
3459 uint32_t b = (c & 0x001f) << 3;
3460 uint32_t g = (c & 0x03e0) >> 2;
3461 uint32_t r = (c & 0x7c00) >> 7;
3462
3463 if (cliprect.contains(res_x, res_y))
3464 *fbaddr = b | (g<<8) | (r<<16);
3465 addrp+=2;
3466 }
3467 }
3468 }
3469 break;
3470
3471 case 0x01: // 0565 RGB 16-bit
3472 // should upsample back to 8-bit output using fb_concat
3473 for (int y=0;y <= dy;y++)
3474 {
3475 uint32_t addrp = fb_r_sof1+y*xi*2;
3476 if(vo_control & 0x100)
3477 {
3478 for (int x=0;x < xi;x++)
3479 {
3480 int res_x = x*2+0 + hstart;
3481 int res_y = y + ystart_f1;
3482 uint32_t *fbaddr=&bitmap.pix(res_y, res_x);
3483 uint32_t c=*((reinterpret_cast<uint16_t *>(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1));
3484
3485 uint32_t b = (c & 0x001f) << 3;
3486 uint32_t g = (c & 0x07e0) >> 3;
3487 uint32_t r = (c & 0xf800) >> 8;
3488
3489 if (cliprect.contains(res_x, res_y))
3490 *fbaddr = b | (g<<8) | (r<<16);
3491
3492 res_x = x*2+1 + hstart;
3493 //res_y = y + ystart_f1;
3494 fbaddr=&bitmap.pix(res_y, res_x);
3495
3496 if (cliprect.contains(res_x, res_y))
3497 *fbaddr = b | (g<<8) | (r<<16);
3498
3499 addrp+=2;
3500 }
3501 }
3502 else
3503 {
3504 for (int x=0;x < xi;x++)
3505 {
3506 int res_x = x + hstart;
3507 int res_y = y + ystart_f1;
3508 uint32_t *fbaddr=&bitmap.pix(res_y, res_x);
3509 uint32_t c=*((reinterpret_cast<uint16_t *>(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1));
3510
3511 uint32_t b = (c & 0x001f) << 3;
3512 uint32_t g = (c & 0x07e0) >> 3;
3513 uint32_t r = (c & 0xf800) >> 8;
3514
3515 if (cliprect.contains(res_x, res_y))
3516 *fbaddr = b | (g<<8) | (r<<16);
3517 addrp+=2;
3518 }
3519 }
3520 }
3521 break;
3522
3523 case 0x02: ; // 888 RGB 24-bit - suchie3, Soul Calibur
3524 for (int y=0;y <= dy;y++)
3525 {
3526 uint32_t addrp = fb_r_sof1+y*xi*2;
3527
3528 if(vo_control & 0x100)
3529 {
3530 for (int x=0;x < xi;x++)
3531 {
3532 int res_x = x*2+0 + hstart;
3533 int res_y = y + ystart_f1;
3534
3535 uint32_t *fbaddr=&bitmap.pix(res_y, res_x);
3536
3537 uint32_t b =*(uint8_t *)((reinterpret_cast<uint8_t *>(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp));
3538
3539 uint32_t g =*(uint8_t *)((reinterpret_cast<uint8_t *>(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp+1));
3540
3541 uint32_t r =*(uint8_t *)((reinterpret_cast<uint8_t *>(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp+2));
3542
3543 if (cliprect.contains(res_x, res_y))
3544 *fbaddr = b | (g<<8) | (r<<16);
3545
3546 res_x = x*2+1 + hstart;
3547
3548 fbaddr=&bitmap.pix(res_y, res_x);
3549 if (cliprect.contains(res_x, res_y))
3550 *fbaddr = b | (g<<8) | (r<<16);
3551
3552 addrp+=3;
3553 }
3554 }
3555 else
3556 {
3557 for (int x=0;x < xi;x++)
3558 {
3559 int res_x = x + hstart;
3560 int res_y = y + ystart_f1;
3561 uint32_t *fbaddr=&bitmap.pix(res_y, res_x);
3562
3563 uint32_t b =*(uint8_t *)((reinterpret_cast<uint8_t *>(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp));
3564
3565 uint32_t g =*(uint8_t *)((reinterpret_cast<uint8_t *>(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp+1));
3566
3567 uint32_t r =*(uint8_t *)((reinterpret_cast<uint8_t *>(dc_framebuffer_ram)) + BYTE8_XOR_LE(addrp+2));
3568
3569 if (cliprect.contains(res_x, res_y))
3570 *fbaddr = b | (g<<8) | (r<<16);
3571
3572 addrp+=3;
3573 }
3574 }
3575 }
3576 break;
3577
3578 case 0x03: // 0888 ARGB 32-bit
3579 for (int y=0;y <= dy;y++)
3580 {
3581 uint32_t addrp = fb_r_sof1+y*xi*2;
3582
3583 if(vo_control & 0x100)
3584 {
3585 for (int x=0;x < xi;x++)
3586 {
3587 int res_x = x*2+0 + hstart;
3588 int res_y = y + ystart_f1;
3589
3590 uint32_t *fbaddr=&bitmap.pix(res_y, res_x);
3591 uint32_t c =*((reinterpret_cast<uint32_t *>(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 2));
3592
3593 uint32_t b = (c & 0x0000ff) >> 0;
3594 uint32_t g = (c & 0x00ff00) >> 8;
3595 uint32_t r = (c & 0xff0000) >> 16;
3596
3597 if (cliprect.contains(res_x, res_y))
3598 *fbaddr = b | (g<<8) | (r<<16);
3599
3600 res_x = x*2+1 + hstart;
3601
3602 fbaddr=&bitmap.pix(res_y, res_x);
3603 if (cliprect.contains(res_x, res_y))
3604 *fbaddr = b | (g<<8) | (r<<16);
3605
3606 addrp+=4;
3607 }
3608 }
3609 else
3610 {
3611 for (int x=0;x < xi;x++)
3612 {
3613 int res_x = x + hstart;
3614 int res_y = y + ystart_f1;
3615 uint32_t *fbaddr=&bitmap.pix(res_y, res_x);
3616 uint32_t c =*((reinterpret_cast<uint32_t *>(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 2));
3617
3618 uint32_t b = (c & 0x0000ff) >> 0;
3619 uint32_t g = (c & 0x00ff00) >> 8;
3620 uint32_t r = (c & 0xff0000) >> 16;
3621
3622 if (cliprect.contains(res_x, res_y))
3623 *fbaddr = b | (g<<8) | (r<<16);
3624
3625 addrp+=4;
3626 }
3627 }
3628 }
3629 break;
3630 }
3631 }
3632
3633
3634 #if DEBUG_PALRAM
debug_paletteram()3635 void powervr2_device::debug_paletteram()
3636 {
3637 //popmessage("%02x",pal_ram_ctrl);
3638
3639 for(int i=0;i<0x400;i++)
3640 {
3641 uint64_t pal = palette[i];
3642 switch(pal_ram_ctrl)
3643 {
3644 case 0: //argb1555 <- guilty gear uses this mode
3645 {
3646 //a = (pal & 0x8000)>>15;
3647 uint32_t r = (pal & 0x7c00)>>10;
3648 uint32_t g = (pal & 0x03e0)>>5;
3649 uint32_t b = (pal & 0x001f)>>0;
3650 //a = a ? 0xff : 0x00;
3651 m_palette->set_pen_color(i, pal5bit(r), pal5bit(g), pal5bit(b));
3652 }
3653 break;
3654 case 1: //rgb565
3655 {
3656 //a = 0xff;
3657 uint32_t r = (pal & 0xf800)>>11;
3658 uint32_t g = (pal & 0x07e0)>>5;
3659 uint32_t b = (pal & 0x001f)>>0;
3660 m_palette->set_pen_color(i, pal5bit(r), pal6bit(g), pal5bit(b));
3661 }
3662 break;
3663 case 2: //argb4444
3664 {
3665 //a = (pal & 0xf000)>>12;
3666 uint32_t r = (pal & 0x0f00)>>8;
3667 uint32_t g = (pal & 0x00f0)>>4;
3668 uint32_t b = (pal & 0x000f)>>0;
3669 m_palette->set_pen_color(i, pal4bit(r), pal4bit(g), pal4bit(b));
3670 }
3671 break;
3672 case 3: //argb8888
3673 {
3674 //a = (pal & 0xff000000)>>20;
3675 uint32_t r = (pal & 0x00ff0000)>>16;
3676 uint32_t g = (pal & 0x0000ff00)>>8;
3677 uint32_t b = (pal & 0x000000ff)>>0;
3678 m_palette->set_pen_color(i, r, g, b);
3679 }
3680 break;
3681 }
3682 }
3683 }
3684 #endif
3685
3686 /* test video end */
3687
pvr_build_parameterconfig()3688 void powervr2_device::pvr_build_parameterconfig()
3689 {
3690 int a,b,c,d,e,p;
3691
3692 for (a = 0;a <= 63;a++)
3693 pvr_parameterconfig[a] = -1;
3694 p=0;
3695 // volume,col_type,texture,offset,16bit_uv
3696 for (a = 0;a <= 1;a++)
3697 for (b = 0;b <= 3;b++)
3698 for (c = 0;c <= 1;c++)
3699 if (c == 0)
3700 {
3701 for (d = 0;d <= 1;d++)
3702 for (e = 0;e <= 1;e++)
3703 pvr_parameterconfig[(a << 6) | (b << 4) | (c << 3) | (d << 2) | (e << 0)] = pvr_parconfseq[p];
3704 p++;
3705 }
3706 else
3707 for (d = 0;d <= 1;d++)
3708 for (e = 0;e <= 1;e++)
3709 {
3710 pvr_parameterconfig[(a << 6) | (b << 4) | (c << 3) | (d << 2) | (e << 0)] = pvr_parconfseq[p];
3711 p++;
3712 }
3713 for (a = 1;a <= 63;a++)
3714 if (pvr_parameterconfig[a] < 0)
3715 pvr_parameterconfig[a] = pvr_parameterconfig[a-1];
3716 }
3717
TIMER_CALLBACK_MEMBER(powervr2_device::vbin)3718 TIMER_CALLBACK_MEMBER(powervr2_device::vbin)
3719 {
3720 irq_cb(VBL_IN_IRQ);
3721
3722 //popmessage("VII %d VOI %d VI %d VO %d VS %d",spg_vblank_int & 0x3ff,(spg_vblank_int >> 16) & 0x3ff,spg_vblank & 0x3ff,(spg_vblank >> 16) & 0x3ff,(spg_load >> 16) & 0x3ff);
3723 // vbin_timer->adjust(screen().time_until_pos(spg_vblank_int & 0x3ff));
3724 }
3725
TIMER_CALLBACK_MEMBER(powervr2_device::vbout)3726 TIMER_CALLBACK_MEMBER(powervr2_device::vbout)
3727 {
3728 irq_cb(VBL_OUT_IRQ);
3729
3730 // vbout_timer->adjust(screen().time_until_pos((spg_vblank_int >> 16) & 0x3ff));
3731 }
3732
TIMER_CALLBACK_MEMBER(powervr2_device::hbin)3733 TIMER_CALLBACK_MEMBER(powervr2_device::hbin)
3734 {
3735 if(spg_hblank_int & 0x1000)
3736 {
3737 if(scanline == next_y)
3738 {
3739 irq_cb(HBL_IN_IRQ);
3740 next_y += spg_hblank_int & 0x3ff;
3741 }
3742 }
3743 else if((scanline == (spg_hblank_int & 0x3ff)) || (spg_hblank_int & 0x2000))
3744 {
3745 irq_cb(HBL_IN_IRQ);
3746 }
3747
3748 // printf("hbin on scanline %d\n",scanline);
3749
3750 scanline++;
3751
3752 if(scanline >= ((spg_load >> 16) & 0x3ff))
3753 {
3754 scanline = 0;
3755 next_y = spg_hblank_int & 0x3ff;
3756 }
3757
3758 hbin_timer->adjust(screen().time_until_pos(scanline, ((spg_hblank_int >> 16) & 0x3ff)-1));
3759 }
3760
3761
3762
TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_video)3763 TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_video)
3764 {
3765 printf("VIDEO END %d\n",screen().vpos());
3766 // endofrender_timer_video->adjust(attotime::never);
3767 }
3768
TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_tsp)3769 TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_tsp)
3770 {
3771 printf("TSP END %d\n",screen().vpos());
3772
3773 // endofrender_timer_tsp->adjust(attotime::never);
3774 // endofrender_timer_video->adjust(attotime::from_usec(500) );
3775 }
3776
TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_isp)3777 TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_isp)
3778 {
3779 irq_cb(EOR_ISP_IRQ); // ISP end of render
3780 irq_cb(EOR_TSP_IRQ); // TSP end of render
3781 irq_cb(EOR_VIDEO_IRQ); // VIDEO end of render
3782
3783 // printf("ISP END %d\n",screen().vpos());
3784
3785 endofrender_timer_isp->adjust(attotime::never);
3786 // endofrender_timer_tsp->adjust(attotime::from_usec(500) );
3787 }
3788
screen_update(screen_device & screen,bitmap_rgb32 & bitmap,const rectangle & cliprect)3789 uint32_t powervr2_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
3790 {
3791 /******************
3792 MAME note
3793 *******************
3794
3795 The video update function should NOT be generating interrupts, setting timers or doing _anything_ the game might be able to detect
3796 as it will be called at different times depending on frameskip etc.
3797
3798 Rendering should happen when the hardware requests it, to the framebuffer(s)
3799
3800 Everything else should depend on timers.
3801
3802 ******************/
3803
3804 // static int useframebuffer=1;
3805 // const rectangle &visarea = screen.visible_area();
3806
3807 #if DEBUG_PALRAM
3808 debug_paletteram();
3809 #endif
3810
3811 // copy our fake framebuffer bitmap (where things have been rendered) to the screen
3812 #if 0
3813 for (int y = visarea->min_y ; y <= visarea->max_y ; y++)
3814 {
3815 for (int x = visarea->min_x ; x <= visarea->max_x ; x++)
3816 {
3817 uint32_t const *const src = &fake_accumulationbuffer_bitmap->pix(y, x);
3818 uint32_t *const dst = &bitmap.pix(y, x);
3819 dst[0] = src[0];
3820 }
3821 }
3822 #endif
3823
3824 bitmap.fill(rgb_t(0xff,
3825 (vo_border_col >> 16) & 0xff,
3826 (vo_border_col >> 8 ) & 0xff,
3827 (vo_border_col ) & 0xff), cliprect); //FIXME: Chroma bit?
3828
3829 if(!(vo_control & 8))
3830 pvr_drawframebuffer(bitmap, cliprect);
3831
3832 // update this here so we only do string lookup once per frame
3833 debug_dip_status = m_mamedebug->read();
3834
3835 return 0;
3836 }
3837
3838
3839 /* Naomi 2 attempts (TBD) */
3840
pvr2_ta_r(offs_t offset)3841 uint32_t powervr2_device::pvr2_ta_r(offs_t offset)
3842 {
3843 printf("PVR2 %08x R\n", offset);
3844
3845 return 0;
3846 }
3847
pvr2_ta_w(offs_t offset,uint32_t data,uint32_t mem_mask)3848 void powervr2_device::pvr2_ta_w(offs_t offset, uint32_t data, uint32_t mem_mask)
3849 {
3850 // int reg;
3851 // uint64_t shift;
3852 // uint32_t dat;
3853
3854 // reg = decode_reg_64(offset, mem_mask, &shift);
3855 // dat = (uint32_t)(data >> shift);
3856
3857 //printf("PVR2 %08x %08x\n",reg,dat);
3858 }
3859
3860 // TODO: move to specific device
elan_regs_r(offs_t offset)3861 uint32_t powervr2_device::elan_regs_r(offs_t offset)
3862 {
3863 switch(offset)
3864 {
3865 case 0x00/4: // ID chip (TODO: BIOS crashes / gives a black screen with this as per now!)
3866 return 0xe1ad0000;
3867 case 0x04/4: // REVISION
3868 return 0x12; //or 0x01?
3869 case 0x10/4: // SH4 interface control (???)
3870 /* ---- -x-- enable second PVR */
3871 /* ---- --x- elan has channel 2 */
3872 /* ---- ---x broadcast on cs1 (?) */
3873 return 6;
3874 case 0x14/4: // SDRAM refresh register
3875 return 0x2029; //default 0x1429
3876 case 0x1c/4: // SDRAM CFG
3877 return 0xa7320961; //default 0xa7320961
3878 case 0x30/4: // Macro tiler configuration, bit 0 is enable
3879 return 0;
3880 case 0x74/4: // IRQ STAT
3881 return 0;
3882 case 0x78/4: // IRQ MASK
3883 return 0;
3884 default:
3885 logerror("%s %08x\n", machine().describe_context(),offset*4);
3886 break;
3887 }
3888
3889 return 0;
3890 }
3891
elan_regs_w(offs_t offset,uint32_t data)3892 void powervr2_device::elan_regs_w(offs_t offset, uint32_t data)
3893 {
3894 switch(offset)
3895 {
3896 default:
3897 logerror("%s %08x %08x W\n", machine().describe_context(),offset*4,data);
3898 break;
3899 }
3900 }
3901
3902
pvrs_ta_w(offs_t offset,uint32_t data,uint32_t mem_mask)3903 void powervr2_device::pvrs_ta_w(offs_t offset, uint32_t data, uint32_t mem_mask)
3904 {
3905 // pvr_ta_w(offset,data,mem_mask);
3906 // pvr2_ta_w(offset,data,mem_mask);
3907 //printf("PVR2 %08x %08x\n",reg,dat);
3908 }
3909
TIMER_CALLBACK_MEMBER(powervr2_device::pvr_dma_irq)3910 TIMER_CALLBACK_MEMBER(powervr2_device::pvr_dma_irq)
3911 {
3912 m_pvr_dma.start = sb_pdst = 0;
3913 irq_cb(DMA_PVR_IRQ);
3914 }
3915
pvr_dma_execute(address_space & space)3916 void powervr2_device::pvr_dma_execute(address_space &space)
3917 {
3918 dc_state *state = machine().driver_data<dc_state>();
3919 uint32_t src,dst,size;
3920 dst = m_pvr_dma.pvr_addr;
3921 src = m_pvr_dma.sys_addr;
3922 size = 0;
3923
3924 /* used so far by usagui and sprtjam*/
3925 printf("PVR-DMA start\n");
3926 printf("%08x %08x %08x\n",m_pvr_dma.pvr_addr,m_pvr_dma.sys_addr,m_pvr_dma.size);
3927 printf("src %s dst %08x\n",m_pvr_dma.dir ? "->" : "<-",m_pvr_dma.sel);
3928
3929 /* Throw illegal address set */
3930 #if 0
3931 if((m_pvr_dma.sys_addr & 0x1c000000) != 0x0c000000)
3932 {
3933 /* TODO: timing */
3934 irq_cb(ERR_PVRIF_ILL_ADDR_IRQ);
3935 m_pvr_dma.start = sb_pdst = 0;
3936 printf("Illegal PVR DMA set\n");
3937 return;
3938 }
3939 #endif
3940
3941 /* 0 rounding size = 16 Mbytes */
3942 if(m_pvr_dma.size == 0) { m_pvr_dma.size = 0x100000; }
3943
3944 if(m_pvr_dma.dir == 0)
3945 {
3946 for(;size<m_pvr_dma.size;size+=4)
3947 {
3948 space.write_dword(dst,space.read_dword(src));
3949 src+=4;
3950 dst+=4;
3951 }
3952 }
3953 else
3954 {
3955 for(;size<m_pvr_dma.size;size+=4)
3956 {
3957 space.write_dword(src,space.read_dword(dst));
3958 src+=4;
3959 dst+=4;
3960 }
3961 }
3962 /* Note: do not update the params, since this DMA type doesn't support it. */
3963 /* TODO: timing of this */
3964 machine().scheduler().timer_set(state->m_maincpu->cycles_to_attotime(m_pvr_dma.size/4), timer_expired_delegate(FUNC(powervr2_device::pvr_dma_irq), this));
3965 }
3966
powervr2_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)3967 powervr2_device::powervr2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
3968 : device_t(mconfig, POWERVR2, tag, owner, clock),
3969 device_video_interface(mconfig, *this),
3970 irq_cb(*this),
3971 m_mamedebug(*this, ":MAMEDEBUG")
3972 {
3973 }
3974
device_start()3975 void powervr2_device::device_start()
3976 {
3977 irq_cb.resolve_safe();
3978
3979 grab = std::make_unique<receiveddata[]>(NUM_BUFFERS);
3980
3981 pvr_build_parameterconfig();
3982
3983 computedilated();
3984
3985 // vbout_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::vbout),this));
3986 // vbin_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::vbin),this));
3987 hbin_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::hbin),this));
3988 yuv_timer_end = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::yuv_convert_end),this));
3989
3990 endofrender_timer_isp = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::endofrender_isp),this));
3991 endofrender_timer_tsp = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::endofrender_tsp),this));
3992 endofrender_timer_video = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::endofrender_video),this));
3993
3994 fake_accumulationbuffer_bitmap = std::make_unique<bitmap_rgb32>(2048,2048);
3995
3996 softreset = 0;
3997 param_base = 0;
3998 region_base = 0;
3999 vo_border_col = 0;
4000 fb_r_ctrl = 0;
4001 fb_w_ctrl = 0;
4002 fb_w_linestride = 0;
4003 fb_r_sof1 = 0;
4004 fb_r_sof2 = 0;
4005 fb_r_size = 0;
4006 fb_w_sof1 = 0;
4007 fb_w_sof2 = 0;
4008 fb_x_clip = 0;
4009 fb_y_clip = 0;
4010 fpu_param_cfg = 0;
4011 isp_backgnd_t = 0;
4012 spg_hblank_int = 0;
4013 spg_vblank_int = 0;
4014 spg_hblank = 0;
4015 spg_load = 0;
4016 spg_vblank = 0;
4017 spg_width = 0;
4018 spg_control = 0;
4019 vo_control = 0;
4020 vo_startx = 0;
4021 vo_starty = 0;
4022 text_control = 0;
4023 pal_ram_ctrl = 0;
4024 ta_ol_base = 0;
4025 ta_ol_limit = 0;
4026 ta_isp_base = 0;
4027 ta_isp_limit = 0;
4028 ta_next_opb = 0;
4029 ta_itp_current = 0;
4030 ta_alloc_ctrl = 0;
4031 ta_next_opb_init = 0;
4032 ta_yuv_tex_base = 0;
4033 ta_yuv_tex_ctrl = 0;
4034 ta_yuv_tex_cnt = 0;
4035 memset(fog_table, 0, sizeof(fog_table));
4036 memset(palette, 0, sizeof(palette));
4037 memset(&m_pvr_dma, 0x00, sizeof(m_pvr_dma));
4038
4039 sb_pdstap = 0;
4040 sb_pdstar = 0;
4041 sb_pdlen = 0;
4042 sb_pddir = 0;
4043 sb_pdtsel = 0;
4044 sb_pden = 0;
4045 sb_pdst = 0;
4046 sb_pdapro = 0;
4047
4048 save_item(NAME(softreset));
4049 save_item(NAME(param_base));
4050 save_item(NAME(region_base));
4051 save_item(NAME(vo_border_col));
4052 save_item(NAME(fb_r_ctrl));
4053 save_item(NAME(fb_w_ctrl));
4054 save_item(NAME(fb_w_linestride));
4055 save_item(NAME(fb_r_sof1));
4056 save_item(NAME(fb_r_sof2));
4057 save_item(NAME(fb_r_size));
4058 save_item(NAME(fb_w_sof1));
4059 save_item(NAME(fb_w_sof2));
4060 save_item(NAME(fb_x_clip));
4061 save_item(NAME(fb_y_clip));
4062 save_item(NAME(fpu_param_cfg));
4063 save_item(NAME(isp_backgnd_t));
4064 save_item(NAME(spg_hblank_int));
4065 save_item(NAME(spg_vblank_int));
4066 save_item(NAME(spg_hblank));
4067 save_item(NAME(spg_load));
4068 save_item(NAME(spg_vblank));
4069 save_item(NAME(spg_width));
4070 save_item(NAME(vo_control));
4071 save_item(NAME(vo_startx));
4072 save_item(NAME(vo_starty));
4073 save_item(NAME(text_control));
4074 save_item(NAME(pal_ram_ctrl));
4075 save_item(NAME(ta_ol_base));
4076 save_item(NAME(ta_ol_limit));
4077 save_item(NAME(ta_isp_base));
4078 save_item(NAME(ta_isp_limit));
4079 save_item(NAME(ta_next_opb));
4080 save_item(NAME(ta_itp_current));
4081 save_item(NAME(ta_alloc_ctrl));
4082 save_item(NAME(ta_next_opb_init));
4083 save_item(NAME(ta_yuv_tex_base));
4084 save_item(NAME(ta_yuv_tex_ctrl));
4085 save_item(NAME(ta_yuv_tex_cnt));
4086 save_pointer(NAME(fog_table), 0x80);
4087 save_pointer(NAME(palette), 0x400);
4088
4089 save_item(NAME(sb_pdstap));
4090 save_item(NAME(sb_pdstar));
4091 save_item(NAME(sb_pdlen));
4092 save_item(NAME(sb_pddir));
4093 save_item(NAME(sb_pdtsel));
4094 save_item(NAME(sb_pden));
4095 save_item(NAME(sb_pdst));
4096 save_item(NAME(sb_pdapro));
4097
4098 save_item(NAME(m_pvr_dma.pvr_addr));
4099 save_item(NAME(m_pvr_dma.sys_addr));
4100 save_item(NAME(m_pvr_dma.size));
4101 save_item(NAME(m_pvr_dma.sel));
4102 save_item(NAME(m_pvr_dma.dir));
4103 save_item(NAME(m_pvr_dma.flag));
4104 save_item(NAME(m_pvr_dma.start));
4105 save_item(NAME(debug_dip_status));
4106 save_pointer(NAME(tafifo_buff),32);
4107 save_item(NAME(scanline));
4108 save_item(NAME(next_y));
4109 }
4110
device_reset()4111 void powervr2_device::device_reset()
4112 {
4113 softreset = 0x00000007;
4114 vo_control = 0x00000108;
4115 vo_startx = 0x0000009d;
4116 vo_starty = 0x00150015;
4117 spg_hblank = 0x007e0345;
4118 spg_load = 0x01060359;
4119 spg_vblank = 0x01500104;
4120 spg_hblank_int = 0x031d0000;
4121 spg_vblank_int = 0x01500104;
4122
4123 tafifo_pos=0;
4124 tafifo_mask=7;
4125 tafifo_vertexwords=8;
4126 tafifo_listtype= DISPLAY_LIST_NONE;
4127 start_render_received=0;
4128 renderselect= -1;
4129 grabsel=0;
4130
4131 // vbout_timer->adjust(screen().time_until_pos((spg_vblank_int >> 16) & 0x3ff));
4132 // vbin_timer->adjust(screen().time_until_pos(spg_vblank_int & 0x3ff));
4133 hbin_timer->adjust(screen().time_until_pos(0, ((spg_hblank_int >> 16) & 0x3ff)-1));
4134
4135 scanline = 0;
4136 next_y = 0;
4137
4138 endofrender_timer_isp->adjust(attotime::never);
4139 endofrender_timer_tsp->adjust(attotime::never);
4140 endofrender_timer_video->adjust(attotime::never);
4141 yuv_timer_end->adjust(attotime::never);
4142
4143 dc_state *state = machine().driver_data<dc_state>();
4144 dc_texture_ram = state->dc_texture_ram.target();
4145 dc_framebuffer_ram = state->dc_framebuffer_ram.target();
4146 }
4147
4148 /* called by TIMER_ADD_PERIODIC, in driver sections (controlled by SPG, that's a PVR sub-device) */
pvr_scanline_timer(int vpos)4149 void powervr2_device::pvr_scanline_timer(int vpos)
4150 {
4151 int vbin_line = spg_vblank_int & 0x3ff;
4152 int vbout_line = (spg_vblank_int >> 16) & 0x3ff;
4153 uint8_t interlace_on = ((spg_control & 0x10) >> 4);
4154 dc_state *state = machine().driver_data<dc_state>();
4155
4156 vbin_line <<= interlace_on;
4157 vbout_line <<= interlace_on;
4158
4159 if(vbin_line-(1+interlace_on) == vpos)
4160 state->m_maple->maple_hw_trigger();
4161
4162 if(vbin_line == vpos)
4163 irq_cb(VBL_IN_IRQ);
4164
4165 if(vbout_line == vpos)
4166 irq_cb(VBL_OUT_IRQ);
4167 }
4168