trunk/src/mame/video/snes.c
| r21558 | r21559 | |
| 95 | 95 | static struct DEBUGOPTS debug_options; |
| 96 | 96 | /* red green blue purple yellow cyan grey white */ |
| 97 | 97 | static const UINT16 dbg_mode_colours[8] = { 0x1f, 0x3e0, 0x7c00, 0x7c1f, 0x3ff, 0x7fe0, 0x4210, 0x7fff }; |
| 98 | | static UINT8 snes_dbg_video(running_machine &machine, UINT16 curline); |
| 99 | 98 | #endif /* SNES_LAYER_DEBUG */ |
| 100 | 99 | |
| 101 | 100 | static const UINT16 table_obj_offset[8][8] = |
| r21558 | r21559 | |
| 121 | 120 | }; |
| 122 | 121 | |
| 123 | 122 | static struct SCANLINE scanlines[2]; |
| 124 | | struct SNES_PPU_STRUCT snes_ppu; |
| 123 | //struct SNES_PPU_STRUCT snes_ppu; |
| 125 | 124 | |
| 126 | 125 | enum |
| 127 | 126 | { |
| r21558 | r21559 | |
| 136 | 135 | * Get the proper color (direct or from cgram) |
| 137 | 136 | *****************************************/ |
| 138 | 137 | |
| 139 | | inline UINT16 snes_state::snes_get_bgcolor( UINT8 direct_colors, UINT16 palette, UINT8 color ) |
| 138 | inline UINT16 snes_ppu_class::snes_get_bgcolor( UINT8 direct_colors, UINT16 palette, UINT8 color ) |
| 140 | 139 | { |
| 141 | 140 | UINT16 c = 0; |
| 142 | 141 | |
| r21558 | r21559 | |
| 147 | 146 | c |= ((palette & 0x04) >> 1) | ((palette & 0x08) << 3) | ((palette & 0x10) << 8); |
| 148 | 147 | } |
| 149 | 148 | else |
| 150 | | c = m_snes_cgram[(palette + color) % FIXED_COLOUR]; |
| 149 | c = m_cgram[(palette + color) % FIXED_COLOUR]; |
| 151 | 150 | |
| 152 | 151 | return c; |
| 153 | 152 | } |
| r21558 | r21559 | |
| 160 | 159 | * proper scanline |
| 161 | 160 | *****************************************/ |
| 162 | 161 | |
| 163 | | inline void snes_state::snes_set_scanline_pixel( int screen, INT16 x, UINT16 color, UINT8 priority, UINT8 layer, int blend ) |
| 162 | inline void snes_ppu_class::snes_set_scanline_pixel( int screen, INT16 x, UINT16 color, UINT8 priority, UINT8 layer, int blend ) |
| 164 | 163 | { |
| 165 | 164 | scanlines[screen].buffer[x] = color; |
| 166 | 165 | scanlines[screen].priority[x] = priority; |
| r21558 | r21559 | |
| 191 | 190 | * or lores) |
| 192 | 191 | *****************************************/ |
| 193 | 192 | |
| 194 | | inline void snes_state::snes_draw_bgtile_lores( UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority ) |
| 193 | inline void snes_ppu_class::snes_draw_bgtile_lores( UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority ) |
| 195 | 194 | { |
| 196 | 195 | int screen; |
| 197 | 196 | UINT16 c; |
| r21558 | r21559 | |
| 203 | 202 | if (scanlines[screen].priority[ii] <= priority) |
| 204 | 203 | { |
| 205 | 204 | UINT8 clr = colour; |
| 206 | | UINT8 clipmask = snes_ppu.clipmasks[layer][ii]; |
| 205 | UINT8 clipmask = m_clipmasks[layer][ii]; |
| 207 | 206 | |
| 208 | 207 | #if SNES_LAYER_DEBUG |
| 209 | 208 | if (debug_options.windows_disabled) |
| r21558 | r21559 | |
| 225 | 224 | } |
| 226 | 225 | } |
| 227 | 226 | |
| 228 | | inline void snes_state::snes_draw_bgtile_hires( UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority ) |
| 227 | inline void snes_ppu_class::snes_draw_bgtile_hires( UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority ) |
| 229 | 228 | { |
| 230 | 229 | int screen; |
| 231 | 230 | UINT16 c; |
| r21558 | r21559 | |
| 238 | 237 | if (scanlines[screen].priority[ii >> 1] <= priority) |
| 239 | 238 | { |
| 240 | 239 | UINT8 clr = colour; |
| 241 | | UINT8 clipmask = snes_ppu.clipmasks[layer][ii >> 1]; |
| 240 | UINT8 clipmask = m_clipmasks[layer][ii >> 1]; |
| 242 | 241 | |
| 243 | 242 | #if SNES_LAYER_DEBUG |
| 244 | 243 | if (debug_options.windows_disabled) |
| r21558 | r21559 | |
| 260 | 259 | } |
| 261 | 260 | } |
| 262 | 261 | |
| 263 | | inline void snes_state::snes_draw_oamtile( INT16 ii, UINT8 colour, UINT16 pal, UINT8 priority ) |
| 262 | inline void snes_ppu_class::snes_draw_oamtile( INT16 ii, UINT8 colour, UINT16 pal, UINT8 priority ) |
| 264 | 263 | { |
| 265 | 264 | int screen; |
| 266 | 265 | int blend; |
| r21558 | r21559 | |
| 272 | 271 | if (pos >= 0 && pos < SNES_SCR_WIDTH && scanlines[screen].enable) |
| 273 | 272 | { |
| 274 | 273 | UINT8 clr = colour; |
| 275 | | UINT8 clipmask = snes_ppu.clipmasks[SNES_OAM][pos]; |
| 274 | UINT8 clipmask = m_clipmasks[SNES_OAM][pos]; |
| 276 | 275 | |
| 277 | 276 | #if SNES_LAYER_DEBUG |
| 278 | 277 | if (debug_options.windows_disabled) |
| r21558 | r21559 | |
| 286 | 285 | /* Only draw if we have a colour (0 == transparent) */ |
| 287 | 286 | if (clr) |
| 288 | 287 | { |
| 289 | | c = m_snes_cgram[(pal + clr) % FIXED_COLOUR]; |
| 288 | c = m_cgram[(pal + clr) % FIXED_COLOUR]; |
| 290 | 289 | blend = (pal + clr < 192) ? 1 : 0; |
| 291 | 290 | snes_set_scanline_pixel(screen, pos, c, priority, SNES_OAM, blend); |
| 292 | 291 | } |
| r21558 | r21559 | |
| 303 | 302 | * (depending on layer and resolution) |
| 304 | 303 | *****************************************/ |
| 305 | 304 | |
| 306 | | inline void snes_state::snes_draw_tile( UINT8 planes, UINT8 layer, UINT32 tileaddr, INT16 x, UINT8 priority, UINT8 flip, UINT8 direct_colors, UINT16 pal, UINT8 hires ) |
| 305 | inline void snes_ppu_class::snes_draw_tile( UINT8 planes, UINT8 layer, UINT32 tileaddr, INT16 x, UINT8 priority, UINT8 flip, UINT8 direct_colors, UINT16 pal, UINT8 hires ) |
| 307 | 306 | { |
| 308 | 307 | UINT8 plane[8]; |
| 309 | 308 | INT16 ii, jj; |
| r21558 | r21559 | |
| 311 | 310 | |
| 312 | 311 | for (ii = 0; ii < planes / 2; ii++) |
| 313 | 312 | { |
| 314 | | plane[2 * ii + 0] = m_snes_vram[(tileaddr + 16 * ii + 0) % SNES_VRAM_SIZE]; |
| 315 | | plane[2 * ii + 1] = m_snes_vram[(tileaddr + 16 * ii + 1) % SNES_VRAM_SIZE]; |
| 313 | plane[2 * ii + 0] = m_vram[(tileaddr + 16 * ii + 0) % SNES_VRAM_SIZE]; |
| 314 | plane[2 * ii + 1] = m_vram[(tileaddr + 16 * ii + 1) % SNES_VRAM_SIZE]; |
| 316 | 315 | } |
| 317 | 316 | |
| 318 | 317 | for (ii = x; ii < (x + 8); ii++) |
| 319 | 318 | { |
| 320 | 319 | UINT8 colour = 0; |
| 321 | | UINT8 mosaic = snes_ppu.layer[layer].mosaic_enabled; |
| 320 | UINT8 mosaic = m_layer[layer].mosaic_enabled; |
| 322 | 321 | |
| 323 | 322 | #if SNES_LAYER_DEBUG |
| 324 | 323 | if (debug_options.mosaic_disabled) |
| r21558 | r21559 | |
| 342 | 341 | { |
| 343 | 342 | if (mosaic) |
| 344 | 343 | { |
| 345 | | for (x_mos = 0; x_mos < (snes_ppu.mosaic_size + 1); x_mos++) |
| 344 | for (x_mos = 0; x_mos < (m_mosaic_size + 1); x_mos++) |
| 346 | 345 | snes_draw_bgtile_lores(layer, ii + x_mos, colour, pal, direct_colors, priority); |
| 347 | 346 | ii += x_mos - 1; |
| 348 | 347 | } |
| r21558 | r21559 | |
| 353 | 352 | { |
| 354 | 353 | if (mosaic) |
| 355 | 354 | { |
| 356 | | for (x_mos = 0; x_mos < (snes_ppu.mosaic_size + 1); x_mos++) |
| 355 | for (x_mos = 0; x_mos < (m_mosaic_size + 1); x_mos++) |
| 357 | 356 | snes_draw_bgtile_hires(layer, ii + x_mos, colour, pal, direct_colors, priority); |
| 358 | 357 | ii += x_mos - 1; |
| 359 | 358 | } |
| r21558 | r21559 | |
| 369 | 368 | * BG drawing theory of each scanline is quite easy: depending on the graphics Mode (0-7), there |
| 370 | 369 | * are up to 4 background layers. Pixels for each BG layer can have two different priorities. |
| 371 | 370 | * Depending on the line and on the BGHOFS and BGVOFS PPU registers, we first determine the tile |
| 372 | | * address in m_snes_vram (by determining x,y coord and tile size and by calling snes_get_tmap_addr). |
| 371 | * address in m_vram (by determining x,y coord and tile size and by calling snes_get_tmap_addr). |
| 373 | 372 | * Then, we load the correspondent data and we determine the tile properties: which priority to |
| 374 | 373 | * use, which palette etc. Finally, for each pixel of the tile appearing on screen, we check if |
| 375 | 374 | * the tile priority is higher than the BG/OAM already stored in that pixel for that line. If so |
| r21558 | r21559 | |
| 386 | 385 | * Find the address in VRAM of the tile (x,y) |
| 387 | 386 | *********************************************/ |
| 388 | 387 | |
| 389 | | inline UINT32 snes_state::snes_get_tmap_addr( UINT8 layer, UINT8 tile_size, UINT32 base, UINT32 x, UINT32 y ) |
| 388 | inline UINT32 snes_ppu_class::snes_get_tmap_addr( UINT8 layer, UINT8 tile_size, UINT32 base, UINT32 x, UINT32 y ) |
| 390 | 389 | { |
| 391 | 390 | UINT32 res = base; |
| 392 | 391 | x >>= (3 + tile_size); |
| 393 | 392 | y >>= (3 + tile_size); |
| 394 | 393 | |
| 395 | | res += (snes_ppu.layer[layer].tilemap_size & 2) ? ((y & 0x20) << ((snes_ppu.layer[layer].tilemap_size & 1) ? 7 : 6)) : 0; |
| 394 | res += (m_layer[layer].tilemap_size & 2) ? ((y & 0x20) << ((m_layer[layer].tilemap_size & 1) ? 7 : 6)) : 0; |
| 396 | 395 | /* Scroll vertically */ |
| 397 | 396 | res += (y & 0x1f) << 6; |
| 398 | 397 | /* Offset horizontally */ |
| 399 | | res += (snes_ppu.layer[layer].tilemap_size & 1) ? ((x & 0x20) << 6) : 0; |
| 398 | res += (m_layer[layer].tilemap_size & 1) ? ((x & 0x20) << 6) : 0; |
| 400 | 399 | /* Scroll horizontally */ |
| 401 | 400 | res += (x & 0x1f) << 1; |
| 402 | 401 | |
| r21558 | r21559 | |
| 409 | 408 | * Update an entire line of tiles. |
| 410 | 409 | *********************************************/ |
| 411 | 410 | |
| 412 | | inline void snes_state::snes_update_line( UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a, UINT8 color_depth, UINT8 hires, UINT8 offset_per_tile, UINT8 direct_colors ) |
| 411 | inline void snes_ppu_class::snes_update_line( UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a, UINT8 color_depth, UINT8 hires, UINT8 offset_per_tile, UINT8 direct_colors ) |
| 413 | 412 | { |
| 414 | 413 | UINT32 tmap, tile, xoff, yoff, charaddr, addr; |
| 415 | 414 | UINT16 ii = 0, vflip, hflip, pal, pal_direct, tilemap; |
| r21558 | r21559 | |
| 428 | 427 | return; |
| 429 | 428 | #endif /* SNES_LAYER_DEBUG */ |
| 430 | 429 | |
| 431 | | scanlines[SNES_MAINSCREEN].enable = snes_ppu.layer[layer].main_bg_enabled; |
| 432 | | scanlines[SNES_SUBSCREEN].enable = snes_ppu.layer[layer].sub_bg_enabled; |
| 433 | | scanlines[SNES_MAINSCREEN].clip = snes_ppu.layer[layer].main_window_enabled; |
| 434 | | scanlines[SNES_SUBSCREEN].clip = snes_ppu.layer[layer].sub_window_enabled; |
| 430 | scanlines[SNES_MAINSCREEN].enable = m_layer[layer].main_bg_enabled; |
| 431 | scanlines[SNES_SUBSCREEN].enable = m_layer[layer].sub_bg_enabled; |
| 432 | scanlines[SNES_MAINSCREEN].clip = m_layer[layer].main_window_enabled; |
| 433 | scanlines[SNES_SUBSCREEN].clip = m_layer[layer].sub_window_enabled; |
| 435 | 434 | |
| 436 | 435 | if (!scanlines[SNES_MAINSCREEN].enable && !scanlines[SNES_SUBSCREEN].enable) |
| 437 | 436 | return; |
| 438 | 437 | |
| 439 | 438 | /* Handle Mosaic effects */ |
| 440 | | if (snes_ppu.layer[layer].mosaic_enabled) |
| 441 | | curline -= (curline % (snes_ppu.mosaic_size + 1)); |
| 439 | if (m_layer[layer].mosaic_enabled) |
| 440 | curline -= (curline % (m_mosaic_size + 1)); |
| 442 | 441 | |
| 443 | | if ((snes_ppu.interlace == 2) && !hires && !snes_ppu.pseudo_hires) |
| 442 | if ((m_interlace == 2) && !hires && !m_pseudo_hires) |
| 444 | 443 | curline /= 2; |
| 445 | 444 | |
| 446 | 445 | /* Find the size of the tiles (8x8 or 16x16) */ |
| 447 | | tile_size = snes_ppu.layer[layer].tile_size; |
| 446 | tile_size = m_layer[layer].tile_size; |
| 448 | 447 | |
| 449 | 448 | /* Find scroll info */ |
| 450 | | xoff = snes_ppu.layer[layer].hoffs; |
| 451 | | yoff = snes_ppu.layer[layer].voffs; |
| 449 | xoff = m_layer[layer].hoffs; |
| 450 | yoff = m_layer[layer].voffs; |
| 452 | 451 | |
| 453 | 452 | xscroll = xoff & ((1 << (3 + tile_size)) - 1); |
| 454 | 453 | |
| 455 | 454 | /* Jump to base map address */ |
| 456 | | tmap = snes_ppu.layer[layer].tilemap << 9; |
| 457 | | charaddr = snes_ppu.layer[layer].charmap << 13; |
| 455 | tmap = m_layer[layer].tilemap << 9; |
| 456 | charaddr = m_layer[layer].charmap << 13; |
| 458 | 457 | |
| 459 | 458 | while (ii < 256 + (8 << tile_size)) |
| 460 | 459 | { |
| r21558 | r21559 | |
| 474 | 473 | { |
| 475 | 474 | case SNES_OPT_MODE2: |
| 476 | 475 | case SNES_OPT_MODE6: |
| 477 | | haddr = snes_get_tmap_addr(SNES_BG3, snes_ppu.layer[SNES_BG3].tile_size, snes_ppu.layer[SNES_BG3].tilemap << 9, (opt_x - 8) + ((snes_ppu.layer[SNES_BG3].hoffs & 0x3ff) & ~7), (snes_ppu.layer[SNES_BG3].voffs & 0x3ff)); |
| 478 | | vaddr = snes_get_tmap_addr(SNES_BG3, snes_ppu.layer[SNES_BG3].tile_size, snes_ppu.layer[SNES_BG3].tilemap << 9, (opt_x - 8) + ((snes_ppu.layer[SNES_BG3].hoffs & 0x3ff) & ~7), (snes_ppu.layer[SNES_BG3].voffs & 0x3ff) + 8); |
| 479 | | hval = m_snes_vram[haddr % SNES_VRAM_SIZE] | (m_snes_vram[(haddr + 1) % SNES_VRAM_SIZE] << 8); |
| 480 | | vval = m_snes_vram[vaddr % SNES_VRAM_SIZE] | (m_snes_vram[(vaddr + 1) % SNES_VRAM_SIZE] << 8); |
| 476 | haddr = snes_get_tmap_addr(SNES_BG3, m_layer[SNES_BG3].tile_size, m_layer[SNES_BG3].tilemap << 9, (opt_x - 8) + ((m_layer[SNES_BG3].hoffs & 0x3ff) & ~7), (m_layer[SNES_BG3].voffs & 0x3ff)); |
| 477 | vaddr = snes_get_tmap_addr(SNES_BG3, m_layer[SNES_BG3].tile_size, m_layer[SNES_BG3].tilemap << 9, (opt_x - 8) + ((m_layer[SNES_BG3].hoffs & 0x3ff) & ~7), (m_layer[SNES_BG3].voffs & 0x3ff) + 8); |
| 478 | hval = m_vram[haddr % SNES_VRAM_SIZE] | (m_vram[(haddr + 1) % SNES_VRAM_SIZE] << 8); |
| 479 | vval = m_vram[vaddr % SNES_VRAM_SIZE] | (m_vram[(vaddr + 1) % SNES_VRAM_SIZE] << 8); |
| 481 | 480 | if (BIT(hval, opt_bit)) |
| 482 | 481 | xpos = opt_x + (hval & ~7); |
| 483 | 482 | if (BIT(vval, opt_bit)) |
| 484 | 483 | ypos = curline + vval; |
| 485 | 484 | break; |
| 486 | 485 | case SNES_OPT_MODE4: |
| 487 | | haddr = snes_get_tmap_addr(SNES_BG3, snes_ppu.layer[SNES_BG3].tile_size, snes_ppu.layer[SNES_BG3].tilemap << 9, (opt_x - 8) + ((snes_ppu.layer[SNES_BG3].hoffs & 0x3ff) & ~7), (snes_ppu.layer[SNES_BG3].voffs & 0x3ff)); |
| 488 | | hval = m_snes_vram[haddr % SNES_VRAM_SIZE] | (m_snes_vram[(haddr + 1) % SNES_VRAM_SIZE] << 8); |
| 486 | haddr = snes_get_tmap_addr(SNES_BG3, m_layer[SNES_BG3].tile_size, m_layer[SNES_BG3].tilemap << 9, (opt_x - 8) + ((m_layer[SNES_BG3].hoffs & 0x3ff) & ~7), (m_layer[SNES_BG3].voffs & 0x3ff)); |
| 487 | hval = m_vram[haddr % SNES_VRAM_SIZE] | (m_vram[(haddr + 1) % SNES_VRAM_SIZE] << 8); |
| 489 | 488 | if (BIT(hval, opt_bit)) |
| 490 | 489 | { |
| 491 | 490 | if (!BIT(hval, 15)) |
| r21558 | r21559 | |
| 509 | 508 | ppp = Tile palette. The number of entries in the palette depends on the Mode and the BG. |
| 510 | 509 | cccccccccc = Tile number. |
| 511 | 510 | */ |
| 512 | | tilemap = m_snes_vram[addr % SNES_VRAM_SIZE] | (m_snes_vram[(addr + 1) % SNES_VRAM_SIZE] << 8); |
| 511 | tilemap = m_vram[addr % SNES_VRAM_SIZE] | (m_vram[(addr + 1) % SNES_VRAM_SIZE] << 8); |
| 513 | 512 | vflip = BIT(tilemap, 15); |
| 514 | 513 | hflip = BIT(tilemap, 14); |
| 515 | 514 | priority = BIT(tilemap, 13) ? priority_a : priority_b; |
| r21558 | r21559 | |
| 519 | 518 | pal = ((pal_direct >> 2) << color_shift); |
| 520 | 519 | |
| 521 | 520 | /* Mode 0 palettes are layer specific */ |
| 522 | | if (snes_ppu.mode == 0) |
| 521 | if (m_mode == 0) |
| 523 | 522 | { |
| 524 | 523 | pal += (layer << 5); |
| 525 | 524 | } |
| r21558 | r21559 | |
| 594 | 593 | |
| 595 | 594 | #define MODE7_CLIP(x) (((x) & 0x2000) ? ((x) | ~0x03ff) : ((x) & 0x03ff)) |
| 596 | 595 | |
| 597 | | void snes_state::snes_update_line_mode7( UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a ) |
| 596 | void snes_ppu_class::snes_update_line_mode7( UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a ) |
| 598 | 597 | { |
| 599 | 598 | UINT32 tiled; |
| 600 | 599 | INT16 ma, mb, mc, md; |
| r21558 | r21559 | |
| 610 | 609 | return; |
| 611 | 610 | #endif /* SNES_LAYER_DEBUG */ |
| 612 | 611 | |
| 613 | | scanlines[SNES_MAINSCREEN].enable = snes_ppu.layer[layer].main_bg_enabled; |
| 614 | | scanlines[SNES_SUBSCREEN].enable = snes_ppu.layer[layer].sub_bg_enabled; |
| 615 | | scanlines[SNES_MAINSCREEN].clip = snes_ppu.layer[layer].main_window_enabled; |
| 616 | | scanlines[SNES_SUBSCREEN].clip = snes_ppu.layer[layer].sub_window_enabled; |
| 612 | scanlines[SNES_MAINSCREEN].enable = m_layer[layer].main_bg_enabled; |
| 613 | scanlines[SNES_SUBSCREEN].enable = m_layer[layer].sub_bg_enabled; |
| 614 | scanlines[SNES_MAINSCREEN].clip = m_layer[layer].main_window_enabled; |
| 615 | scanlines[SNES_SUBSCREEN].clip = m_layer[layer].sub_window_enabled; |
| 617 | 616 | |
| 618 | 617 | if (!scanlines[SNES_MAINSCREEN].enable && !scanlines[SNES_SUBSCREEN].enable) |
| 619 | 618 | return; |
| 620 | 619 | |
| 621 | | ma = snes_ppu.mode7.matrix_a; |
| 622 | | mb = snes_ppu.mode7.matrix_b; |
| 623 | | mc = snes_ppu.mode7.matrix_c; |
| 624 | | md = snes_ppu.mode7.matrix_d; |
| 625 | | xc = snes_ppu.mode7.origin_x; |
| 626 | | yc = snes_ppu.mode7.origin_y; |
| 627 | | hs = snes_ppu.mode7.hor_offset; |
| 628 | | vs = snes_ppu.mode7.ver_offset; |
| 620 | ma = m_mode7.matrix_a; |
| 621 | mb = m_mode7.matrix_b; |
| 622 | mc = m_mode7.matrix_c; |
| 623 | md = m_mode7.matrix_d; |
| 624 | xc = m_mode7.origin_x; |
| 625 | yc = m_mode7.origin_y; |
| 626 | hs = m_mode7.hor_offset; |
| 627 | vs = m_mode7.ver_offset; |
| 629 | 628 | |
| 630 | 629 | /* Sign extend */ |
| 631 | 630 | xc <<= 19; |
| r21558 | r21559 | |
| 638 | 637 | vs >>= 19; |
| 639 | 638 | |
| 640 | 639 | /* Vertical flip */ |
| 641 | | if (snes_ppu.mode7.vflip) |
| 640 | if (m_mode7.vflip) |
| 642 | 641 | sy = 255 - curline; |
| 643 | 642 | else |
| 644 | 643 | sy = curline; |
| 645 | 644 | |
| 646 | 645 | /* Horizontal flip */ |
| 647 | | if (snes_ppu.mode7.hflip) |
| 646 | if (m_mode7.hflip) |
| 648 | 647 | { |
| 649 | 648 | xpos = 255; |
| 650 | 649 | xdir = -1; |
| r21558 | r21559 | |
| 658 | 657 | /* MOSAIC - to be verified */ |
| 659 | 658 | if (layer == SNES_BG2) // BG2 use two different bits for horizontal and vertical mosaic |
| 660 | 659 | { |
| 661 | | mosaic_x = snes_ppu.mosaic_table[snes_ppu.layer[SNES_BG2].mosaic_enabled ? snes_ppu.mosaic_size : 0]; |
| 662 | | mosaic_y = snes_ppu.mosaic_table[snes_ppu.layer[SNES_BG1].mosaic_enabled ? snes_ppu.mosaic_size : 0]; |
| 660 | mosaic_x = m_mosaic_table[m_layer[SNES_BG2].mosaic_enabled ? m_mosaic_size : 0]; |
| 661 | mosaic_y = m_mosaic_table[m_layer[SNES_BG1].mosaic_enabled ? m_mosaic_size : 0]; |
| 663 | 662 | } |
| 664 | 663 | else // BG1 works as usual |
| 665 | 664 | { |
| 666 | | mosaic_x = snes_ppu.mosaic_table[snes_ppu.layer[SNES_BG1].mosaic_enabled ? snes_ppu.mosaic_size : 0]; |
| 667 | | mosaic_y = snes_ppu.mosaic_table[snes_ppu.layer[SNES_BG1].mosaic_enabled ? snes_ppu.mosaic_size : 0]; |
| 665 | mosaic_x = m_mosaic_table[m_layer[SNES_BG1].mosaic_enabled ? m_mosaic_size : 0]; |
| 666 | mosaic_y = m_mosaic_table[m_layer[SNES_BG1].mosaic_enabled ? m_mosaic_size : 0]; |
| 668 | 667 | } |
| 669 | 668 | |
| 670 | 669 | #if SNES_LAYER_DEBUG |
| 671 | 670 | if (debug_options.mosaic_disabled) |
| 672 | 671 | { |
| 673 | | mosaic_x = snes_ppu.mosaic_table[0]; |
| 674 | | mosaic_y = snes_ppu.mosaic_table[0]; |
| 672 | mosaic_x = m_mosaic_table[0]; |
| 673 | mosaic_y = m_mosaic_table[0]; |
| 675 | 674 | } |
| 676 | 675 | #endif /* SNES_LAYER_DEBUG */ |
| 677 | 676 | |
| r21558 | r21559 | |
| 685 | 684 | tx = (x0 + (ma * mosaic_x[sx])) >> 8; |
| 686 | 685 | ty = (y0 + (mc * mosaic_x[sx])) >> 8; |
| 687 | 686 | |
| 688 | | switch (snes_ppu.mode7.repeat) |
| 687 | switch (m_mode7.repeat) |
| 689 | 688 | { |
| 690 | 689 | case 0x00: /* Repeat if outside screen area */ |
| 691 | 690 | case 0x01: /* Repeat if outside screen area */ |
| 692 | 691 | tx &= 0x3ff; |
| 693 | 692 | ty &= 0x3ff; |
| 694 | | tiled = m_snes_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 695 | | colour = m_snes_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 693 | tiled = m_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 694 | colour = m_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 696 | 695 | break; |
| 697 | 696 | case 0x02: /* Single colour backdrop screen if outside screen area */ |
| 698 | 697 | if ((tx >= 0) && (tx < 1024) && (ty >= 0) && (ty < 1024)) |
| 699 | 698 | { |
| 700 | | tiled = m_snes_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 701 | | colour = m_snes_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 699 | tiled = m_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 700 | colour = m_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 702 | 701 | } |
| 703 | 702 | else |
| 704 | 703 | colour = 0; |
| 705 | 704 | break; |
| 706 | 705 | case 0x03: /* Character 0x00 repeat if outside screen area */ |
| 707 | 706 | if ((tx >= 0) && (tx < 1024) && (ty >= 0) && (ty < 1024)) |
| 708 | | tiled = m_snes_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 707 | tiled = m_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 709 | 708 | else |
| 710 | 709 | tiled = 0; |
| 711 | 710 | |
| 712 | | colour = m_snes_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 711 | colour = m_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 713 | 712 | break; |
| 714 | 713 | } |
| 715 | 714 | |
| r21558 | r21559 | |
| 732 | 731 | if (scanlines[screen].enable) |
| 733 | 732 | { |
| 734 | 733 | UINT8 clr = colour; |
| 735 | | UINT8 clipmask = snes_ppu.clipmasks[layer][xpos]; |
| 734 | UINT8 clipmask = m_clipmasks[layer][xpos]; |
| 736 | 735 | |
| 737 | 736 | #if SNES_LAYER_DEBUG |
| 738 | 737 | if (debug_options.windows_disabled) |
| r21558 | r21559 | |
| 749 | 748 | /* Direct select, but only outside EXTBG! */ |
| 750 | 749 | // Direct color format is: 0 | BB000 | GGG00 | RRR00, HW confirms that the data is zero padded. |
| 751 | 750 | // In other words, like normal direct color, with pal = 0 |
| 752 | | c = snes_get_bgcolor(snes_ppu.direct_color && layer == SNES_BG1, 0, clr); |
| 751 | c = snes_get_bgcolor(m_direct_color && layer == SNES_BG1, 0, clr); |
| 753 | 752 | snes_set_scanline_pixel(screen, xpos, c, priority, layer, 0); |
| 754 | 753 | } |
| 755 | 754 | } |
| r21558 | r21559 | |
| 819 | 818 | * Update sprite settings for next line. |
| 820 | 819 | *********************************************/ |
| 821 | 820 | |
| 822 | | void snes_state::snes_update_obsel( void ) |
| 821 | void snes_ppu_class::snes_update_obsel( void ) |
| 823 | 822 | { |
| 824 | | snes_ppu.layer[SNES_OAM].charmap = snes_ppu.oam.next_charmap; |
| 825 | | snes_ppu.oam.name_select = snes_ppu.oam.next_name_select; |
| 823 | m_layer[SNES_OAM].charmap = m_oam.next_charmap; |
| 824 | m_oam.name_select = m_oam.next_name_select; |
| 826 | 825 | |
| 827 | | if (snes_ppu.oam.size != snes_ppu.oam.next_size) |
| 826 | if (m_oam.size != m_oam.next_size) |
| 828 | 827 | { |
| 829 | | snes_ppu.oam.size = snes_ppu.oam.next_size; |
| 830 | | snes_ppu.update_oam_list = 1; |
| 828 | m_oam.size = m_oam.next_size; |
| 829 | m_update_oam_list = 1; |
| 831 | 830 | } |
| 832 | 831 | } |
| 833 | 832 | |
| r21558 | r21559 | |
| 837 | 836 | * Build a list of the available obj in OAM ram. |
| 838 | 837 | *********************************************/ |
| 839 | 838 | |
| 840 | | void snes_state::snes_oam_list_build( void ) |
| 839 | void snes_ppu_class::snes_oam_list_build( void ) |
| 841 | 840 | { |
| 842 | | UINT8 *oamram = (UINT8 *)m_snes_oam; |
| 841 | UINT8 *oamram = (UINT8 *)m_oam_ram; |
| 843 | 842 | INT16 oam = 0x1ff; |
| 844 | 843 | UINT16 oam_extra = oam + 0x20; |
| 845 | 844 | UINT16 extra = 0; |
| 846 | 845 | int ii; |
| 847 | 846 | |
| 848 | | snes_ppu.update_oam_list = 0; // eventually, we can optimize the code by only calling this function when there is a change in size |
| 847 | m_update_oam_list = 0; // eventually, we can optimize the code by only calling this function when there is a change in size |
| 849 | 848 | |
| 850 | 849 | for (ii = 127; ii >= 0; ii--) |
| 851 | 850 | { |
| r21558 | r21559 | |
| 865 | 864 | oam_spritelist[ii].x |= ((extra & 0x80) << 1); |
| 866 | 865 | extra <<= 1; |
| 867 | 866 | |
| 868 | | oam_spritelist[ii].y *= snes_ppu.obj_interlace; |
| 867 | oam_spritelist[ii].y *= m_obj_interlace; |
| 869 | 868 | oam_spritelist[ii].y &= 0x1ff; |
| 870 | 869 | |
| 871 | 870 | oam_spritelist[ii].x &= 0x1ff; |
| 872 | 871 | |
| 873 | 872 | /* Determine object size */ |
| 874 | | switch (snes_ppu.oam.size) |
| 873 | switch (m_oam.size) |
| 875 | 874 | { |
| 876 | 875 | case 0: /* 8x8 or 16x16 */ |
| 877 | 876 | oam_spritelist[ii].width = oam_spritelist[ii].size ? 2 : 1; |
| r21558 | r21559 | |
| 900 | 899 | case 6: /* undocumented: 16x32 or 32x64 */ |
| 901 | 900 | oam_spritelist[ii].width = oam_spritelist[ii].size ? 4 : 2; |
| 902 | 901 | oam_spritelist[ii].height = oam_spritelist[ii].size ? 8 : 4; |
| 903 | | if (snes_ppu.obj_interlace && !oam_spritelist[ii].size) |
| 902 | if (m_obj_interlace && !oam_spritelist[ii].size) |
| 904 | 903 | oam_spritelist[ii].height = 2; |
| 905 | 904 | break; |
| 906 | 905 | case 7: /* undocumented: 16x32 or 32x32 */ |
| 907 | 906 | oam_spritelist[ii].width = oam_spritelist[ii].size ? 4 : 2; |
| 908 | 907 | oam_spritelist[ii].height = oam_spritelist[ii].size ? 4 : 4; |
| 909 | | if (snes_ppu.obj_interlace && !oam_spritelist[ii].size) |
| 908 | if (m_obj_interlace && !oam_spritelist[ii].size) |
| 910 | 909 | oam_spritelist[ii].height = 2; |
| 911 | 910 | break; |
| 912 | 911 | default: |
| 913 | 912 | /* we should never enter here... */ |
| 914 | | logerror("Object size unsupported: %d\n", snes_ppu.oam.size); |
| 913 | logerror("Object size unsupported: %d\n", m_oam.size); |
| 915 | 914 | break; |
| 916 | 915 | } |
| 917 | 916 | } |
| r21558 | r21559 | |
| 924 | 923 | * scanline |
| 925 | 924 | *********************************************/ |
| 926 | 925 | |
| 927 | | int snes_state::is_sprite_on_scanline( UINT16 curline, UINT8 sprite ) |
| 926 | int snes_ppu_class::is_sprite_on_scanline( UINT16 curline, UINT8 sprite ) |
| 928 | 927 | { |
| 929 | 928 | //if sprite is entirely offscreen and doesn't wrap around to the left side of the screen, |
| 930 | 929 | //then it is not counted. this *should* be 256, and not 255, even though dot 256 is offscreen. |
| r21558 | r21559 | |
| 949 | 948 | * scanline. |
| 950 | 949 | *********************************************/ |
| 951 | 950 | |
| 952 | | void snes_state::snes_update_objects_rto( UINT16 curline ) |
| 951 | void snes_ppu_class::snes_update_objects_rto( UINT16 curline ) |
| 953 | 952 | { |
| 954 | 953 | int ii, jj, active_sprite; |
| 955 | 954 | UINT8 range_over, time_over; |
| r21558 | r21559 | |
| 967 | 966 | time_over = 0; |
| 968 | 967 | |
| 969 | 968 | /* setup the proper line */ |
| 970 | | curline /= snes_ppu.interlace; |
| 971 | | curline *= snes_ppu.obj_interlace; |
| 969 | curline /= m_interlace; |
| 970 | curline *= m_obj_interlace; |
| 972 | 971 | |
| 973 | 972 | /* reset the list of first 32 objects which intersect current scanline */ |
| 974 | 973 | memset(oam_itemlist, 0xff, 32); |
| r21558 | r21559 | |
| 976 | 975 | /* populate the list of 32 objects */ |
| 977 | 976 | for (ii = 0; ii < 128; ii++) |
| 978 | 977 | { |
| 979 | | active_sprite = (ii + snes_ppu.oam.first_sprite) & 0x7f; |
| 978 | active_sprite = (ii + m_oam.first_sprite) & 0x7f; |
| 980 | 979 | |
| 981 | 980 | if (!is_sprite_on_scanline(curline, active_sprite)) |
| 982 | 981 | continue; |
| r21558 | r21559 | |
| 1010 | 1009 | pal = oam_spritelist[active_sprite].pal; |
| 1011 | 1010 | |
| 1012 | 1011 | /* Adjust y, if past maximum position (for sprites which overlap between top & bottom) */ |
| 1013 | | if (y >= (0x100 - 16) * snes_ppu.interlace) |
| 1014 | | y -= (0x100) * snes_ppu.interlace; |
| 1012 | if (y >= (0x100 - 16) * m_interlace) |
| 1013 | y -= (0x100) * m_interlace; |
| 1015 | 1014 | |
| 1016 | 1015 | if (curline >= y && curline < (y + (height << 3))) |
| 1017 | 1016 | { |
| 1018 | 1017 | /* Only objects using tiles over 255 use name select */ |
| 1019 | | name_sel = (tile < 256) ? 0 : snes_ppu.oam.name_select; |
| 1018 | name_sel = (tile < 256) ? 0 : m_oam.name_select; |
| 1020 | 1019 | |
| 1021 | 1020 | ys = (curline - y) >> 3; |
| 1022 | 1021 | line = (curline - y) % 8; |
| r21558 | r21559 | |
| 1050 | 1049 | |
| 1051 | 1050 | /* set Range Over flag if necessary */ |
| 1052 | 1051 | if (range_over > 32) |
| 1053 | | snes_ppu.stat77_flags |= 0x40; |
| 1052 | m_stat77_flags |= 0x40; |
| 1054 | 1053 | |
| 1055 | 1054 | /* set Time Over flag if necessary */ |
| 1056 | 1055 | if (time_over > 34) |
| 1057 | | snes_ppu.stat77_flags |= 0x80; |
| 1056 | m_stat77_flags |= 0x80; |
| 1058 | 1057 | } |
| 1059 | 1058 | |
| 1060 | 1059 | /********************************************* |
| r21558 | r21559 | |
| 1063 | 1062 | * Update an entire line of sprites. |
| 1064 | 1063 | *********************************************/ |
| 1065 | 1064 | |
| 1066 | | void snes_state::snes_update_objects( UINT8 priority_oam0, UINT8 priority_oam1, UINT8 priority_oam2, UINT8 priority_oam3 ) |
| 1065 | void snes_ppu_class::snes_update_objects( UINT8 priority_oam0, UINT8 priority_oam1, UINT8 priority_oam2, UINT8 priority_oam3 ) |
| 1067 | 1066 | { |
| 1068 | 1067 | UINT8 pri, priority[4]; |
| 1069 | 1068 | UINT32 charaddr; |
| r21558 | r21559 | |
| 1074 | 1073 | return; |
| 1075 | 1074 | #endif /* SNES_LAYER_DEBUG */ |
| 1076 | 1075 | |
| 1077 | | scanlines[SNES_MAINSCREEN].enable = snes_ppu.layer[SNES_OAM].main_bg_enabled; |
| 1078 | | scanlines[SNES_SUBSCREEN].enable = snes_ppu.layer[SNES_OAM].sub_bg_enabled; |
| 1079 | | scanlines[SNES_MAINSCREEN].clip = snes_ppu.layer[SNES_OAM].main_window_enabled; |
| 1080 | | scanlines[SNES_SUBSCREEN].clip = snes_ppu.layer[SNES_OAM].sub_window_enabled; |
| 1076 | scanlines[SNES_MAINSCREEN].enable = m_layer[SNES_OAM].main_bg_enabled; |
| 1077 | scanlines[SNES_SUBSCREEN].enable = m_layer[SNES_OAM].sub_bg_enabled; |
| 1078 | scanlines[SNES_MAINSCREEN].clip = m_layer[SNES_OAM].main_window_enabled; |
| 1079 | scanlines[SNES_SUBSCREEN].clip = m_layer[SNES_OAM].sub_window_enabled; |
| 1081 | 1080 | |
| 1082 | 1081 | if (!scanlines[SNES_MAINSCREEN].enable && !scanlines[SNES_SUBSCREEN].enable) |
| 1083 | 1082 | return; |
| 1084 | 1083 | |
| 1085 | | charaddr = snes_ppu.layer[SNES_OAM].charmap << 13; |
| 1084 | charaddr = m_layer[SNES_OAM].charmap << 13; |
| 1086 | 1085 | |
| 1087 | 1086 | priority[0] = priority_oam0; |
| 1088 | 1087 | priority[1] = priority_oam1; |
| r21558 | r21559 | |
| 1124 | 1123 | * Update Mode X line. |
| 1125 | 1124 | *********************************************/ |
| 1126 | 1125 | |
| 1127 | | void snes_state::snes_update_mode_0( UINT16 curline ) |
| 1126 | void snes_ppu_class::snes_update_mode_0( UINT16 curline ) |
| 1128 | 1127 | { |
| 1129 | 1128 | #if SNES_LAYER_DEBUG |
| 1130 | 1129 | if (debug_options.mode_disabled[0]) |
| r21558 | r21559 | |
| 1138 | 1137 | snes_update_line(curline, SNES_BG4, 1, 4, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_NONE, 0); |
| 1139 | 1138 | } |
| 1140 | 1139 | |
| 1141 | | void snes_state::snes_update_mode_1( UINT16 curline ) |
| 1140 | void snes_ppu_class::snes_update_mode_1( UINT16 curline ) |
| 1142 | 1141 | { |
| 1143 | 1142 | #if SNES_LAYER_DEBUG |
| 1144 | 1143 | if (debug_options.mode_disabled[1]) |
| 1145 | 1144 | return; |
| 1146 | 1145 | #endif /* SNES_LAYER_DEBUG */ |
| 1147 | 1146 | |
| 1148 | | if (!snes_ppu.bg3_priority_bit) |
| 1147 | if (!m_bg3_priority_bit) |
| 1149 | 1148 | { |
| 1150 | 1149 | snes_update_objects(2, 4, 7, 10); |
| 1151 | 1150 | snes_update_line(curline, SNES_BG1, 6, 9, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_NONE, 0); |
| r21558 | r21559 | |
| 1161 | 1160 | } |
| 1162 | 1161 | } |
| 1163 | 1162 | |
| 1164 | | void snes_state::snes_update_mode_2( UINT16 curline ) |
| 1163 | void snes_ppu_class::snes_update_mode_2( UINT16 curline ) |
| 1165 | 1164 | { |
| 1166 | 1165 | #if SNES_LAYER_DEBUG |
| 1167 | 1166 | if (debug_options.mode_disabled[2]) |
| r21558 | r21559 | |
| 1173 | 1172 | snes_update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_MODE2, 0); |
| 1174 | 1173 | } |
| 1175 | 1174 | |
| 1176 | | void snes_state::snes_update_mode_3( UINT16 curline ) |
| 1175 | void snes_ppu_class::snes_update_mode_3( UINT16 curline ) |
| 1177 | 1176 | { |
| 1178 | 1177 | #if SNES_LAYER_DEBUG |
| 1179 | 1178 | if (debug_options.mode_disabled[3]) |
| r21558 | r21559 | |
| 1181 | 1180 | #endif /* SNES_LAYER_DEBUG */ |
| 1182 | 1181 | |
| 1183 | 1182 | snes_update_objects(2, 4, 6, 8); |
| 1184 | | snes_update_line(curline, SNES_BG1, 3, 7, SNES_COLOR_DEPTH_8BPP, 0, SNES_OPT_NONE, snes_ppu.direct_color); |
| 1183 | snes_update_line(curline, SNES_BG1, 3, 7, SNES_COLOR_DEPTH_8BPP, 0, SNES_OPT_NONE, m_direct_color); |
| 1185 | 1184 | snes_update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_NONE, 0); |
| 1186 | 1185 | } |
| 1187 | 1186 | |
| 1188 | | void snes_state::snes_update_mode_4( UINT16 curline ) |
| 1187 | void snes_ppu_class::snes_update_mode_4( UINT16 curline ) |
| 1189 | 1188 | { |
| 1190 | 1189 | #if SNES_LAYER_DEBUG |
| 1191 | 1190 | if (debug_options.mode_disabled[4]) |
| r21558 | r21559 | |
| 1193 | 1192 | #endif /* SNES_LAYER_DEBUG */ |
| 1194 | 1193 | |
| 1195 | 1194 | snes_update_objects(2, 4, 6, 8); |
| 1196 | | snes_update_line(curline, SNES_BG1, 3, 7, SNES_COLOR_DEPTH_8BPP, 0, SNES_OPT_MODE4, snes_ppu.direct_color); |
| 1195 | snes_update_line(curline, SNES_BG1, 3, 7, SNES_COLOR_DEPTH_8BPP, 0, SNES_OPT_MODE4, m_direct_color); |
| 1197 | 1196 | snes_update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_MODE4, 0); |
| 1198 | 1197 | } |
| 1199 | 1198 | |
| 1200 | | void snes_state::snes_update_mode_5( UINT16 curline ) |
| 1199 | void snes_ppu_class::snes_update_mode_5( UINT16 curline ) |
| 1201 | 1200 | { |
| 1202 | 1201 | #if SNES_LAYER_DEBUG |
| 1203 | 1202 | if (debug_options.mode_disabled[5]) |
| r21558 | r21559 | |
| 1209 | 1208 | snes_update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_2BPP, 1, SNES_OPT_NONE, 0); |
| 1210 | 1209 | } |
| 1211 | 1210 | |
| 1212 | | void snes_state::snes_update_mode_6( UINT16 curline ) |
| 1211 | void snes_ppu_class::snes_update_mode_6( UINT16 curline ) |
| 1213 | 1212 | { |
| 1214 | 1213 | #if SNES_LAYER_DEBUG |
| 1215 | 1214 | if (debug_options.mode_disabled[6]) |
| r21558 | r21559 | |
| 1220 | 1219 | snes_update_line(curline, SNES_BG1, 2, 5, SNES_COLOR_DEPTH_4BPP, 1, SNES_OPT_MODE6, 0); |
| 1221 | 1220 | } |
| 1222 | 1221 | |
| 1223 | | void snes_state::snes_update_mode_7( UINT16 curline ) |
| 1222 | void snes_ppu_class::snes_update_mode_7( UINT16 curline ) |
| 1224 | 1223 | { |
| 1225 | 1224 | #if SNES_LAYER_DEBUG |
| 1226 | 1225 | if (debug_options.mode_disabled[7]) |
| 1227 | 1226 | return; |
| 1228 | 1227 | #endif /* SNES_LAYER_DEBUG */ |
| 1229 | 1228 | |
| 1230 | | if (!snes_ppu.mode7.extbg) |
| 1229 | if (!m_mode7.extbg) |
| 1231 | 1230 | { |
| 1232 | 1231 | snes_update_objects(1, 3, 4, 5); |
| 1233 | 1232 | snes_update_line_mode7(curline, SNES_BG1, 2, 2); |
| r21558 | r21559 | |
| 1246 | 1245 | * Draw the whole screen (Mode 0 -> 7). |
| 1247 | 1246 | *********************************************/ |
| 1248 | 1247 | |
| 1249 | | void snes_state::snes_draw_screens( UINT16 curline ) |
| 1248 | void snes_ppu_class::snes_draw_screens( UINT16 curline ) |
| 1250 | 1249 | { |
| 1251 | | switch (snes_ppu.mode) |
| 1250 | switch (m_mode) |
| 1252 | 1251 | { |
| 1253 | 1252 | case 0: snes_update_mode_0(curline); break; /* Mode 0 */ |
| 1254 | 1253 | case 1: snes_update_mode_1(curline); break; /* Mode 1 */ |
| r21558 | r21559 | |
| 1274 | 1273 | * XNOR: ###...##...### ...###..###... |
| 1275 | 1274 | *********************************************/ |
| 1276 | 1275 | |
| 1277 | | void snes_state::snes_update_windowmasks( void ) |
| 1276 | void snes_ppu_class::snes_update_windowmasks( void ) |
| 1278 | 1277 | { |
| 1279 | 1278 | UINT16 ii, jj; |
| 1280 | 1279 | INT8 w1, w2; |
| 1281 | 1280 | |
| 1282 | | snes_ppu.update_windows = 0; /* reset the flag */ |
| 1281 | m_update_windows = 0; /* reset the flag */ |
| 1283 | 1282 | |
| 1284 | 1283 | for (ii = 0; ii < SNES_SCR_WIDTH; ii++) |
| 1285 | 1284 | { |
| r21558 | r21559 | |
| 1287 | 1286 | /* jj = layer */ |
| 1288 | 1287 | for (jj = 0; jj < 6; jj++) |
| 1289 | 1288 | { |
| 1290 | | snes_ppu.clipmasks[jj][ii] = 0xff; /* let's start from un-masked */ |
| 1289 | m_clipmasks[jj][ii] = 0xff; /* let's start from un-masked */ |
| 1291 | 1290 | w1 = w2 = -1; |
| 1292 | 1291 | |
| 1293 | | if (snes_ppu.layer[jj].window1_enabled) |
| 1292 | if (m_layer[jj].window1_enabled) |
| 1294 | 1293 | { |
| 1295 | 1294 | /* Default to mask area inside */ |
| 1296 | | if ((ii < snes_ppu.window1_left) || (ii > snes_ppu.window1_right)) |
| 1295 | if ((ii < m_window1_left) || (ii > m_window1_right)) |
| 1297 | 1296 | w1 = 0; |
| 1298 | 1297 | else |
| 1299 | 1298 | w1 = 1; |
| 1300 | 1299 | |
| 1301 | 1300 | /* If mask area is outside then swap */ |
| 1302 | | if (snes_ppu.layer[jj].window1_invert) |
| 1301 | if (m_layer[jj].window1_invert) |
| 1303 | 1302 | w1 = !w1; |
| 1304 | 1303 | } |
| 1305 | 1304 | |
| 1306 | | if (snes_ppu.layer[jj].window2_enabled) |
| 1305 | if (m_layer[jj].window2_enabled) |
| 1307 | 1306 | { |
| 1308 | | if ((ii < snes_ppu.window2_left) || (ii > snes_ppu.window2_right)) |
| 1307 | if ((ii < m_window2_left) || (ii > m_window2_right)) |
| 1309 | 1308 | w2 = 0; |
| 1310 | 1309 | else |
| 1311 | 1310 | w2 = 1; |
| 1312 | | if (snes_ppu.layer[jj].window2_invert) |
| 1311 | if (m_layer[jj].window2_invert) |
| 1313 | 1312 | w2 = !w2; |
| 1314 | 1313 | } |
| 1315 | 1314 | |
| 1316 | 1315 | /* mask if the appropriate expression is true */ |
| 1317 | 1316 | if (w1 >= 0 && w2 >= 0) |
| 1318 | 1317 | { |
| 1319 | | switch (snes_ppu.layer[jj].wlog_mask) |
| 1318 | switch (m_layer[jj].wlog_mask) |
| 1320 | 1319 | { |
| 1321 | 1320 | case 0x00: /* OR */ |
| 1322 | | snes_ppu.clipmasks[jj][ii] = (w1 | w2) ? 0x00 : 0xff; |
| 1321 | m_clipmasks[jj][ii] = (w1 | w2) ? 0x00 : 0xff; |
| 1323 | 1322 | break; |
| 1324 | 1323 | case 0x01: /* AND */ |
| 1325 | | snes_ppu.clipmasks[jj][ii] = (w1 & w2) ? 0x00 : 0xff; |
| 1324 | m_clipmasks[jj][ii] = (w1 & w2) ? 0x00 : 0xff; |
| 1326 | 1325 | break; |
| 1327 | 1326 | case 0x02: /* XOR */ |
| 1328 | | snes_ppu.clipmasks[jj][ii] = (w1 ^ w2) ? 0x00 : 0xff; |
| 1327 | m_clipmasks[jj][ii] = (w1 ^ w2) ? 0x00 : 0xff; |
| 1329 | 1328 | break; |
| 1330 | 1329 | case 0x03: /* XNOR */ |
| 1331 | | snes_ppu.clipmasks[jj][ii] = !(w1 ^ w2) ? 0x00 : 0xff; |
| 1330 | m_clipmasks[jj][ii] = !(w1 ^ w2) ? 0x00 : 0xff; |
| 1332 | 1331 | break; |
| 1333 | 1332 | } |
| 1334 | 1333 | } |
| 1335 | 1334 | else if (w1 >= 0) |
| 1336 | | snes_ppu.clipmasks[jj][ii] = w1 ? 0x00 : 0xff; |
| 1335 | m_clipmasks[jj][ii] = w1 ? 0x00 : 0xff; |
| 1337 | 1336 | else if (w2 >= 0) |
| 1338 | | snes_ppu.clipmasks[jj][ii] = w2 ? 0x00 : 0xff; |
| 1337 | m_clipmasks[jj][ii] = w2 ? 0x00 : 0xff; |
| 1339 | 1338 | } |
| 1340 | 1339 | } |
| 1341 | 1340 | } |
| r21558 | r21559 | |
| 1348 | 1347 | * possibly be handy for some minor optimization |
| 1349 | 1348 | *********************************************/ |
| 1350 | 1349 | |
| 1351 | | void snes_state::snes_update_offsets( void ) |
| 1350 | void snes_ppu_class::snes_update_offsets( void ) |
| 1352 | 1351 | { |
| 1353 | 1352 | int ii; |
| 1354 | 1353 | for (ii = 0; ii < 4; ii++) |
| 1355 | 1354 | { |
| 1356 | 1355 | } |
| 1357 | | snes_ppu.update_offsets = 0; |
| 1356 | m_update_offsets = 0; |
| 1358 | 1357 | } |
| 1359 | 1358 | |
| 1360 | 1359 | /***************************************** |
| r21558 | r21559 | |
| 1365 | 1364 | * color math. |
| 1366 | 1365 | *****************************************/ |
| 1367 | 1366 | |
| 1368 | | inline void snes_state::snes_draw_blend( UINT16 offset, UINT16 *colour, UINT8 prevent_color_math, UINT8 black_pen_clip, int switch_screens ) |
| 1367 | inline void snes_ppu_class::snes_draw_blend( UINT16 offset, UINT16 *colour, UINT8 prevent_color_math, UINT8 black_pen_clip, int switch_screens ) |
| 1369 | 1368 | { |
| 1370 | 1369 | #if SNES_LAYER_DEBUG |
| 1371 | 1370 | if (debug_options.colormath_disabled) |
| r21558 | r21559 | |
| 1378 | 1377 | offset -= 1; |
| 1379 | 1378 | |
| 1380 | 1379 | if ((black_pen_clip == SNES_CLIP_ALWAYS) || |
| 1381 | | (black_pen_clip == SNES_CLIP_IN && snes_ppu.clipmasks[SNES_COLOR][offset]) || |
| 1382 | | (black_pen_clip == SNES_CLIP_OUT && !snes_ppu.clipmasks[SNES_COLOR][offset])) |
| 1380 | (black_pen_clip == SNES_CLIP_IN && m_clipmasks[SNES_COLOR][offset]) || |
| 1381 | (black_pen_clip == SNES_CLIP_OUT && !m_clipmasks[SNES_COLOR][offset])) |
| 1383 | 1382 | *colour = 0; //clip to black before color math |
| 1384 | 1383 | |
| 1385 | 1384 | if (prevent_color_math == SNES_CLIP_ALWAYS) // blending mode 3 == always OFF |
| 1386 | 1385 | return; |
| 1387 | 1386 | |
| 1388 | 1387 | if ((prevent_color_math == SNES_CLIP_NEVER) || |
| 1389 | | (prevent_color_math == SNES_CLIP_IN && !snes_ppu.clipmasks[SNES_COLOR][offset]) || |
| 1390 | | (prevent_color_math == SNES_CLIP_OUT && snes_ppu.clipmasks[SNES_COLOR][offset])) |
| 1388 | (prevent_color_math == SNES_CLIP_IN && !m_clipmasks[SNES_COLOR][offset]) || |
| 1389 | (prevent_color_math == SNES_CLIP_OUT && m_clipmasks[SNES_COLOR][offset])) |
| 1391 | 1390 | { |
| 1392 | 1391 | UINT16 r, g, b; |
| 1393 | 1392 | struct SCANLINE *subscreen; |
| r21558 | r21559 | |
| 1405 | 1404 | subscreen = switch_screens ? &scanlines[SNES_MAINSCREEN] : &scanlines[SNES_SUBSCREEN]; |
| 1406 | 1405 | } |
| 1407 | 1406 | |
| 1408 | | if (snes_ppu.sub_add_mode) /* SNES_SUBSCREEN*/ |
| 1407 | if (m_sub_add_mode) /* SNES_SUBSCREEN*/ |
| 1409 | 1408 | { |
| 1410 | | if (!BIT(snes_ppu.color_modes, 7)) |
| 1409 | if (!BIT(m_color_modes, 7)) |
| 1411 | 1410 | { |
| 1412 | 1411 | /* 0x00 add */ |
| 1413 | 1412 | r = (*colour & 0x1f) + (subscreen->buffer[offset] & 0x1f); |
| r21558 | r21559 | |
| 1426 | 1425 | if (b > 0x1f) b = 0; |
| 1427 | 1426 | } |
| 1428 | 1427 | /* only halve if the color is not the back colour */ |
| 1429 | | if (BIT(snes_ppu.color_modes, 6) && (subscreen->buffer[offset] != m_snes_cgram[FIXED_COLOUR])) |
| 1428 | if (BIT(m_color_modes, 6) && (subscreen->buffer[offset] != m_cgram[FIXED_COLOUR])) |
| 1430 | 1429 | { |
| 1431 | 1430 | r >>= 1; |
| 1432 | 1431 | g >>= 1; |
| r21558 | r21559 | |
| 1435 | 1434 | } |
| 1436 | 1435 | else /* Fixed colour */ |
| 1437 | 1436 | { |
| 1438 | | if (!BIT(snes_ppu.color_modes, 7)) |
| 1437 | if (!BIT(m_color_modes, 7)) |
| 1439 | 1438 | { |
| 1440 | 1439 | /* 0x00 add */ |
| 1441 | | r = (*colour & 0x1f) + (m_snes_cgram[FIXED_COLOUR] & 0x1f); |
| 1442 | | g = ((*colour & 0x3e0) >> 5) + ((m_snes_cgram[FIXED_COLOUR] & 0x3e0) >> 5); |
| 1443 | | b = ((*colour & 0x7c00) >> 10) + ((m_snes_cgram[FIXED_COLOUR] & 0x7c00) >> 10); |
| 1440 | r = (*colour & 0x1f) + (m_cgram[FIXED_COLOUR] & 0x1f); |
| 1441 | g = ((*colour & 0x3e0) >> 5) + ((m_cgram[FIXED_COLOUR] & 0x3e0) >> 5); |
| 1442 | b = ((*colour & 0x7c00) >> 10) + ((m_cgram[FIXED_COLOUR] & 0x7c00) >> 10); |
| 1444 | 1443 | clip_max = 1; |
| 1445 | 1444 | } |
| 1446 | 1445 | else |
| 1447 | 1446 | { |
| 1448 | 1447 | /* 0x80: sub */ |
| 1449 | | r = (*colour & 0x1f) - (m_snes_cgram[FIXED_COLOUR] & 0x1f); |
| 1450 | | g = ((*colour & 0x3e0) >> 5) - ((m_snes_cgram[FIXED_COLOUR] & 0x3e0) >> 5); |
| 1451 | | b = ((*colour & 0x7c00) >> 10) - ((m_snes_cgram[FIXED_COLOUR] & 0x7c00) >> 10); |
| 1448 | r = (*colour & 0x1f) - (m_cgram[FIXED_COLOUR] & 0x1f); |
| 1449 | g = ((*colour & 0x3e0) >> 5) - ((m_cgram[FIXED_COLOUR] & 0x3e0) >> 5); |
| 1450 | b = ((*colour & 0x7c00) >> 10) - ((m_cgram[FIXED_COLOUR] & 0x7c00) >> 10); |
| 1452 | 1451 | if (r > 0x1f) r = 0; |
| 1453 | 1452 | if (g > 0x1f) g = 0; |
| 1454 | 1453 | if (b > 0x1f) b = 0; |
| 1455 | 1454 | } |
| 1456 | 1455 | /* halve if necessary */ |
| 1457 | | if (BIT(snes_ppu.color_modes, 6)) |
| 1456 | if (BIT(m_color_modes, 6)) |
| 1458 | 1457 | { |
| 1459 | 1458 | r >>= 1; |
| 1460 | 1459 | g >>= 1; |
| r21558 | r21559 | |
| 1493 | 1492 | * the optimized averaging algorithm. |
| 1494 | 1493 | *********************************************/ |
| 1495 | 1494 | |
| 1496 | | void snes_state::snes_refresh_scanline( running_machine &machine, bitmap_rgb32 &bitmap, UINT16 curline ) |
| 1495 | void snes_ppu_class::snes_refresh_scanline( running_machine &machine, bitmap_rgb32 &bitmap, UINT16 curline ) |
| 1497 | 1496 | { |
| 1498 | 1497 | UINT16 ii; |
| 1499 | 1498 | int x; |
| r21558 | r21559 | |
| 1505 | 1504 | |
| 1506 | 1505 | g_profiler.start(PROFILER_VIDEO); |
| 1507 | 1506 | |
| 1508 | | if (snes_ppu.screen_disabled) /* screen is forced blank */ |
| 1507 | if (m_screen_disabled) /* screen is forced blank */ |
| 1509 | 1508 | for (x = 0; x < SNES_SCR_WIDTH * 2; x++) |
| 1510 | 1509 | bitmap.pix32(curline, x) = RGB_BLACK; |
| 1511 | 1510 | else |
| 1512 | 1511 | { |
| 1513 | 1512 | /* Update clip window masks if necessary */ |
| 1514 | | if (snes_ppu.update_windows) |
| 1513 | if (m_update_windows) |
| 1515 | 1514 | snes_update_windowmasks(); |
| 1516 | 1515 | /* Update the offsets if necessary */ |
| 1517 | | if (snes_ppu.update_offsets) |
| 1516 | if (m_update_offsets) |
| 1518 | 1517 | snes_update_offsets(); |
| 1519 | 1518 | |
| 1520 | 1519 | /* Clear priority */ |
| r21558 | r21559 | |
| 1532 | 1531 | /* Draw back colour */ |
| 1533 | 1532 | for (ii = 0; ii < SNES_SCR_WIDTH; ii++) |
| 1534 | 1533 | { |
| 1535 | | if (snes_ppu.mode == 5 || snes_ppu.mode == 6 || snes_ppu.pseudo_hires) |
| 1536 | | scanlines[SNES_SUBSCREEN].buffer[ii] = m_snes_cgram[0]; |
| 1534 | if (m_mode == 5 || m_mode == 6 || m_pseudo_hires) |
| 1535 | scanlines[SNES_SUBSCREEN].buffer[ii] = m_cgram[0]; |
| 1537 | 1536 | else |
| 1538 | | scanlines[SNES_SUBSCREEN].buffer[ii] = m_snes_cgram[FIXED_COLOUR]; |
| 1537 | scanlines[SNES_SUBSCREEN].buffer[ii] = m_cgram[FIXED_COLOUR]; |
| 1539 | 1538 | |
| 1540 | | scanlines[SNES_MAINSCREEN].buffer[ii] = m_snes_cgram[0]; |
| 1539 | scanlines[SNES_MAINSCREEN].buffer[ii] = m_cgram[0]; |
| 1541 | 1540 | } |
| 1542 | 1541 | |
| 1543 | 1542 | /* Prepare OAM for this scanline */ |
| r21558 | r21559 | |
| 1549 | 1548 | snes_update_obsel(); |
| 1550 | 1549 | |
| 1551 | 1550 | #if SNES_LAYER_DEBUG |
| 1552 | | if (snes_dbg_video(machine, curline)) |
| 1551 | if (snes_dbg_video(machine, curline, snes_ram)) |
| 1553 | 1552 | { |
| 1554 | 1553 | g_profiler.stop(); |
| 1555 | 1554 | return; |
| r21558 | r21559 | |
| 1570 | 1569 | |
| 1571 | 1570 | /* Draw the scanline to screen */ |
| 1572 | 1571 | |
| 1573 | | fade = snes_ppu.screen_brightness; |
| 1572 | fade = m_screen_brightness; |
| 1574 | 1573 | |
| 1575 | 1574 | for (x = 0; x < SNES_SCR_WIDTH; x++) |
| 1576 | 1575 | { |
| 1577 | 1576 | int r, g, b, hires; |
| 1578 | 1577 | UINT16 tmp_col[2]; |
| 1579 | | hires = (snes_ppu.mode != 5 && snes_ppu.mode != 6 && !snes_ppu.pseudo_hires) ? 0 : 1; |
| 1578 | hires = (m_mode != 5 && m_mode != 6 && !m_pseudo_hires) ? 0 : 1; |
| 1580 | 1579 | |
| 1581 | 1580 | /* in hires, the first pixel (of 512) is subscreen pixel, then the first mainscreen pixel follows, and so on... */ |
| 1582 | 1581 | if (!hires) |
| r21558 | r21559 | |
| 1584 | 1583 | c = scanline1->buffer[x]; |
| 1585 | 1584 | |
| 1586 | 1585 | /* perform color math if the layer wants it (except if it's an object > 192) */ |
| 1587 | | if (!scanline1->blend_exception[x] && snes_ppu.layer[scanline1->layer[x]].color_math) |
| 1588 | | snes_draw_blend(x, &c, snes_ppu.prevent_color_math, snes_ppu.clip_to_black, 0); |
| 1586 | if (!scanline1->blend_exception[x] && m_layer[scanline1->layer[x]].color_math) |
| 1587 | snes_draw_blend(x, &c, m_prevent_color_math, m_clip_to_black, 0); |
| 1589 | 1588 | |
| 1590 | 1589 | r = ((c & 0x1f) * fade) >> 4; |
| 1591 | 1590 | g = (((c & 0x3e0) >> 5) * fade) >> 4; |
| r21558 | r21559 | |
| 1600 | 1599 | c = scanline1->buffer[x]; |
| 1601 | 1600 | |
| 1602 | 1601 | /* perform color math if the layer wants it (except if it's an object > 192) */ |
| 1603 | | if (!scanline1->blend_exception[x] && snes_ppu.layer[scanline1->layer[x]].color_math) |
| 1604 | | snes_draw_blend(x, &c, snes_ppu.prevent_color_math, snes_ppu.clip_to_black, 0); |
| 1602 | if (!scanline1->blend_exception[x] && m_layer[scanline1->layer[x]].color_math) |
| 1603 | snes_draw_blend(x, &c, m_prevent_color_math, m_clip_to_black, 0); |
| 1605 | 1604 | |
| 1606 | 1605 | tmp_col[1] = c; |
| 1607 | 1606 | |
| r21558 | r21559 | |
| 1613 | 1612 | (which has no previous mainscreen pixel) is undocumented. Until more info are discovered, we (arbitrarily) |
| 1614 | 1613 | apply to it the same color math as the *next* mainscreen pixel (i.e. mainscreen pixel 0), which seems as good as |
| 1615 | 1614 | any other choice */ |
| 1616 | | if (x == 0 && !scanline1->blend_exception[0] && snes_ppu.layer[scanline1->layer[0]].color_math) |
| 1617 | | snes_draw_blend(0, &c, snes_ppu.prevent_color_math, snes_ppu.clip_to_black, 1); |
| 1618 | | else if (x > 0 && !scanline1->blend_exception[x - 1] && snes_ppu.layer[scanline1->layer[x - 1]].color_math) |
| 1619 | | snes_draw_blend(x, &c, snes_ppu.prevent_color_math, snes_ppu.clip_to_black, 1); |
| 1615 | if (x == 0 && !scanline1->blend_exception[0] && m_layer[scanline1->layer[0]].color_math) |
| 1616 | snes_draw_blend(0, &c, m_prevent_color_math, m_clip_to_black, 1); |
| 1617 | else if (x > 0 && !scanline1->blend_exception[x - 1] && m_layer[scanline1->layer[x - 1]].color_math) |
| 1618 | snes_draw_blend(x, &c, m_prevent_color_math, m_clip_to_black, 1); |
| 1620 | 1619 | |
| 1621 | 1620 | tmp_col[0] = c; |
| 1622 | 1621 | |
| r21558 | r21559 | |
| 1652 | 1651 | g_profiler.stop(); |
| 1653 | 1652 | } |
| 1654 | 1653 | |
| 1655 | | VIDEO_START( snes ) |
| 1654 | void snes_ppu_class::ppu_start(running_machine &machine) |
| 1656 | 1655 | { |
| 1657 | | snes_state *state = machine.driver_data<snes_state>(); |
| 1658 | | int i,j; |
| 1659 | | |
| 1660 | | #if SNES_LAYER_DEBUG |
| 1661 | | memset(&debug_options, 0, sizeof(debug_options)); |
| 1662 | | #endif |
| 1663 | | |
| 1664 | | state->m_snes_vram = auto_alloc_array(machine, UINT8, SNES_VRAM_SIZE); |
| 1665 | | state->m_snes_cgram = auto_alloc_array(machine, UINT16, SNES_CGRAM_SIZE/2); |
| 1666 | | state->m_snes_oam = auto_alloc_array(machine, UINT16, SNES_OAM_SIZE/2); |
| 1667 | | |
| 1656 | m_vram = auto_alloc_array(machine, UINT8, SNES_VRAM_SIZE); |
| 1657 | m_cgram = auto_alloc_array(machine, UINT16, SNES_CGRAM_SIZE/2); |
| 1658 | m_oam_ram = auto_alloc_array(machine, UINT16, SNES_OAM_SIZE/2); |
| 1659 | |
| 1668 | 1660 | /* Inititialize registers/variables */ |
| 1669 | | snes_ppu.update_windows = 1; |
| 1670 | | snes_ppu.beam.latch_vert = 0; |
| 1671 | | snes_ppu.beam.latch_horz = 0; |
| 1672 | | snes_ppu.beam.current_vert = 0; |
| 1673 | | snes_ppu.beam.current_horz = 0; |
| 1674 | | snes_ppu.beam.last_visible_line = 225; /* TODO: PAL setting */ |
| 1675 | | snes_ppu.mode = 0; |
| 1676 | | snes_ppu.ppu1_version = 1; // 5C77 chip version number, read by STAT77, only '1' is known |
| 1677 | | snes_ppu.ppu2_version = 3; // 5C78 chip version number, read by STAT78, only '2' & '3' encountered so far. |
| 1678 | | |
| 1661 | m_update_windows = 1; |
| 1662 | m_beam.latch_vert = 0; |
| 1663 | m_beam.latch_horz = 0; |
| 1664 | m_beam.current_vert = 0; |
| 1665 | m_beam.current_horz = 0; |
| 1666 | m_beam.last_visible_line = 225; /* TODO: PAL setting */ |
| 1667 | m_mode = 0; |
| 1668 | m_ppu1_version = 1; // 5C77 chip version number, read by STAT77, only '1' is known |
| 1669 | m_ppu2_version = 3; // 5C78 chip version number, read by STAT78, only '2' & '3' encountered so far. |
| 1670 | |
| 1671 | |
| 1679 | 1672 | /* Inititialize mosaic table */ |
| 1680 | | for (j = 0; j < 16; j++) |
| 1673 | for (int j = 0; j < 16; j++) |
| 1681 | 1674 | { |
| 1682 | | for (i = 0; i < 4096; i++) |
| 1683 | | snes_ppu.mosaic_table[j][i] = (i / (j + 1)) * (j + 1); |
| 1675 | for (int i = 0; i < 4096; i++) |
| 1676 | m_mosaic_table[j][i] = (i / (j + 1)) * (j + 1); |
| 1684 | 1677 | } |
| 1685 | | |
| 1678 | |
| 1686 | 1679 | /* Init VRAM */ |
| 1687 | | memset(state->m_snes_vram, 0, SNES_VRAM_SIZE); |
| 1688 | | |
| 1680 | memset(m_vram, 0, SNES_VRAM_SIZE); |
| 1681 | |
| 1689 | 1682 | /* Init Palette RAM */ |
| 1690 | | memset((UINT8 *)state->m_snes_cgram, 0, SNES_CGRAM_SIZE); |
| 1691 | | |
| 1683 | memset((UINT8 *)m_cgram, 0, SNES_CGRAM_SIZE); |
| 1684 | |
| 1692 | 1685 | /* Init oam RAM */ |
| 1693 | | memset((UINT8 *)state->m_snes_oam, 0xff, SNES_OAM_SIZE); |
| 1694 | | |
| 1695 | | for (i = 0; i < 6; i++) |
| 1686 | memset((UINT8 *)m_oam_ram, 0xff, SNES_OAM_SIZE); |
| 1687 | |
| 1688 | for (int i = 0; i < 6; i++) |
| 1696 | 1689 | { |
| 1697 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].window1_enabled); |
| 1698 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].window1_invert); |
| 1699 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].window2_enabled); |
| 1700 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].window2_invert); |
| 1701 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].wlog_mask); |
| 1702 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].color_math); |
| 1703 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].charmap); |
| 1704 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].tilemap); |
| 1705 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].tilemap_size); |
| 1706 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].tile_size); |
| 1707 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].mosaic_enabled); |
| 1708 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].main_window_enabled); |
| 1709 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].sub_window_enabled); |
| 1710 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].main_bg_enabled); |
| 1711 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].sub_bg_enabled); |
| 1712 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].hoffs); |
| 1713 | | state_save_register_item(machine, "snes_ppu", NULL, i, snes_ppu.layer[i].voffs); |
| 1714 | | |
| 1715 | | state_save_register_item_array(machine, "snes_ppu", NULL, i, snes_ppu.clipmasks[i]); |
| 1690 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].window1_enabled); |
| 1691 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].window1_invert); |
| 1692 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].window2_enabled); |
| 1693 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].window2_invert); |
| 1694 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].wlog_mask); |
| 1695 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].color_math); |
| 1696 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].charmap); |
| 1697 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].tilemap); |
| 1698 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].tilemap_size); |
| 1699 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].tile_size); |
| 1700 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].mosaic_enabled); |
| 1701 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].main_window_enabled); |
| 1702 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].sub_window_enabled); |
| 1703 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].main_bg_enabled); |
| 1704 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].sub_bg_enabled); |
| 1705 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].hoffs); |
| 1706 | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].voffs); |
| 1707 | |
| 1708 | state_save_register_item_array(machine, "snes_ppu", NULL, i, m_clipmasks[i]); |
| 1716 | 1709 | } |
| 1710 | |
| 1711 | state_save_register_global(machine, m_oam.address_low); |
| 1712 | state_save_register_global(machine, m_oam.address_high); |
| 1713 | state_save_register_global(machine, m_oam.saved_address_low); |
| 1714 | state_save_register_global(machine, m_oam.saved_address_high); |
| 1715 | state_save_register_global(machine, m_oam.address); |
| 1716 | state_save_register_global(machine, m_oam.priority_rotation); |
| 1717 | state_save_register_global(machine, m_oam.next_charmap); |
| 1718 | state_save_register_global(machine, m_oam.next_size); |
| 1719 | state_save_register_global(machine, m_oam.size); |
| 1720 | state_save_register_global(machine, m_oam.next_name_select); |
| 1721 | state_save_register_global(machine, m_oam.name_select); |
| 1722 | state_save_register_global(machine, m_oam.first_sprite); |
| 1723 | state_save_register_global(machine, m_oam.flip); |
| 1724 | state_save_register_global(machine, m_oam.write_latch); |
| 1725 | |
| 1726 | state_save_register_global(machine, m_beam.latch_horz); |
| 1727 | state_save_register_global(machine, m_beam.latch_vert); |
| 1728 | state_save_register_global(machine, m_beam.current_horz); |
| 1729 | state_save_register_global(machine, m_beam.current_vert); |
| 1730 | state_save_register_global(machine, m_beam.last_visible_line); |
| 1731 | state_save_register_global(machine, m_beam.interlace_count); |
| 1732 | |
| 1733 | state_save_register_global(machine, m_mode7.repeat); |
| 1734 | state_save_register_global(machine, m_mode7.hflip); |
| 1735 | state_save_register_global(machine, m_mode7.vflip); |
| 1736 | state_save_register_global(machine, m_mode7.matrix_a); |
| 1737 | state_save_register_global(machine, m_mode7.matrix_b); |
| 1738 | state_save_register_global(machine, m_mode7.matrix_c); |
| 1739 | state_save_register_global(machine, m_mode7.matrix_d); |
| 1740 | state_save_register_global(machine, m_mode7.origin_x); |
| 1741 | state_save_register_global(machine, m_mode7.origin_y); |
| 1742 | state_save_register_global(machine, m_mode7.hor_offset); |
| 1743 | state_save_register_global(machine, m_mode7.ver_offset); |
| 1744 | state_save_register_global(machine, m_mode7.extbg); |
| 1745 | |
| 1746 | state_save_register_global(machine, m_mosaic_size); |
| 1747 | state_save_register_global(machine, m_clip_to_black); |
| 1748 | state_save_register_global(machine, m_prevent_color_math); |
| 1749 | state_save_register_global(machine, m_sub_add_mode); |
| 1750 | state_save_register_global(machine, m_bg3_priority_bit); |
| 1751 | state_save_register_global(machine, m_direct_color); |
| 1752 | state_save_register_global(machine, m_ppu_last_scroll); |
| 1753 | state_save_register_global(machine, m_mode7_last_scroll); |
| 1754 | |
| 1755 | state_save_register_global(machine, m_ppu1_open_bus); |
| 1756 | state_save_register_global(machine, m_ppu2_open_bus); |
| 1757 | state_save_register_global(machine, m_ppu1_version); |
| 1758 | state_save_register_global(machine, m_ppu2_version); |
| 1759 | state_save_register_global(machine, m_window1_left); |
| 1760 | state_save_register_global(machine, m_window1_right); |
| 1761 | state_save_register_global(machine, m_window2_left); |
| 1762 | state_save_register_global(machine, m_window2_right); |
| 1763 | |
| 1764 | state_save_register_global(machine, m_update_windows); |
| 1765 | state_save_register_global(machine, m_update_offsets); |
| 1766 | state_save_register_global(machine, m_update_oam_list); |
| 1767 | state_save_register_global(machine, m_mode); |
| 1768 | state_save_register_global(machine, m_interlace); |
| 1769 | state_save_register_global(machine, m_obj_interlace); |
| 1770 | state_save_register_global(machine, m_screen_brightness); |
| 1771 | state_save_register_global(machine, m_screen_disabled); |
| 1772 | state_save_register_global(machine, m_pseudo_hires); |
| 1773 | state_save_register_global(machine, m_color_modes); |
| 1774 | state_save_register_global(machine, m_stat77_flags); |
| 1775 | |
| 1776 | state_save_register_global_pointer(machine, m_vram, SNES_VRAM_SIZE); |
| 1777 | state_save_register_global_pointer(machine, m_cgram, SNES_CGRAM_SIZE/2); |
| 1778 | state_save_register_global_pointer(machine, m_oam_ram, SNES_OAM_SIZE/2); |
| 1779 | } |
| 1717 | 1780 | |
| 1718 | | state_save_register_global(machine, snes_ppu.oam.address_low); |
| 1719 | | state_save_register_global(machine, snes_ppu.oam.address_high); |
| 1720 | | state_save_register_global(machine, snes_ppu.oam.saved_address_low); |
| 1721 | | state_save_register_global(machine, snes_ppu.oam.saved_address_high); |
| 1722 | | state_save_register_global(machine, snes_ppu.oam.address); |
| 1723 | | state_save_register_global(machine, snes_ppu.oam.priority_rotation); |
| 1724 | | state_save_register_global(machine, snes_ppu.oam.next_charmap); |
| 1725 | | state_save_register_global(machine, snes_ppu.oam.next_size); |
| 1726 | | state_save_register_global(machine, snes_ppu.oam.size); |
| 1727 | | state_save_register_global(machine, snes_ppu.oam.next_name_select); |
| 1728 | | state_save_register_global(machine, snes_ppu.oam.name_select); |
| 1729 | | state_save_register_global(machine, snes_ppu.oam.first_sprite); |
| 1730 | | state_save_register_global(machine, snes_ppu.oam.flip); |
| 1731 | | state_save_register_global(machine, snes_ppu.oam.write_latch); |
| 1781 | VIDEO_START( snes ) |
| 1782 | { |
| 1783 | snes_state *state = machine.driver_data<snes_state>(); |
| 1732 | 1784 | |
| 1733 | | state_save_register_global(machine, snes_ppu.beam.latch_horz); |
| 1734 | | state_save_register_global(machine, snes_ppu.beam.latch_vert); |
| 1735 | | state_save_register_global(machine, snes_ppu.beam.current_horz); |
| 1736 | | state_save_register_global(machine, snes_ppu.beam.current_vert); |
| 1737 | | state_save_register_global(machine, snes_ppu.beam.last_visible_line); |
| 1738 | | state_save_register_global(machine, snes_ppu.beam.interlace_count); |
| 1785 | #if SNES_LAYER_DEBUG |
| 1786 | memset(&debug_options, 0, sizeof(debug_options)); |
| 1787 | #endif |
| 1739 | 1788 | |
| 1740 | | state_save_register_global(machine, snes_ppu.mode7.repeat); |
| 1741 | | state_save_register_global(machine, snes_ppu.mode7.hflip); |
| 1742 | | state_save_register_global(machine, snes_ppu.mode7.vflip); |
| 1743 | | state_save_register_global(machine, snes_ppu.mode7.matrix_a); |
| 1744 | | state_save_register_global(machine, snes_ppu.mode7.matrix_b); |
| 1745 | | state_save_register_global(machine, snes_ppu.mode7.matrix_c); |
| 1746 | | state_save_register_global(machine, snes_ppu.mode7.matrix_d); |
| 1747 | | state_save_register_global(machine, snes_ppu.mode7.origin_x); |
| 1748 | | state_save_register_global(machine, snes_ppu.mode7.origin_y); |
| 1749 | | state_save_register_global(machine, snes_ppu.mode7.hor_offset); |
| 1750 | | state_save_register_global(machine, snes_ppu.mode7.ver_offset); |
| 1751 | | state_save_register_global(machine, snes_ppu.mode7.extbg); |
| 1752 | | |
| 1753 | | state_save_register_global(machine, snes_ppu.mosaic_size); |
| 1754 | | state_save_register_global(machine, snes_ppu.clip_to_black); |
| 1755 | | state_save_register_global(machine, snes_ppu.prevent_color_math); |
| 1756 | | state_save_register_global(machine, snes_ppu.sub_add_mode); |
| 1757 | | state_save_register_global(machine, snes_ppu.bg3_priority_bit); |
| 1758 | | state_save_register_global(machine, snes_ppu.direct_color); |
| 1759 | | state_save_register_global(machine, snes_ppu.ppu_last_scroll); |
| 1760 | | state_save_register_global(machine, snes_ppu.mode7_last_scroll); |
| 1761 | | |
| 1762 | | state_save_register_global(machine, snes_ppu.ppu1_open_bus); |
| 1763 | | state_save_register_global(machine, snes_ppu.ppu2_open_bus); |
| 1764 | | state_save_register_global(machine, snes_ppu.ppu1_version); |
| 1765 | | state_save_register_global(machine, snes_ppu.ppu2_version); |
| 1766 | | state_save_register_global(machine, snes_ppu.window1_left); |
| 1767 | | state_save_register_global(machine, snes_ppu.window1_right); |
| 1768 | | state_save_register_global(machine, snes_ppu.window2_left); |
| 1769 | | state_save_register_global(machine, snes_ppu.window2_right); |
| 1770 | | |
| 1771 | | state_save_register_global(machine, snes_ppu.update_windows); |
| 1772 | | state_save_register_global(machine, snes_ppu.update_offsets); |
| 1773 | | state_save_register_global(machine, snes_ppu.update_oam_list); |
| 1774 | | state_save_register_global(machine, snes_ppu.mode); |
| 1775 | | state_save_register_global(machine, snes_ppu.interlace); |
| 1776 | | state_save_register_global(machine, snes_ppu.obj_interlace); |
| 1777 | | state_save_register_global(machine, snes_ppu.screen_brightness); |
| 1778 | | state_save_register_global(machine, snes_ppu.screen_disabled); |
| 1779 | | state_save_register_global(machine, snes_ppu.pseudo_hires); |
| 1780 | | state_save_register_global(machine, snes_ppu.color_modes); |
| 1781 | | state_save_register_global(machine, snes_ppu.stat77_flags); |
| 1782 | | |
| 1783 | | state_save_register_global_pointer(machine, state->m_snes_vram, SNES_VRAM_SIZE); |
| 1784 | | state_save_register_global_pointer(machine, state->m_snes_cgram, SNES_CGRAM_SIZE/2); |
| 1785 | | state_save_register_global_pointer(machine, state->m_snes_oam, SNES_OAM_SIZE/2); |
| 1789 | state->m_ppu.ppu_start(machine); |
| 1786 | 1790 | } |
| 1787 | 1791 | |
| 1788 | 1792 | UINT32 snes_state::snes_screen_update( screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) |
| 1789 | 1793 | { |
| 1794 | snes_state *state = machine().driver_data<snes_state>(); |
| 1790 | 1795 | int y; |
| 1791 | 1796 | |
| 1792 | 1797 | /*NTSC SNES draw range is 1-225. */ |
| 1793 | 1798 | for (y = cliprect.min_y; y <= cliprect.max_y; y++) |
| 1794 | 1799 | { |
| 1795 | | snes_refresh_scanline(machine(), bitmap, y + 1); |
| 1800 | state->m_ppu.snes_refresh_scanline(machine(), bitmap, y + 1); |
| 1796 | 1801 | } |
| 1797 | 1802 | return 0; |
| 1798 | 1803 | } |
| r21558 | r21559 | |
| 1806 | 1811 | static const UINT16 vram_fgr_shiftab[4] = { 0, 5, 6, 7 }; |
| 1807 | 1812 | |
| 1808 | 1813 | // utility function - latches the H/V counters. Used by IRQ, writes to WRIO, etc. |
| 1809 | | void snes_latch_counters( running_machine &machine ) |
| 1814 | void snes_ppu_class::snes_latch_counters( running_machine &machine, UINT8 *ram_ptr ) |
| 1810 | 1815 | { |
| 1811 | 1816 | snes_state *state = machine.driver_data<snes_state>(); |
| 1812 | 1817 | |
| 1813 | | snes_ppu.beam.current_horz = machine.primary_screen->hpos() / state->m_htmult; |
| 1814 | | snes_ppu.beam.latch_vert = machine.primary_screen->vpos(); |
| 1815 | | snes_ppu.beam.latch_horz = snes_ppu.beam.current_horz; |
| 1816 | | snes_ram[STAT78] |= 0x40; // indicate we latched |
| 1818 | m_beam.current_horz = machine.primary_screen->hpos() / state->m_htmult; |
| 1819 | m_beam.latch_vert = machine.primary_screen->vpos(); |
| 1820 | m_beam.latch_horz = m_beam.current_horz; |
| 1821 | ram_ptr[STAT78] |= 0x40; // indicate we latched |
| 1817 | 1822 | // state->m_read_ophct = state->m_read_opvct = 0; // clear read flags - 2009-08: I think we must clear these when STAT78 is read... |
| 1818 | 1823 | |
| 1819 | | // printf("latched @ H %d V %d\n", snes_ppu.beam.latch_horz, snes_ppu.beam.latch_vert); |
| 1824 | // printf("latched @ H %d V %d\n", m_beam.latch_horz, m_beam.latch_vert); |
| 1820 | 1825 | } |
| 1821 | 1826 | |
| 1822 | | static void snes_dynamic_res_change( running_machine &machine ) |
| 1827 | void snes_ppu_class::snes_dynamic_res_change( running_machine &machine, UINT8 *ram_ptr ) |
| 1823 | 1828 | { |
| 1824 | 1829 | snes_state *state = machine.driver_data<snes_state>(); |
| 1825 | 1830 | rectangle visarea = machine.primary_screen->visible_area(); |
| 1826 | 1831 | attoseconds_t refresh; |
| 1827 | 1832 | |
| 1828 | 1833 | visarea.min_x = visarea.min_y = 0; |
| 1829 | | visarea.max_y = snes_ppu.beam.last_visible_line * snes_ppu.interlace - 1; |
| 1834 | visarea.max_y = m_beam.last_visible_line * m_interlace - 1; |
| 1830 | 1835 | visarea.max_x = (SNES_SCR_WIDTH * 2) - 1; |
| 1831 | 1836 | |
| 1832 | | // fixme: should compensate for SNES_DBG_video |
| 1833 | | if (snes_ppu.mode == 5 || snes_ppu.mode == 6 || snes_ppu.pseudo_hires) |
| 1837 | // fixme: should compensate for SNES_DBG_VIDEO |
| 1838 | if (m_mode == 5 || m_mode == 6 || m_pseudo_hires) |
| 1834 | 1839 | state->m_htmult = 2; |
| 1835 | 1840 | else |
| 1836 | 1841 | state->m_htmult = 1; |
| 1837 | 1842 | |
| 1838 | 1843 | /* FIXME: does the timing changes when the gfx mode is equal to 5 or 6? */ |
| 1839 | | if ((snes_ram[STAT78] & 0x10) == SNES_NTSC) |
| 1844 | if ((ram_ptr[STAT78] & 0x10) == SNES_NTSC) |
| 1840 | 1845 | refresh = HZ_TO_ATTOSECONDS(DOTCLK_NTSC) * SNES_HTOTAL * SNES_VTOTAL_NTSC; |
| 1841 | 1846 | else |
| 1842 | 1847 | refresh = HZ_TO_ATTOSECONDS(DOTCLK_PAL) * SNES_HTOTAL * SNES_VTOTAL_PAL; |
| 1843 | 1848 | |
| 1844 | | if ((snes_ram[STAT78] & 0x10) == SNES_NTSC) |
| 1845 | | machine.primary_screen->configure(SNES_HTOTAL * 2, SNES_VTOTAL_NTSC * snes_ppu.interlace, visarea, refresh); |
| 1849 | if ((ram_ptr[STAT78] & 0x10) == SNES_NTSC) |
| 1850 | machine.primary_screen->configure(SNES_HTOTAL * 2, SNES_VTOTAL_NTSC * m_interlace, visarea, refresh); |
| 1846 | 1851 | else |
| 1847 | | machine.primary_screen->configure(SNES_HTOTAL * 2, SNES_VTOTAL_PAL * snes_ppu.interlace, visarea, refresh); |
| 1852 | machine.primary_screen->configure(SNES_HTOTAL * 2, SNES_VTOTAL_PAL * m_interlace, visarea, refresh); |
| 1848 | 1853 | } |
| 1849 | 1854 | |
| 1850 | 1855 | /************************************************* |
| r21558 | r21559 | |
| 1863 | 1868 | when interlace is active. |
| 1864 | 1869 | *************************************************/ |
| 1865 | 1870 | |
| 1866 | | inline UINT32 snes_get_vram_address( running_machine &machine ) |
| 1871 | inline UINT32 snes_ppu_class::snes_get_vram_address( running_machine &machine ) |
| 1867 | 1872 | { |
| 1868 | 1873 | snes_state *state = machine.driver_data<snes_state>(); |
| 1869 | 1874 | UINT32 addr = state->m_vmadd; |
| r21558 | r21559 | |
| 1878 | 1883 | return addr << 1; |
| 1879 | 1884 | } |
| 1880 | 1885 | |
| 1881 | | READ8_MEMBER( snes_state::snes_vram_read ) |
| 1886 | READ8_MEMBER( snes_ppu_class::snes_vram_read ) |
| 1882 | 1887 | { |
| 1883 | 1888 | UINT8 res = 0; |
| 1884 | 1889 | offset &= 0xffff; // only 64KB are present on SNES |
| 1885 | 1890 | |
| 1886 | | if (snes_ppu.screen_disabled) |
| 1887 | | res = m_snes_vram[offset]; |
| 1891 | if (m_screen_disabled) |
| 1892 | res = m_vram[offset]; |
| 1888 | 1893 | else |
| 1889 | 1894 | { |
| 1890 | | UINT16 v = machine().primary_screen->vpos(); |
| 1891 | | UINT16 h = machine().primary_screen->hpos(); |
| 1895 | UINT16 v = space.machine().primary_screen->vpos(); |
| 1896 | UINT16 h = space.machine().primary_screen->hpos(); |
| 1892 | 1897 | UINT16 ls = (((snes_ram[STAT78] & 0x10) == SNES_NTSC ? 525 : 625) >> 1) - 1; |
| 1893 | 1898 | |
| 1894 | | if (snes_ppu.interlace == 2) |
| 1899 | if (m_interlace == 2) |
| 1895 | 1900 | ls++; |
| 1896 | 1901 | |
| 1897 | 1902 | if (v == ls && h == 1362) |
| 1898 | 1903 | res = 0; |
| 1899 | | else if (v < snes_ppu.beam.last_visible_line - 1) |
| 1904 | else if (v < m_beam.last_visible_line - 1) |
| 1900 | 1905 | res = 0; |
| 1901 | | else if (v == snes_ppu.beam.last_visible_line - 1) |
| 1906 | else if (v == m_beam.last_visible_line - 1) |
| 1902 | 1907 | { |
| 1903 | 1908 | if (h == 1362) |
| 1904 | | res = m_snes_vram[offset]; |
| 1909 | res = m_vram[offset]; |
| 1905 | 1910 | else |
| 1906 | 1911 | { |
| 1907 | 1912 | //printf("%d %d VRAM read, CHECK!\n",h,v); |
| r21558 | r21559 | |
| 1909 | 1914 | } |
| 1910 | 1915 | } |
| 1911 | 1916 | else |
| 1912 | | res = m_snes_vram[offset]; |
| 1917 | res = m_vram[offset]; |
| 1913 | 1918 | } |
| 1914 | 1919 | return res; |
| 1915 | 1920 | } |
| 1916 | 1921 | |
| 1917 | | WRITE8_MEMBER( snes_state::snes_vram_write ) |
| 1922 | WRITE8_MEMBER( snes_ppu_class::snes_vram_write ) |
| 1918 | 1923 | { |
| 1919 | 1924 | offset &= 0xffff; // only 64KB are present on SNES, Robocop 3 relies on this |
| 1920 | 1925 | |
| 1921 | | if (snes_ppu.screen_disabled) |
| 1922 | | m_snes_vram[offset] = data; |
| 1926 | if (m_screen_disabled) |
| 1927 | m_vram[offset] = data; |
| 1923 | 1928 | else |
| 1924 | 1929 | { |
| 1925 | | UINT16 v = machine().primary_screen->vpos(); |
| 1926 | | UINT16 h = machine().primary_screen->hpos(); |
| 1930 | UINT16 v = space.machine().primary_screen->vpos(); |
| 1931 | UINT16 h = space.machine().primary_screen->hpos(); |
| 1927 | 1932 | if (v == 0) |
| 1928 | 1933 | { |
| 1929 | 1934 | if (h <= 4) |
| 1930 | | m_snes_vram[offset] = data; |
| 1935 | m_vram[offset] = data; |
| 1931 | 1936 | else if (h == 6) |
| 1932 | | m_snes_vram[offset] = snes_open_bus_r(space, 0); |
| 1937 | m_vram[offset] = snes_open_bus_r(space, 0); |
| 1933 | 1938 | else |
| 1934 | 1939 | { |
| 1935 | 1940 | //printf("%d %d VRAM write, CHECK!\n",h,v); |
| 1936 | 1941 | //no write |
| 1937 | 1942 | } |
| 1938 | 1943 | } |
| 1939 | | else if (v < snes_ppu.beam.last_visible_line) |
| 1944 | else if (v < m_beam.last_visible_line) |
| 1940 | 1945 | { |
| 1941 | 1946 | //printf("%d %d VRAM write, CHECK!\n",h,v); |
| 1942 | 1947 | //no write |
| 1943 | 1948 | } |
| 1944 | | else if (v == snes_ppu.beam.last_visible_line) |
| 1949 | else if (v == m_beam.last_visible_line) |
| 1945 | 1950 | { |
| 1946 | 1951 | if (h <= 4) |
| 1947 | 1952 | { |
| r21558 | r21559 | |
| 1949 | 1954 | //no write |
| 1950 | 1955 | } |
| 1951 | 1956 | else |
| 1952 | | m_snes_vram[offset] = data; |
| 1957 | m_vram[offset] = data; |
| 1953 | 1958 | } |
| 1954 | 1959 | else |
| 1955 | | m_snes_vram[offset] = data; |
| 1960 | m_vram[offset] = data; |
| 1956 | 1961 | } |
| 1957 | 1962 | } |
| 1958 | 1963 | |
| r21558 | r21559 | |
| 1979 | 1984 | to choose the high/low byte of the snes_oam word. |
| 1980 | 1985 | *************************************************/ |
| 1981 | 1986 | |
| 1982 | | READ8_MEMBER( snes_state::snes_oam_read ) |
| 1987 | READ8_MEMBER( snes_ppu_class::snes_oam_read ) |
| 1983 | 1988 | { |
| 1984 | 1989 | offset &= 0x1ff; |
| 1985 | 1990 | |
| 1986 | 1991 | if (offset & 0x100) |
| 1987 | 1992 | offset &= 0x10f; |
| 1988 | 1993 | |
| 1989 | | if (!snes_ppu.screen_disabled) |
| 1994 | if (!m_screen_disabled) |
| 1990 | 1995 | { |
| 1991 | | UINT16 v = machine().primary_screen->vpos(); |
| 1996 | UINT16 v = space.machine().primary_screen->vpos(); |
| 1992 | 1997 | |
| 1993 | | if (v < snes_ppu.beam.last_visible_line) |
| 1998 | if (v < m_beam.last_visible_line) |
| 1994 | 1999 | offset = 0x010c; |
| 1995 | 2000 | } |
| 1996 | 2001 | |
| 1997 | | return (m_snes_oam[offset] >> (snes_ram[OAMDATA] << 3)) & 0xff; |
| 2002 | return (m_oam_ram[offset] >> (snes_ram[OAMDATA] << 3)) & 0xff; |
| 1998 | 2003 | } |
| 1999 | 2004 | |
| 2000 | | WRITE8_MEMBER( snes_state::snes_oam_write ) |
| 2005 | WRITE8_MEMBER( snes_ppu_class::snes_oam_write ) |
| 2001 | 2006 | { |
| 2002 | 2007 | offset &= 0x1ff; |
| 2003 | 2008 | |
| 2004 | 2009 | if (offset & 0x100) |
| 2005 | 2010 | offset &= 0x10f; |
| 2006 | 2011 | |
| 2007 | | if (!snes_ppu.screen_disabled) |
| 2012 | if (!m_screen_disabled) |
| 2008 | 2013 | { |
| 2009 | | UINT16 v = machine().primary_screen->vpos(); |
| 2014 | UINT16 v = space.machine().primary_screen->vpos(); |
| 2010 | 2015 | |
| 2011 | | if (v < snes_ppu.beam.last_visible_line) |
| 2016 | if (v < m_beam.last_visible_line) |
| 2012 | 2017 | offset = 0x010c; |
| 2013 | 2018 | } |
| 2014 | 2019 | |
| 2015 | 2020 | if (!(snes_ram[OAMDATA])) |
| 2016 | | m_snes_oam[offset] = (m_snes_oam[offset] & 0xff00) | (data << 0); |
| 2021 | m_oam_ram[offset] = (m_oam_ram[offset] & 0xff00) | (data << 0); |
| 2017 | 2022 | else |
| 2018 | | m_snes_oam[offset] = (m_snes_oam[offset] & 0x00ff) | (data << 8); |
| 2023 | m_oam_ram[offset] = (m_oam_ram[offset] & 0x00ff) | (data << 8); |
| 2019 | 2024 | } |
| 2020 | 2025 | |
| 2021 | 2026 | /************************************************* |
| r21558 | r21559 | |
| 2039 | 2044 | solution adopted by BSNES without enabling it. |
| 2040 | 2045 | *************************************************/ |
| 2041 | 2046 | |
| 2042 | | READ8_MEMBER( snes_state::snes_cgram_read ) |
| 2047 | READ8_MEMBER( snes_ppu_class::snes_cgram_read ) |
| 2043 | 2048 | { |
| 2044 | 2049 | UINT8 res = 0; |
| 2045 | 2050 | offset &= 0x1ff; |
| 2046 | 2051 | |
| 2047 | 2052 | #if 0 |
| 2048 | | if (!snes_ppu.screen_disabled) |
| 2053 | if (!m_screen_disabled) |
| 2049 | 2054 | { |
| 2050 | 2055 | UINT16 v = space.machine().primary_screen->vpos(); |
| 2051 | 2056 | UINT16 h = space.machine().primary_screen->hpos(); |
| 2052 | 2057 | |
| 2053 | | if (v < snes_ppu.beam.last_visible_line && h >= 128 && h < 1096) |
| 2058 | if (v < m_beam.last_visible_line && h >= 128 && h < 1096) |
| 2054 | 2059 | offset = 0x1ff; |
| 2055 | 2060 | } |
| 2056 | 2061 | #endif |
| 2057 | 2062 | |
| 2058 | | res = ((UINT8 *)m_snes_cgram)[offset]; |
| 2063 | res = ((UINT8 *)m_cgram)[offset]; |
| 2059 | 2064 | |
| 2060 | 2065 | // CGRAM palette data format is 15-bits (0,bbbbb,ggggg,rrrrr). |
| 2061 | 2066 | // Highest bit is simply ignored. |
| r21558 | r21559 | |
| 2065 | 2070 | return res; |
| 2066 | 2071 | } |
| 2067 | 2072 | |
| 2068 | | WRITE8_MEMBER( snes_state::snes_cgram_write ) |
| 2073 | WRITE8_MEMBER( snes_ppu_class::snes_cgram_write ) |
| 2069 | 2074 | { |
| 2070 | 2075 | offset &= 0x1ff; |
| 2071 | 2076 | |
| r21558 | r21559 | |
| 2073 | 2078 | // FIXME: this currently breaks some games (e.g. Tokimeki Memorial), |
| 2074 | 2079 | // even if it's expected to be more accurate than allowing for |
| 2075 | 2080 | // writes to the cgram address |
| 2076 | | if (!snes_ppu.screen_disabled) |
| 2081 | if (!m_screen_disabled) |
| 2077 | 2082 | { |
| 2078 | 2083 | UINT16 v = space.machine().primary_screen->vpos(); |
| 2079 | 2084 | UINT16 h = space.machine().primary_screen->hpos(); |
| 2080 | 2085 | |
| 2081 | | if (v < snes_ppu.beam.last_visible_line && h >= 128 && h < 1096) |
| 2086 | if (v < m_beam.last_visible_line && h >= 128 && h < 1096) |
| 2082 | 2087 | offset = 0x1ff; |
| 2083 | 2088 | } |
| 2084 | 2089 | #endif |
| r21558 | r21559 | |
| 2088 | 2093 | if (offset & 0x01) |
| 2089 | 2094 | data &= 0x7f; |
| 2090 | 2095 | |
| 2091 | | ((UINT8 *)m_snes_cgram)[offset] = data; |
| 2096 | ((UINT8 *)m_cgram)[offset] = data; |
| 2092 | 2097 | } |
| 2093 | 2098 | |
| 2094 | | READ8_HANDLER( snes_ppu_read ) |
| 2099 | UINT8 snes_ppu_class::snes_ppu_read(address_space &space, UINT32 offset, UINT8 *ram_ptr) |
| 2095 | 2100 | { |
| 2096 | 2101 | snes_state *state = space.machine().driver_data<snes_state>(); |
| 2097 | 2102 | UINT8 value; |
| r21558 | r21559 | |
| 2116 | 2121 | case WH2: |
| 2117 | 2122 | case WH3: |
| 2118 | 2123 | case WBGLOG: |
| 2119 | | return snes_ppu.ppu1_open_bus; |
| 2124 | return m_ppu1_open_bus; |
| 2120 | 2125 | |
| 2121 | 2126 | case MPYL: /* Multiplication result (low) */ |
| 2122 | 2127 | { |
| 2123 | 2128 | /* Perform 16bit * 8bit multiply */ |
| 2124 | | UINT32 c = (INT16)snes_ppu.mode7.matrix_a * (INT8)(snes_ppu.mode7.matrix_b >> 8); |
| 2125 | | snes_ppu.ppu1_open_bus = c & 0xff; |
| 2126 | | return snes_ppu.ppu1_open_bus; |
| 2129 | UINT32 c = (INT16)m_mode7.matrix_a * (INT8)(m_mode7.matrix_b >> 8); |
| 2130 | m_ppu1_open_bus = c & 0xff; |
| 2131 | return m_ppu1_open_bus; |
| 2127 | 2132 | } |
| 2128 | 2133 | case MPYM: /* Multiplication result (mid) */ |
| 2129 | 2134 | { |
| 2130 | 2135 | /* Perform 16bit * 8bit multiply */ |
| 2131 | | UINT32 c = (INT16)snes_ppu.mode7.matrix_a * (INT8)(snes_ppu.mode7.matrix_b >> 8); |
| 2132 | | snes_ppu.ppu1_open_bus = (c >> 8) & 0xff; |
| 2133 | | return snes_ppu.ppu1_open_bus; |
| 2136 | UINT32 c = (INT16)m_mode7.matrix_a * (INT8)(m_mode7.matrix_b >> 8); |
| 2137 | m_ppu1_open_bus = (c >> 8) & 0xff; |
| 2138 | return m_ppu1_open_bus; |
| 2134 | 2139 | } |
| 2135 | 2140 | case MPYH: /* Multiplication result (high) */ |
| 2136 | 2141 | { |
| 2137 | 2142 | /* Perform 16bit * 8bit multiply */ |
| 2138 | | UINT32 c = (INT16)snes_ppu.mode7.matrix_a * (INT8)(snes_ppu.mode7.matrix_b >> 8); |
| 2139 | | snes_ppu.ppu1_open_bus = (c >> 16) & 0xff; |
| 2140 | | return snes_ppu.ppu1_open_bus; |
| 2143 | UINT32 c = (INT16)m_mode7.matrix_a * (INT8)(m_mode7.matrix_b >> 8); |
| 2144 | m_ppu1_open_bus = (c >> 16) & 0xff; |
| 2145 | return m_ppu1_open_bus; |
| 2141 | 2146 | } |
| 2142 | 2147 | case SLHV: /* Software latch for H/V counter */ |
| 2143 | | snes_latch_counters(space.machine()); |
| 2148 | snes_latch_counters(space.machine(), ram_ptr); |
| 2144 | 2149 | return snes_open_bus_r(space, 0); /* Return value is meaningless */ |
| 2145 | 2150 | case ROAMDATA: /* Read data from OAM (DR) */ |
| 2146 | | snes_ppu.ppu1_open_bus = state->snes_oam_read(space, snes_ppu.oam.address); |
| 2147 | | snes_ram[OAMDATA] = (snes_ram[OAMDATA] + 1) % 2; |
| 2148 | | if (!snes_ram[OAMDATA]) |
| 2151 | m_ppu1_open_bus = snes_oam_read(space, m_oam.address); |
| 2152 | ram_ptr[OAMDATA] = (ram_ptr[OAMDATA] + 1) % 2; |
| 2153 | if (!ram_ptr[OAMDATA]) |
| 2149 | 2154 | { |
| 2150 | | snes_ppu.oam.address++; |
| 2151 | | snes_ppu.oam.address &= 0x1ff; |
| 2152 | | snes_ppu.oam.first_sprite = snes_ppu.oam.priority_rotation ? (snes_ppu.oam.address >> 1) & 127 : 0; |
| 2155 | m_oam.address++; |
| 2156 | m_oam.address &= 0x1ff; |
| 2157 | m_oam.first_sprite = m_oam.priority_rotation ? (m_oam.address >> 1) & 127 : 0; |
| 2153 | 2158 | } |
| 2154 | | return snes_ppu.ppu1_open_bus; |
| 2159 | return m_ppu1_open_bus; |
| 2155 | 2160 | case RVMDATAL: /* Read data from VRAM (low) */ |
| 2156 | 2161 | { |
| 2157 | 2162 | UINT32 addr = snes_get_vram_address(space.machine()); |
| 2158 | | snes_ppu.ppu1_open_bus = state->m_vram_read_buffer & 0xff; |
| 2163 | m_ppu1_open_bus = state->m_vram_read_buffer & 0xff; |
| 2159 | 2164 | |
| 2160 | 2165 | if (!state->m_vram_fgr_high) |
| 2161 | 2166 | { |
| 2162 | | state->m_vram_read_buffer = state->snes_vram_read(space, addr); |
| 2163 | | state->m_vram_read_buffer |= (state->snes_vram_read(space, addr + 1) << 8); |
| 2167 | state->m_vram_read_buffer = snes_vram_read(space, addr); |
| 2168 | state->m_vram_read_buffer |= (snes_vram_read(space, addr + 1) << 8); |
| 2164 | 2169 | |
| 2165 | 2170 | state->m_vmadd = (state->m_vmadd + state->m_vram_fgr_increment) & 0xffff; |
| 2166 | 2171 | } |
| 2167 | 2172 | |
| 2168 | | return snes_ppu.ppu1_open_bus; |
| 2173 | return m_ppu1_open_bus; |
| 2169 | 2174 | } |
| 2170 | 2175 | case RVMDATAH: /* Read data from VRAM (high) */ |
| 2171 | 2176 | { |
| 2172 | 2177 | UINT32 addr = snes_get_vram_address(space.machine()); |
| 2173 | | snes_ppu.ppu1_open_bus = (state->m_vram_read_buffer >> 8) & 0xff; |
| 2178 | m_ppu1_open_bus = (state->m_vram_read_buffer >> 8) & 0xff; |
| 2174 | 2179 | |
| 2175 | 2180 | if (state->m_vram_fgr_high) |
| 2176 | 2181 | { |
| 2177 | | state->m_vram_read_buffer = state->snes_vram_read(space, addr); |
| 2178 | | state->m_vram_read_buffer |= (state->snes_vram_read(space, addr + 1) << 8); |
| 2182 | state->m_vram_read_buffer = snes_vram_read(space, addr); |
| 2183 | state->m_vram_read_buffer |= (snes_vram_read(space, addr + 1) << 8); |
| 2179 | 2184 | |
| 2180 | 2185 | state->m_vmadd = (state->m_vmadd + state->m_vram_fgr_increment) & 0xffff; |
| 2181 | 2186 | } |
| 2182 | 2187 | |
| 2183 | | return snes_ppu.ppu1_open_bus; |
| 2188 | return m_ppu1_open_bus; |
| 2184 | 2189 | } |
| 2185 | 2190 | case RCGDATA: /* Read data from CGRAM */ |
| 2186 | 2191 | if (!(state->m_cgram_address & 0x01)) |
| 2187 | | snes_ppu.ppu2_open_bus = state->snes_cgram_read(space, state->m_cgram_address); |
| 2192 | m_ppu2_open_bus = snes_cgram_read(space, state->m_cgram_address); |
| 2188 | 2193 | else |
| 2189 | 2194 | { |
| 2190 | | snes_ppu.ppu2_open_bus &= 0x80; |
| 2191 | | snes_ppu.ppu2_open_bus |= state->snes_cgram_read(space, state->m_cgram_address) & 0x7f; |
| 2195 | m_ppu2_open_bus &= 0x80; |
| 2196 | m_ppu2_open_bus |= snes_cgram_read(space, state->m_cgram_address) & 0x7f; |
| 2192 | 2197 | } |
| 2193 | 2198 | |
| 2194 | 2199 | state->m_cgram_address = (state->m_cgram_address + 1) % (SNES_CGRAM_SIZE - 2); |
| 2195 | | return snes_ppu.ppu2_open_bus; |
| 2200 | return m_ppu2_open_bus; |
| 2196 | 2201 | case OPHCT: /* Horizontal counter data by ext/soft latch */ |
| 2197 | 2202 | if (state->m_read_ophct) |
| 2198 | 2203 | { |
| 2199 | | snes_ppu.ppu2_open_bus &= 0xfe; |
| 2200 | | snes_ppu.ppu2_open_bus |= (snes_ppu.beam.latch_horz >> 8) & 0x01; |
| 2204 | m_ppu2_open_bus &= 0xfe; |
| 2205 | m_ppu2_open_bus |= (m_beam.latch_horz >> 8) & 0x01; |
| 2201 | 2206 | } |
| 2202 | 2207 | else |
| 2203 | 2208 | { |
| 2204 | | snes_ppu.ppu2_open_bus = snes_ppu.beam.latch_horz & 0xff; |
| 2209 | m_ppu2_open_bus = m_beam.latch_horz & 0xff; |
| 2205 | 2210 | } |
| 2206 | 2211 | state->m_read_ophct ^= 1; |
| 2207 | | return snes_ppu.ppu2_open_bus; |
| 2212 | return m_ppu2_open_bus; |
| 2208 | 2213 | case OPVCT: /* Vertical counter data by ext/soft latch */ |
| 2209 | 2214 | if (state->m_read_opvct) |
| 2210 | 2215 | { |
| 2211 | | snes_ppu.ppu2_open_bus &= 0xfe; |
| 2212 | | snes_ppu.ppu2_open_bus |= (snes_ppu.beam.latch_vert >> 8) & 0x01; |
| 2216 | m_ppu2_open_bus &= 0xfe; |
| 2217 | m_ppu2_open_bus |= (m_beam.latch_vert >> 8) & 0x01; |
| 2213 | 2218 | } |
| 2214 | 2219 | else |
| 2215 | 2220 | { |
| 2216 | | snes_ppu.ppu2_open_bus = snes_ppu.beam.latch_vert & 0xff; |
| 2221 | m_ppu2_open_bus = m_beam.latch_vert & 0xff; |
| 2217 | 2222 | } |
| 2218 | 2223 | state->m_read_opvct ^= 1; |
| 2219 | | return snes_ppu.ppu2_open_bus; |
| 2224 | return m_ppu2_open_bus; |
| 2220 | 2225 | case STAT77: /* PPU status flag and version number */ |
| 2221 | | value = snes_ppu.stat77_flags & 0xc0; // 0x80 & 0x40 are Time Over / Range Over Sprite flags, set by the video code |
| 2226 | value = m_stat77_flags & 0xc0; // 0x80 & 0x40 are Time Over / Range Over Sprite flags, set by the video code |
| 2222 | 2227 | // 0x20 - Master/slave mode select. Little is known about this bit. We always seem to read back 0 here. |
| 2223 | | value |= (snes_ppu.ppu1_open_bus & 0x10); |
| 2224 | | value |= (snes_ppu.ppu1_version & 0x0f); |
| 2225 | | snes_ppu.stat77_flags = value; // not sure if this is needed... |
| 2226 | | snes_ppu.ppu1_open_bus = value; |
| 2227 | | return snes_ppu.ppu1_open_bus; |
| 2228 | value |= (m_ppu1_open_bus & 0x10); |
| 2229 | value |= (m_ppu1_version & 0x0f); |
| 2230 | m_stat77_flags = value; // not sure if this is needed... |
| 2231 | m_ppu1_open_bus = value; |
| 2232 | return m_ppu1_open_bus; |
| 2228 | 2233 | case STAT78: /* PPU status flag and version number */ |
| 2229 | 2234 | state->m_read_ophct = 0; |
| 2230 | 2235 | state->m_read_opvct = 0; |
| 2231 | | if(snes_ram[WRIO] & 0x80) |
| 2232 | | snes_ram[STAT78] &= ~0x40; //clear ext latch if bit 7 of WRIO is set |
| 2233 | | snes_ram[STAT78] = (snes_ram[STAT78] & ~0x2f) | (snes_ppu.ppu2_open_bus & 0x20) | (snes_ppu.ppu2_version & 0x0f); |
| 2234 | | snes_ppu.ppu2_open_bus = snes_ram[STAT78]; |
| 2235 | | return snes_ppu.ppu2_open_bus; |
| 2236 | if(ram_ptr[WRIO] & 0x80) |
| 2237 | ram_ptr[STAT78] &= ~0x40; //clear ext latch if bit 7 of WRIO is set |
| 2238 | ram_ptr[STAT78] = (ram_ptr[STAT78] & ~0x2f) | (m_ppu2_open_bus & 0x20) | (m_ppu2_version & 0x0f); |
| 2239 | m_ppu2_open_bus = ram_ptr[STAT78]; |
| 2240 | return m_ppu2_open_bus; |
| 2236 | 2241 | } |
| 2237 | 2242 | |
| 2238 | 2243 | /* note: remaining registers (Namely TM in Super Kick Boxing) returns MDR open bus, not PPU Open Bus! */ |
| r21558 | r21559 | |
| 2240 | 2245 | } |
| 2241 | 2246 | |
| 2242 | 2247 | |
| 2243 | | WRITE8_HANDLER( snes_ppu_write ) |
| 2248 | void snes_ppu_class::snes_ppu_write(address_space &space, UINT32 offset, UINT8 data, UINT8 *ram_ptr) |
| 2244 | 2249 | { |
| 2245 | 2250 | snes_state *state = space.machine().driver_data<snes_state>(); |
| 2246 | 2251 | |
| 2247 | 2252 | switch (offset) |
| 2248 | 2253 | { |
| 2249 | 2254 | case INIDISP: /* Initial settings for screen */ |
| 2250 | | if ((snes_ppu.screen_disabled & 0x80) && (!(data & 0x80))) //a 1->0 force blank transition causes a reset OAM address |
| 2255 | if ((m_screen_disabled & 0x80) && (!(data & 0x80))) //a 1->0 force blank transition causes a reset OAM address |
| 2251 | 2256 | { |
| 2252 | | space.write_byte(OAMADDL, snes_ppu.oam.saved_address_low); |
| 2253 | | space.write_byte(OAMADDH, snes_ppu.oam.saved_address_high); |
| 2254 | | snes_ppu.oam.first_sprite = snes_ppu.oam.priority_rotation ? (snes_ppu.oam.address >> 1) & 127 : 0; |
| 2257 | space.write_byte(OAMADDL, m_oam.saved_address_low); |
| 2258 | space.write_byte(OAMADDH, m_oam.saved_address_high); |
| 2259 | m_oam.first_sprite = m_oam.priority_rotation ? (m_oam.address >> 1) & 127 : 0; |
| 2255 | 2260 | } |
| 2256 | | snes_ppu.screen_disabled = data & 0x80; |
| 2257 | | snes_ppu.screen_brightness = (data & 0x0f) + 1; |
| 2261 | m_screen_disabled = data & 0x80; |
| 2262 | m_screen_brightness = (data & 0x0f) + 1; |
| 2258 | 2263 | break; |
| 2259 | 2264 | case OBSEL: /* Object size and data area designation */ |
| 2260 | | snes_ppu.oam.next_charmap = (data & 0x03) << 1; |
| 2261 | | snes_ppu.oam.next_name_select = (((data & 0x18) >> 3) * 0x1000) << 1; |
| 2262 | | snes_ppu.oam.next_size = (data & 0xe0) >> 5; |
| 2265 | m_oam.next_charmap = (data & 0x03) << 1; |
| 2266 | m_oam.next_name_select = (((data & 0x18) >> 3) * 0x1000) << 1; |
| 2267 | m_oam.next_size = (data & 0xe0) >> 5; |
| 2263 | 2268 | break; |
| 2264 | 2269 | case OAMADDL: /* Address for accessing OAM (low) */ |
| 2265 | | snes_ppu.oam.saved_address_low = data; |
| 2266 | | snes_ppu.oam.address = (snes_ppu.oam.address & 0xff00) + data; |
| 2267 | | snes_ppu.oam.first_sprite = snes_ppu.oam.priority_rotation ? (snes_ppu.oam.address >> 1) & 127 : 0; |
| 2268 | | snes_ram[OAMDATA] = 0; |
| 2270 | m_oam.saved_address_low = data; |
| 2271 | m_oam.address = (m_oam.address & 0xff00) + data; |
| 2272 | m_oam.first_sprite = m_oam.priority_rotation ? (m_oam.address >> 1) & 127 : 0; |
| 2273 | ram_ptr[OAMDATA] = 0; |
| 2269 | 2274 | break; |
| 2270 | 2275 | case OAMADDH: /* Address for accessing OAM (high) */ |
| 2271 | | snes_ppu.oam.saved_address_high = data; |
| 2272 | | snes_ppu.oam.address = (snes_ppu.oam.address & 0x00ff) | ((data & 0x01) << 8); |
| 2273 | | snes_ppu.oam.priority_rotation = BIT(data, 7); |
| 2274 | | snes_ppu.oam.first_sprite = snes_ppu.oam.priority_rotation ? (snes_ppu.oam.address >> 1) & 127 : 0; |
| 2275 | | snes_ram[OAMDATA] = 0; |
| 2276 | m_oam.saved_address_high = data; |
| 2277 | m_oam.address = (m_oam.address & 0x00ff) | ((data & 0x01) << 8); |
| 2278 | m_oam.priority_rotation = BIT(data, 7); |
| 2279 | m_oam.first_sprite = m_oam.priority_rotation ? (m_oam.address >> 1) & 127 : 0; |
| 2280 | ram_ptr[OAMDATA] = 0; |
| 2276 | 2281 | break; |
| 2277 | 2282 | case OAMDATA: /* Data for OAM write (DW) */ |
| 2278 | | if (snes_ppu.oam.address >= 0x100) |
| 2279 | | state->snes_oam_write(space, snes_ppu.oam.address, data); |
| 2283 | if (m_oam.address >= 0x100) |
| 2284 | snes_oam_write(space, m_oam.address, data); |
| 2280 | 2285 | else |
| 2281 | 2286 | { |
| 2282 | | if (!snes_ram[OAMDATA]) |
| 2283 | | snes_ppu.oam.write_latch = data; |
| 2287 | if (!ram_ptr[OAMDATA]) |
| 2288 | m_oam.write_latch = data; |
| 2284 | 2289 | else |
| 2285 | 2290 | { |
| 2286 | 2291 | // in this case, we not only write data to the upper byte of the word, |
| 2287 | | // but also snes_ppu.oam.write_latch to the lower byte (recall that |
| 2288 | | // snes_ram[OAMDATA] is used to select high/low byte) |
| 2289 | | state->snes_oam_write(space, snes_ppu.oam.address, data); |
| 2290 | | snes_ram[OAMDATA] = 0; |
| 2291 | | state->snes_oam_write(space, snes_ppu.oam.address, snes_ppu.oam.write_latch); |
| 2292 | | snes_ram[OAMDATA] = 1; |
| 2292 | // but also m_oam.write_latch to the lower byte (recall that |
| 2293 | // ram_ptr[OAMDATA] is used to select high/low byte) |
| 2294 | snes_oam_write(space, m_oam.address, data); |
| 2295 | ram_ptr[OAMDATA] = 0; |
| 2296 | snes_oam_write(space, m_oam.address, m_oam.write_latch); |
| 2297 | ram_ptr[OAMDATA] = 1; |
| 2293 | 2298 | } |
| 2294 | 2299 | } |
| 2295 | | snes_ram[OAMDATA] = (snes_ram[OAMDATA] + 1) % 2; |
| 2296 | | if (!snes_ram[OAMDATA]) |
| 2300 | ram_ptr[OAMDATA] = (ram_ptr[OAMDATA] + 1) % 2; |
| 2301 | if (!ram_ptr[OAMDATA]) |
| 2297 | 2302 | { |
| 2298 | | snes_ppu.oam.address++; |
| 2299 | | snes_ppu.oam.address &= 0x1ff; |
| 2300 | | snes_ppu.oam.first_sprite = snes_ppu.oam.priority_rotation ? (snes_ppu.oam.address >> 1) & 127 : 0; |
| 2303 | m_oam.address++; |
| 2304 | m_oam.address &= 0x1ff; |
| 2305 | m_oam.first_sprite = m_oam.priority_rotation ? (m_oam.address >> 1) & 127 : 0; |
| 2301 | 2306 | } |
| 2302 | 2307 | return; |
| 2303 | 2308 | case BGMODE: /* BG mode and character size settings */ |
| 2304 | | snes_ppu.mode = data & 0x07; |
| 2305 | | snes_dynamic_res_change(space.machine()); |
| 2306 | | snes_ppu.bg3_priority_bit = BIT(data, 3); |
| 2307 | | snes_ppu.layer[SNES_BG1].tile_size = BIT(data, 4); |
| 2308 | | snes_ppu.layer[SNES_BG2].tile_size = BIT(data, 5); |
| 2309 | | snes_ppu.layer[SNES_BG3].tile_size = BIT(data, 6); |
| 2310 | | snes_ppu.layer[SNES_BG4].tile_size = BIT(data, 7); |
| 2311 | | snes_ppu.update_offsets = 1; |
| 2309 | m_mode = data & 0x07; |
| 2310 | snes_dynamic_res_change(space.machine(), ram_ptr); |
| 2311 | m_bg3_priority_bit = BIT(data, 3); |
| 2312 | m_layer[SNES_BG1].tile_size = BIT(data, 4); |
| 2313 | m_layer[SNES_BG2].tile_size = BIT(data, 5); |
| 2314 | m_layer[SNES_BG3].tile_size = BIT(data, 6); |
| 2315 | m_layer[SNES_BG4].tile_size = BIT(data, 7); |
| 2316 | m_update_offsets = 1; |
| 2312 | 2317 | break; |
| 2313 | 2318 | case MOSAIC: /* Size and screen designation for mosaic */ |
| 2314 | | snes_ppu.mosaic_size = (data & 0xf0) >> 4; |
| 2315 | | snes_ppu.layer[SNES_BG1].mosaic_enabled = BIT(data, 0); |
| 2316 | | snes_ppu.layer[SNES_BG2].mosaic_enabled = BIT(data, 1); |
| 2317 | | snes_ppu.layer[SNES_BG3].mosaic_enabled = BIT(data, 2); |
| 2318 | | snes_ppu.layer[SNES_BG4].mosaic_enabled = BIT(data, 3); |
| 2319 | m_mosaic_size = (data & 0xf0) >> 4; |
| 2320 | m_layer[SNES_BG1].mosaic_enabled = BIT(data, 0); |
| 2321 | m_layer[SNES_BG2].mosaic_enabled = BIT(data, 1); |
| 2322 | m_layer[SNES_BG3].mosaic_enabled = BIT(data, 2); |
| 2323 | m_layer[SNES_BG4].mosaic_enabled = BIT(data, 3); |
| 2319 | 2324 | break; |
| 2320 | 2325 | case BG1SC: /* Address for storing SC data BG1 SC size designation */ |
| 2321 | 2326 | case BG2SC: /* Address for storing SC data BG2 SC size designation */ |
| 2322 | 2327 | case BG3SC: /* Address for storing SC data BG3 SC size designation */ |
| 2323 | 2328 | case BG4SC: /* Address for storing SC data BG4 SC size designation */ |
| 2324 | | snes_ppu.layer[offset - BG1SC].tilemap = data & 0xfc; |
| 2325 | | snes_ppu.layer[offset - BG1SC].tilemap_size = data & 0x3; |
| 2329 | m_layer[offset - BG1SC].tilemap = data & 0xfc; |
| 2330 | m_layer[offset - BG1SC].tilemap_size = data & 0x3; |
| 2326 | 2331 | break; |
| 2327 | 2332 | case BG12NBA: /* Address for BG 1 and 2 character data */ |
| 2328 | | snes_ppu.layer[SNES_BG1].charmap = (data & 0x0f); |
| 2329 | | snes_ppu.layer[SNES_BG2].charmap = (data & 0xf0) >> 4; |
| 2333 | m_layer[SNES_BG1].charmap = (data & 0x0f); |
| 2334 | m_layer[SNES_BG2].charmap = (data & 0xf0) >> 4; |
| 2330 | 2335 | break; |
| 2331 | 2336 | case BG34NBA: /* Address for BG 3 and 4 character data */ |
| 2332 | | snes_ppu.layer[SNES_BG3].charmap = (data & 0x0f); |
| 2333 | | snes_ppu.layer[SNES_BG4].charmap = (data & 0xf0) >> 4; |
| 2337 | m_layer[SNES_BG3].charmap = (data & 0x0f); |
| 2338 | m_layer[SNES_BG4].charmap = (data & 0xf0) >> 4; |
| 2334 | 2339 | break; |
| 2335 | 2340 | |
| 2336 | 2341 | // Anomie says "H Current = (Byte<<8) | (Prev&~7) | ((Current>>8)&7); V Current = (Current<<8) | Prev;" and Prev is shared by all scrolls but in Mode 7! |
| 2337 | 2342 | case BG1HOFS: /* BG1 - horizontal scroll (DW) */ |
| 2338 | 2343 | /* In Mode 0->6 we use ppu_last_scroll as Prev */ |
| 2339 | | snes_ppu.layer[SNES_BG1].hoffs = (data << 8) | (snes_ppu.ppu_last_scroll & ~7) | ((snes_ppu.layer[SNES_BG1].hoffs >> 8) & 7); |
| 2340 | | snes_ppu.ppu_last_scroll = data; |
| 2344 | m_layer[SNES_BG1].hoffs = (data << 8) | (m_ppu_last_scroll & ~7) | ((m_layer[SNES_BG1].hoffs >> 8) & 7); |
| 2345 | m_ppu_last_scroll = data; |
| 2341 | 2346 | /* In Mode 7 we use mode7_last_scroll as Prev */ |
| 2342 | | snes_ppu.mode7.hor_offset = (data << 8) | (snes_ppu.mode7_last_scroll & ~7) | ((snes_ppu.mode7.hor_offset >> 8) & 7); |
| 2343 | | snes_ppu.mode7_last_scroll = data; |
| 2344 | | snes_ppu.update_offsets = 1; |
| 2347 | m_mode7.hor_offset = (data << 8) | (m_mode7_last_scroll & ~7) | ((m_mode7.hor_offset >> 8) & 7); |
| 2348 | m_mode7_last_scroll = data; |
| 2349 | m_update_offsets = 1; |
| 2345 | 2350 | return; |
| 2346 | 2351 | case BG1VOFS: /* BG1 - vertical scroll (DW) */ |
| 2347 | 2352 | /* In Mode 0->6 we use ppu_last_scroll as Prev */ |
| 2348 | | snes_ppu.layer[SNES_BG1].voffs = (data << 8) | snes_ppu.ppu_last_scroll; |
| 2349 | | snes_ppu.ppu_last_scroll = data; |
| 2353 | m_layer[SNES_BG1].voffs = (data << 8) | m_ppu_last_scroll; |
| 2354 | m_ppu_last_scroll = data; |
| 2350 | 2355 | /* In Mode 7 we use mode7_last_scroll as Prev */ |
| 2351 | | snes_ppu.mode7.ver_offset = (data << 8) | snes_ppu.mode7_last_scroll; |
| 2352 | | snes_ppu.mode7_last_scroll = data; |
| 2353 | | snes_ppu.update_offsets = 1; |
| 2356 | m_mode7.ver_offset = (data << 8) | m_mode7_last_scroll; |
| 2357 | m_mode7_last_scroll = data; |
| 2358 | m_update_offsets = 1; |
| 2354 | 2359 | return; |
| 2355 | 2360 | case BG2HOFS: /* BG2 - horizontal scroll (DW) */ |
| 2356 | | snes_ppu.layer[SNES_BG2].hoffs = (data << 8) | (snes_ppu.ppu_last_scroll & ~7) | ((snes_ppu.layer[SNES_BG2].hoffs >> 8) & 7); |
| 2357 | | snes_ppu.ppu_last_scroll = data; |
| 2358 | | snes_ppu.update_offsets = 1; |
| 2361 | m_layer[SNES_BG2].hoffs = (data << 8) | (m_ppu_last_scroll & ~7) | ((m_layer[SNES_BG2].hoffs >> 8) & 7); |
| 2362 | m_ppu_last_scroll = data; |
| 2363 | m_update_offsets = 1; |
| 2359 | 2364 | return; |
| 2360 | 2365 | case BG2VOFS: /* BG2 - vertical scroll (DW) */ |
| 2361 | | snes_ppu.layer[SNES_BG2].voffs = (data << 8) | (snes_ppu.ppu_last_scroll); |
| 2362 | | snes_ppu.ppu_last_scroll = data; |
| 2363 | | snes_ppu.update_offsets = 1; |
| 2366 | m_layer[SNES_BG2].voffs = (data << 8) | (m_ppu_last_scroll); |
| 2367 | m_ppu_last_scroll = data; |
| 2368 | m_update_offsets = 1; |
| 2364 | 2369 | return; |
| 2365 | 2370 | case BG3HOFS: /* BG3 - horizontal scroll (DW) */ |
| 2366 | | snes_ppu.layer[SNES_BG3].hoffs = (data << 8) | (snes_ppu.ppu_last_scroll & ~7) | ((snes_ppu.layer[SNES_BG3].hoffs >> 8) & 7); |
| 2367 | | snes_ppu.ppu_last_scroll = data; |
| 2368 | | snes_ppu.update_offsets = 1; |
| 2371 | m_layer[SNES_BG3].hoffs = (data << 8) | (m_ppu_last_scroll & ~7) | ((m_layer[SNES_BG3].hoffs >> 8) & 7); |
| 2372 | m_ppu_last_scroll = data; |
| 2373 | m_update_offsets = 1; |
| 2369 | 2374 | return; |
| 2370 | 2375 | case BG3VOFS: /* BG3 - vertical scroll (DW) */ |
| 2371 | | snes_ppu.layer[SNES_BG3].voffs = (data << 8) | (snes_ppu.ppu_last_scroll); |
| 2372 | | snes_ppu.ppu_last_scroll = data; |
| 2373 | | snes_ppu.update_offsets = 1; |
| 2376 | m_layer[SNES_BG3].voffs = (data << 8) | (m_ppu_last_scroll); |
| 2377 | m_ppu_last_scroll = data; |
| 2378 | m_update_offsets = 1; |
| 2374 | 2379 | return; |
| 2375 | 2380 | case BG4HOFS: /* BG4 - horizontal scroll (DW) */ |
| 2376 | | snes_ppu.layer[SNES_BG4].hoffs = (data << 8) | (snes_ppu.ppu_last_scroll & ~7) | ((snes_ppu.layer[SNES_BG4].hoffs >> 8) & 7); |
| 2377 | | snes_ppu.ppu_last_scroll = data; |
| 2378 | | snes_ppu.update_offsets = 1; |
| 2381 | m_layer[SNES_BG4].hoffs = (data << 8) | (m_ppu_last_scroll & ~7) | ((m_layer[SNES_BG4].hoffs >> 8) & 7); |
| 2382 | m_ppu_last_scroll = data; |
| 2383 | m_update_offsets = 1; |
| 2379 | 2384 | return; |
| 2380 | 2385 | case BG4VOFS: /* BG4 - vertical scroll (DW) */ |
| 2381 | | snes_ppu.layer[SNES_BG4].voffs = (data << 8) | (snes_ppu.ppu_last_scroll); |
| 2382 | | snes_ppu.ppu_last_scroll = data; |
| 2383 | | snes_ppu.update_offsets = 1; |
| 2386 | m_layer[SNES_BG4].voffs = (data << 8) | (m_ppu_last_scroll); |
| 2387 | m_ppu_last_scroll = data; |
| 2388 | m_update_offsets = 1; |
| 2384 | 2389 | return; |
| 2385 | 2390 | case VMAIN: /* VRAM address increment value designation */ |
| 2386 | 2391 | state->m_vram_fgr_high = (data & 0x80); |
| r21558 | r21559 | |
| 2405 | 2410 | UINT32 addr; |
| 2406 | 2411 | state->m_vmadd = (state->m_vmadd & 0xff00) | (data << 0); |
| 2407 | 2412 | addr = snes_get_vram_address(space.machine()); |
| 2408 | | state->m_vram_read_buffer = state->snes_vram_read(space, addr); |
| 2409 | | state->m_vram_read_buffer |= (state->snes_vram_read(space, addr + 1) << 8); |
| 2413 | state->m_vram_read_buffer = snes_vram_read(space, addr); |
| 2414 | state->m_vram_read_buffer |= (snes_vram_read(space, addr + 1) << 8); |
| 2410 | 2415 | } |
| 2411 | 2416 | break; |
| 2412 | 2417 | case VMADDH: /* Address for VRAM read/write (high) */ |
| r21558 | r21559 | |
| 2414 | 2419 | UINT32 addr; |
| 2415 | 2420 | state->m_vmadd = (state->m_vmadd & 0x00ff) | (data << 8); |
| 2416 | 2421 | addr = snes_get_vram_address(space.machine()); |
| 2417 | | state->m_vram_read_buffer = state->snes_vram_read(space, addr); |
| 2418 | | state->m_vram_read_buffer |= (state->snes_vram_read(space, addr + 1) << 8); |
| 2422 | state->m_vram_read_buffer = snes_vram_read(space, addr); |
| 2423 | state->m_vram_read_buffer |= (snes_vram_read(space, addr + 1) << 8); |
| 2419 | 2424 | } |
| 2420 | 2425 | break; |
| 2421 | 2426 | case VMDATAL: /* 2118: Data for VRAM write (low) */ |
| 2422 | 2427 | { |
| 2423 | 2428 | UINT32 addr = snes_get_vram_address(space.machine()); |
| 2424 | | state->snes_vram_write(space, addr, data); |
| 2429 | snes_vram_write(space, addr, data); |
| 2425 | 2430 | |
| 2426 | 2431 | if (!state->m_vram_fgr_high) |
| 2427 | 2432 | state->m_vmadd = (state->m_vmadd + state->m_vram_fgr_increment) & 0xffff; |
| r21558 | r21559 | |
| 2430 | 2435 | case VMDATAH: /* 2119: Data for VRAM write (high) */ |
| 2431 | 2436 | { |
| 2432 | 2437 | UINT32 addr = snes_get_vram_address(space.machine()); |
| 2433 | | state->snes_vram_write(space, addr + 1, data); |
| 2438 | snes_vram_write(space, addr + 1, data); |
| 2434 | 2439 | |
| 2435 | 2440 | if (state->m_vram_fgr_high) |
| 2436 | 2441 | state->m_vmadd = (state->m_vmadd + state->m_vram_fgr_increment) & 0xffff; |
| 2437 | 2442 | } |
| 2438 | 2443 | return; |
| 2439 | 2444 | case M7SEL: /* Mode 7 initial settings */ |
| 2440 | | snes_ppu.mode7.repeat = (data >> 6) & 3; |
| 2441 | | snes_ppu.mode7.vflip = BIT(data, 1); |
| 2442 | | snes_ppu.mode7.hflip = BIT(data, 0); |
| 2445 | m_mode7.repeat = (data >> 6) & 3; |
| 2446 | m_mode7.vflip = BIT(data, 1); |
| 2447 | m_mode7.hflip = BIT(data, 0); |
| 2443 | 2448 | break; |
| 2444 | 2449 | /* As per Anomie's doc: Reg = (Current<<8) | Prev; and there is only one Prev, shared by these matrix regs and Mode 7 scroll regs */ |
| 2445 | 2450 | case M7A: /* Mode 7 COS angle/x expansion (DW) */ |
| 2446 | | snes_ppu.mode7.matrix_a = snes_ppu.mode7_last_scroll + (data << 8); |
| 2447 | | snes_ppu.mode7_last_scroll = data; |
| 2451 | m_mode7.matrix_a = m_mode7_last_scroll + (data << 8); |
| 2452 | m_mode7_last_scroll = data; |
| 2448 | 2453 | break; |
| 2449 | 2454 | case M7B: /* Mode 7 SIN angle/ x expansion (DW) */ |
| 2450 | | snes_ppu.mode7.matrix_b = snes_ppu.mode7_last_scroll + (data << 8); |
| 2451 | | snes_ppu.mode7_last_scroll = data; |
| 2455 | m_mode7.matrix_b = m_mode7_last_scroll + (data << 8); |
| 2456 | m_mode7_last_scroll = data; |
| 2452 | 2457 | break; |
| 2453 | 2458 | case M7C: /* Mode 7 SIN angle/y expansion (DW) */ |
| 2454 | | snes_ppu.mode7.matrix_c = snes_ppu.mode7_last_scroll + (data << 8); |
| 2455 | | snes_ppu.mode7_last_scroll = data; |
| 2459 | m_mode7.matrix_c = m_mode7_last_scroll + (data << 8); |
| 2460 | m_mode7_last_scroll = data; |
| 2456 | 2461 | break; |
| 2457 | 2462 | case M7D: /* Mode 7 COS angle/y expansion (DW) */ |
| 2458 | | snes_ppu.mode7.matrix_d = snes_ppu.mode7_last_scroll + (data << 8); |
| 2459 | | snes_ppu.mode7_last_scroll = data; |
| 2463 | m_mode7.matrix_d = m_mode7_last_scroll + (data << 8); |
| 2464 | m_mode7_last_scroll = data; |
| 2460 | 2465 | break; |
| 2461 | 2466 | case M7X: /* Mode 7 x center position (DW) */ |
| 2462 | | snes_ppu.mode7.origin_x = snes_ppu.mode7_last_scroll + (data << 8); |
| 2463 | | snes_ppu.mode7_last_scroll = data; |
| 2467 | m_mode7.origin_x = m_mode7_last_scroll + (data << 8); |
| 2468 | m_mode7_last_scroll = data; |
| 2464 | 2469 | break; |
| 2465 | 2470 | case M7Y: /* Mode 7 y center position (DW) */ |
| 2466 | | snes_ppu.mode7.origin_y = snes_ppu.mode7_last_scroll + (data << 8); |
| 2467 | | snes_ppu.mode7_last_scroll = data; |
| 2471 | m_mode7.origin_y = m_mode7_last_scroll + (data << 8); |
| 2472 | m_mode7_last_scroll = data; |
| 2468 | 2473 | break; |
| 2469 | 2474 | case CGADD: /* Initial address for colour RAM writing */ |
| 2470 | 2475 | /* CGRAM is 16-bit, but when reading/writing we treat it as 8-bit, so we need to double the address */ |
| 2471 | 2476 | state->m_cgram_address = data << 1; |
| 2472 | 2477 | break; |
| 2473 | 2478 | case CGDATA: /* Data for colour RAM */ |
| 2474 | | state->snes_cgram_write(space, state->m_cgram_address, data); |
| 2479 | snes_cgram_write(space, state->m_cgram_address, data); |
| 2475 | 2480 | state->m_cgram_address = (state->m_cgram_address + 1) % (SNES_CGRAM_SIZE - 2); |
| 2476 | 2481 | break; |
| 2477 | 2482 | case W12SEL: /* Window mask settings for BG1-2 */ |
| 2478 | | if (data != snes_ram[offset]) |
| 2483 | if (data != ram_ptr[offset]) |
| 2479 | 2484 | { |
| 2480 | | snes_ppu.layer[SNES_BG1].window1_invert = BIT(data, 0); |
| 2481 | | snes_ppu.layer[SNES_BG1].window1_enabled = BIT(data, 1); |
| 2482 | | snes_ppu.layer[SNES_BG1].window2_invert = BIT(data, 2); |
| 2483 | | snes_ppu.layer[SNES_BG1].window2_enabled = BIT(data, 3); |
| 2484 | | snes_ppu.layer[SNES_BG2].window1_invert = BIT(data, 4); |
| 2485 | | snes_ppu.layer[SNES_BG2].window1_enabled = BIT(data, 5); |
| 2486 | | snes_ppu.layer[SNES_BG2].window2_invert = BIT(data, 6); |
| 2487 | | snes_ppu.layer[SNES_BG2].window2_enabled = BIT(data, 7); |
| 2488 | | snes_ppu.update_windows = 1; |
| 2485 | m_layer[SNES_BG1].window1_invert = BIT(data, 0); |
| 2486 | m_layer[SNES_BG1].window1_enabled = BIT(data, 1); |
| 2487 | m_layer[SNES_BG1].window2_invert = BIT(data, 2); |
| 2488 | m_layer[SNES_BG1].window2_enabled = BIT(data, 3); |
| 2489 | m_layer[SNES_BG2].window1_invert = BIT(data, 4); |
| 2490 | m_layer[SNES_BG2].window1_enabled = BIT(data, 5); |
| 2491 | m_layer[SNES_BG2].window2_invert = BIT(data, 6); |
| 2492 | m_layer[SNES_BG2].window2_enabled = BIT(data, 7); |
| 2493 | m_update_windows = 1; |
| 2489 | 2494 | } |
| 2490 | 2495 | break; |
| 2491 | 2496 | case W34SEL: /* Window mask settings for BG3-4 */ |
| 2492 | | if (data != snes_ram[offset]) |
| 2497 | if (data != ram_ptr[offset]) |
| 2493 | 2498 | { |
| 2494 | | snes_ppu.layer[SNES_BG3].window1_invert = BIT(data, 0); |
| 2495 | | snes_ppu.layer[SNES_BG3].window1_enabled = BIT(data, 1); |
| 2496 | | snes_ppu.layer[SNES_BG3].window2_invert = BIT(data, 2); |
| 2497 | | snes_ppu.layer[SNES_BG3].window2_enabled = BIT(data, 3); |
| 2498 | | snes_ppu.layer[SNES_BG4].window1_invert = BIT(data, 4); |
| 2499 | | snes_ppu.layer[SNES_BG4].window1_enabled = BIT(data, 5); |
| 2500 | | snes_ppu.layer[SNES_BG4].window2_invert = BIT(data, 6); |
| 2501 | | snes_ppu.layer[SNES_BG4].window2_enabled = BIT(data, 7); |
| 2502 | | snes_ppu.update_windows = 1; |
| 2499 | m_layer[SNES_BG3].window1_invert = BIT(data, 0); |
| 2500 | m_layer[SNES_BG3].window1_enabled = BIT(data, 1); |
| 2501 | m_layer[SNES_BG3].window2_invert = BIT(data, 2); |
| 2502 | m_layer[SNES_BG3].window2_enabled = BIT(data, 3); |
| 2503 | m_layer[SNES_BG4].window1_invert = BIT(data, 4); |
| 2504 | m_layer[SNES_BG4].window1_enabled = BIT(data, 5); |
| 2505 | m_layer[SNES_BG4].window2_invert = BIT(data, 6); |
| 2506 | m_layer[SNES_BG4].window2_enabled = BIT(data, 7); |
| 2507 | m_update_windows = 1; |
| 2503 | 2508 | } |
| 2504 | 2509 | break; |
| 2505 | 2510 | case WOBJSEL: /* Window mask settings for objects */ |
| 2506 | | if (data != snes_ram[offset]) |
| 2511 | if (data != ram_ptr[offset]) |
| 2507 | 2512 | { |
| 2508 | | snes_ppu.layer[SNES_OAM].window1_invert = BIT(data, 0); |
| 2509 | | snes_ppu.layer[SNES_OAM].window1_enabled = BIT(data, 1); |
| 2510 | | snes_ppu.layer[SNES_OAM].window2_invert = BIT(data, 2); |
| 2511 | | snes_ppu.layer[SNES_OAM].window2_enabled = BIT(data, 3); |
| 2512 | | snes_ppu.layer[SNES_COLOR].window1_invert = BIT(data, 4); |
| 2513 | | snes_ppu.layer[SNES_COLOR].window1_enabled = BIT(data, 5); |
| 2514 | | snes_ppu.layer[SNES_COLOR].window2_invert = BIT(data, 6); |
| 2515 | | snes_ppu.layer[SNES_COLOR].window2_enabled = BIT(data, 7); |
| 2516 | | snes_ppu.update_windows = 1; |
| 2513 | m_layer[SNES_OAM].window1_invert = BIT(data, 0); |
| 2514 | m_layer[SNES_OAM].window1_enabled = BIT(data, 1); |
| 2515 | m_layer[SNES_OAM].window2_invert = BIT(data, 2); |
| 2516 | m_layer[SNES_OAM].window2_enabled = BIT(data, 3); |
| 2517 | m_layer[SNES_COLOR].window1_invert = BIT(data, 4); |
| 2518 | m_layer[SNES_COLOR].window1_enabled = BIT(data, 5); |
| 2519 | m_layer[SNES_COLOR].window2_invert = BIT(data, 6); |
| 2520 | m_layer[SNES_COLOR].window2_enabled = BIT(data, 7); |
| 2521 | m_update_windows = 1; |
| 2517 | 2522 | } |
| 2518 | 2523 | break; |
| 2519 | 2524 | case WH0: /* Window 1 left position */ |
| 2520 | | if (data != snes_ram[offset]) |
| 2525 | if (data != ram_ptr[offset]) |
| 2521 | 2526 | { |
| 2522 | | snes_ppu.window1_left = data; |
| 2523 | | snes_ppu.update_windows = 1; |
| 2527 | m_window1_left = data; |
| 2528 | m_update_windows = 1; |
| 2524 | 2529 | } |
| 2525 | 2530 | break; |
| 2526 | 2531 | case WH1: /* Window 1 right position */ |
| 2527 | | if (data != snes_ram[offset]) |
| 2532 | if (data != ram_ptr[offset]) |
| 2528 | 2533 | { |
| 2529 | | snes_ppu.window1_right = data; |
| 2530 | | snes_ppu.update_windows = 1; |
| 2534 | m_window1_right = data; |
| 2535 | m_update_windows = 1; |
| 2531 | 2536 | } |
| 2532 | 2537 | break; |
| 2533 | 2538 | case WH2: /* Window 2 left position */ |
| 2534 | | if (data != snes_ram[offset]) |
| 2539 | if (data != ram_ptr[offset]) |
| 2535 | 2540 | { |
| 2536 | | snes_ppu.window2_left = data; |
| 2537 | | snes_ppu.update_windows = 1; |
| 2541 | m_window2_left = data; |
| 2542 | m_update_windows = 1; |
| 2538 | 2543 | } |
| 2539 | 2544 | break; |
| 2540 | 2545 | case WH3: /* Window 2 right position */ |
| 2541 | | if (data != snes_ram[offset]) |
| 2546 | if (data != ram_ptr[offset]) |
| 2542 | 2547 | { |
| 2543 | | snes_ppu.window2_right = data; |
| 2544 | | snes_ppu.update_windows = 1; |
| 2548 | m_window2_right = data; |
| 2549 | m_update_windows = 1; |
| 2545 | 2550 | } |
| 2546 | 2551 | break; |
| 2547 | 2552 | case WBGLOG: /* Window mask logic for BG's */ |
| 2548 | | if (data != snes_ram[offset]) |
| 2553 | if (data != ram_ptr[offset]) |
| 2549 | 2554 | { |
| 2550 | | snes_ppu.layer[SNES_BG1].wlog_mask = data & 0x03; |
| 2551 | | snes_ppu.layer[SNES_BG2].wlog_mask = (data & 0x0c) >> 2; |
| 2552 | | snes_ppu.layer[SNES_BG3].wlog_mask = (data & 0x30) >> 4; |
| 2553 | | snes_ppu.layer[SNES_BG4].wlog_mask = (data & 0xc0) >> 6; |
| 2554 | | snes_ppu.update_windows = 1; |
| 2555 | m_layer[SNES_BG1].wlog_mask = data & 0x03; |
| 2556 | m_layer[SNES_BG2].wlog_mask = (data & 0x0c) >> 2; |
| 2557 | m_layer[SNES_BG3].wlog_mask = (data & 0x30) >> 4; |
| 2558 | m_layer[SNES_BG4].wlog_mask = (data & 0xc0) >> 6; |
| 2559 | m_update_windows = 1; |
| 2555 | 2560 | } |
| 2556 | 2561 | break; |
| 2557 | 2562 | case WOBJLOG: /* Window mask logic for objects */ |
| 2558 | | if (data != snes_ram[offset]) |
| 2563 | if (data != ram_ptr[offset]) |
| 2559 | 2564 | { |
| 2560 | | snes_ppu.layer[SNES_OAM].wlog_mask = data & 0x03; |
| 2561 | | snes_ppu.layer[SNES_COLOR].wlog_mask = (data & 0x0c) >> 2; |
| 2562 | | snes_ppu.update_windows = 1; |
| 2565 | m_layer[SNES_OAM].wlog_mask = data & 0x03; |
| 2566 | m_layer[SNES_COLOR].wlog_mask = (data & 0x0c) >> 2; |
| 2567 | m_update_windows = 1; |
| 2563 | 2568 | } |
| 2564 | 2569 | break; |
| 2565 | 2570 | case TM: /* Main screen designation */ |
| 2566 | | snes_ppu.layer[SNES_BG1].main_bg_enabled = BIT(data, 0); |
| 2567 | | snes_ppu.layer[SNES_BG2].main_bg_enabled = BIT(data, 1); |
| 2568 | | snes_ppu.layer[SNES_BG3].main_bg_enabled = BIT(data, 2); |
| 2569 | | snes_ppu.layer[SNES_BG4].main_bg_enabled = BIT(data, 3); |
| 2570 | | snes_ppu.layer[SNES_OAM].main_bg_enabled = BIT(data, 4); |
| 2571 | m_layer[SNES_BG1].main_bg_enabled = BIT(data, 0); |
| 2572 | m_layer[SNES_BG2].main_bg_enabled = BIT(data, 1); |
| 2573 | m_layer[SNES_BG3].main_bg_enabled = BIT(data, 2); |
| 2574 | m_layer[SNES_BG4].main_bg_enabled = BIT(data, 3); |
| 2575 | m_layer[SNES_OAM].main_bg_enabled = BIT(data, 4); |
| 2571 | 2576 | break; |
| 2572 | 2577 | case TS: /* Subscreen designation */ |
| 2573 | | snes_ppu.layer[SNES_BG1].sub_bg_enabled = BIT(data, 0); |
| 2574 | | snes_ppu.layer[SNES_BG2].sub_bg_enabled = BIT(data, 1); |
| 2575 | | snes_ppu.layer[SNES_BG3].sub_bg_enabled = BIT(data, 2); |
| 2576 | | snes_ppu.layer[SNES_BG4].sub_bg_enabled = BIT(data, 3); |
| 2577 | | snes_ppu.layer[SNES_OAM].sub_bg_enabled = BIT(data, 4); |
| 2578 | m_layer[SNES_BG1].sub_bg_enabled = BIT(data, 0); |
| 2579 | m_layer[SNES_BG2].sub_bg_enabled = BIT(data, 1); |
| 2580 | m_layer[SNES_BG3].sub_bg_enabled = BIT(data, 2); |
| 2581 | m_layer[SNES_BG4].sub_bg_enabled = BIT(data, 3); |
| 2582 | m_layer[SNES_OAM].sub_bg_enabled = BIT(data, 4); |
| 2578 | 2583 | break; |
| 2579 | 2584 | case TMW: /* Window mask for main screen designation */ |
| 2580 | | snes_ppu.layer[SNES_BG1].main_window_enabled = BIT(data, 0); |
| 2581 | | snes_ppu.layer[SNES_BG2].main_window_enabled = BIT(data, 1); |
| 2582 | | snes_ppu.layer[SNES_BG3].main_window_enabled = BIT(data, 2); |
| 2583 | | snes_ppu.layer[SNES_BG4].main_window_enabled = BIT(data, 3); |
| 2584 | | snes_ppu.layer[SNES_OAM].main_window_enabled = BIT(data, 4); |
| 2585 | m_layer[SNES_BG1].main_window_enabled = BIT(data, 0); |
| 2586 | m_layer[SNES_BG2].main_window_enabled = BIT(data, 1); |
| 2587 | m_layer[SNES_BG3].main_window_enabled = BIT(data, 2); |
| 2588 | m_layer[SNES_BG4].main_window_enabled = BIT(data, 3); |
| 2589 | m_layer[SNES_OAM].main_window_enabled = BIT(data, 4); |
| 2585 | 2590 | break; |
| 2586 | 2591 | case TSW: /* Window mask for subscreen designation */ |
| 2587 | | snes_ppu.layer[SNES_BG1].sub_window_enabled = BIT(data, 0); |
| 2588 | | snes_ppu.layer[SNES_BG2].sub_window_enabled = BIT(data, 1); |
| 2589 | | snes_ppu.layer[SNES_BG3].sub_window_enabled = BIT(data, 2); |
| 2590 | | snes_ppu.layer[SNES_BG4].sub_window_enabled = BIT(data, 3); |
| 2591 | | snes_ppu.layer[SNES_OAM].sub_window_enabled = BIT(data, 4); |
| 2592 | m_layer[SNES_BG1].sub_window_enabled = BIT(data, 0); |
| 2593 | m_layer[SNES_BG2].sub_window_enabled = BIT(data, 1); |
| 2594 | m_layer[SNES_BG3].sub_window_enabled = BIT(data, 2); |
| 2595 | m_layer[SNES_BG4].sub_window_enabled = BIT(data, 3); |
| 2596 | m_layer[SNES_OAM].sub_window_enabled = BIT(data, 4); |
| 2592 | 2597 | break; |
| 2593 | 2598 | case CGWSEL: /* Initial settings for Fixed colour addition or screen addition */ |
| 2594 | | snes_ppu.clip_to_black = (data >> 6) & 0x03; |
| 2595 | | snes_ppu.prevent_color_math = (data >> 4) & 0x03; |
| 2596 | | snes_ppu.sub_add_mode = BIT(data, 1); |
| 2597 | | snes_ppu.direct_color = BIT(data, 0); |
| 2599 | m_clip_to_black = (data >> 6) & 0x03; |
| 2600 | m_prevent_color_math = (data >> 4) & 0x03; |
| 2601 | m_sub_add_mode = BIT(data, 1); |
| 2602 | m_direct_color = BIT(data, 0); |
| 2598 | 2603 | #ifdef SNES_DBG_REG_W |
| 2599 | | if ((data & 0x2) != (snes_ram[CGWSEL] & 0x2)) |
| 2600 | | mame_printf_debug( "Add/Sub Layer: %s\n", ((data & 0x2) >> 1) ? "Subscreen" : "Fixed colour" ); |
| 2604 | if ((data & 0x2) != (ram_ptr[CGWSEL] & 0x2)) |
| 2605 | mame_printf_debug("Add/Sub Layer: %s\n", ((data & 0x2) >> 1) ? "Subscreen" : "Fixed colour"); |
| 2601 | 2606 | #endif |
| 2602 | 2607 | break; |
| 2603 | 2608 | case CGADSUB: /* Addition/Subtraction designation for each screen */ |
| 2604 | | snes_ppu.color_modes = data & 0xc0; |
| 2605 | | snes_ppu.layer[SNES_BG1].color_math = BIT(data, 0); |
| 2606 | | snes_ppu.layer[SNES_BG2].color_math = BIT(data, 1); |
| 2607 | | snes_ppu.layer[SNES_BG3].color_math = BIT(data, 2); |
| 2608 | | snes_ppu.layer[SNES_BG4].color_math = BIT(data, 3); |
| 2609 | | snes_ppu.layer[SNES_OAM].color_math = BIT(data, 4); |
| 2610 | | snes_ppu.layer[SNES_COLOR].color_math = BIT(data, 5); |
| 2609 | m_color_modes = data & 0xc0; |
| 2610 | m_layer[SNES_BG1].color_math = BIT(data, 0); |
| 2611 | m_layer[SNES_BG2].color_math = BIT(data, 1); |
| 2612 | m_layer[SNES_BG3].color_math = BIT(data, 2); |
| 2613 | m_layer[SNES_BG4].color_math = BIT(data, 3); |
| 2614 | m_layer[SNES_OAM].color_math = BIT(data, 4); |
| 2615 | m_layer[SNES_COLOR].color_math = BIT(data, 5); |
| 2611 | 2616 | break; |
| 2612 | 2617 | case COLDATA: /* Fixed colour data for fixed colour addition/subtraction */ |
| 2613 | 2618 | { |
| r21558 | r21559 | |
| 2615 | 2620 | UINT8 r, g, b; |
| 2616 | 2621 | |
| 2617 | 2622 | /* Get existing value. */ |
| 2618 | | r = state->m_snes_cgram[FIXED_COLOUR] & 0x1f; |
| 2619 | | g = (state->m_snes_cgram[FIXED_COLOUR] & 0x3e0) >> 5; |
| 2620 | | b = (state->m_snes_cgram[FIXED_COLOUR] & 0x7c00) >> 10; |
| 2623 | r = m_cgram[FIXED_COLOUR] & 0x1f; |
| 2624 | g = (m_cgram[FIXED_COLOUR] & 0x3e0) >> 5; |
| 2625 | b = (m_cgram[FIXED_COLOUR] & 0x7c00) >> 10; |
| 2621 | 2626 | /* Set new value */ |
| 2622 | 2627 | if (data & 0x20) |
| 2623 | 2628 | r = data & 0x1f; |
| r21558 | r21559 | |
| 2625 | 2630 | g = data & 0x1f; |
| 2626 | 2631 | if (data & 0x80) |
| 2627 | 2632 | b = data & 0x1f; |
| 2628 | | state->m_snes_cgram[FIXED_COLOUR] = (r | (g << 5) | (b << 10)); |
| 2633 | m_cgram[FIXED_COLOUR] = (r | (g << 5) | (b << 10)); |
| 2629 | 2634 | } break; |
| 2630 | 2635 | case SETINI: /* Screen mode/video select */ |
| 2631 | | snes_ppu.interlace = (data & 0x01) ? 2 : 1; |
| 2632 | | snes_ppu.obj_interlace = (data & 0x02) ? 2 : 1; |
| 2633 | | snes_ppu.beam.last_visible_line = (data & 0x04) ? 240 : 225; |
| 2634 | | snes_ppu.pseudo_hires = BIT(data, 3); |
| 2635 | | snes_ppu.mode7.extbg = BIT(data, 6); |
| 2636 | | snes_dynamic_res_change(space.machine()); |
| 2636 | m_interlace = (data & 0x01) ? 2 : 1; |
| 2637 | m_obj_interlace = (data & 0x02) ? 2 : 1; |
| 2638 | m_beam.last_visible_line = (data & 0x04) ? 240 : 225; |
| 2639 | m_pseudo_hires = BIT(data, 3); |
| 2640 | m_mode7.extbg = BIT(data, 6); |
| 2641 | snes_dynamic_res_change(space.machine(), ram_ptr); |
| 2637 | 2642 | #ifdef SNES_DBG_REG_W |
| 2638 | | if ((data & 0x8) != (snes_ram[SETINI] & 0x8)) |
| 2639 | | mame_printf_debug( "Pseudo 512 mode: %s\n", (data & 0x8) ? "on" : "off" ); |
| 2643 | if ((data & 0x8) != (ram_ptr[SETINI] & 0x8)) |
| 2644 | mame_printf_debug("Pseudo 512 mode: %s\n", (data & 0x8) ? "on" : "off"); |
| 2640 | 2645 | #endif |
| 2641 | 2646 | break; |
| 2642 | 2647 | } |
| 2643 | 2648 | |
| 2644 | | snes_ram[offset] = data; |
| 2649 | ram_ptr[offset] = data; |
| 2645 | 2650 | } |
| 2646 | 2651 | |
| 2647 | 2652 | /***** Debug Functions *****/ |
| r21558 | r21559 | |
| 2660 | 2665 | popmessage MSG2; \ |
| 2661 | 2666 | } |
| 2662 | 2667 | |
| 2663 | | static UINT8 snes_dbg_video( running_machine &machine, UINT16 curline ) |
| 2668 | static UINT8 snes_dbg_video( running_machine &machine, UINT16 curline, UINT8 *ram_ptr ) |
| 2664 | 2669 | { |
| 2665 | 2670 | int i; |
| 2666 | 2671 | UINT8 toggles = machine.root_device().ioport("DEBUG1")->read_safe(0); |
| r21558 | r21559 | |
| 2695 | 2700 | logerror("%s", debug_options.windows_disabled?" ":"W"); |
| 2696 | 2701 | logerror("%s1 %s%s%s%s%s%c%s%s%d%s %d %4X %4X", |
| 2697 | 2702 | debug_options.bg_disabled[0]?" ":"*", |
| 2698 | | (snes_ram[TM] & 0x1)?"M":" ", |
| 2699 | | (snes_ram[TS] & 0x1)?"S":" ", |
| 2700 | | (snes_ram[CGADSUB] & 0x1)?"B":" ", |
| 2701 | | (snes_ram[TMW] & 0x1)?"m":" ", |
| 2702 | | (snes_ram[TSW] & 0x1)?"s":" ", |
| 2703 | | WINLOGIC[(snes_ram[WBGLOG] & 0x3)], |
| 2704 | | (snes_ram[W12SEL] & 0x2)?((snes_ram[W12SEL] & 0x1)?"o":"i"):" ", |
| 2705 | | (snes_ram[W12SEL] & 0x8)?((snes_ram[W12SEL] & 0x4)?"o":"i"):" ", |
| 2706 | | snes_ppu.layer[SNES_BG1].tile_size + 1, |
| 2707 | | (snes_ram[MOSAIC] & 0x1)?"m":" ", |
| 2708 | | snes_ram[BG1SC] & 0x3, |
| 2709 | | (snes_ram[BG1SC] & 0xfc) << 9, |
| 2710 | | snes_ppu.layer[SNES_BG1].charmap << 13); |
| 2703 | (ram_ptr[TM] & 0x1)?"M":" ", |
| 2704 | (ram_ptr[TS] & 0x1)?"S":" ", |
| 2705 | (ram_ptr[CGADSUB] & 0x1)?"B":" ", |
| 2706 | (ram_ptr[TMW] & 0x1)?"m":" ", |
| 2707 | (ram_ptr[TSW] & 0x1)?"s":" ", |
| 2708 | WINLOGIC[(ram_ptr[WBGLOG] & 0x3)], |
| 2709 | (ram_ptr[W12SEL] & 0x2)?((ram_ptr[W12SEL] & 0x1)?"o":"i"):" ", |
| 2710 | (ram_ptr[W12SEL] & 0x8)?((ram_ptr[W12SEL] & 0x4)?"o":"i"):" ", |
| 2711 | m_layer[SNES_BG1].tile_size + 1, |
| 2712 | (ram_ptr[MOSAIC] & 0x1)?"m":" ", |
| 2713 | ram_ptr[BG1SC] & 0x3, |
| 2714 | (ram_ptr[BG1SC] & 0xfc) << 9, |
| 2715 | m_layer[SNES_BG1].charmap << 13); |
| 2711 | 2716 | logerror("%s2 %s%s%s%s%s%c%s%s%d%s %d %4X %4X", |
| 2712 | 2717 | debug_options.bg_disabled[1]?" ":"*", |
| 2713 | | (snes_ram[TM] & 0x2)?"M":" ", |
| 2714 | | (snes_ram[TS] & 0x2)?"S":" ", |
| 2715 | | (snes_ram[CGADSUB] & 0x2)?"B":" ", |
| 2716 | | (snes_ram[TMW] & 0x2)?"m":" ", |
| 2717 | | (snes_ram[TSW] & 0x2)?"s":" ", |
| 2718 | | WINLOGIC[(snes_ram[WBGLOG] & 0xc) >> 2], |
| 2719 | | (snes_ram[W12SEL] & 0x20)?((snes_ram[W12SEL] & 0x10)?"o":"i"):" ", |
| 2720 | | (snes_ram[W12SEL] & 0x80)?((snes_ram[W12SEL] & 0x40)?"o":"i"):" ", |
| 2721 | | snes_ppu.layer[SNES_BG2].tile_size + 1, |
| 2722 | | (snes_ram[MOSAIC] & 0x2)?"m":" ", |
| 2723 | | snes_ram[BG2SC] & 0x3, |
| 2724 | | (snes_ram[BG2SC] & 0xfc) << 9, |
| 2725 | | snes_ppu.layer[SNES_BG2].charmap << 13); |
| 2718 | (ram_ptr[TM] & 0x2)?"M":" ", |
| 2719 | (ram_ptr[TS] & 0x2)?"S":" ", |
| 2720 | (ram_ptr[CGADSUB] & 0x2)?"B":" ", |
| 2721 | (ram_ptr[TMW] & 0x2)?"m":" ", |
| 2722 | (ram_ptr[TSW] & 0x2)?"s":" ", |
| 2723 | WINLOGIC[(ram_ptr[WBGLOG] & 0xc) >> 2], |
| 2724 | (ram_ptr[W12SEL] & 0x20)?((ram_ptr[W12SEL] & 0x10)?"o":"i"):" ", |
| 2725 | (ram_ptr[W12SEL] & 0x80)?((ram_ptr[W12SEL] & 0x40)?"o":"i"):" ", |
| 2726 | m_layer[SNES_BG2].tile_size + 1, |
| 2727 | (ram_ptr[MOSAIC] & 0x2)?"m":" ", |
| 2728 | ram_ptr[BG2SC] & 0x3, |
| 2729 | (ram_ptr[BG2SC] & 0xfc) << 9, |
| 2730 | m_layer[SNES_BG2].charmap << 13); |
| 2726 | 2731 | logerror("%s3 %s%s%s%s%s%c%s%s%d%s%s%d %4X %4X", |
| 2727 | 2732 | debug_options.bg_disabled[2]?" ":"*", |
| 2728 | | (snes_ram[TM] & 0x4)?"M":" ", |
| 2729 | | (snes_ram[TS] & 0x4)?"S":" ", |
| 2730 | | (snes_ram[CGADSUB] & 0x4)?"B":" ", |
| 2731 | | (snes_ram[TMW] & 0x4)?"m":" ", |
| 2732 | | (snes_ram[TSW] & 0x4)?"s":" ", |
| 2733 | | WINLOGIC[(snes_ram[WBGLOG] & 0x30)>>4], |
| 2734 | | (snes_ram[W34SEL] & 0x2)?((snes_ram[W34SEL] & 0x1)?"o":"i"):" ", |
| 2735 | | (snes_ram[W34SEL] & 0x8)?((snes_ram[W34SEL] & 0x4)?"o":"i"):" ", |
| 2736 | | snes_ppu.layer[SNES_BG3].tile_size + 1, |
| 2737 | | (snes_ram[MOSAIC] & 0x4)?"m":" ", |
| 2738 | | (snes_ram[BGMODE] & 0x8)?"P":" ", |
| 2739 | | snes_ram[BG3SC] & 0x3, |
| 2740 | | (snes_ram[BG3SC] & 0xfc) << 9, |
| 2741 | | snes_ppu.layer[SNES_BG3].charmap << 13); |
| 2733 | (ram_ptr[TM] & 0x4)?"M":" ", |
| 2734 | (ram_ptr[TS] & 0x4)?"S":" ", |
| 2735 | (ram_ptr[CGADSUB] & 0x4)?"B":" ", |
| 2736 | (ram_ptr[TMW] & 0x4)?"m":" ", |
| 2737 | (ram_ptr[TSW] & 0x4)?"s":" ", |
| 2738 | WINLOGIC[(ram_ptr[WBGLOG] & 0x30)>>4], |
| 2739 | (ram_ptr[W34SEL] & 0x2)?((ram_ptr[W34SEL] & 0x1)?"o":"i"):" ", |
| 2740 | (ram_ptr[W34SEL] & 0x8)?((ram_ptr[W34SEL] & 0x4)?"o":"i"):" ", |
| 2741 | m_layer[SNES_BG3].tile_size + 1, |
| 2742 | (ram_ptr[MOSAIC] & 0x4)?"m":" ", |
| 2743 | (ram_ptr[BGMODE] & 0x8)?"P":" ", |
| 2744 | ram_ptr[BG3SC] & 0x3, |
| 2745 | (ram_ptr[BG3SC] & 0xfc) << 9, |
| 2746 | m_layer[SNES_BG3].charmap << 13); |
| 2742 | 2747 | logerror("%s4 %s%s%s%s%s%c%s%s%d%s %d %4X %4X", |
| 2743 | 2748 | debug_options.bg_disabled[3]?" ":"*", |
| 2744 | | (snes_ram[TM] & 0x8)?"M":" ", |
| 2745 | | (snes_ram[TS] & 0x8)?"S":" ", |
| 2746 | | (snes_ram[CGADSUB] & 0x8)?"B":" ", |
| 2747 | | (snes_ram[TMW] & 0x8)?"m":" ", |
| 2748 | | (snes_ram[TSW] & 0x8)?"s":" ", |
| 2749 | | WINLOGIC[(snes_ram[WBGLOG] & 0xc0)>>6], |
| 2750 | | (snes_ram[W34SEL] & 0x20)?((snes_ram[W34SEL] & 0x10)?"o":"i"):" ", |
| 2751 | | (snes_ram[W34SEL] & 0x80)?((snes_ram[W34SEL] & 0x40)?"o":"i"):" ", |
| 2752 | | snes_ppu.layer[SNES_BG4].tile_size + 1, |
| 2753 | | (snes_ram[MOSAIC] & 0x8)?"m":" ", |
| 2754 | | snes_ram[BG4SC] & 0x3, |
| 2755 | | (snes_ram[BG4SC] & 0xfc) << 9, |
| 2756 | | snes_ppu.layer[SNES_BG4].charmap << 13 ); |
| 2749 | (ram_ptr[TM] & 0x8)?"M":" ", |
| 2750 | (ram_ptr[TS] & 0x8)?"S":" ", |
| 2751 | (ram_ptr[CGADSUB] & 0x8)?"B":" ", |
| 2752 | (ram_ptr[TMW] & 0x8)?"m":" ", |
| 2753 | (ram_ptr[TSW] & 0x8)?"s":" ", |
| 2754 | WINLOGIC[(ram_ptr[WBGLOG] & 0xc0)>>6], |
| 2755 | (ram_ptr[W34SEL] & 0x20)?((ram_ptr[W34SEL] & 0x10)?"o":"i"):" ", |
| 2756 | (ram_ptr[W34SEL] & 0x80)?((ram_ptr[W34SEL] & 0x40)?"o":"i"):" ", |
| 2757 | m_layer[SNES_BG4].tile_size + 1, |
| 2758 | (ram_ptr[MOSAIC] & 0x8)?"m":" ", |
| 2759 | ram_ptr[BG4SC] & 0x3, |
| 2760 | (ram_ptr[BG4SC] & 0xfc) << 9, |
| 2761 | m_layer[SNES_BG4].charmap << 13 ); |
| 2757 | 2762 | logerror("%sO %s%s%s%s%s%c%s%s %4X", |
| 2758 | 2763 | debug_options.bg_disabled[4]?" ":"*", |
| 2759 | | (snes_ram[TM] & 0x10)?"M":" ", |
| 2760 | | (snes_ram[TS] & 0x10)?"S":" ", |
| 2761 | | (snes_ram[CGADSUB] & 0x10)?"B":" ", |
| 2762 | | (snes_ram[TMW] & 0x10)?"m":" ", |
| 2763 | | (snes_ram[TSW] & 0x10)?"s":" ", |
| 2764 | | WINLOGIC[(snes_ram[WOBJLOG] & 0x3)], |
| 2765 | | (snes_ram[WOBJSEL] & 0x2)?((snes_ram[WOBJSEL] & 0x1)?"o":"i"):" ", |
| 2766 | | (snes_ram[WOBJSEL] & 0x8)?((snes_ram[WOBJSEL] & 0x4)?"o":"i"):" ", |
| 2767 | | snes_ppu.layer[SNES_OAM].charmap << 13 ); |
| 2764 | (ram_ptr[TM] & 0x10)?"M":" ", |
| 2765 | (ram_ptr[TS] & 0x10)?"S":" ", |
| 2766 | (ram_ptr[CGADSUB] & 0x10)?"B":" ", |
| 2767 | (ram_ptr[TMW] & 0x10)?"m":" ", |
| 2768 | (ram_ptr[TSW] & 0x10)?"s":" ", |
| 2769 | WINLOGIC[(ram_ptr[WOBJLOG] & 0x3)], |
| 2770 | (ram_ptr[WOBJSEL] & 0x2)?((ram_ptr[WOBJSEL] & 0x1)?"o":"i"):" ", |
| 2771 | (ram_ptr[WOBJSEL] & 0x8)?((ram_ptr[WOBJSEL] & 0x4)?"o":"i"):" ", |
| 2772 | m_layer[SNES_OAM].charmap << 13 ); |
| 2768 | 2773 | logerror("%sB %s %c%s%s", |
| 2769 | 2774 | debug_options.colormath_disabled?" ":"*", |
| 2770 | | (snes_ram[CGADSUB] & 0x20)?"B":" ", |
| 2771 | | WINLOGIC[(snes_ram[WOBJLOG] & 0xc)>>2], |
| 2772 | | (snes_ram[WOBJSEL] & 0x20)?((snes_ram[WOBJSEL] & 0x10)?"o":"i"):" ", |
| 2773 | | (snes_ram[WOBJSEL] & 0x80)?((snes_ram[WOBJSEL] & 0x40)?"o":"i"):" " ); |
| 2774 | | logerror("1) %3d %3d 2) %3d %3d", (snes_ppu.bgd_offset.horizontal[0] & 0x3ff) >> 3, (snes_ppu.bgd_offset.vertical[0] & 0x3ff) >> 3, (snes_ppu.bgd_offset.horizontal[1] & 0x3ff) >> 3, (snes_ppu.bgd_offset.vertical[1] & 0x3ff) >> 3 ); |
| 2775 | | logerror("3) %3d %3d 4) %3d %3d", (snes_ppu.bgd_offset.horizontal[2] & 0x3ff) >> 3, (snes_ppu.bgd_offset.vertical[2] & 0x3ff) >> 3, (snes_ppu.bgd_offset.horizontal[3] & 0x3ff) >> 3, (snes_ppu.bgd_offset.vertical[3] & 0x3ff) >> 3 ); |
| 2776 | | logerror("Flags: %s%s%s %s %2d", (snes_ram[CGWSEL] & 0x2)?"S":"F", (snes_ram[CGADSUB] & 0x80)?"-":"+", (snes_ram[CGADSUB] & 0x40)?" 50%":"100%",(snes_ram[CGWSEL] & 0x1)?"D":"P", (snes_ram[MOSAIC] & 0xf0) >> 4 ); |
| 2777 | | logerror("SetINI: %s %s %s %s %s %s", (snes_ram[SETINI] & 0x1)?" I":"NI", (snes_ram[SETINI] & 0x2)?"P":"R", (snes_ram[SETINI] & 0x4)?"240":"225",(snes_ram[SETINI] & 0x8)?"512":"256",(snes_ram[SETINI] & 0x40)?"E":"N",(snes_ram[SETINI] & 0x80)?"ES":"NS" ); |
| 2778 | | logerror("Mode7: A %5d B %5d", snes_ppu.mode7.matrix_a, snes_ppu.mode7.matrix_b ); |
| 2779 | | logerror(" %s%s%s C %5d D %5d", (snes_ram[M7SEL] & 0xc0)?((snes_ram[M7SEL] & 0x40)?"0":"C"):"R", (snes_ram[M7SEL] & 0x1)?"H":" ", (snes_ram[M7SEL] & 0x2)?"V":" ", snes_ppu.mode7.matrix_c, snes_ppu.mode7.matrix_d ); |
| 2780 | | logerror(" X %5d Y %5d", snes_ppu.mode7.origin_x, snes_ppu.mode7.origin_y ); |
| 2775 | (ram_ptr[CGADSUB] & 0x20)?"B":" ", |
| 2776 | WINLOGIC[(ram_ptr[WOBJLOG] & 0xc)>>2], |
| 2777 | (ram_ptr[WOBJSEL] & 0x20)?((ram_ptr[WOBJSEL] & 0x10)?"o":"i"):" ", |
| 2778 | (ram_ptr[WOBJSEL] & 0x80)?((ram_ptr[WOBJSEL] & 0x40)?"o":"i"):" " ); |
| 2779 | logerror("1) %3d %3d 2) %3d %3d", (m_bgd_offset.horizontal[0] & 0x3ff) >> 3, (m_bgd_offset.vertical[0] & 0x3ff) >> 3, (m_bgd_offset.horizontal[1] & 0x3ff) >> 3, (m_bgd_offset.vertical[1] & 0x3ff) >> 3 ); |
| 2780 | logerror("3) %3d %3d 4) %3d %3d", (m_bgd_offset.horizontal[2] & 0x3ff) >> 3, (m_bgd_offset.vertical[2] & 0x3ff) >> 3, (m_bgd_offset.horizontal[3] & 0x3ff) >> 3, (m_bgd_offset.vertical[3] & 0x3ff) >> 3 ); |
| 2781 | logerror("Flags: %s%s%s %s %2d", (ram_ptr[CGWSEL] & 0x2)?"S":"F", (ram_ptr[CGADSUB] & 0x80)?"-":"+", (ram_ptr[CGADSUB] & 0x40)?" 50%":"100%",(ram_ptr[CGWSEL] & 0x1)?"D":"P", (ram_ptr[MOSAIC] & 0xf0) >> 4 ); |
| 2782 | logerror("SetINI: %s %s %s %s %s %s", (ram_ptr[SETINI] & 0x1)?" I":"NI", (ram_ptr[SETINI] & 0x2)?"P":"R", (ram_ptr[SETINI] & 0x4)?"240":"225",(ram_ptr[SETINI] & 0x8)?"512":"256",(ram_ptr[SETINI] & 0x40)?"E":"N",(ram_ptr[SETINI] & 0x80)?"ES":"NS" ); |
| 2783 | logerror("Mode7: A %5d B %5d", m_mode7.matrix_a, m_mode7.matrix_b ); |
| 2784 | logerror(" %s%s%s C %5d D %5d", (ram_ptr[M7SEL] & 0xc0)?((ram_ptr[M7SEL] & 0x40)?"0":"C"):"R", (ram_ptr[M7SEL] & 0x1)?"H":" ", (ram_ptr[M7SEL] & 0x2)?"V":" ", m_mode7.matrix_c, m_mode7.matrix_d ); |
| 2785 | logerror(" X %5d Y %5d", m_mode7.origin_x, m_mode7.origin_y ); |
| 2781 | 2786 | } |
| 2782 | 2787 | #endif |
| 2783 | 2788 | |