trunk/src/mame/video/dc.c
| r23534 | r23535 | |
| 1 | | /* |
| 2 | | dc.c - Dreamcast video emulation |
| 3 | | |
| 4 | | */ |
| 5 | | |
| 6 | | #include "emu.h" |
| 7 | | #include "includes/dc.h" |
| 8 | | #include "cpu/sh4/sh4.h" |
| 9 | | #include "render.h" |
| 10 | | #include "rendutil.h" |
| 11 | | #include "video/rgbutil.h" |
| 12 | | |
| 13 | | #define DEBUG_FIFO_POLY (0) |
| 14 | | #define DEBUG_PVRTA (0) |
| 15 | | #define DEBUG_PVRTA_REGS (0) |
| 16 | | #define DEBUG_PVRDLIST (0) |
| 17 | | #define DEBUG_PALRAM (1) |
| 18 | | |
| 19 | | #define NUM_BUFFERS 4 |
| 20 | | |
| 21 | | /* PVR TA macro defines */ |
| 22 | | /* |
| 23 | | SPG_HBLANK_INT |
| 24 | | ---- --xx xxxx xxxx ---- ---- ---- ---- hblank_in_interrupt |
| 25 | | ---- ---- ---- ---- --xx ---- ---- ---- hblank_int_mode |
| 26 | | ---- ---- ---- ---- ---- --xx xxxx xxxx line_comp_val |
| 27 | | */ |
| 28 | | #define spg_hblank_in_irq ((state->pvrta_regs[SPG_HBLANK_INT] & 0x03ff0000) >> 16) |
| 29 | | #define spg_hblank_in_irq_new ((pvrta_regs[SPG_HBLANK_INT] & 0x03ff0000) >> 16) |
| 30 | | #define spg_hblank_int_mode ((state->pvrta_regs[SPG_HBLANK_INT] & 0x00003000) >> 12) |
| 31 | | #define spg_line_comp_val ((state->pvrta_regs[SPG_HBLANK_INT] & 0x000003ff) >> 0) |
| 32 | | |
| 33 | | /* |
| 34 | | SPG_VBLANK_INT |
| 35 | | ---- --xx xxxx xxxx ---- ---- ---- ---- vblank_out_interrupt_line_number |
| 36 | | ---- ---- ---- ---- ---- --xx xxxx xxxx vblank_in_interrupt_line_number |
| 37 | | */ |
| 38 | | #define spg_vblank_out_irq_line_num ((state->pvrta_regs[SPG_VBLANK_INT] & 0x03ff0000) >> 16) |
| 39 | | #define spg_vblank_in_irq_line_num ((state->pvrta_regs[SPG_VBLANK_INT] & 0x000003ff) >> 0) |
| 40 | | #define spg_vblank_out_irq_line_num_new ((pvrta_regs[SPG_VBLANK_INT] & 0x03ff0000) >> 16) |
| 41 | | #define spg_vblank_in_irq_line_num_new ((pvrta_regs[SPG_VBLANK_INT] & 0x000003ff) >> 0) |
| 42 | | |
| 43 | | |
| 44 | | /* |
| 45 | | VO_BORDER_COL |
| 46 | | ---- ---x ---- ---- ---- ---- ---- ---- Chroma ;suchie3 sets 0xff there, maybe it's 8 bits too? |
| 47 | | ---- ---- xxxx xxxx ---- ---- ---- ---- Red |
| 48 | | ---- ---- ---- ---- xxxx xxxx ---- ---- Green |
| 49 | | ---- ---- ---- ---- ---- ---- xxxx xxxx Blue |
| 50 | | */ |
| 51 | | #define vo_border_K ((pvrta_regs[VO_BORDER_COL] & 0x01000000) >> 24) |
| 52 | | #define vo_border_R ((pvrta_regs[VO_BORDER_COL] & 0x00ff0000) >> 16) |
| 53 | | #define vo_border_G ((pvrta_regs[VO_BORDER_COL] & 0x0000ff00) >> 8) |
| 54 | | #define vo_border_B ((pvrta_regs[VO_BORDER_COL] & 0x000000ff) >> 0) |
| 55 | | |
| 56 | | /* |
| 57 | | SPG_HBLANK |
| 58 | | ---- ---- --xx xxxx xxxx ---- ---- ---- hbend |
| 59 | | ---- ---- ---- ---- ---- --xx xxxx xxxx hbstart |
| 60 | | */ |
| 61 | | #define spg_hbend ((state->pvrta_regs[SPG_HBLANK] & 0x03ff0000) >> 16) |
| 62 | | #define spg_hbstart ((state->pvrta_regs[SPG_HBLANK] & 0x000003ff) >> 0) |
| 63 | | |
| 64 | | |
| 65 | | /* |
| 66 | | SPG_LOAD |
| 67 | | ---- ---- --xx xxxx xxxx ---- ---- ---- vcount |
| 68 | | ---- ---- ---- ---- ---- --xx xxxx xxxx hcount |
| 69 | | */ |
| 70 | | #define spg_vcount ((state->pvrta_regs[SPG_LOAD] & 0x03ff0000) >> 16) |
| 71 | | #define spg_hcount ((state->pvrta_regs[SPG_LOAD] & 0x000003ff) >> 0) |
| 72 | | |
| 73 | | /* |
| 74 | | SPG_VBLANK |
| 75 | | ---- ---- --xx xxxx xxxx ---- ---- ---- vbend |
| 76 | | ---- ---- ---- ---- ---- --xx xxxx xxxx vbstart |
| 77 | | */ |
| 78 | | #define spg_vbend ((state->pvrta_regs[SPG_VBLANK] & 0x03ff0000) >> 16) |
| 79 | | #define spg_vbstart ((state->pvrta_regs[SPG_VBLANK] & 0x000003ff) >> 0) |
| 80 | | |
| 81 | | |
| 82 | | /* |
| 83 | | VO_CONTROL |
| 84 | | ---- ---- --xx xxxx ---- ---- ---- ---- pclk_delay |
| 85 | | ---- ---- ---- ---- ---- ---x ---- ---- pixel_double ;used in test mode |
| 86 | | ---- ---- ---- ---- ---- ---- xxxx ---- field_mode |
| 87 | | ---- ---- ---- ---- ---- ---- ---- x--- blank_video |
| 88 | | ---- ---- ---- ---- ---- ---- ---- -x-- blank_pol |
| 89 | | ---- ---- ---- ---- ---- ---- ---- --x- vsync_pol |
| 90 | | ---- ---- ---- ---- ---- ---- ---- ---x hsync_pol |
| 91 | | */ |
| 92 | | #define spg_pclk_delay ((state->pvrta_regs[VO_CONTROL] & 0x003f0000) >> 16) |
| 93 | | #define spg_pixel_double ((state->pvrta_regs[VO_CONTROL] & 0x00000100) >> 8) |
| 94 | | #define spg_field_mode ((state->pvrta_regs[VO_CONTROL] & 0x000000f0) >> 4) |
| 95 | | #define spg_blank_video ((pvrta_regs[VO_CONTROL] & 0x00000008) >> 3) |
| 96 | | #define spg_blank_pol ((state->pvrta_regs[VO_CONTROL] & 0x00000004) >> 2) |
| 97 | | #define spg_vsync_pol ((state->pvrta_regs[VO_CONTROL] & 0x00000002) >> 1) |
| 98 | | #define spg_hsync_pol ((state->pvrta_regs[VO_CONTROL] & 0x00000001) >> 0) |
| 99 | | |
| 100 | | /* |
| 101 | | VO_STARTX |
| 102 | | ---- ---- ---- ---- ---- ---x xxxx xxxx horzontal start position |
| 103 | | */ |
| 104 | | #define vo_horz_start_pos ((state->pvrta_regs[VO_STARTX] & 0x000003ff) >> 0) |
| 105 | | |
| 106 | | /* |
| 107 | | VO_STARTY |
| 108 | | ---- ---x xxxx xxxx ---- ---- ---- ---- vertical start position on field 2 |
| 109 | | ---- ---- ---- ---- ---- ---x xxxx xxxx vertical start position on field 1 |
| 110 | | */ |
| 111 | | |
| 112 | | #define vo_vert_start_pos_f2 ((state->pvrta_regs[VO_STARTY] & 0x03ff0000) >> 16) |
| 113 | | #define vo_vert_start_pos_f1 ((state->pvrta_regs[VO_STARTY] & 0x000003ff) >> 0) |
| 114 | | |
| 115 | | /* |
| 116 | | SPG_STATUS |
| 117 | | ---- ---- ---- ---- --x- ---- ---- ---- vsync |
| 118 | | ---- ---- ---- ---- ---x ---- ---- ---- hsync |
| 119 | | ---- ---- ---- ---- ---- x--- ---- ---- blank |
| 120 | | ---- ---- ---- ---- ---- -x-- ---- ---- field number |
| 121 | | ---- ---- ---- ---- ---- --xx xxxx xxxx state->scanline |
| 122 | | */ |
| 123 | | |
| 124 | | static const int 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}; |
| 125 | | static const int 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}; |
| 126 | | static const int 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}; |
| 127 | | static int pvr_parameterconfig[128]; |
| 128 | | static UINT32 dilated0[15][1024]; |
| 129 | | static UINT32 dilated1[15][1024]; |
| 130 | | static int dilatechose[64]; |
| 131 | | static float wbuffer[480][640]; |
| 132 | | static void pvr_accumulationbuffer_to_framebuffer(address_space &space, int x,int y); |
| 133 | | |
| 134 | | // the real accumulation buffer is a 32x32x8bpp buffer into which tiles get rendered before they get copied to the framebuffer |
| 135 | | // our implementation is not currently tile based, and thus the accumulation buffer is screen sized |
| 136 | | static bitmap_rgb32 *fake_accumulationbuffer_bitmap; |
| 137 | | static void render_to_accumulation_buffer(running_machine &machine,bitmap_rgb32 &bitmap,const rectangle &cliprect); |
| 138 | | |
| 139 | | struct texinfo { |
| 140 | | UINT32 address, vqbase; |
| 141 | | int textured, sizex, sizey, stride, sizes, pf, palette, mode, mipmapped, blend_mode, filter_mode, flip_u, flip_v; |
| 142 | | |
| 143 | | UINT32 (*r)(running_machine &machine, struct texinfo *t, float x, float y); |
| 144 | | UINT32 (*blend)(UINT32 s, UINT32 d); |
| 145 | | int palbase, cd; |
| 146 | | }; |
| 147 | | |
| 148 | | typedef struct |
| 149 | | { |
| 150 | | float x, y, w, u, v; |
| 151 | | } vert; |
| 152 | | |
| 153 | | struct strip |
| 154 | | { |
| 155 | | int svert, evert; |
| 156 | | texinfo ti; |
| 157 | | }; |
| 158 | | |
| 159 | | struct receiveddata { |
| 160 | | vert verts[65536]; |
| 161 | | strip strips[65536]; |
| 162 | | |
| 163 | | int verts_size, strips_size; |
| 164 | | UINT32 ispbase; |
| 165 | | UINT32 fbwsof1; |
| 166 | | UINT32 fbwsof2; |
| 167 | | int busy; |
| 168 | | int valid; |
| 169 | | }; |
| 170 | | |
| 171 | | struct pvrta_state { |
| 172 | | int tafifo_pos, tafifo_mask, tafifo_vertexwords, tafifo_listtype; |
| 173 | | int start_render_received; |
| 174 | | int renderselect; |
| 175 | | int listtype_used; |
| 176 | | int alloc_ctrl_OPB_Mode, alloc_ctrl_PT_OPB, alloc_ctrl_TM_OPB, alloc_ctrl_T_OPB, alloc_ctrl_OM_OPB, alloc_ctrl_O_OPB; |
| 177 | | receiveddata grab[NUM_BUFFERS]; |
| 178 | | int grabsel; |
| 179 | | int grabsellast; |
| 180 | | UINT32 paracontrol,paratype,endofstrip,listtype,global_paratype,parameterconfig; |
| 181 | | UINT32 groupcontrol,groupen,striplen,userclip; |
| 182 | | UINT32 objcontrol,shadow,volume,coltype,texture,offfset,gouraud,uv16bit; |
| 183 | | UINT32 texturesizes,textureaddress,scanorder,pixelformat; |
| 184 | | UINT32 blend_mode, srcselect,dstselect,fogcontrol,colorclamp, use_alpha; |
| 185 | | UINT32 ignoretexalpha,flipuv,clampuv,filtermode,sstexture,mmdadjust,tsinstruction; |
| 186 | | UINT32 depthcomparemode,cullingmode,zwritedisable,cachebypass,dcalcctrl,volumeinstruction,mipmapped,vqcompressed,strideselect,paletteselector; |
| 187 | | }; |
| 188 | | |
| 189 | | enum |
| 190 | | { |
| 191 | | TEX_FILTER_NEAREST = 0, |
| 192 | | TEX_FILTER_BILINEAR, |
| 193 | | TEX_FILTER_TRILINEAR_A, |
| 194 | | TEX_FILTER_TRILINEAR_B |
| 195 | | }; |
| 196 | | |
| 197 | | static pvrta_state state_ta; |
| 198 | | |
| 199 | | // Perform a standard bilinear filter across four pixels |
| 200 | | INLINE INT32 clamp(INT32 in, INT32 min, INT32 max) |
| 201 | | { |
| 202 | | if(in < min) return min; |
| 203 | | if(in > max) return max; |
| 204 | | return in; |
| 205 | | } |
| 206 | | |
| 207 | | INLINE UINT32 bilinear_filter(UINT32 c0, UINT32 c1, UINT32 c2, UINT32 c3, float u, float v) |
| 208 | | { |
| 209 | | UINT32 ui = (u * 256.0); |
| 210 | | UINT32 vi = (v * 256.0); |
| 211 | | return rgba_bilinear_filter(c0, c1, c3, c2, ui, vi); |
| 212 | | } |
| 213 | | |
| 214 | | // Multiply with alpha value in bits 31-24 |
| 215 | | INLINE UINT32 bla(UINT32 c, UINT32 a) |
| 216 | | { |
| 217 | | a = a >> 24; |
| 218 | | return ((((c & 0xff00ff)*a) & 0xff00ff00) >> 8) | ((((c >> 8) & 0xff00ff)*a) & 0xff00ff00); |
| 219 | | } |
| 220 | | |
| 221 | | // Multiply with 1-alpha value in bits 31-24 |
| 222 | | INLINE UINT32 blia(UINT32 c, UINT32 a) |
| 223 | | { |
| 224 | | a = 0x100 - (a >> 24); |
| 225 | | return ((((c & 0xff00ff)*a) & 0xff00ff00) >> 8) | ((((c >> 8) & 0xff00ff)*a) & 0xff00ff00); |
| 226 | | } |
| 227 | | |
| 228 | | // Per-component multiply with color value |
| 229 | | INLINE UINT32 blc(UINT32 c1, UINT32 c2) |
| 230 | | { |
| 231 | | UINT32 cr = |
| 232 | | (((c1 & 0x000000ff)*(c2 & 0x000000ff) & 0x0000ff00) >> 8) | |
| 233 | | (((c1 & 0x0000ff00)*(c2 & 0x0000ff00) & 0x00ff0000) >> 8); |
| 234 | | c1 >>= 16; |
| 235 | | c2 >>= 16; |
| 236 | | cr |= |
| 237 | | (((c1 & 0x000000ff)*(c2 & 0x000000ff) & 0x0000ff00) << 8) | |
| 238 | | (((c1 & 0x0000ff00)*(c2 & 0x0000ff00) & 0x00ff0000) << 8); |
| 239 | | return cr; |
| 240 | | } |
| 241 | | |
| 242 | | // Per-component multiply with 1-color value |
| 243 | | INLINE UINT32 blic(UINT32 c1, UINT32 c2) |
| 244 | | { |
| 245 | | UINT32 cr = |
| 246 | | (((c1 & 0x000000ff)*(0x00100-(c2 & 0x000000ff)) & 0x0000ff00) >> 8) | |
| 247 | | (((c1 & 0x0000ff00)*(0x10000-(c2 & 0x0000ff00)) & 0x00ff0000) >> 8); |
| 248 | | c1 >>= 16; |
| 249 | | c2 >>= 16; |
| 250 | | cr |= |
| 251 | | (((c1 & 0x000000ff)*(0x00100-(c2 & 0x000000ff)) & 0x0000ff00) << 8) | |
| 252 | | (((c1 & 0x0000ff00)*(0x10000-(c2 & 0x0000ff00)) & 0x00ff0000) << 8); |
| 253 | | return cr; |
| 254 | | } |
| 255 | | |
| 256 | | // Add two colors with saturation |
| 257 | | INLINE UINT32 bls(UINT32 c1, UINT32 c2) |
| 258 | | { |
| 259 | | UINT32 cr1, cr2; |
| 260 | | cr1 = (c1 & 0x00ff00ff) + (c2 & 0x00ff00ff); |
| 261 | | if(cr1 & 0x0000ff00) |
| 262 | | cr1 = (cr1 & 0xffff00ff) | 0x000000ff; |
| 263 | | if(cr1 & 0xff000000) |
| 264 | | cr1 = (cr1 & 0x00ffffff) | 0x00ff0000; |
| 265 | | |
| 266 | | cr2 = ((c1 >> 8) & 0x00ff00ff) + ((c2 >> 8) & 0x00ff00ff); |
| 267 | | if(cr2 & 0x0000ff00) |
| 268 | | cr2 = (cr2 & 0xffff00ff) | 0x000000ff; |
| 269 | | if(cr2 & 0xff000000) |
| 270 | | cr2 = (cr2 & 0x00ffffff) | 0x00ff0000; |
| 271 | | return cr1|(cr2 << 8); |
| 272 | | } |
| 273 | | |
| 274 | | // All 64 blending modes, 3 top bits are source mode, 3 bottom bits are destination mode |
| 275 | | INLINE UINT32 bl00(UINT32 s, UINT32 d) { return 0; } |
| 276 | | INLINE UINT32 bl01(UINT32 s, UINT32 d) { return d; } |
| 277 | | INLINE UINT32 bl02(UINT32 s, UINT32 d) { return blc(d, s); } |
| 278 | | INLINE UINT32 bl03(UINT32 s, UINT32 d) { return blic(d, s); } |
| 279 | | INLINE UINT32 bl04(UINT32 s, UINT32 d) { return bla(d, s); } |
| 280 | | INLINE UINT32 bl05(UINT32 s, UINT32 d) { return blia(d, s); } |
| 281 | | INLINE UINT32 bl06(UINT32 s, UINT32 d) { return bla(d, d); } |
| 282 | | INLINE UINT32 bl07(UINT32 s, UINT32 d) { return blia(d, d); } |
| 283 | | INLINE UINT32 bl10(UINT32 s, UINT32 d) { return s; } |
| 284 | | INLINE UINT32 bl11(UINT32 s, UINT32 d) { return bls(s, d); } |
| 285 | | INLINE UINT32 bl12(UINT32 s, UINT32 d) { return bls(s, blc(s, d)); } |
| 286 | | INLINE UINT32 bl13(UINT32 s, UINT32 d) { return bls(s, blic(s, d)); } |
| 287 | | INLINE UINT32 bl14(UINT32 s, UINT32 d) { return bls(s, bla(d, s)); } |
| 288 | | INLINE UINT32 bl15(UINT32 s, UINT32 d) { return bls(s, blia(d, s)); } |
| 289 | | INLINE UINT32 bl16(UINT32 s, UINT32 d) { return bls(s, bla(d, d)); } |
| 290 | | INLINE UINT32 bl17(UINT32 s, UINT32 d) { return bls(s, blia(d, d)); } |
| 291 | | INLINE UINT32 bl20(UINT32 s, UINT32 d) { return blc(d, s); } |
| 292 | | INLINE UINT32 bl21(UINT32 s, UINT32 d) { return bls(blc(d, s), d); } |
| 293 | | INLINE UINT32 bl22(UINT32 s, UINT32 d) { return bls(blc(d, s), blc(s, d)); } |
| 294 | | INLINE UINT32 bl23(UINT32 s, UINT32 d) { return bls(blc(d, s), blic(s, d)); } |
| 295 | | INLINE UINT32 bl24(UINT32 s, UINT32 d) { return bls(blc(d, s), bla(d, s)); } |
| 296 | | INLINE UINT32 bl25(UINT32 s, UINT32 d) { return bls(blc(d, s), blia(d, s)); } |
| 297 | | INLINE UINT32 bl26(UINT32 s, UINT32 d) { return bls(blc(d, s), bla(d, d)); } |
| 298 | | INLINE UINT32 bl27(UINT32 s, UINT32 d) { return bls(blc(d, s), blia(d, d)); } |
| 299 | | INLINE UINT32 bl30(UINT32 s, UINT32 d) { return blic(d, s); } |
| 300 | | INLINE UINT32 bl31(UINT32 s, UINT32 d) { return bls(blic(d, s), d); } |
| 301 | | INLINE UINT32 bl32(UINT32 s, UINT32 d) { return bls(blic(d, s), blc(s, d)); } |
| 302 | | INLINE UINT32 bl33(UINT32 s, UINT32 d) { return bls(blic(d, s), blic(s, d)); } |
| 303 | | INLINE UINT32 bl34(UINT32 s, UINT32 d) { return bls(blic(d, s), bla(d, s)); } |
| 304 | | INLINE UINT32 bl35(UINT32 s, UINT32 d) { return bls(blic(d, s), blia(d, s)); } |
| 305 | | INLINE UINT32 bl36(UINT32 s, UINT32 d) { return bls(blic(d, s), bla(d, d)); } |
| 306 | | INLINE UINT32 bl37(UINT32 s, UINT32 d) { return bls(blic(d, s), blia(d, d)); } |
| 307 | | INLINE UINT32 bl40(UINT32 s, UINT32 d) { return bla(s, s); } |
| 308 | | INLINE UINT32 bl41(UINT32 s, UINT32 d) { return bls(bla(s, s), d); } |
| 309 | | INLINE UINT32 bl42(UINT32 s, UINT32 d) { return bls(bla(s, s), blc(s, d)); } |
| 310 | | INLINE UINT32 bl43(UINT32 s, UINT32 d) { return bls(bla(s, s), blic(s, d)); } |
| 311 | | INLINE UINT32 bl44(UINT32 s, UINT32 d) { return bls(bla(s, s), bla(d, s)); } |
| 312 | | INLINE UINT32 bl45(UINT32 s, UINT32 d) { return bls(bla(s, s), blia(d, s)); } |
| 313 | | INLINE UINT32 bl46(UINT32 s, UINT32 d) { return bls(bla(s, s), bla(d, d)); } |
| 314 | | INLINE UINT32 bl47(UINT32 s, UINT32 d) { return bls(bla(s, s), blia(d, d)); } |
| 315 | | INLINE UINT32 bl50(UINT32 s, UINT32 d) { return blia(s, s); } |
| 316 | | INLINE UINT32 bl51(UINT32 s, UINT32 d) { return bls(blia(s, s), d); } |
| 317 | | INLINE UINT32 bl52(UINT32 s, UINT32 d) { return bls(blia(s, s), blc(s, d)); } |
| 318 | | INLINE UINT32 bl53(UINT32 s, UINT32 d) { return bls(blia(s, s), blic(s, d)); } |
| 319 | | INLINE UINT32 bl54(UINT32 s, UINT32 d) { return bls(blia(s, s), bla(d, s)); } |
| 320 | | INLINE UINT32 bl55(UINT32 s, UINT32 d) { return bls(blia(s, s), blia(d, s)); } |
| 321 | | INLINE UINT32 bl56(UINT32 s, UINT32 d) { return bls(blia(s, s), bla(d, d)); } |
| 322 | | INLINE UINT32 bl57(UINT32 s, UINT32 d) { return bls(blia(s, s), blia(d, d)); } |
| 323 | | INLINE UINT32 bl60(UINT32 s, UINT32 d) { return bla(s, d); } |
| 324 | | INLINE UINT32 bl61(UINT32 s, UINT32 d) { return bls(bla(s, d), d); } |
| 325 | | INLINE UINT32 bl62(UINT32 s, UINT32 d) { return bls(bla(s, d), blc(s, d)); } |
| 326 | | INLINE UINT32 bl63(UINT32 s, UINT32 d) { return bls(bla(s, d), blic(s, d)); } |
| 327 | | INLINE UINT32 bl64(UINT32 s, UINT32 d) { return bls(bla(s, d), bla(d, s)); } |
| 328 | | INLINE UINT32 bl65(UINT32 s, UINT32 d) { return bls(bla(s, d), blia(d, s)); } |
| 329 | | INLINE UINT32 bl66(UINT32 s, UINT32 d) { return bls(bla(s, d), bla(d, d)); } |
| 330 | | INLINE UINT32 bl67(UINT32 s, UINT32 d) { return bls(bla(s, d), blia(d, d)); } |
| 331 | | INLINE UINT32 bl70(UINT32 s, UINT32 d) { return blia(s, d); } |
| 332 | | INLINE UINT32 bl71(UINT32 s, UINT32 d) { return bls(blia(s, d), d); } |
| 333 | | INLINE UINT32 bl72(UINT32 s, UINT32 d) { return bls(blia(s, d), blc(s, d)); } |
| 334 | | INLINE UINT32 bl73(UINT32 s, UINT32 d) { return bls(blia(s, d), blic(s, d)); } |
| 335 | | INLINE UINT32 bl74(UINT32 s, UINT32 d) { return bls(blia(s, d), bla(d, s)); } |
| 336 | | INLINE UINT32 bl75(UINT32 s, UINT32 d) { return bls(blia(s, d), blia(d, s)); } |
| 337 | | INLINE UINT32 bl76(UINT32 s, UINT32 d) { return bls(blia(s, d), bla(d, d)); } |
| 338 | | INLINE UINT32 bl77(UINT32 s, UINT32 d) { return bls(blia(s, d), blia(d, d)); } |
| 339 | | |
| 340 | | static UINT32 (*const blend_functions[64])(UINT32 s, UINT32 d) = { |
| 341 | | bl00, bl01, bl02, bl03, bl04, bl05, bl06, bl07, |
| 342 | | bl10, bl11, bl12, bl13, bl14, bl15, bl16, bl17, |
| 343 | | bl20, bl21, bl22, bl23, bl24, bl25, bl26, bl27, |
| 344 | | bl30, bl31, bl32, bl33, bl34, bl35, bl36, bl37, |
| 345 | | bl40, bl41, bl42, bl43, bl44, bl45, bl46, bl47, |
| 346 | | bl50, bl51, bl52, bl53, bl54, bl55, bl56, bl57, |
| 347 | | bl60, bl61, bl62, bl63, bl64, bl65, bl66, bl67, |
| 348 | | bl70, bl71, bl72, bl73, bl74, bl75, bl76, bl77, |
| 349 | | }; |
| 350 | | |
| 351 | | INLINE UINT32 cv_1555(UINT16 c) |
| 352 | | { |
| 353 | | return |
| 354 | | (c & 0x8000 ? 0xff000000 : 0) | |
| 355 | | ((c << 9) & 0x00f80000) | ((c << 4) & 0x00070000) | |
| 356 | | ((c << 6) & 0x0000f800) | ((c << 1) & 0x00000700) | |
| 357 | | ((c << 3) & 0x000000f8) | ((c >> 2) & 0x00000007); |
| 358 | | } |
| 359 | | |
| 360 | | INLINE UINT32 cv_1555z(UINT16 c) |
| 361 | | { |
| 362 | | return |
| 363 | | (c & 0x8000 ? 0xff000000 : 0) | |
| 364 | | ((c << 9) & 0x00f80000) | |
| 365 | | ((c << 6) & 0x0000f800) | |
| 366 | | ((c << 3) & 0x000000f8); |
| 367 | | } |
| 368 | | |
| 369 | | INLINE UINT32 cv_565(UINT16 c) |
| 370 | | { |
| 371 | | return |
| 372 | | 0xff000000 | |
| 373 | | ((c << 8) & 0x00f80000) | ((c << 3) & 0x00070000) | |
| 374 | | ((c << 5) & 0x0000fc00) | ((c >> 1) & 0x00000300) | |
| 375 | | ((c << 3) & 0x000000f8) | ((c >> 2) & 0x00000007); |
| 376 | | } |
| 377 | | |
| 378 | | INLINE UINT32 cv_565z(UINT16 c) |
| 379 | | { |
| 380 | | return |
| 381 | | 0xff000000 | |
| 382 | | ((c << 8) & 0x00f80000) | |
| 383 | | ((c << 5) & 0x0000fc00) | |
| 384 | | ((c << 3) & 0x000000f8); |
| 385 | | } |
| 386 | | |
| 387 | | INLINE UINT32 cv_4444(UINT16 c) |
| 388 | | { |
| 389 | | return |
| 390 | | ((c << 16) & 0xf0000000) | ((c << 12) & 0x0f000000) | |
| 391 | | ((c << 12) & 0x00f00000) | ((c << 8) & 0x000f0000) | |
| 392 | | ((c << 8) & 0x0000f000) | ((c << 4) & 0x00000f00) | |
| 393 | | ((c << 4) & 0x000000f0) | ((c ) & 0x0000000f); |
| 394 | | } |
| 395 | | |
| 396 | | INLINE UINT32 cv_4444z(UINT16 c) |
| 397 | | { |
| 398 | | return |
| 399 | | ((c << 16) & 0xf0000000) | |
| 400 | | ((c << 12) & 0x00f00000) | |
| 401 | | ((c << 8) & 0x0000f000) | |
| 402 | | ((c << 4) & 0x000000f0); |
| 403 | | } |
| 404 | | |
| 405 | | INLINE UINT32 cv_yuv(UINT16 c1, UINT16 c2, int x) |
| 406 | | { |
| 407 | | int u = 11*((c1 & 0xff) - 128); |
| 408 | | int v = 11*((c2 & 0xff) - 128); |
| 409 | | int y = (x & 1 ? c2 : c1) >> 8; |
| 410 | | int r = y + v/8; |
| 411 | | int g = y - u/32 - v/16; |
| 412 | | int b = y + (3*u)/16; |
| 413 | | r = r < 0 ? 0 : r > 255 ? 255 : r; |
| 414 | | g = g < 0 ? 0 : g > 255 ? 255 : g; |
| 415 | | b = b < 0 ? 0 : b > 255 ? 255 : b; |
| 416 | | return 0xff000000 | (r << 16) | (g << 8) | b; |
| 417 | | } |
| 418 | | |
| 419 | | |
| 420 | | INLINE UINT32 tex_r_yuv_n(running_machine &machine, texinfo *t, float x, float y) |
| 421 | | { |
| 422 | | dc_state *state = machine.driver_data<dc_state>(); |
| 423 | | int xt = ((int)x) & (t->sizex-1); |
| 424 | | int yt = ((int)y) & (t->sizey-1); |
| 425 | | int addrp = t->address + (t->stride*yt + (xt & ~1))*2; |
| 426 | | UINT16 c1 = *(UINT16 *)((reinterpret_cast<UINT8 *>(state->dc_texture_ram.target())) + WORD_XOR_LE(addrp)); |
| 427 | | UINT16 c2 = *(UINT16 *)((reinterpret_cast<UINT8 *>(state->dc_texture_ram.target())) + WORD_XOR_LE(addrp+2)); |
| 428 | | return cv_yuv(c1, c2, xt); |
| 429 | | } |
| 430 | | |
| 431 | | INLINE UINT32 tex_r_1555_n(running_machine &machine, texinfo *t, float x, float y) |
| 432 | | { |
| 433 | | dc_state *state = machine.driver_data<dc_state>(); |
| 434 | | int xt = ((int)x) & (t->sizex-1); |
| 435 | | int yt = ((int)y) & (t->sizey-1); |
| 436 | | int addrp = t->address + (t->stride*yt + xt)*2; |
| 437 | | return cv_1555z(*(UINT16 *)((reinterpret_cast<UINT8 *>(state->dc_texture_ram.target())) + WORD_XOR_LE(addrp))); |
| 438 | | } |
| 439 | | |
| 440 | | INLINE UINT32 tex_r_1555_tw(running_machine &machine, texinfo *t, float x, float y) |
| 441 | | { |
| 442 | | dc_state *state = machine.driver_data<dc_state>(); |
| 443 | | int xt = ((int)x) & (t->sizex-1); |
| 444 | | int yt = ((int)y) & (t->sizey-1); |
| 445 | | int addrp = t->address + (dilated1[t->cd][xt] + dilated0[t->cd][yt])*2; |
| 446 | | return cv_1555(*(UINT16 *)((reinterpret_cast<UINT8 *>(state->dc_texture_ram.target())) + WORD_XOR_LE(addrp))); |
| 447 | | } |
| 448 | | |
| 449 | | INLINE UINT32 tex_r_1555_vq(running_machine &machine, texinfo *t, float x, float y) |
| 450 | | { |
| 451 | | dc_state *state = machine.driver_data<dc_state>(); |
| 452 | | int xt = ((int)x) & (t->sizex-1); |
| 453 | | int yt = ((int)y) & (t->sizey-1); |
| 454 | | int idx = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 455 | | int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2; |
| 456 | | return cv_1555(*(UINT16 *)((reinterpret_cast<UINT8 *>(state->dc_texture_ram.target())) + WORD_XOR_LE(addrp))); |
| 457 | | } |
| 458 | | |
| 459 | | INLINE UINT32 tex_r_565_n(running_machine &machine, texinfo *t, float x, float y) |
| 460 | | { |
| 461 | | dc_state *state = machine.driver_data<dc_state>(); |
| 462 | | int xt = ((int)x) & (t->sizex-1); |
| 463 | | int yt = ((int)y) & (t->sizey-1); |
| 464 | | int addrp = t->address + (t->stride*yt + xt)*2; |
| 465 | | return cv_565z(*(UINT16 *)((reinterpret_cast<UINT8 *>(state->dc_texture_ram.target())) + WORD_XOR_LE(addrp))); |
| 466 | | } |
| 467 | | |
| 468 | | INLINE UINT32 tex_r_565_tw(running_machine &machine, texinfo *t, float x, float y) |
| 469 | | { |
| 470 | | dc_state *state = machine.driver_data<dc_state>(); |
| 471 | | int xt = ((int)x) & (t->sizex-1); |
| 472 | | int yt = ((int)y) & (t->sizey-1); |
| 473 | | int addrp = t->address + (dilated1[t->cd][xt] + dilated0[t->cd][yt])*2; |
| 474 | | return cv_565(*(UINT16 *)((reinterpret_cast<UINT8 *>(state->dc_texture_ram.target())) + WORD_XOR_LE(addrp))); |
| 475 | | } |
| 476 | | |
| 477 | | INLINE UINT32 tex_r_565_vq(running_machine &machine, texinfo *t, float x, float y) |
| 478 | | { |
| 479 | | dc_state *state = machine.driver_data<dc_state>(); |
| 480 | | int xt = ((int)x) & (t->sizex-1); |
| 481 | | int yt = ((int)y) & (t->sizey-1); |
| 482 | | int idx = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 483 | | int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2; |
| 484 | | return cv_565(*(UINT16 *)((reinterpret_cast<UINT8 *>(state->dc_texture_ram.target())) + WORD_XOR_LE(addrp))); |
| 485 | | } |
| 486 | | |
| 487 | | INLINE UINT32 tex_r_4444_n(running_machine &machine, texinfo *t, float x, float y) |
| 488 | | { |
| 489 | | dc_state *state = machine.driver_data<dc_state>(); |
| 490 | | int xt = ((int)x) & (t->sizex-1); |
| 491 | | int yt = ((int)y) & (t->sizey-1); |
| 492 | | int addrp = t->address + (t->stride*yt + xt)*2; |
| 493 | | return cv_4444z(*(UINT16 *)((reinterpret_cast<UINT8 *>(state->dc_texture_ram.target())) + WORD_XOR_LE(addrp))); |
| 494 | | } |
| 495 | | |
| 496 | | INLINE UINT32 tex_r_4444_tw(running_machine &machine, texinfo *t, float x, float y) |
| 497 | | { |
| 498 | | dc_state *state = machine.driver_data<dc_state>(); |
| 499 | | int xt = ((int)x) & (t->sizex-1); |
| 500 | | int yt = ((int)y) & (t->sizey-1); |
| 501 | | int addrp = t->address + (dilated1[t->cd][xt] + dilated0[t->cd][yt])*2; |
| 502 | | return cv_4444(*(UINT16 *)((reinterpret_cast<UINT8 *>(state->dc_texture_ram.target())) + WORD_XOR_LE(addrp))); |
| 503 | | } |
| 504 | | |
| 505 | | INLINE UINT32 tex_r_4444_vq(running_machine &machine, texinfo *t, float x, float y) |
| 506 | | { |
| 507 | | dc_state *state = machine.driver_data<dc_state>(); |
| 508 | | int xt = ((int)x) & (t->sizex-1); |
| 509 | | int yt = ((int)y) & (t->sizey-1); |
| 510 | | int idx = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 511 | | int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2; |
| 512 | | return cv_4444(*(UINT16 *)((reinterpret_cast<UINT8 *>(state->dc_texture_ram.target())) + WORD_XOR_LE(addrp))); |
| 513 | | } |
| 514 | | |
| 515 | | INLINE UINT32 tex_r_p4_1555_tw(running_machine &machine, texinfo *t, float x, float y) |
| 516 | | { |
| 517 | | dc_state *state = machine.driver_data<dc_state>(); |
| 518 | | int xt = ((int)x) & (t->sizex-1); |
| 519 | | int yt = ((int)y) & (t->sizey-1); |
| 520 | | int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 521 | | int addrp = t->address + (off >> 1); |
| 522 | | int c = ((reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; |
| 523 | | return cv_1555(state->pvrta_regs[t->palbase + c]); |
| 524 | | } |
| 525 | | |
| 526 | | INLINE UINT32 tex_r_p4_1555_vq(running_machine &machine, texinfo *t, float x, float y) |
| 527 | | { |
| 528 | | dc_state *state = machine.driver_data<dc_state>(); |
| 529 | | int xt = ((int)x) & (t->sizex-1); |
| 530 | | int yt = ((int)y) & (t->sizey-1); |
| 531 | | int idx = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 532 | | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 533 | | int c = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)] & 0xf; |
| 534 | | return cv_1555(state->pvrta_regs[t->palbase + c]); |
| 535 | | } |
| 536 | | |
| 537 | | INLINE UINT32 tex_r_p4_565_tw(running_machine &machine, texinfo *t, float x, float y) |
| 538 | | { |
| 539 | | dc_state *state = machine.driver_data<dc_state>(); |
| 540 | | int xt = ((int)x) & (t->sizex-1); |
| 541 | | int yt = ((int)y) & (t->sizey-1); |
| 542 | | int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 543 | | int addrp = t->address + (off >> 1); |
| 544 | | int c = ((reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; |
| 545 | | return cv_565(state->pvrta_regs[t->palbase + c]); |
| 546 | | } |
| 547 | | |
| 548 | | INLINE UINT32 tex_r_p4_565_vq(running_machine &machine, texinfo *t, float x, float y) |
| 549 | | { |
| 550 | | dc_state *state = machine.driver_data<dc_state>(); |
| 551 | | int xt = ((int)x) & (t->sizex-1); |
| 552 | | int yt = ((int)y) & (t->sizey-1); |
| 553 | | int idx = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 554 | | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 555 | | int c = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)] & 0xf; |
| 556 | | return cv_565(state->pvrta_regs[t->palbase + c]); |
| 557 | | } |
| 558 | | |
| 559 | | INLINE UINT32 tex_r_p4_4444_tw(running_machine &machine, texinfo *t, float x, float y) |
| 560 | | { |
| 561 | | dc_state *state = machine.driver_data<dc_state>(); |
| 562 | | int xt = ((int)x) & (t->sizex-1); |
| 563 | | int yt = ((int)y) & (t->sizey-1); |
| 564 | | int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 565 | | int addrp = t->address + (off >> 1); |
| 566 | | int c = ((reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; |
| 567 | | return cv_4444(state->pvrta_regs[t->palbase + c]); |
| 568 | | } |
| 569 | | |
| 570 | | INLINE UINT32 tex_r_p4_4444_vq(running_machine &machine, texinfo *t, float x, float y) |
| 571 | | { |
| 572 | | dc_state *state = machine.driver_data<dc_state>(); |
| 573 | | int xt = ((int)x) & (t->sizex-1); |
| 574 | | int yt = ((int)y) & (t->sizey-1); |
| 575 | | int idx = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 576 | | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 577 | | int c = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)] & 0xf; |
| 578 | | return cv_4444(state->pvrta_regs[t->palbase + c]); |
| 579 | | } |
| 580 | | |
| 581 | | INLINE UINT32 tex_r_p4_8888_tw(running_machine &machine, texinfo *t, float x, float y) |
| 582 | | { |
| 583 | | dc_state *state = machine.driver_data<dc_state>(); |
| 584 | | int xt = ((int)x) & (t->sizex-1); |
| 585 | | int yt = ((int)y) & (t->sizey-1); |
| 586 | | int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 587 | | int addrp = t->address + (off >> 1); |
| 588 | | int c = ((reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; |
| 589 | | return state->pvrta_regs[t->palbase + c]; |
| 590 | | } |
| 591 | | |
| 592 | | INLINE UINT32 tex_r_p4_8888_vq(running_machine &machine, texinfo *t, float x, float y) |
| 593 | | { |
| 594 | | dc_state *state = machine.driver_data<dc_state>(); |
| 595 | | int xt = ((int)x) & (t->sizex-1); |
| 596 | | int yt = ((int)y) & (t->sizey-1); |
| 597 | | int idx = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 598 | | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 599 | | int c = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)] & 0xf; |
| 600 | | return state->pvrta_regs[t->palbase + c]; |
| 601 | | } |
| 602 | | |
| 603 | | INLINE UINT32 tex_r_p8_1555_tw(running_machine &machine, texinfo *t, float x, float y) |
| 604 | | { |
| 605 | | dc_state *state = machine.driver_data<dc_state>(); |
| 606 | | int xt = ((int)x) & (t->sizex-1); |
| 607 | | int yt = ((int)y) & (t->sizey-1); |
| 608 | | int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 609 | | int c = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)]; |
| 610 | | return cv_1555(state->pvrta_regs[t->palbase + c]); |
| 611 | | } |
| 612 | | |
| 613 | | INLINE UINT32 tex_r_p8_1555_vq(running_machine &machine, texinfo *t, float x, float y) |
| 614 | | { |
| 615 | | dc_state *state = machine.driver_data<dc_state>(); |
| 616 | | int xt = ((int)x) & (t->sizex-1); |
| 617 | | int yt = ((int)y) & (t->sizey-1); |
| 618 | | int idx = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 619 | | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 620 | | int c = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)]; |
| 621 | | return cv_1555(state->pvrta_regs[t->palbase + c]); |
| 622 | | } |
| 623 | | |
| 624 | | INLINE UINT32 tex_r_p8_565_tw(running_machine &machine, texinfo *t, float x, float y) |
| 625 | | { |
| 626 | | dc_state *state = machine.driver_data<dc_state>(); |
| 627 | | int xt = ((int)x) & (t->sizex-1); |
| 628 | | int yt = ((int)y) & (t->sizey-1); |
| 629 | | int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 630 | | int c = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)]; |
| 631 | | return cv_565(state->pvrta_regs[t->palbase + c]); |
| 632 | | } |
| 633 | | |
| 634 | | INLINE UINT32 tex_r_p8_565_vq(running_machine &machine, texinfo *t, float x, float y) |
| 635 | | { |
| 636 | | dc_state *state = machine.driver_data<dc_state>(); |
| 637 | | int xt = ((int)x) & (t->sizex-1); |
| 638 | | int yt = ((int)y) & (t->sizey-1); |
| 639 | | int idx = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 640 | | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 641 | | int c = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)]; |
| 642 | | return cv_565(state->pvrta_regs[t->palbase + c]); |
| 643 | | } |
| 644 | | |
| 645 | | INLINE UINT32 tex_r_p8_4444_tw(running_machine &machine, texinfo *t, float x, float y) |
| 646 | | { |
| 647 | | dc_state *state = machine.driver_data<dc_state>(); |
| 648 | | int xt = ((int)x) & (t->sizex-1); |
| 649 | | int yt = ((int)y) & (t->sizey-1); |
| 650 | | int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 651 | | int c = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)]; |
| 652 | | return cv_4444(state->pvrta_regs[t->palbase + c]); |
| 653 | | } |
| 654 | | |
| 655 | | INLINE UINT32 tex_r_p8_4444_vq(running_machine &machine, texinfo *t, float x, float y) |
| 656 | | { |
| 657 | | dc_state *state = machine.driver_data<dc_state>(); |
| 658 | | int xt = ((int)x) & (t->sizex-1); |
| 659 | | int yt = ((int)y) & (t->sizey-1); |
| 660 | | int idx = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 661 | | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 662 | | int c = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)]; |
| 663 | | return cv_4444(state->pvrta_regs[t->palbase + c]); |
| 664 | | } |
| 665 | | |
| 666 | | INLINE UINT32 tex_r_p8_8888_tw(running_machine &machine, texinfo *t, float x, float y) |
| 667 | | { |
| 668 | | dc_state *state = machine.driver_data<dc_state>(); |
| 669 | | int xt = ((int)x) & (t->sizex-1); |
| 670 | | int yt = ((int)y) & (t->sizey-1); |
| 671 | | int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 672 | | int c = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)]; |
| 673 | | return state->pvrta_regs[t->palbase + c]; |
| 674 | | } |
| 675 | | |
| 676 | | INLINE UINT32 tex_r_p8_8888_vq(running_machine &machine, texinfo *t, float x, float y) |
| 677 | | { |
| 678 | | dc_state *state = machine.driver_data<dc_state>(); |
| 679 | | int xt = ((int)x) & (t->sizex-1); |
| 680 | | int yt = ((int)y) & (t->sizey-1); |
| 681 | | int idx = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 682 | | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 683 | | int c = (reinterpret_cast<UINT8 *>(state->dc_texture_ram.target()))[BYTE_XOR_LE(addrp)]; |
| 684 | | return state->pvrta_regs[t->palbase + c]; |
| 685 | | } |
| 686 | | |
| 687 | | |
| 688 | | INLINE UINT32 tex_r_default(running_machine &machine, texinfo *t, float x, float y) |
| 689 | | { |
| 690 | | return ((int)x ^ (int)y) & 4 ? 0xffffff00 : 0xff0000ff; |
| 691 | | } |
| 692 | | |
| 693 | | static void tex_get_info(running_machine &machine,texinfo *t, pvrta_state *sa) |
| 694 | | { |
| 695 | | dc_state *state = machine.driver_data<dc_state>(); |
| 696 | | int miptype = 0; |
| 697 | | |
| 698 | | t->textured = sa->texture; |
| 699 | | |
| 700 | | // not textured, abort. |
| 701 | | if (!t->textured) return; |
| 702 | | |
| 703 | | t->address = sa->textureaddress; |
| 704 | | t->pf = sa->pixelformat; |
| 705 | | t->palette = 0; |
| 706 | | |
| 707 | | t->mode = (sa->vqcompressed<<1); |
| 708 | | |
| 709 | | // scanorder is ignored for palettized textures (palettized textures are ALWAYS twiddled) |
| 710 | | // (the same bits are used for palette select instead) |
| 711 | | if ((t->pf == 5) || (t->pf == 6)) |
| 712 | | { |
| 713 | | t->palette = sa->paletteselector; |
| 714 | | } |
| 715 | | else |
| 716 | | { |
| 717 | | t->mode |= sa->scanorder; |
| 718 | | } |
| 719 | | |
| 720 | | /* When scan order is 1 (non-twiddled) mipmap is ignored */ |
| 721 | | t->mipmapped = t->mode & 1 ? 0 : sa->mipmapped; |
| 722 | | |
| 723 | | // Mipmapped textures are always square, ignore v size |
| 724 | | if (t->mipmapped) |
| 725 | | { |
| 726 | | t->sizes = (sa->texturesizes & 0x38) | ((sa->texturesizes & 0x38) >> 3); |
| 727 | | } |
| 728 | | else |
| 729 | | { |
| 730 | | t->sizes = sa->texturesizes; |
| 731 | | } |
| 732 | | |
| 733 | | t->sizex = 1 << (3+((t->sizes >> 3) & 7)); |
| 734 | | t->sizey = 1 << (3+(t->sizes & 7)); |
| 735 | | |
| 736 | | |
| 737 | | /* Stride select is used only in the non-twiddled case */ |
| 738 | | t->stride = (t->mode & 1) && sa->strideselect ? (state->pvrta_regs[TEXT_CONTROL] & 0x1f) << 5 : t->sizex; |
| 739 | | |
| 740 | | t->blend_mode = sa->blend_mode; |
| 741 | | t->filter_mode = sa->filtermode; |
| 742 | | t->flip_u = (sa->flipuv >> 1) & 1; |
| 743 | | t->flip_v = sa->flipuv & 1; |
| 744 | | |
| 745 | | t->r = tex_r_default; |
| 746 | | t->cd = dilatechose[t->sizes]; |
| 747 | | t->palbase = 0; |
| 748 | | t->vqbase = t->address; |
| 749 | | t->blend = sa->use_alpha ? blend_functions[t->blend_mode] : bl10; |
| 750 | | |
| 751 | | // fprintf(stderr, "tex %d %d %d %d\n", t->pf, t->mode, state->pvrta_regs[PAL_RAM_CTRL], t->mipmapped); |
| 752 | | |
| 753 | | switch(t->pf) { |
| 754 | | case 0: // 1555 |
| 755 | | switch(t->mode) { |
| 756 | | case 0: t->r = tex_r_1555_tw; miptype = 2; break; |
| 757 | | case 1: t->r = tex_r_1555_n; miptype = 2; break; |
| 758 | | case 2: |
| 759 | | case 3: t->r = tex_r_1555_vq; miptype = 3; t->address += 0x800; break; |
| 760 | | |
| 761 | | default: |
| 762 | | // |
| 763 | | break; |
| 764 | | } |
| 765 | | break; |
| 766 | | |
| 767 | | case 1: // 565 |
| 768 | | switch(t->mode) { |
| 769 | | case 0: t->r = tex_r_565_tw; miptype = 2; break; |
| 770 | | case 1: t->r = tex_r_565_n; miptype = 2; break; |
| 771 | | case 2: |
| 772 | | case 3: t->r = tex_r_565_vq; miptype = 3; t->address += 0x800; break; |
| 773 | | |
| 774 | | default: |
| 775 | | // |
| 776 | | break; |
| 777 | | } |
| 778 | | break; |
| 779 | | |
| 780 | | case 2: // 4444 |
| 781 | | switch(t->mode) { |
| 782 | | case 0: t->r = tex_r_4444_tw; miptype = 2; break; |
| 783 | | case 1: t->r = tex_r_4444_n; miptype = 2; break; |
| 784 | | case 2: |
| 785 | | case 3: t->r = tex_r_4444_vq; miptype = 3; t->address += 0x800; break; |
| 786 | | |
| 787 | | default: |
| 788 | | // |
| 789 | | break; |
| 790 | | } |
| 791 | | break; |
| 792 | | |
| 793 | | case 3: // yuv422 |
| 794 | | switch(t->mode) { |
| 795 | | case 0: /*t->r = tex_r_yuv_tw*/; miptype = -1; break; |
| 796 | | case 1: t->r = tex_r_yuv_n; miptype = -1; break; |
| 797 | | default: /*t->r = tex_r_yuv_vq*/; miptype = -1; break; |
| 798 | | } |
| 799 | | break; |
| 800 | | |
| 801 | | case 4: // bumpmap |
| 802 | | break; |
| 803 | | |
| 804 | | case 5: // 4bpp palette |
| 805 | | t->palbase = 0x400 | ((t->palette & 0x3f) << 4); |
| 806 | | switch(t->mode) { |
| 807 | | case 0: case 1: |
| 808 | | miptype = 0; |
| 809 | | |
| 810 | | switch(state->pvrta_regs[PAL_RAM_CTRL]) { |
| 811 | | case 0: t->r = tex_r_p4_1555_tw; break; |
| 812 | | case 1: t->r = tex_r_p4_565_tw; break; |
| 813 | | case 2: t->r = tex_r_p4_4444_tw; break; |
| 814 | | case 3: t->r = tex_r_p4_8888_tw; break; |
| 815 | | } |
| 816 | | break; |
| 817 | | case 2: case 3: |
| 818 | | miptype = 3; // ? |
| 819 | | switch(state->pvrta_regs[PAL_RAM_CTRL]) { |
| 820 | | case 0: t->r = tex_r_p4_1555_vq; t->address += 0x800; break; |
| 821 | | case 1: t->r = tex_r_p4_565_vq; t->address += 0x800; break; |
| 822 | | case 2: t->r = tex_r_p4_4444_vq; t->address += 0x800; break; |
| 823 | | case 3: t->r = tex_r_p4_8888_vq; t->address += 0x800; break; |
| 824 | | } |
| 825 | | break; |
| 826 | | |
| 827 | | default: |
| 828 | | // |
| 829 | | break; |
| 830 | | } |
| 831 | | break; |
| 832 | | |
| 833 | | case 6: // 8bpp palette |
| 834 | | t->palbase = 0x400 | ((t->palette & 0x30) << 4); |
| 835 | | switch(t->mode) { |
| 836 | | case 0: case 1: |
| 837 | | miptype = 1; |
| 838 | | |
| 839 | | switch(state->pvrta_regs[PAL_RAM_CTRL]) { |
| 840 | | case 0: t->r = tex_r_p8_1555_tw; break; |
| 841 | | case 1: t->r = tex_r_p8_565_tw; break; |
| 842 | | case 2: t->r = tex_r_p8_4444_tw; break; |
| 843 | | case 3: t->r = tex_r_p8_8888_tw; break; |
| 844 | | } |
| 845 | | break; |
| 846 | | case 2: case 3: |
| 847 | | miptype = 3; // ? |
| 848 | | switch(state->pvrta_regs[PAL_RAM_CTRL]) { |
| 849 | | case 0: t->r = tex_r_p8_1555_vq; t->address += 0x800; break; |
| 850 | | case 1: t->r = tex_r_p8_565_vq; t->address += 0x800; break; |
| 851 | | case 2: t->r = tex_r_p8_4444_vq; t->address += 0x800; break; |
| 852 | | case 3: t->r = tex_r_p8_8888_vq; t->address += 0x800; break; |
| 853 | | } |
| 854 | | break; |
| 855 | | |
| 856 | | default: |
| 857 | | // |
| 858 | | break; |
| 859 | | } |
| 860 | | break; |
| 861 | | |
| 862 | | case 9: // reserved |
| 863 | | break; |
| 864 | | } |
| 865 | | |
| 866 | | if (t->mipmapped) |
| 867 | | { |
| 868 | | // full offset tables for reference, |
| 869 | | // we don't do mipmapping, so don't use anything < 8x8 |
| 870 | | // first table is half-bytes |
| 871 | | |
| 872 | | // 4BPP palette textures |
| 873 | | // Texture size _4-bit_ offset value for starting address |
| 874 | | // 1x1 0x00003 |
| 875 | | // 2x2 0x00004 |
| 876 | | // 4x4 0x00008 |
| 877 | | // 8x8 0x00018 |
| 878 | | // 16x16 0x00058 |
| 879 | | // 32x32 0x00158 |
| 880 | | // 64x64 0x00558 |
| 881 | | // 128x128 0x01558 |
| 882 | | // 256x256 0x05558 |
| 883 | | // 512x512 0x15558 |
| 884 | | // 1024x1024 0x55558 |
| 885 | | |
| 886 | | // 8BPP palette textures |
| 887 | | // Texture size Byte offset value for starting address |
| 888 | | // 1x1 0x00003 |
| 889 | | // 2x2 0x00004 |
| 890 | | // 4x4 0x00008 |
| 891 | | // 8x8 0x00018 |
| 892 | | // 16x16 0x00058 |
| 893 | | // 32x32 0x00158 |
| 894 | | // 64x64 0x00558 |
| 895 | | // 128x128 0x01558 |
| 896 | | // 256x256 0x05558 |
| 897 | | // 512x512 0x15558 |
| 898 | | // 1024x1024 0x55558 |
| 899 | | |
| 900 | | // Non-palette textures |
| 901 | | // Texture size Byte offset value for starting address |
| 902 | | // 1x1 0x00006 |
| 903 | | // 2x2 0x00008 |
| 904 | | // 4x4 0x00010 |
| 905 | | // 8x8 0x00030 |
| 906 | | // 16x16 0x000B0 |
| 907 | | // 32x32 0x002B0 |
| 908 | | // 64x64 0x00AB0 |
| 909 | | // 128x128 0x02AB0 |
| 910 | | // 256x256 0x0AAB0 |
| 911 | | // 512x512 0x2AAB0 |
| 912 | | // 1024x1024 0xAAAB0 |
| 913 | | |
| 914 | | // VQ textures |
| 915 | | // Texture size Byte offset value for starting address |
| 916 | | // 1x1 0x00000 |
| 917 | | // 2x2 0x00001 |
| 918 | | // 4x4 0x00002 |
| 919 | | // 8x8 0x00006 |
| 920 | | // 16x16 0x00016 |
| 921 | | // 32x32 0x00056 |
| 922 | | // 64x64 0x00156 |
| 923 | | // 128x128 0x00556 |
| 924 | | // 256x256 0x01556 |
| 925 | | // 512x512 0x05556 |
| 926 | | // 1024x1024 0x15556 |
| 927 | | |
| 928 | | static const int mipmap_4_8_offset[8] = { 0x00018, 0x00058, 0x00158, 0x00558, 0x01558, 0x05558, 0x15558, 0x55558 }; // 4bpp (4bit offset) / 8bpp (8bit offset) |
| 929 | | static const int mipmap_np_offset[8] = { 0x00030, 0x000B0, 0x002B0, 0x00AB0, 0x02AB0, 0x0AAB0, 0x2AAB0, 0xAAAB0 }; // nonpalette textures |
| 930 | | static const int mipmap_vq_offset[8] = { 0x00006, 0x00016, 0x00056, 0x00156, 0x00556, 0x01556, 0x05556, 0x15556 }; // vq textures |
| 931 | | |
| 932 | | switch (miptype) |
| 933 | | { |
| 934 | | case 0: // 4bpp |
| 935 | | //printf("4bpp\n"); |
| 936 | | t->address += mipmap_4_8_offset[(t->sizes)&7]>>1; |
| 937 | | break; |
| 938 | | |
| 939 | | case 1: // 8bpp |
| 940 | | //printf("8bpp\n"); |
| 941 | | t->address += mipmap_4_8_offset[(t->sizes)&7]; |
| 942 | | break; |
| 943 | | |
| 944 | | case 2: // nonpalette |
| 945 | | //printf("np\n"); |
| 946 | | t->address += mipmap_np_offset[(t->sizes)&7]; |
| 947 | | break; |
| 948 | | |
| 949 | | case 3: // vq |
| 950 | | //printf("vq\n"); |
| 951 | | t->address += mipmap_vq_offset[(t->sizes)&7]; |
| 952 | | break; |
| 953 | | } |
| 954 | | } |
| 955 | | |
| 956 | | } |
| 957 | | |
| 958 | | // register decode helper |
| 959 | | INLINE int decode_reg_64(UINT32 offset, UINT64 mem_mask, UINT64 *shift) |
| 960 | | { |
| 961 | | int reg = offset * 2; |
| 962 | | |
| 963 | | *shift = 0; |
| 964 | | |
| 965 | | // non 32-bit accesses have not yet been seen here, we need to know when they are |
| 966 | | if ((mem_mask != U64(0xffffffff00000000)) && (mem_mask != U64(0x00000000ffffffff))) |
| 967 | | { |
| 968 | | /*assume to return the lower 32-bits ONLY*/ |
| 969 | | return reg & 0xffffffff; |
| 970 | | } |
| 971 | | |
| 972 | | if (mem_mask == U64(0xffffffff00000000)) |
| 973 | | { |
| 974 | | reg++; |
| 975 | | *shift = 32; |
| 976 | | } |
| 977 | | |
| 978 | | return reg; |
| 979 | | } |
| 980 | | |
| 981 | | READ64_HANDLER( pvr_ta_r ) |
| 982 | | { |
| 983 | | dc_state *state = space.machine().driver_data<dc_state>(); |
| 984 | | int reg; |
| 985 | | UINT64 shift; |
| 986 | | |
| 987 | | reg = decode_reg_64(offset, mem_mask, &shift); |
| 988 | | |
| 989 | | switch (reg) |
| 990 | | { |
| 991 | | case SPG_STATUS: |
| 992 | | { |
| 993 | | UINT8 fieldnum,vsync,hsync,blank; |
| 994 | | |
| 995 | | fieldnum = (space.machine().primary_screen->frame_number() & 1) ? 1 : 0; |
| 996 | | |
| 997 | | vsync = space.machine().primary_screen->vblank() ? 1 : 0; |
| 998 | | if(spg_vsync_pol) { vsync^=1; } |
| 999 | | |
| 1000 | | hsync = space.machine().primary_screen->hblank() ? 1 : 0; |
| 1001 | | if(spg_hsync_pol) { hsync^=1; } |
| 1002 | | |
| 1003 | | /* FIXME: following is just a wild guess */ |
| 1004 | | blank = (space.machine().primary_screen->vblank() | space.machine().primary_screen->hblank()) ? 0 : 1; |
| 1005 | | if(spg_blank_pol) { blank^=1; } |
| 1006 | | |
| 1007 | | state->pvrta_regs[reg] = (vsync << 13) | (hsync << 12) | (blank << 11) | (fieldnum << 10) | (space.machine().primary_screen->vpos() & 0x3ff); |
| 1008 | | break; |
| 1009 | | } |
| 1010 | | case SPG_TRIGGER_POS: |
| 1011 | | printf("Warning: read at h/v counter ext latches\n"); |
| 1012 | | break; |
| 1013 | | case TA_LIST_INIT: |
| 1014 | | return 0; //bit 31 always return 0, a probable left-over in Crazy Taxi reads this and discards the read (?) |
| 1015 | | } |
| 1016 | | |
| 1017 | | #if DEBUG_PVRTA_REGS |
| 1018 | | if (reg != 0x43) |
| 1019 | | mame_printf_verbose("PVRTA: [%08x] read %x @ %x (reg %x), mask %" I64FMT "x (PC=%x)\n", 0x5f8000+reg*4, state->pvrta_regs[reg], offset, reg, mem_mask, space.device().safe_pc()); |
| 1020 | | #endif |
| 1021 | | return (UINT64)state->pvrta_regs[reg] << shift; |
| 1022 | | } |
| 1023 | | |
| 1024 | | WRITE64_HANDLER( pvr_ta_w ) |
| 1025 | | { |
| 1026 | | dc_state *state = space.machine().driver_data<dc_state>(); |
| 1027 | | int reg; |
| 1028 | | UINT64 shift; |
| 1029 | | UINT32 dat; |
| 1030 | | UINT32 sizera,offsetra; |
| 1031 | | int a; |
| 1032 | | int sanitycount; |
| 1033 | | |
| 1034 | | reg = decode_reg_64(offset, mem_mask, &shift); |
| 1035 | | dat = (UINT32)(data >> shift); |
| 1036 | | //old = state->pvrta_regs[reg]; |
| 1037 | | |
| 1038 | | // Dreamcast BIOS attempts to set PVRID to zero and then dies |
| 1039 | | // if it succeeds. Don't allow. |
| 1040 | | if ((reg != PVRID) && (reg != REVISION)) |
| 1041 | | { |
| 1042 | | state->pvrta_regs[reg] = dat; // 5f8000+reg*4=dat |
| 1043 | | } |
| 1044 | | |
| 1045 | | switch (reg) |
| 1046 | | { |
| 1047 | | case SOFTRESET: |
| 1048 | | if (dat & 1) |
| 1049 | | { |
| 1050 | | #if DEBUG_PVRTA |
| 1051 | | mame_printf_verbose("pvr_ta_w: TA soft reset\n"); |
| 1052 | | #endif |
| 1053 | | state_ta.listtype_used=0; |
| 1054 | | } |
| 1055 | | if (dat & 2) |
| 1056 | | { |
| 1057 | | #if DEBUG_PVRTA |
| 1058 | | mame_printf_verbose("pvr_ta_w: Core Pipeline soft reset\n"); |
| 1059 | | #endif |
| 1060 | | if (state_ta.start_render_received == 1) |
| 1061 | | { |
| 1062 | | for (a=0;a < NUM_BUFFERS;a++) |
| 1063 | | if (state_ta.grab[a].busy == 1) |
| 1064 | | state_ta.grab[a].busy = 0; |
| 1065 | | state_ta.start_render_received = 0; |
| 1066 | | } |
| 1067 | | } |
| 1068 | | if (dat & 4) |
| 1069 | | { |
| 1070 | | #if DEBUG_PVRTA |
| 1071 | | mame_printf_verbose("pvr_ta_w: sdram I/F soft reset\n"); |
| 1072 | | #endif |
| 1073 | | } |
| 1074 | | break; |
| 1075 | | case STARTRENDER: |
| 1076 | | g_profiler.start(PROFILER_USER1); |
| 1077 | | #if DEBUG_PVRTA |
| 1078 | | mame_printf_verbose("Start Render Received:\n"); |
| 1079 | | mame_printf_verbose(" Region Array at %08x\n",state->pvrta_regs[REGION_BASE]); |
| 1080 | | mame_printf_verbose(" ISP/TSP Parameters at %08x\n",state->pvrta_regs[PARAM_BASE]); |
| 1081 | | |
| 1082 | | #endif |
| 1083 | | // select buffer to draw using PARAM_BASE |
| 1084 | | for (a=0;a < NUM_BUFFERS;a++) |
| 1085 | | { |
| 1086 | | if ((state_ta.grab[a].ispbase == state->pvrta_regs[PARAM_BASE]) && (state_ta.grab[a].valid == 1) && (state_ta.grab[a].busy == 0)) |
| 1087 | | { |
| 1088 | | state_ta.grab[a].busy = 1; |
| 1089 | | state_ta.renderselect = a; |
| 1090 | | state_ta.start_render_received=1; |
| 1091 | | |
| 1092 | | |
| 1093 | | state_ta.grab[a].fbwsof1=state->pvrta_regs[FB_W_SOF1]; |
| 1094 | | state_ta.grab[a].fbwsof2=state->pvrta_regs[FB_W_SOF2]; |
| 1095 | | |
| 1096 | | rectangle clip(0, 1023, 0, 1023); |
| 1097 | | |
| 1098 | | // we've got a request to draw, so, draw to the accumulation buffer! |
| 1099 | | // this should really be done for each tile! |
| 1100 | | render_to_accumulation_buffer(space.machine(),*fake_accumulationbuffer_bitmap,clip); |
| 1101 | | |
| 1102 | | state->endofrender_timer_isp->adjust(attotime::from_usec(4000) ); // hack, make sure render takes some amount of time |
| 1103 | | |
| 1104 | | /* copy the tiles to the framebuffer (really the rendering should be in this loop too) */ |
| 1105 | | if (state->pvrta_regs[FPU_PARAM_CFG] & 0x200000) |
| 1106 | | sizera=6; |
| 1107 | | else |
| 1108 | | sizera=5; |
| 1109 | | offsetra=state->pvrta_regs[REGION_BASE]; |
| 1110 | | |
| 1111 | | //printf("base is %08x\n", offsetra); |
| 1112 | | |
| 1113 | | // sanity |
| 1114 | | sanitycount = 0; |
| 1115 | | for (;;) |
| 1116 | | { |
| 1117 | | UINT32 st[6]; |
| 1118 | | |
| 1119 | | st[0]=space.read_dword((0x05000000+offsetra)); |
| 1120 | | st[1]=space.read_dword((0x05000004+offsetra)); // Opaque List Pointer |
| 1121 | | st[2]=space.read_dword((0x05000008+offsetra)); // Opaque Modifier Volume List Pointer |
| 1122 | | st[3]=space.read_dword((0x0500000c+offsetra)); // Translucent List Pointer |
| 1123 | | st[4]=space.read_dword((0x05000010+offsetra)); // Translucent Modifier Volume List Pointer |
| 1124 | | |
| 1125 | | if (sizera == 6) |
| 1126 | | { |
| 1127 | | st[5] = space.read_dword((0x05000014+offsetra)); // Punch Through List Pointer |
| 1128 | | offsetra+=0x18; |
| 1129 | | } |
| 1130 | | else |
| 1131 | | { |
| 1132 | | st[5] = 0; |
| 1133 | | offsetra+=0x14; |
| 1134 | | } |
| 1135 | | |
| 1136 | | { |
| 1137 | | int x = ((st[0]&0x000000fc)>>2)*32; |
| 1138 | | int y = ((st[0]&0x00003f00)>>8)*32; |
| 1139 | | //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]); |
| 1140 | | |
| 1141 | | // should render to the accumulation buffer here using pointers we filled in when processing the data |
| 1142 | | // sent to the TA. HOWEVER, we don't process the TA data and create the real format object lists, so |
| 1143 | | // instead just use these co-ordinates to copy data from our fake full-screnen accumnulation buffer into |
| 1144 | | // the framebuffer |
| 1145 | | |
| 1146 | | pvr_accumulationbuffer_to_framebuffer(space, x,y); |
| 1147 | | } |
| 1148 | | |
| 1149 | | if (st[0] & 0x80000000) |
| 1150 | | break; |
| 1151 | | |
| 1152 | | // prevent infinite loop if asked to process invalid data |
| 1153 | | if(sanitycount>2000) |
| 1154 | | break; |
| 1155 | | } |
| 1156 | | |
| 1157 | | |
| 1158 | | |
| 1159 | | |
| 1160 | | break; |
| 1161 | | } |
| 1162 | | } |
| 1163 | | if (a != NUM_BUFFERS) |
| 1164 | | break; |
| 1165 | | assert_always(0, "TA grabber error A!\n"); |
| 1166 | | break; |
| 1167 | | case TA_LIST_INIT: |
| 1168 | | if(dat & 0x80000000) |
| 1169 | | { |
| 1170 | | state_ta.tafifo_pos=0; |
| 1171 | | state_ta.tafifo_mask=7; |
| 1172 | | state_ta.tafifo_vertexwords=8; |
| 1173 | | state_ta.tafifo_listtype= -1; |
| 1174 | | #if DEBUG_PVRTA |
| 1175 | | mame_printf_verbose("TA_OL_BASE %08x TA_OL_LIMIT %08x\n", state->pvrta_regs[TA_OL_BASE], state->pvrta_regs[TA_OL_LIMIT]); |
| 1176 | | mame_printf_verbose("TA_ISP_BASE %08x TA_ISP_LIMIT %08x\n", state->pvrta_regs[TA_ISP_BASE], state->pvrta_regs[TA_ISP_LIMIT]); |
| 1177 | | mame_printf_verbose("TA_ALLOC_CTRL %08x\n", state->pvrta_regs[TA_ALLOC_CTRL]); |
| 1178 | | mame_printf_verbose("TA_NEXT_OPB_INIT %08x\n", state->pvrta_regs[TA_NEXT_OPB_INIT]); |
| 1179 | | #endif |
| 1180 | | state->pvrta_regs[TA_NEXT_OPB] = state->pvrta_regs[TA_NEXT_OPB_INIT]; |
| 1181 | | state->pvrta_regs[TA_ITP_CURRENT] = state->pvrta_regs[TA_ISP_BASE]; |
| 1182 | | state_ta.alloc_ctrl_OPB_Mode = state->pvrta_regs[TA_ALLOC_CTRL] & 0x100000; // 0 up 1 down |
| 1183 | | state_ta.alloc_ctrl_PT_OPB = (4 << ((state->pvrta_regs[TA_ALLOC_CTRL] >> 16) & 3)) & 0x38; // number of 32 bit words (0,8,16,32) |
| 1184 | | state_ta.alloc_ctrl_TM_OPB = (4 << ((state->pvrta_regs[TA_ALLOC_CTRL] >> 12) & 3)) & 0x38; |
| 1185 | | state_ta.alloc_ctrl_T_OPB = (4 << ((state->pvrta_regs[TA_ALLOC_CTRL] >> 8) & 3)) & 0x38; |
| 1186 | | state_ta.alloc_ctrl_OM_OPB = (4 << ((state->pvrta_regs[TA_ALLOC_CTRL] >> 4) & 3)) & 0x38; |
| 1187 | | state_ta.alloc_ctrl_O_OPB = (4 << ((state->pvrta_regs[TA_ALLOC_CTRL] >> 0) & 3)) & 0x38; |
| 1188 | | state_ta.listtype_used |= (1+4); |
| 1189 | | // use TA_ISP_BASE and select buffer for grab data |
| 1190 | | state_ta.grabsel = -1; |
| 1191 | | // try to find already used buffer but not busy |
| 1192 | | for (a=0;a < NUM_BUFFERS;a++) |
| 1193 | | { |
| 1194 | | if ((state_ta.grab[a].ispbase == state->pvrta_regs[TA_ISP_BASE]) && (state_ta.grab[a].busy == 0) && (state_ta.grab[a].valid == 1)) |
| 1195 | | { |
| 1196 | | state_ta.grabsel=a; |
| 1197 | | break; |
| 1198 | | } |
| 1199 | | } |
| 1200 | | // try a buffer not used yet |
| 1201 | | if (state_ta.grabsel < 0) |
| 1202 | | { |
| 1203 | | for (a=0;a < NUM_BUFFERS;a++) |
| 1204 | | { |
| 1205 | | if (state_ta.grab[a].valid == 0) |
| 1206 | | { |
| 1207 | | state_ta.grabsel=a; |
| 1208 | | break; |
| 1209 | | } |
| 1210 | | } |
| 1211 | | } |
| 1212 | | // find a non busy buffer starting from the last one used |
| 1213 | | if (state_ta.grabsel < 0) |
| 1214 | | { |
| 1215 | | for (a=0;a < 3;a++) |
| 1216 | | { |
| 1217 | | if (state_ta.grab[(state_ta.grabsellast+1+a) & 3].busy == 0) |
| 1218 | | { |
| 1219 | | state_ta.grabsel=a; |
| 1220 | | break; |
| 1221 | | } |
| 1222 | | } |
| 1223 | | } |
| 1224 | | if (state_ta.grabsel < 0) |
| 1225 | | assert_always(0, "TA grabber error B!\n"); |
| 1226 | | state_ta.grabsellast=state_ta.grabsel; |
| 1227 | | state_ta.grab[state_ta.grabsel].ispbase=state->pvrta_regs[TA_ISP_BASE]; |
| 1228 | | state_ta.grab[state_ta.grabsel].busy=0; |
| 1229 | | state_ta.grab[state_ta.grabsel].valid=1; |
| 1230 | | state_ta.grab[state_ta.grabsel].verts_size=0; |
| 1231 | | state_ta.grab[state_ta.grabsel].strips_size=0; |
| 1232 | | |
| 1233 | | g_profiler.stop(); |
| 1234 | | } |
| 1235 | | break; |
| 1236 | | //#define TA_YUV_TEX_BASE ((0x005f8148-0x005f8000)/4) |
| 1237 | | case TA_YUV_TEX_BASE: |
| 1238 | | printf("TA_YUV_TEX_BASE initialized to %08x\n", dat); |
| 1239 | | |
| 1240 | | // hack, this interrupt is generated after transfering a set amount of data |
| 1241 | | //state->dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_YUV; |
| 1242 | | //dc_update_interrupt_status(space.machine()); |
| 1243 | | |
| 1244 | | break; |
| 1245 | | case TA_YUV_TEX_CTRL: |
| 1246 | | printf("TA_YUV_TEX_CTRL initialized to %08x\n", dat); |
| 1247 | | break; |
| 1248 | | |
| 1249 | | case SPG_VBLANK_INT: |
| 1250 | | /* clear pending irqs and modify them with the updated ones */ |
| 1251 | | state->vbin_timer->adjust(attotime::never); |
| 1252 | | state->vbout_timer->adjust(attotime::never); |
| 1253 | | |
| 1254 | | state->vbin_timer->adjust(space.machine().primary_screen->time_until_pos(spg_vblank_in_irq_line_num)); |
| 1255 | | state->vbout_timer->adjust(space.machine().primary_screen->time_until_pos(spg_vblank_out_irq_line_num)); |
| 1256 | | break; |
| 1257 | | /* TODO: timer adjust for SPG_HBLANK_INT too */ |
| 1258 | | case TA_LIST_CONT: |
| 1259 | | #if DEBUG_PVRTA |
| 1260 | | mame_printf_verbose("List continuation processing\n"); |
| 1261 | | #endif |
| 1262 | | if(dat & 0x80000000) |
| 1263 | | { |
| 1264 | | state_ta.tafifo_listtype= -1; // no list being received |
| 1265 | | state_ta.listtype_used |= (1+4); |
| 1266 | | } |
| 1267 | | break; |
| 1268 | | case SPG_VBLANK: |
| 1269 | | case SPG_HBLANK: |
| 1270 | | case SPG_LOAD: |
| 1271 | | case VO_STARTX: |
| 1272 | | case VO_STARTY: |
| 1273 | | { |
| 1274 | | rectangle visarea = space.machine().primary_screen->visible_area(); |
| 1275 | | /* FIXME: right visible area calculations aren't known yet*/ |
| 1276 | | visarea.min_x = 0; |
| 1277 | | visarea.max_x = ((spg_hbstart - spg_hbend - vo_horz_start_pos) <= 0x180 ? 320 : 640) - 1; |
| 1278 | | visarea.min_y = 0; |
| 1279 | | visarea.max_y = ((spg_vbstart - spg_vbend - vo_vert_start_pos_f1) <= 0x100 ? 240 : 480) - 1; |
| 1280 | | |
| 1281 | | |
| 1282 | | space.machine().primary_screen->configure(spg_hbstart, spg_vbstart, visarea, space.machine().primary_screen->frame_period().attoseconds ); |
| 1283 | | } |
| 1284 | | break; |
| 1285 | | } |
| 1286 | | |
| 1287 | | #if DEBUG_PVRTA_REGS |
| 1288 | | if ((reg != 0x14) && (reg != 0x15)) |
| 1289 | | mame_printf_verbose("PVRTA: [%08x=%x] write %" I64FMT "x to %x (reg %x %x), mask %" I64FMT "x\n", 0x5f8000+reg*4, dat, data>>shift, offset, reg, (reg*4)+0x8000, mem_mask); |
| 1290 | | #endif |
| 1291 | | } |
| 1292 | | |
| 1293 | | TIMER_CALLBACK_MEMBER(dc_state::transfer_opaque_list_irq) |
| 1294 | | { |
| 1295 | | dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_OPLST; |
| 1296 | | dc_update_interrupt_status(); |
| 1297 | | } |
| 1298 | | |
| 1299 | | TIMER_CALLBACK_MEMBER(dc_state::transfer_opaque_modifier_volume_list_irq) |
| 1300 | | { |
| 1301 | | dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_OPMV; |
| 1302 | | dc_update_interrupt_status(); |
| 1303 | | } |
| 1304 | | |
| 1305 | | TIMER_CALLBACK_MEMBER(dc_state::transfer_translucent_list_irq) |
| 1306 | | { |
| 1307 | | dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_TRLST; |
| 1308 | | dc_update_interrupt_status(); |
| 1309 | | } |
| 1310 | | |
| 1311 | | TIMER_CALLBACK_MEMBER(dc_state::transfer_translucent_modifier_volume_list_irq) |
| 1312 | | { |
| 1313 | | dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_TRMV; |
| 1314 | | dc_update_interrupt_status(); |
| 1315 | | } |
| 1316 | | |
| 1317 | | TIMER_CALLBACK_MEMBER(dc_state::transfer_punch_through_list_irq) |
| 1318 | | { |
| 1319 | | dc_sysctrl_regs[SB_ISTNRM] |= (1 << 21); |
| 1320 | | dc_update_interrupt_status(); |
| 1321 | | } |
| 1322 | | |
| 1323 | | static void process_ta_fifo(running_machine& machine) |
| 1324 | | { |
| 1325 | | dc_state *state = machine.driver_data<dc_state>(); |
| 1326 | | |
| 1327 | | /* first byte in the buffer is the Parameter Control Word |
| 1328 | | |
| 1329 | | pppp pppp gggg gggg oooo oooo oooo oooo |
| 1330 | | |
| 1331 | | p = para control |
| 1332 | | g = group control |
| 1333 | | o = object control |
| 1334 | | |
| 1335 | | */ |
| 1336 | | |
| 1337 | | receiveddata *rd = &state_ta.grab[state_ta.grabsel]; |
| 1338 | | |
| 1339 | | // Para Control |
| 1340 | | state_ta.paracontrol=(state->tafifo_buff[0] >> 24) & 0xff; |
| 1341 | | // 0 end of list |
| 1342 | | // 1 user tile clip |
| 1343 | | // 2 object list set |
| 1344 | | // 3 reserved |
| 1345 | | // 4 polygon/modifier volume |
| 1346 | | // 5 sprite |
| 1347 | | // 6 reserved |
| 1348 | | // 7 vertex |
| 1349 | | state_ta.paratype=(state_ta.paracontrol >> 5) & 7; |
| 1350 | | state_ta.endofstrip=(state_ta.paracontrol >> 4) & 1; |
| 1351 | | state_ta.listtype=(state_ta.paracontrol >> 0) & 7; |
| 1352 | | if ((state_ta.paratype >= 4) && (state_ta.paratype <= 6)) |
| 1353 | | { |
| 1354 | | state_ta.global_paratype = state_ta.paratype; |
| 1355 | | // Group Control |
| 1356 | | state_ta.groupcontrol=(state->tafifo_buff[0] >> 16) & 0xff; |
| 1357 | | state_ta.groupen=(state_ta.groupcontrol >> 7) & 1; |
| 1358 | | state_ta.striplen=(state_ta.groupcontrol >> 2) & 3; |
| 1359 | | state_ta.userclip=(state_ta.groupcontrol >> 0) & 3; |
| 1360 | | // Obj Control |
| 1361 | | state_ta.objcontrol=(state->tafifo_buff[0] >> 0) & 0xffff; |
| 1362 | | state_ta.shadow=(state_ta.objcontrol >> 7) & 1; |
| 1363 | | state_ta.volume=(state_ta.objcontrol >> 6) & 1; |
| 1364 | | state_ta.coltype=(state_ta.objcontrol >> 4) & 3; |
| 1365 | | state_ta.texture=(state_ta.objcontrol >> 3) & 1; |
| 1366 | | state_ta.offfset=(state_ta.objcontrol >> 2) & 1; |
| 1367 | | state_ta.gouraud=(state_ta.objcontrol >> 1) & 1; |
| 1368 | | state_ta.uv16bit=(state_ta.objcontrol >> 0) & 1; |
| 1369 | | } |
| 1370 | | |
| 1371 | | // check if we need 8 words more |
| 1372 | | if (state_ta.tafifo_mask == 7) |
| 1373 | | { |
| 1374 | | state_ta.parameterconfig = pvr_parameterconfig[state_ta.objcontrol & 0x3d]; |
| 1375 | | // decide number of words per vertex |
| 1376 | | if (state_ta.paratype == 7) |
| 1377 | | { |
| 1378 | | if ((state_ta.global_paratype == 5) || (state_ta.tafifo_listtype == 1) || (state_ta.tafifo_listtype == 3)) |
| 1379 | | state_ta.tafifo_vertexwords = 16; |
| 1380 | | if (state_ta.tafifo_vertexwords == 16) |
| 1381 | | { |
| 1382 | | state_ta.tafifo_mask = 15; |
| 1383 | | state_ta.tafifo_pos = 8; |
| 1384 | | return; |
| 1385 | | } |
| 1386 | | } |
| 1387 | | // decide number of words when not a vertex |
| 1388 | | state_ta.tafifo_vertexwords=pvr_wordsvertex[state_ta.parameterconfig]; |
| 1389 | | if ((state_ta.paratype == 4) && ((state_ta.listtype != 1) && (state_ta.listtype != 3))) |
| 1390 | | if (pvr_wordspolygon[state_ta.parameterconfig] == 16) |
| 1391 | | { |
| 1392 | | state_ta.tafifo_mask = 15; |
| 1393 | | state_ta.tafifo_pos = 8; |
| 1394 | | return; |
| 1395 | | } |
| 1396 | | } |
| 1397 | | state_ta.tafifo_mask = 7; |
| 1398 | | |
| 1399 | | // now we heve all the needed words |
| 1400 | | // here we should generate the data for the various tiles |
| 1401 | | // for now, just interpret their meaning |
| 1402 | | if (state_ta.paratype == 0) |
| 1403 | | { // end of list |
| 1404 | | #if DEBUG_PVRDLIST |
| 1405 | | mame_printf_verbose("Para Type 0 End of List\n"); |
| 1406 | | #endif |
| 1407 | | /* Process transfer FIFO done irqs here */ |
| 1408 | | /* FIXME: timing of these */ |
| 1409 | | switch (state_ta.tafifo_listtype) |
| 1410 | | { |
| 1411 | | case 0: machine.scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(dc_state::transfer_opaque_list_irq),state)); break; |
| 1412 | | case 1: machine.scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(dc_state::transfer_opaque_modifier_volume_list_irq),state)); break; |
| 1413 | | case 2: machine.scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(dc_state::transfer_translucent_list_irq),state)); break; |
| 1414 | | case 3: machine.scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(dc_state::transfer_translucent_modifier_volume_list_irq),state)); break; |
| 1415 | | case 4: machine.scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(dc_state::transfer_punch_through_list_irq),state)); break; |
| 1416 | | } |
| 1417 | | state_ta.tafifo_listtype= -1; // no list being received |
| 1418 | | state_ta.listtype_used |= (2+8); |
| 1419 | | } |
| 1420 | | else if (state_ta.paratype == 1) |
| 1421 | | { // user tile clip |
| 1422 | | #if DEBUG_PVRDLIST |
| 1423 | | mame_printf_verbose("Para Type 1 User Tile Clip\n"); |
| 1424 | | mame_printf_verbose(" (%d , %d)-(%d , %d)\n", state->tafifo_buff[4], state->tafifo_buff[5], state->tafifo_buff[6], state->tafifo_buff[7]); |
| 1425 | | #endif |
| 1426 | | } |
| 1427 | | else if (state_ta.paratype == 2) |
| 1428 | | { // object list set |
| 1429 | | #if DEBUG_PVRDLIST |
| 1430 | | mame_printf_verbose("Para Type 2 Object List Set at %08x\n", state->tafifo_buff[1]); |
| 1431 | | mame_printf_verbose(" (%d , %d)-(%d , %d)\n", state->tafifo_buff[4], state->tafifo_buff[5], state->tafifo_buff[6], state->tafifo_buff[7]); |
| 1432 | | #endif |
| 1433 | | } |
| 1434 | | else if (state_ta.paratype == 3) |
| 1435 | | { |
| 1436 | | #if DEBUG_PVRDLIST |
| 1437 | | mame_printf_verbose("Para Type %x Unknown!\n", state->tafifo_buff[0]); |
| 1438 | | #endif |
| 1439 | | } |
| 1440 | | else |
| 1441 | | { // global parameter or vertex parameter |
| 1442 | | #if DEBUG_PVRDLIST |
| 1443 | | mame_printf_verbose("Para Type %d", state_ta.paratype); |
| 1444 | | if (state_ta.paratype == 7) |
| 1445 | | mame_printf_verbose(" End of Strip %d", state_ta.endofstrip); |
| 1446 | | if (state_ta.listtype_used & 3) |
| 1447 | | mame_printf_verbose(" List Type %d", state_ta.listtype); |
| 1448 | | mame_printf_verbose("\n"); |
| 1449 | | #endif |
| 1450 | | |
| 1451 | | // set type of list currently being received |
| 1452 | | if ((state_ta.paratype == 4) || (state_ta.paratype == 5) || (state_ta.paratype == 6)) |
| 1453 | | { |
| 1454 | | if (state_ta.tafifo_listtype < 0) |
| 1455 | | { |
| 1456 | | state_ta.tafifo_listtype = state_ta.listtype; |
| 1457 | | } |
| 1458 | | } |
| 1459 | | state_ta.listtype_used = state_ta.listtype_used ^ (state_ta.listtype_used & 3); |
| 1460 | | |
| 1461 | | if ((state_ta.paratype == 4) || (state_ta.paratype == 5)) |
| 1462 | | { // quad or polygon |
| 1463 | | state_ta.depthcomparemode=(state->tafifo_buff[1] >> 29) & 7; |
| 1464 | | state_ta.cullingmode=(state->tafifo_buff[1] >> 27) & 3; |
| 1465 | | state_ta.zwritedisable=(state->tafifo_buff[1] >> 26) & 1; |
| 1466 | | state_ta.cachebypass=(state->tafifo_buff[1] >> 21) & 1; |
| 1467 | | state_ta.dcalcctrl=(state->tafifo_buff[1] >> 20) & 1; |
| 1468 | | state_ta.volumeinstruction=(state->tafifo_buff[1] >> 29) & 7; |
| 1469 | | |
| 1470 | | //state_ta.textureusize=1 << (3+((state->tafifo_buff[2] >> 3) & 7)); |
| 1471 | | //state_ta.texturevsize=1 << (3+(state->tafifo_buff[2] & 7)); |
| 1472 | | state_ta.texturesizes=state->tafifo_buff[2] & 0x3f; |
| 1473 | | state_ta.blend_mode = state->tafifo_buff[2] >> 26; |
| 1474 | | state_ta.srcselect=(state->tafifo_buff[2] >> 25) & 1; |
| 1475 | | state_ta.dstselect=(state->tafifo_buff[2] >> 24) & 1; |
| 1476 | | state_ta.fogcontrol=(state->tafifo_buff[2] >> 22) & 3; |
| 1477 | | state_ta.colorclamp=(state->tafifo_buff[2] >> 21) & 1; |
| 1478 | | state_ta.use_alpha = (state->tafifo_buff[2] >> 20) & 1; |
| 1479 | | state_ta.ignoretexalpha=(state->tafifo_buff[2] >> 19) & 1; |
| 1480 | | state_ta.flipuv=(state->tafifo_buff[2] >> 17) & 3; |
| 1481 | | state_ta.clampuv=(state->tafifo_buff[2] >> 15) & 3; |
| 1482 | | state_ta.filtermode=(state->tafifo_buff[2] >> 13) & 3; |
| 1483 | | state_ta.sstexture=(state->tafifo_buff[2] >> 12) & 1; |
| 1484 | | state_ta.mmdadjust=(state->tafifo_buff[2] >> 8) & 1; |
| 1485 | | state_ta.tsinstruction=(state->tafifo_buff[2] >> 6) & 3; |
| 1486 | | if (state_ta.texture == 1) |
| 1487 | | { |
| 1488 | | state_ta.textureaddress=(state->tafifo_buff[3] & 0x1FFFFF) << 3; |
| 1489 | | state_ta.scanorder=(state->tafifo_buff[3] >> 26) & 1; |
| 1490 | | state_ta.pixelformat=(state->tafifo_buff[3] >> 27) & 7; |
| 1491 | | state_ta.mipmapped=(state->tafifo_buff[3] >> 31) & 1; |
| 1492 | | state_ta.vqcompressed=(state->tafifo_buff[3] >> 30) & 1; |
| 1493 | | state_ta.strideselect=(state->tafifo_buff[3] >> 25) & 1; |
| 1494 | | state_ta.paletteselector=(state->tafifo_buff[3] >> 21) & 0x3F; |
| 1495 | | #if DEBUG_PVRDLIST |
| 1496 | | mame_printf_verbose(" Texture at %08x format %d\n", (state->tafifo_buff[3] & 0x1FFFFF) << 3, state_ta.pixelformat); |
| 1497 | | #endif |
| 1498 | | } |
| 1499 | | if (state_ta.paratype == 4) |
| 1500 | | { // polygon or mv |
| 1501 | | if ((state_ta.tafifo_listtype == 1) || (state_ta.tafifo_listtype == 3)) |
| 1502 | | { |
| 1503 | | #if DEBUG_PVRDLIST |
| 1504 | | mame_printf_verbose(" Modifier Volume\n"); |
| 1505 | | #endif |
| 1506 | | } |
| 1507 | | else |
| 1508 | | { |
| 1509 | | #if DEBUG_PVRDLIST |
| 1510 | | mame_printf_verbose(" Polygon\n"); |
| 1511 | | #endif |
| 1512 | | } |
| 1513 | | } |
| 1514 | | if (state_ta.paratype == 5) |
| 1515 | | { // quad |
| 1516 | | #if DEBUG_PVRDLIST |
| 1517 | | mame_printf_verbose(" Sprite\n"); |
| 1518 | | #endif |
| 1519 | | } |
| 1520 | | } |
| 1521 | | |
| 1522 | | if (state_ta.paratype == 7) |
| 1523 | | { // vertex |
| 1524 | | if ((state_ta.tafifo_listtype == 1) || (state_ta.tafifo_listtype == 3)) |
| 1525 | | { |
| 1526 | | #if DEBUG_PVRDLIST |
| 1527 | | mame_printf_verbose(" Vertex modifier volume"); |
| 1528 | | mame_printf_verbose(" A(%f,%f,%f) B(%f,%f,%f) C(%f,%f,%f)", u2f(state->tafifo_buff[1]), u2f(state->tafifo_buff[2]), |
| 1529 | | u2f(state->tafifo_buff[3]), u2f(state->tafifo_buff[4]), u2f(state->tafifo_buff[5]), u2f(state->tafifo_buff[6]), u2f(state->tafifo_buff[7]), |
| 1530 | | u2f(state->tafifo_buff[8]), u2f(state->tafifo_buff[9])); |
| 1531 | | mame_printf_verbose("\n"); |
| 1532 | | #endif |
| 1533 | | } |
| 1534 | | else if (state_ta.global_paratype == 5) |
| 1535 | | { |
| 1536 | | #if DEBUG_PVRDLIST |
| 1537 | | mame_printf_verbose(" Vertex sprite"); |
| 1538 | | mame_printf_verbose(" A(%f,%f,%f) B(%f,%f,%f) C(%f,%f,%f) D(%f,%f,)", u2f(state->tafifo_buff[1]), u2f(state->tafifo_buff[2]), |
| 1539 | | u2f(state->tafifo_buff[3]), u2f(state->tafifo_buff[4]), u2f(state->tafifo_buff[5]), u2f(state->tafifo_buff[6]), u2f(state->tafifo_buff[7]), |
| 1540 | | u2f(state->tafifo_buff[8]), u2f(state->tafifo_buff[9]), u2f(state->tafifo_buff[10]), u2f(state->tafifo_buff[11])); |
| 1541 | | mame_printf_verbose("\n"); |
| 1542 | | #endif |
| 1543 | | if (state_ta.texture == 1) |
| 1544 | | { |
| 1545 | | if (rd->verts_size <= 65530) |
| 1546 | | { |
| 1547 | | strip *ts; |
| 1548 | | vert *tv = &rd->verts[rd->verts_size]; |
| 1549 | | tv[0].x = u2f(state->tafifo_buff[0x1]); |
| 1550 | | tv[0].y = u2f(state->tafifo_buff[0x2]); |
| 1551 | | tv[0].w = u2f(state->tafifo_buff[0x3]); |
| 1552 | | tv[1].x = u2f(state->tafifo_buff[0x4]); |
| 1553 | | tv[1].y = u2f(state->tafifo_buff[0x5]); |
| 1554 | | tv[1].w = u2f(state->tafifo_buff[0x6]); |
| 1555 | | tv[3].x = u2f(state->tafifo_buff[0x7]); |
| 1556 | | tv[3].y = u2f(state->tafifo_buff[0x8]); |
| 1557 | | tv[3].w = u2f(state->tafifo_buff[0x9]); |
| 1558 | | tv[2].x = u2f(state->tafifo_buff[0xa]); |
| 1559 | | tv[2].y = u2f(state->tafifo_buff[0xb]); |
| 1560 | | tv[2].w = tv[0].w+tv[3].w-tv[1].w; |
| 1561 | | tv[0].u = u2f(state->tafifo_buff[0xd] & 0xffff0000); |
| 1562 | | tv[0].v = u2f(state->tafifo_buff[0xd] << 16); |
| 1563 | | tv[1].u = u2f(state->tafifo_buff[0xe] & 0xffff0000); |
| 1564 | | tv[1].v = u2f(state->tafifo_buff[0xe] << 16); |
| 1565 | | tv[3].u = u2f(state->tafifo_buff[0xf] & 0xffff0000); |
| 1566 | | tv[3].v = u2f(state->tafifo_buff[0xf] << 16); |
| 1567 | | tv[2].u = tv[0].u+tv[3].u-tv[1].u; |
| 1568 | | tv[2].v = tv[0].v+tv[3].v-tv[1].v; |
| 1569 | | |
| 1570 | | ts = &rd->strips[rd->strips_size++]; |
| 1571 | | tex_get_info(machine, &ts->ti, &state_ta); |
| 1572 | | ts->svert = rd->verts_size; |
| 1573 | | ts->evert = rd->verts_size + 3; |
| 1574 | | |
| 1575 | | rd->verts_size += 4; |
| 1576 | | } |
| 1577 | | } |
| 1578 | | } |
| 1579 | | else if (state_ta.global_paratype == 4) |
| 1580 | | { |
| 1581 | | #if DEBUG_PVRDLIST |
| 1582 | | mame_printf_verbose(" Vertex polygon"); |
| 1583 | | mame_printf_verbose(" V(%f,%f,%f) T(%f,%f)", u2f(state->tafifo_buff[1]), u2f(state->tafifo_buff[2]), u2f(state->tafifo_buff[3]), u2f(state->tafifo_buff[4]), u2f(state->tafifo_buff[5])); |
| 1584 | | mame_printf_verbose("\n"); |
| 1585 | | #endif |
| 1586 | | if (rd->verts_size <= 65530) |
| 1587 | | { |
| 1588 | | /* add a vertex to our list */ |
| 1589 | | /* this is used for 3d stuff, ie most of the graphics (see guilty gear, confidential mission, maze of the kings etc.) */ |
| 1590 | | /* -- this is also wildly inaccurate! */ |
| 1591 | | vert *tv = &rd->verts[rd->verts_size]; |
| 1592 | | |
| 1593 | | tv->x=u2f(state->tafifo_buff[1]); |
| 1594 | | tv->y=u2f(state->tafifo_buff[2]); |
| 1595 | | tv->w=u2f(state->tafifo_buff[3]); |
| 1596 | | tv->u=u2f(state->tafifo_buff[4]); |
| 1597 | | tv->v=u2f(state->tafifo_buff[5]); |
| 1598 | | |
| 1599 | | |
| 1600 | | if((!rd->strips_size) || |
| 1601 | | rd->strips[rd->strips_size-1].evert != -1) |
| 1602 | | { |
| 1603 | | strip *ts = &rd->strips[rd->strips_size++]; |
| 1604 | | tex_get_info(machine, &ts->ti, &state_ta); |
| 1605 | | ts->svert = rd->verts_size; |
| 1606 | | ts->evert = -1; |
| 1607 | | } |
| 1608 | | if(state_ta.endofstrip) |
| 1609 | | rd->strips[rd->strips_size-1].evert = rd->verts_size; |
| 1610 | | rd->verts_size++; |
| 1611 | | } |
| 1612 | | } |
| 1613 | | } |
| 1614 | | } |
| 1615 | | } |
| 1616 | | |
| 1617 | | WRITE64_HANDLER( ta_fifo_poly_w ) |
| 1618 | | { |
| 1619 | | dc_state *state = space.machine().driver_data<dc_state>(); |
| 1620 | | |
| 1621 | | if (mem_mask == U64(0xffffffffffffffff)) // 64 bit |
| 1622 | | { |
| 1623 | | state->tafifo_buff[state_ta.tafifo_pos]=(UINT32)data; |
| 1624 | | state->tafifo_buff[state_ta.tafifo_pos+1]=(UINT32)(data >> 32); |
| 1625 | | #if DEBUG_FIFO_POLY |
| 1626 | | mame_printf_debug("ta_fifo_poly_w: Unmapped write64 %08x = %" I64FMT "x -> %08x %08x\n", 0x10000000+offset*8, data, state->tafifo_buff[state_ta.tafifo_pos], state->tafifo_buff[state_ta.tafifo_pos+1]); |
| 1627 | | #endif |
| 1628 | | state_ta.tafifo_pos += 2; |
| 1629 | | } |
| 1630 | | else |
| 1631 | | { |
| 1632 | | fatalerror("ta_fifo_poly_w: Only 64 bit writes supported!\n"); |
| 1633 | | } |
| 1634 | | |
| 1635 | | state_ta.tafifo_pos &= state_ta.tafifo_mask; |
| 1636 | | |
| 1637 | | // if the command is complete, process it |
| 1638 | | if (state_ta.tafifo_pos == 0) |
| 1639 | | process_ta_fifo(space.machine()); |
| 1640 | | |
| 1641 | | } |
| 1642 | | |
| 1643 | | WRITE64_HANDLER( ta_fifo_yuv_w ) |
| 1644 | | { |
| 1645 | | //dc_state *state = space.machine().driver_data<dc_state>(); |
| 1646 | | |
| 1647 | | // int reg; |
| 1648 | | // UINT64 shift; |
| 1649 | | // UINT32 dat; |
| 1650 | | |
| 1651 | | // reg = decode_reg_64(offset, mem_mask, &shift); |
| 1652 | | // dat = (UINT32)(data >> shift); |
| 1653 | | |
| 1654 | | // printf("YUV FIFO: [%08x=%x] write %" I64FMT "x to %x, mask %" I64FMT "x %08x\n", 0x10800000+reg*4, dat, data, offset, mem_mask,test); |
| 1655 | | } |
| 1656 | | |
| 1657 | | /* test video start */ |
| 1658 | | static UINT32 dilate0(UINT32 value,int bits) // dilate first "bits" bits in "value" |
| 1659 | | { |
| 1660 | | UINT32 x,m1,m2,m3; |
| 1661 | | int a; |
| 1662 | | |
| 1663 | | x = value; |
| 1664 | | for (a=0;a < bits;a++) |
| 1665 | | { |
| 1666 | | m2 = 1 << (a << 1); |
| 1667 | | m1 = m2 - 1; |
| 1668 | | m3 = (~m1) << 1; |
| 1669 | | x = (x & m1) + (x & m2) + ((x & m3) << 1); |
| 1670 | | } |
| 1671 | | return x; |
| 1672 | | } |
| 1673 | | |
| 1674 | | static UINT32 dilate1(UINT32 value,int bits) // dilate first "bits" bits in "value" |
| 1675 | | { |
| 1676 | | UINT32 x,m1,m2,m3; |
| 1677 | | int a; |
| 1678 | | |
| 1679 | | x = value; |
| 1680 | | for (a=0;a < bits;a++) |
| 1681 | | { |
| 1682 | | m2 = 1 << (a << 1); |
| 1683 | | m1 = m2 - 1; |
| 1684 | | m3 = (~m1) << 1; |
| 1685 | | x = (x & m1) + ((x & m2) << 1) + ((x & m3) << 1); |
| 1686 | | } |
| 1687 | | return x; |
| 1688 | | } |
| 1689 | | |
| 1690 | | static void computedilated(void) |
| 1691 | | { |
| 1692 | | int a,b; |
| 1693 | | |
| 1694 | | for (b=0;b <= 14;b++) |
| 1695 | | for (a=0;a < 1024;a++) { |
| 1696 | | dilated0[b][a]=dilate0(a,b); |
| 1697 | | dilated1[b][a]=dilate1(a,b); |
| 1698 | | } |
| 1699 | | for (b=0;b <= 7;b++) |
| 1700 | | for (a=0;a <= 7;a++) |
| 1701 | | dilatechose[(b << 3) + a]=3+(a < b ? a : b); |
| 1702 | | } |
| 1703 | | |
| 1704 | | static void render_hline(running_machine &machine,bitmap_rgb32 &bitmap, texinfo *ti, int y, float xl, float xr, float ul, float ur, float vl, float vr, float wl, float wr) |
| 1705 | | { |
| 1706 | | dc_state *state = machine.driver_data<dc_state>(); |
| 1707 | | int xxl, xxr; |
| 1708 | | float dx, ddx, dudx, dvdx, dwdx; |
| 1709 | | UINT32 *tdata; |
| 1710 | | float *wbufline; |
| 1711 | | |
| 1712 | | // untextured cases aren't handled |
| 1713 | | if (!ti->textured) return; |
| 1714 | | |
| 1715 | | if(xr < 0 || xl >= 640) |
| 1716 | | return; |
| 1717 | | |
| 1718 | | xxl = round(xl); |
| 1719 | | xxr = round(xr); |
| 1720 | | |
| 1721 | | if(xxl == xxr) |
| 1722 | | return; |
| 1723 | | |
| 1724 | | dx = xr-xl; |
| 1725 | | dudx = (ur-ul)/dx; |
| 1726 | | dvdx = (vr-vl)/dx; |
| 1727 | | dwdx = (wr-wl)/dx; |
| 1728 | | |
| 1729 | | if(xxl < 0) |
| 1730 | | xxl = 0; |
| 1731 | | if(xxr > 640) |
| 1732 | | xxr = 640; |
| 1733 | | |
| 1734 | | // Target the pixel center |
| 1735 | | ddx = xxl + 0.5 - xl; |
| 1736 | | ul += ddx*dudx; |
| 1737 | | vl += ddx*dvdx; |
| 1738 | | wl += ddx*dwdx; |
| 1739 | | |
| 1740 | | |
| 1741 | | tdata = &bitmap.pix32(y, xxl); |
| 1742 | | wbufline = &wbuffer[y][xxl]; |
| 1743 | | |
| 1744 | | while(xxl < xxr) { |
| 1745 | | if((wl >= *wbufline)) { |
| 1746 | | UINT32 c; |
| 1747 | | float u = ul/wl; |
| 1748 | | float v = vl/wl; |
| 1749 | | |
| 1750 | | /* |
| 1751 | | if(ti->flip_u) |
| 1752 | | { |
| 1753 | | u = ti->sizex - u; |
| 1754 | | } |
| 1755 | | |
| 1756 | | if(ti->flip_v) |
| 1757 | | { |
| 1758 | | v = ti->sizey - v; |
| 1759 | | }*/ |
| 1760 | | |
| 1761 | | c = ti->r(machine, ti, u, v); |
| 1762 | | |
| 1763 | | // debug dip to turn on/off bilinear filtering, it's slooooow |
| 1764 | | if (state->debug_dip_status&0x1) |
| 1765 | | { |
| 1766 | | if(ti->filter_mode >= TEX_FILTER_BILINEAR) |
| 1767 | | { |
| 1768 | | UINT32 c1 = ti->r(machine, ti, u+1.0, v); |
| 1769 | | UINT32 c2 = ti->r(machine, ti, u+1.0, v+1.0); |
| 1770 | | UINT32 c3 = ti->r(machine, ti, u, v+1.0); |
| 1771 | | c = bilinear_filter(c, c1, c2, c3, u, v); |
| 1772 | | } |
| 1773 | | } |
| 1774 | | |
| 1775 | | if(c & 0xff000000) { |
| 1776 | | *tdata = ti->blend(c, *tdata); |
| 1777 | | *wbufline = wl; |
| 1778 | | } |
| 1779 | | } |
| 1780 | | wbufline++; |
| 1781 | | tdata++; |
| 1782 | | |
| 1783 | | ul += dudx; |
| 1784 | | vl += dvdx; |
| 1785 | | wl += dwdx; |
| 1786 | | xxl ++; |
| 1787 | | } |
| 1788 | | } |
| 1789 | | |
| 1790 | | static void render_span(running_machine &machine, bitmap_rgb32 &bitmap, texinfo *ti, |
| 1791 | | float y0, float y1, |
| 1792 | | float xl, float xr, |
| 1793 | | float ul, float ur, |
| 1794 | | float vl, float vr, |
| 1795 | | float wl, float wr, |
| 1796 | | float dxldy, float dxrdy, |
| 1797 | | float duldy, float durdy, |
| 1798 | | float dvldy, float dvrdy, |
| 1799 | | float dwldy, float dwrdy) |
| 1800 | | { |
| 1801 | | float dy; |
| 1802 | | int yy0, yy1; |
| 1803 | | |
| 1804 | | if(y1 <= 0) |
| 1805 | | return; |
| 1806 | | if(y1 > 480) |
| 1807 | | y1 = 480; |
| 1808 | | |
| 1809 | | if(y0 < 0) { |
| 1810 | | xl += -dxldy*y0; |
| 1811 | | xr += -dxrdy*y0; |
| 1812 | | ul += -duldy*y0; |
| 1813 | | ur += -durdy*y0; |
| 1814 | | vl += -dvldy*y0; |
| 1815 | | vr += -dvrdy*y0; |
| 1816 | | wl += -dwldy*y0; |
| 1817 | | wr += -dwrdy*y0; |
| 1818 | | y0 = 0; |
| 1819 | | } |
| 1820 | | |
| 1821 | | yy0 = round(y0); |
| 1822 | | yy1 = round(y1); |
| 1823 | | |
| 1824 | | if((yy0 < 0 && y0 > 0) || (yy1 < 0 && y1 > 0)) //temp handling of int32 overflow, needed by hotd2/totd |
| 1825 | | return; |
| 1826 | | |
| 1827 | | dy = yy0+0.5-y0; |
| 1828 | | |
| 1829 | | if(0) |
| 1830 | | fprintf(stderr, "%f %f %f %f -> %f %f | %f %f -> %f %f\n", |
| 1831 | | y0, |
| 1832 | | dy, dxldy, dxrdy, dy*dxldy, dy*dxrdy, |
| 1833 | | xl, xr, xl + dy*dxldy, xr + dy*dxrdy); |
| 1834 | | xl += dy*dxldy; |
| 1835 | | xr += dy*dxrdy; |
| 1836 | | ul += dy*duldy; |
| 1837 | | ur += dy*durdy; |
| 1838 | | vl += dy*dvldy; |
| 1839 | | vr += dy*dvrdy; |
| 1840 | | wl += dy*dwldy; |
| 1841 | | wr += dy*dwrdy; |
| 1842 | | |
| 1843 | | while(yy0 < yy1) { |
| 1844 | | render_hline(machine, bitmap, ti, yy0, xl, xr, ul, ur, vl, vr, wl, wr); |
| 1845 | | |
| 1846 | | xl += dxldy; |
| 1847 | | xr += dxrdy; |
| 1848 | | ul += duldy; |
| 1849 | | ur += durdy; |
| 1850 | | vl += dvldy; |
| 1851 | | vr += dvrdy; |
| 1852 | | wl += dwldy; |
| 1853 | | wr += dwrdy; |
| 1854 | | yy0 ++; |
| 1855 | | } |
| 1856 | | } |
| 1857 | | |
| 1858 | | static void sort_vertices(const vert *v, int *i0, int *i1, int *i2) |
| 1859 | | { |
| 1860 | | float miny, maxy; |
| 1861 | | int imin, imax, imid; |
| 1862 | | miny = maxy = v[0].y; |
| 1863 | | imin = imax = 0; |
| 1864 | | |
| 1865 | | if(miny > v[1].y) { |
| 1866 | | miny = v[1].y; |
| 1867 | | imin = 1; |
| 1868 | | } else if(maxy < v[1].y) { |
| 1869 | | maxy = v[1].y; |
| 1870 | | imax = 1; |
| 1871 | | } |
| 1872 | | |
| 1873 | | if(miny > v[2].y) { |
| 1874 | | miny = v[2].y; |
| 1875 | | imin = 2; |
| 1876 | | } else if(maxy < v[2].y) { |
| 1877 | | maxy = v[2].y; |
| 1878 | | imax = 2; |
| 1879 | | } |
| 1880 | | |
| 1881 | | imid = (imin == 0 || imax == 0) ? (imin == 1 || imax == 1) ? 2 : 1 : 0; |
| 1882 | | |
| 1883 | | *i0 = imin; |
| 1884 | | *i1 = imid; |
| 1885 | | *i2 = imax; |
| 1886 | | } |
| 1887 | | |
| 1888 | | |
| 1889 | | static void render_tri_sorted(running_machine &machine, bitmap_rgb32 &bitmap, texinfo *ti, const vert *v0, const vert *v1, const vert *v2) |
| 1890 | | { |
| 1891 | | float dy01, dy02, dy12; |
| 1892 | | // float dy; // unused, compiler complains about this |
| 1893 | | |
| 1894 | | float dx01dy, dx02dy, dx12dy, du01dy, du02dy, du12dy, dv01dy, dv02dy, dv12dy, dw01dy, dw02dy, dw12dy; |
| 1895 | | |
| 1896 | | if(v0->y >= 480 || v2->y < 0) |
| 1897 | | return; |
| 1898 | | |
| 1899 | | dy01 = v1->y - v0->y; |
| 1900 | | dy02 = v2->y - v0->y; |
| 1901 | | dy12 = v2->y - v1->y; |
| 1902 | | |
| 1903 | | dx01dy = dy01 ? (v1->x-v0->x)/dy01 : 0; |
| 1904 | | dx02dy = dy02 ? (v2->x-v0->x)/dy02 : 0; |
| 1905 | | dx12dy = dy12 ? (v2->x-v1->x)/dy12 : 0; |
| 1906 | | |
| 1907 | | du01dy = dy01 ? (v1->u-v0->u)/dy01 : 0; |
| 1908 | | du02dy = dy02 ? (v2->u-v0->u)/dy02 : 0; |
| 1909 | | du12dy = dy12 ? (v2->u-v1->u)/dy12 : 0; |
| 1910 | | |
| 1911 | | dv01dy = dy01 ? (v1->v-v0->v)/dy01 : 0; |
| 1912 | | dv02dy = dy02 ? (v2->v-v0->v)/dy02 : 0; |
| 1913 | | dv12dy = dy12 ? (v2->v-v1->v)/dy12 : 0; |
| 1914 | | |
| 1915 | | dw01dy = dy01 ? (v1->w-v0->w)/dy01 : 0; |
| 1916 | | dw02dy = dy02 ? (v2->w-v0->w)/dy02 : 0; |
| 1917 | | dw12dy = dy12 ? (v2->w-v1->w)/dy12 : 0; |
| 1918 | | |
| 1919 | | if(!dy01) { |
| 1920 | | if(!dy12) |
| 1921 | | return; |
| 1922 | | |
| 1923 | | if(v1->x > v0->x) |
| 1924 | | render_span(machine, bitmap, ti, v1->y, v2->y, v0->x, v1->x, v0->u, v1->u, v0->v, v1->v, v0->w, v1->w, dx02dy, dx12dy, du02dy, du12dy, dv02dy, dv12dy, dw02dy, dw12dy); |
| 1925 | | else |
| 1926 | | render_span(machine, bitmap, ti, v1->y, v2->y, v1->x, v0->x, v1->u, v0->u, v1->v, v0->v, v1->w, v0->w, dx12dy, dx02dy, du12dy, du02dy, dv12dy, dv02dy, dw12dy, dw02dy); |
| 1927 | | |
| 1928 | | } else if(!dy12) { |
| 1929 | | if(v2->x > v1->x) |
| 1930 | | render_span(machine, bitmap, ti, v0->y, v1->y, v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, dx01dy, dx02dy, du01dy, du02dy, dv01dy, dv02dy, dw01dy, dw02dy); |
| 1931 | | else |
| 1932 | | render_span(machine, bitmap, ti, v0->y, v1->y, v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, dx02dy, dx01dy, du02dy, du01dy, dv02dy, dv01dy, dw02dy, dw01dy); |
| 1933 | | |
| 1934 | | } else { |
| 1935 | | if(dx01dy < dx02dy) { |
| 1936 | | render_span(machine, bitmap, ti, v0->y, v1->y, |
| 1937 | | v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, |
| 1938 | | dx01dy, dx02dy, du01dy, du02dy, dv01dy, dv02dy, dw01dy, dw02dy); |
| 1939 | | render_span(machine, bitmap, ti, v1->y, v2->y, |
| 1940 | | v1->x, v0->x + dx02dy*dy01, v1->u, v0->u + du02dy*dy01, v1->v, v0->v + dv02dy*dy01, v1->w, v0->w + dw02dy*dy01, |
| 1941 | | dx12dy, dx02dy, du12dy, du02dy, dv12dy, dv02dy, dw12dy, dw02dy); |
| 1942 | | } else { |
| 1943 | | render_span(machine, bitmap, ti, v0->y, v1->y, |
| 1944 | | v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, |
| 1945 | | dx02dy, dx01dy, du02dy, du01dy, dv02dy, dv01dy, dw02dy, dw01dy); |
| 1946 | | render_span(machine, bitmap, ti, v1->y, v2->y, |
| 1947 | | v0->x + dx02dy*dy01, v1->x, v0->u + du02dy*dy01, v1->u, v0->v + dv02dy*dy01, v1->v, v0->w + dw02dy*dy01, v1->w, |
| 1948 | | dx02dy, dx12dy, du02dy, du12dy, dv02dy, dv12dy, dw02dy, dw12dy); |
| 1949 | | } |
| 1950 | | } |
| 1951 | | } |
| 1952 | | |
| 1953 | | static void render_tri(running_machine &machine, bitmap_rgb32 &bitmap, texinfo *ti, const vert *v) |
| 1954 | | { |
| 1955 | | int i0, i1, i2; |
| 1956 | | |
| 1957 | | sort_vertices(v, &i0, &i1, &i2); |
| 1958 | | render_tri_sorted(machine, bitmap, ti, v+i0, v+i1, v+i2); |
| 1959 | | } |
| 1960 | | |
| 1961 | | static void render_to_accumulation_buffer(running_machine &machine,bitmap_rgb32 &bitmap,const rectangle &cliprect) |
| 1962 | | { |
| 1963 | | dc_state *state = machine.driver_data<dc_state>(); |
| 1964 | | address_space &space = state->m_maincpu->space(AS_PROGRAM); |
| 1965 | | int cs,rs,ns; |
| 1966 | | UINT32 c; |
| 1967 | | #if 0 |
| 1968 | | int stride; |
| 1969 | | UINT16 *bmpaddr16; |
| 1970 | | UINT32 k; |
| 1971 | | #endif |
| 1972 | | |
| 1973 | | |
| 1974 | | if (state_ta.renderselect < 0) |
| 1975 | | return; |
| 1976 | | |
| 1977 | | //printf("drawtest!\n"); |
| 1978 | | |
| 1979 | | rs=state_ta.renderselect; |
| 1980 | | c=state->pvrta_regs[ISP_BACKGND_T]; |
| 1981 | | c=space.read_dword(0x05000000+((c&0xfffff8)>>1)+(3+3)*4); |
| 1982 | | bitmap.fill(c, cliprect); |
| 1983 | | |
| 1984 | | |
| 1985 | | ns=state_ta.grab[rs].strips_size; |
| 1986 | | if(ns) |
| 1987 | | memset(wbuffer, 0x00, sizeof(wbuffer)); |
| 1988 | | |
| 1989 | | for (cs=0;cs < ns;cs++) |
| 1990 | | { |
| 1991 | | strip *ts = &state_ta.grab[rs].strips[cs]; |
| 1992 | | int sv = ts->svert; |
| 1993 | | int ev = ts->evert; |
| 1994 | | int i; |
| 1995 | | if(ev == -1) |
| 1996 | | continue; |
| 1997 | | |
| 1998 | | for(i=sv; i <= ev; i++) |
| 1999 | | { |
| 2000 | | vert *tv = state_ta.grab[rs].verts + i; |
| 2001 | | tv->u = tv->u * ts->ti.sizex * tv->w; |
| 2002 | | tv->v = tv->v * ts->ti.sizey * tv->w; |
| 2003 | | } |
| 2004 | | |
| 2005 | | for(i=sv; i <= ev-2; i++) |
| 2006 | | { |
| 2007 | | if (!(state->debug_dip_status&0x2)) |
| 2008 | | render_tri(machine, bitmap, &ts->ti, state_ta.grab[rs].verts + i); |
| 2009 | | |
| 2010 | | } |
| 2011 | | } |
| 2012 | | state_ta.grab[rs].busy=0; |
| 2013 | | } |
| 2014 | | |
| 2015 | | // copies the accumulation buffer into the framebuffer, converting to the specified format |
| 2016 | | // not accurate, ignores field stuff and just uses SOF1 for now |
| 2017 | | // also ignores scale effects (can scale accumulation buffer to half size with filtering etc.) |
| 2018 | | // also can specify dither etc. |
| 2019 | | // basically, just a crude implementation! |
| 2020 | | |
| 2021 | | /* |
| 2022 | | |
| 2023 | | 0x0 0555 KRGB 16 bit (default) Bit 15 is the value of fb_kval 7. |
| 2024 | | 0x1 565 RGB 16 bit |
| 2025 | | 0x2 4444 ARGB 16 bit |
| 2026 | | 0x3 1555 ARGB 16 bit The alpha value is determined by comparison with the value of fb_alpha_threshold. |
| 2027 | | 0x4 888 RGB 24 bit packed |
| 2028 | | 0x5 0888 KRGB 32 bit K is the value of fk_kval. |
| 2029 | | 0x6 8888 ARGB 32 bit |
| 2030 | | 0x7 Setting prohibited. |
| 2031 | | |
| 2032 | | */ |
| 2033 | | |
| 2034 | | static void pvr_accumulationbuffer_to_framebuffer(address_space &space, int x,int y) |
| 2035 | | { |
| 2036 | | dc_state *state = space.machine().driver_data<dc_state>(); |
| 2037 | | |
| 2038 | | // the accumulation buffer is always 8888 |
| 2039 | | // |
| 2040 | | // the standard format for the framebuffer appears to be 565 |
| 2041 | | // yes, this means colour data is lost in the conversion |
| 2042 | | |
| 2043 | | UINT32 wc = state->pvrta_regs[FB_W_CTRL]; |
| 2044 | | UINT32 stride = state->pvrta_regs[FB_W_LINESTRIDE]; |
| 2045 | | UINT32 writeoffs = state->pvrta_regs[FB_W_SOF1]; |
| 2046 | | |
| 2047 | | UINT32* src; |
| 2048 | | |
| 2049 | | |
| 2050 | | UINT8 packmode = wc & 0x7; |
| 2051 | | |
| 2052 | | switch (packmode) |
| 2053 | | { |
| 2054 | | // used by ringout |
| 2055 | | case 0x00: //0555 KRGB |
| 2056 | | { |
| 2057 | | int xcnt,ycnt; |
| 2058 | | for (ycnt=0;ycnt<32;ycnt++) |
| 2059 | | { |
| 2060 | | UINT32 realwriteoffs = 0x05000000 + writeoffs + (y+ycnt) * (stride<<3) + (x*2); |
| 2061 | | src = &fake_accumulationbuffer_bitmap->pix32(y+ycnt, x); |
| 2062 | | |
| 2063 | | |
| 2064 | | for (xcnt=0;xcnt<32;xcnt++) |
| 2065 | | { |
| 2066 | | // data starts in 8888 format, downsample it |
| 2067 | | UINT32 data = src[xcnt]; |
| 2068 | | UINT16 newdat = ((((data & 0x000000f8) >> 3)) << 0) | |
| 2069 | | ((((data & 0x0000f800) >> 11)) << 5) | |
| 2070 | | ((((data & 0x00f80000) >> 19)) << 10); |
| 2071 | | |
| 2072 | | space.write_word(realwriteoffs+xcnt*2, newdat); |
| 2073 | | } |
| 2074 | | } |
| 2075 | | } |
| 2076 | | break; |
| 2077 | | |
| 2078 | | // used by cleoftp |
| 2079 | | case 0x01: //565 RGB 16 bit |
| 2080 | | { |
| 2081 | | int xcnt,ycnt; |
| 2082 | | for (ycnt=0;ycnt<32;ycnt++) |
| 2083 | | { |
| 2084 | | UINT32 realwriteoffs = 0x05000000 + writeoffs + (y+ycnt) * (stride<<3) + (x*2); |
| 2085 | | src = &fake_accumulationbuffer_bitmap->pix32(y+ycnt, x); |
| 2086 | | |
| 2087 | | |
| 2088 | | for (xcnt=0;xcnt<32;xcnt++) |
| 2089 | | { |
| 2090 | | // data starts in 8888 format, downsample it |
| 2091 | | UINT32 data = src[xcnt]; |
| 2092 | | UINT16 newdat = ((((data & 0x000000f8) >> 3)) << 0) | |
| 2093 | | ((((data & 0x0000fc00) >> 10)) << 5) | |
| 2094 | | ((((data & 0x00f80000) >> 19)) << 11); |
| 2095 | | |
| 2096 | | space.write_word(realwriteoffs+xcnt*2, newdat); |
| 2097 | | } |
| 2098 | | } |
| 2099 | | } |
| 2100 | | break; |
| 2101 | | |
| 2102 | | case 0x02: |
| 2103 | | printf("pvr_accumulationbuffer_to_framebuffer buffer to tile at %d,%d - unsupported pack mode %02x (4444 ARGB)\n",x,y,packmode); |
| 2104 | | break; |
| 2105 | | |
| 2106 | | case 0x03: // 1555 ARGB 16 bit |
| 2107 | | { |
| 2108 | | int xcnt,ycnt; |
| 2109 | | for (ycnt=0;ycnt<32;ycnt++) |
| 2110 | | { |
| 2111 | | UINT32 realwriteoffs = 0x05000000 + writeoffs + (y+ycnt) * (stride<<3) + (x*2); |
| 2112 | | src = &fake_accumulationbuffer_bitmap->pix32(y+ycnt, x); |
| 2113 | | |
| 2114 | | |
| 2115 | | for (xcnt=0;xcnt<32;xcnt++) |
| 2116 | | { |
| 2117 | | // data starts in 8888 format, downsample it |
| 2118 | | UINT32 data = src[xcnt]; |
| 2119 | | UINT16 newdat = ((((data & 0x000000f8) >> 3)) << 0) | |
| 2120 | | ((((data & 0x0000f800) >> 11)) << 5) | |
| 2121 | | ((((data & 0x00f80000) >> 19)) << 10); |
| 2122 | | // alpha? |
| 2123 | | |
| 2124 | | space.write_word(realwriteoffs+xcnt*2, newdat); |
| 2125 | | } |
| 2126 | | } |
| 2127 | | } |
| 2128 | | break; |
| 2129 | | |
| 2130 | | // used by Suchie3 |
| 2131 | | case 0x04: // 888 RGB 24-bit (HACK! should not downconvert and pvr_drawframebuffer should change accordingly) |
| 2132 | | { |
| 2133 | | int xcnt,ycnt; |
| 2134 | | for (ycnt=0;ycnt<32;ycnt++) |
| 2135 | | { |
| 2136 | | UINT32 realwriteoffs = 0x05000000 + writeoffs + (y+ycnt) * (stride<<3) + (x*2); |
| 2137 | | src = &fake_accumulationbuffer_bitmap->pix32(y+ycnt, x); |
| 2138 | | |
| 2139 | | |
| 2140 | | for (xcnt=0;xcnt<32;xcnt++) |
| 2141 | | { |
| 2142 | | // data is 8888 format |
| 2143 | | UINT32 data = src[xcnt]; |
| 2144 | | UINT16 newdat = ((((data & 0x000000f8) >> 3)) << 0) | |
| 2145 | | ((((data & 0x0000fc00) >> 10)) << 5) | |
| 2146 | | ((((data & 0x00f80000) >> 19)) << 11); |
| 2147 | | |
| 2148 | | space.write_word(realwriteoffs+xcnt*2, newdat); |
| 2149 | | } |
| 2150 | | } |
| 2151 | | } |
| 2152 | | break; |
| 2153 | | |
| 2154 | | case 0x05: |
| 2155 | | printf("pvr_accumulationbuffer_to_framebuffer buffer to tile at %d,%d - unsupported pack mode %02x (0888 KGB 32-bit)\n",x,y,packmode); |
| 2156 | | break; |
| 2157 | | |
| 2158 | | case 0x06: // 8888 ARGB 32 bit (HACK! should not downconvert and pvr_drawframebuffer should change accordingly) |
| 2159 | | { |
| 2160 | | int xcnt,ycnt; |
| 2161 | | for (ycnt=0;ycnt<32;ycnt++) |
| 2162 | | { |
| 2163 | | UINT32 realwriteoffs = 0x05000000 + writeoffs + (y+ycnt) * (stride<<3) + (x*2); |
| 2164 | | src = &fake_accumulationbuffer_bitmap->pix32(y+ycnt, x); |
| 2165 | | |
| 2166 | | |
| 2167 | | for (xcnt=0;xcnt<32;xcnt++) |
| 2168 | | { |
| 2169 | | // data is 8888 format |
| 2170 | | UINT32 data = src[xcnt]; |
| 2171 | | UINT16 newdat = ((((data & 0x000000f8) >> 3)) << 0) | |
| 2172 | | ((((data & 0x0000fc00) >> 10)) << 5) | |
| 2173 | | ((((data & 0x00f80000) >> 19)) << 11); |
| 2174 | | |
| 2175 | | space.write_word(realwriteoffs+xcnt*2, newdat); |
| 2176 | | } |
| 2177 | | } |
| 2178 | | } |
| 2179 | | break; |
| 2180 | | |
| 2181 | | case 0x07: |
| 2182 | | printf("pvr_accumulationbuffer_to_framebuffer buffer to tile at %d,%d - unsupported pack mode %02x (Reserved! Don't Use!)\n",x,y,packmode); |
| 2183 | | break; |
| 2184 | | } |
| 2185 | | |
| 2186 | | |
| 2187 | | } |
| 2188 | | |
| 2189 | | |
| 2190 | | static void pvr_drawframebuffer(running_machine &machine,bitmap_rgb32 &bitmap,const rectangle &cliprect) |
| 2191 | | { |
| 2192 | | dc_state *state = machine.driver_data<dc_state>(); |
| 2193 | | |
| 2194 | | int x,y,dy,xi; |
| 2195 | | UINT32 addrp; |
| 2196 | | UINT32 *fbaddr; |
| 2197 | | UINT32 c; |
| 2198 | | UINT32 r,g,b; |
| 2199 | | |
| 2200 | | UINT32 wc = state->pvrta_regs[FB_R_CTRL]; |
| 2201 | | UINT8 unpackmode = (wc & 0x0000000c) >>2; // aka fb_depth |
| 2202 | | UINT8 enable = (wc & 0x00000001); |
| 2203 | | |
| 2204 | | // ?? |
| 2205 | | if (!enable) return; |
| 2206 | | |
| 2207 | | // only for rgb565 framebuffer |
| 2208 | | xi=((state->pvrta_regs[FB_R_SIZE] & 0x3ff)+1) << 1; |
| 2209 | | dy=((state->pvrta_regs[FB_R_SIZE] >> 10) & 0x3ff)+1; |
| 2210 | | |
| 2211 | | dy++; |
| 2212 | | dy*=2; // probably depends on interlace mode, fields etc... |
| 2213 | | |
| 2214 | | switch (unpackmode) |
| 2215 | | { |
| 2216 | | case 0x00: // 0555 RGB 16-bit, Cleo Fortune Plus |
| 2217 | | // should upsample back to 8-bit output using fb_concat |
| 2218 | | for (y=0;y <= dy;y++) |
| 2219 | | { |
| 2220 | | addrp=state->pvrta_regs[FB_R_SOF1]+y*xi*2; |
| 2221 | | if(spg_pixel_double) |
| 2222 | | { |
| 2223 | | for (x=0;x < xi;x++) |
| 2224 | | { |
| 2225 | | fbaddr=&bitmap.pix32(y, x*2+0); |
| 2226 | | c=*((reinterpret_cast<UINT16 *>(state->dc_framebuffer_ram.target())) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2227 | | |
| 2228 | | b = (c & 0x001f) << 3; |
| 2229 | | g = (c & 0x03e0) >> 2; |
| 2230 | | r = (c & 0x7c00) >> 7; |
| 2231 | | |
| 2232 | | if (y<=cliprect.max_y) |
| 2233 | | *fbaddr = b | (g<<8) | (r<<16); |
| 2234 | | |
| 2235 | | fbaddr=&bitmap.pix32(y, x*2+1); |
| 2236 | | if (y<=cliprect.max_y) |
| 2237 | | *fbaddr = b | (g<<8) | (r<<16); |
| 2238 | | addrp+=2; |
| 2239 | | } |
| 2240 | | } |
| 2241 | | else |
| 2242 | | { |
| 2243 | | for (x=0;x < xi;x++) |
| 2244 | | { |
| 2245 | | fbaddr=&bitmap.pix32(y, x); |
| 2246 | | c=*((reinterpret_cast<UINT16 *>(state->dc_framebuffer_ram.target())) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2247 | | |
| 2248 | | b = (c & 0x001f) << 3; |
| 2249 | | g = (c & 0x03e0) >> 2; |
| 2250 | | r = (c & 0x7c00) >> 7; |
| 2251 | | |
| 2252 | | if (y<=cliprect.max_y) |
| 2253 | | *fbaddr = b | (g<<8) | (r<<16); |
| 2254 | | addrp+=2; |
| 2255 | | } |
| 2256 | | } |
| 2257 | | } |
| 2258 | | |
| 2259 | | break; |
| 2260 | | case 0x01: // 0565 RGB 16-bit |
| 2261 | | // should upsample back to 8-bit output using fb_concat |
| 2262 | | for (y=0;y <= dy;y++) |
| 2263 | | { |
| 2264 | | addrp=state->pvrta_regs[FB_R_SOF1]+y*xi*2; |
| 2265 | | if(spg_pixel_double) |
| 2266 | | { |
| 2267 | | for (x=0;x < xi;x++) |
| 2268 | | { |
| 2269 | | fbaddr=&bitmap.pix32(y, x*2+0); |
| 2270 | | c=*((reinterpret_cast<UINT16 *>(state->dc_framebuffer_ram.target())) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2271 | | |
| 2272 | | b = (c & 0x001f) << 3; |
| 2273 | | g = (c & 0x07e0) >> 3; |
| 2274 | | r = (c & 0xf800) >> 8; |
| 2275 | | |
| 2276 | | if (y<=cliprect.max_y) |
| 2277 | | *fbaddr = b | (g<<8) | (r<<16); |
| 2278 | | |
| 2279 | | fbaddr=&bitmap.pix32(y, x*2+1); |
| 2280 | | |
| 2281 | | if (y<=cliprect.max_y) |
| 2282 | | *fbaddr = b | (g<<8) | (r<<16); |
| 2283 | | |
| 2284 | | addrp+=2; |
| 2285 | | } |
| 2286 | | } |
| 2287 | | else |
| 2288 | | { |
| 2289 | | for (x=0;x < xi;x++) |
| 2290 | | { |
| 2291 | | fbaddr=&bitmap.pix32(y, x); |
| 2292 | | c=*((reinterpret_cast<UINT16 *>(state->dc_framebuffer_ram.target())) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2293 | | |
| 2294 | | b = (c & 0x001f) << 3; |
| 2295 | | g = (c & 0x07e0) >> 3; |
| 2296 | | r = (c & 0xf800) >> 8; |
| 2297 | | |
| 2298 | | if (y<=cliprect.max_y) |
| 2299 | | *fbaddr = b | (g<<8) | (r<<16); |
| 2300 | | addrp+=2; |
| 2301 | | } |
| 2302 | | } |
| 2303 | | } |
| 2304 | | break; |
| 2305 | | |
| 2306 | | case 0x02: ; // 888 RGB 24-bit - suchie3 - HACKED, see pvr_accumulationbuffer_to_framebuffer! |
| 2307 | | for (y=0;y <= dy;y++) |
| 2308 | | { |
| 2309 | | addrp=state->pvrta_regs[FB_R_SOF1]+y*xi*2; |
| 2310 | | if(spg_pixel_double) |
| 2311 | | { |
| 2312 | | for (x=0;x < xi;x++) |
| 2313 | | { |
| 2314 | | fbaddr=&bitmap.pix32(y, x*2+0); |
| 2315 | | c=*((reinterpret_cast<UINT16 *>(state->dc_framebuffer_ram.target())) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2316 | | |
| 2317 | | b = (c & 0x001f) << 3; |
| 2318 | | g = (c & 0x07e0) >> 3; |
| 2319 | | r = (c & 0xf800) >> 8; |
| 2320 | | |
| 2321 | | if (y<=cliprect.max_y) |
| 2322 | | *fbaddr = b | (g<<8) | (r<<16); |
| 2323 | | |
| 2324 | | fbaddr=&bitmap.pix32(y, x*2+1); |
| 2325 | | |
| 2326 | | if (y<=cliprect.max_y) |
| 2327 | | *fbaddr = b | (g<<8) | (r<<16); |
| 2328 | | addrp+=2; |
| 2329 | | } |
| 2330 | | } |
| 2331 | | else |
| 2332 | | { |
| 2333 | | for (x=0;x < xi;x++) |
| 2334 | | { |
| 2335 | | fbaddr=&bitmap.pix32(y, x); |
| 2336 | | c=*((reinterpret_cast<UINT16 *>(state->dc_framebuffer_ram.target())) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2337 | | |
| 2338 | | b = (c & 0x001f) << 3; |
| 2339 | | g = (c & 0x07e0) >> 3; |
| 2340 | | r = (c & 0xf800) >> 8; |
| 2341 | | |
| 2342 | | if (y<=cliprect.max_y) |
| 2343 | | *fbaddr = b | (g<<8) | (r<<16); |
| 2344 | | addrp+=2; |
| 2345 | | } |
| 2346 | | } |
| 2347 | | } |
| 2348 | | break; |
| 2349 | | |
| 2350 | | case 0x03: // 0888 ARGB 32-bit - HACKED, see pvr_accumulationbuffer_to_framebuffer! |
| 2351 | | for (y=0;y <= dy;y++) |
| 2352 | | { |
| 2353 | | addrp=state->pvrta_regs[FB_R_SOF1]+y*xi*2; |
| 2354 | | if(spg_pixel_double) |
| 2355 | | { |
| 2356 | | for (x=0;x < xi;x++) |
| 2357 | | { |
| 2358 | | fbaddr=&bitmap.pix32(y, x*2+0); |
| 2359 | | c=*((reinterpret_cast<UINT16 *>(state->dc_framebuffer_ram.target())) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2360 | | |
| 2361 | | b = (c & 0x001f) << 3; |
| 2362 | | g = (c & 0x07e0) >> 3; |
| 2363 | | r = (c & 0xf800) >> 8; |
| 2364 | | |
| 2365 | | if (y<=cliprect.max_y) |
| 2366 | | *fbaddr = b | (g<<8) | (r<<16); |
| 2367 | | |
| 2368 | | fbaddr=&bitmap.pix32(y, x*2+1); |
| 2369 | | if (y<=cliprect.max_y) |
| 2370 | | *fbaddr = b | (g<<8) | (r<<16); |
| 2371 | | |
| 2372 | | addrp+=2; |
| 2373 | | } |
| 2374 | | } |
| 2375 | | else |
| 2376 | | { |
| 2377 | | for (x=0;x < xi;x++) |
| 2378 | | { |
| 2379 | | fbaddr=&bitmap.pix32(y, x); |
| 2380 | | c=*((reinterpret_cast<UINT16 *>(state->dc_framebuffer_ram.target())) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2381 | | |
| 2382 | | b = (c & 0x001f) << 3; |
| 2383 | | g = (c & 0x07e0) >> 3; |
| 2384 | | r = (c & 0xf800) >> 8; |
| 2385 | | |
| 2386 | | if (y<=cliprect.max_y) |
| 2387 | | *fbaddr = b | (g<<8) | (r<<16); |
| 2388 | | addrp+=2; |
| 2389 | | } |
| 2390 | | } |
| 2391 | | } |
| 2392 | | break; |
| 2393 | | } |
| 2394 | | } |
| 2395 | | |
| 2396 | | |
| 2397 | | #if DEBUG_PALRAM |
| 2398 | | static void debug_paletteram(running_machine &machine) |
| 2399 | | { |
| 2400 | | dc_state *state = machine.driver_data<dc_state>(); |
| 2401 | | |
| 2402 | | UINT64 pal; |
| 2403 | | UINT32 r,g,b; |
| 2404 | | int i; |
| 2405 | | |
| 2406 | | //popmessage("%02x",state->pvrta_regs[PAL_RAM_CTRL]); |
| 2407 | | |
| 2408 | | for(i=0;i<0x400;i++) |
| 2409 | | { |
| 2410 | | pal = state->pvrta_regs[((0x005F9000-0x005F8000)/4)+i]; |
| 2411 | | switch(state->pvrta_regs[PAL_RAM_CTRL]) |
| 2412 | | { |
| 2413 | | case 0: //argb1555 <- guilty gear uses this mode |
| 2414 | | { |
| 2415 | | //a = (pal & 0x8000)>>15; |
| 2416 | | r = (pal & 0x7c00)>>10; |
| 2417 | | g = (pal & 0x03e0)>>5; |
| 2418 | | b = (pal & 0x001f)>>0; |
| 2419 | | //a = a ? 0xff : 0x00; |
| 2420 | | palette_set_color_rgb(machine, i, pal5bit(r), pal5bit(g), pal5bit(b)); |
| 2421 | | } |
| 2422 | | break; |
| 2423 | | case 1: //rgb565 |
| 2424 | | { |
| 2425 | | //a = 0xff; |
| 2426 | | r = (pal & 0xf800)>>11; |
| 2427 | | g = (pal & 0x07e0)>>5; |
| 2428 | | b = (pal & 0x001f)>>0; |
| 2429 | | palette_set_color_rgb(machine, i, pal5bit(r), pal6bit(g), pal5bit(b)); |
| 2430 | | } |
| 2431 | | break; |
| 2432 | | case 2: //argb4444 |
| 2433 | | { |
| 2434 | | //a = (pal & 0xf000)>>12; |
| 2435 | | r = (pal & 0x0f00)>>8; |
| 2436 | | g = (pal & 0x00f0)>>4; |
| 2437 | | b = (pal & 0x000f)>>0; |
| 2438 | | palette_set_color_rgb(machine, i, pal4bit(r), pal4bit(g), pal4bit(b)); |
| 2439 | | } |
| 2440 | | break; |
| 2441 | | case 3: //argb8888 |
| 2442 | | { |
| 2443 | | //a = (pal & 0xff000000)>>20; |
| 2444 | | r = (pal & 0x00ff0000)>>16; |
| 2445 | | g = (pal & 0x0000ff00)>>8; |
| 2446 | | b = (pal & 0x000000ff)>>0; |
| 2447 | | palette_set_color_rgb(machine, i, r, g, b); |
| 2448 | | } |
| 2449 | | break; |
| 2450 | | } |
| 2451 | | } |
| 2452 | | } |
| 2453 | | #endif |
| 2454 | | |
| 2455 | | /* test video end */ |
| 2456 | | |
| 2457 | | static void pvr_build_parameterconfig(void) |
| 2458 | | { |
| 2459 | | int a,b,c,d,e,p; |
| 2460 | | |
| 2461 | | for (a = 0;a <= 63;a++) |
| 2462 | | pvr_parameterconfig[a] = -1; |
| 2463 | | p=0; |
| 2464 | | // volume,col_type,texture,offset,16bit_uv |
| 2465 | | for (a = 0;a <= 1;a++) |
| 2466 | | for (b = 0;b <= 3;b++) |
| 2467 | | for (c = 0;c <= 1;c++) |
| 2468 | | if (c == 0) |
| 2469 | | { |
| 2470 | | for (d = 0;d <= 1;d++) |
| 2471 | | for (e = 0;e <= 1;e++) |
| 2472 | | pvr_parameterconfig[(a << 6) | (b << 4) | (c << 3) | (d << 2) | (e << 0)] = pvr_parconfseq[p]; |
| 2473 | | p++; |
| 2474 | | } |
| 2475 | | else |
| 2476 | | for (d = 0;d <= 1;d++) |
| 2477 | | for (e = 0;e <= 1;e++) |
| 2478 | | { |
| 2479 | | pvr_parameterconfig[(a << 6) | (b << 4) | (c << 3) | (d << 2) | (e << 0)] = pvr_parconfseq[p]; |
| 2480 | | p++; |
| 2481 | | } |
| 2482 | | for (a = 1;a <= 63;a++) |
| 2483 | | if (pvr_parameterconfig[a] < 0) |
| 2484 | | pvr_parameterconfig[a] = pvr_parameterconfig[a-1]; |
| 2485 | | } |
| 2486 | | |
| 2487 | | TIMER_CALLBACK_MEMBER(dc_state::vbin) |
| 2488 | | { |
| 2489 | | dc_state *state = machine().driver_data<dc_state>(); |
| 2490 | | |
| 2491 | | dc_sysctrl_regs[SB_ISTNRM] |= IST_VBL_IN; // V Blank-in interrupt |
| 2492 | | dc_update_interrupt_status(); |
| 2493 | | |
| 2494 | | vbin_timer->adjust(machine().primary_screen->time_until_pos(spg_vblank_in_irq_line_num)); |
| 2495 | | } |
| 2496 | | |
| 2497 | | TIMER_CALLBACK_MEMBER(dc_state::vbout) |
| 2498 | | { |
| 2499 | | dc_state *state = machine().driver_data<dc_state>(); |
| 2500 | | |
| 2501 | | dc_sysctrl_regs[SB_ISTNRM] |= IST_VBL_OUT; // V Blank-out interrupt |
| 2502 | | dc_update_interrupt_status(); |
| 2503 | | |
| 2504 | | vbout_timer->adjust(machine().primary_screen->time_until_pos(spg_vblank_out_irq_line_num)); |
| 2505 | | } |
| 2506 | | |
| 2507 | | TIMER_CALLBACK_MEMBER(dc_state::hbin) |
| 2508 | | { |
| 2509 | | dc_state *state = machine().driver_data<dc_state>(); |
| 2510 | | |
| 2511 | | if(spg_hblank_int_mode & 1) |
| 2512 | | { |
| 2513 | | if(scanline == next_y) |
| 2514 | | { |
| 2515 | | dc_sysctrl_regs[SB_ISTNRM] |= IST_HBL_IN; // H Blank-in interrupt |
| 2516 | | dc_update_interrupt_status(); |
| 2517 | | next_y+=spg_line_comp_val; |
| 2518 | | } |
| 2519 | | } |
| 2520 | | else if((scanline == spg_line_comp_val) || (spg_hblank_int_mode & 2)) |
| 2521 | | { |
| 2522 | | dc_sysctrl_regs[SB_ISTNRM] |= IST_HBL_IN; // H Blank-in interrupt |
| 2523 | | dc_update_interrupt_status(); |
| 2524 | | } |
| 2525 | | |
| 2526 | | // printf("hbin on scanline %d\n",scanline); |
| 2527 | | |
| 2528 | | scanline++; |
| 2529 | | |
| 2530 | | if(scanline >= spg_vblank_in_irq_line_num) |
| 2531 | | { |
| 2532 | | scanline = 0; |
| 2533 | | next_y = spg_line_comp_val; |
| 2534 | | } |
| 2535 | | |
| 2536 | | hbin_timer->adjust(machine().primary_screen->time_until_pos(scanline, spg_hblank_in_irq-1)); |
| 2537 | | } |
| 2538 | | |
| 2539 | | |
| 2540 | | |
| 2541 | | TIMER_CALLBACK_MEMBER(dc_state::endofrender_video) |
| 2542 | | { |
| 2543 | | dc_sysctrl_regs[SB_ISTNRM] |= IST_EOR_VIDEO;// VIDEO end of render |
| 2544 | | dc_update_interrupt_status(); |
| 2545 | | endofrender_timer_video->adjust(attotime::never); |
| 2546 | | } |
| 2547 | | |
| 2548 | | TIMER_CALLBACK_MEMBER(dc_state::endofrender_tsp) |
| 2549 | | { |
| 2550 | | dc_sysctrl_regs[SB_ISTNRM] |= IST_EOR_TSP; // TSP end of render |
| 2551 | | dc_update_interrupt_status(); |
| 2552 | | |
| 2553 | | endofrender_timer_tsp->adjust(attotime::never); |
| 2554 | | endofrender_timer_video->adjust(attotime::from_usec(500) ); |
| 2555 | | } |
| 2556 | | |
| 2557 | | TIMER_CALLBACK_MEMBER(dc_state::endofrender_isp) |
| 2558 | | { |
| 2559 | | dc_sysctrl_regs[SB_ISTNRM] |= IST_EOR_ISP; // ISP end of render |
| 2560 | | dc_update_interrupt_status(); |
| 2561 | | |
| 2562 | | endofrender_timer_isp->adjust(attotime::never); |
| 2563 | | endofrender_timer_tsp->adjust(attotime::from_usec(500) ); |
| 2564 | | } |
| 2565 | | |
| 2566 | | |
| 2567 | | void dc_state::video_start() |
| 2568 | | { |
| 2569 | | memset(pvrctrl_regs, 0, sizeof(pvrctrl_regs)); |
| 2570 | | memset(pvrta_regs, 0, sizeof(pvrta_regs)); |
| 2571 | | memset(state_ta.grab, 0, sizeof(state_ta.grab)); |
| 2572 | | pvr_build_parameterconfig(); |
| 2573 | | |
| 2574 | | // if the next 2 registers do not have the correct values, the naomi bios will hang |
| 2575 | | pvrta_regs[PVRID]=0x17fd11db; |
| 2576 | | pvrta_regs[REVISION]=0x11; |
| 2577 | | /* FIXME: move the following regs inside MACHINE_RESET */ |
| 2578 | | pvrta_regs[VO_CONTROL]= 0x00000108; |
| 2579 | | pvrta_regs[SOFTRESET]= 0x00000007; |
| 2580 | | pvrta_regs[VO_STARTX]= 0x0000009d; |
| 2581 | | pvrta_regs[VO_STARTY]= 0x00150015; |
| 2582 | | pvrta_regs[SPG_HBLANK]= 0x007e0345; |
| 2583 | | pvrta_regs[SPG_LOAD]= 0x01060359; |
| 2584 | | pvrta_regs[SPG_VBLANK]= 0x01500104; |
| 2585 | | pvrta_regs[SPG_HBLANK_INT]= 0x031d0000; |
| 2586 | | pvrta_regs[SPG_VBLANK_INT]= 0x01500104; |
| 2587 | | |
| 2588 | | state_ta.tafifo_pos=0; |
| 2589 | | state_ta.tafifo_mask=7; |
| 2590 | | state_ta.tafifo_vertexwords=8; |
| 2591 | | state_ta.tafifo_listtype= -1; |
| 2592 | | state_ta.start_render_received=0; |
| 2593 | | state_ta.renderselect= -1; |
| 2594 | | state_ta.grabsel=0; |
| 2595 | | |
| 2596 | | computedilated(); |
| 2597 | | |
| 2598 | | vbout_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(dc_state::vbout),this)); |
| 2599 | | vbout_timer->adjust(machine().primary_screen->time_until_pos(spg_vblank_out_irq_line_num_new)); |
| 2600 | | |
| 2601 | | vbin_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(dc_state::vbin),this)); |
| 2602 | | vbin_timer->adjust(machine().primary_screen->time_until_pos(spg_vblank_in_irq_line_num_new)); |
| 2603 | | |
| 2604 | | hbin_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(dc_state::hbin),this)); |
| 2605 | | hbin_timer->adjust(machine().primary_screen->time_until_pos(0, spg_hblank_in_irq_new-1)); |
| 2606 | | |
| 2607 | | scanline = 0; |
| 2608 | | next_y = 0; |
| 2609 | | |
| 2610 | | endofrender_timer_isp = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(dc_state::endofrender_isp),this)); |
| 2611 | | endofrender_timer_tsp = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(dc_state::endofrender_tsp),this)); |
| 2612 | | endofrender_timer_video = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(dc_state::endofrender_video),this)); |
| 2613 | | |
| 2614 | | endofrender_timer_isp->adjust(attotime::never); |
| 2615 | | endofrender_timer_tsp->adjust(attotime::never); |
| 2616 | | endofrender_timer_video->adjust(attotime::never); |
| 2617 | | |
| 2618 | | fake_accumulationbuffer_bitmap = auto_bitmap_rgb32_alloc(machine(),1024,1024); |
| 2619 | | |
| 2620 | | } |
| 2621 | | |
| 2622 | | UINT32 dc_state::screen_update_dc(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| 2623 | | { |
| 2624 | | /****************** |
| 2625 | | MAME note |
| 2626 | | ******************* |
| 2627 | | |
| 2628 | | The video update function should NOT be generating interrupts, setting timers or doing _anything_ the game might be able to detect |
| 2629 | | as it will be called at different times depending on frameskip etc. |
| 2630 | | |
| 2631 | | Rendering should happen when the hardware requests it, to the framebuffer(s) |
| 2632 | | |
| 2633 | | Everything else should depend on timers. |
| 2634 | | |
| 2635 | | ******************/ |
| 2636 | | |
| 2637 | | // static int useframebuffer=1; |
| 2638 | | // const rectangle &visarea = screen.visible_area(); |
| 2639 | | // int y,x; |
| 2640 | | |
| 2641 | | #if DEBUG_PALRAM |
| 2642 | | debug_paletteram(machine()); |
| 2643 | | #endif |
| 2644 | | |
| 2645 | | // copy our fake framebuffer bitmap (where things have been rendered) to the screen |
| 2646 | | #if 0 |
| 2647 | | for (y = visarea->min_y ; y <= visarea->max_y ; y++) |
| 2648 | | { |
| 2649 | | for (x = visarea->min_x ; x <= visarea->max_x ; x++) |
| 2650 | | { |
| 2651 | | UINT32* src = &fake_accumulationbuffer_bitmap->pix32(y, x); |
| 2652 | | UINT32* dst = &bitmap.pix32(y, x); |
| 2653 | | dst[0] = src[0]; |
| 2654 | | } |
| 2655 | | } |
| 2656 | | #endif |
| 2657 | | |
| 2658 | | bitmap.fill(MAKE_ARGB(0xff,vo_border_R,vo_border_G,vo_border_B), cliprect); //FIXME: Chroma bit? |
| 2659 | | |
| 2660 | | if(!spg_blank_video) |
| 2661 | | pvr_drawframebuffer(machine(),bitmap,cliprect); |
| 2662 | | |
| 2663 | | // update this here so we only do string lookup once per frame |
| 2664 | | debug_dip_status = ioport("MAMEDEBUG")->read(); |
| 2665 | | |
| 2666 | | return 0; |
| 2667 | | } |
| 2668 | | |
| 2669 | | |
| 2670 | | /* Naomi 2 attempts (TBD) */ |
| 2671 | | |
| 2672 | | READ64_HANDLER( pvr2_ta_r ) |
| 2673 | | { |
| 2674 | | int reg; |
| 2675 | | UINT64 shift; |
| 2676 | | |
| 2677 | | reg = decode_reg_64(offset, mem_mask, &shift); |
| 2678 | | |
| 2679 | | switch (reg) |
| 2680 | | { |
| 2681 | | } |
| 2682 | | |
| 2683 | | printf("PVR2 %08x R\n",reg); |
| 2684 | | |
| 2685 | | return 0; |
| 2686 | | } |
| 2687 | | |
| 2688 | | WRITE64_HANDLER( pvr2_ta_w ) |
| 2689 | | { |
| 2690 | | // int reg; |
| 2691 | | // UINT64 shift; |
| 2692 | | // UINT32 dat; |
| 2693 | | |
| 2694 | | // reg = decode_reg_64(offset, mem_mask, &shift); |
| 2695 | | // dat = (UINT32)(data >> shift); |
| 2696 | | |
| 2697 | | //printf("PVR2 %08x %08x\n",reg,dat); |
| 2698 | | } |
| 2699 | | |
| 2700 | | READ32_HANDLER( elan_regs_r ) |
| 2701 | | { |
| 2702 | | switch(offset) |
| 2703 | | { |
| 2704 | | case 0x00/4: // ID chip (TODO: BIOS crashes / gives a black screen with this as per now!) |
| 2705 | | return 0xe1ad0000; |
| 2706 | | case 0x04/4: // REVISION |
| 2707 | | return 0x12; //or 0x01? |
| 2708 | | case 0x10/4: // SH4 interface control (???) |
| 2709 | | /* ---- -x-- enable second PVR */ |
| 2710 | | /* ---- --x- elan has channel 2 */ |
| 2711 | | /* ---- ---x broadcast on cs1 (?) */ |
| 2712 | | return 6; |
| 2713 | | case 0x14/4: // SDRAM refresh register |
| 2714 | | return 0x2029; //default 0x1429 |
| 2715 | | case 0x1c/4: // SDRAM CFG |
| 2716 | | return 0xa7320961; //default 0xa7320961 |
| 2717 | | case 0x30/4: // Macro tiler configuration, bit 0 is enable |
| 2718 | | return 0; |
| 2719 | | case 0x74/4: // IRQ STAT |
| 2720 | | return 0; |
| 2721 | | case 0x78/4: // IRQ MASK |
| 2722 | | return 0; |
| 2723 | | default: |
| 2724 | | printf("%08x %08x\n",space.device().safe_pc(),offset*4); |
| 2725 | | break; |
| 2726 | | } |
| 2727 | | |
| 2728 | | return 0; |
| 2729 | | } |
| 2730 | | |
| 2731 | | WRITE32_HANDLER( elan_regs_w ) |
| 2732 | | { |
| 2733 | | switch(offset) |
| 2734 | | { |
| 2735 | | default: |
| 2736 | | printf("%08x %08x %08x W\n",space.device().safe_pc(),offset*4,data); |
| 2737 | | break; |
| 2738 | | } |
| 2739 | | } |
| 2740 | | |
| 2741 | | |
| 2742 | | WRITE64_HANDLER( pvrs_ta_w ) |
| 2743 | | { |
| 2744 | | pvr_ta_w(space,offset,data,mem_mask); |
| 2745 | | pvr2_ta_w(space,offset,data,mem_mask); |
| 2746 | | //printf("PVR2 %08x %08x\n",reg,dat); |
| 2747 | | } |
trunk/src/mame/video/powervr2.c
| r0 | r23535 | |
| 1 | /* |
| 2 | dc.c - Dreamcast video emulation |
| 3 | |
| 4 | */ |
| 5 | |
| 6 | #include "emu.h" |
| 7 | #include "powervr2.h" |
| 8 | #include "includes/dc.h" |
| 9 | #include "cpu/sh4/sh4.h" |
| 10 | #include "render.h" |
| 11 | #include "rendutil.h" |
| 12 | #include "video/rgbutil.h" |
| 13 | |
| 14 | const device_type POWERVR2 = &device_creator<powervr2_device>; |
| 15 | |
| 16 | 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}; |
| 17 | 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}; |
| 18 | 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}; |
| 19 | |
| 20 | #define DEBUG_FIFO_POLY (0) |
| 21 | #define DEBUG_PVRTA (0) |
| 22 | #define DEBUG_PVRTA_REGS (0) |
| 23 | #define DEBUG_PVRDLIST (0) |
| 24 | #define DEBUG_PALRAM (1) |
| 25 | #define DEBUG_PVRCTRL (0) |
| 26 | |
| 27 | /* PVR TA macro defines */ |
| 28 | /* |
| 29 | SPG_HBLANK_INT |
| 30 | ---- --xx xxxx xxxx ---- ---- ---- ---- hblank_in_interrupt |
| 31 | ---- ---- ---- ---- --xx ---- ---- ---- hblank_int_mode |
| 32 | ---- ---- ---- ---- ---- --xx xxxx xxxx line_comp_val |
| 33 | */ |
| 34 | #define spg_hblank_in_irq ((pvrta_regs[SPG_HBLANK_INT] & 0x03ff0000) >> 16) |
| 35 | #define spg_hblank_in_irq_new ((pvrta_regs[SPG_HBLANK_INT] & 0x03ff0000) >> 16) |
| 36 | #define spg_hblank_int_mode ((pvrta_regs[SPG_HBLANK_INT] & 0x00003000) >> 12) |
| 37 | #define spg_line_comp_val ((pvrta_regs[SPG_HBLANK_INT] & 0x000003ff) >> 0) |
| 38 | |
| 39 | /* |
| 40 | SPG_VBLANK_INT |
| 41 | ---- --xx xxxx xxxx ---- ---- ---- ---- vblank_out_interrupt_line_number |
| 42 | ---- ---- ---- ---- ---- --xx xxxx xxxx vblank_in_interrupt_line_number |
| 43 | */ |
| 44 | #define spg_vblank_out_irq_line_num ((pvrta_regs[SPG_VBLANK_INT] & 0x03ff0000) >> 16) |
| 45 | #define spg_vblank_in_irq_line_num ((pvrta_regs[SPG_VBLANK_INT] & 0x000003ff) >> 0) |
| 46 | #define spg_vblank_out_irq_line_num_new ((pvrta_regs[SPG_VBLANK_INT] & 0x03ff0000) >> 16) |
| 47 | #define spg_vblank_in_irq_line_num_new ((pvrta_regs[SPG_VBLANK_INT] & 0x000003ff) >> 0) |
| 48 | |
| 49 | |
| 50 | /* |
| 51 | VO_BORDER_COL |
| 52 | ---- ---x ---- ---- ---- ---- ---- ---- Chroma ;suchie3 sets 0xff there, maybe it's 8 bits too? |
| 53 | ---- ---- xxxx xxxx ---- ---- ---- ---- Red |
| 54 | ---- ---- ---- ---- xxxx xxxx ---- ---- Green |
| 55 | ---- ---- ---- ---- ---- ---- xxxx xxxx Blue |
| 56 | */ |
| 57 | #define vo_border_K ((pvrta_regs[VO_BORDER_COL] & 0x01000000) >> 24) |
| 58 | #define vo_border_R ((pvrta_regs[VO_BORDER_COL] & 0x00ff0000) >> 16) |
| 59 | #define vo_border_G ((pvrta_regs[VO_BORDER_COL] & 0x0000ff00) >> 8) |
| 60 | #define vo_border_B ((pvrta_regs[VO_BORDER_COL] & 0x000000ff) >> 0) |
| 61 | |
| 62 | /* |
| 63 | SPG_HBLANK |
| 64 | ---- ---- --xx xxxx xxxx ---- ---- ---- hbend |
| 65 | ---- ---- ---- ---- ---- --xx xxxx xxxx hbstart |
| 66 | */ |
| 67 | #define spg_hbend ((pvrta_regs[SPG_HBLANK] & 0x03ff0000) >> 16) |
| 68 | #define spg_hbstart ((pvrta_regs[SPG_HBLANK] & 0x000003ff) >> 0) |
| 69 | |
| 70 | |
| 71 | /* |
| 72 | SPG_LOAD |
| 73 | ---- ---- --xx xxxx xxxx ---- ---- ---- vcount |
| 74 | ---- ---- ---- ---- ---- --xx xxxx xxxx hcount |
| 75 | */ |
| 76 | #define spg_vcount ((pvrta_regs[SPG_LOAD] & 0x03ff0000) >> 16) |
| 77 | #define spg_hcount ((pvrta_regs[SPG_LOAD] & 0x000003ff) >> 0) |
| 78 | |
| 79 | /* |
| 80 | SPG_VBLANK |
| 81 | ---- ---- --xx xxxx xxxx ---- ---- ---- vbend |
| 82 | ---- ---- ---- ---- ---- --xx xxxx xxxx vbstart |
| 83 | */ |
| 84 | #define spg_vbend ((pvrta_regs[SPG_VBLANK] & 0x03ff0000) >> 16) |
| 85 | #define spg_vbstart ((pvrta_regs[SPG_VBLANK] & 0x000003ff) >> 0) |
| 86 | |
| 87 | |
| 88 | /* |
| 89 | VO_CONTROL |
| 90 | ---- ---- --xx xxxx ---- ---- ---- ---- pclk_delay |
| 91 | ---- ---- ---- ---- ---- ---x ---- ---- pixel_double ;used in test mode |
| 92 | ---- ---- ---- ---- ---- ---- xxxx ---- field_mode |
| 93 | ---- ---- ---- ---- ---- ---- ---- x--- blank_video |
| 94 | ---- ---- ---- ---- ---- ---- ---- -x-- blank_pol |
| 95 | ---- ---- ---- ---- ---- ---- ---- --x- vsync_pol |
| 96 | ---- ---- ---- ---- ---- ---- ---- ---x hsync_pol |
| 97 | */ |
| 98 | #define spg_pclk_delay ((pvrta_regs[VO_CONTROL] & 0x003f0000) >> 16) |
| 99 | #define spg_pixel_double ((pvrta_regs[VO_CONTROL] & 0x00000100) >> 8) |
| 100 | #define spg_field_mode ((pvrta_regs[VO_CONTROL] & 0x000000f0) >> 4) |
| 101 | #define spg_blank_video ((pvrta_regs[VO_CONTROL] & 0x00000008) >> 3) |
| 102 | #define spg_blank_pol ((pvrta_regs[VO_CONTROL] & 0x00000004) >> 2) |
| 103 | #define spg_vsync_pol ((pvrta_regs[VO_CONTROL] & 0x00000002) >> 1) |
| 104 | #define spg_hsync_pol ((pvrta_regs[VO_CONTROL] & 0x00000001) >> 0) |
| 105 | |
| 106 | /* |
| 107 | VO_STARTX |
| 108 | ---- ---- ---- ---- ---- ---x xxxx xxxx horzontal start position |
| 109 | */ |
| 110 | #define vo_horz_start_pos ((pvrta_regs[VO_STARTX] & 0x000003ff) >> 0) |
| 111 | |
| 112 | /* |
| 113 | VO_STARTY |
| 114 | ---- ---x xxxx xxxx ---- ---- ---- ---- vertical start position on field 2 |
| 115 | ---- ---- ---- ---- ---- ---x xxxx xxxx vertical start position on field 1 |
| 116 | */ |
| 117 | |
| 118 | #define vo_vert_start_pos_f2 ((pvrta_regs[VO_STARTY] & 0x03ff0000) >> 16) |
| 119 | #define vo_vert_start_pos_f1 ((pvrta_regs[VO_STARTY] & 0x000003ff) >> 0) |
| 120 | |
| 121 | /* |
| 122 | SPG_STATUS |
| 123 | ---- ---- ---- ---- --x- ---- ---- ---- vsync |
| 124 | ---- ---- ---- ---- ---x ---- ---- ---- hsync |
| 125 | ---- ---- ---- ---- ---- x--- ---- ---- blank |
| 126 | ---- ---- ---- ---- ---- -x-- ---- ---- field number |
| 127 | ---- ---- ---- ---- ---- --xx xxxx xxxx state->scanline |
| 128 | */ |
| 129 | |
| 130 | |
| 131 | // Perform a standard bilinear filter across four pixels |
| 132 | inline INT32 powervr2_device::clamp(INT32 in, INT32 min, INT32 max) |
| 133 | { |
| 134 | if(in < min) return min; |
| 135 | if(in > max) return max; |
| 136 | return in; |
| 137 | } |
| 138 | |
| 139 | inline UINT32 powervr2_device::bilinear_filter(UINT32 c0, UINT32 c1, UINT32 c2, UINT32 c3, float u, float v) |
| 140 | { |
| 141 | UINT32 ui = (u * 256.0); |
| 142 | UINT32 vi = (v * 256.0); |
| 143 | return rgba_bilinear_filter(c0, c1, c3, c2, ui, vi); |
| 144 | } |
| 145 | |
| 146 | // Multiply with alpha value in bits 31-24 |
| 147 | inline UINT32 powervr2_device::bla(UINT32 c, UINT32 a) |
| 148 | { |
| 149 | a = a >> 24; |
| 150 | return ((((c & 0xff00ff)*a) & 0xff00ff00) >> 8) | ((((c >> 8) & 0xff00ff)*a) & 0xff00ff00); |
| 151 | } |
| 152 | |
| 153 | // Multiply with 1-alpha value in bits 31-24 |
| 154 | inline UINT32 powervr2_device::blia(UINT32 c, UINT32 a) |
| 155 | { |
| 156 | a = 0x100 - (a >> 24); |
| 157 | return ((((c & 0xff00ff)*a) & 0xff00ff00) >> 8) | ((((c >> 8) & 0xff00ff)*a) & 0xff00ff00); |
| 158 | } |
| 159 | |
| 160 | // Per-component multiply with color value |
| 161 | inline UINT32 powervr2_device::blc(UINT32 c1, UINT32 c2) |
| 162 | { |
| 163 | UINT32 cr = |
| 164 | (((c1 & 0x000000ff)*(c2 & 0x000000ff) & 0x0000ff00) >> 8) | |
| 165 | (((c1 & 0x0000ff00)*(c2 & 0x0000ff00) & 0x00ff0000) >> 8); |
| 166 | c1 >>= 16; |
| 167 | c2 >>= 16; |
| 168 | cr |= |
| 169 | (((c1 & 0x000000ff)*(c2 & 0x000000ff) & 0x0000ff00) << 8) | |
| 170 | (((c1 & 0x0000ff00)*(c2 & 0x0000ff00) & 0x00ff0000) << 8); |
| 171 | return cr; |
| 172 | } |
| 173 | |
| 174 | // Per-component multiply with 1-color value |
| 175 | inline UINT32 powervr2_device::blic(UINT32 c1, UINT32 c2) |
| 176 | { |
| 177 | UINT32 cr = |
| 178 | (((c1 & 0x000000ff)*(0x00100-(c2 & 0x000000ff)) & 0x0000ff00) >> 8) | |
| 179 | (((c1 & 0x0000ff00)*(0x10000-(c2 & 0x0000ff00)) & 0x00ff0000) >> 8); |
| 180 | c1 >>= 16; |
| 181 | c2 >>= 16; |
| 182 | cr |= |
| 183 | (((c1 & 0x000000ff)*(0x00100-(c2 & 0x000000ff)) & 0x0000ff00) << 8) | |
| 184 | (((c1 & 0x0000ff00)*(0x10000-(c2 & 0x0000ff00)) & 0x00ff0000) << 8); |
| 185 | return cr; |
| 186 | } |
| 187 | |
| 188 | // Add two colors with saturation |
| 189 | inline UINT32 powervr2_device::bls(UINT32 c1, UINT32 c2) |
| 190 | { |
| 191 | UINT32 cr1, cr2; |
| 192 | cr1 = (c1 & 0x00ff00ff) + (c2 & 0x00ff00ff); |
| 193 | if(cr1 & 0x0000ff00) |
| 194 | cr1 = (cr1 & 0xffff00ff) | 0x000000ff; |
| 195 | if(cr1 & 0xff000000) |
| 196 | cr1 = (cr1 & 0x00ffffff) | 0x00ff0000; |
| 197 | |
| 198 | cr2 = ((c1 >> 8) & 0x00ff00ff) + ((c2 >> 8) & 0x00ff00ff); |
| 199 | if(cr2 & 0x0000ff00) |
| 200 | cr2 = (cr2 & 0xffff00ff) | 0x000000ff; |
| 201 | if(cr2 & 0xff000000) |
| 202 | cr2 = (cr2 & 0x00ffffff) | 0x00ff0000; |
| 203 | return cr1|(cr2 << 8); |
| 204 | } |
| 205 | |
| 206 | // All 64 blending modes, 3 top bits are source mode, 3 bottom bits are destination mode |
| 207 | UINT32 powervr2_device::bl00(UINT32 s, UINT32 d) { return 0; } |
| 208 | UINT32 powervr2_device::bl01(UINT32 s, UINT32 d) { return d; } |
| 209 | UINT32 powervr2_device::bl02(UINT32 s, UINT32 d) { return blc(d, s); } |
| 210 | UINT32 powervr2_device::bl03(UINT32 s, UINT32 d) { return blic(d, s); } |
| 211 | UINT32 powervr2_device::bl04(UINT32 s, UINT32 d) { return bla(d, s); } |
| 212 | UINT32 powervr2_device::bl05(UINT32 s, UINT32 d) { return blia(d, s); } |
| 213 | UINT32 powervr2_device::bl06(UINT32 s, UINT32 d) { return bla(d, d); } |
| 214 | UINT32 powervr2_device::bl07(UINT32 s, UINT32 d) { return blia(d, d); } |
| 215 | UINT32 powervr2_device::bl10(UINT32 s, UINT32 d) { return s; } |
| 216 | UINT32 powervr2_device::bl11(UINT32 s, UINT32 d) { return bls(s, d); } |
| 217 | UINT32 powervr2_device::bl12(UINT32 s, UINT32 d) { return bls(s, blc(s, d)); } |
| 218 | UINT32 powervr2_device::bl13(UINT32 s, UINT32 d) { return bls(s, blic(s, d)); } |
| 219 | UINT32 powervr2_device::bl14(UINT32 s, UINT32 d) { return bls(s, bla(d, s)); } |
| 220 | UINT32 powervr2_device::bl15(UINT32 s, UINT32 d) { return bls(s, blia(d, s)); } |
| 221 | UINT32 powervr2_device::bl16(UINT32 s, UINT32 d) { return bls(s, bla(d, d)); } |
| 222 | UINT32 powervr2_device::bl17(UINT32 s, UINT32 d) { return bls(s, blia(d, d)); } |
| 223 | UINT32 powervr2_device::bl20(UINT32 s, UINT32 d) { return blc(d, s); } |
| 224 | UINT32 powervr2_device::bl21(UINT32 s, UINT32 d) { return bls(blc(d, s), d); } |
| 225 | UINT32 powervr2_device::bl22(UINT32 s, UINT32 d) { return bls(blc(d, s), blc(s, d)); } |
| 226 | UINT32 powervr2_device::bl23(UINT32 s, UINT32 d) { return bls(blc(d, s), blic(s, d)); } |
| 227 | UINT32 powervr2_device::bl24(UINT32 s, UINT32 d) { return bls(blc(d, s), bla(d, s)); } |
| 228 | UINT32 powervr2_device::bl25(UINT32 s, UINT32 d) { return bls(blc(d, s), blia(d, s)); } |
| 229 | UINT32 powervr2_device::bl26(UINT32 s, UINT32 d) { return bls(blc(d, s), bla(d, d)); } |
| 230 | UINT32 powervr2_device::bl27(UINT32 s, UINT32 d) { return bls(blc(d, s), blia(d, d)); } |
| 231 | UINT32 powervr2_device::bl30(UINT32 s, UINT32 d) { return blic(d, s); } |
| 232 | UINT32 powervr2_device::bl31(UINT32 s, UINT32 d) { return bls(blic(d, s), d); } |
| 233 | UINT32 powervr2_device::bl32(UINT32 s, UINT32 d) { return bls(blic(d, s), blc(s, d)); } |
| 234 | UINT32 powervr2_device::bl33(UINT32 s, UINT32 d) { return bls(blic(d, s), blic(s, d)); } |
| 235 | UINT32 powervr2_device::bl34(UINT32 s, UINT32 d) { return bls(blic(d, s), bla(d, s)); } |
| 236 | UINT32 powervr2_device::bl35(UINT32 s, UINT32 d) { return bls(blic(d, s), blia(d, s)); } |
| 237 | UINT32 powervr2_device::bl36(UINT32 s, UINT32 d) { return bls(blic(d, s), bla(d, d)); } |
| 238 | UINT32 powervr2_device::bl37(UINT32 s, UINT32 d) { return bls(blic(d, s), blia(d, d)); } |
| 239 | UINT32 powervr2_device::bl40(UINT32 s, UINT32 d) { return bla(s, s); } |
| 240 | UINT32 powervr2_device::bl41(UINT32 s, UINT32 d) { return bls(bla(s, s), d); } |
| 241 | UINT32 powervr2_device::bl42(UINT32 s, UINT32 d) { return bls(bla(s, s), blc(s, d)); } |
| 242 | UINT32 powervr2_device::bl43(UINT32 s, UINT32 d) { return bls(bla(s, s), blic(s, d)); } |
| 243 | UINT32 powervr2_device::bl44(UINT32 s, UINT32 d) { return bls(bla(s, s), bla(d, s)); } |
| 244 | UINT32 powervr2_device::bl45(UINT32 s, UINT32 d) { return bls(bla(s, s), blia(d, s)); } |
| 245 | UINT32 powervr2_device::bl46(UINT32 s, UINT32 d) { return bls(bla(s, s), bla(d, d)); } |
| 246 | UINT32 powervr2_device::bl47(UINT32 s, UINT32 d) { return bls(bla(s, s), blia(d, d)); } |
| 247 | UINT32 powervr2_device::bl50(UINT32 s, UINT32 d) { return blia(s, s); } |
| 248 | UINT32 powervr2_device::bl51(UINT32 s, UINT32 d) { return bls(blia(s, s), d); } |
| 249 | UINT32 powervr2_device::bl52(UINT32 s, UINT32 d) { return bls(blia(s, s), blc(s, d)); } |
| 250 | UINT32 powervr2_device::bl53(UINT32 s, UINT32 d) { return bls(blia(s, s), blic(s, d)); } |
| 251 | UINT32 powervr2_device::bl54(UINT32 s, UINT32 d) { return bls(blia(s, s), bla(d, s)); } |
| 252 | UINT32 powervr2_device::bl55(UINT32 s, UINT32 d) { return bls(blia(s, s), blia(d, s)); } |
| 253 | UINT32 powervr2_device::bl56(UINT32 s, UINT32 d) { return bls(blia(s, s), bla(d, d)); } |
| 254 | UINT32 powervr2_device::bl57(UINT32 s, UINT32 d) { return bls(blia(s, s), blia(d, d)); } |
| 255 | UINT32 powervr2_device::bl60(UINT32 s, UINT32 d) { return bla(s, d); } |
| 256 | UINT32 powervr2_device::bl61(UINT32 s, UINT32 d) { return bls(bla(s, d), d); } |
| 257 | UINT32 powervr2_device::bl62(UINT32 s, UINT32 d) { return bls(bla(s, d), blc(s, d)); } |
| 258 | UINT32 powervr2_device::bl63(UINT32 s, UINT32 d) { return bls(bla(s, d), blic(s, d)); } |
| 259 | UINT32 powervr2_device::bl64(UINT32 s, UINT32 d) { return bls(bla(s, d), bla(d, s)); } |
| 260 | UINT32 powervr2_device::bl65(UINT32 s, UINT32 d) { return bls(bla(s, d), blia(d, s)); } |
| 261 | UINT32 powervr2_device::bl66(UINT32 s, UINT32 d) { return bls(bla(s, d), bla(d, d)); } |
| 262 | UINT32 powervr2_device::bl67(UINT32 s, UINT32 d) { return bls(bla(s, d), blia(d, d)); } |
| 263 | UINT32 powervr2_device::bl70(UINT32 s, UINT32 d) { return blia(s, d); } |
| 264 | UINT32 powervr2_device::bl71(UINT32 s, UINT32 d) { return bls(blia(s, d), d); } |
| 265 | UINT32 powervr2_device::bl72(UINT32 s, UINT32 d) { return bls(blia(s, d), blc(s, d)); } |
| 266 | UINT32 powervr2_device::bl73(UINT32 s, UINT32 d) { return bls(blia(s, d), blic(s, d)); } |
| 267 | UINT32 powervr2_device::bl74(UINT32 s, UINT32 d) { return bls(blia(s, d), bla(d, s)); } |
| 268 | UINT32 powervr2_device::bl75(UINT32 s, UINT32 d) { return bls(blia(s, d), blia(d, s)); } |
| 269 | UINT32 powervr2_device::bl76(UINT32 s, UINT32 d) { return bls(blia(s, d), bla(d, d)); } |
| 270 | UINT32 powervr2_device::bl77(UINT32 s, UINT32 d) { return bls(blia(s, d), blia(d, d)); } |
| 271 | |
| 272 | UINT32 (*const powervr2_device::blend_functions[64])(UINT32 s, UINT32 d) = { |
| 273 | bl00, bl01, bl02, bl03, bl04, bl05, bl06, bl07, |
| 274 | bl10, bl11, bl12, bl13, bl14, bl15, bl16, bl17, |
| 275 | bl20, bl21, bl22, bl23, bl24, bl25, bl26, bl27, |
| 276 | bl30, bl31, bl32, bl33, bl34, bl35, bl36, bl37, |
| 277 | bl40, bl41, bl42, bl43, bl44, bl45, bl46, bl47, |
| 278 | bl50, bl51, bl52, bl53, bl54, bl55, bl56, bl57, |
| 279 | bl60, bl61, bl62, bl63, bl64, bl65, bl66, bl67, |
| 280 | bl70, bl71, bl72, bl73, bl74, bl75, bl76, bl77, |
| 281 | }; |
| 282 | |
| 283 | inline UINT32 powervr2_device::cv_1555(UINT16 c) |
| 284 | { |
| 285 | return |
| 286 | (c & 0x8000 ? 0xff000000 : 0) | |
| 287 | ((c << 9) & 0x00f80000) | ((c << 4) & 0x00070000) | |
| 288 | ((c << 6) & 0x0000f800) | ((c << 1) & 0x00000700) | |
| 289 | ((c << 3) & 0x000000f8) | ((c >> 2) & 0x00000007); |
| 290 | } |
| 291 | |
| 292 | inline UINT32 powervr2_device::cv_1555z(UINT16 c) |
| 293 | { |
| 294 | return |
| 295 | (c & 0x8000 ? 0xff000000 : 0) | |
| 296 | ((c << 9) & 0x00f80000) | |
| 297 | ((c << 6) & 0x0000f800) | |
| 298 | ((c << 3) & 0x000000f8); |
| 299 | } |
| 300 | |
| 301 | inline UINT32 powervr2_device::cv_565(UINT16 c) |
| 302 | { |
| 303 | return |
| 304 | 0xff000000 | |
| 305 | ((c << 8) & 0x00f80000) | ((c << 3) & 0x00070000) | |
| 306 | ((c << 5) & 0x0000fc00) | ((c >> 1) & 0x00000300) | |
| 307 | ((c << 3) & 0x000000f8) | ((c >> 2) & 0x00000007); |
| 308 | } |
| 309 | |
| 310 | inline UINT32 powervr2_device::cv_565z(UINT16 c) |
| 311 | { |
| 312 | return |
| 313 | 0xff000000 | |
| 314 | ((c << 8) & 0x00f80000) | |
| 315 | ((c << 5) & 0x0000fc00) | |
| 316 | ((c << 3) & 0x000000f8); |
| 317 | } |
| 318 | |
| 319 | inline UINT32 powervr2_device::cv_4444(UINT16 c) |
| 320 | { |
| 321 | return |
| 322 | ((c << 16) & 0xf0000000) | ((c << 12) & 0x0f000000) | |
| 323 | ((c << 12) & 0x00f00000) | ((c << 8) & 0x000f0000) | |
| 324 | ((c << 8) & 0x0000f000) | ((c << 4) & 0x00000f00) | |
| 325 | ((c << 4) & 0x000000f0) | ((c ) & 0x0000000f); |
| 326 | } |
| 327 | |
| 328 | inline UINT32 powervr2_device::cv_4444z(UINT16 c) |
| 329 | { |
| 330 | return |
| 331 | ((c << 16) & 0xf0000000) | |
| 332 | ((c << 12) & 0x00f00000) | |
| 333 | ((c << 8) & 0x0000f000) | |
| 334 | ((c << 4) & 0x000000f0); |
| 335 | } |
| 336 | |
| 337 | inline UINT32 powervr2_device::cv_yuv(UINT16 c1, UINT16 c2, int x) |
| 338 | { |
| 339 | int u = 11*((c1 & 0xff) - 128); |
| 340 | int v = 11*((c2 & 0xff) - 128); |
| 341 | int y = (x & 1 ? c2 : c1) >> 8; |
| 342 | int r = y + v/8; |
| 343 | int g = y - u/32 - v/16; |
| 344 | int b = y + (3*u)/16; |
| 345 | r = r < 0 ? 0 : r > 255 ? 255 : r; |
| 346 | g = g < 0 ? 0 : g > 255 ? 255 : g; |
| 347 | b = b < 0 ? 0 : b > 255 ? 255 : b; |
| 348 | return 0xff000000 | (r << 16) | (g << 8) | b; |
| 349 | } |
| 350 | |
| 351 | |
| 352 | UINT32 powervr2_device::tex_r_yuv_n(texinfo *t, float x, float y) |
| 353 | { |
| 354 | int xt = ((int)x) & (t->sizex-1); |
| 355 | int yt = ((int)y) & (t->sizey-1); |
| 356 | int addrp = t->address + (t->stride*yt + (xt & ~1))*2; |
| 357 | UINT16 c1 = *(UINT16 *)((reinterpret_cast<UINT8 *>(dc_texture_ram)) + WORD_XOR_LE(addrp)); |
| 358 | UINT16 c2 = *(UINT16 *)((reinterpret_cast<UINT8 *>(dc_texture_ram)) + WORD_XOR_LE(addrp+2)); |
| 359 | return cv_yuv(c1, c2, xt); |
| 360 | } |
| 361 | |
| 362 | UINT32 powervr2_device::tex_r_1555_n(texinfo *t, float x, float y) |
| 363 | { |
| 364 | int xt = ((int)x) & (t->sizex-1); |
| 365 | int yt = ((int)y) & (t->sizey-1); |
| 366 | int addrp = t->address + (t->stride*yt + xt)*2; |
| 367 | return cv_1555z(*(UINT16 *)((reinterpret_cast<UINT8 *>(dc_texture_ram)) + WORD_XOR_LE(addrp))); |
| 368 | } |
| 369 | |
| 370 | UINT32 powervr2_device::tex_r_1555_tw(texinfo *t, float x, float y) |
| 371 | { |
| 372 | int xt = ((int)x) & (t->sizex-1); |
| 373 | int yt = ((int)y) & (t->sizey-1); |
| 374 | int addrp = t->address + (dilated1[t->cd][xt] + dilated0[t->cd][yt])*2; |
| 375 | return cv_1555(*(UINT16 *)((reinterpret_cast<UINT8 *>(dc_texture_ram)) + WORD_XOR_LE(addrp))); |
| 376 | } |
| 377 | |
| 378 | UINT32 powervr2_device::tex_r_1555_vq(texinfo *t, float x, float y) |
| 379 | { |
| 380 | int xt = ((int)x) & (t->sizex-1); |
| 381 | int yt = ((int)y) & (t->sizey-1); |
| 382 | int idx = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 383 | int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2; |
| 384 | return cv_1555(*(UINT16 *)((reinterpret_cast<UINT8 *>(dc_texture_ram)) + WORD_XOR_LE(addrp))); |
| 385 | } |
| 386 | |
| 387 | UINT32 powervr2_device::tex_r_565_n(texinfo *t, float x, float y) |
| 388 | { |
| 389 | int xt = ((int)x) & (t->sizex-1); |
| 390 | int yt = ((int)y) & (t->sizey-1); |
| 391 | int addrp = t->address + (t->stride*yt + xt)*2; |
| 392 | return cv_565z(*(UINT16 *)((reinterpret_cast<UINT8 *>(dc_texture_ram)) + WORD_XOR_LE(addrp))); |
| 393 | } |
| 394 | |
| 395 | UINT32 powervr2_device::tex_r_565_tw(texinfo *t, float x, float y) |
| 396 | { |
| 397 | int xt = ((int)x) & (t->sizex-1); |
| 398 | int yt = ((int)y) & (t->sizey-1); |
| 399 | int addrp = t->address + (dilated1[t->cd][xt] + dilated0[t->cd][yt])*2; |
| 400 | return cv_565(*(UINT16 *)((reinterpret_cast<UINT8 *>(dc_texture_ram)) + WORD_XOR_LE(addrp))); |
| 401 | } |
| 402 | |
| 403 | UINT32 powervr2_device::tex_r_565_vq(texinfo *t, float x, float y) |
| 404 | { |
| 405 | int xt = ((int)x) & (t->sizex-1); |
| 406 | int yt = ((int)y) & (t->sizey-1); |
| 407 | int idx = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 408 | int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2; |
| 409 | return cv_565(*(UINT16 *)((reinterpret_cast<UINT8 *>(dc_texture_ram)) + WORD_XOR_LE(addrp))); |
| 410 | } |
| 411 | |
| 412 | UINT32 powervr2_device::tex_r_4444_n(texinfo *t, float x, float y) |
| 413 | { |
| 414 | int xt = ((int)x) & (t->sizex-1); |
| 415 | int yt = ((int)y) & (t->sizey-1); |
| 416 | int addrp = t->address + (t->stride*yt + xt)*2; |
| 417 | return cv_4444z(*(UINT16 *)((reinterpret_cast<UINT8 *>(dc_texture_ram)) + WORD_XOR_LE(addrp))); |
| 418 | } |
| 419 | |
| 420 | UINT32 powervr2_device::tex_r_4444_tw(texinfo *t, float x, float y) |
| 421 | { |
| 422 | int xt = ((int)x) & (t->sizex-1); |
| 423 | int yt = ((int)y) & (t->sizey-1); |
| 424 | int addrp = t->address + (dilated1[t->cd][xt] + dilated0[t->cd][yt])*2; |
| 425 | return cv_4444(*(UINT16 *)((reinterpret_cast<UINT8 *>(dc_texture_ram)) + WORD_XOR_LE(addrp))); |
| 426 | } |
| 427 | |
| 428 | UINT32 powervr2_device::tex_r_4444_vq(texinfo *t, float x, float y) |
| 429 | { |
| 430 | int xt = ((int)x) & (t->sizex-1); |
| 431 | int yt = ((int)y) & (t->sizey-1); |
| 432 | int idx = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 433 | int addrp = t->vqbase + 8*idx + (dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 1])*2; |
| 434 | return cv_4444(*(UINT16 *)((reinterpret_cast<UINT8 *>(dc_texture_ram)) + WORD_XOR_LE(addrp))); |
| 435 | } |
| 436 | |
| 437 | UINT32 powervr2_device::tex_r_p4_1555_tw(texinfo *t, float x, float y) |
| 438 | { |
| 439 | int xt = ((int)x) & (t->sizex-1); |
| 440 | int yt = ((int)y) & (t->sizey-1); |
| 441 | int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 442 | int addrp = t->address + (off >> 1); |
| 443 | int c = ((reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; |
| 444 | return cv_1555(pvrta_regs[t->palbase + c]); |
| 445 | } |
| 446 | |
| 447 | UINT32 powervr2_device::tex_r_p4_1555_vq(texinfo *t, float x, float y) |
| 448 | { |
| 449 | int xt = ((int)x) & (t->sizex-1); |
| 450 | int yt = ((int)y) & (t->sizey-1); |
| 451 | int idx = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 452 | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 453 | int c = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf; |
| 454 | return cv_1555(pvrta_regs[t->palbase + c]); |
| 455 | } |
| 456 | |
| 457 | UINT32 powervr2_device::tex_r_p4_565_tw(texinfo *t, float x, float y) |
| 458 | { |
| 459 | int xt = ((int)x) & (t->sizex-1); |
| 460 | int yt = ((int)y) & (t->sizey-1); |
| 461 | int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 462 | int addrp = t->address + (off >> 1); |
| 463 | int c = ((reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; |
| 464 | return cv_565(pvrta_regs[t->palbase + c]); |
| 465 | } |
| 466 | |
| 467 | UINT32 powervr2_device::tex_r_p4_565_vq(texinfo *t, float x, float y) |
| 468 | { |
| 469 | int xt = ((int)x) & (t->sizex-1); |
| 470 | int yt = ((int)y) & (t->sizey-1); |
| 471 | int idx = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 472 | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 473 | int c = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf; |
| 474 | return cv_565(pvrta_regs[t->palbase + c]); |
| 475 | } |
| 476 | |
| 477 | UINT32 powervr2_device::tex_r_p4_4444_tw(texinfo *t, float x, float y) |
| 478 | { |
| 479 | int xt = ((int)x) & (t->sizex-1); |
| 480 | int yt = ((int)y) & (t->sizey-1); |
| 481 | int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 482 | int addrp = t->address + (off >> 1); |
| 483 | int c = ((reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; |
| 484 | return cv_4444(pvrta_regs[t->palbase + c]); |
| 485 | } |
| 486 | |
| 487 | UINT32 powervr2_device::tex_r_p4_4444_vq(texinfo *t, float x, float y) |
| 488 | { |
| 489 | int xt = ((int)x) & (t->sizex-1); |
| 490 | int yt = ((int)y) & (t->sizey-1); |
| 491 | int idx = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 492 | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 493 | int c = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf; |
| 494 | return cv_4444(pvrta_regs[t->palbase + c]); |
| 495 | } |
| 496 | |
| 497 | UINT32 powervr2_device::tex_r_p4_8888_tw(texinfo *t, float x, float y) |
| 498 | { |
| 499 | int xt = ((int)x) & (t->sizex-1); |
| 500 | int yt = ((int)y) & (t->sizey-1); |
| 501 | int off = dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 502 | int addrp = t->address + (off >> 1); |
| 503 | int c = ((reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] >> ((off & 1) << 2)) & 0xf; |
| 504 | return pvrta_regs[t->palbase + c]; |
| 505 | } |
| 506 | |
| 507 | UINT32 powervr2_device::tex_r_p4_8888_vq(texinfo *t, float x, float y) |
| 508 | { |
| 509 | int xt = ((int)x) & (t->sizex-1); |
| 510 | int yt = ((int)y) & (t->sizey-1); |
| 511 | int idx = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 512 | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 513 | int c = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)] & 0xf; |
| 514 | return pvrta_regs[t->palbase + c]; |
| 515 | } |
| 516 | |
| 517 | UINT32 powervr2_device::tex_r_p8_1555_tw(texinfo *t, float x, float y) |
| 518 | { |
| 519 | int xt = ((int)x) & (t->sizex-1); |
| 520 | int yt = ((int)y) & (t->sizey-1); |
| 521 | int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 522 | int c = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)]; |
| 523 | return cv_1555(pvrta_regs[t->palbase + c]); |
| 524 | } |
| 525 | |
| 526 | UINT32 powervr2_device::tex_r_p8_1555_vq(texinfo *t, float x, float y) |
| 527 | { |
| 528 | int xt = ((int)x) & (t->sizex-1); |
| 529 | int yt = ((int)y) & (t->sizey-1); |
| 530 | int idx = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 531 | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 532 | int c = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)]; |
| 533 | return cv_1555(pvrta_regs[t->palbase + c]); |
| 534 | } |
| 535 | |
| 536 | UINT32 powervr2_device::tex_r_p8_565_tw(texinfo *t, float x, float y) |
| 537 | { |
| 538 | int xt = ((int)x) & (t->sizex-1); |
| 539 | int yt = ((int)y) & (t->sizey-1); |
| 540 | int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 541 | int c = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)]; |
| 542 | return cv_565(pvrta_regs[t->palbase + c]); |
| 543 | } |
| 544 | |
| 545 | UINT32 powervr2_device::tex_r_p8_565_vq(texinfo *t, float x, float y) |
| 546 | { |
| 547 | int xt = ((int)x) & (t->sizex-1); |
| 548 | int yt = ((int)y) & (t->sizey-1); |
| 549 | int idx = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 550 | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 551 | int c = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)]; |
| 552 | return cv_565(pvrta_regs[t->palbase + c]); |
| 553 | } |
| 554 | |
| 555 | UINT32 powervr2_device::tex_r_p8_4444_tw(texinfo *t, float x, float y) |
| 556 | { |
| 557 | int xt = ((int)x) & (t->sizex-1); |
| 558 | int yt = ((int)y) & (t->sizey-1); |
| 559 | int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 560 | int c = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)]; |
| 561 | return cv_4444(pvrta_regs[t->palbase + c]); |
| 562 | } |
| 563 | |
| 564 | UINT32 powervr2_device::tex_r_p8_4444_vq(texinfo *t, float x, float y) |
| 565 | { |
| 566 | int xt = ((int)x) & (t->sizex-1); |
| 567 | int yt = ((int)y) & (t->sizey-1); |
| 568 | int idx = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 569 | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 570 | int c = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)]; |
| 571 | return cv_4444(pvrta_regs[t->palbase + c]); |
| 572 | } |
| 573 | |
| 574 | UINT32 powervr2_device::tex_r_p8_8888_tw(texinfo *t, float x, float y) |
| 575 | { |
| 576 | int xt = ((int)x) & (t->sizex-1); |
| 577 | int yt = ((int)y) & (t->sizey-1); |
| 578 | int addrp = t->address + dilated1[t->cd][xt] + dilated0[t->cd][yt]; |
| 579 | int c = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)]; |
| 580 | return pvrta_regs[t->palbase + c]; |
| 581 | } |
| 582 | |
| 583 | UINT32 powervr2_device::tex_r_p8_8888_vq(texinfo *t, float x, float y) |
| 584 | { |
| 585 | int xt = ((int)x) & (t->sizex-1); |
| 586 | int yt = ((int)y) & (t->sizey-1); |
| 587 | int idx = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(t->address + dilated1[t->cd][xt >> 1] + dilated0[t->cd][yt >> 1])]; |
| 588 | int addrp = t->vqbase + 8*idx + dilated1[t->cd][xt & 1] + dilated0[t->cd][yt & 3]; |
| 589 | int c = (reinterpret_cast<UINT8 *>(dc_texture_ram))[BYTE_XOR_LE(addrp)]; |
| 590 | return pvrta_regs[t->palbase + c]; |
| 591 | } |
| 592 | |
| 593 | |
| 594 | UINT32 powervr2_device::tex_r_default(texinfo *t, float x, float y) |
| 595 | { |
| 596 | return ((int)x ^ (int)y) & 4 ? 0xffffff00 : 0xff0000ff; |
| 597 | } |
| 598 | |
| 599 | void powervr2_device::tex_get_info(texinfo *t) |
| 600 | { |
| 601 | int miptype = 0; |
| 602 | |
| 603 | t->textured = texture; |
| 604 | |
| 605 | // not textured, abort. |
| 606 | if (!t->textured) return; |
| 607 | |
| 608 | t->address = textureaddress; |
| 609 | t->pf = pixelformat; |
| 610 | t->palette = 0; |
| 611 | |
| 612 | t->mode = (vqcompressed<<1); |
| 613 | |
| 614 | // scanorder is ignored for palettized textures (palettized textures are ALWAYS twiddled) |
| 615 | // (the same bits are used for palette select instead) |
| 616 | if ((t->pf == 5) || (t->pf == 6)) |
| 617 | { |
| 618 | t->palette = paletteselector; |
| 619 | } |
| 620 | else |
| 621 | { |
| 622 | t->mode |= scanorder; |
| 623 | } |
| 624 | |
| 625 | /* When scan order is 1 (non-twiddled) mipmap is ignored */ |
| 626 | t->mipmapped = t->mode & 1 ? 0 : mipmapped; |
| 627 | |
| 628 | // Mipmapped textures are always square, ignore v size |
| 629 | if (t->mipmapped) |
| 630 | { |
| 631 | t->sizes = (texturesizes & 0x38) | ((texturesizes & 0x38) >> 3); |
| 632 | } |
| 633 | else |
| 634 | { |
| 635 | t->sizes = texturesizes; |
| 636 | } |
| 637 | |
| 638 | t->sizex = 1 << (3+((t->sizes >> 3) & 7)); |
| 639 | t->sizey = 1 << (3+(t->sizes & 7)); |
| 640 | |
| 641 | |
| 642 | /* Stride select is used only in the non-twiddled case */ |
| 643 | t->stride = (t->mode & 1) && strideselect ? (pvrta_regs[TEXT_CONTROL] & 0x1f) << 5 : t->sizex; |
| 644 | |
| 645 | t->blend_mode = blend_mode; |
| 646 | t->filter_mode = filtermode; |
| 647 | t->flip_u = (flipuv >> 1) & 1; |
| 648 | t->flip_v = flipuv & 1; |
| 649 | |
| 650 | t->r = &powervr2_device::tex_r_default; |
| 651 | t->cd = dilatechose[t->sizes]; |
| 652 | t->palbase = 0; |
| 653 | t->vqbase = t->address; |
| 654 | t->blend = use_alpha ? blend_functions[t->blend_mode] : bl10; |
| 655 | |
| 656 | // fprintf(stderr, "tex %d %d %d %d\n", t->pf, t->mode, pvrta_regs[PAL_RAM_CTRL], t->mipmapped); |
| 657 | |
| 658 | switch(t->pf) { |
| 659 | case 0: // 1555 |
| 660 | switch(t->mode) { |
| 661 | case 0: t->r = &powervr2_device::tex_r_1555_tw; miptype = 2; break; |
| 662 | case 1: t->r = &powervr2_device::tex_r_1555_n; miptype = 2; break; |
| 663 | case 2: |
| 664 | case 3: t->r = &powervr2_device::tex_r_1555_vq; miptype = 3; t->address += 0x800; break; |
| 665 | |
| 666 | default: |
| 667 | // |
| 668 | break; |
| 669 | } |
| 670 | break; |
| 671 | |
| 672 | case 1: // 565 |
| 673 | switch(t->mode) { |
| 674 | case 0: t->r = &powervr2_device::tex_r_565_tw; miptype = 2; break; |
| 675 | case 1: t->r = &powervr2_device::tex_r_565_n; miptype = 2; break; |
| 676 | case 2: |
| 677 | case 3: t->r = &powervr2_device::tex_r_565_vq; miptype = 3; t->address += 0x800; break; |
| 678 | |
| 679 | default: |
| 680 | // |
| 681 | break; |
| 682 | } |
| 683 | break; |
| 684 | |
| 685 | case 2: // 4444 |
| 686 | switch(t->mode) { |
| 687 | case 0: t->r = &powervr2_device::tex_r_4444_tw; miptype = 2; break; |
| 688 | case 1: t->r = &powervr2_device::tex_r_4444_n; miptype = 2; break; |
| 689 | case 2: |
| 690 | case 3: t->r = &powervr2_device::tex_r_4444_vq; miptype = 3; t->address += 0x800; break; |
| 691 | |
| 692 | default: |
| 693 | // |
| 694 | break; |
| 695 | } |
| 696 | break; |
| 697 | |
| 698 | case 3: // yuv422 |
| 699 | switch(t->mode) { |
| 700 | case 0: /*t->r = &powervr2_device::tex_r_yuv_tw*/; miptype = -1; break; |
| 701 | case 1: t->r = &powervr2_device::tex_r_yuv_n; miptype = -1; break; |
| 702 | default: /*t->r = &powervr2_device::tex_r_yuv_vq*/; miptype = -1; break; |
| 703 | } |
| 704 | break; |
| 705 | |
| 706 | case 4: // bumpmap |
| 707 | break; |
| 708 | |
| 709 | case 5: // 4bpp palette |
| 710 | t->palbase = 0x400 | ((t->palette & 0x3f) << 4); |
| 711 | switch(t->mode) { |
| 712 | case 0: case 1: |
| 713 | miptype = 0; |
| 714 | |
| 715 | switch(pvrta_regs[PAL_RAM_CTRL]) { |
| 716 | case 0: t->r = &powervr2_device::tex_r_p4_1555_tw; break; |
| 717 | case 1: t->r = &powervr2_device::tex_r_p4_565_tw; break; |
| 718 | case 2: t->r = &powervr2_device::tex_r_p4_4444_tw; break; |
| 719 | case 3: t->r = &powervr2_device::tex_r_p4_8888_tw; break; |
| 720 | } |
| 721 | break; |
| 722 | case 2: case 3: |
| 723 | miptype = 3; // ? |
| 724 | switch(pvrta_regs[PAL_RAM_CTRL]) { |
| 725 | case 0: t->r = &powervr2_device::tex_r_p4_1555_vq; t->address += 0x800; break; |
| 726 | case 1: t->r = &powervr2_device::tex_r_p4_565_vq; t->address += 0x800; break; |
| 727 | case 2: t->r = &powervr2_device::tex_r_p4_4444_vq; t->address += 0x800; break; |
| 728 | case 3: t->r = &powervr2_device::tex_r_p4_8888_vq; t->address += 0x800; break; |
| 729 | } |
| 730 | break; |
| 731 | |
| 732 | default: |
| 733 | // |
| 734 | break; |
| 735 | } |
| 736 | break; |
| 737 | |
| 738 | case 6: // 8bpp palette |
| 739 | t->palbase = 0x400 | ((t->palette & 0x30) << 4); |
| 740 | switch(t->mode) { |
| 741 | case 0: case 1: |
| 742 | miptype = 1; |
| 743 | |
| 744 | switch(pvrta_regs[PAL_RAM_CTRL]) { |
| 745 | case 0: t->r = &powervr2_device::tex_r_p8_1555_tw; break; |
| 746 | case 1: t->r = &powervr2_device::tex_r_p8_565_tw; break; |
| 747 | case 2: t->r = &powervr2_device::tex_r_p8_4444_tw; break; |
| 748 | case 3: t->r = &powervr2_device::tex_r_p8_8888_tw; break; |
| 749 | } |
| 750 | break; |
| 751 | case 2: case 3: |
| 752 | miptype = 3; // ? |
| 753 | switch(pvrta_regs[PAL_RAM_CTRL]) { |
| 754 | case 0: t->r = &powervr2_device::tex_r_p8_1555_vq; t->address += 0x800; break; |
| 755 | case 1: t->r = &powervr2_device::tex_r_p8_565_vq; t->address += 0x800; break; |
| 756 | case 2: t->r = &powervr2_device::tex_r_p8_4444_vq; t->address += 0x800; break; |
| 757 | case 3: t->r = &powervr2_device::tex_r_p8_8888_vq; t->address += 0x800; break; |
| 758 | } |
| 759 | break; |
| 760 | |
| 761 | default: |
| 762 | // |
| 763 | break; |
| 764 | } |
| 765 | break; |
| 766 | |
| 767 | case 9: // reserved |
| 768 | break; |
| 769 | } |
| 770 | |
| 771 | if (t->mipmapped) |
| 772 | { |
| 773 | // full offset tables for reference, |
| 774 | // we don't do mipmapping, so don't use anything < 8x8 |
| 775 | // first table is half-bytes |
| 776 | |
| 777 | // 4BPP palette textures |
| 778 | // Texture size _4-bit_ offset value for starting address |
| 779 | // 1x1 0x00003 |
| 780 | // 2x2 0x00004 |
| 781 | // 4x4 0x00008 |
| 782 | // 8x8 0x00018 |
| 783 | // 16x16 0x00058 |
| 784 | // 32x32 0x00158 |
| 785 | // 64x64 0x00558 |
| 786 | // 128x128 0x01558 |
| 787 | // 256x256 0x05558 |
| 788 | // 512x512 0x15558 |
| 789 | // 1024x1024 0x55558 |
| 790 | |
| 791 | // 8BPP palette textures |
| 792 | // Texture size Byte offset value for starting address |
| 793 | // 1x1 0x00003 |
| 794 | // 2x2 0x00004 |
| 795 | // 4x4 0x00008 |
| 796 | // 8x8 0x00018 |
| 797 | // 16x16 0x00058 |
| 798 | // 32x32 0x00158 |
| 799 | // 64x64 0x00558 |
| 800 | // 128x128 0x01558 |
| 801 | // 256x256 0x05558 |
| 802 | // 512x512 0x15558 |
| 803 | // 1024x1024 0x55558 |
| 804 | |
| 805 | // Non-palette textures |
| 806 | // Texture size Byte offset value for starting address |
| 807 | // 1x1 0x00006 |
| 808 | // 2x2 0x00008 |
| 809 | // 4x4 0x00010 |
| 810 | // 8x8 0x00030 |
| 811 | // 16x16 0x000B0 |
| 812 | // 32x32 0x002B0 |
| 813 | // 64x64 0x00AB0 |
| 814 | // 128x128 0x02AB0 |
| 815 | // 256x256 0x0AAB0 |
| 816 | // 512x512 0x2AAB0 |
| 817 | // 1024x1024 0xAAAB0 |
| 818 | |
| 819 | // VQ textures |
| 820 | // Texture size Byte offset value for starting address |
| 821 | // 1x1 0x00000 |
| 822 | // 2x2 0x00001 |
| 823 | // 4x4 0x00002 |
| 824 | // 8x8 0x00006 |
| 825 | // 16x16 0x00016 |
| 826 | // 32x32 0x00056 |
| 827 | // 64x64 0x00156 |
| 828 | // 128x128 0x00556 |
| 829 | // 256x256 0x01556 |
| 830 | // 512x512 0x05556 |
| 831 | // 1024x1024 0x15556 |
| 832 | |
| 833 | static const int mipmap_4_8_offset[8] = { 0x00018, 0x00058, 0x00158, 0x00558, 0x01558, 0x05558, 0x15558, 0x55558 }; // 4bpp (4bit offset) / 8bpp (8bit offset) |
| 834 | static const int mipmap_np_offset[8] = { 0x00030, 0x000B0, 0x002B0, 0x00AB0, 0x02AB0, 0x0AAB0, 0x2AAB0, 0xAAAB0 }; // nonpalette textures |
| 835 | static const int mipmap_vq_offset[8] = { 0x00006, 0x00016, 0x00056, 0x00156, 0x00556, 0x01556, 0x05556, 0x15556 }; // vq textures |
| 836 | |
| 837 | switch (miptype) |
| 838 | { |
| 839 | case 0: // 4bpp |
| 840 | //printf("4bpp\n"); |
| 841 | t->address += mipmap_4_8_offset[(t->sizes)&7]>>1; |
| 842 | break; |
| 843 | |
| 844 | case 1: // 8bpp |
| 845 | //printf("8bpp\n"); |
| 846 | t->address += mipmap_4_8_offset[(t->sizes)&7]; |
| 847 | break; |
| 848 | |
| 849 | case 2: // nonpalette |
| 850 | //printf("np\n"); |
| 851 | t->address += mipmap_np_offset[(t->sizes)&7]; |
| 852 | break; |
| 853 | |
| 854 | case 3: // vq |
| 855 | //printf("vq\n"); |
| 856 | t->address += mipmap_vq_offset[(t->sizes)&7]; |
| 857 | break; |
| 858 | } |
| 859 | } |
| 860 | |
| 861 | } |
| 862 | |
| 863 | // register decode helper |
| 864 | static inline int decode_reg_64(UINT32 offset, UINT64 mem_mask, UINT64 *shift) |
| 865 | { |
| 866 | int reg = offset * 2; |
| 867 | |
| 868 | *shift = 0; |
| 869 | |
| 870 | // non 32-bit accesses have not yet been seen here, we need to know when they are |
| 871 | if ((mem_mask != U64(0xffffffff00000000)) && (mem_mask != U64(0x00000000ffffffff))) |
| 872 | { |
| 873 | /*assume to return the lower 32-bits ONLY*/ |
| 874 | return reg & 0xffffffff; |
| 875 | } |
| 876 | |
| 877 | if (mem_mask == U64(0xffffffff00000000)) |
| 878 | { |
| 879 | reg++; |
| 880 | *shift = 32; |
| 881 | } |
| 882 | |
| 883 | return reg; |
| 884 | } |
| 885 | |
| 886 | READ64_MEMBER( powervr2_device::pvr_ta_r ) |
| 887 | { |
| 888 | int reg; |
| 889 | UINT64 shift; |
| 890 | |
| 891 | reg = decode_reg_64(offset, mem_mask, &shift); |
| 892 | |
| 893 | switch (reg) |
| 894 | { |
| 895 | case SPG_STATUS: |
| 896 | { |
| 897 | UINT8 fieldnum,vsync,hsync,blank; |
| 898 | |
| 899 | fieldnum = (space.machine().primary_screen->frame_number() & 1) ? 1 : 0; |
| 900 | |
| 901 | vsync = space.machine().primary_screen->vblank() ? 1 : 0; |
| 902 | if(spg_vsync_pol) { vsync^=1; } |
| 903 | |
| 904 | hsync = space.machine().primary_screen->hblank() ? 1 : 0; |
| 905 | if(spg_hsync_pol) { hsync^=1; } |
| 906 | |
| 907 | /* FIXME: following is just a wild guess */ |
| 908 | blank = (space.machine().primary_screen->vblank() | space.machine().primary_screen->hblank()) ? 0 : 1; |
| 909 | if(spg_blank_pol) { blank^=1; } |
| 910 | |
| 911 | pvrta_regs[reg] = (vsync << 13) | (hsync << 12) | (blank << 11) | (fieldnum << 10) | (space.machine().primary_screen->vpos() & 0x3ff); |
| 912 | break; |
| 913 | } |
| 914 | case SPG_TRIGGER_POS: |
| 915 | printf("Warning: read at h/v counter ext latches\n"); |
| 916 | break; |
| 917 | case TA_LIST_INIT: |
| 918 | return 0; //bit 31 always return 0, a probable left-over in Crazy Taxi reads this and discards the read (?) |
| 919 | } |
| 920 | |
| 921 | #if DEBUG_PVRTA_REGS |
| 922 | if (reg != 0x43) |
| 923 | mame_printf_verbose("PVRTA: [%08x] read %x @ %x (reg %x), mask %" I64FMT "x (PC=%x)\n", 0x5f8000+reg*4, pvrta_regs[reg], offset, reg, mem_mask, space.device().safe_pc()); |
| 924 | #endif |
| 925 | return (UINT64)pvrta_regs[reg] << shift; |
| 926 | } |
| 927 | |
| 928 | WRITE64_MEMBER( powervr2_device::pvr_ta_w ) |
| 929 | { |
| 930 | int reg; |
| 931 | UINT64 shift; |
| 932 | UINT32 dat; |
| 933 | UINT32 sizera,offsetra; |
| 934 | int a; |
| 935 | int sanitycount; |
| 936 | |
| 937 | reg = decode_reg_64(offset, mem_mask, &shift); |
| 938 | dat = (UINT32)(data >> shift); |
| 939 | //old = pvrta_regs[reg]; |
| 940 | |
| 941 | // Dreamcast BIOS attempts to set PVRID to zero and then dies |
| 942 | // if it succeeds. Don't allow. |
| 943 | if ((reg != PVRID) && (reg != REVISION)) |
| 944 | { |
| 945 | pvrta_regs[reg] = dat; // 5f8000+reg*4=dat |
| 946 | } |
| 947 | |
| 948 | switch (reg) |
| 949 | { |
| 950 | case SOFTRESET: |
| 951 | if (dat & 1) |
| 952 | { |
| 953 | #if DEBUG_PVRTA |
| 954 | mame_printf_verbose("pvr_ta_w: TA soft reset\n"); |
| 955 | #endif |
| 956 | listtype_used=0; |
| 957 | } |
| 958 | if (dat & 2) |
| 959 | { |
| 960 | #if DEBUG_PVRTA |
| 961 | mame_printf_verbose("pvr_ta_w: Core Pipeline soft reset\n"); |
| 962 | #endif |
| 963 | if (start_render_received == 1) |
| 964 | { |
| 965 | for (a=0;a < NUM_BUFFERS;a++) |
| 966 | if (grab[a].busy == 1) |
| 967 | grab[a].busy = 0; |
| 968 | start_render_received = 0; |
| 969 | } |
| 970 | } |
| 971 | if (dat & 4) |
| 972 | { |
| 973 | #if DEBUG_PVRTA |
| 974 | mame_printf_verbose("pvr_ta_w: sdram I/F soft reset\n"); |
| 975 | #endif |
| 976 | } |
| 977 | break; |
| 978 | case STARTRENDER: |
| 979 | g_profiler.start(PROFILER_USER1); |
| 980 | #if DEBUG_PVRTA |
| 981 | mame_printf_verbose("Start Render Received:\n"); |
| 982 | mame_printf_verbose(" Region Array at %08x\n",pvrta_regs[REGION_BASE]); |
| 983 | mame_printf_verbose(" ISP/TSP Parameters at %08x\n",pvrta_regs[PARAM_BASE]); |
| 984 | |
| 985 | #endif |
| 986 | // select buffer to draw using PARAM_BASE |
| 987 | for (a=0;a < NUM_BUFFERS;a++) |
| 988 | { |
| 989 | if ((grab[a].ispbase == pvrta_regs[PARAM_BASE]) && (grab[a].valid == 1) && (grab[a].busy == 0)) |
| 990 | { |
| 991 | grab[a].busy = 1; |
| 992 | renderselect = a; |
| 993 | start_render_received=1; |
| 994 | |
| 995 | |
| 996 | grab[a].fbwsof1=pvrta_regs[FB_W_SOF1]; |
| 997 | grab[a].fbwsof2=pvrta_regs[FB_W_SOF2]; |
| 998 | |
| 999 | rectangle clip(0, 1023, 0, 1023); |
| 1000 | |
| 1001 | // we've got a request to draw, so, draw to the accumulation buffer! |
| 1002 | // this should really be done for each tile! |
| 1003 | render_to_accumulation_buffer(*fake_accumulationbuffer_bitmap,clip); |
| 1004 | |
| 1005 | endofrender_timer_isp->adjust(attotime::from_usec(4000) ); // hack, make sure render takes some amount of time |
| 1006 | |
| 1007 | /* copy the tiles to the framebuffer (really the rendering should be in this loop too) */ |
| 1008 | if (pvrta_regs[FPU_PARAM_CFG] & 0x200000) |
| 1009 | sizera=6; |
| 1010 | else |
| 1011 | sizera=5; |
| 1012 | offsetra=pvrta_regs[REGION_BASE]; |
| 1013 | |
| 1014 | //printf("base is %08x\n", offsetra); |
| 1015 | |
| 1016 | // sanity |
| 1017 | sanitycount = 0; |
| 1018 | for (;;) |
| 1019 | { |
| 1020 | UINT32 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 | { |
| 1030 | st[5] = space.read_dword((0x05000014+offsetra)); // Punch Through List Pointer |
| 1031 | offsetra+=0x18; |
| 1032 | } |
| 1033 | else |
| 1034 | { |
| 1035 | st[5] = 0; |
| 1036 | offsetra+=0x14; |
| 1037 | } |
| 1038 | |
| 1039 | { |
| 1040 | int x = ((st[0]&0x000000fc)>>2)*32; |
| 1041 | int y = ((st[0]&0x00003f00)>>8)*32; |
| 1042 | //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]); |
| 1043 | |
| 1044 | // should render to the accumulation buffer here using pointers we filled in when processing the data |
| 1045 | // sent to the TA. HOWEVER, we don't process the TA data and create the real format object lists, so |
| 1046 | // instead just use these co-ordinates to copy data from our fake full-screnen accumnulation buffer into |
| 1047 | // the framebuffer |
| 1048 | |
| 1049 | pvr_accumulationbuffer_to_framebuffer(space, x,y); |
| 1050 | } |
| 1051 | |
| 1052 | if (st[0] & 0x80000000) |
| 1053 | break; |
| 1054 | |
| 1055 | // prevent infinite loop if asked to process invalid data |
| 1056 | if(sanitycount>2000) |
| 1057 | break; |
| 1058 | } |
| 1059 | |
| 1060 | |
| 1061 | |
| 1062 | |
| 1063 | break; |
| 1064 | } |
| 1065 | } |
| 1066 | if (a != NUM_BUFFERS) |
| 1067 | break; |
| 1068 | assert_always(0, "TA grabber error A!\n"); |
| 1069 | break; |
| 1070 | case TA_LIST_INIT: |
| 1071 | if(dat & 0x80000000) |
| 1072 | { |
| 1073 | tafifo_pos=0; |
| 1074 | tafifo_mask=7; |
| 1075 | tafifo_vertexwords=8; |
| 1076 | tafifo_listtype= -1; |
| 1077 | #if DEBUG_PVRTA |
| 1078 | mame_printf_verbose("TA_OL_BASE %08x TA_OL_LIMIT %08x\n", pvrta_regs[TA_OL_BASE], pvrta_regs[TA_OL_LIMIT]); |
| 1079 | mame_printf_verbose("TA_ISP_BASE %08x TA_ISP_LIMIT %08x\n", pvrta_regs[TA_ISP_BASE], pvrta_regs[TA_ISP_LIMIT]); |
| 1080 | mame_printf_verbose("TA_ALLOC_CTRL %08x\n", pvrta_regs[TA_ALLOC_CTRL]); |
| 1081 | mame_printf_verbose("TA_NEXT_OPB_INIT %08x\n", pvrta_regs[TA_NEXT_OPB_INIT]); |
| 1082 | #endif |
| 1083 | pvrta_regs[TA_NEXT_OPB] = pvrta_regs[TA_NEXT_OPB_INIT]; |
| 1084 | pvrta_regs[TA_ITP_CURRENT] = pvrta_regs[TA_ISP_BASE]; |
| 1085 | alloc_ctrl_OPB_Mode = pvrta_regs[TA_ALLOC_CTRL] & 0x100000; // 0 up 1 down |
| 1086 | alloc_ctrl_PT_OPB = (4 << ((pvrta_regs[TA_ALLOC_CTRL] >> 16) & 3)) & 0x38; // number of 32 bit words (0,8,16,32) |
| 1087 | alloc_ctrl_TM_OPB = (4 << ((pvrta_regs[TA_ALLOC_CTRL] >> 12) & 3)) & 0x38; |
| 1088 | alloc_ctrl_T_OPB = (4 << ((pvrta_regs[TA_ALLOC_CTRL] >> 8) & 3)) & 0x38; |
| 1089 | alloc_ctrl_OM_OPB = (4 << ((pvrta_regs[TA_ALLOC_CTRL] >> 4) & 3)) & 0x38; |
| 1090 | alloc_ctrl_O_OPB = (4 << ((pvrta_regs[TA_ALLOC_CTRL] >> 0) & 3)) & 0x38; |
| 1091 | listtype_used |= (1+4); |
| 1092 | // use TA_ISP_BASE and select buffer for grab data |
| 1093 | grabsel = -1; |
| 1094 | // try to find already used buffer but not busy |
| 1095 | for (a=0;a < NUM_BUFFERS;a++) |
| 1096 | { |
| 1097 | if ((grab[a].ispbase == pvrta_regs[TA_ISP_BASE]) && (grab[a].busy == 0) && (grab[a].valid == 1)) |
| 1098 | { |
| 1099 | grabsel=a; |
| 1100 | break; |
| 1101 | } |
| 1102 | } |
| 1103 | // try a buffer not used yet |
| 1104 | if (grabsel < 0) |
| 1105 | { |
| 1106 | for (a=0;a < NUM_BUFFERS;a++) |
| 1107 | { |
| 1108 | if (grab[a].valid == 0) |
| 1109 | { |
| 1110 | grabsel=a; |
| 1111 | break; |
| 1112 | } |
| 1113 | } |
| 1114 | } |
| 1115 | // find a non busy buffer starting from the last one used |
| 1116 | if (grabsel < 0) |
| 1117 | { |
| 1118 | for (a=0;a < 3;a++) |
| 1119 | { |
| 1120 | if (grab[(grabsellast+1+a) & 3].busy == 0) |
| 1121 | { |
| 1122 | grabsel=a; |
| 1123 | break; |
| 1124 | } |
| 1125 | } |
| 1126 | } |
| 1127 | if (grabsel < 0) |
| 1128 | assert_always(0, "TA grabber error B!\n"); |
| 1129 | grabsellast=grabsel; |
| 1130 | grab[grabsel].ispbase=pvrta_regs[TA_ISP_BASE]; |
| 1131 | grab[grabsel].busy=0; |
| 1132 | grab[grabsel].valid=1; |
| 1133 | grab[grabsel].verts_size=0; |
| 1134 | grab[grabsel].strips_size=0; |
| 1135 | |
| 1136 | g_profiler.stop(); |
| 1137 | } |
| 1138 | break; |
| 1139 | //#define TA_YUV_TEX_BASE ((0x005f8148-0x005f8000)/4) |
| 1140 | case TA_YUV_TEX_BASE: |
| 1141 | printf("TA_YUV_TEX_BASE initialized to %08x\n", dat); |
| 1142 | |
| 1143 | // hack, this interrupt is generated after transfering a set amount of data |
| 1144 | //state->state->dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_YUV; |
| 1145 | //state->state->dc_update_interrupt_status(); |
| 1146 | |
| 1147 | break; |
| 1148 | case TA_YUV_TEX_CTRL: |
| 1149 | printf("TA_YUV_TEX_CTRL initialized to %08x\n", dat); |
| 1150 | break; |
| 1151 | |
| 1152 | case SPG_VBLANK_INT: |
| 1153 | /* clear pending irqs and modify them with the updated ones */ |
| 1154 | vbin_timer->adjust(attotime::never); |
| 1155 | vbout_timer->adjust(attotime::never); |
| 1156 | |
| 1157 | vbin_timer->adjust(space.machine().primary_screen->time_until_pos(spg_vblank_in_irq_line_num)); |
| 1158 | vbout_timer->adjust(space.machine().primary_screen->time_until_pos(spg_vblank_out_irq_line_num)); |
| 1159 | break; |
| 1160 | /* TODO: timer adjust for SPG_HBLANK_INT too */ |
| 1161 | case TA_LIST_CONT: |
| 1162 | #if DEBUG_PVRTA |
| 1163 | mame_printf_verbose("List continuation processing\n"); |
| 1164 | #endif |
| 1165 | if(dat & 0x80000000) |
| 1166 | { |
| 1167 | tafifo_listtype= -1; // no list being received |
| 1168 | listtype_used |= (1+4); |
| 1169 | } |
| 1170 | break; |
| 1171 | case SPG_VBLANK: |
| 1172 | case SPG_HBLANK: |
| 1173 | case SPG_LOAD: |
| 1174 | case VO_STARTX: |
| 1175 | case VO_STARTY: |
| 1176 | { |
| 1177 | rectangle visarea = space.machine().primary_screen->visible_area(); |
| 1178 | /* FIXME: right visible area calculations aren't known yet*/ |
| 1179 | visarea.min_x = 0; |
| 1180 | visarea.max_x = ((spg_hbstart - spg_hbend - vo_horz_start_pos) <= 0x180 ? 320 : 640) - 1; |
| 1181 | visarea.min_y = 0; |
| 1182 | visarea.max_y = ((spg_vbstart - spg_vbend - vo_vert_start_pos_f1) <= 0x100 ? 240 : 480) - 1; |
| 1183 | |
| 1184 | |
| 1185 | space.machine().primary_screen->configure(spg_hbstart, spg_vbstart, visarea, space.machine().primary_screen->frame_period().attoseconds ); |
| 1186 | } |
| 1187 | break; |
| 1188 | } |
| 1189 | |
| 1190 | #if DEBUG_PVRTA_REGS |
| 1191 | if ((reg != 0x14) && (reg != 0x15)) |
| 1192 | mame_printf_verbose("PVRTA: [%08x=%x] write %" I64FMT "x to %x (reg %x %x), mask %" I64FMT "x\n", 0x5f8000+reg*4, dat, data>>shift, offset, reg, (reg*4)+0x8000, mem_mask); |
| 1193 | #endif |
| 1194 | } |
| 1195 | |
| 1196 | TIMER_CALLBACK_MEMBER(powervr2_device::transfer_opaque_list_irq) |
| 1197 | { |
| 1198 | dc_state *state = machine().driver_data<dc_state>(); |
| 1199 | state->dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_OPLST; |
| 1200 | state->dc_update_interrupt_status(); |
| 1201 | } |
| 1202 | |
| 1203 | TIMER_CALLBACK_MEMBER(powervr2_device::transfer_opaque_modifier_volume_list_irq) |
| 1204 | { |
| 1205 | dc_state *state = machine().driver_data<dc_state>(); |
| 1206 | state->dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_OPMV; |
| 1207 | state->dc_update_interrupt_status(); |
| 1208 | } |
| 1209 | |
| 1210 | TIMER_CALLBACK_MEMBER(powervr2_device::transfer_translucent_list_irq) |
| 1211 | { |
| 1212 | dc_state *state = machine().driver_data<dc_state>(); |
| 1213 | state->dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_TRLST; |
| 1214 | state->dc_update_interrupt_status(); |
| 1215 | } |
| 1216 | |
| 1217 | TIMER_CALLBACK_MEMBER(powervr2_device::transfer_translucent_modifier_volume_list_irq) |
| 1218 | { |
| 1219 | dc_state *state = machine().driver_data<dc_state>(); |
| 1220 | state->dc_sysctrl_regs[SB_ISTNRM] |= IST_EOXFER_TRMV; |
| 1221 | state->dc_update_interrupt_status(); |
| 1222 | } |
| 1223 | |
| 1224 | TIMER_CALLBACK_MEMBER(powervr2_device::transfer_punch_through_list_irq) |
| 1225 | { |
| 1226 | dc_state *state = machine().driver_data<dc_state>(); |
| 1227 | state->dc_sysctrl_regs[SB_ISTNRM] |= (1 << 21); |
| 1228 | state->dc_update_interrupt_status(); |
| 1229 | } |
| 1230 | |
| 1231 | void powervr2_device::process_ta_fifo() |
| 1232 | { |
| 1233 | /* first byte in the buffer is the Parameter Control Word |
| 1234 | |
| 1235 | pppp pppp gggg gggg oooo oooo oooo oooo |
| 1236 | |
| 1237 | p = para control |
| 1238 | g = group control |
| 1239 | o = object control |
| 1240 | |
| 1241 | */ |
| 1242 | |
| 1243 | receiveddata *rd = &grab[grabsel]; |
| 1244 | |
| 1245 | // Para Control |
| 1246 | paracontrol=(tafifo_buff[0] >> 24) & 0xff; |
| 1247 | // 0 end of list |
| 1248 | // 1 user tile clip |
| 1249 | // 2 object list set |
| 1250 | // 3 reserved |
| 1251 | // 4 polygon/modifier volume |
| 1252 | // 5 sprite |
| 1253 | // 6 reserved |
| 1254 | // 7 vertex |
| 1255 | paratype=(paracontrol >> 5) & 7; |
| 1256 | endofstrip=(paracontrol >> 4) & 1; |
| 1257 | listtype=(paracontrol >> 0) & 7; |
| 1258 | if ((paratype >= 4) && (paratype <= 6)) |
| 1259 | { |
| 1260 | global_paratype = paratype; |
| 1261 | // Group Control |
| 1262 | groupcontrol=(tafifo_buff[0] >> 16) & 0xff; |
| 1263 | groupen=(groupcontrol >> 7) & 1; |
| 1264 | striplen=(groupcontrol >> 2) & 3; |
| 1265 | userclip=(groupcontrol >> 0) & 3; |
| 1266 | // Obj Control |
| 1267 | objcontrol=(tafifo_buff[0] >> 0) & 0xffff; |
| 1268 | shadow=(objcontrol >> 7) & 1; |
| 1269 | volume=(objcontrol >> 6) & 1; |
| 1270 | coltype=(objcontrol >> 4) & 3; |
| 1271 | texture=(objcontrol >> 3) & 1; |
| 1272 | offfset=(objcontrol >> 2) & 1; |
| 1273 | gouraud=(objcontrol >> 1) & 1; |
| 1274 | uv16bit=(objcontrol >> 0) & 1; |
| 1275 | } |
| 1276 | |
| 1277 | // check if we need 8 words more |
| 1278 | if (tafifo_mask == 7) |
| 1279 | { |
| 1280 | parameterconfig = pvr_parameterconfig[objcontrol & 0x3d]; |
| 1281 | // decide number of words per vertex |
| 1282 | if (paratype == 7) |
| 1283 | { |
| 1284 | if ((global_paratype == 5) || (tafifo_listtype == 1) || (tafifo_listtype == 3)) |
| 1285 | tafifo_vertexwords = 16; |
| 1286 | if (tafifo_vertexwords == 16) |
| 1287 | { |
| 1288 | tafifo_mask = 15; |
| 1289 | tafifo_pos = 8; |
| 1290 | return; |
| 1291 | } |
| 1292 | } |
| 1293 | // decide number of words when not a vertex |
| 1294 | tafifo_vertexwords=pvr_wordsvertex[parameterconfig]; |
| 1295 | if ((paratype == 4) && ((listtype != 1) && (listtype != 3))) |
| 1296 | if (pvr_wordspolygon[parameterconfig] == 16) |
| 1297 | { |
| 1298 | tafifo_mask = 15; |
| 1299 | tafifo_pos = 8; |
| 1300 | return; |
| 1301 | } |
| 1302 | } |
| 1303 | tafifo_mask = 7; |
| 1304 | |
| 1305 | // now we heve all the needed words |
| 1306 | // here we should generate the data for the various tiles |
| 1307 | // for now, just interpret their meaning |
| 1308 | if (paratype == 0) |
| 1309 | { // end of list |
| 1310 | #if DEBUG_PVRDLIST |
| 1311 | mame_printf_verbose("Para Type 0 End of List\n"); |
| 1312 | #endif |
| 1313 | /* Process transfer FIFO done irqs here */ |
| 1314 | /* FIXME: timing of these */ |
| 1315 | switch (tafifo_listtype) |
| 1316 | { |
| 1317 | case 0: machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(powervr2_device::transfer_opaque_list_irq), this)); break; |
| 1318 | case 1: machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(powervr2_device::transfer_opaque_modifier_volume_list_irq), this)); break; |
| 1319 | case 2: machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(powervr2_device::transfer_translucent_list_irq), this)); break; |
| 1320 | case 3: machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(powervr2_device::transfer_translucent_modifier_volume_list_irq), this)); break; |
| 1321 | case 4: machine().scheduler().timer_set(attotime::from_usec(100), timer_expired_delegate(FUNC(powervr2_device::transfer_punch_through_list_irq), this)); break; |
| 1322 | } |
| 1323 | tafifo_listtype= -1; // no list being received |
| 1324 | listtype_used |= (2+8); |
| 1325 | } |
| 1326 | else if (paratype == 1) |
| 1327 | { // user tile clip |
| 1328 | #if DEBUG_PVRDLIST |
| 1329 | mame_printf_verbose("Para Type 1 User Tile Clip\n"); |
| 1330 | mame_printf_verbose(" (%d , %d)-(%d , %d)\n", tafifo_buff[4], tafifo_buff[5], tafifo_buff[6], tafifo_buff[7]); |
| 1331 | #endif |
| 1332 | } |
| 1333 | else if (paratype == 2) |
| 1334 | { // object list set |
| 1335 | #if DEBUG_PVRDLIST |
| 1336 | mame_printf_verbose("Para Type 2 Object List Set at %08x\n", tafifo_buff[1]); |
| 1337 | mame_printf_verbose(" (%d , %d)-(%d , %d)\n", tafifo_buff[4], tafifo_buff[5], tafifo_buff[6], tafifo_buff[7]); |
| 1338 | #endif |
| 1339 | } |
| 1340 | else if (paratype == 3) |
| 1341 | { |
| 1342 | #if DEBUG_PVRDLIST |
| 1343 | mame_printf_verbose("Para Type %x Unknown!\n", tafifo_buff[0]); |
| 1344 | #endif |
| 1345 | } |
| 1346 | else |
| 1347 | { // global parameter or vertex parameter |
| 1348 | #if DEBUG_PVRDLIST |
| 1349 | mame_printf_verbose("Para Type %d", paratype); |
| 1350 | if (paratype == 7) |
| 1351 | mame_printf_verbose(" End of Strip %d", endofstrip); |
| 1352 | if (listtype_used & 3) |
| 1353 | mame_printf_verbose(" List Type %d", listtype); |
| 1354 | mame_printf_verbose("\n"); |
| 1355 | #endif |
| 1356 | |
| 1357 | // set type of list currently being received |
| 1358 | if ((paratype == 4) || (paratype == 5) || (paratype == 6)) |
| 1359 | { |
| 1360 | if (tafifo_listtype < 0) |
| 1361 | { |
| 1362 | tafifo_listtype = listtype; |
| 1363 | } |
| 1364 | } |
| 1365 | listtype_used = listtype_used ^ (listtype_used & 3); |
| 1366 | |
| 1367 | if ((paratype == 4) || (paratype == 5)) |
| 1368 | { // quad or polygon |
| 1369 | depthcomparemode=(tafifo_buff[1] >> 29) & 7; |
| 1370 | cullingmode=(tafifo_buff[1] >> 27) & 3; |
| 1371 | zwritedisable=(tafifo_buff[1] >> 26) & 1; |
| 1372 | cachebypass=(tafifo_buff[1] >> 21) & 1; |
| 1373 | dcalcctrl=(tafifo_buff[1] >> 20) & 1; |
| 1374 | volumeinstruction=(tafifo_buff[1] >> 29) & 7; |
| 1375 | |
| 1376 | //textureusize=1 << (3+((tafifo_buff[2] >> 3) & 7)); |
| 1377 | //texturevsize=1 << (3+(tafifo_buff[2] & 7)); |
| 1378 | texturesizes=tafifo_buff[2] & 0x3f; |
| 1379 | blend_mode = tafifo_buff[2] >> 26; |
| 1380 | srcselect=(tafifo_buff[2] >> 25) & 1; |
| 1381 | dstselect=(tafifo_buff[2] >> 24) & 1; |
| 1382 | fogcontrol=(tafifo_buff[2] >> 22) & 3; |
| 1383 | colorclamp=(tafifo_buff[2] >> 21) & 1; |
| 1384 | use_alpha = (tafifo_buff[2] >> 20) & 1; |
| 1385 | ignoretexalpha=(tafifo_buff[2] >> 19) & 1; |
| 1386 | flipuv=(tafifo_buff[2] >> 17) & 3; |
| 1387 | clampuv=(tafifo_buff[2] >> 15) & 3; |
| 1388 | filtermode=(tafifo_buff[2] >> 13) & 3; |
| 1389 | sstexture=(tafifo_buff[2] >> 12) & 1; |
| 1390 | mmdadjust=(tafifo_buff[2] >> 8) & 1; |
| 1391 | tsinstruction=(tafifo_buff[2] >> 6) & 3; |
| 1392 | if (texture == 1) |
| 1393 | { |
| 1394 | textureaddress=(tafifo_buff[3] & 0x1FFFFF) << 3; |
| 1395 | scanorder=(tafifo_buff[3] >> 26) & 1; |
| 1396 | pixelformat=(tafifo_buff[3] >> 27) & 7; |
| 1397 | mipmapped=(tafifo_buff[3] >> 31) & 1; |
| 1398 | vqcompressed=(tafifo_buff[3] >> 30) & 1; |
| 1399 | strideselect=(tafifo_buff[3] >> 25) & 1; |
| 1400 | paletteselector=(tafifo_buff[3] >> 21) & 0x3F; |
| 1401 | #if DEBUG_PVRDLIST |
| 1402 | mame_printf_verbose(" Texture at %08x format %d\n", (tafifo_buff[3] & 0x1FFFFF) << 3, pixelformat); |
| 1403 | #endif |
| 1404 | } |
| 1405 | if (paratype == 4) |
| 1406 | { // polygon or mv |
| 1407 | if ((tafifo_listtype == 1) || (tafifo_listtype == 3)) |
| 1408 | { |
| 1409 | #if DEBUG_PVRDLIST |
| 1410 | mame_printf_verbose(" Modifier Volume\n"); |
| 1411 | #endif |
| 1412 | } |
| 1413 | else |
| 1414 | { |
| 1415 | #if DEBUG_PVRDLIST |
| 1416 | mame_printf_verbose(" Polygon\n"); |
| 1417 | #endif |
| 1418 | } |
| 1419 | } |
| 1420 | if (paratype == 5) |
| 1421 | { // quad |
| 1422 | #if DEBUG_PVRDLIST |
| 1423 | mame_printf_verbose(" Sprite\n"); |
| 1424 | #endif |
| 1425 | } |
| 1426 | } |
| 1427 | |
| 1428 | if (paratype == 7) |
| 1429 | { // vertex |
| 1430 | if ((tafifo_listtype == 1) || (tafifo_listtype == 3)) |
| 1431 | { |
| 1432 | #if DEBUG_PVRDLIST |
| 1433 | mame_printf_verbose(" Vertex modifier volume"); |
| 1434 | mame_printf_verbose(" A(%f,%f,%f) B(%f,%f,%f) C(%f,%f,%f)", u2f(tafifo_buff[1]), u2f(tafifo_buff[2]), |
| 1435 | u2f(tafifo_buff[3]), u2f(tafifo_buff[4]), u2f(tafifo_buff[5]), u2f(tafifo_buff[6]), u2f(tafifo_buff[7]), |
| 1436 | u2f(tafifo_buff[8]), u2f(tafifo_buff[9])); |
| 1437 | mame_printf_verbose("\n"); |
| 1438 | #endif |
| 1439 | } |
| 1440 | else if (global_paratype == 5) |
| 1441 | { |
| 1442 | #if DEBUG_PVRDLIST |
| 1443 | mame_printf_verbose(" Vertex sprite"); |
| 1444 | mame_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]), |
| 1445 | u2f(tafifo_buff[3]), u2f(tafifo_buff[4]), u2f(tafifo_buff[5]), u2f(tafifo_buff[6]), u2f(tafifo_buff[7]), |
| 1446 | u2f(tafifo_buff[8]), u2f(tafifo_buff[9]), u2f(tafifo_buff[10]), u2f(tafifo_buff[11])); |
| 1447 | mame_printf_verbose("\n"); |
| 1448 | #endif |
| 1449 | if (texture == 1) |
| 1450 | { |
| 1451 | if (rd->verts_size <= 65530) |
| 1452 | { |
| 1453 | strip *ts; |
| 1454 | vert *tv = &rd->verts[rd->verts_size]; |
| 1455 | tv[0].x = u2f(tafifo_buff[0x1]); |
| 1456 | tv[0].y = u2f(tafifo_buff[0x2]); |
| 1457 | tv[0].w = u2f(tafifo_buff[0x3]); |
| 1458 | tv[1].x = u2f(tafifo_buff[0x4]); |
| 1459 | tv[1].y = u2f(tafifo_buff[0x5]); |
| 1460 | tv[1].w = u2f(tafifo_buff[0x6]); |
| 1461 | tv[3].x = u2f(tafifo_buff[0x7]); |
| 1462 | tv[3].y = u2f(tafifo_buff[0x8]); |
| 1463 | tv[3].w = u2f(tafifo_buff[0x9]); |
| 1464 | tv[2].x = u2f(tafifo_buff[0xa]); |
| 1465 | tv[2].y = u2f(tafifo_buff[0xb]); |
| 1466 | tv[2].w = tv[0].w+tv[3].w-tv[1].w; |
| 1467 | tv[0].u = u2f(tafifo_buff[0xd] & 0xffff0000); |
| 1468 | tv[0].v = u2f(tafifo_buff[0xd] << 16); |
| 1469 | tv[1].u = u2f(tafifo_buff[0xe] & 0xffff0000); |
| 1470 | tv[1].v = u2f(tafifo_buff[0xe] << 16); |
| 1471 | tv[3].u = u2f(tafifo_buff[0xf] & 0xffff0000); |
| 1472 | tv[3].v = u2f(tafifo_buff[0xf] << 16); |
| 1473 | tv[2].u = tv[0].u+tv[3].u-tv[1].u; |
| 1474 | tv[2].v = tv[0].v+tv[3].v-tv[1].v; |
| 1475 | |
| 1476 | ts = &rd->strips[rd->strips_size++]; |
| 1477 | tex_get_info(&ts->ti); |
| 1478 | ts->svert = rd->verts_size; |
| 1479 | ts->evert = rd->verts_size + 3; |
| 1480 | |
| 1481 | rd->verts_size += 4; |
| 1482 | } |
| 1483 | } |
| 1484 | } |
| 1485 | else if (global_paratype == 4) |
| 1486 | { |
| 1487 | #if DEBUG_PVRDLIST |
| 1488 | mame_printf_verbose(" Vertex polygon"); |
| 1489 | mame_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])); |
| 1490 | mame_printf_verbose("\n"); |
| 1491 | #endif |
| 1492 | if (rd->verts_size <= 65530) |
| 1493 | { |
| 1494 | /* add a vertex to our list */ |
| 1495 | /* this is used for 3d stuff, ie most of the graphics (see guilty gear, confidential mission, maze of the kings etc.) */ |
| 1496 | /* -- this is also wildly inaccurate! */ |
| 1497 | vert *tv = &rd->verts[rd->verts_size]; |
| 1498 | |
| 1499 | tv->x=u2f(tafifo_buff[1]); |
| 1500 | tv->y=u2f(tafifo_buff[2]); |
| 1501 | tv->w=u2f(tafifo_buff[3]); |
| 1502 | tv->u=u2f(tafifo_buff[4]); |
| 1503 | tv->v=u2f(tafifo_buff[5]); |
| 1504 | |
| 1505 | |
| 1506 | if((!rd->strips_size) || |
| 1507 | rd->strips[rd->strips_size-1].evert != -1) |
| 1508 | { |
| 1509 | strip *ts = &rd->strips[rd->strips_size++]; |
| 1510 | tex_get_info(&ts->ti); |
| 1511 | ts->svert = rd->verts_size; |
| 1512 | ts->evert = -1; |
| 1513 | } |
| 1514 | if(endofstrip) |
| 1515 | rd->strips[rd->strips_size-1].evert = rd->verts_size; |
| 1516 | rd->verts_size++; |
| 1517 | } |
| 1518 | } |
| 1519 | } |
| 1520 | } |
| 1521 | } |
| 1522 | |
| 1523 | WRITE64_MEMBER( powervr2_device::ta_fifo_poly_w ) |
| 1524 | { |
| 1525 | if (mem_mask == U64(0xffffffffffffffff)) // 64 bit |
| 1526 | { |
| 1527 | tafifo_buff[tafifo_pos]=(UINT32)data; |
| 1528 | tafifo_buff[tafifo_pos+1]=(UINT32)(data >> 32); |
| 1529 | #if DEBUG_FIFO_POLY |
| 1530 | mame_printf_debug("ta_fifo_poly_w: Unmapped write64 %08x = %" I64FMT "x -> %08x %08x\n", 0x10000000+offset*8, data, tafifo_buff[tafifo_pos], tafifo_buff[tafifo_pos+1]); |
| 1531 | #endif |
| 1532 | tafifo_pos += 2; |
| 1533 | } |
| 1534 | else |
| 1535 | { |
| 1536 | fatalerror("ta_fifo_poly_w: Only 64 bit writes supported!\n"); |
| 1537 | } |
| 1538 | |
| 1539 | tafifo_pos &= tafifo_mask; |
| 1540 | |
| 1541 | // if the command is complete, process it |
| 1542 | if (tafifo_pos == 0) |
| 1543 | process_ta_fifo(); |
| 1544 | |
| 1545 | } |
| 1546 | |
| 1547 | WRITE64_MEMBER( powervr2_device::ta_fifo_yuv_w ) |
| 1548 | { |
| 1549 | //dc_state *state = space.machine().driver_data<dc_state>(); |
| 1550 | |
| 1551 | // int reg; |
| 1552 | // UINT64 shift; |
| 1553 | // UINT32 dat; |
| 1554 | |
| 1555 | // reg = decode_reg_64(offset, mem_mask, &shift); |
| 1556 | // dat = (UINT32)(data >> shift); |
| 1557 | |
| 1558 | // printf("YUV FIFO: [%08x=%x] write %" I64FMT "x to %x, mask %" I64FMT "x %08x\n", 0x10800000+reg*4, dat, data, offset, mem_mask,test); |
| 1559 | } |
| 1560 | |
| 1561 | // SB_LMMODE0 |
| 1562 | WRITE64_MEMBER(powervr2_device::ta_texture_directpath0_w ) |
| 1563 | { |
| 1564 | int mode = pvrctrl_regs[SB_LMMODE0]&1; |
| 1565 | if (mode&1) |
| 1566 | { |
| 1567 | printf("ta_texture_directpath0_w 32-bit access!\n"); |
| 1568 | COMBINE_DATA(&dc_framebuffer_ram[offset]); |
| 1569 | } |
| 1570 | else |
| 1571 | { |
| 1572 | COMBINE_DATA(&dc_texture_ram[offset]); |
| 1573 | } |
| 1574 | } |
| 1575 | |
| 1576 | // SB_LMMODE1 |
| 1577 | WRITE64_MEMBER(powervr2_device::ta_texture_directpath1_w ) |
| 1578 | { |
| 1579 | int mode = pvrctrl_regs[SB_LMMODE1]&1; |
| 1580 | if (mode&1) |
| 1581 | { |
| 1582 | printf("ta_texture_directpath1_w 32-bit access!\n"); |
| 1583 | COMBINE_DATA(&dc_framebuffer_ram[offset]); |
| 1584 | } |
| 1585 | else |
| 1586 | { |
| 1587 | COMBINE_DATA(&dc_texture_ram[offset]); |
| 1588 | } |
| 1589 | } |
| 1590 | |
| 1591 | /* test video start */ |
| 1592 | UINT32 powervr2_device::dilate0(UINT32 value,int bits) // dilate first "bits" bits in "value" |
| 1593 | { |
| 1594 | UINT32 x,m1,m2,m3; |
| 1595 | int a; |
| 1596 | |
| 1597 | x = value; |
| 1598 | for (a=0;a < bits;a++) |
| 1599 | { |
| 1600 | m2 = 1 << (a << 1); |
| 1601 | m1 = m2 - 1; |
| 1602 | m3 = (~m1) << 1; |
| 1603 | x = (x & m1) + (x & m2) + ((x & m3) << 1); |
| 1604 | } |
| 1605 | return x; |
| 1606 | } |
| 1607 | |
| 1608 | UINT32 powervr2_device::dilate1(UINT32 value,int bits) // dilate first "bits" bits in "value" |
| 1609 | { |
| 1610 | UINT32 x,m1,m2,m3; |
| 1611 | int a; |
| 1612 | |
| 1613 | x = value; |
| 1614 | for (a=0;a < bits;a++) |
| 1615 | { |
| 1616 | m2 = 1 << (a << 1); |
| 1617 | m1 = m2 - 1; |
| 1618 | m3 = (~m1) << 1; |
| 1619 | x = (x & m1) + ((x & m2) << 1) + ((x & m3) << 1); |
| 1620 | } |
| 1621 | return x; |
| 1622 | } |
| 1623 | |
| 1624 | void powervr2_device::computedilated() |
| 1625 | { |
| 1626 | int a,b; |
| 1627 | |
| 1628 | for (b=0;b <= 14;b++) |
| 1629 | for (a=0;a < 1024;a++) { |
| 1630 | dilated0[b][a]=dilate0(a,b); |
| 1631 | dilated1[b][a]=dilate1(a,b); |
| 1632 | } |
| 1633 | for (b=0;b <= 7;b++) |
| 1634 | for (a=0;a <= 7;a++) |
| 1635 | dilatechose[(b << 3) + a]=3+(a < b ? a : b); |
| 1636 | } |
| 1637 | |
| 1638 | 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) |
| 1639 | { |
| 1640 | int xxl, xxr; |
| 1641 | float dx, ddx, dudx, dvdx, dwdx; |
| 1642 | UINT32 *tdata; |
| 1643 | float *wbufline; |
| 1644 | |
| 1645 | // untextured cases aren't handled |
| 1646 | if (!ti->textured) return; |
| 1647 | |
| 1648 | if(xr < 0 || xl >= 640) |
| 1649 | return; |
| 1650 | |
| 1651 | xxl = round(xl); |
| 1652 | xxr = round(xr); |
| 1653 | |
| 1654 | if(xxl == xxr) |
| 1655 | return; |
| 1656 | |
| 1657 | dx = xr-xl; |
| 1658 | dudx = (ur-ul)/dx; |
| 1659 | dvdx = (vr-vl)/dx; |
| 1660 | dwdx = (wr-wl)/dx; |
| 1661 | |
| 1662 | if(xxl < 0) |
| 1663 | xxl = 0; |
| 1664 | if(xxr > 640) |
| 1665 | xxr = 640; |
| 1666 | |
| 1667 | // Target the pixel center |
| 1668 | ddx = xxl + 0.5 - xl; |
| 1669 | ul += ddx*dudx; |
| 1670 | vl += ddx*dvdx; |
| 1671 | wl += ddx*dwdx; |
| 1672 | |
| 1673 | |
| 1674 | tdata = &bitmap.pix32(y, xxl); |
| 1675 | wbufline = &wbuffer[y][xxl]; |
| 1676 | |
| 1677 | while(xxl < xxr) { |
| 1678 | if((wl >= *wbufline)) { |
| 1679 | UINT32 c; |
| 1680 | float u = ul/wl; |
| 1681 | float v = vl/wl; |
| 1682 | |
| 1683 | /* |
| 1684 | if(ti->flip_u) |
| 1685 | { |
| 1686 | u = ti->sizex - u; |
| 1687 | } |
| 1688 | |
| 1689 | if(ti->flip_v) |
| 1690 | { |
| 1691 | v = ti->sizey - v; |
| 1692 | }*/ |
| 1693 | |
| 1694 | c = (this->*(ti->r))(ti, u, v); |
| 1695 | |
| 1696 | // debug dip to turn on/off bilinear filtering, it's slooooow |
| 1697 | if (debug_dip_status&0x1) |
| 1698 | { |
| 1699 | if(ti->filter_mode >= TEX_FILTER_BILINEAR) |
| 1700 | { |
| 1701 | UINT32 c1 = (this->*(ti->r))(ti, u+1.0, v); |
| 1702 | UINT32 c2 = (this->*(ti->r))(ti, u+1.0, v+1.0); |
| 1703 | UINT32 c3 = (this->*(ti->r))(ti, u, v+1.0); |
| 1704 | c = bilinear_filter(c, c1, c2, c3, u, v); |
| 1705 | } |
| 1706 | } |
| 1707 | |
| 1708 | if(c & 0xff000000) { |
| 1709 | *tdata = ti->blend(c, *tdata); |
| 1710 | *wbufline = wl; |
| 1711 | } |
| 1712 | } |
| 1713 | wbufline++; |
| 1714 | tdata++; |
| 1715 | |
| 1716 | ul += dudx; |
| 1717 | vl += dvdx; |
| 1718 | wl += dwdx; |
| 1719 | xxl ++; |
| 1720 | } |
| 1721 | } |
| 1722 | |
| 1723 | void powervr2_device::render_span(bitmap_rgb32 &bitmap, texinfo *ti, |
| 1724 | float y0, float y1, |
| 1725 | float xl, float xr, |
| 1726 | float ul, float ur, |
| 1727 | float vl, float vr, |
| 1728 | float wl, float wr, |
| 1729 | float dxldy, float dxrdy, |
| 1730 | float duldy, float durdy, |
| 1731 | float dvldy, float dvrdy, |
| 1732 | float dwldy, float dwrdy) |
| 1733 | { |
| 1734 | float dy; |
| 1735 | int yy0, yy1; |
| 1736 | |
| 1737 | if(y1 <= 0) |
| 1738 | return; |
| 1739 | if(y1 > 480) |
| 1740 | y1 = 480; |
| 1741 | |
| 1742 | if(y0 < 0) { |
| 1743 | xl += -dxldy*y0; |
| 1744 | xr += -dxrdy*y0; |
| 1745 | ul += -duldy*y0; |
| 1746 | ur += -durdy*y0; |
| 1747 | vl += -dvldy*y0; |
| 1748 | vr += -dvrdy*y0; |
| 1749 | wl += -dwldy*y0; |
| 1750 | wr += -dwrdy*y0; |
| 1751 | y0 = 0; |
| 1752 | } |
| 1753 | |
| 1754 | yy0 = round(y0); |
| 1755 | yy1 = round(y1); |
| 1756 | |
| 1757 | if((yy0 < 0 && y0 > 0) || (yy1 < 0 && y1 > 0)) //temp handling of int32 overflow, needed by hotd2/totd |
| 1758 | return; |
| 1759 | |
| 1760 | dy = yy0+0.5-y0; |
| 1761 | |
| 1762 | if(0) |
| 1763 | fprintf(stderr, "%f %f %f %f -> %f %f | %f %f -> %f %f\n", |
| 1764 | y0, |
| 1765 | dy, dxldy, dxrdy, dy*dxldy, dy*dxrdy, |
| 1766 | xl, xr, xl + dy*dxldy, xr + dy*dxrdy); |
| 1767 | xl += dy*dxldy; |
| 1768 | xr += dy*dxrdy; |
| 1769 | ul += dy*duldy; |
| 1770 | ur += dy*durdy; |
| 1771 | vl += dy*dvldy; |
| 1772 | vr += dy*dvrdy; |
| 1773 | wl += dy*dwldy; |
| 1774 | wr += dy*dwrdy; |
| 1775 | |
| 1776 | while(yy0 < yy1) { |
| 1777 | render_hline(bitmap, ti, yy0, xl, xr, ul, ur, vl, vr, wl, wr); |
| 1778 | |
| 1779 | xl += dxldy; |
| 1780 | xr += dxrdy; |
| 1781 | ul += duldy; |
| 1782 | ur += durdy; |
| 1783 | vl += dvldy; |
| 1784 | vr += dvrdy; |
| 1785 | wl += dwldy; |
| 1786 | wr += dwrdy; |
| 1787 | yy0 ++; |
| 1788 | } |
| 1789 | } |
| 1790 | |
| 1791 | void powervr2_device::sort_vertices(const vert *v, int *i0, int *i1, int *i2) |
| 1792 | { |
| 1793 | float miny, maxy; |
| 1794 | int imin, imax, imid; |
| 1795 | miny = maxy = v[0].y; |
| 1796 | imin = imax = 0; |
| 1797 | |
| 1798 | if(miny > v[1].y) { |
| 1799 | miny = v[1].y; |
| 1800 | imin = 1; |
| 1801 | } else if(maxy < v[1].y) { |
| 1802 | maxy = v[1].y; |
| 1803 | imax = 1; |
| 1804 | } |
| 1805 | |
| 1806 | if(miny > v[2].y) { |
| 1807 | miny = v[2].y; |
| 1808 | imin = 2; |
| 1809 | } else if(maxy < v[2].y) { |
| 1810 | maxy = v[2].y; |
| 1811 | imax = 2; |
| 1812 | } |
| 1813 | |
| 1814 | imid = (imin == 0 || imax == 0) ? (imin == 1 || imax == 1) ? 2 : 1 : 0; |
| 1815 | |
| 1816 | *i0 = imin; |
| 1817 | *i1 = imid; |
| 1818 | *i2 = imax; |
| 1819 | } |
| 1820 | |
| 1821 | |
| 1822 | void powervr2_device::render_tri_sorted(bitmap_rgb32 &bitmap, texinfo *ti, const vert *v0, const vert *v1, const vert *v2) |
| 1823 | { |
| 1824 | float dy01, dy02, dy12; |
| 1825 | |
| 1826 | float dx01dy, dx02dy, dx12dy, du01dy, du02dy, du12dy, dv01dy, dv02dy, dv12dy, dw01dy, dw02dy, dw12dy; |
| 1827 | |
| 1828 | if(v0->y >= 480 || v2->y < 0) |
| 1829 | return; |
| 1830 | |
| 1831 | dy01 = v1->y - v0->y; |
| 1832 | dy02 = v2->y - v0->y; |
| 1833 | dy12 = v2->y - v1->y; |
| 1834 | |
| 1835 | dx01dy = dy01 ? (v1->x-v0->x)/dy01 : 0; |
| 1836 | dx02dy = dy02 ? (v2->x-v0->x)/dy02 : 0; |
| 1837 | dx12dy = dy12 ? (v2->x-v1->x)/dy12 : 0; |
| 1838 | |
| 1839 | du01dy = dy01 ? (v1->u-v0->u)/dy01 : 0; |
| 1840 | du02dy = dy02 ? (v2->u-v0->u)/dy02 : 0; |
| 1841 | du12dy = dy12 ? (v2->u-v1->u)/dy12 : 0; |
| 1842 | |
| 1843 | dv01dy = dy01 ? (v1->v-v0->v)/dy01 : 0; |
| 1844 | dv02dy = dy02 ? (v2->v-v0->v)/dy02 : 0; |
| 1845 | dv12dy = dy12 ? (v2->v-v1->v)/dy12 : 0; |
| 1846 | |
| 1847 | dw01dy = dy01 ? (v1->w-v0->w)/dy01 : 0; |
| 1848 | dw02dy = dy02 ? (v2->w-v0->w)/dy02 : 0; |
| 1849 | dw12dy = dy12 ? (v2->w-v1->w)/dy12 : 0; |
| 1850 | |
| 1851 | if(!dy01) { |
| 1852 | if(!dy12) |
| 1853 | return; |
| 1854 | |
| 1855 | if(v1->x > v0->x) |
| 1856 | render_span(bitmap, ti, v1->y, v2->y, v0->x, v1->x, v0->u, v1->u, v0->v, v1->v, v0->w, v1->w, dx02dy, dx12dy, du02dy, du12dy, dv02dy, dv12dy, dw02dy, dw12dy); |
| 1857 | else |
| 1858 | render_span(bitmap, ti, v1->y, v2->y, v1->x, v0->x, v1->u, v0->u, v1->v, v0->v, v1->w, v0->w, dx12dy, dx02dy, du12dy, du02dy, dv12dy, dv02dy, dw12dy, dw02dy); |
| 1859 | |
| 1860 | } else if(!dy12) { |
| 1861 | if(v2->x > v1->x) |
| 1862 | render_span(bitmap, ti, v0->y, v1->y, v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, dx01dy, dx02dy, du01dy, du02dy, dv01dy, dv02dy, dw01dy, dw02dy); |
| 1863 | else |
| 1864 | render_span(bitmap, ti, v0->y, v1->y, v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, dx02dy, dx01dy, du02dy, du01dy, dv02dy, dv01dy, dw02dy, dw01dy); |
| 1865 | |
| 1866 | } else { |
| 1867 | if(dx01dy < dx02dy) { |
| 1868 | render_span(bitmap, ti, v0->y, v1->y, |
| 1869 | v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, |
| 1870 | dx01dy, dx02dy, du01dy, du02dy, dv01dy, dv02dy, dw01dy, dw02dy); |
| 1871 | render_span(bitmap, ti, v1->y, v2->y, |
| 1872 | v1->x, v0->x + dx02dy*dy01, v1->u, v0->u + du02dy*dy01, v1->v, v0->v + dv02dy*dy01, v1->w, v0->w + dw02dy*dy01, |
| 1873 | dx12dy, dx02dy, du12dy, du02dy, dv12dy, dv02dy, dw12dy, dw02dy); |
| 1874 | } else { |
| 1875 | render_span(bitmap, ti, v0->y, v1->y, |
| 1876 | v0->x, v0->x, v0->u, v0->u, v0->v, v0->v, v0->w, v0->w, |
| 1877 | dx02dy, dx01dy, du02dy, du01dy, dv02dy, dv01dy, dw02dy, dw01dy); |
| 1878 | render_span(bitmap, ti, v1->y, v2->y, |
| 1879 | v0->x + dx02dy*dy01, v1->x, v0->u + du02dy*dy01, v1->u, v0->v + dv02dy*dy01, v1->v, v0->w + dw02dy*dy01, v1->w, |
| 1880 | dx02dy, dx12dy, du02dy, du12dy, dv02dy, dv12dy, dw02dy, dw12dy); |
| 1881 | } |
| 1882 | } |
| 1883 | } |
| 1884 | |
| 1885 | void powervr2_device::render_tri(bitmap_rgb32 &bitmap, texinfo *ti, const vert *v) |
| 1886 | { |
| 1887 | int i0, i1, i2; |
| 1888 | |
| 1889 | sort_vertices(v, &i0, &i1, &i2); |
| 1890 | render_tri_sorted(bitmap, ti, v+i0, v+i1, v+i2); |
| 1891 | } |
| 1892 | |
| 1893 | void powervr2_device::render_to_accumulation_buffer(bitmap_rgb32 &bitmap,const rectangle &cliprect) |
| 1894 | { |
| 1895 | dc_state *state = machine().driver_data<dc_state>(); |
| 1896 | address_space &space = state->m_maincpu->space(AS_PROGRAM); |
| 1897 | int cs,rs,ns; |
| 1898 | UINT32 c; |
| 1899 | #if 0 |
| 1900 | int stride; |
| 1901 | UINT16 *bmpaddr16; |
| 1902 | UINT32 k; |
| 1903 | #endif |
| 1904 | |
| 1905 | |
| 1906 | if (renderselect < 0) |
| 1907 | return; |
| 1908 | |
| 1909 | //printf("drawtest!\n"); |
| 1910 | |
| 1911 | rs=renderselect; |
| 1912 | c=pvrta_regs[ISP_BACKGND_T]; |
| 1913 | c=space.read_dword(0x05000000+((c&0xfffff8)>>1)+(3+3)*4); |
| 1914 | bitmap.fill(c, cliprect); |
| 1915 | |
| 1916 | |
| 1917 | ns=grab[rs].strips_size; |
| 1918 | if(ns) |
| 1919 | memset(wbuffer, 0x00, sizeof(wbuffer)); |
| 1920 | |
| 1921 | for (cs=0;cs < ns;cs++) |
| 1922 | { |
| 1923 | strip *ts = &grab[rs].strips[cs]; |
| 1924 | int sv = ts->svert; |
| 1925 | int ev = ts->evert; |
| 1926 | int i; |
| 1927 | if(ev == -1) |
| 1928 | continue; |
| 1929 | |
| 1930 | for(i=sv; i <= ev; i++) |
| 1931 | { |
| 1932 | vert *tv = grab[rs].verts + i; |
| 1933 | tv->u = tv->u * ts->ti.sizex * tv->w; |
| 1934 | tv->v = tv->v * ts->ti.sizey * tv->w; |
| 1935 | } |
| 1936 | |
| 1937 | for(i=sv; i <= ev-2; i++) |
| 1938 | { |
| 1939 | if (!(debug_dip_status&0x2)) |
| 1940 | render_tri(bitmap, &ts->ti, grab[rs].verts + i); |
| 1941 | |
| 1942 | } |
| 1943 | } |
| 1944 | grab[rs].busy=0; |
| 1945 | } |
| 1946 | |
| 1947 | // copies the accumulation buffer into the framebuffer, converting to the specified format |
| 1948 | // not accurate, ignores field stuff and just uses SOF1 for now |
| 1949 | // also ignores scale effects (can scale accumulation buffer to half size with filtering etc.) |
| 1950 | // also can specify dither etc. |
| 1951 | // basically, just a crude implementation! |
| 1952 | |
| 1953 | /* |
| 1954 | |
| 1955 | 0x0 0555 KRGB 16 bit (default) Bit 15 is the value of fb_kval 7. |
| 1956 | 0x1 565 RGB 16 bit |
| 1957 | 0x2 4444 ARGB 16 bit |
| 1958 | 0x3 1555 ARGB 16 bit The alpha value is determined by comparison with the value of fb_alpha_threshold. |
| 1959 | 0x4 888 RGB 24 bit packed |
| 1960 | 0x5 0888 KRGB 32 bit K is the value of fk_kval. |
| 1961 | 0x6 8888 ARGB 32 bit |
| 1962 | 0x7 Setting prohibited. |
| 1963 | |
| 1964 | */ |
| 1965 | |
| 1966 | void powervr2_device::pvr_accumulationbuffer_to_framebuffer(address_space &space, int x,int y) |
| 1967 | { |
| 1968 | // the accumulation buffer is always 8888 |
| 1969 | // |
| 1970 | // the standard format for the framebuffer appears to be 565 |
| 1971 | // yes, this means colour data is lost in the conversion |
| 1972 | |
| 1973 | UINT32 wc = pvrta_regs[FB_W_CTRL]; |
| 1974 | UINT32 stride = pvrta_regs[FB_W_LINESTRIDE]; |
| 1975 | UINT32 writeoffs = pvrta_regs[FB_W_SOF1]; |
| 1976 | |
| 1977 | UINT32* src; |
| 1978 | |
| 1979 | |
| 1980 | UINT8 packmode = wc & 0x7; |
| 1981 | |
| 1982 | switch (packmode) |
| 1983 | { |
| 1984 | // used by ringout |
| 1985 | case 0x00: //0555 KRGB |
| 1986 | { |
| 1987 | int xcnt,ycnt; |
| 1988 | for (ycnt=0;ycnt<32;ycnt++) |
| 1989 | { |
| 1990 | UINT32 realwriteoffs = 0x05000000 + writeoffs + (y+ycnt) * (stride<<3) + (x*2); |
| 1991 | src = &fake_accumulationbuffer_bitmap->pix32(y+ycnt, x); |
| 1992 | |
| 1993 | |
| 1994 | for (xcnt=0;xcnt<32;xcnt++) |
| 1995 | { |
| 1996 | // data starts in 8888 format, downsample it |
| 1997 | UINT32 data = src[xcnt]; |
| 1998 | UINT16 newdat = ((((data & 0x000000f8) >> 3)) << 0) | |
| 1999 | ((((data & 0x0000f800) >> 11)) << 5) | |
| 2000 | ((((data & 0x00f80000) >> 19)) << 10); |
| 2001 | |
| 2002 | space.write_word(realwriteoffs+xcnt*2, newdat); |
| 2003 | } |
| 2004 | } |
| 2005 | } |
| 2006 | break; |
| 2007 | |
| 2008 | // used by cleoftp |
| 2009 | case 0x01: //565 RGB 16 bit |
| 2010 | { |
| 2011 | int xcnt,ycnt; |
| 2012 | for (ycnt=0;ycnt<32;ycnt++) |
| 2013 | { |
| 2014 | UINT32 realwriteoffs = 0x05000000 + writeoffs + (y+ycnt) * (stride<<3) + (x*2); |
| 2015 | src = &fake_accumulationbuffer_bitmap->pix32(y+ycnt, x); |
| 2016 | |
| 2017 | |
| 2018 | for (xcnt=0;xcnt<32;xcnt++) |
| 2019 | { |
| 2020 | // data starts in 8888 format, downsample it |
| 2021 | UINT32 data = src[xcnt]; |
| 2022 | UINT16 newdat = ((((data & 0x000000f8) >> 3)) << 0) | |
| 2023 | ((((data & 0x0000fc00) >> 10)) << 5) | |
| 2024 | ((((data & 0x00f80000) >> 19)) << 11); |
| 2025 | |
| 2026 | space.write_word(realwriteoffs+xcnt*2, newdat); |
| 2027 | } |
| 2028 | } |
| 2029 | } |
| 2030 | break; |
| 2031 | |
| 2032 | case 0x02: |
| 2033 | printf("pvr_accumulationbuffer_to_framebuffer buffer to tile at %d,%d - unsupported pack mode %02x (4444 ARGB)\n",x,y,packmode); |
| 2034 | break; |
| 2035 | |
| 2036 | case 0x03: // 1555 ARGB 16 bit |
| 2037 | { |
| 2038 | int xcnt,ycnt; |
| 2039 | for (ycnt=0;ycnt<32;ycnt++) |
| 2040 | { |
| 2041 | UINT32 realwriteoffs = 0x05000000 + writeoffs + (y+ycnt) * (stride<<3) + (x*2); |
| 2042 | src = &fake_accumulationbuffer_bitmap->pix32(y+ycnt, x); |
| 2043 | |
| 2044 | |
| 2045 | for (xcnt=0;xcnt<32;xcnt++) |
| 2046 | { |
| 2047 | // data starts in 8888 format, downsample it |
| 2048 | UINT32 data = src[xcnt]; |
| 2049 | UINT16 newdat = ((((data & 0x000000f8) >> 3)) << 0) | |
| 2050 | ((((data & 0x0000f800) >> 11)) << 5) | |
| 2051 | ((((data & 0x00f80000) >> 19)) << 10); |
| 2052 | // alpha? |
| 2053 | |
| 2054 | space.write_word(realwriteoffs+xcnt*2, newdat); |
| 2055 | } |
| 2056 | } |
| 2057 | } |
| 2058 | break; |
| 2059 | |
| 2060 | // used by Suchie3 |
| 2061 | case 0x04: // 888 RGB 24-bit (HACK! should not downconvert and pvr_drawframebuffer should change accordingly) |
| 2062 | { |
| 2063 | int xcnt,ycnt; |
| 2064 | for (ycnt=0;ycnt<32;ycnt++) |
| 2065 | { |
| 2066 | UINT32 realwriteoffs = 0x05000000 + writeoffs + (y+ycnt) * (stride<<3) + (x*2); |
| 2067 | src = &fake_accumulationbuffer_bitmap->pix32(y+ycnt, x); |
| 2068 | |
| 2069 | |
| 2070 | for (xcnt=0;xcnt<32;xcnt++) |
| 2071 | { |
| 2072 | // data is 8888 format |
| 2073 | UINT32 data = src[xcnt]; |
| 2074 | UINT16 newdat = ((((data & 0x000000f8) >> 3)) << 0) | |
| 2075 | ((((data & 0x0000fc00) >> 10)) << 5) | |
| 2076 | ((((data & 0x00f80000) >> 19)) << 11); |
| 2077 | |
| 2078 | space.write_word(realwriteoffs+xcnt*2, newdat); |
| 2079 | } |
| 2080 | } |
| 2081 | } |
| 2082 | break; |
| 2083 | |
| 2084 | case 0x05: |
| 2085 | printf("pvr_accumulationbuffer_to_framebuffer buffer to tile at %d,%d - unsupported pack mode %02x (0888 KGB 32-bit)\n",x,y,packmode); |
| 2086 | break; |
| 2087 | |
| 2088 | case 0x06: // 8888 ARGB 32 bit (HACK! should not downconvert and pvr_drawframebuffer should change accordingly) |
| 2089 | { |
| 2090 | int xcnt,ycnt; |
| 2091 | for (ycnt=0;ycnt<32;ycnt++) |
| 2092 | { |
| 2093 | UINT32 realwriteoffs = 0x05000000 + writeoffs + (y+ycnt) * (stride<<3) + (x*2); |
| 2094 | src = &fake_accumulationbuffer_bitmap->pix32(y+ycnt, x); |
| 2095 | |
| 2096 | |
| 2097 | for (xcnt=0;xcnt<32;xcnt++) |
| 2098 | { |
| 2099 | // data is 8888 format |
| 2100 | UINT32 data = src[xcnt]; |
| 2101 | UINT16 newdat = ((((data & 0x000000f8) >> 3)) << 0) | |
| 2102 | ((((data & 0x0000fc00) >> 10)) << 5) | |
| 2103 | ((((data & 0x00f80000) >> 19)) << 11); |
| 2104 | |
| 2105 | space.write_word(realwriteoffs+xcnt*2, newdat); |
| 2106 | } |
| 2107 | } |
| 2108 | } |
| 2109 | break; |
| 2110 | |
| 2111 | case 0x07: |
| 2112 | printf("pvr_accumulationbuffer_to_framebuffer buffer to tile at %d,%d - unsupported pack mode %02x (Reserved! Don't Use!)\n",x,y,packmode); |
| 2113 | break; |
| 2114 | } |
| 2115 | |
| 2116 | |
| 2117 | } |
| 2118 | |
| 2119 | void powervr2_device::pvr_drawframebuffer(bitmap_rgb32 &bitmap,const rectangle &cliprect) |
| 2120 | { |
| 2121 | int x,y,dy,xi; |
| 2122 | UINT32 addrp; |
| 2123 | UINT32 *fbaddr; |
| 2124 | UINT32 c; |
| 2125 | UINT32 r,g,b; |
| 2126 | |
| 2127 | UINT32 wc = pvrta_regs[FB_R_CTRL]; |
| 2128 | UINT8 unpackmode = (wc & 0x0000000c) >>2; // aka fb_depth |
| 2129 | UINT8 enable = (wc & 0x00000001); |
| 2130 | |
| 2131 | // ?? |
| 2132 | if (!enable) return; |
| 2133 | |
| 2134 | // only for rgb565 framebuffer |
| 2135 | xi=((pvrta_regs[FB_R_SIZE] & 0x3ff)+1) << 1; |
| 2136 | dy=((pvrta_regs[FB_R_SIZE] >> 10) & 0x3ff)+1; |
| 2137 | |
| 2138 | dy++; |
| 2139 | dy*=2; // probably depends on interlace mode, fields etc... |
| 2140 | |
| 2141 | switch (unpackmode) |
| 2142 | { |
| 2143 | case 0x00: // 0555 RGB 16-bit, Cleo Fortune Plus |
| 2144 | // should upsample back to 8-bit output using fb_concat |
| 2145 | for (y=0;y <= dy;y++) |
| 2146 | { |
| 2147 | addrp=pvrta_regs[FB_R_SOF1]+y*xi*2; |
| 2148 | if(spg_pixel_double) |
| 2149 | { |
| 2150 | for (x=0;x < xi;x++) |
| 2151 | { |
| 2152 | fbaddr=&bitmap.pix32(y, x*2+0); |
| 2153 | c=*((reinterpret_cast<UINT16 *>(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2154 | |
| 2155 | b = (c & 0x001f) << 3; |
| 2156 | g = (c & 0x03e0) >> 2; |
| 2157 | r = (c & 0x7c00) >> 7; |
| 2158 | |
| 2159 | if (y<=cliprect.max_y) |
| 2160 | *fbaddr = b | (g<<8) | (r<<16); |
| 2161 | |
| 2162 | fbaddr=&bitmap.pix32(y, x*2+1); |
| 2163 | if (y<=cliprect.max_y) |
| 2164 | *fbaddr = b | (g<<8) | (r<<16); |
| 2165 | addrp+=2; |
| 2166 | } |
| 2167 | } |
| 2168 | else |
| 2169 | { |
| 2170 | for (x=0;x < xi;x++) |
| 2171 | { |
| 2172 | fbaddr=&bitmap.pix32(y, x); |
| 2173 | c=*((reinterpret_cast<UINT16 *>(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2174 | |
| 2175 | b = (c & 0x001f) << 3; |
| 2176 | g = (c & 0x03e0) >> 2; |
| 2177 | r = (c & 0x7c00) >> 7; |
| 2178 | |
| 2179 | if (y<=cliprect.max_y) |
| 2180 | *fbaddr = b | (g<<8) | (r<<16); |
| 2181 | addrp+=2; |
| 2182 | } |
| 2183 | } |
| 2184 | } |
| 2185 | |
| 2186 | break; |
| 2187 | case 0x01: // 0565 RGB 16-bit |
| 2188 | // should upsample back to 8-bit output using fb_concat |
| 2189 | for (y=0;y <= dy;y++) |
| 2190 | { |
| 2191 | addrp=pvrta_regs[FB_R_SOF1]+y*xi*2; |
| 2192 | if(spg_pixel_double) |
| 2193 | { |
| 2194 | for (x=0;x < xi;x++) |
| 2195 | { |
| 2196 | fbaddr=&bitmap.pix32(y, x*2+0); |
| 2197 | c=*((reinterpret_cast<UINT16 *>(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2198 | |
| 2199 | b = (c & 0x001f) << 3; |
| 2200 | g = (c & 0x07e0) >> 3; |
| 2201 | r = (c & 0xf800) >> 8; |
| 2202 | |
| 2203 | if (y<=cliprect.max_y) |
| 2204 | *fbaddr = b | (g<<8) | (r<<16); |
| 2205 | |
| 2206 | fbaddr=&bitmap.pix32(y, x*2+1); |
| 2207 | |
| 2208 | if (y<=cliprect.max_y) |
| 2209 | *fbaddr = b | (g<<8) | (r<<16); |
| 2210 | |
| 2211 | addrp+=2; |
| 2212 | } |
| 2213 | } |
| 2214 | else |
| 2215 | { |
| 2216 | for (x=0;x < xi;x++) |
| 2217 | { |
| 2218 | fbaddr=&bitmap.pix32(y, x); |
| 2219 | c=*((reinterpret_cast<UINT16 *>(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2220 | |
| 2221 | b = (c & 0x001f) << 3; |
| 2222 | g = (c & 0x07e0) >> 3; |
| 2223 | r = (c & 0xf800) >> 8; |
| 2224 | |
| 2225 | if (y<=cliprect.max_y) |
| 2226 | *fbaddr = b | (g<<8) | (r<<16); |
| 2227 | addrp+=2; |
| 2228 | } |
| 2229 | } |
| 2230 | } |
| 2231 | break; |
| 2232 | |
| 2233 | case 0x02: ; // 888 RGB 24-bit - suchie3 - HACKED, see pvr_accumulationbuffer_to_framebuffer! |
| 2234 | for (y=0;y <= dy;y++) |
| 2235 | { |
| 2236 | addrp=pvrta_regs[FB_R_SOF1]+y*xi*2; |
| 2237 | if(spg_pixel_double) |
| 2238 | { |
| 2239 | for (x=0;x < xi;x++) |
| 2240 | { |
| 2241 | fbaddr=&bitmap.pix32(y, x*2+0); |
| 2242 | c=*((reinterpret_cast<UINT16 *>(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2243 | |
| 2244 | b = (c & 0x001f) << 3; |
| 2245 | g = (c & 0x07e0) >> 3; |
| 2246 | r = (c & 0xf800) >> 8; |
| 2247 | |
| 2248 | if (y<=cliprect.max_y) |
| 2249 | *fbaddr = b | (g<<8) | (r<<16); |
| 2250 | |
| 2251 | fbaddr=&bitmap.pix32(y, x*2+1); |
| 2252 | |
| 2253 | if (y<=cliprect.max_y) |
| 2254 | *fbaddr = b | (g<<8) | (r<<16); |
| 2255 | addrp+=2; |
| 2256 | } |
| 2257 | } |
| 2258 | else |
| 2259 | { |
| 2260 | for (x=0;x < xi;x++) |
| 2261 | { |
| 2262 | fbaddr=&bitmap.pix32(y, x); |
| 2263 | c=*((reinterpret_cast<UINT16 *>(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2264 | |
| 2265 | b = (c & 0x001f) << 3; |
| 2266 | g = (c & 0x07e0) >> 3; |
| 2267 | r = (c & 0xf800) >> 8; |
| 2268 | |
| 2269 | if (y<=cliprect.max_y) |
| 2270 | *fbaddr = b | (g<<8) | (r<<16); |
| 2271 | addrp+=2; |
| 2272 | } |
| 2273 | } |
| 2274 | } |
| 2275 | break; |
| 2276 | |
| 2277 | case 0x03: // 0888 ARGB 32-bit - HACKED, see pvr_accumulationbuffer_to_framebuffer! |
| 2278 | for (y=0;y <= dy;y++) |
| 2279 | { |
| 2280 | addrp=pvrta_regs[FB_R_SOF1]+y*xi*2; |
| 2281 | if(spg_pixel_double) |
| 2282 | { |
| 2283 | for (x=0;x < xi;x++) |
| 2284 | { |
| 2285 | fbaddr=&bitmap.pix32(y, x*2+0); |
| 2286 | c=*((reinterpret_cast<UINT16 *>(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2287 | |
| 2288 | b = (c & 0x001f) << 3; |
| 2289 | g = (c & 0x07e0) >> 3; |
| 2290 | r = (c & 0xf800) >> 8; |
| 2291 | |
| 2292 | if (y<=cliprect.max_y) |
| 2293 | *fbaddr = b | (g<<8) | (r<<16); |
| 2294 | |
| 2295 | fbaddr=&bitmap.pix32(y, x*2+1); |
| 2296 | if (y<=cliprect.max_y) |
| 2297 | *fbaddr = b | (g<<8) | (r<<16); |
| 2298 | |
| 2299 | addrp+=2; |
| 2300 | } |
| 2301 | } |
| 2302 | else |
| 2303 | { |
| 2304 | for (x=0;x < xi;x++) |
| 2305 | { |
| 2306 | fbaddr=&bitmap.pix32(y, x); |
| 2307 | c=*((reinterpret_cast<UINT16 *>(dc_framebuffer_ram)) + (WORD2_XOR_LE(addrp) >> 1)); |
| 2308 | |
| 2309 | b = (c & 0x001f) << 3; |
| 2310 | g = (c & 0x07e0) >> 3; |
| 2311 | r = (c & 0xf800) >> 8; |
| 2312 | |
| 2313 | if (y<=cliprect.max_y) |
| 2314 | *fbaddr = b | (g<<8) | (r<<16); |
| 2315 | addrp+=2; |
| 2316 | } |
| 2317 | } |
| 2318 | } |
| 2319 | break; |
| 2320 | } |
| 2321 | } |
| 2322 | |
| 2323 | |
| 2324 | #if DEBUG_PALRAM |
| 2325 | void powervr2_device::debug_paletteram() |
| 2326 | { |
| 2327 | UINT64 pal; |
| 2328 | UINT32 r,g,b; |
| 2329 | int i; |
| 2330 | |
| 2331 | //popmessage("%02x",pvrta_regs[PAL_RAM_CTRL]); |
| 2332 | |
| 2333 | for(i=0;i<0x400;i++) |
| 2334 | { |
| 2335 | pal = pvrta_regs[((0x005F9000-0x005F8000)/4)+i]; |
| 2336 | switch(pvrta_regs[PAL_RAM_CTRL]) |
| 2337 | { |
| 2338 | case 0: //argb1555 <- guilty gear uses this mode |
| 2339 | { |
| 2340 | //a = (pal & 0x8000)>>15; |
| 2341 | r = (pal & 0x7c00)>>10; |
| 2342 | g = (pal & 0x03e0)>>5; |
| 2343 | b = (pal & 0x001f)>>0; |
| 2344 | //a = a ? 0xff : 0x00; |
| 2345 | palette_set_color_rgb(machine(), i, pal5bit(r), pal5bit(g), pal5bit(b)); |
| 2346 | } |
| 2347 | break; |
| 2348 | case 1: //rgb565 |
| 2349 | { |
| 2350 | //a = 0xff; |
| 2351 | r = (pal & 0xf800)>>11; |
| 2352 | g = (pal & 0x07e0)>>5; |
| 2353 | b = (pal & 0x001f)>>0; |
| 2354 | palette_set_color_rgb(machine(), i, pal5bit(r), pal6bit(g), pal5bit(b)); |
| 2355 | } |
| 2356 | break; |
| 2357 | case 2: //argb4444 |
| 2358 | { |
| 2359 | //a = (pal & 0xf000)>>12; |
| 2360 | r = (pal & 0x0f00)>>8; |
| 2361 | g = (pal & 0x00f0)>>4; |
| 2362 | b = (pal & 0x000f)>>0; |
| 2363 | palette_set_color_rgb(machine(), i, pal4bit(r), pal4bit(g), pal4bit(b)); |
| 2364 | } |
| 2365 | break; |
| 2366 | case 3: //argb8888 |
| 2367 | { |
| 2368 | //a = (pal & 0xff000000)>>20; |
| 2369 | r = (pal & 0x00ff0000)>>16; |
| 2370 | g = (pal & 0x0000ff00)>>8; |
| 2371 | b = (pal & 0x000000ff)>>0; |
| 2372 | palette_set_color_rgb(machine(), i, r, g, b); |
| 2373 | } |
| 2374 | break; |
| 2375 | } |
| 2376 | } |
| 2377 | } |
| 2378 | #endif |
| 2379 | |
| 2380 | /* test video end */ |
| 2381 | |
| 2382 | void powervr2_device::pvr_build_parameterconfig() |
| 2383 | { |
| 2384 | int a,b,c,d,e,p; |
| 2385 | |
| 2386 | for (a = 0;a <= 63;a++) |
| 2387 | pvr_parameterconfig[a] = -1; |
| 2388 | p=0; |
| 2389 | // volume,col_type,texture,offset,16bit_uv |
| 2390 | for (a = 0;a <= 1;a++) |
| 2391 | for (b = 0;b <= 3;b++) |
| 2392 | for (c = 0;c <= 1;c++) |
| 2393 | if (c == 0) |
| 2394 | { |
| 2395 | for (d = 0;d <= 1;d++) |
| 2396 | for (e = 0;e <= 1;e++) |
| 2397 | pvr_parameterconfig[(a << 6) | (b << 4) | (c << 3) | (d << 2) | (e << 0)] = pvr_parconfseq[p]; |
| 2398 | p++; |
| 2399 | } |
| 2400 | else |
| 2401 | for (d = 0;d <= 1;d++) |
| 2402 | for (e = 0;e <= 1;e++) |
| 2403 | { |
| 2404 | pvr_parameterconfig[(a << 6) | (b << 4) | (c << 3) | (d << 2) | (e << 0)] = pvr_parconfseq[p]; |
| 2405 | p++; |
| 2406 | } |
| 2407 | for (a = 1;a <= 63;a++) |
| 2408 | if (pvr_parameterconfig[a] < 0) |
| 2409 | pvr_parameterconfig[a] = pvr_parameterconfig[a-1]; |
| 2410 | } |
| 2411 | |
| 2412 | TIMER_CALLBACK_MEMBER(powervr2_device::vbin) |
| 2413 | { |
| 2414 | dc_state *state = machine().driver_data<dc_state>(); |
| 2415 | state->dc_sysctrl_regs[SB_ISTNRM] |= IST_VBL_IN; // V Blank-in interrupt |
| 2416 | state->dc_update_interrupt_status(); |
| 2417 | |
| 2418 | vbin_timer->adjust(machine().primary_screen->time_until_pos(spg_vblank_in_irq_line_num)); |
| 2419 | } |
| 2420 | |
| 2421 | TIMER_CALLBACK_MEMBER(powervr2_device::vbout) |
| 2422 | { |
| 2423 | dc_state *state = machine().driver_data<dc_state>(); |
| 2424 | state->dc_sysctrl_regs[SB_ISTNRM] |= IST_VBL_OUT; // V Blank-out interrupt |
| 2425 | state->dc_update_interrupt_status(); |
| 2426 | |
| 2427 | vbout_timer->adjust(machine().primary_screen->time_until_pos(spg_vblank_out_irq_line_num)); |
| 2428 | } |
| 2429 | |
| 2430 | TIMER_CALLBACK_MEMBER(powervr2_device::hbin) |
| 2431 | { |
| 2432 | if(spg_hblank_int_mode & 1) |
| 2433 | { |
| 2434 | if(scanline == next_y) |
| 2435 | { |
| 2436 | dc_state *state = machine().driver_data<dc_state>(); |
| 2437 | state->dc_sysctrl_regs[SB_ISTNRM] |= IST_HBL_IN; // H Blank-in interrupt |
| 2438 | state->dc_update_interrupt_status(); |
| 2439 | next_y+=spg_line_comp_val; |
| 2440 | } |
| 2441 | } |
| 2442 | else if((scanline == spg_line_comp_val) || (spg_hblank_int_mode & 2)) |
| 2443 | { |
| 2444 | dc_state *state = machine().driver_data<dc_state>(); |
| 2445 | state->dc_sysctrl_regs[SB_ISTNRM] |= IST_HBL_IN; // H Blank-in interrupt |
| 2446 | state->dc_update_interrupt_status(); |
| 2447 | } |
| 2448 | |
| 2449 | // printf("hbin on scanline %d\n",scanline); |
| 2450 | |
| 2451 | scanline++; |
| 2452 | |
| 2453 | if(scanline >= spg_vblank_in_irq_line_num) |
| 2454 | { |
| 2455 | scanline = 0; |
| 2456 | next_y = spg_line_comp_val; |
| 2457 | } |
| 2458 | |
| 2459 | hbin_timer->adjust(machine().primary_screen->time_until_pos(scanline, spg_hblank_in_irq-1)); |
| 2460 | } |
| 2461 | |
| 2462 | |
| 2463 | |
| 2464 | TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_video) |
| 2465 | { |
| 2466 | dc_state *state = machine().driver_data<dc_state>(); |
| 2467 | state->dc_sysctrl_regs[SB_ISTNRM] |= IST_EOR_VIDEO;// VIDEO end of render |
| 2468 | state->dc_update_interrupt_status(); |
| 2469 | endofrender_timer_video->adjust(attotime::never); |
| 2470 | } |
| 2471 | |
| 2472 | TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_tsp) |
| 2473 | { |
| 2474 | dc_state *state = machine().driver_data<dc_state>(); |
| 2475 | state->dc_sysctrl_regs[SB_ISTNRM] |= IST_EOR_TSP; // TSP end of render |
| 2476 | state->dc_update_interrupt_status(); |
| 2477 | |
| 2478 | endofrender_timer_tsp->adjust(attotime::never); |
| 2479 | endofrender_timer_video->adjust(attotime::from_usec(500) ); |
| 2480 | } |
| 2481 | |
| 2482 | TIMER_CALLBACK_MEMBER(powervr2_device::endofrender_isp) |
| 2483 | { |
| 2484 | dc_state *state = machine().driver_data<dc_state>(); |
| 2485 | state->dc_sysctrl_regs[SB_ISTNRM] |= IST_EOR_ISP; // ISP end of render |
| 2486 | state->dc_update_interrupt_status(); |
| 2487 | |
| 2488 | endofrender_timer_isp->adjust(attotime::never); |
| 2489 | endofrender_timer_tsp->adjust(attotime::from_usec(500) ); |
| 2490 | } |
| 2491 | |
| 2492 | UINT32 powervr2_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| 2493 | { |
| 2494 | /****************** |
| 2495 | MAME note |
| 2496 | ******************* |
| 2497 | |
| 2498 | The video update function should NOT be generating interrupts, setting timers or doing _anything_ the game might be able to detect |
| 2499 | as it will be called at different times depending on frameskip etc. |
| 2500 | |
| 2501 | Rendering should happen when the hardware requests it, to the framebuffer(s) |
| 2502 | |
| 2503 | Everything else should depend on timers. |
| 2504 | |
| 2505 | ******************/ |
| 2506 | |
| 2507 | // static int useframebuffer=1; |
| 2508 | // const rectangle &visarea = screen.visible_area(); |
| 2509 | // int y,x; |
| 2510 | |
| 2511 | #if DEBUG_PALRAM |
| 2512 | debug_paletteram(); |
| 2513 | #endif |
| 2514 | |
| 2515 | // copy our fake framebuffer bitmap (where things have been rendered) to the screen |
| 2516 | #if 0 |
| 2517 | for (y = visarea->min_y ; y <= visarea->max_y ; y++) |
| 2518 | { |
| 2519 | for (x = visarea->min_x ; x <= visarea->max_x ; x++) |
| 2520 | { |
| 2521 | UINT32* src = &fake_accumulationbuffer_bitmap->pix32(y, x); |
| 2522 | UINT32* dst = &bitmap.pix32(y, x); |
| 2523 | dst[0] = src[0]; |
| 2524 | } |
| 2525 | } |
| 2526 | #endif |
| 2527 | |
| 2528 | bitmap.fill(MAKE_ARGB(0xff,vo_border_R,vo_border_G,vo_border_B), cliprect); //FIXME: Chroma bit? |
| 2529 | |
| 2530 | if(!spg_blank_video) |
| 2531 | pvr_drawframebuffer(bitmap, cliprect); |
| 2532 | |
| 2533 | // update this here so we only do string lookup once per frame |
| 2534 | debug_dip_status = ioport(":MAMEDEBUG")->read(); |
| 2535 | |
| 2536 | return 0; |
| 2537 | } |
| 2538 | |
| 2539 | |
| 2540 | /* Naomi 2 attempts (TBD) */ |
| 2541 | |
| 2542 | READ64_MEMBER( powervr2_device::pvr2_ta_r ) |
| 2543 | { |
| 2544 | int reg; |
| 2545 | UINT64 shift; |
| 2546 | |
| 2547 | reg = decode_reg_64(offset, mem_mask, &shift); |
| 2548 | |
| 2549 | switch (reg) |
| 2550 | { |
| 2551 | } |
| 2552 | |
| 2553 | printf("PVR2 %08x R\n",reg); |
| 2554 | |
| 2555 | return 0; |
| 2556 | } |
| 2557 | |
| 2558 | WRITE64_MEMBER( powervr2_device::pvr2_ta_w ) |
| 2559 | { |
| 2560 | // int reg; |
| 2561 | // UINT64 shift; |
| 2562 | // UINT32 dat; |
| 2563 | |
| 2564 | // reg = decode_reg_64(offset, mem_mask, &shift); |
| 2565 | // dat = (UINT32)(data >> shift); |
| 2566 | |
| 2567 | //printf("PVR2 %08x %08x\n",reg,dat); |
| 2568 | } |
| 2569 | |
| 2570 | READ32_MEMBER( powervr2_device::elan_regs_r ) |
| 2571 | { |
| 2572 | switch(offset) |
| 2573 | { |
| 2574 | case 0x00/4: // ID chip (TODO: BIOS crashes / gives a black screen with this as per now!) |
| 2575 | return 0xe1ad0000; |
| 2576 | case 0x04/4: // REVISION |
| 2577 | return 0x12; //or 0x01? |
| 2578 | case 0x10/4: // SH4 interface control (???) |
| 2579 | /* ---- -x-- enable second PVR */ |
| 2580 | /* ---- --x- elan has channel 2 */ |
| 2581 | /* ---- ---x broadcast on cs1 (?) */ |
| 2582 | return 6; |
| 2583 | case 0x14/4: // SDRAM refresh register |
| 2584 | return 0x2029; //default 0x1429 |
| 2585 | case 0x1c/4: // SDRAM CFG |
| 2586 | return 0xa7320961; //default 0xa7320961 |
| 2587 | case 0x30/4: // Macro tiler configuration, bit 0 is enable |
| 2588 | return 0; |
| 2589 | case 0x74/4: // IRQ STAT |
| 2590 | return 0; |
| 2591 | case 0x78/4: // IRQ MASK |
| 2592 | return 0; |
| 2593 | default: |
| 2594 | printf("%08x %08x\n",space.device().safe_pc(),offset*4); |
| 2595 | break; |
| 2596 | } |
| 2597 | |
| 2598 | return 0; |
| 2599 | } |
| 2600 | |
| 2601 | WRITE32_MEMBER( powervr2_device::elan_regs_w ) |
| 2602 | { |
| 2603 | switch(offset) |
| 2604 | { |
| 2605 | default: |
| 2606 | printf("%08x %08x %08x W\n",space.device().safe_pc(),offset*4,data); |
| 2607 | break; |
| 2608 | } |
| 2609 | } |
| 2610 | |
| 2611 | |
| 2612 | WRITE64_MEMBER( powervr2_device::pvrs_ta_w ) |
| 2613 | { |
| 2614 | pvr_ta_w(space,offset,data,mem_mask); |
| 2615 | pvr2_ta_w(space,offset,data,mem_mask); |
| 2616 | //printf("PVR2 %08x %08x\n",reg,dat); |
| 2617 | } |
| 2618 | |
| 2619 | TIMER_CALLBACK_MEMBER(powervr2_device::pvr_dma_irq) |
| 2620 | { |
| 2621 | dc_state *state = machine().driver_data<dc_state>(); |
| 2622 | m_pvr_dma.start = pvrctrl_regs[SB_PDST] = 0; |
| 2623 | state->dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_PVR; |
| 2624 | state->dc_update_interrupt_status(); |
| 2625 | } |
| 2626 | |
| 2627 | READ64_MEMBER(powervr2_device::pvr_ctrl_r ) |
| 2628 | { |
| 2629 | int reg; |
| 2630 | UINT64 shift; |
| 2631 | |
| 2632 | reg = decode_reg_64(offset, mem_mask, &shift); |
| 2633 | |
| 2634 | #if DEBUG_PVRCTRL |
| 2635 | mame_printf_verbose("PVRCTRL: [%08x] read %x @ %x (reg %x), mask %" I64FMT "x (PC=%x)\n", 0x5f7c00+reg*4, pvrctrl_regs[reg], offset, reg, mem_mask, space.device().safe_pc()); |
| 2636 | #endif |
| 2637 | |
| 2638 | return (UINT64)pvrctrl_regs[reg] << shift; |
| 2639 | } |
| 2640 | |
| 2641 | WRITE64_MEMBER(powervr2_device::pvr_ctrl_w ) |
| 2642 | { |
| 2643 | int reg; |
| 2644 | UINT64 shift; |
| 2645 | UINT32 dat; |
| 2646 | UINT8 old; |
| 2647 | |
| 2648 | reg = decode_reg_64(offset, mem_mask, &shift); |
| 2649 | dat = (UINT32)(data >> shift); |
| 2650 | |
| 2651 | switch (reg) |
| 2652 | { |
| 2653 | case SB_PDSTAP: m_pvr_dma.pvr_addr = dat; break; |
| 2654 | case SB_PDSTAR: m_pvr_dma.sys_addr = dat; break; |
| 2655 | case SB_PDLEN: m_pvr_dma.size = dat; break; |
| 2656 | case SB_PDDIR: m_pvr_dma.dir = dat & 1; break; |
| 2657 | case SB_PDTSEL: |
| 2658 | m_pvr_dma.sel = dat & 1; |
| 2659 | //if(m_pvr_dma.sel & 1) |
| 2660 | // printf("Warning: Unsupported irq mode trigger PVR-DMA\n"); |
| 2661 | break; |
| 2662 | case SB_PDEN: m_pvr_dma.flag = dat & 1; break; |
| 2663 | case SB_PDST: |
| 2664 | old = m_pvr_dma.start & 1; |
| 2665 | m_pvr_dma.start = dat & 1; |
| 2666 | |
| 2667 | if(((old & 1) == 0) && m_pvr_dma.flag && m_pvr_dma.start && ((m_pvr_dma.sel & 1) == 0)) // 0 -> 1 |
| 2668 | pvr_dma_execute(space); |
| 2669 | break; |
| 2670 | } |
| 2671 | |
| 2672 | #if DEBUG_PVRCTRL |
| 2673 | mame_printf_verbose("PVRCTRL: [%08x=%x] write %" I64FMT "x to %x (reg %x), mask %" I64FMT "x\n", 0x5f7c00+reg*4, dat, data>>shift, offset, reg, mem_mask); |
| 2674 | #endif |
| 2675 | |
| 2676 | // pvrctrl_regs[reg] |= dat; |
| 2677 | pvrctrl_regs[reg] = dat; |
| 2678 | } |
| 2679 | |
| 2680 | void powervr2_device::pvr_dma_execute(address_space &space) |
| 2681 | { |
| 2682 | UINT32 src,dst,size; |
| 2683 | dst = m_pvr_dma.pvr_addr; |
| 2684 | src = m_pvr_dma.sys_addr; |
| 2685 | size = 0; |
| 2686 | |
| 2687 | /* used so far by usagui and sprtjam*/ |
| 2688 | //printf("PVR-DMA start\n"); |
| 2689 | //printf("%08x %08x %08x\n",m_pvr_dma.pvr_addr,m_pvr_dma.sys_addr,m_pvr_dma.size); |
| 2690 | //printf("src %s dst %08x\n",m_pvr_dma.dir ? "->" : "<-",m_pvr_dma.sel); |
| 2691 | |
| 2692 | /* 0 rounding size = 16 Mbytes */ |
| 2693 | if(m_pvr_dma.size == 0) { m_pvr_dma.size = 0x100000; } |
| 2694 | |
| 2695 | if(m_pvr_dma.dir == 0) |
| 2696 | { |
| 2697 | for(;size<m_pvr_dma.size;size+=4) |
| 2698 | { |
| 2699 | space.write_dword(dst,space.read_dword(src)); |
| 2700 | src+=4; |
| 2701 | dst+=4; |
| 2702 | } |
| 2703 | } |
| 2704 | else |
| 2705 | { |
| 2706 | for(;size<m_pvr_dma.size;size+=4) |
| 2707 | { |
| 2708 | space.write_dword(src,space.read_dword(dst)); |
| 2709 | src+=4; |
| 2710 | dst+=4; |
| 2711 | } |
| 2712 | } |
| 2713 | /* Note: do not update the params, since this DMA type doesn't support it. */ |
| 2714 | /* TODO: timing of this */ |
| 2715 | machine().scheduler().timer_set(attotime::from_usec(250), timer_expired_delegate(FUNC(powervr2_device::pvr_dma_irq), this)); |
| 2716 | } |
| 2717 | |
| 2718 | powervr2_device::powervr2_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 2719 | : device_t(mconfig, POWERVR2, "PowerVR 2", tag, owner, clock) |
| 2720 | { |
| 2721 | } |
| 2722 | |
| 2723 | void powervr2_device::device_start() |
| 2724 | { |
| 2725 | memset(pvrctrl_regs, 0, sizeof(pvrctrl_regs)); |
| 2726 | memset(pvrta_regs, 0, sizeof(pvrta_regs)); |
| 2727 | memset(grab, 0, sizeof(grab)); |
| 2728 | pvr_build_parameterconfig(); |
| 2729 | |
| 2730 | computedilated(); |
| 2731 | |
| 2732 | vbout_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::vbout),this)); |
| 2733 | vbin_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::vbin),this)); |
| 2734 | hbin_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::hbin),this)); |
| 2735 | |
| 2736 | endofrender_timer_isp = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::endofrender_isp),this)); |
| 2737 | endofrender_timer_tsp = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::endofrender_tsp),this)); |
| 2738 | endofrender_timer_video = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(powervr2_device::endofrender_video),this)); |
| 2739 | |
| 2740 | fake_accumulationbuffer_bitmap = auto_bitmap_rgb32_alloc(machine(),1024,1024); |
| 2741 | |
| 2742 | save_item(NAME(m_pvr_dma.pvr_addr)); |
| 2743 | save_item(NAME(m_pvr_dma.sys_addr)); |
| 2744 | save_item(NAME(m_pvr_dma.size)); |
| 2745 | save_item(NAME(m_pvr_dma.sel)); |
| 2746 | save_item(NAME(m_pvr_dma.dir)); |
| 2747 | save_item(NAME(m_pvr_dma.flag)); |
| 2748 | save_item(NAME(m_pvr_dma.start)); |
| 2749 | save_pointer(NAME(pvrta_regs),0x2000/4); |
| 2750 | save_pointer(NAME(pvrctrl_regs),0x100/4); |
| 2751 | save_item(NAME(debug_dip_status)); |
| 2752 | save_pointer(NAME(tafifo_buff),32); |
| 2753 | save_item(NAME(scanline)); |
| 2754 | save_item(NAME(next_y)); |
| 2755 | } |
| 2756 | |
| 2757 | void powervr2_device::device_reset() |
| 2758 | { |
| 2759 | pvrta_regs[VO_CONTROL]= 0x00000108; |
| 2760 | pvrta_regs[SOFTRESET]= 0x00000007; |
| 2761 | pvrta_regs[VO_STARTX]= 0x0000009d; |
| 2762 | pvrta_regs[VO_STARTY]= 0x00150015; |
| 2763 | pvrta_regs[SPG_HBLANK]= 0x007e0345; |
| 2764 | pvrta_regs[SPG_LOAD]= 0x01060359; |
| 2765 | pvrta_regs[SPG_VBLANK]= 0x01500104; |
| 2766 | pvrta_regs[SPG_HBLANK_INT]= 0x031d0000; |
| 2767 | pvrta_regs[SPG_VBLANK_INT]= 0x01500104; |
| 2768 | |
| 2769 | // if the next 2 registers do not have the correct values, the naomi bios will hang |
| 2770 | pvrta_regs[PVRID]=0x17fd11db; |
| 2771 | pvrta_regs[REVISION]=0x11; |
| 2772 | |
| 2773 | tafifo_pos=0; |
| 2774 | tafifo_mask=7; |
| 2775 | tafifo_vertexwords=8; |
| 2776 | tafifo_listtype= -1; |
| 2777 | start_render_received=0; |
| 2778 | renderselect= -1; |
| 2779 | grabsel=0; |
| 2780 | |
| 2781 | vbout_timer->adjust(machine().primary_screen->time_until_pos(spg_vblank_out_irq_line_num_new)); |
| 2782 | vbin_timer->adjust(machine().primary_screen->time_until_pos(spg_vblank_in_irq_line_num_new)); |
| 2783 | hbin_timer->adjust(machine().primary_screen->time_until_pos(0, spg_hblank_in_irq_new-1)); |
| 2784 | |
| 2785 | scanline = 0; |
| 2786 | next_y = 0; |
| 2787 | |
| 2788 | endofrender_timer_isp->adjust(attotime::never); |
| 2789 | endofrender_timer_tsp->adjust(attotime::never); |
| 2790 | endofrender_timer_video->adjust(attotime::never); |
| 2791 | |
| 2792 | dc_state *state = machine().driver_data<dc_state>(); |
| 2793 | dc_texture_ram = state->dc_texture_ram.target(); |
| 2794 | dc_framebuffer_ram = state->dc_framebuffer_ram.target(); |
| 2795 | } |