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(&param_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(&region_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