branches/new_menus/src/emu/video/snes_ppu.c
| r0 | r29544 | |
| 1 | /*************************************************************************** |
| 2 | |
| 3 | snes.c |
| 4 | |
| 5 | Video file to handle emulation of the Nintendo Super NES. |
| 6 | |
| 7 | Anthony Kruize |
| 8 | Based on the original code by Lee Hammerton (aka Savoury Snax) |
| 9 | |
| 10 | Some notes on the snes video hardware: |
| 11 | |
| 12 | Object Attribute Memory(OAM) is made up of 128 blocks of 32 bits, followed |
| 13 | by 128 blocks of 2 bits. The format for each block is: |
| 14 | -First Block---------------------------------------------------------------- |
| 15 | | x pos | y pos |char no.| v flip | h flip |priority|palette |char no msb| |
| 16 | +--------+--------+--------+--------+--------+--------+--------+-----------+ |
| 17 | | 8 bits | 8 bits | 8 bits | 1 bit | 1 bit | 2 bits | 3 bits | 1 bit | |
| 18 | -Second Block--------------------------------------------------------------- |
| 19 | | size | x pos msb | |
| 20 | +-------+-----------+ |
| 21 | | 1 bit | 1 bit | |
| 22 | --------------------- |
| 23 | |
| 24 | Video RAM contains information for character data and screen maps. |
| 25 | Screen maps are made up of 32 x 32 blocks of 16 bits each. |
| 26 | The format for each block is: |
| 27 | ---------------------------------------------- |
| 28 | | v flip | x flip |priority|palette |char no.| |
| 29 | +--------+--------+--------+--------+--------+ |
| 30 | | 1 bit | 1 bit | 1 bit | 3 bits |10 bits | |
| 31 | ---------------------------------------------- |
| 32 | Mode 7 is stored differently. Character data and screen map are interleaved. |
| 33 | There are two formats: |
| 34 | -Normal----------------- -EXTBG----------------------------- |
| 35 | | char data | char no. | | priority | char data | char no. | |
| 36 | +-----------+----------+ +----------+-----------+----------+ |
| 37 | | 8 bits | 8 bits | | 1 bit | 7 bits | 8 bits | |
| 38 | ------------------------ ----------------------------------- |
| 39 | |
| 40 | The screen layers are drawn with the following priorities (updated info courtesy of byuu): |
| 41 | |
| 42 | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | |
| 43 | ------------------------------------------------------------------------------------------------------------- |
| 44 | | Mode 0 | BG4B | BG3B | OAM0 | BG4A | BG3A | OAM1 | BG2B | BG1B | OAM2 | BG2A | BG1A | OAM3 | |
| 45 | ------------------------------------------------------------------------------------------------------------- |
| 46 | | Mode 1 (*)| BG3B | OAM0 | OAM1 | BG2B | BG1B | OAM2 | BG2A | BG1A | OAM3 | BG3A | | | |
| 47 | ------------------------------------------------------------------------------------------------------------- |
| 48 | | Mode 1 (!)| BG3B | OAM0 | BG3A | OAM1 | BG2B | BG1B | OAM2 | BG2A | BG1A | OAM3 | | | |
| 49 | ------------------------------------------------------------------------------------------------------------- |
| 50 | | Mode 2 | BG2B | OAM0 | BG1B | OAM1 | BG2A | OAM2 | BG1A | OAM3 | | | | | |
| 51 | ------------------------------------------------------------------------------------------------------------- |
| 52 | | Mode 3 | BG2B | OAM0 | BG1B | OAM1 | BG2A | OAM2 | BG1A | OAM3 | | | | | |
| 53 | ------------------------------------------------------------------------------------------------------------- |
| 54 | | Mode 4 | BG2B | OAM0 | BG1B | OAM1 | BG2A | OAM2 | BG1A | OAM3 | | | | | |
| 55 | ------------------------------------------------------------------------------------------------------------- |
| 56 | | Mode 5 | BG2B | OAM0 | BG1B | OAM1 | BG2A | OAM2 | BG1A | OAM3 | | | | | |
| 57 | ------------------------------------------------------------------------------------------------------------- |
| 58 | | Mode 6 | OAM0 | BG1B | OAM1 | OAM2 | BG1A | OAM3 | | | | | | | |
| 59 | ------------------------------------------------------------------------------------------------------------- |
| 60 | | Mode 7 (+)| OAM0 | BG1n | OAM1 | OAM2 | OAM3 | | | | | | | | |
| 61 | ------------------------------------------------------------------------------------------------------------- |
| 62 | | Mode 7 (-)| BG2B | OAM0 | BG1n | OAM1 | BG2A | OAM2 | OAM3 | | | | | | |
| 63 | ------------------------------------------------------------------------------------------------------------- |
| 64 | |
| 65 | Where: |
| 66 | - Mode 1 (*) is Mode 1 with bg3_pty = 1 |
| 67 | - Mode 1 (!) is Mode 1 with bg3_pty = 0 |
| 68 | - Mode 7 (+) is base Mode 7 |
| 69 | - Mode 7 (-) is Mode 7 EXTBG |
| 70 | |
| 71 | ***************************************************************************/ |
| 72 | |
| 73 | #include "emu.h" |
| 74 | #include "video/snes_ppu.h" |
| 75 | |
| 76 | #define SNES_MAINSCREEN 0 |
| 77 | #define SNES_SUBSCREEN 1 |
| 78 | #define SNES_CLIP_NEVER 0 |
| 79 | #define SNES_CLIP_IN 1 |
| 80 | #define SNES_CLIP_OUT 2 |
| 81 | #define SNES_CLIP_ALWAYS 3 |
| 82 | |
| 83 | #define SNES_VRAM_SIZE 0x20000 /* 128kb of video ram */ |
| 84 | #define SNES_CGRAM_SIZE 0x202 /* 256 16-bit colours + 1 tacked on 16-bit colour for fixed colour */ |
| 85 | #define SNES_OAM_SIZE 0x440 /* 1088 bytes of Object Attribute Memory */ |
| 86 | #define FIXED_COLOUR 256 /* Position in cgram for fixed colour */ |
| 87 | |
| 88 | |
| 89 | /* Definitions for PPU Memory-Mapped registers */ |
| 90 | #define INIDISP 0x2100 |
| 91 | #define OBSEL 0x2101 |
| 92 | #define OAMADDL 0x2102 |
| 93 | #define OAMADDH 0x2103 |
| 94 | #define OAMDATA 0x2104 |
| 95 | #define BGMODE 0x2105 /* abcdefff = abcd: bg4-1 tile size | e: BG3 high priority | f: mode */ |
| 96 | #define MOSAIC 0x2106 /* xxxxabcd = x: pixel size | abcd: affects bg 1-4 */ |
| 97 | #define BG1SC 0x2107 |
| 98 | #define BG2SC 0x2108 |
| 99 | #define BG3SC 0x2109 |
| 100 | #define BG4SC 0x210A |
| 101 | #define BG12NBA 0x210B |
| 102 | #define BG34NBA 0x210C |
| 103 | #define BG1HOFS 0x210D |
| 104 | #define BG1VOFS 0x210E |
| 105 | #define BG2HOFS 0x210F |
| 106 | #define BG2VOFS 0x2110 |
| 107 | #define BG3HOFS 0x2111 |
| 108 | #define BG3VOFS 0x2112 |
| 109 | #define BG4HOFS 0x2113 |
| 110 | #define BG4VOFS 0x2114 |
| 111 | #define VMAIN 0x2115 /* i---ffrr = i: Increment timing | f: Full graphic | r: increment rate */ |
| 112 | #define VMADDL 0x2116 /* aaaaaaaa = a: LSB of vram address */ |
| 113 | #define VMADDH 0x2117 /* aaaaaaaa = a: MSB of vram address */ |
| 114 | #define VMDATAL 0x2118 /* dddddddd = d: data to be written */ |
| 115 | #define VMDATAH 0x2119 /* dddddddd = d: data to be written */ |
| 116 | #define M7SEL 0x211A /* ab----yx = a: screen over | y: vertical flip | x: horizontal flip */ |
| 117 | #define M7A 0x211B /* aaaaaaaa = a: COSINE rotate angle / X expansion */ |
| 118 | #define M7B 0x211C /* aaaaaaaa = a: SINE rotate angle / X expansion */ |
| 119 | #define M7C 0x211D /* aaaaaaaa = a: SINE rotate angle / Y expansion */ |
| 120 | #define M7D 0x211E /* aaaaaaaa = a: COSINE rotate angle / Y expansion */ |
| 121 | #define M7X 0x211F |
| 122 | #define M7Y 0x2120 |
| 123 | #define CGADD 0x2121 |
| 124 | #define CGDATA 0x2122 |
| 125 | #define W12SEL 0x2123 |
| 126 | #define W34SEL 0x2124 |
| 127 | #define WOBJSEL 0x2125 |
| 128 | #define WH0 0x2126 /* pppppppp = p: Left position of window 1 */ |
| 129 | #define WH1 0x2127 /* pppppppp = p: Right position of window 1 */ |
| 130 | #define WH2 0x2128 /* pppppppp = p: Left position of window 2 */ |
| 131 | #define WH3 0x2129 /* pppppppp = p: Right position of window 2 */ |
| 132 | #define WBGLOG 0x212A /* aabbccdd = a: BG4 params | b: BG3 params | c: BG2 params | d: BG1 params */ |
| 133 | #define WOBJLOG 0x212B /* ----ccoo = c: Colour window params | o: Object window params */ |
| 134 | #define TM 0x212C |
| 135 | #define TS 0x212D |
| 136 | #define TMW 0x212E |
| 137 | #define TSW 0x212F |
| 138 | #define CGWSEL 0x2130 |
| 139 | #define CGADSUB 0x2131 |
| 140 | #define COLDATA 0x2132 |
| 141 | #define SETINI 0x2133 |
| 142 | #define MPYL 0x2134 |
| 143 | #define MPYM 0x2135 |
| 144 | #define MPYH 0x2136 |
| 145 | #define SLHV 0x2137 |
| 146 | #define ROAMDATA 0x2138 |
| 147 | #define RVMDATAL 0x2139 |
| 148 | #define RVMDATAH 0x213A |
| 149 | #define RCGDATA 0x213B |
| 150 | #define OPHCT 0x213C |
| 151 | #define OPVCT 0x213D |
| 152 | #define STAT77 0x213E |
| 153 | #define STAT78 0x213F |
| 154 | |
| 155 | |
| 156 | #if SNES_LAYER_DEBUG |
| 157 | /* red green blue purple yellow cyan grey white */ |
| 158 | static const UINT16 dbg_mode_colours[8] = { 0x1f, 0x3e0, 0x7c00, 0x7c1f, 0x3ff, 0x7fe0, 0x4210, 0x7fff }; |
| 159 | #endif /* SNES_LAYER_DEBUG */ |
| 160 | |
| 161 | static const UINT16 table_obj_offset[8][8] = |
| 162 | { |
| 163 | { (0*32), (0*32)+32, (0*32)+64, (0*32)+96, (0*32)+128, (0*32)+160, (0*32)+192, (0*32)+224 }, |
| 164 | { (16*32), (16*32)+32, (16*32)+64, (16*32)+96, (16*32)+128, (16*32)+160, (16*32)+192, (16*32)+224 }, |
| 165 | { (32*32), (32*32)+32, (32*32)+64, (32*32)+96, (32*32)+128, (32*32)+160, (32*32)+192, (32*32)+224 }, |
| 166 | { (48*32), (48*32)+32, (48*32)+64, (48*32)+96, (48*32)+128, (48*32)+160, (48*32)+192, (48*32)+224 }, |
| 167 | { (64*32), (64*32)+32, (64*32)+64, (64*32)+96, (64*32)+128, (64*32)+160, (64*32)+192, (64*32)+224 }, |
| 168 | { (80*32), (80*32)+32, (80*32)+64, (80*32)+96, (80*32)+128, (80*32)+160, (80*32)+192, (80*32)+224 }, |
| 169 | { (96*32), (96*32)+32, (96*32)+64, (96*32)+96, (96*32)+128, (96*32)+160, (96*32)+192, (96*32)+224 }, |
| 170 | { (112*32), (112*32)+32, (112*32)+64, (112*32)+96, (112*32)+128, (112*32)+160, (112*32)+192, (112*32)+224 } |
| 171 | }; |
| 172 | |
| 173 | |
| 174 | enum |
| 175 | { |
| 176 | SNES_COLOR_DEPTH_2BPP = 0, |
| 177 | SNES_COLOR_DEPTH_4BPP, |
| 178 | SNES_COLOR_DEPTH_8BPP |
| 179 | }; |
| 180 | |
| 181 | |
| 182 | #define PPU_REG(a) m_regs[a - 0x2100] |
| 183 | |
| 184 | |
| 185 | |
| 186 | //************************************************************************** |
| 187 | // DEVICE DEFINITIONS |
| 188 | //************************************************************************** |
| 189 | |
| 190 | const device_type SNES_PPU = &device_creator<snes_ppu_device>; |
| 191 | |
| 192 | |
| 193 | //************************************************************************** |
| 194 | // live device |
| 195 | //************************************************************************** |
| 196 | |
| 197 | //------------------------------------------------- |
| 198 | // snes_ppu_device - constructor |
| 199 | //------------------------------------------------- |
| 200 | |
| 201 | snes_ppu_device::snes_ppu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 202 | : device_t(mconfig, SNES_PPU, "SNES PPU", tag, owner, clock, "snes_ppu", __FILE__), |
| 203 | device_video_interface(mconfig, *this), |
| 204 | m_openbus_cb(*this) |
| 205 | { |
| 206 | } |
| 207 | |
| 208 | |
| 209 | //------------------------------------------------- |
| 210 | // device_start - device-specific startup |
| 211 | //------------------------------------------------- |
| 212 | |
| 213 | void snes_ppu_device::device_start() |
| 214 | { |
| 215 | m_openbus_cb.resolve_safe(0); |
| 216 | |
| 217 | #if SNES_LAYER_DEBUG |
| 218 | memset(&m_debug_options, 0, sizeof(m_debug_options)); |
| 219 | #endif |
| 220 | |
| 221 | m_vram = auto_alloc_array(machine(), UINT8, SNES_VRAM_SIZE); |
| 222 | m_cgram = auto_alloc_array(machine(), UINT16, SNES_CGRAM_SIZE/2); |
| 223 | m_oam_ram = auto_alloc_array(machine(), UINT16, SNES_OAM_SIZE/2); |
| 224 | |
| 225 | /* Inititialize registers/variables */ |
| 226 | m_update_windows = 1; |
| 227 | m_beam.latch_vert = 0; |
| 228 | m_beam.latch_horz = 0; |
| 229 | m_beam.current_vert = 0; |
| 230 | m_beam.current_horz = 0; |
| 231 | m_beam.last_visible_line = 225; /* TODO: PAL setting */ |
| 232 | m_mode = 0; |
| 233 | m_ppu1_version = 1; // 5C77 chip version number, read by STAT77, only '1' is known |
| 234 | m_ppu2_version = 3; // 5C78 chip version number, read by STAT78, only '2' & '3' encountered so far. |
| 235 | |
| 236 | m_cgram_address = 0; |
| 237 | m_read_ophct = 0; |
| 238 | m_read_opvct = 0; |
| 239 | |
| 240 | PPU_REG(VMAIN) = 0x80; |
| 241 | // what about other regs? |
| 242 | |
| 243 | /* Inititialize mosaic table */ |
| 244 | for (int j = 0; j < 16; j++) |
| 245 | { |
| 246 | for (int i = 0; i < 4096; i++) |
| 247 | m_mosaic_table[j][i] = (i / (j + 1)) * (j + 1); |
| 248 | } |
| 249 | |
| 250 | /* Init VRAM */ |
| 251 | memset(m_vram, 0, SNES_VRAM_SIZE); |
| 252 | |
| 253 | /* Init Palette RAM */ |
| 254 | memset((UINT8 *)m_cgram, 0, SNES_CGRAM_SIZE); |
| 255 | |
| 256 | /* Init oam RAM */ |
| 257 | memset((UINT8 *)m_oam_ram, 0xff, SNES_OAM_SIZE); |
| 258 | |
| 259 | for (int i = 0; i < 2; i++) |
| 260 | { |
| 261 | save_item(NAME(m_scanlines[i].enable), i); |
| 262 | save_item(NAME(m_scanlines[i].clip), i); |
| 263 | save_item(NAME(m_scanlines[i].buffer), i); |
| 264 | save_item(NAME(m_scanlines[i].priority), i); |
| 265 | save_item(NAME(m_scanlines[i].layer), i); |
| 266 | save_item(NAME(m_scanlines[i].blend_exception), i); |
| 267 | } |
| 268 | |
| 269 | for (int i = 0; i < 6; i++) |
| 270 | { |
| 271 | save_item(NAME(m_layer[i].window1_enabled), i); |
| 272 | save_item(NAME(m_layer[i].window1_invert), i); |
| 273 | save_item(NAME(m_layer[i].window2_enabled), i); |
| 274 | save_item(NAME(m_layer[i].window2_invert), i); |
| 275 | save_item(NAME(m_layer[i].wlog_mask), i); |
| 276 | save_item(NAME(m_layer[i].color_math), i); |
| 277 | save_item(NAME(m_layer[i].charmap), i); |
| 278 | save_item(NAME(m_layer[i].tilemap), i); |
| 279 | save_item(NAME(m_layer[i].tilemap_size), i); |
| 280 | save_item(NAME(m_layer[i].tile_size), i); |
| 281 | save_item(NAME(m_layer[i].mosaic_enabled), i); |
| 282 | save_item(NAME(m_layer[i].main_window_enabled), i); |
| 283 | save_item(NAME(m_layer[i].sub_window_enabled), i); |
| 284 | save_item(NAME(m_layer[i].main_bg_enabled), i); |
| 285 | save_item(NAME(m_layer[i].sub_bg_enabled), i); |
| 286 | save_item(NAME(m_layer[i].hoffs), i); |
| 287 | save_item(NAME(m_layer[i].voffs), i); |
| 288 | |
| 289 | save_item(NAME(m_clipmasks[i]), i); |
| 290 | } |
| 291 | |
| 292 | save_item(NAME(m_oam.address_low)); |
| 293 | save_item(NAME(m_oam.address_high)); |
| 294 | save_item(NAME(m_oam.saved_address_low)); |
| 295 | save_item(NAME(m_oam.saved_address_high)); |
| 296 | save_item(NAME(m_oam.address)); |
| 297 | save_item(NAME(m_oam.priority_rotation)); |
| 298 | save_item(NAME(m_oam.next_charmap)); |
| 299 | save_item(NAME(m_oam.next_size)); |
| 300 | save_item(NAME(m_oam.size)); |
| 301 | save_item(NAME(m_oam.next_name_select)); |
| 302 | save_item(NAME(m_oam.name_select)); |
| 303 | save_item(NAME(m_oam.first_sprite)); |
| 304 | save_item(NAME(m_oam.flip)); |
| 305 | save_item(NAME(m_oam.write_latch)); |
| 306 | |
| 307 | save_item(NAME(m_beam.latch_horz)); |
| 308 | save_item(NAME(m_beam.latch_vert)); |
| 309 | save_item(NAME(m_beam.current_horz)); |
| 310 | save_item(NAME(m_beam.current_vert)); |
| 311 | save_item(NAME(m_beam.last_visible_line)); |
| 312 | save_item(NAME(m_beam.interlace_count)); |
| 313 | |
| 314 | save_item(NAME(m_mode7.repeat)); |
| 315 | save_item(NAME(m_mode7.hflip)); |
| 316 | save_item(NAME(m_mode7.vflip)); |
| 317 | save_item(NAME(m_mode7.matrix_a)); |
| 318 | save_item(NAME(m_mode7.matrix_b)); |
| 319 | save_item(NAME(m_mode7.matrix_c)); |
| 320 | save_item(NAME(m_mode7.matrix_d)); |
| 321 | save_item(NAME(m_mode7.origin_x)); |
| 322 | save_item(NAME(m_mode7.origin_y)); |
| 323 | save_item(NAME(m_mode7.hor_offset)); |
| 324 | save_item(NAME(m_mode7.ver_offset)); |
| 325 | save_item(NAME(m_mode7.extbg)); |
| 326 | |
| 327 | save_item(NAME(m_mosaic_size)); |
| 328 | save_item(NAME(m_clip_to_black)); |
| 329 | save_item(NAME(m_prevent_color_math)); |
| 330 | save_item(NAME(m_sub_add_mode)); |
| 331 | save_item(NAME(m_bg3_priority_bit)); |
| 332 | save_item(NAME(m_direct_color)); |
| 333 | save_item(NAME(m_ppu_last_scroll)); |
| 334 | save_item(NAME(m_mode7_last_scroll)); |
| 335 | |
| 336 | save_item(NAME(m_ppu1_open_bus)); |
| 337 | save_item(NAME(m_ppu2_open_bus)); |
| 338 | save_item(NAME(m_ppu1_version)); |
| 339 | save_item(NAME(m_ppu2_version)); |
| 340 | save_item(NAME(m_window1_left)); |
| 341 | save_item(NAME(m_window1_right)); |
| 342 | save_item(NAME(m_window2_left)); |
| 343 | save_item(NAME(m_window2_right)); |
| 344 | |
| 345 | save_item(NAME(m_update_windows)); |
| 346 | save_item(NAME(m_update_offsets)); |
| 347 | save_item(NAME(m_update_oam_list)); |
| 348 | save_item(NAME(m_mode)); |
| 349 | save_item(NAME(m_interlace)); |
| 350 | save_item(NAME(m_obj_interlace)); |
| 351 | save_item(NAME(m_screen_brightness)); |
| 352 | save_item(NAME(m_screen_disabled)); |
| 353 | save_item(NAME(m_pseudo_hires)); |
| 354 | save_item(NAME(m_color_modes)); |
| 355 | save_item(NAME(m_stat77)); |
| 356 | save_item(NAME(m_stat78)); |
| 357 | |
| 358 | save_item(NAME(m_htmult)); |
| 359 | save_item(NAME(m_cgram_address)); |
| 360 | save_item(NAME(m_read_ophct)); |
| 361 | save_item(NAME(m_read_opvct)); |
| 362 | save_item(NAME(m_vram_fgr_high)); |
| 363 | save_item(NAME(m_vram_fgr_increment)); |
| 364 | save_item(NAME(m_vram_fgr_count)); |
| 365 | save_item(NAME(m_vram_fgr_mask)); |
| 366 | save_item(NAME(m_vram_fgr_shift)); |
| 367 | save_item(NAME(m_vram_read_buffer)); |
| 368 | save_item(NAME(m_vmadd)); |
| 369 | |
| 370 | save_item(NAME(m_regs)); |
| 371 | |
| 372 | save_pointer(NAME(m_vram), SNES_VRAM_SIZE); |
| 373 | save_pointer(NAME(m_cgram), SNES_CGRAM_SIZE/2); |
| 374 | save_pointer(NAME(m_oam_ram), SNES_OAM_SIZE/2); |
| 375 | } |
| 376 | |
| 377 | |
| 378 | |
| 379 | /***************************************** |
| 380 | * get_bgcolor() |
| 381 | * |
| 382 | * Get the proper color (direct or from cgram) |
| 383 | *****************************************/ |
| 384 | |
| 385 | inline UINT16 snes_ppu_device::get_bgcolor( UINT8 direct_colors, UINT16 palette, UINT8 color ) |
| 386 | { |
| 387 | UINT16 c = 0; |
| 388 | |
| 389 | if (direct_colors) |
| 390 | { |
| 391 | /* format is 0 | BBb00 | GGGg0 | RRRr0, HW confirms that the data is zero padded. */ |
| 392 | c = ((color & 0x07) << 2) | ((color & 0x38) << 4) | ((color & 0xc0) << 7); |
| 393 | c |= ((palette & 0x04) >> 1) | ((palette & 0x08) << 3) | ((palette & 0x10) << 8); |
| 394 | } |
| 395 | else |
| 396 | c = m_cgram[(palette + color) % FIXED_COLOUR]; |
| 397 | |
| 398 | return c; |
| 399 | } |
| 400 | |
| 401 | /***************************************** |
| 402 | * set_scanline_pixel() |
| 403 | * |
| 404 | * Store pixel color, priority, layer and |
| 405 | * color math exception (for OAM) in the |
| 406 | * proper scanline |
| 407 | *****************************************/ |
| 408 | |
| 409 | inline void snes_ppu_device::set_scanline_pixel( int screen, INT16 x, UINT16 color, UINT8 priority, UINT8 layer, int blend ) |
| 410 | { |
| 411 | m_scanlines[screen].buffer[x] = color; |
| 412 | m_scanlines[screen].priority[x] = priority; |
| 413 | m_scanlines[screen].layer[x] = layer; |
| 414 | m_scanlines[screen].blend_exception[x] = blend; |
| 415 | } |
| 416 | |
| 417 | /************************************************************************************************* |
| 418 | * SNES tiles |
| 419 | * |
| 420 | * The way vram is accessed to draw tiles is basically the same for both BG and OAM tiles. Main |
| 421 | * differences are bit planes (variable for BG and fixed for OAM) and a few details of the scanline |
| 422 | * output (since OAM has neither mosaic, nor hires, nor direct colors). |
| 423 | * Hence, we use a common function to take data from VRAM and then we call specific routines for |
| 424 | * OAM vs BG vs Hi-Res BG tiles. |
| 425 | *************************************************************************************************/ |
| 426 | |
| 427 | /***************************************** |
| 428 | * draw_bgtile_lores() |
| 429 | * draw_bgtile_hires() |
| 430 | * draw_oamtile_() |
| 431 | * |
| 432 | * Check if a pixel is clipped or not, and |
| 433 | * copy it to the scanline buffer when |
| 434 | * appropriate. The actual way to perform |
| 435 | * such operations depends on the source |
| 436 | * (BG or OAM) and on the resolution (hires |
| 437 | * or lores) |
| 438 | *****************************************/ |
| 439 | |
| 440 | inline void snes_ppu_device::draw_bgtile_lores( UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority ) |
| 441 | { |
| 442 | int screen; |
| 443 | UINT16 c; |
| 444 | |
| 445 | for (screen = SNES_MAINSCREEN; screen <= SNES_SUBSCREEN; screen++) |
| 446 | { |
| 447 | if (ii >= 0 && ii < SNES_SCR_WIDTH && m_scanlines[screen].enable) |
| 448 | { |
| 449 | if (m_scanlines[screen].priority[ii] <= priority) |
| 450 | { |
| 451 | UINT8 clr = colour; |
| 452 | UINT8 clipmask = m_clipmasks[layer][ii]; |
| 453 | |
| 454 | #if SNES_LAYER_DEBUG |
| 455 | if (m_debug_options.windows_disabled) |
| 456 | clipmask = 0xff; |
| 457 | #endif /* SNES_LAYER_DEBUG */ |
| 458 | |
| 459 | /* Clip to windows */ |
| 460 | if (m_scanlines[screen].clip) |
| 461 | clr &= clipmask; |
| 462 | |
| 463 | /* Only draw if we have a colour (0 == transparent) */ |
| 464 | if (clr) |
| 465 | { |
| 466 | c = get_bgcolor(direct_colors, pal, clr); |
| 467 | set_scanline_pixel(screen, ii, c, priority, layer, 0); |
| 468 | } |
| 469 | } |
| 470 | } |
| 471 | } |
| 472 | } |
| 473 | |
| 474 | inline void snes_ppu_device::draw_bgtile_hires( UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority ) |
| 475 | { |
| 476 | int screen; |
| 477 | UINT16 c; |
| 478 | |
| 479 | for (screen = SNES_MAINSCREEN; screen <= SNES_SUBSCREEN; screen++) |
| 480 | { |
| 481 | // odd pixels to main screen, even pixels to sub screen |
| 482 | if (ii >= 0 && ii < (SNES_SCR_WIDTH << 1) && ((ii & 1) ^ screen) && m_scanlines[screen].enable) |
| 483 | { |
| 484 | if (m_scanlines[screen].priority[ii >> 1] <= priority) |
| 485 | { |
| 486 | UINT8 clr = colour; |
| 487 | UINT8 clipmask = m_clipmasks[layer][ii >> 1]; |
| 488 | |
| 489 | #if SNES_LAYER_DEBUG |
| 490 | if (m_debug_options.windows_disabled) |
| 491 | clipmask = 0xff; |
| 492 | #endif /* SNES_LAYER_DEBUG */ |
| 493 | |
| 494 | /* Clip to windows */ |
| 495 | if (m_scanlines[screen].clip) |
| 496 | clr &= clipmask; |
| 497 | |
| 498 | /* Only draw if we have a colour (0 == transparent) */ |
| 499 | if (clr) |
| 500 | { |
| 501 | c = get_bgcolor(direct_colors, pal, clr); |
| 502 | set_scanline_pixel(screen, ii >> 1, c, priority, layer, 0); |
| 503 | } |
| 504 | } |
| 505 | } |
| 506 | } |
| 507 | } |
| 508 | |
| 509 | inline void snes_ppu_device::draw_oamtile( INT16 ii, UINT8 colour, UINT16 pal, UINT8 priority ) |
| 510 | { |
| 511 | int screen; |
| 512 | int blend; |
| 513 | UINT16 c; |
| 514 | INT16 pos = ii & 0x1ff; |
| 515 | |
| 516 | for (screen = SNES_MAINSCREEN; screen <= SNES_SUBSCREEN; screen++) |
| 517 | { |
| 518 | if (pos >= 0 && pos < SNES_SCR_WIDTH && m_scanlines[screen].enable) |
| 519 | { |
| 520 | UINT8 clr = colour; |
| 521 | UINT8 clipmask = m_clipmasks[SNES_OAM][pos]; |
| 522 | |
| 523 | #if SNES_LAYER_DEBUG |
| 524 | if (m_debug_options.windows_disabled) |
| 525 | clipmask = 0xff; |
| 526 | #endif /* SNES_LAYER_DEBUG */ |
| 527 | |
| 528 | /* Clip to windows */ |
| 529 | if (m_scanlines[screen].clip) |
| 530 | clr &= clipmask; |
| 531 | |
| 532 | /* Only draw if we have a colour (0 == transparent) */ |
| 533 | if (clr) |
| 534 | { |
| 535 | c = m_cgram[(pal + clr) % FIXED_COLOUR]; |
| 536 | blend = (pal + clr < 192) ? 1 : 0; |
| 537 | set_scanline_pixel(screen, pos, c, priority, SNES_OAM, blend); |
| 538 | } |
| 539 | } |
| 540 | } |
| 541 | } |
| 542 | |
| 543 | /***************************************** |
| 544 | * draw_tile() |
| 545 | * |
| 546 | * Draw 8 pixels from the expected tile |
| 547 | * by reading the color planes from vram |
| 548 | * and by calling the appropriate routine |
| 549 | * (depending on layer and resolution) |
| 550 | *****************************************/ |
| 551 | |
| 552 | inline void snes_ppu_device::draw_tile( UINT8 planes, UINT8 layer, UINT32 tileaddr, INT16 x, UINT8 priority, UINT8 flip, UINT8 direct_colors, UINT16 pal, UINT8 hires ) |
| 553 | { |
| 554 | UINT8 plane[8]; |
| 555 | INT16 ii, jj; |
| 556 | int x_mos; |
| 557 | |
| 558 | for (ii = 0; ii < planes / 2; ii++) |
| 559 | { |
| 560 | plane[2 * ii + 0] = m_vram[(tileaddr + 16 * ii + 0) % SNES_VRAM_SIZE]; |
| 561 | plane[2 * ii + 1] = m_vram[(tileaddr + 16 * ii + 1) % SNES_VRAM_SIZE]; |
| 562 | } |
| 563 | |
| 564 | for (ii = x; ii < (x + 8); ii++) |
| 565 | { |
| 566 | UINT8 colour = 0; |
| 567 | UINT8 mosaic = m_layer[layer].mosaic_enabled; |
| 568 | |
| 569 | #if SNES_LAYER_DEBUG |
| 570 | if (m_debug_options.mosaic_disabled) |
| 571 | mosaic = 0; |
| 572 | #endif /* SNES_LAYER_DEBUG */ |
| 573 | |
| 574 | if (flip) |
| 575 | { |
| 576 | for (jj = 0; jj < planes; jj++) |
| 577 | colour |= BIT(plane[jj], ii - x) ? (1 << jj) : 0; |
| 578 | } |
| 579 | else |
| 580 | { |
| 581 | for (jj = 0; jj < planes; jj++) |
| 582 | colour |= BIT(plane[jj], 7 - (ii - x)) ? (1 << jj) : 0; |
| 583 | } |
| 584 | |
| 585 | if (layer == SNES_OAM) |
| 586 | draw_oamtile(ii, colour, pal, priority); |
| 587 | else if (!hires) |
| 588 | { |
| 589 | if (mosaic) |
| 590 | { |
| 591 | for (x_mos = 0; x_mos < (m_mosaic_size + 1); x_mos++) |
| 592 | draw_bgtile_lores(layer, ii + x_mos, colour, pal, direct_colors, priority); |
| 593 | ii += x_mos - 1; |
| 594 | } |
| 595 | else |
| 596 | draw_bgtile_lores(layer, ii, colour, pal, direct_colors, priority); |
| 597 | } |
| 598 | else /* hires */ |
| 599 | { |
| 600 | if (mosaic) |
| 601 | { |
| 602 | for (x_mos = 0; x_mos < (m_mosaic_size + 1); x_mos++) |
| 603 | draw_bgtile_hires(layer, ii + x_mos, colour, pal, direct_colors, priority); |
| 604 | ii += x_mos - 1; |
| 605 | } |
| 606 | else |
| 607 | draw_bgtile_hires(layer, ii, colour, pal, direct_colors, priority); |
| 608 | } |
| 609 | } |
| 610 | } |
| 611 | |
| 612 | /************************************************************************************************* |
| 613 | * SNES BG layers |
| 614 | * |
| 615 | * BG drawing theory of each scanline is quite easy: depending on the graphics Mode (0-7), there |
| 616 | * are up to 4 background layers. Pixels for each BG layer can have two different priorities. |
| 617 | * Depending on the line and on the BGHOFS and BGVOFS PPU registers, we first determine the tile |
| 618 | * address in m_vram (by determining x,y coord and tile size and by calling get_tmap_addr). |
| 619 | * Then, we load the correspondent data and we determine the tile properties: which priority to |
| 620 | * use, which palette etc. Finally, for each pixel of the tile appearing on screen, we check if |
| 621 | * the tile priority is higher than the BG/OAM already stored in that pixel for that line. If so |
| 622 | * we store the pixel in the buffer, otherwise we discard it. |
| 623 | * |
| 624 | * Of course, depending on the graphics Mode, it might be easier or harder to determine the proper |
| 625 | * tile address in vram (Mode 7 uses different registers, Mode 2, 4 and 6 uses OPT effect, etc.), |
| 626 | * but in general it works as described. |
| 627 | *************************************************************************************************/ |
| 628 | |
| 629 | /********************************************* |
| 630 | * get_tmap_addr() |
| 631 | * |
| 632 | * Find the address in VRAM of the tile (x,y) |
| 633 | *********************************************/ |
| 634 | |
| 635 | inline UINT32 snes_ppu_device::get_tmap_addr( UINT8 layer, UINT8 tile_size, UINT32 base, UINT32 x, UINT32 y ) |
| 636 | { |
| 637 | UINT32 res = base; |
| 638 | x >>= (3 + tile_size); |
| 639 | y >>= (3 + tile_size); |
| 640 | |
| 641 | res += (m_layer[layer].tilemap_size & 2) ? ((y & 0x20) << ((m_layer[layer].tilemap_size & 1) ? 7 : 6)) : 0; |
| 642 | /* Scroll vertically */ |
| 643 | res += (y & 0x1f) << 6; |
| 644 | /* Offset horizontally */ |
| 645 | res += (m_layer[layer].tilemap_size & 1) ? ((x & 0x20) << 6) : 0; |
| 646 | /* Scroll horizontally */ |
| 647 | res += (x & 0x1f) << 1; |
| 648 | |
| 649 | return res; |
| 650 | } |
| 651 | |
| 652 | /********************************************* |
| 653 | * update_line() |
| 654 | * |
| 655 | * Update an entire line of tiles. |
| 656 | *********************************************/ |
| 657 | |
| 658 | inline void snes_ppu_device::update_line( UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a, UINT8 color_depth, UINT8 hires, UINT8 offset_per_tile, UINT8 direct_colors ) |
| 659 | { |
| 660 | UINT32 tmap, tile, xoff, yoff, charaddr, addr; |
| 661 | UINT16 ii = 0, vflip, hflip, pal, pal_direct, tilemap; |
| 662 | UINT8 xscroll, priority; |
| 663 | INT8 yscroll; |
| 664 | int tile_incr = 0; |
| 665 | UINT16 opt_bit = (layer == SNES_BG1) ? 13 : (layer == SNES_BG2) ? 14 : 0; |
| 666 | UINT8 tile_size; |
| 667 | /* variables depending on color_depth */ |
| 668 | UINT8 color_planes = 2 << color_depth; |
| 669 | /* below we cheat to simplify the code: 8BPP should have 0 pal offset, not 0x100 (but we take care of this by later using pal % FIXED_COLOUR) */ |
| 670 | UINT8 color_shift = 2 << color_depth; |
| 671 | |
| 672 | #if SNES_LAYER_DEBUG |
| 673 | if (m_debug_options.bg_disabled[layer]) |
| 674 | return; |
| 675 | #endif /* SNES_LAYER_DEBUG */ |
| 676 | |
| 677 | m_scanlines[SNES_MAINSCREEN].enable = m_layer[layer].main_bg_enabled; |
| 678 | m_scanlines[SNES_SUBSCREEN].enable = m_layer[layer].sub_bg_enabled; |
| 679 | m_scanlines[SNES_MAINSCREEN].clip = m_layer[layer].main_window_enabled; |
| 680 | m_scanlines[SNES_SUBSCREEN].clip = m_layer[layer].sub_window_enabled; |
| 681 | |
| 682 | if (!m_scanlines[SNES_MAINSCREEN].enable && !m_scanlines[SNES_SUBSCREEN].enable) |
| 683 | return; |
| 684 | |
| 685 | /* Handle Mosaic effects */ |
| 686 | if (m_layer[layer].mosaic_enabled) |
| 687 | curline -= (curline % (m_mosaic_size + 1)); |
| 688 | |
| 689 | if ((m_interlace == 2) && !hires && !m_pseudo_hires) |
| 690 | curline /= 2; |
| 691 | |
| 692 | /* Find the size of the tiles (8x8 or 16x16) */ |
| 693 | tile_size = m_layer[layer].tile_size; |
| 694 | |
| 695 | /* Find scroll info */ |
| 696 | xoff = m_layer[layer].hoffs; |
| 697 | yoff = m_layer[layer].voffs; |
| 698 | |
| 699 | xscroll = xoff & ((1 << (3 + tile_size)) - 1); |
| 700 | |
| 701 | /* Jump to base map address */ |
| 702 | tmap = m_layer[layer].tilemap << 9; |
| 703 | charaddr = m_layer[layer].charmap << 13; |
| 704 | |
| 705 | while (ii < 256 + (8 << tile_size)) |
| 706 | { |
| 707 | // determine the horizontal position (Bishojo Janshi Suchi Pai & Desert Figther have tile_size & hires == 1) |
| 708 | UINT32 xpos = xoff + (ii << (tile_size * hires)); |
| 709 | UINT32 ypos = yoff + curline; |
| 710 | |
| 711 | if (offset_per_tile != SNES_OPT_NONE) |
| 712 | { |
| 713 | int opt_x = ii + (xoff & 7); |
| 714 | UINT32 haddr = 0, vaddr = 0; |
| 715 | UINT16 hval = 0, vval = 0; |
| 716 | |
| 717 | if (opt_x >= 8) |
| 718 | { |
| 719 | switch (offset_per_tile) |
| 720 | { |
| 721 | case SNES_OPT_MODE2: |
| 722 | case SNES_OPT_MODE6: |
| 723 | haddr = 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)); |
| 724 | vaddr = 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); |
| 725 | hval = m_vram[haddr % SNES_VRAM_SIZE] | (m_vram[(haddr + 1) % SNES_VRAM_SIZE] << 8); |
| 726 | vval = m_vram[vaddr % SNES_VRAM_SIZE] | (m_vram[(vaddr + 1) % SNES_VRAM_SIZE] << 8); |
| 727 | if (BIT(hval, opt_bit)) |
| 728 | xpos = opt_x + (hval & ~7); |
| 729 | if (BIT(vval, opt_bit)) |
| 730 | ypos = curline + vval; |
| 731 | break; |
| 732 | case SNES_OPT_MODE4: |
| 733 | haddr = 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)); |
| 734 | hval = m_vram[haddr % SNES_VRAM_SIZE] | (m_vram[(haddr + 1) % SNES_VRAM_SIZE] << 8); |
| 735 | if (BIT(hval, opt_bit)) |
| 736 | { |
| 737 | if (!BIT(hval, 15)) |
| 738 | xpos = opt_x + (hval & ~7); |
| 739 | else |
| 740 | ypos = curline + hval; |
| 741 | } |
| 742 | break; |
| 743 | } |
| 744 | } |
| 745 | } |
| 746 | |
| 747 | addr = get_tmap_addr(layer, tile_size, tmap, xpos, ypos); |
| 748 | |
| 749 | /* |
| 750 | Tilemap format |
| 751 | vhopppcc cccccccc |
| 752 | |
| 753 | v/h = Vertical/Horizontal flip this tile. |
| 754 | o = Tile priority. |
| 755 | ppp = Tile palette. The number of entries in the palette depends on the Mode and the BG. |
| 756 | cccccccccc = Tile number. |
| 757 | */ |
| 758 | tilemap = m_vram[addr % SNES_VRAM_SIZE] | (m_vram[(addr + 1) % SNES_VRAM_SIZE] << 8); |
| 759 | vflip = BIT(tilemap, 15); |
| 760 | hflip = BIT(tilemap, 14); |
| 761 | priority = BIT(tilemap, 13) ? priority_a : priority_b; |
| 762 | pal_direct = ((tilemap & 0x1c00) >> 8); |
| 763 | tile = tilemap & 0x03ff; |
| 764 | |
| 765 | pal = ((pal_direct >> 2) << color_shift); |
| 766 | |
| 767 | /* Mode 0 palettes are layer specific */ |
| 768 | if (m_mode == 0) |
| 769 | { |
| 770 | pal += (layer << 5); |
| 771 | } |
| 772 | |
| 773 | #if SNES_LAYER_DEBUG |
| 774 | /* if we want to draw only one of the priorities of this layer */ |
| 775 | if (((m_debug_options.select_pri[layer] & 0x01) && (priority == priority_a)) || |
| 776 | ((m_debug_options.select_pri[layer] & 0x02) && (priority == priority_b))) |
| 777 | { |
| 778 | if (!hires && tile_size) |
| 779 | ii += 16; |
| 780 | else |
| 781 | ii += 8; |
| 782 | continue; |
| 783 | } |
| 784 | #endif /* SNES_LAYER_DEBUG */ |
| 785 | |
| 786 | /* figure out which line to draw */ |
| 787 | yscroll = ypos & ((8 << tile_size) - 1); |
| 788 | |
| 789 | if (tile_size) |
| 790 | if (BIT(yscroll, 3) != vflip) |
| 791 | tile += 16; |
| 792 | |
| 793 | if (yscroll > 7) |
| 794 | yscroll &= 7; |
| 795 | |
| 796 | if (vflip) |
| 797 | yscroll = 7 - yscroll; |
| 798 | |
| 799 | yscroll <<= 1; |
| 800 | |
| 801 | /* if we have to draw 16 pixels, set tile_incr and adjust tile for horizontal flip */ |
| 802 | if (tile_size || hires) |
| 803 | { |
| 804 | if (hflip) |
| 805 | { |
| 806 | tile += 1; |
| 807 | tile_incr = -1; // next 8 pixels from previous tile (because of hflip) |
| 808 | } |
| 809 | else |
| 810 | tile_incr = 1; // next 8 pixels from next tile |
| 811 | } |
| 812 | |
| 813 | if (hires) |
| 814 | { |
| 815 | /* draw 16 pixels (the routine will automatically send half of them to the mainscreen scanline and half to the subscreen one) */ |
| 816 | draw_tile(color_planes, layer, charaddr + (((tile + 0) & 0x3ff) * 8 * color_planes) + yscroll, (ii - xscroll) * 2, priority, hflip, direct_colors, direct_colors ? pal_direct : pal, hires); |
| 817 | draw_tile(color_planes, layer, charaddr + (((tile + tile_incr) & 0x3ff) * 8 * color_planes) + yscroll, (ii - xscroll) * 2 + 8, priority, hflip, direct_colors, direct_colors ? pal_direct : pal, hires); |
| 818 | ii += 8; |
| 819 | } |
| 820 | else |
| 821 | { |
| 822 | draw_tile(color_planes, layer, charaddr + ((tile & 0x3ff) * 8 * color_planes) + yscroll, ii - xscroll, priority, hflip, direct_colors, direct_colors ? pal_direct : pal, hires); |
| 823 | ii += 8; |
| 824 | |
| 825 | if (tile_size) |
| 826 | { |
| 827 | draw_tile(color_planes, layer, charaddr + (((tile + tile_incr) & 0x3ff) * 8 * color_planes) + yscroll, ii - xscroll, priority, hflip, direct_colors, direct_colors ? pal_direct : pal, hires); |
| 828 | ii += 8; |
| 829 | } |
| 830 | } |
| 831 | } |
| 832 | } |
| 833 | |
| 834 | |
| 835 | /********************************************* |
| 836 | * update_line_mode7() |
| 837 | * |
| 838 | * Update an entire line of mode7 tiles. |
| 839 | *********************************************/ |
| 840 | |
| 841 | #define MODE7_CLIP(x) (((x) & 0x2000) ? ((x) | ~0x03ff) : ((x) & 0x03ff)) |
| 842 | |
| 843 | void snes_ppu_device::update_line_mode7( UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a ) |
| 844 | { |
| 845 | UINT32 tiled; |
| 846 | INT16 ma, mb, mc, md; |
| 847 | INT32 xc, yc, tx, ty, sx, sy, hs, vs, xpos, xdir, x0, y0; |
| 848 | UINT8 priority = priority_b; |
| 849 | UINT8 colour = 0; |
| 850 | UINT16 *mosaic_x, *mosaic_y; |
| 851 | UINT16 c; |
| 852 | int screen; |
| 853 | |
| 854 | #if SNES_LAYER_DEBUG |
| 855 | if (m_debug_options.bg_disabled[layer]) |
| 856 | return; |
| 857 | #endif /* SNES_LAYER_DEBUG */ |
| 858 | |
| 859 | m_scanlines[SNES_MAINSCREEN].enable = m_layer[layer].main_bg_enabled; |
| 860 | m_scanlines[SNES_SUBSCREEN].enable = m_layer[layer].sub_bg_enabled; |
| 861 | m_scanlines[SNES_MAINSCREEN].clip = m_layer[layer].main_window_enabled; |
| 862 | m_scanlines[SNES_SUBSCREEN].clip = m_layer[layer].sub_window_enabled; |
| 863 | |
| 864 | if (!m_scanlines[SNES_MAINSCREEN].enable && !m_scanlines[SNES_SUBSCREEN].enable) |
| 865 | return; |
| 866 | |
| 867 | ma = m_mode7.matrix_a; |
| 868 | mb = m_mode7.matrix_b; |
| 869 | mc = m_mode7.matrix_c; |
| 870 | md = m_mode7.matrix_d; |
| 871 | xc = m_mode7.origin_x; |
| 872 | yc = m_mode7.origin_y; |
| 873 | hs = m_mode7.hor_offset; |
| 874 | vs = m_mode7.ver_offset; |
| 875 | |
| 876 | /* Sign extend */ |
| 877 | xc <<= 19; |
| 878 | xc >>= 19; |
| 879 | yc <<= 19; |
| 880 | yc >>= 19; |
| 881 | hs <<= 19; |
| 882 | hs >>= 19; |
| 883 | vs <<= 19; |
| 884 | vs >>= 19; |
| 885 | |
| 886 | /* Vertical flip */ |
| 887 | if (m_mode7.vflip) |
| 888 | sy = 255 - curline; |
| 889 | else |
| 890 | sy = curline; |
| 891 | |
| 892 | /* Horizontal flip */ |
| 893 | if (m_mode7.hflip) |
| 894 | { |
| 895 | xpos = 255; |
| 896 | xdir = -1; |
| 897 | } |
| 898 | else |
| 899 | { |
| 900 | xpos = 0; |
| 901 | xdir = 1; |
| 902 | } |
| 903 | |
| 904 | /* MOSAIC - to be verified */ |
| 905 | if (layer == SNES_BG2) // BG2 use two different bits for horizontal and vertical mosaic |
| 906 | { |
| 907 | mosaic_x = m_mosaic_table[m_layer[SNES_BG2].mosaic_enabled ? m_mosaic_size : 0]; |
| 908 | mosaic_y = m_mosaic_table[m_layer[SNES_BG1].mosaic_enabled ? m_mosaic_size : 0]; |
| 909 | } |
| 910 | else // BG1 works as usual |
| 911 | { |
| 912 | mosaic_x = m_mosaic_table[m_layer[SNES_BG1].mosaic_enabled ? m_mosaic_size : 0]; |
| 913 | mosaic_y = m_mosaic_table[m_layer[SNES_BG1].mosaic_enabled ? m_mosaic_size : 0]; |
| 914 | } |
| 915 | |
| 916 | #if SNES_LAYER_DEBUG |
| 917 | if (m_debug_options.mosaic_disabled) |
| 918 | { |
| 919 | mosaic_x = m_mosaic_table[0]; |
| 920 | mosaic_y = m_mosaic_table[0]; |
| 921 | } |
| 922 | #endif /* SNES_LAYER_DEBUG */ |
| 923 | |
| 924 | /* Let's do some mode7 drawing huh? */ |
| 925 | /* These can be computed only once, since they do not depend on sx */ |
| 926 | x0 = ((ma * MODE7_CLIP(hs - xc)) & ~0x3f) + ((mb * mosaic_y[sy]) & ~0x3f) + ((mb * MODE7_CLIP(vs - yc)) & ~0x3f) + (xc << 8); |
| 927 | y0 = ((mc * MODE7_CLIP(hs - xc)) & ~0x3f) + ((md * mosaic_y[sy]) & ~0x3f) + ((md * MODE7_CLIP(vs - yc)) & ~0x3f) + (yc << 8); |
| 928 | |
| 929 | for (sx = 0; sx < 256; sx++, xpos += xdir) |
| 930 | { |
| 931 | tx = (x0 + (ma * mosaic_x[sx])) >> 8; |
| 932 | ty = (y0 + (mc * mosaic_x[sx])) >> 8; |
| 933 | |
| 934 | switch (m_mode7.repeat) |
| 935 | { |
| 936 | case 0x00: /* Repeat if outside screen area */ |
| 937 | case 0x01: /* Repeat if outside screen area */ |
| 938 | tx &= 0x3ff; |
| 939 | ty &= 0x3ff; |
| 940 | tiled = m_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 941 | colour = m_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 942 | break; |
| 943 | case 0x02: /* Single colour backdrop screen if outside screen area */ |
| 944 | if ((tx >= 0) && (tx < 1024) && (ty >= 0) && (ty < 1024)) |
| 945 | { |
| 946 | tiled = m_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 947 | colour = m_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 948 | } |
| 949 | else |
| 950 | colour = 0; |
| 951 | break; |
| 952 | case 0x03: /* Character 0x00 repeat if outside screen area */ |
| 953 | if ((tx >= 0) && (tx < 1024) && (ty >= 0) && (ty < 1024)) |
| 954 | tiled = m_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 955 | else |
| 956 | tiled = 0; |
| 957 | |
| 958 | colour = m_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 959 | break; |
| 960 | } |
| 961 | |
| 962 | /* The last bit is for priority in EXTBG mode (used only for BG2) */ |
| 963 | if (layer == SNES_BG2) |
| 964 | { |
| 965 | priority = ((colour & 0x80) >> 7) ? priority_a : priority_b; |
| 966 | colour &= 0x7f; |
| 967 | |
| 968 | #if SNES_LAYER_DEBUG |
| 969 | /* if we want to draw only one of the priorities of this layer */ |
| 970 | if (((m_debug_options.select_pri[layer] & 0x01) && (priority == priority_a)) || |
| 971 | ((m_debug_options.select_pri[layer] & 0x02) && (priority == priority_b))) |
| 972 | continue; |
| 973 | #endif /* SNES_LAYER_DEBUG */ |
| 974 | } |
| 975 | |
| 976 | for (screen = SNES_MAINSCREEN; screen <= SNES_SUBSCREEN; screen++) |
| 977 | { |
| 978 | if (m_scanlines[screen].enable) |
| 979 | { |
| 980 | UINT8 clr = colour; |
| 981 | UINT8 clipmask = m_clipmasks[layer][xpos]; |
| 982 | |
| 983 | #if SNES_LAYER_DEBUG |
| 984 | if (m_debug_options.windows_disabled) |
| 985 | clipmask = 0xff; |
| 986 | #endif /* SNES_LAYER_DEBUG */ |
| 987 | |
| 988 | /* Clip to windows */ |
| 989 | if (m_scanlines[screen].clip) |
| 990 | clr &= clipmask; |
| 991 | |
| 992 | /* Draw pixel if appropriate */ |
| 993 | if (m_scanlines[screen].priority[xpos] <= priority && clr > 0) |
| 994 | { |
| 995 | /* Direct select, but only outside EXTBG! */ |
| 996 | // Direct color format is: 0 | BB000 | GGG00 | RRR00, HW confirms that the data is zero padded. |
| 997 | // In other words, like normal direct color, with pal = 0 |
| 998 | c = get_bgcolor(m_direct_color && layer == SNES_BG1, 0, clr); |
| 999 | set_scanline_pixel(screen, xpos, c, priority, layer, 0); |
| 1000 | } |
| 1001 | } |
| 1002 | } |
| 1003 | } |
| 1004 | } |
| 1005 | |
| 1006 | /************************************************************************************************* |
| 1007 | * SNES Sprites |
| 1008 | * |
| 1009 | * 1. First of all: sprites are drawn one line in advance. We emulate this by caching the |
| 1010 | * starting vram address, the sprite size and the "name select" at each line, and by using |
| 1011 | * them the next line to output the proper sprites - see update_obsel. |
| 1012 | * |
| 1013 | * 2. Each line can select its sprites among 128 available ones in oam_ram, hence we start |
| 1014 | * by creating a list of the available objects (each one with its x,y coordinate, its size, |
| 1015 | * its tile address, etc.) - see oam_list_build. |
| 1016 | * |
| 1017 | * 3. Next, we start finding out which sprites will appear in the line: starting from |
| 1018 | * FirstSprite, we count 32 OBJs which intersect our line and we store their indexes in the |
| 1019 | * oam_itemlist array (if more than 32 sprites intersect our line, we set the Range Over |
| 1020 | * flag); then, selecting among these sprites, we count 34 8x8 tiles which are visible |
| 1021 | * in our line (i.e. whose x coord is between -size and 256) and we store the corresponding |
| 1022 | * coordinates/priorities/palettes/etc. in the oam_tilelist array (if more than 34 tiles would |
| 1023 | * appear on screen, we set the Time Over flag). |
| 1024 | * Notice that when we populate oam_tilelist, we proceed from oam_itemlist[31] (or from the last |
| 1025 | * item which intersects the scanline), towards oam_itemlist[0], i.e. the higher tiles (say |
| 1026 | * oam_tilelist[34], or the last tile which appear on screen) will contain FirstSprite object, |
| 1027 | * or the sprites with closer index to FirstSprite which get displayed. This will play an |
| 1028 | * important role for sprite priority - see update_objects_rto. |
| 1029 | * |
| 1030 | * 4. All the above happens at the beginning of each VIDEO_UPDATE. When we finally draw the |
| 1031 | * scanline, we pass through the oam_tilelist and we store the displayed pixels in our scanline |
| 1032 | * buffer. Notice that, for each pixel of a SNES sprite, only the priority of the topmost sprite |
| 1033 | * is tested against the priority of the BG pixel (because FirstSprite is on top of FirstSprite+1, |
| 1034 | * which is on top of FirstSprite+2, etc., and therefore other sprites are already covered by the |
| 1035 | * topmost one). To emulate this, we draw each tile over the previous ones no matter what |
| 1036 | * priorities are (differently from what we did with BGs): in the end, we will have in each pixel z |
| 1037 | * its topmost sprite and scanline.priority[z] will be the topmost sprite priority as expected. |
| 1038 | * Of course, sprite drawing must happen before BG drawing, so that afterwords BG pixels properly |
| 1039 | * test their priority with the one of the correct sprite - see update_objects. |
| 1040 | *************************************************************************************************/ |
| 1041 | |
| 1042 | |
| 1043 | /********************************************* |
| 1044 | * update_obsel() |
| 1045 | * |
| 1046 | * Update sprite settings for next line. |
| 1047 | *********************************************/ |
| 1048 | |
| 1049 | void snes_ppu_device::update_obsel( void ) |
| 1050 | { |
| 1051 | m_layer[SNES_OAM].charmap = m_oam.next_charmap; |
| 1052 | m_oam.name_select = m_oam.next_name_select; |
| 1053 | |
| 1054 | if (m_oam.size != m_oam.next_size) |
| 1055 | { |
| 1056 | m_oam.size = m_oam.next_size; |
| 1057 | m_update_oam_list = 1; |
| 1058 | } |
| 1059 | } |
| 1060 | |
| 1061 | /********************************************* |
| 1062 | * oam_list_build() |
| 1063 | * |
| 1064 | * Build a list of the available obj in OAM ram. |
| 1065 | *********************************************/ |
| 1066 | |
| 1067 | void snes_ppu_device::oam_list_build( void ) |
| 1068 | { |
| 1069 | UINT8 *oamram = (UINT8 *)m_oam_ram; |
| 1070 | INT16 oam = 0x1ff; |
| 1071 | UINT16 oam_extra = oam + 0x20; |
| 1072 | UINT16 extra = 0; |
| 1073 | int ii; |
| 1074 | |
| 1075 | m_update_oam_list = 0; // eventually, we can optimize the code by only calling this function when there is a change in size |
| 1076 | |
| 1077 | for (ii = 127; ii >= 0; ii--) |
| 1078 | { |
| 1079 | if (((ii + 1) % 4) == 0) |
| 1080 | extra = oamram[oam_extra--]; |
| 1081 | |
| 1082 | m_oam_spritelist[ii].vflip = (oamram[oam] & 0x80) >> 7; |
| 1083 | m_oam_spritelist[ii].hflip = (oamram[oam] & 0x40) >> 6; |
| 1084 | m_oam_spritelist[ii].priority_bits = (oamram[oam] & 0x30) >> 4; |
| 1085 | m_oam_spritelist[ii].pal = 128 + ((oamram[oam] & 0x0e) << 3); |
| 1086 | m_oam_spritelist[ii].tile = (oamram[oam--] & 0x1) << 8; |
| 1087 | m_oam_spritelist[ii].tile |= oamram[oam--]; |
| 1088 | m_oam_spritelist[ii].y = oamram[oam--] + 1; |
| 1089 | m_oam_spritelist[ii].x = oamram[oam--]; |
| 1090 | m_oam_spritelist[ii].size = (extra & 0x80) >> 7; |
| 1091 | extra <<= 1; |
| 1092 | m_oam_spritelist[ii].x |= ((extra & 0x80) << 1); |
| 1093 | extra <<= 1; |
| 1094 | |
| 1095 | m_oam_spritelist[ii].y *= m_obj_interlace; |
| 1096 | m_oam_spritelist[ii].y &= 0x1ff; |
| 1097 | |
| 1098 | m_oam_spritelist[ii].x &= 0x1ff; |
| 1099 | |
| 1100 | /* Determine object size */ |
| 1101 | switch (m_oam.size) |
| 1102 | { |
| 1103 | case 0: /* 8x8 or 16x16 */ |
| 1104 | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 2 : 1; |
| 1105 | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 2 : 1; |
| 1106 | break; |
| 1107 | case 1: /* 8x8 or 32x32 */ |
| 1108 | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 4 : 1; |
| 1109 | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 4 : 1; |
| 1110 | break; |
| 1111 | case 2: /* 8x8 or 64x64 */ |
| 1112 | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 8 : 1; |
| 1113 | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 8 : 1; |
| 1114 | break; |
| 1115 | case 3: /* 16x16 or 32x32 */ |
| 1116 | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 4 : 2; |
| 1117 | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 4 : 2; |
| 1118 | break; |
| 1119 | case 4: /* 16x16 or 64x64 */ |
| 1120 | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 8 : 2; |
| 1121 | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 8 : 2; |
| 1122 | break; |
| 1123 | case 5: /* 32x32 or 64x64 */ |
| 1124 | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 8 : 4; |
| 1125 | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 8 : 4; |
| 1126 | break; |
| 1127 | case 6: /* undocumented: 16x32 or 32x64 */ |
| 1128 | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 4 : 2; |
| 1129 | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 8 : 4; |
| 1130 | if (m_obj_interlace && !m_oam_spritelist[ii].size) |
| 1131 | m_oam_spritelist[ii].height = 2; |
| 1132 | break; |
| 1133 | case 7: /* undocumented: 16x32 or 32x32 */ |
| 1134 | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 4 : 2; |
| 1135 | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 4 : 4; |
| 1136 | if (m_obj_interlace && !m_oam_spritelist[ii].size) |
| 1137 | m_oam_spritelist[ii].height = 2; |
| 1138 | break; |
| 1139 | default: |
| 1140 | /* we should never enter here... */ |
| 1141 | logerror("Object size unsupported: %d\n", m_oam.size); |
| 1142 | break; |
| 1143 | } |
| 1144 | } |
| 1145 | } |
| 1146 | |
| 1147 | /********************************************* |
| 1148 | * is_sprite_on_scanline() |
| 1149 | * |
| 1150 | * Check if a given sprites intersect current |
| 1151 | * scanline |
| 1152 | *********************************************/ |
| 1153 | |
| 1154 | int snes_ppu_device::is_sprite_on_scanline( UINT16 curline, UINT8 sprite ) |
| 1155 | { |
| 1156 | //if sprite is entirely offscreen and doesn't wrap around to the left side of the screen, |
| 1157 | //then it is not counted. this *should* be 256, and not 255, even though dot 256 is offscreen. |
| 1158 | int spr_height = (m_oam_spritelist[sprite].height << 3); |
| 1159 | |
| 1160 | if (m_oam_spritelist[sprite].x > 256 && (m_oam_spritelist[sprite].x + (m_oam_spritelist[sprite].width << 3) - 1) < 512) |
| 1161 | return 0; |
| 1162 | |
| 1163 | if (curline >= m_oam_spritelist[sprite].y && curline < (m_oam_spritelist[sprite].y + spr_height)) |
| 1164 | return 1; |
| 1165 | |
| 1166 | if ((m_oam_spritelist[sprite].y + spr_height) >= 256 && curline < ((m_oam_spritelist[sprite].y + spr_height) & 255)) |
| 1167 | return 1; |
| 1168 | |
| 1169 | return 0; |
| 1170 | } |
| 1171 | |
| 1172 | /********************************************* |
| 1173 | * update_objects_rto() |
| 1174 | * |
| 1175 | * Determine which OBJs will be drawn on this |
| 1176 | * scanline. |
| 1177 | *********************************************/ |
| 1178 | |
| 1179 | void snes_ppu_device::update_objects_rto( UINT16 curline ) |
| 1180 | { |
| 1181 | int ii, jj, active_sprite; |
| 1182 | UINT8 range_over, time_over; |
| 1183 | INT8 xs, ys; |
| 1184 | UINT8 line; |
| 1185 | UINT8 height, width, vflip, hflip, priority, pal; |
| 1186 | UINT16 tile; |
| 1187 | INT16 x, y; |
| 1188 | UINT32 name_sel = 0; |
| 1189 | |
| 1190 | oam_list_build(); |
| 1191 | |
| 1192 | /* initialize counters */ |
| 1193 | range_over = 0; |
| 1194 | time_over = 0; |
| 1195 | |
| 1196 | /* setup the proper line */ |
| 1197 | curline /= m_interlace; |
| 1198 | curline *= m_obj_interlace; |
| 1199 | |
| 1200 | /* reset the list of first 32 objects which intersect current scanline */ |
| 1201 | memset(m_oam_itemlist, 0xff, 32); |
| 1202 | |
| 1203 | /* populate the list of 32 objects */ |
| 1204 | for (ii = 0; ii < 128; ii++) |
| 1205 | { |
| 1206 | active_sprite = (ii + m_oam.first_sprite) & 0x7f; |
| 1207 | |
| 1208 | if (!is_sprite_on_scanline(curline, active_sprite)) |
| 1209 | continue; |
| 1210 | |
| 1211 | if (range_over++ >= 32) |
| 1212 | break; |
| 1213 | |
| 1214 | m_oam_itemlist[range_over - 1] = active_sprite; |
| 1215 | } |
| 1216 | |
| 1217 | /* reset the list of first 34 tiles to be drawn */ |
| 1218 | for (ii = 0; ii < 34; ii++) |
| 1219 | m_oam_tilelist[ii].tileaddr = 0xffff; |
| 1220 | |
| 1221 | /* populate the list of 34 tiles */ |
| 1222 | for (ii = 31; ii >= 0; ii--) |
| 1223 | { |
| 1224 | if (m_oam_itemlist[ii] == 0xff) |
| 1225 | continue; |
| 1226 | |
| 1227 | active_sprite = m_oam_itemlist[ii]; |
| 1228 | |
| 1229 | tile = m_oam_spritelist[active_sprite].tile; |
| 1230 | x = m_oam_spritelist[active_sprite].x; |
| 1231 | y = m_oam_spritelist[active_sprite].y; |
| 1232 | height = m_oam_spritelist[active_sprite].height; |
| 1233 | width = m_oam_spritelist[active_sprite].width; |
| 1234 | vflip = m_oam_spritelist[active_sprite].vflip; |
| 1235 | hflip = m_oam_spritelist[active_sprite].hflip; |
| 1236 | priority = m_oam_spritelist[active_sprite].priority_bits; |
| 1237 | pal = m_oam_spritelist[active_sprite].pal; |
| 1238 | |
| 1239 | /* Adjust y, if past maximum position (for sprites which overlap between top & bottom) */ |
| 1240 | if (y >= (0x100 - 16) * m_interlace) |
| 1241 | y -= (0x100) * m_interlace; |
| 1242 | |
| 1243 | if (curline >= y && curline < (y + (height << 3))) |
| 1244 | { |
| 1245 | /* Only objects using tiles over 255 use name select */ |
| 1246 | name_sel = (tile < 256) ? 0 : m_oam.name_select; |
| 1247 | |
| 1248 | ys = (curline - y) >> 3; |
| 1249 | line = (curline - y) % 8; |
| 1250 | if (vflip) |
| 1251 | { |
| 1252 | ys = height - ys - 1; |
| 1253 | line = 7 - line; |
| 1254 | } |
| 1255 | line <<= 1; |
| 1256 | tile <<= 5; |
| 1257 | |
| 1258 | for (jj = 0; jj < width; jj++) |
| 1259 | { |
| 1260 | INT16 xx = (x + (jj << 3)) & 0x1ff; |
| 1261 | |
| 1262 | if (x != 256 && xx >= 256 && (xx + 7) < 512) |
| 1263 | continue; |
| 1264 | |
| 1265 | if (time_over++ >= 34) |
| 1266 | break; |
| 1267 | |
| 1268 | xs = (hflip) ? (width - 1 - jj) : jj; |
| 1269 | m_oam_tilelist[time_over - 1].tileaddr = name_sel + tile + table_obj_offset[ys][xs] + line; |
| 1270 | m_oam_tilelist[time_over - 1].hflip = hflip; |
| 1271 | m_oam_tilelist[time_over - 1].x = xx; |
| 1272 | m_oam_tilelist[time_over - 1].pal = pal; |
| 1273 | m_oam_tilelist[time_over - 1].priority = priority; |
| 1274 | } |
| 1275 | } |
| 1276 | } |
| 1277 | |
| 1278 | /* set Range Over flag if necessary */ |
| 1279 | if (range_over > 32) |
| 1280 | m_stat77 |= 0x40; |
| 1281 | |
| 1282 | /* set Time Over flag if necessary */ |
| 1283 | if (time_over > 34) |
| 1284 | m_stat77 |= 0x80; |
| 1285 | } |
| 1286 | |
| 1287 | /********************************************* |
| 1288 | * update_objects() |
| 1289 | * |
| 1290 | * Update an entire line of sprites. |
| 1291 | *********************************************/ |
| 1292 | |
| 1293 | void snes_ppu_device::update_objects( UINT8 priority_oam0, UINT8 priority_oam1, UINT8 priority_oam2, UINT8 priority_oam3 ) |
| 1294 | { |
| 1295 | UINT8 pri, priority[4]; |
| 1296 | UINT32 charaddr; |
| 1297 | int ii; |
| 1298 | |
| 1299 | #if SNES_LAYER_DEBUG |
| 1300 | if (m_debug_options.bg_disabled[SNES_OAM]) |
| 1301 | return; |
| 1302 | #endif /* SNES_LAYER_DEBUG */ |
| 1303 | |
| 1304 | m_scanlines[SNES_MAINSCREEN].enable = m_layer[SNES_OAM].main_bg_enabled; |
| 1305 | m_scanlines[SNES_SUBSCREEN].enable = m_layer[SNES_OAM].sub_bg_enabled; |
| 1306 | m_scanlines[SNES_MAINSCREEN].clip = m_layer[SNES_OAM].main_window_enabled; |
| 1307 | m_scanlines[SNES_SUBSCREEN].clip = m_layer[SNES_OAM].sub_window_enabled; |
| 1308 | |
| 1309 | if (!m_scanlines[SNES_MAINSCREEN].enable && !m_scanlines[SNES_SUBSCREEN].enable) |
| 1310 | return; |
| 1311 | |
| 1312 | charaddr = m_layer[SNES_OAM].charmap << 13; |
| 1313 | |
| 1314 | priority[0] = priority_oam0; |
| 1315 | priority[1] = priority_oam1; |
| 1316 | priority[2] = priority_oam2; |
| 1317 | priority[3] = priority_oam3; |
| 1318 | |
| 1319 | /* finally draw the tiles from the tilelist */ |
| 1320 | for (ii = 0; ii < 34; ii++) |
| 1321 | { |
| 1322 | int tile = ii; |
| 1323 | #if SNES_LAYER_DEBUG |
| 1324 | if (m_debug_options.sprite_reversed) |
| 1325 | tile = 33 - ii; |
| 1326 | #endif /* SNES_LAYER_DEBUG */ |
| 1327 | |
| 1328 | if (m_oam_tilelist[tile].tileaddr == 0xffff) |
| 1329 | continue; |
| 1330 | |
| 1331 | pri = priority[m_oam_tilelist[tile].priority]; |
| 1332 | |
| 1333 | #if SNES_LAYER_DEBUG |
| 1334 | if (m_debug_options.select_pri[SNES_OAM]) |
| 1335 | { |
| 1336 | int oam_draw = m_debug_options.select_pri[SNES_OAM] - 1; |
| 1337 | if (oam_draw != m_oam_tilelist[tile].priority) |
| 1338 | continue; |
| 1339 | } |
| 1340 | #endif /* SNES_LAYER_DEBUG */ |
| 1341 | |
| 1342 | /* OAM tiles have fixed planes (4), no direct color and no hires, but otherwise work the same as BG ones */ |
| 1343 | draw_tile(4, SNES_OAM, charaddr + m_oam_tilelist[tile].tileaddr, m_oam_tilelist[tile].x, pri, m_oam_tilelist[tile].hflip, 0, m_oam_tilelist[tile].pal, 0); |
| 1344 | } |
| 1345 | } |
| 1346 | |
| 1347 | |
| 1348 | /********************************************* |
| 1349 | * snes_update_mode_X() |
| 1350 | * |
| 1351 | * Update Mode X line. |
| 1352 | *********************************************/ |
| 1353 | |
| 1354 | void snes_ppu_device::update_mode_0( UINT16 curline ) |
| 1355 | { |
| 1356 | #if SNES_LAYER_DEBUG |
| 1357 | if (m_debug_options.mode_disabled[0]) |
| 1358 | return; |
| 1359 | #endif /* SNES_LAYER_DEBUG */ |
| 1360 | |
| 1361 | update_objects(3, 6, 9, 12); |
| 1362 | update_line(curline, SNES_BG1, 8, 11, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_NONE, 0); |
| 1363 | update_line(curline, SNES_BG2, 7, 10, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_NONE, 0); |
| 1364 | update_line(curline, SNES_BG3, 2, 5, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_NONE, 0); |
| 1365 | update_line(curline, SNES_BG4, 1, 4, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_NONE, 0); |
| 1366 | } |
| 1367 | |
| 1368 | void snes_ppu_device::update_mode_1( UINT16 curline ) |
| 1369 | { |
| 1370 | #if SNES_LAYER_DEBUG |
| 1371 | if (m_debug_options.mode_disabled[1]) |
| 1372 | return; |
| 1373 | #endif /* SNES_LAYER_DEBUG */ |
| 1374 | |
| 1375 | if (!m_bg3_priority_bit) |
| 1376 | { |
| 1377 | update_objects(2, 4, 7, 10); |
| 1378 | update_line(curline, SNES_BG1, 6, 9, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_NONE, 0); |
| 1379 | update_line(curline, SNES_BG2, 5, 8, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_NONE, 0); |
| 1380 | update_line(curline, SNES_BG3, 1, 3, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_NONE, 0); |
| 1381 | } |
| 1382 | else |
| 1383 | { |
| 1384 | update_objects(2, 3, 6, 9); |
| 1385 | update_line(curline, SNES_BG1, 5, 8, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_NONE, 0); |
| 1386 | update_line(curline, SNES_BG2, 4, 7, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_NONE, 0); |
| 1387 | update_line(curline, SNES_BG3, 1, 10, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_NONE, 0); |
| 1388 | } |
| 1389 | } |
| 1390 | |
| 1391 | void snes_ppu_device::update_mode_2( UINT16 curline ) |
| 1392 | { |
| 1393 | #if SNES_LAYER_DEBUG |
| 1394 | if (m_debug_options.mode_disabled[2]) |
| 1395 | return; |
| 1396 | #endif /* SNES_LAYER_DEBUG */ |
| 1397 | |
| 1398 | update_objects(2, 4, 6, 8); |
| 1399 | update_line(curline, SNES_BG1, 3, 7, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_MODE2, 0); |
| 1400 | update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_MODE2, 0); |
| 1401 | } |
| 1402 | |
| 1403 | void snes_ppu_device::update_mode_3( UINT16 curline ) |
| 1404 | { |
| 1405 | #if SNES_LAYER_DEBUG |
| 1406 | if (m_debug_options.mode_disabled[3]) |
| 1407 | return; |
| 1408 | #endif /* SNES_LAYER_DEBUG */ |
| 1409 | |
| 1410 | update_objects(2, 4, 6, 8); |
| 1411 | update_line(curline, SNES_BG1, 3, 7, SNES_COLOR_DEPTH_8BPP, 0, SNES_OPT_NONE, m_direct_color); |
| 1412 | update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_NONE, 0); |
| 1413 | } |
| 1414 | |
| 1415 | void snes_ppu_device::update_mode_4( UINT16 curline ) |
| 1416 | { |
| 1417 | #if SNES_LAYER_DEBUG |
| 1418 | if (m_debug_options.mode_disabled[4]) |
| 1419 | return; |
| 1420 | #endif /* SNES_LAYER_DEBUG */ |
| 1421 | |
| 1422 | update_objects(2, 4, 6, 8); |
| 1423 | update_line(curline, SNES_BG1, 3, 7, SNES_COLOR_DEPTH_8BPP, 0, SNES_OPT_MODE4, m_direct_color); |
| 1424 | update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_MODE4, 0); |
| 1425 | } |
| 1426 | |
| 1427 | void snes_ppu_device::update_mode_5( UINT16 curline ) |
| 1428 | { |
| 1429 | #if SNES_LAYER_DEBUG |
| 1430 | if (m_debug_options.mode_disabled[5]) |
| 1431 | return; |
| 1432 | #endif /* SNES_LAYER_DEBUG */ |
| 1433 | |
| 1434 | update_objects(2, 4, 6, 8); |
| 1435 | update_line(curline, SNES_BG1, 3, 7, SNES_COLOR_DEPTH_4BPP, 1, SNES_OPT_NONE, 0); |
| 1436 | update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_2BPP, 1, SNES_OPT_NONE, 0); |
| 1437 | } |
| 1438 | |
| 1439 | void snes_ppu_device::update_mode_6( UINT16 curline ) |
| 1440 | { |
| 1441 | #if SNES_LAYER_DEBUG |
| 1442 | if (m_debug_options.mode_disabled[6]) |
| 1443 | return; |
| 1444 | #endif /* SNES_LAYER_DEBUG */ |
| 1445 | |
| 1446 | update_objects(1, 3, 4, 6); |
| 1447 | update_line(curline, SNES_BG1, 2, 5, SNES_COLOR_DEPTH_4BPP, 1, SNES_OPT_MODE6, 0); |
| 1448 | } |
| 1449 | |
| 1450 | void snes_ppu_device::update_mode_7( UINT16 curline ) |
| 1451 | { |
| 1452 | #if SNES_LAYER_DEBUG |
| 1453 | if (m_debug_options.mode_disabled[7]) |
| 1454 | return; |
| 1455 | #endif /* SNES_LAYER_DEBUG */ |
| 1456 | |
| 1457 | if (!m_mode7.extbg) |
| 1458 | { |
| 1459 | update_objects(1, 3, 4, 5); |
| 1460 | update_line_mode7(curline, SNES_BG1, 2, 2); |
| 1461 | } |
| 1462 | else |
| 1463 | { |
| 1464 | update_objects(2, 4, 6, 7); |
| 1465 | update_line_mode7(curline, SNES_BG1, 3, 3); |
| 1466 | update_line_mode7(curline, SNES_BG2, 1, 5); |
| 1467 | } |
| 1468 | } |
| 1469 | |
| 1470 | /********************************************* |
| 1471 | * snes_draw_screens() |
| 1472 | * |
| 1473 | * Draw the whole screen (Mode 0 -> 7). |
| 1474 | *********************************************/ |
| 1475 | |
| 1476 | void snes_ppu_device::draw_screens( UINT16 curline ) |
| 1477 | { |
| 1478 | switch (m_mode) |
| 1479 | { |
| 1480 | case 0: update_mode_0(curline); break; /* Mode 0 */ |
| 1481 | case 1: update_mode_1(curline); break; /* Mode 1 */ |
| 1482 | case 2: update_mode_2(curline); break; /* Mode 2 - Supports offset per tile */ |
| 1483 | case 3: update_mode_3(curline); break; /* Mode 3 - Supports direct colour */ |
| 1484 | case 4: update_mode_4(curline); break; /* Mode 4 - Supports offset per tile and direct colour */ |
| 1485 | case 5: update_mode_5(curline); break; /* Mode 5 - Supports hires */ |
| 1486 | case 6: update_mode_6(curline); break; /* Mode 6 - Supports offset per tile and hires */ |
| 1487 | case 7: update_mode_7(curline); break; /* Mode 7 - Supports direct colour */ |
| 1488 | } |
| 1489 | } |
| 1490 | |
| 1491 | /********************************************* |
| 1492 | * update_windowmasks() |
| 1493 | * |
| 1494 | * An example of how windows work: |
| 1495 | * Win1: ...#####...... |
| 1496 | * Win2: ......#####... |
| 1497 | * IN OUT |
| 1498 | * OR: ...########... ###........### |
| 1499 | * AND: ......##...... ######..###### |
| 1500 | * XOR: ...###..###... ###...##...### |
| 1501 | * XNOR: ###...##...### ...###..###... |
| 1502 | *********************************************/ |
| 1503 | |
| 1504 | void snes_ppu_device::update_windowmasks( void ) |
| 1505 | { |
| 1506 | UINT16 ii, jj; |
| 1507 | INT8 w1, w2; |
| 1508 | |
| 1509 | m_update_windows = 0; /* reset the flag */ |
| 1510 | |
| 1511 | for (ii = 0; ii < SNES_SCR_WIDTH; ii++) |
| 1512 | { |
| 1513 | /* update bg 1, 2, 3, 4, obj & color windows */ |
| 1514 | /* jj = layer */ |
| 1515 | for (jj = 0; jj < 6; jj++) |
| 1516 | { |
| 1517 | m_clipmasks[jj][ii] = 0xff; /* let's start from un-masked */ |
| 1518 | w1 = w2 = -1; |
| 1519 | |
| 1520 | if (m_layer[jj].window1_enabled) |
| 1521 | { |
| 1522 | /* Default to mask area inside */ |
| 1523 | if ((ii < m_window1_left) || (ii > m_window1_right)) |
| 1524 | w1 = 0; |
| 1525 | else |
| 1526 | w1 = 1; |
| 1527 | |
| 1528 | /* If mask area is outside then swap */ |
| 1529 | if (m_layer[jj].window1_invert) |
| 1530 | w1 = !w1; |
| 1531 | } |
| 1532 | |
| 1533 | if (m_layer[jj].window2_enabled) |
| 1534 | { |
| 1535 | if ((ii < m_window2_left) || (ii > m_window2_right)) |
| 1536 | w2 = 0; |
| 1537 | else |
| 1538 | w2 = 1; |
| 1539 | if (m_layer[jj].window2_invert) |
| 1540 | w2 = !w2; |
| 1541 | } |
| 1542 | |
| 1543 | /* mask if the appropriate expression is true */ |
| 1544 | if (w1 >= 0 && w2 >= 0) |
| 1545 | { |
| 1546 | switch (m_layer[jj].wlog_mask) |
| 1547 | { |
| 1548 | case 0x00: /* OR */ |
| 1549 | m_clipmasks[jj][ii] = (w1 | w2) ? 0x00 : 0xff; |
| 1550 | break; |
| 1551 | case 0x01: /* AND */ |
| 1552 | m_clipmasks[jj][ii] = (w1 & w2) ? 0x00 : 0xff; |
| 1553 | break; |
| 1554 | case 0x02: /* XOR */ |
| 1555 | m_clipmasks[jj][ii] = (w1 ^ w2) ? 0x00 : 0xff; |
| 1556 | break; |
| 1557 | case 0x03: /* XNOR */ |
| 1558 | m_clipmasks[jj][ii] = !(w1 ^ w2) ? 0x00 : 0xff; |
| 1559 | break; |
| 1560 | } |
| 1561 | } |
| 1562 | else if (w1 >= 0) |
| 1563 | m_clipmasks[jj][ii] = w1 ? 0x00 : 0xff; |
| 1564 | else if (w2 >= 0) |
| 1565 | m_clipmasks[jj][ii] = w2 ? 0x00 : 0xff; |
| 1566 | } |
| 1567 | } |
| 1568 | } |
| 1569 | |
| 1570 | /********************************************* |
| 1571 | * update_offsets() |
| 1572 | * |
| 1573 | * Update the offsets with the latest changes. |
| 1574 | * This is currently unused, but it could |
| 1575 | * possibly be handy for some minor optimization |
| 1576 | *********************************************/ |
| 1577 | |
| 1578 | void snes_ppu_device::update_offsets( void ) |
| 1579 | { |
| 1580 | int ii; |
| 1581 | for (ii = 0; ii < 4; ii++) |
| 1582 | { |
| 1583 | } |
| 1584 | m_update_offsets = 0; |
| 1585 | } |
| 1586 | |
| 1587 | /***************************************** |
| 1588 | * draw_blend() |
| 1589 | * |
| 1590 | * Routine for additive/subtractive blending |
| 1591 | * between the main and sub screens, i.e. |
| 1592 | * color math. |
| 1593 | *****************************************/ |
| 1594 | |
| 1595 | inline void snes_ppu_device::draw_blend( UINT16 offset, UINT16 *colour, UINT8 prevent_color_math, UINT8 black_pen_clip, int switch_screens ) |
| 1596 | { |
| 1597 | #if SNES_LAYER_DEBUG |
| 1598 | if (m_debug_options.colormath_disabled) |
| 1599 | return; |
| 1600 | #endif /* SNES_LAYER_DEBUG */ |
| 1601 | |
| 1602 | /* when color math is applied to subscreen pixels, the blending depends on the blending used by the previous mainscreen |
| 1603 | pixel, except for subscreen pixel 0 which has no previous mainscreen pixel, see comments in refresh_scanline */ |
| 1604 | if (switch_screens && offset > 0) |
| 1605 | offset -= 1; |
| 1606 | |
| 1607 | if ((black_pen_clip == SNES_CLIP_ALWAYS) || |
| 1608 | (black_pen_clip == SNES_CLIP_IN && m_clipmasks[SNES_COLOR][offset]) || |
| 1609 | (black_pen_clip == SNES_CLIP_OUT && !m_clipmasks[SNES_COLOR][offset])) |
| 1610 | *colour = 0; //clip to black before color math |
| 1611 | |
| 1612 | if (prevent_color_math == SNES_CLIP_ALWAYS) // blending mode 3 == always OFF |
| 1613 | return; |
| 1614 | |
| 1615 | if ((prevent_color_math == SNES_CLIP_NEVER) || |
| 1616 | (prevent_color_math == SNES_CLIP_IN && !m_clipmasks[SNES_COLOR][offset]) || |
| 1617 | (prevent_color_math == SNES_CLIP_OUT && m_clipmasks[SNES_COLOR][offset])) |
| 1618 | { |
| 1619 | UINT16 r, g, b; |
| 1620 | struct SNES_SCANLINE *subscreen; |
| 1621 | int clip_max = 0; // if add then clip to 0x1f, if sub then clip to 0 |
| 1622 | |
| 1623 | #if SNES_LAYER_DEBUG |
| 1624 | /* Toggle drawing of SNES_SUBSCREEN or SNES_MAINSCREEN */ |
| 1625 | if (m_debug_options.draw_subscreen) |
| 1626 | { |
| 1627 | subscreen = switch_screens ? &m_scanlines[SNES_SUBSCREEN] : &m_scanlines[SNES_MAINSCREEN]; |
| 1628 | } |
| 1629 | else |
| 1630 | #endif /* SNES_LAYER_DEBUG */ |
| 1631 | { |
| 1632 | subscreen = switch_screens ? &m_scanlines[SNES_MAINSCREEN] : &m_scanlines[SNES_SUBSCREEN]; |
| 1633 | } |
| 1634 | |
| 1635 | if (m_sub_add_mode) /* SNES_SUBSCREEN*/ |
| 1636 | { |
| 1637 | if (!BIT(m_color_modes, 7)) |
| 1638 | { |
| 1639 | /* 0x00 add */ |
| 1640 | r = (*colour & 0x1f) + (subscreen->buffer[offset] & 0x1f); |
| 1641 | g = ((*colour & 0x3e0) >> 5) + ((subscreen->buffer[offset] & 0x3e0) >> 5); |
| 1642 | b = ((*colour & 0x7c00) >> 10) + ((subscreen->buffer[offset] & 0x7c00) >> 10); |
| 1643 | clip_max = 1; |
| 1644 | } |
| 1645 | else |
| 1646 | { |
| 1647 | /* 0x80 sub */ |
| 1648 | r = (*colour & 0x1f) - (subscreen->buffer[offset] & 0x1f); |
| 1649 | g = ((*colour & 0x3e0) >> 5) - ((subscreen->buffer[offset] & 0x3e0) >> 5); |
| 1650 | b = ((*colour & 0x7c00) >> 10) - ((subscreen->buffer[offset] & 0x7c00) >> 10); |
| 1651 | if (r > 0x1f) r = 0; |
| 1652 | if (g > 0x1f) g = 0; |
| 1653 | if (b > 0x1f) b = 0; |
| 1654 | } |
| 1655 | /* only halve if the color is not the back colour */ |
| 1656 | if (BIT(m_color_modes, 6) && (subscreen->buffer[offset] != m_cgram[FIXED_COLOUR])) |
| 1657 | { |
| 1658 | r >>= 1; |
| 1659 | g >>= 1; |
| 1660 | b >>= 1; |
| 1661 | } |
| 1662 | } |
| 1663 | else /* Fixed colour */ |
| 1664 | { |
| 1665 | if (!BIT(m_color_modes, 7)) |
| 1666 | { |
| 1667 | /* 0x00 add */ |
| 1668 | r = (*colour & 0x1f) + (m_cgram[FIXED_COLOUR] & 0x1f); |
| 1669 | g = ((*colour & 0x3e0) >> 5) + ((m_cgram[FIXED_COLOUR] & 0x3e0) >> 5); |
| 1670 | b = ((*colour & 0x7c00) >> 10) + ((m_cgram[FIXED_COLOUR] & 0x7c00) >> 10); |
| 1671 | clip_max = 1; |
| 1672 | } |
| 1673 | else |
| 1674 | { |
| 1675 | /* 0x80: sub */ |
| 1676 | r = (*colour & 0x1f) - (m_cgram[FIXED_COLOUR] & 0x1f); |
| 1677 | g = ((*colour & 0x3e0) >> 5) - ((m_cgram[FIXED_COLOUR] & 0x3e0) >> 5); |
| 1678 | b = ((*colour & 0x7c00) >> 10) - ((m_cgram[FIXED_COLOUR] & 0x7c00) >> 10); |
| 1679 | if (r > 0x1f) r = 0; |
| 1680 | if (g > 0x1f) g = 0; |
| 1681 | if (b > 0x1f) b = 0; |
| 1682 | } |
| 1683 | /* halve if necessary */ |
| 1684 | if (BIT(m_color_modes, 6)) |
| 1685 | { |
| 1686 | r >>= 1; |
| 1687 | g >>= 1; |
| 1688 | b >>= 1; |
| 1689 | } |
| 1690 | } |
| 1691 | |
| 1692 | /* according to anomie's docs, after addition has been performed, division by 2 happens *before* clipping to max, hence we clip now */ |
| 1693 | if (clip_max) |
| 1694 | { |
| 1695 | if (r > 0x1f) r = 0x1f; |
| 1696 | if (g > 0x1f) g = 0x1f; |
| 1697 | if (b > 0x1f) b = 0x1f; |
| 1698 | } |
| 1699 | |
| 1700 | *colour = ((r & 0x1f) | ((g & 0x1f) << 5) | ((b & 0x1f) << 10)); |
| 1701 | } |
| 1702 | } |
| 1703 | |
| 1704 | /********************************************* |
| 1705 | * refresh_scanline() |
| 1706 | * |
| 1707 | * Redraw the current line. |
| 1708 | *********************************************/ |
| 1709 | /********************************************* |
| 1710 | * Notice that in hires and pseudo hires modes, |
| 1711 | * i.e. when 512 different pixels are present |
| 1712 | * in a scanline, a crt TV monitor would end |
| 1713 | * up blending adjacent pixels. To mimic this, |
| 1714 | * we add a small (optional) hack which enters |
| 1715 | * only in the very last stage of the scanline |
| 1716 | * drawing and which simulates the TV by |
| 1717 | * replacing the exact pixel color with an |
| 1718 | * average of the current and next pixel colors. |
| 1719 | * Credits (and thanks) to Blargg and Byuu for |
| 1720 | * the optimized averaging algorithm. |
| 1721 | *********************************************/ |
| 1722 | |
| 1723 | void snes_ppu_device::refresh_scanline( running_machine &machine, bitmap_rgb32 &bitmap, UINT16 curline ) |
| 1724 | { |
| 1725 | UINT16 ii; |
| 1726 | int x; |
| 1727 | int fade; |
| 1728 | struct SNES_SCANLINE *scanline1, *scanline2; |
| 1729 | UINT16 c; |
| 1730 | UINT16 prev_colour = 0; |
| 1731 | int blurring = machine.root_device().ioport("OPTIONS")->read_safe(0) & 0x01; |
| 1732 | |
| 1733 | g_profiler.start(PROFILER_VIDEO); |
| 1734 | |
| 1735 | if (m_screen_disabled) /* screen is forced blank */ |
| 1736 | for (x = 0; x < SNES_SCR_WIDTH * 2; x++) |
| 1737 | bitmap.pix32(curline, x) = rgb_t::black; |
| 1738 | else |
| 1739 | { |
| 1740 | /* Update clip window masks if necessary */ |
| 1741 | if (m_update_windows) |
| 1742 | update_windowmasks(); |
| 1743 | /* Update the offsets if necessary */ |
| 1744 | if (m_update_offsets) |
| 1745 | update_offsets(); |
| 1746 | |
| 1747 | /* Clear priority */ |
| 1748 | memset(m_scanlines[SNES_MAINSCREEN].priority, 0, SNES_SCR_WIDTH); |
| 1749 | memset(m_scanlines[SNES_SUBSCREEN].priority, 0, SNES_SCR_WIDTH); |
| 1750 | |
| 1751 | /* Clear layers */ |
| 1752 | memset(m_scanlines[SNES_MAINSCREEN].layer, SNES_COLOR, SNES_SCR_WIDTH); |
| 1753 | memset(m_scanlines[SNES_SUBSCREEN].layer, SNES_COLOR, SNES_SCR_WIDTH); |
| 1754 | |
| 1755 | /* Clear blend_exception (only used for OAM) */ |
| 1756 | memset(m_scanlines[SNES_MAINSCREEN].blend_exception, 0, SNES_SCR_WIDTH); |
| 1757 | memset(m_scanlines[SNES_SUBSCREEN].blend_exception, 0, SNES_SCR_WIDTH); |
| 1758 | |
| 1759 | /* Draw back colour */ |
| 1760 | for (ii = 0; ii < SNES_SCR_WIDTH; ii++) |
| 1761 | { |
| 1762 | if (m_mode == 5 || m_mode == 6 || m_pseudo_hires) |
| 1763 | m_scanlines[SNES_SUBSCREEN].buffer[ii] = m_cgram[0]; |
| 1764 | else |
| 1765 | m_scanlines[SNES_SUBSCREEN].buffer[ii] = m_cgram[FIXED_COLOUR]; |
| 1766 | |
| 1767 | m_scanlines[SNES_MAINSCREEN].buffer[ii] = m_cgram[0]; |
| 1768 | } |
| 1769 | |
| 1770 | /* Prepare OAM for this scanline */ |
| 1771 | update_objects_rto(curline); |
| 1772 | |
| 1773 | /* Draw scanline */ |
| 1774 | draw_screens(curline); |
| 1775 | |
| 1776 | update_obsel(); |
| 1777 | |
| 1778 | #if SNES_LAYER_DEBUG |
| 1779 | if (dbg_video(machine, curline)) |
| 1780 | { |
| 1781 | g_profiler.stop(); |
| 1782 | return; |
| 1783 | } |
| 1784 | |
| 1785 | /* Toggle drawing of SNES_SUBSCREEN or SNES_MAINSCREEN */ |
| 1786 | if (m_debug_options.draw_subscreen) |
| 1787 | { |
| 1788 | scanline1 = &m_scanlines[SNES_SUBSCREEN]; |
| 1789 | scanline2 = &m_scanlines[SNES_MAINSCREEN]; |
| 1790 | } |
| 1791 | else |
| 1792 | #endif /* SNES_LAYER_DEBUG */ |
| 1793 | { |
| 1794 | scanline1 = &m_scanlines[SNES_MAINSCREEN]; |
| 1795 | scanline2 = &m_scanlines[SNES_SUBSCREEN]; |
| 1796 | } |
| 1797 | |
| 1798 | /* Draw the scanline to screen */ |
| 1799 | |
| 1800 | fade = m_screen_brightness; |
| 1801 | |
| 1802 | for (x = 0; x < SNES_SCR_WIDTH; x++) |
| 1803 | { |
| 1804 | int r, g, b, hires; |
| 1805 | UINT16 tmp_col[2]; |
| 1806 | hires = (m_mode != 5 && m_mode != 6 && !m_pseudo_hires) ? 0 : 1; |
| 1807 | |
| 1808 | /* in hires, the first pixel (of 512) is subscreen pixel, then the first mainscreen pixel follows, and so on... */ |
| 1809 | if (!hires) |
| 1810 | { |
| 1811 | c = scanline1->buffer[x]; |
| 1812 | |
| 1813 | /* perform color math if the layer wants it (except if it's an object > 192) */ |
| 1814 | if (!scanline1->blend_exception[x] && m_layer[scanline1->layer[x]].color_math) |
| 1815 | draw_blend(x, &c, m_prevent_color_math, m_clip_to_black, 0); |
| 1816 | |
| 1817 | r = ((c & 0x1f) * fade) >> 4; |
| 1818 | g = (((c & 0x3e0) >> 5) * fade) >> 4; |
| 1819 | b = (((c & 0x7c00) >> 10) * fade) >> 4; |
| 1820 | |
| 1821 | bitmap.pix32(curline, x * 2 + 0) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b)); |
| 1822 | bitmap.pix32(curline, x * 2 + 1) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b)); |
| 1823 | } |
| 1824 | else |
| 1825 | { |
| 1826 | /* prepare the pixel from main screen */ |
| 1827 | c = scanline1->buffer[x]; |
| 1828 | |
| 1829 | /* perform color math if the layer wants it (except if it's an object > 192) */ |
| 1830 | if (!scanline1->blend_exception[x] && m_layer[scanline1->layer[x]].color_math) |
| 1831 | draw_blend(x, &c, m_prevent_color_math, m_clip_to_black, 0); |
| 1832 | |
| 1833 | tmp_col[1] = c; |
| 1834 | |
| 1835 | /* prepare the pixel from sub screen */ |
| 1836 | c = scanline2->buffer[x]; |
| 1837 | |
| 1838 | /* in hires/pseudo-hires, subscreen pixels are blended as well: for each subscreen pixel, color math |
| 1839 | is applied if it had been applied to the previous mainscreen pixel. What happens at subscreen pixel 0 |
| 1840 | (which has no previous mainscreen pixel) is undocumented. Until more info are discovered, we (arbitrarily) |
| 1841 | apply to it the same color math as the *next* mainscreen pixel (i.e. mainscreen pixel 0), which seems as good as |
| 1842 | any other choice */ |
| 1843 | if (x == 0 && !scanline1->blend_exception[0] && m_layer[scanline1->layer[0]].color_math) |
| 1844 | draw_blend(0, &c, m_prevent_color_math, m_clip_to_black, 1); |
| 1845 | else if (x > 0 && !scanline1->blend_exception[x - 1] && m_layer[scanline1->layer[x - 1]].color_math) |
| 1846 | draw_blend(x, &c, m_prevent_color_math, m_clip_to_black, 1); |
| 1847 | |
| 1848 | tmp_col[0] = c; |
| 1849 | |
| 1850 | /* average the first pixel if required, or draw it directly*/ |
| 1851 | if (blurring) |
| 1852 | c = (prev_colour + tmp_col[0] - ((prev_colour ^ tmp_col[0]) & 0x0421)) >> 1; // Hack code to mimic TV pixel blurring |
| 1853 | else |
| 1854 | c = tmp_col[0]; |
| 1855 | |
| 1856 | r = ((c & 0x1f) * fade) >> 4; |
| 1857 | g = (((c & 0x3e0) >> 5) * fade) >> 4; |
| 1858 | b = (((c & 0x7c00) >> 10) * fade) >> 4; |
| 1859 | |
| 1860 | bitmap.pix32(curline, x * 2 + 0) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b)); |
| 1861 | prev_colour = tmp_col[0]; |
| 1862 | |
| 1863 | /* average the second pixel if required, or draw it directly*/ |
| 1864 | if (blurring) |
| 1865 | c = (prev_colour + tmp_col[1] - ((prev_colour ^ tmp_col[1]) & 0x0421)) >> 1; // Hack code to mimic TV pixel blurring |
| 1866 | else |
| 1867 | c = tmp_col[1]; |
| 1868 | |
| 1869 | r = ((c & 0x1f) * fade) >> 4; |
| 1870 | g = (((c & 0x3e0) >> 5) * fade) >> 4; |
| 1871 | b = (((c & 0x7c00) >> 10) * fade) >> 4; |
| 1872 | |
| 1873 | bitmap.pix32(curline, x * 2 + 1) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b)); |
| 1874 | prev_colour = tmp_col[1]; |
| 1875 | } |
| 1876 | } |
| 1877 | } |
| 1878 | |
| 1879 | g_profiler.stop(); |
| 1880 | } |
| 1881 | |
| 1882 | |
| 1883 | /* CPU <-> PPU comms */ |
| 1884 | |
| 1885 | // full graphic variables |
| 1886 | static const UINT16 vram_fgr_inctab[4] = { 1, 32, 128, 128 }; |
| 1887 | static const UINT16 vram_fgr_inccnts[4] = { 0, 32, 64, 128 }; |
| 1888 | static const UINT16 vram_fgr_shiftab[4] = { 0, 5, 6, 7 }; |
| 1889 | |
| 1890 | // utility function - latches the H/V counters. Used by IRQ, writes to WRIO, etc. |
| 1891 | void snes_ppu_device::latch_counters( running_machine &machine ) |
| 1892 | { |
| 1893 | m_beam.current_horz = machine.first_screen()->hpos() / m_htmult; |
| 1894 | m_beam.latch_vert = machine.first_screen()->vpos(); |
| 1895 | m_beam.latch_horz = m_beam.current_horz; |
| 1896 | m_stat78 |= 0x40; // indicate we latched |
| 1897 | // m_read_ophct = m_read_opvct = 0; // clear read flags - 2009-08: I think we must clear these when STAT78 is read... |
| 1898 | |
| 1899 | // printf("latched @ H %d V %d\n", m_beam.latch_horz, m_beam.latch_vert); |
| 1900 | } |
| 1901 | |
| 1902 | void snes_ppu_device::dynamic_res_change( running_machine &machine ) |
| 1903 | { |
| 1904 | rectangle visarea = machine.first_screen()->visible_area(); |
| 1905 | attoseconds_t refresh; |
| 1906 | |
| 1907 | visarea.min_x = visarea.min_y = 0; |
| 1908 | visarea.max_y = m_beam.last_visible_line * m_interlace - 1; |
| 1909 | visarea.max_x = (SNES_SCR_WIDTH * 2) - 1; |
| 1910 | |
| 1911 | // fixme: should compensate for SNES_DBG_VIDEO |
| 1912 | if (m_mode == 5 || m_mode == 6 || m_pseudo_hires) |
| 1913 | m_htmult = 2; |
| 1914 | else |
| 1915 | m_htmult = 1; |
| 1916 | |
| 1917 | /* FIXME: does the timing changes when the gfx mode is equal to 5 or 6? */ |
| 1918 | if ((m_stat78 & 0x10) == SNES_NTSC) |
| 1919 | { |
| 1920 | refresh = HZ_TO_ATTOSECONDS(DOTCLK_NTSC) * SNES_HTOTAL * SNES_VTOTAL_NTSC; |
| 1921 | machine.first_screen()->configure(SNES_HTOTAL * 2, SNES_VTOTAL_NTSC * m_interlace, visarea, refresh); |
| 1922 | } |
| 1923 | else |
| 1924 | { |
| 1925 | refresh = HZ_TO_ATTOSECONDS(DOTCLK_PAL) * SNES_HTOTAL * SNES_VTOTAL_PAL; |
| 1926 | machine.first_screen()->configure(SNES_HTOTAL * 2, SNES_VTOTAL_PAL * m_interlace, visarea, refresh); |
| 1927 | } |
| 1928 | } |
| 1929 | |
| 1930 | /************************************************* |
| 1931 | |
| 1932 | SNES VRAM accesses: |
| 1933 | |
| 1934 | VRAM accesses during active display are invalid. |
| 1935 | Unlike OAM and CGRAM, they will not be written |
| 1936 | anywhere at all. Thanks to byuu's researches, |
| 1937 | the ranges where writes are invalid have been |
| 1938 | validated on hardware, as has the edge case where |
| 1939 | the S-CPU open bus can be written if the write |
| 1940 | occurs during the very last clock cycle of |
| 1941 | vblank. |
| 1942 | Our implementation could be not 100% accurate |
| 1943 | when interlace is active. |
| 1944 | *************************************************/ |
| 1945 | |
| 1946 | inline UINT32 snes_ppu_device::get_vram_address( running_machine &machine ) |
| 1947 | { |
| 1948 | UINT32 addr = m_vmadd; |
| 1949 | |
| 1950 | if (m_vram_fgr_count) |
| 1951 | { |
| 1952 | UINT32 rem = addr & m_vram_fgr_mask; |
| 1953 | UINT32 faddr = (addr & ~m_vram_fgr_mask) + (rem >> m_vram_fgr_shift) + ((rem & (m_vram_fgr_count - 1)) << 3); |
| 1954 | return faddr << 1; |
| 1955 | } |
| 1956 | |
| 1957 | return addr << 1; |
| 1958 | } |
| 1959 | |
| 1960 | READ8_MEMBER( snes_ppu_device::vram_read ) |
| 1961 | { |
| 1962 | UINT8 res = 0; |
| 1963 | offset &= 0xffff; // only 64KB are present on SNES |
| 1964 | |
| 1965 | if (m_screen_disabled) |
| 1966 | res = m_vram[offset]; |
| 1967 | else |
| 1968 | { |
| 1969 | UINT16 v = m_screen->vpos(); |
| 1970 | UINT16 h = m_screen->hpos(); |
| 1971 | UINT16 ls = (((m_stat78 & 0x10) == SNES_NTSC ? 525 : 625) >> 1) - 1; |
| 1972 | |
| 1973 | if (m_interlace == 2) |
| 1974 | ls++; |
| 1975 | |
| 1976 | if (v == ls && h == 1362) |
| 1977 | res = 0; |
| 1978 | else if (v < m_beam.last_visible_line - 1) |
| 1979 | res = 0; |
| 1980 | else if (v == m_beam.last_visible_line - 1) |
| 1981 | { |
| 1982 | if (h == 1362) |
| 1983 | res = m_vram[offset]; |
| 1984 | else |
| 1985 | { |
| 1986 | //printf("%d %d VRAM read, CHECK!\n",h,v); |
| 1987 | res = 0; |
| 1988 | } |
| 1989 | } |
| 1990 | else |
| 1991 | res = m_vram[offset]; |
| 1992 | } |
| 1993 | return res; |
| 1994 | } |
| 1995 | |
| 1996 | WRITE8_MEMBER( snes_ppu_device::vram_write ) |
| 1997 | { |
| 1998 | offset &= 0xffff; // only 64KB are present on SNES, Robocop 3 relies on this |
| 1999 | |
| 2000 | if (m_screen_disabled) |
| 2001 | m_vram[offset] = data; |
| 2002 | else |
| 2003 | { |
| 2004 | UINT16 v = m_screen->vpos(); |
| 2005 | UINT16 h = m_screen->hpos(); |
| 2006 | if (v == 0) |
| 2007 | { |
| 2008 | if (h <= 4) |
| 2009 | m_vram[offset] = data; |
| 2010 | else if (h == 6) |
| 2011 | m_vram[offset] = m_openbus_cb(space, 0); |
| 2012 | else |
| 2013 | { |
| 2014 | //printf("%d %d VRAM write, CHECK!\n",h,v); |
| 2015 | //no write |
| 2016 | } |
| 2017 | } |
| 2018 | else if (v < m_beam.last_visible_line) |
| 2019 | { |
| 2020 | //printf("%d %d VRAM write, CHECK!\n",h,v); |
| 2021 | //no write |
| 2022 | } |
| 2023 | else if (v == m_beam.last_visible_line) |
| 2024 | { |
| 2025 | if (h <= 4) |
| 2026 | { |
| 2027 | //printf("%d %d VRAM write, CHECK!\n",h,v); |
| 2028 | //no write |
| 2029 | } |
| 2030 | else |
| 2031 | m_vram[offset] = data; |
| 2032 | } |
| 2033 | else |
| 2034 | m_vram[offset] = data; |
| 2035 | } |
| 2036 | } |
| 2037 | |
| 2038 | /************************************************* |
| 2039 | |
| 2040 | SNES OAM accesses: |
| 2041 | |
| 2042 | OAM accesses during active display are allowed. |
| 2043 | The actual address varies during rendering, as the |
| 2044 | PPU reads in data itself for processing. |
| 2045 | Unfortunately, no one has been able (yet) to |
| 2046 | determine how this works. The only known game to |
| 2047 | actually access OAM during active display is |
| 2048 | Uniracers and it expects accesses to map to |
| 2049 | offset 0x0218. Hence, following byuu's choice |
| 2050 | we rerouted OAM accesses during active display |
| 2051 | to 0x0218 (0x010c in our snes_oam). |
| 2052 | This is a hack, but it is more accurate than |
| 2053 | writing to the 'expected' address set by |
| 2054 | $2102,$2103. |
| 2055 | |
| 2056 | Notice that, since PPU_REG(OAMDATA) is never |
| 2057 | read/written directly, we use it as an index |
| 2058 | to choose the high/low byte of the snes_oam word. |
| 2059 | *************************************************/ |
| 2060 | |
| 2061 | READ8_MEMBER( snes_ppu_device::oam_read ) |
| 2062 | { |
| 2063 | offset &= 0x1ff; |
| 2064 | |
| 2065 | if (offset & 0x100) |
| 2066 | offset &= 0x10f; |
| 2067 | |
| 2068 | if (!m_screen_disabled) |
| 2069 | { |
| 2070 | UINT16 v = m_screen->vpos(); |
| 2071 | |
| 2072 | if (v < m_beam.last_visible_line) |
| 2073 | offset = 0x010c; |
| 2074 | } |
| 2075 | |
| 2076 | return (m_oam_ram[offset] >> (PPU_REG(OAMDATA) << 3)) & 0xff; |
| 2077 | } |
| 2078 | |
| 2079 | WRITE8_MEMBER( snes_ppu_device::oam_write ) |
| 2080 | { |
| 2081 | offset &= 0x1ff; |
| 2082 | |
| 2083 | if (offset & 0x100) |
| 2084 | offset &= 0x10f; |
| 2085 | |
| 2086 | if (!m_screen_disabled) |
| 2087 | { |
| 2088 | UINT16 v = m_screen->vpos(); |
| 2089 | |
| 2090 | if (v < m_beam.last_visible_line) |
| 2091 | offset = 0x010c; |
| 2092 | } |
| 2093 | |
| 2094 | if (!(PPU_REG(OAMDATA))) |
| 2095 | m_oam_ram[offset] = (m_oam_ram[offset] & 0xff00) | (data << 0); |
| 2096 | else |
| 2097 | m_oam_ram[offset] = (m_oam_ram[offset] & 0x00ff) | (data << 8); |
| 2098 | } |
| 2099 | |
| 2100 | /************************************************* |
| 2101 | |
| 2102 | SNES CGRAM accesses: |
| 2103 | |
| 2104 | CGRAM writes during hblank are valid. During |
| 2105 | active display, the actual address the data |
| 2106 | is written to varies, as the PPU itself changes |
| 2107 | the address. Like OAM, it is not known the exact |
| 2108 | algorithm used, but no commercial software seems |
| 2109 | to attempt this. While byuu, in his emu, maps |
| 2110 | those accesses to 0x01ff, because it is more |
| 2111 | accurate to invalidate the 'expected' address |
| 2112 | than not, MESS has issues if we don't write to |
| 2113 | the expected address (see e.g. Tokimeki Memorial). |
| 2114 | This is because writes should work during hblank |
| 2115 | (so that the game can produce color fading), but |
| 2116 | ends up not working with the conditions below. |
| 2117 | Hence, for the moment, we only document the |
| 2118 | solution adopted by BSNES without enabling it. |
| 2119 | *************************************************/ |
| 2120 | |
| 2121 | READ8_MEMBER( snes_ppu_device::cgram_read ) |
| 2122 | { |
| 2123 | UINT8 res = 0; |
| 2124 | offset &= 0x1ff; |
| 2125 | |
| 2126 | #if 0 |
| 2127 | if (!m_screen_disabled) |
| 2128 | { |
| 2129 | UINT16 v = m_screen->vpos(); |
| 2130 | UINT16 h = m_screen->hpos(); |
| 2131 | |
| 2132 | if (v < m_beam.last_visible_line && h >= 128 && h < 1096) |
| 2133 | offset = 0x1ff; |
| 2134 | } |
| 2135 | #endif |
| 2136 | |
| 2137 | res = ((UINT8 *)m_cgram)[offset]; |
| 2138 | |
| 2139 | // CGRAM palette data format is 15-bits (0,bbbbb,ggggg,rrrrr). |
| 2140 | // Highest bit is simply ignored. |
| 2141 | if (offset & 0x01) |
| 2142 | res &= 0x7f; |
| 2143 | |
| 2144 | return res; |
| 2145 | } |
| 2146 | |
| 2147 | WRITE8_MEMBER( snes_ppu_device::cgram_write ) |
| 2148 | { |
| 2149 | offset &= 0x1ff; |
| 2150 | |
| 2151 | #if 0 |
| 2152 | // FIXME: this currently breaks some games (e.g. Tokimeki Memorial), |
| 2153 | // even if it's expected to be more accurate than allowing for |
| 2154 | // writes to the cgram address |
| 2155 | if (!m_screen_disabled) |
| 2156 | { |
| 2157 | UINT16 v = m_screen->vpos(); |
| 2158 | UINT16 h = m_screen->hpos(); |
| 2159 | |
| 2160 | if (v < m_beam.last_visible_line && h >= 128 && h < 1096) |
| 2161 | offset = 0x1ff; |
| 2162 | } |
| 2163 | #endif |
| 2164 | |
| 2165 | // CGRAM palette data format is 15-bits (0,bbbbb,ggggg,rrrrr). |
| 2166 | // Highest bit is simply ignored. |
| 2167 | if (offset & 0x01) |
| 2168 | data &= 0x7f; |
| 2169 | |
| 2170 | ((UINT8 *)m_cgram)[offset] = data; |
| 2171 | } |
| 2172 | |
| 2173 | UINT8 snes_ppu_device::read(address_space &space, UINT32 offset, UINT8 wrio_bit7) |
| 2174 | { |
| 2175 | UINT8 value; |
| 2176 | |
| 2177 | switch (offset) |
| 2178 | { |
| 2179 | case OAMDATA: /* 21xy for x=0,1,2 and y=4,5,6,8,9,a returns PPU1 open bus*/ |
| 2180 | case BGMODE: |
| 2181 | case MOSAIC: |
| 2182 | case BG2SC: |
| 2183 | case BG3SC: |
| 2184 | case BG4SC: |
| 2185 | case BG4VOFS: |
| 2186 | case VMAIN: |
| 2187 | case VMADDL: |
| 2188 | case VMDATAL: |
| 2189 | case VMDATAH: |
| 2190 | case M7SEL: |
| 2191 | case W34SEL: |
| 2192 | case WOBJSEL: |
| 2193 | case WH0: |
| 2194 | case WH2: |
| 2195 | case WH3: |
| 2196 | case WBGLOG: |
| 2197 | return m_ppu1_open_bus; |
| 2198 | |
| 2199 | case MPYL: /* Multiplication result (low) */ |
| 2200 | { |
| 2201 | /* Perform 16bit * 8bit multiply */ |
| 2202 | UINT32 c = (INT16)m_mode7.matrix_a * (INT8)(m_mode7.matrix_b >> 8); |
| 2203 | m_ppu1_open_bus = c & 0xff; |
| 2204 | return m_ppu1_open_bus; |
| 2205 | } |
| 2206 | case MPYM: /* Multiplication result (mid) */ |
| 2207 | { |
| 2208 | /* Perform 16bit * 8bit multiply */ |
| 2209 | UINT32 c = (INT16)m_mode7.matrix_a * (INT8)(m_mode7.matrix_b >> 8); |
| 2210 | m_ppu1_open_bus = (c >> 8) & 0xff; |
| 2211 | return m_ppu1_open_bus; |
| 2212 | } |
| 2213 | case MPYH: /* Multiplication result (high) */ |
| 2214 | { |
| 2215 | /* Perform 16bit * 8bit multiply */ |
| 2216 | UINT32 c = (INT16)m_mode7.matrix_a * (INT8)(m_mode7.matrix_b >> 8); |
| 2217 | m_ppu1_open_bus = (c >> 16) & 0xff; |
| 2218 | return m_ppu1_open_bus; |
| 2219 | } |
| 2220 | case SLHV: /* Software latch for H/V counter */ |
| 2221 | latch_counters(space.machine()); |
| 2222 | return m_openbus_cb(space, 0); /* Return value is meaningless */ |
| 2223 | |
| 2224 | case ROAMDATA: /* Read data from OAM (DR) */ |
| 2225 | m_ppu1_open_bus = oam_read(space, m_oam.address); |
| 2226 | PPU_REG(OAMDATA) = (PPU_REG(OAMDATA) + 1) % 2; |
| 2227 | if (!PPU_REG(OAMDATA)) |
| 2228 | { |
| 2229 | m_oam.address++; |
| 2230 | m_oam.address &= 0x1ff; |
| 2231 | m_oam.first_sprite = m_oam.priority_rotation ? (m_oam.address >> 1) & 127 : 0; |
| 2232 | } |
| 2233 | return m_ppu1_open_bus; |
| 2234 | case RVMDATAL: /* Read data from VRAM (low) */ |
| 2235 | { |
| 2236 | UINT32 addr = get_vram_address(space.machine()); |
| 2237 | m_ppu1_open_bus = m_vram_read_buffer & 0xff; |
| 2238 | |
| 2239 | if (!m_vram_fgr_high) |
| 2240 | { |
| 2241 | m_vram_read_buffer = vram_read(space, addr); |
| 2242 | m_vram_read_buffer |= (vram_read(space, addr + 1) << 8); |
| 2243 | |
| 2244 | m_vmadd = (m_vmadd + m_vram_fgr_increment) & 0xffff; |
| 2245 | } |
| 2246 | |
| 2247 | return m_ppu1_open_bus; |
| 2248 | } |
| 2249 | case RVMDATAH: /* Read data from VRAM (high) */ |
| 2250 | { |
| 2251 | UINT32 addr = get_vram_address(space.machine()); |
| 2252 | m_ppu1_open_bus = (m_vram_read_buffer >> 8) & 0xff; |
| 2253 | |
| 2254 | if (m_vram_fgr_high) |
| 2255 | { |
| 2256 | m_vram_read_buffer = vram_read(space, addr); |
| 2257 | m_vram_read_buffer |= (vram_read(space, addr + 1) << 8); |
| 2258 | |
| 2259 | m_vmadd = (m_vmadd + m_vram_fgr_increment) & 0xffff; |
| 2260 | } |
| 2261 | |
| 2262 | return m_ppu1_open_bus; |
| 2263 | } |
| 2264 | case RCGDATA: /* Read data from CGRAM */ |
| 2265 | if (!(m_cgram_address & 0x01)) |
| 2266 | m_ppu2_open_bus = cgram_read(space, m_cgram_address); |
| 2267 | else |
| 2268 | { |
| 2269 | m_ppu2_open_bus &= 0x80; |
| 2270 | m_ppu2_open_bus |= cgram_read(space, m_cgram_address) & 0x7f; |
| 2271 | } |
| 2272 | |
| 2273 | m_cgram_address = (m_cgram_address + 1) % (SNES_CGRAM_SIZE - 2); |
| 2274 | return m_ppu2_open_bus; |
| 2275 | case OPHCT: /* Horizontal counter data by ext/soft latch */ |
| 2276 | if (m_read_ophct) |
| 2277 | { |
| 2278 | m_ppu2_open_bus &= 0xfe; |
| 2279 | m_ppu2_open_bus |= (m_beam.latch_horz >> 8) & 0x01; |
| 2280 | } |
| 2281 | else |
| 2282 | { |
| 2283 | m_ppu2_open_bus = m_beam.latch_horz & 0xff; |
| 2284 | } |
| 2285 | m_read_ophct ^= 1; |
| 2286 | return m_ppu2_open_bus; |
| 2287 | case OPVCT: /* Vertical counter data by ext/soft latch */ |
| 2288 | if (m_read_opvct) |
| 2289 | { |
| 2290 | m_ppu2_open_bus &= 0xfe; |
| 2291 | m_ppu2_open_bus |= (m_beam.latch_vert >> 8) & 0x01; |
| 2292 | } |
| 2293 | else |
| 2294 | { |
| 2295 | m_ppu2_open_bus = m_beam.latch_vert & 0xff; |
| 2296 | } |
| 2297 | m_read_opvct ^= 1; |
| 2298 | return m_ppu2_open_bus; |
| 2299 | case STAT77: /* PPU status flag and version number */ |
| 2300 | value = m_stat77 & 0xc0; // 0x80 & 0x40 are Time Over / Range Over Sprite flags, set by the video code |
| 2301 | // 0x20 - Master/slave mode select. Little is known about this bit. We always seem to read back 0 here. |
| 2302 | value |= (m_ppu1_open_bus & 0x10); |
| 2303 | value |= (m_ppu1_version & 0x0f); |
| 2304 | m_stat77 = value; // not sure if this is needed... |
| 2305 | m_ppu1_open_bus = value; |
| 2306 | return m_ppu1_open_bus; |
| 2307 | case STAT78: /* PPU status flag and version number */ |
| 2308 | m_read_ophct = 0; |
| 2309 | m_read_opvct = 0; |
| 2310 | if (wrio_bit7) |
| 2311 | m_stat78 &= ~0x40; //clear ext latch if bit 7 of WRIO is set |
| 2312 | m_stat78 = (m_stat78 & ~0x2f) | (m_ppu2_open_bus & 0x20) | (m_ppu2_version & 0x0f); |
| 2313 | m_ppu2_open_bus = m_stat78; |
| 2314 | return m_ppu2_open_bus; |
| 2315 | } |
| 2316 | |
| 2317 | /* note: remaining registers (Namely TM in Super Kick Boxing) returns MDR open bus, not PPU Open Bus! */ |
| 2318 | return m_openbus_cb(space, 0); |
| 2319 | } |
| 2320 | |
| 2321 | |
| 2322 | void snes_ppu_device::write(address_space &space, UINT32 offset, UINT8 data) |
| 2323 | { |
| 2324 | switch (offset) |
| 2325 | { |
| 2326 | case INIDISP: /* Initial settings for screen */ |
| 2327 | if ((m_screen_disabled & 0x80) && (!(data & 0x80))) //a 1->0 force blank transition causes a reset OAM address |
| 2328 | { |
| 2329 | space.write_byte(OAMADDL, m_oam.saved_address_low); |
| 2330 | space.write_byte(OAMADDH, m_oam.saved_address_high); |
| 2331 | m_oam.first_sprite = m_oam.priority_rotation ? (m_oam.address >> 1) & 127 : 0; |
| 2332 | } |
| 2333 | m_screen_disabled = data & 0x80; |
| 2334 | m_screen_brightness = (data & 0x0f) + 1; |
| 2335 | break; |
| 2336 | case OBSEL: /* Object size and data area designation */ |
| 2337 | m_oam.next_charmap = (data & 0x03) << 1; |
| 2338 | m_oam.next_name_select = (((data & 0x18) >> 3) * 0x1000) << 1; |
| 2339 | m_oam.next_size = (data & 0xe0) >> 5; |
| 2340 | break; |
| 2341 | case OAMADDL: /* Address for accessing OAM (low) */ |
| 2342 | m_oam.saved_address_low = data; |
| 2343 | m_oam.address = (m_oam.address & 0xff00) + data; |
| 2344 | m_oam.first_sprite = m_oam.priority_rotation ? (m_oam.address >> 1) & 127 : 0; |
| 2345 | PPU_REG(OAMDATA) = 0; |
| 2346 | break; |
| 2347 | case OAMADDH: /* Address for accessing OAM (high) */ |
| 2348 | m_oam.saved_address_high = data; |
| 2349 | m_oam.address = (m_oam.address & 0x00ff) | ((data & 0x01) << 8); |
| 2350 | m_oam.priority_rotation = BIT(data, 7); |
| 2351 | m_oam.first_sprite = m_oam.priority_rotation ? (m_oam.address >> 1) & 127 : 0; |
| 2352 | PPU_REG(OAMDATA) = 0; |
| 2353 | break; |
| 2354 | case OAMDATA: /* Data for OAM write (DW) */ |
| 2355 | if (m_oam.address >= 0x100) |
| 2356 | oam_write(space, m_oam.address, data); |
| 2357 | else |
| 2358 | { |
| 2359 | if (!PPU_REG(OAMDATA)) |
| 2360 | m_oam.write_latch = data; |
| 2361 | else |
| 2362 | { |
| 2363 | // in this case, we not only write data to the upper byte of the word, |
| 2364 | // but also m_oam.write_latch to the lower byte (recall that |
| 2365 | // PPU_REG(OAMDATA) is used to select high/low byte) |
| 2366 | oam_write(space, m_oam.address, data); |
| 2367 | PPU_REG(OAMDATA) = 0; |
| 2368 | oam_write(space, m_oam.address, m_oam.write_latch); |
| 2369 | PPU_REG(OAMDATA) = 1; |
| 2370 | } |
| 2371 | } |
| 2372 | PPU_REG(OAMDATA) = (PPU_REG(OAMDATA) + 1) % 2; |
| 2373 | if (!PPU_REG(OAMDATA)) |
| 2374 | { |
| 2375 | m_oam.address++; |
| 2376 | m_oam.address &= 0x1ff; |
| 2377 | m_oam.first_sprite = m_oam.priority_rotation ? (m_oam.address >> 1) & 127 : 0; |
| 2378 | } |
| 2379 | return; |
| 2380 | case BGMODE: /* BG mode and character size settings */ |
| 2381 | m_mode = data & 0x07; |
| 2382 | dynamic_res_change(space.machine()); |
| 2383 | m_bg3_priority_bit = BIT(data, 3); |
| 2384 | m_layer[SNES_BG1].tile_size = BIT(data, 4); |
| 2385 | m_layer[SNES_BG2].tile_size = BIT(data, 5); |
| 2386 | m_layer[SNES_BG3].tile_size = BIT(data, 6); |
| 2387 | m_layer[SNES_BG4].tile_size = BIT(data, 7); |
| 2388 | m_update_offsets = 1; |
| 2389 | break; |
| 2390 | case MOSAIC: /* Size and screen designation for mosaic */ |
| 2391 | m_mosaic_size = (data & 0xf0) >> 4; |
| 2392 | m_layer[SNES_BG1].mosaic_enabled = BIT(data, 0); |
| 2393 | m_layer[SNES_BG2].mosaic_enabled = BIT(data, 1); |
| 2394 | m_layer[SNES_BG3].mosaic_enabled = BIT(data, 2); |
| 2395 | m_layer[SNES_BG4].mosaic_enabled = BIT(data, 3); |
| 2396 | break; |
| 2397 | case BG1SC: /* Address for storing SC data BG1 SC size designation */ |
| 2398 | case BG2SC: /* Address for storing SC data BG2 SC size designation */ |
| 2399 | case BG3SC: /* Address for storing SC data BG3 SC size designation */ |
| 2400 | case BG4SC: /* Address for storing SC data BG4 SC size designation */ |
| 2401 | m_layer[offset - BG1SC].tilemap = data & 0xfc; |
| 2402 | m_layer[offset - BG1SC].tilemap_size = data & 0x3; |
| 2403 | break; |
| 2404 | case BG12NBA: /* Address for BG 1 and 2 character data */ |
| 2405 | m_layer[SNES_BG1].charmap = (data & 0x0f); |
| 2406 | m_layer[SNES_BG2].charmap = (data & 0xf0) >> 4; |
| 2407 | break; |
| 2408 | case BG34NBA: /* Address for BG 3 and 4 character data */ |
| 2409 | m_layer[SNES_BG3].charmap = (data & 0x0f); |
| 2410 | m_layer[SNES_BG4].charmap = (data & 0xf0) >> 4; |
| 2411 | break; |
| 2412 | |
| 2413 | // 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! |
| 2414 | case BG1HOFS: /* BG1 - horizontal scroll (DW) */ |
| 2415 | /* In Mode 0->6 we use ppu_last_scroll as Prev */ |
| 2416 | m_layer[SNES_BG1].hoffs = (data << 8) | (m_ppu_last_scroll & ~7) | ((m_layer[SNES_BG1].hoffs >> 8) & 7); |
| 2417 | m_ppu_last_scroll = data; |
| 2418 | /* In Mode 7 we use mode7_last_scroll as Prev */ |
| 2419 | m_mode7.hor_offset = (data << 8) | (m_mode7_last_scroll & ~7) | ((m_mode7.hor_offset >> 8) & 7); |
| 2420 | m_mode7_last_scroll = data; |
| 2421 | m_update_offsets = 1; |
| 2422 | return; |
| 2423 | case BG1VOFS: /* BG1 - vertical scroll (DW) */ |
| 2424 | /* In Mode 0->6 we use ppu_last_scroll as Prev */ |
| 2425 | m_layer[SNES_BG1].voffs = (data << 8) | m_ppu_last_scroll; |
| 2426 | m_ppu_last_scroll = data; |
| 2427 | /* In Mode 7 we use mode7_last_scroll as Prev */ |
| 2428 | m_mode7.ver_offset = (data << 8) | m_mode7_last_scroll; |
| 2429 | m_mode7_last_scroll = data; |
| 2430 | m_update_offsets = 1; |
| 2431 | return; |
| 2432 | case BG2HOFS: /* BG2 - horizontal scroll (DW) */ |
| 2433 | m_layer[SNES_BG2].hoffs = (data << 8) | (m_ppu_last_scroll & ~7) | ((m_layer[SNES_BG2].hoffs >> 8) & 7); |
| 2434 | m_ppu_last_scroll = data; |
| 2435 | m_update_offsets = 1; |
| 2436 | return; |
| 2437 | case BG2VOFS: /* BG2 - vertical scroll (DW) */ |
| 2438 | m_layer[SNES_BG2].voffs = (data << 8) | (m_ppu_last_scroll); |
| 2439 | m_ppu_last_scroll = data; |
| 2440 | m_update_offsets = 1; |
| 2441 | return; |
| 2442 | case BG3HOFS: /* BG3 - horizontal scroll (DW) */ |
| 2443 | m_layer[SNES_BG3].hoffs = (data << 8) | (m_ppu_last_scroll & ~7) | ((m_layer[SNES_BG3].hoffs >> 8) & 7); |
| 2444 | m_ppu_last_scroll = data; |
| 2445 | m_update_offsets = 1; |
| 2446 | return; |
| 2447 | case BG3VOFS: /* BG3 - vertical scroll (DW) */ |
| 2448 | m_layer[SNES_BG3].voffs = (data << 8) | (m_ppu_last_scroll); |
| 2449 | m_ppu_last_scroll = data; |
| 2450 | m_update_offsets = 1; |
| 2451 | return; |
| 2452 | case BG4HOFS: /* BG4 - horizontal scroll (DW) */ |
| 2453 | m_layer[SNES_BG4].hoffs = (data << 8) | (m_ppu_last_scroll & ~7) | ((m_layer[SNES_BG4].hoffs >> 8) & 7); |
| 2454 | m_ppu_last_scroll = data; |
| 2455 | m_update_offsets = 1; |
| 2456 | return; |
| 2457 | case BG4VOFS: /* BG4 - vertical scroll (DW) */ |
| 2458 | m_layer[SNES_BG4].voffs = (data << 8) | (m_ppu_last_scroll); |
| 2459 | m_ppu_last_scroll = data; |
| 2460 | m_update_offsets = 1; |
| 2461 | return; |
| 2462 | case VMAIN: /* VRAM address increment value designation */ |
| 2463 | m_vram_fgr_high = (data & 0x80); |
| 2464 | m_vram_fgr_increment = vram_fgr_inctab[data & 3]; |
| 2465 | |
| 2466 | if (data & 0xc) |
| 2467 | { |
| 2468 | int md = (data & 0xc) >> 2; |
| 2469 | |
| 2470 | m_vram_fgr_count = vram_fgr_inccnts[md]; // 0x20, 0x40, 0x80 |
| 2471 | m_vram_fgr_mask = (m_vram_fgr_count * 8) - 1; // 0xff, 0x1ff, 0x2ff |
| 2472 | m_vram_fgr_shift = vram_fgr_shiftab[md]; // 5, 6, 7 |
| 2473 | } |
| 2474 | else |
| 2475 | { |
| 2476 | m_vram_fgr_count = 0; |
| 2477 | } |
| 2478 | // printf("VMAIN: high %x inc %x count %x mask %x shift %x\n", m_vram_fgr_high, m_vram_fgr_increment, m_vram_fgr_count, m_vram_fgr_mask, m_vram_fgr_shift); |
| 2479 | break; |
| 2480 | case VMADDL: /* Address for VRAM read/write (low) */ |
| 2481 | { |
| 2482 | UINT32 addr; |
| 2483 | m_vmadd = (m_vmadd & 0xff00) | (data << 0); |
| 2484 | addr = get_vram_address(space.machine()); |
| 2485 | m_vram_read_buffer = vram_read(space, addr); |
| 2486 | m_vram_read_buffer |= (vram_read(space, addr + 1) << 8); |
| 2487 | } |
| 2488 | break; |
| 2489 | case VMADDH: /* Address for VRAM read/write (high) */ |
| 2490 | { |
| 2491 | UINT32 addr; |
| 2492 | m_vmadd = (m_vmadd & 0x00ff) | (data << 8); |
| 2493 | addr = get_vram_address(space.machine()); |
| 2494 | m_vram_read_buffer = vram_read(space, addr); |
| 2495 | m_vram_read_buffer |= (vram_read(space, addr + 1) << 8); |
| 2496 | } |
| 2497 | break; |
| 2498 | case VMDATAL: /* 2118: Data for VRAM write (low) */ |
| 2499 | { |
| 2500 | UINT32 addr = get_vram_address(space.machine()); |
| 2501 | vram_write(space, addr, data); |
| 2502 | |
| 2503 | if (!m_vram_fgr_high) |
| 2504 | m_vmadd = (m_vmadd + m_vram_fgr_increment) & 0xffff; |
| 2505 | } |
| 2506 | return; |
| 2507 | case VMDATAH: /* 2119: Data for VRAM write (high) */ |
| 2508 | { |
| 2509 | UINT32 addr = get_vram_address(space.machine()); |
| 2510 | vram_write(space, addr + 1, data); |
| 2511 | |
| 2512 | if (m_vram_fgr_high) |
| 2513 | m_vmadd = (m_vmadd + m_vram_fgr_increment) & 0xffff; |
| 2514 | } |
| 2515 | return; |
| 2516 | case M7SEL: /* Mode 7 initial settings */ |
| 2517 | m_mode7.repeat = (data >> 6) & 3; |
| 2518 | m_mode7.vflip = BIT(data, 1); |
| 2519 | m_mode7.hflip = BIT(data, 0); |
| 2520 | break; |
| 2521 | /* 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 */ |
| 2522 | case M7A: /* Mode 7 COS angle/x expansion (DW) */ |
| 2523 | m_mode7.matrix_a = m_mode7_last_scroll + (data << 8); |
| 2524 | m_mode7_last_scroll = data; |
| 2525 | break; |
| 2526 | case M7B: /* Mode 7 SIN angle/ x expansion (DW) */ |
| 2527 | m_mode7.matrix_b = m_mode7_last_scroll + (data << 8); |
| 2528 | m_mode7_last_scroll = data; |
| 2529 | break; |
| 2530 | case M7C: /* Mode 7 SIN angle/y expansion (DW) */ |
| 2531 | m_mode7.matrix_c = m_mode7_last_scroll + (data << 8); |
| 2532 | m_mode7_last_scroll = data; |
| 2533 | break; |
| 2534 | case M7D: /* Mode 7 COS angle/y expansion (DW) */ |
| 2535 | m_mode7.matrix_d = m_mode7_last_scroll + (data << 8); |
| 2536 | m_mode7_last_scroll = data; |
| 2537 | break; |
| 2538 | case M7X: /* Mode 7 x center position (DW) */ |
| 2539 | m_mode7.origin_x = m_mode7_last_scroll + (data << 8); |
| 2540 | m_mode7_last_scroll = data; |
| 2541 | break; |
| 2542 | case M7Y: /* Mode 7 y center position (DW) */ |
| 2543 | m_mode7.origin_y = m_mode7_last_scroll + (data << 8); |
| 2544 | m_mode7_last_scroll = data; |
| 2545 | break; |
| 2546 | case CGADD: /* Initial address for colour RAM writing */ |
| 2547 | /* CGRAM is 16-bit, but when reading/writing we treat it as 8-bit, so we need to double the address */ |
| 2548 | m_cgram_address = data << 1; |
| 2549 | break; |
| 2550 | case CGDATA: /* Data for colour RAM */ |
| 2551 | cgram_write(space, m_cgram_address, data); |
| 2552 | m_cgram_address = (m_cgram_address + 1) % (SNES_CGRAM_SIZE - 2); |
| 2553 | break; |
| 2554 | case W12SEL: /* Window mask settings for BG1-2 */ |
| 2555 | if (data != PPU_REG(W12SEL)) |
| 2556 | { |
| 2557 | m_layer[SNES_BG1].window1_invert = BIT(data, 0); |
| 2558 | m_layer[SNES_BG1].window1_enabled = BIT(data, 1); |
| 2559 | m_layer[SNES_BG1].window2_invert = BIT(data, 2); |
| 2560 | m_layer[SNES_BG1].window2_enabled = BIT(data, 3); |
| 2561 | m_layer[SNES_BG2].window1_invert = BIT(data, 4); |
| 2562 | m_layer[SNES_BG2].window1_enabled = BIT(data, 5); |
| 2563 | m_layer[SNES_BG2].window2_invert = BIT(data, 6); |
| 2564 | m_layer[SNES_BG2].window2_enabled = BIT(data, 7); |
| 2565 | m_update_windows = 1; |
| 2566 | } |
| 2567 | break; |
| 2568 | case W34SEL: /* Window mask settings for BG3-4 */ |
| 2569 | if (data != PPU_REG(W34SEL)) |
| 2570 | { |
| 2571 | m_layer[SNES_BG3].window1_invert = BIT(data, 0); |
| 2572 | m_layer[SNES_BG3].window1_enabled = BIT(data, 1); |
| 2573 | m_layer[SNES_BG3].window2_invert = BIT(data, 2); |
| 2574 | m_layer[SNES_BG3].window2_enabled = BIT(data, 3); |
| 2575 | m_layer[SNES_BG4].window1_invert = BIT(data, 4); |
| 2576 | m_layer[SNES_BG4].window1_enabled = BIT(data, 5); |
| 2577 | m_layer[SNES_BG4].window2_invert = BIT(data, 6); |
| 2578 | m_layer[SNES_BG4].window2_enabled = BIT(data, 7); |
| 2579 | m_update_windows = 1; |
| 2580 | } |
| 2581 | break; |
| 2582 | case WOBJSEL: /* Window mask settings for objects */ |
| 2583 | if (data != PPU_REG(WOBJSEL)) |
| 2584 | { |
| 2585 | m_layer[SNES_OAM].window1_invert = BIT(data, 0); |
| 2586 | m_layer[SNES_OAM].window1_enabled = BIT(data, 1); |
| 2587 | m_layer[SNES_OAM].window2_invert = BIT(data, 2); |
| 2588 | m_layer[SNES_OAM].window2_enabled = BIT(data, 3); |
| 2589 | m_layer[SNES_COLOR].window1_invert = BIT(data, 4); |
| 2590 | m_layer[SNES_COLOR].window1_enabled = BIT(data, 5); |
| 2591 | m_layer[SNES_COLOR].window2_invert = BIT(data, 6); |
| 2592 | m_layer[SNES_COLOR].window2_enabled = BIT(data, 7); |
| 2593 | m_update_windows = 1; |
| 2594 | } |
| 2595 | break; |
| 2596 | case WH0: /* Window 1 left position */ |
| 2597 | if (data != PPU_REG(WH0)) |
| 2598 | { |
| 2599 | m_window1_left = data; |
| 2600 | m_update_windows = 1; |
| 2601 | } |
| 2602 | break; |
| 2603 | case WH1: /* Window 1 right position */ |
| 2604 | if (data != PPU_REG(WH1)) |
| 2605 | { |
| 2606 | m_window1_right = data; |
| 2607 | m_update_windows = 1; |
| 2608 | } |
| 2609 | break; |
| 2610 | case WH2: /* Window 2 left position */ |
| 2611 | if (data != PPU_REG(WH2)) |
| 2612 | { |
| 2613 | m_window2_left = data; |
| 2614 | m_update_windows = 1; |
| 2615 | } |
| 2616 | break; |
| 2617 | case WH3: /* Window 2 right position */ |
| 2618 | if (data != PPU_REG(WH3)) |
| 2619 | { |
| 2620 | m_window2_right = data; |
| 2621 | m_update_windows = 1; |
| 2622 | } |
| 2623 | break; |
| 2624 | case WBGLOG: /* Window mask logic for BG's */ |
| 2625 | if (data != PPU_REG(WBGLOG)) |
| 2626 | { |
| 2627 | m_layer[SNES_BG1].wlog_mask = data & 0x03; |
| 2628 | m_layer[SNES_BG2].wlog_mask = (data & 0x0c) >> 2; |
| 2629 | m_layer[SNES_BG3].wlog_mask = (data & 0x30) >> 4; |
| 2630 | m_layer[SNES_BG4].wlog_mask = (data & 0xc0) >> 6; |
| 2631 | m_update_windows = 1; |
| 2632 | } |
| 2633 | break; |
| 2634 | case WOBJLOG: /* Window mask logic for objects */ |
| 2635 | if (data != PPU_REG(WOBJLOG)) |
| 2636 | { |
| 2637 | m_layer[SNES_OAM].wlog_mask = data & 0x03; |
| 2638 | m_layer[SNES_COLOR].wlog_mask = (data & 0x0c) >> 2; |
| 2639 | m_update_windows = 1; |
| 2640 | } |
| 2641 | break; |
| 2642 | case TM: /* Main screen designation */ |
| 2643 | m_layer[SNES_BG1].main_bg_enabled = BIT(data, 0); |
| 2644 | m_layer[SNES_BG2].main_bg_enabled = BIT(data, 1); |
| 2645 | m_layer[SNES_BG3].main_bg_enabled = BIT(data, 2); |
| 2646 | m_layer[SNES_BG4].main_bg_enabled = BIT(data, 3); |
| 2647 | m_layer[SNES_OAM].main_bg_enabled = BIT(data, 4); |
| 2648 | break; |
| 2649 | case TS: /* Subscreen designation */ |
| 2650 | m_layer[SNES_BG1].sub_bg_enabled = BIT(data, 0); |
| 2651 | m_layer[SNES_BG2].sub_bg_enabled = BIT(data, 1); |
| 2652 | m_layer[SNES_BG3].sub_bg_enabled = BIT(data, 2); |
| 2653 | m_layer[SNES_BG4].sub_bg_enabled = BIT(data, 3); |
| 2654 | m_layer[SNES_OAM].sub_bg_enabled = BIT(data, 4); |
| 2655 | break; |
| 2656 | case TMW: /* Window mask for main screen designation */ |
| 2657 | m_layer[SNES_BG1].main_window_enabled = BIT(data, 0); |
| 2658 | m_layer[SNES_BG2].main_window_enabled = BIT(data, 1); |
| 2659 | m_layer[SNES_BG3].main_window_enabled = BIT(data, 2); |
| 2660 | m_layer[SNES_BG4].main_window_enabled = BIT(data, 3); |
| 2661 | m_layer[SNES_OAM].main_window_enabled = BIT(data, 4); |
| 2662 | break; |
| 2663 | case TSW: /* Window mask for subscreen designation */ |
| 2664 | m_layer[SNES_BG1].sub_window_enabled = BIT(data, 0); |
| 2665 | m_layer[SNES_BG2].sub_window_enabled = BIT(data, 1); |
| 2666 | m_layer[SNES_BG3].sub_window_enabled = BIT(data, 2); |
| 2667 | m_layer[SNES_BG4].sub_window_enabled = BIT(data, 3); |
| 2668 | m_layer[SNES_OAM].sub_window_enabled = BIT(data, 4); |
| 2669 | break; |
| 2670 | case CGWSEL: /* Initial settings for Fixed colour addition or screen addition */ |
| 2671 | m_clip_to_black = (data >> 6) & 0x03; |
| 2672 | m_prevent_color_math = (data >> 4) & 0x03; |
| 2673 | m_sub_add_mode = BIT(data, 1); |
| 2674 | m_direct_color = BIT(data, 0); |
| 2675 | #ifdef SNES_DBG_REG_W |
| 2676 | if ((data & 0x2) != (PPU_REG(CGWSEL) & 0x2)) |
| 2677 | mame_printf_debug("Add/Sub Layer: %s\n", ((data & 0x2) >> 1) ? "Subscreen" : "Fixed colour"); |
| 2678 | #endif |
| 2679 | break; |
| 2680 | case CGADSUB: /* Addition/Subtraction designation for each screen */ |
| 2681 | m_color_modes = data & 0xc0; |
| 2682 | m_layer[SNES_BG1].color_math = BIT(data, 0); |
| 2683 | m_layer[SNES_BG2].color_math = BIT(data, 1); |
| 2684 | m_layer[SNES_BG3].color_math = BIT(data, 2); |
| 2685 | m_layer[SNES_BG4].color_math = BIT(data, 3); |
| 2686 | m_layer[SNES_OAM].color_math = BIT(data, 4); |
| 2687 | m_layer[SNES_COLOR].color_math = BIT(data, 5); |
| 2688 | break; |
| 2689 | case COLDATA: /* Fixed colour data for fixed colour addition/subtraction */ |
| 2690 | { |
| 2691 | /* Store it in the extra space we made in the CGRAM. It doesn't really go there, but it's as good a place as any. */ |
| 2692 | UINT8 r, g, b; |
| 2693 | |
| 2694 | /* Get existing value. */ |
| 2695 | r = m_cgram[FIXED_COLOUR] & 0x1f; |
| 2696 | g = (m_cgram[FIXED_COLOUR] & 0x3e0) >> 5; |
| 2697 | b = (m_cgram[FIXED_COLOUR] & 0x7c00) >> 10; |
| 2698 | /* Set new value */ |
| 2699 | if (data & 0x20) |
| 2700 | r = data & 0x1f; |
| 2701 | if (data & 0x40) |
| 2702 | g = data & 0x1f; |
| 2703 | if (data & 0x80) |
| 2704 | b = data & 0x1f; |
| 2705 | m_cgram[FIXED_COLOUR] = (r | (g << 5) | (b << 10)); |
| 2706 | } break; |
| 2707 | case SETINI: /* Screen mode/video select */ |
| 2708 | m_interlace = (data & 0x01) ? 2 : 1; |
| 2709 | m_obj_interlace = (data & 0x02) ? 2 : 1; |
| 2710 | m_beam.last_visible_line = (data & 0x04) ? 240 : 225; |
| 2711 | m_pseudo_hires = BIT(data, 3); |
| 2712 | m_mode7.extbg = BIT(data, 6); |
| 2713 | dynamic_res_change(space.machine()); |
| 2714 | #ifdef SNES_DBG_REG_W |
| 2715 | if ((data & 0x8) != (PPU_REG(SETINI) & 0x8)) |
| 2716 | mame_printf_debug("Pseudo 512 mode: %s\n", (data & 0x8) ? "on" : "off"); |
| 2717 | #endif |
| 2718 | break; |
| 2719 | } |
| 2720 | |
| 2721 | PPU_REG(offset) = data; |
| 2722 | } |
| 2723 | |
| 2724 | /***** Debug Functions *****/ |
| 2725 | |
| 2726 | #if SNES_LAYER_DEBUG |
| 2727 | |
| 2728 | #define DEBUG_TOGGLE(bit, debug_settings, MSG1, MSG2) \ |
| 2729 | if (BIT(toggles, bit) && !debug_settings) \ |
| 2730 | { \ |
| 2731 | debug_settings = 1; \ |
| 2732 | popmessage MSG1; \ |
| 2733 | } \ |
| 2734 | else if (!BIT(toggles, bit) && debug_settings) \ |
| 2735 | { \ |
| 2736 | debug_settings = 0; \ |
| 2737 | popmessage MSG2; \ |
| 2738 | } |
| 2739 | |
| 2740 | UINT8 snes_ppu_device::dbg_video( running_machine &machine, UINT16 curline ) |
| 2741 | { |
| 2742 | int i; |
| 2743 | UINT8 toggles = machine.root_device().ioport("DEBUG1")->read_safe(0); |
| 2744 | m_debug_options.select_pri[SNES_BG1] = (toggles & 0x03); |
| 2745 | m_debug_options.select_pri[SNES_BG2] = (toggles & 0x0c) >> 2; |
| 2746 | m_debug_options.select_pri[SNES_BG3] = (toggles & 0x30) >> 4; |
| 2747 | m_debug_options.select_pri[SNES_BG4] = (toggles & 0xc0) >> 6; |
| 2748 | |
| 2749 | toggles = machine.root_device().ioport("DEBUG2")->read_safe(0); |
| 2750 | for (i = 0; i < 4; i++) |
| 2751 | DEBUG_TOGGLE(i, m_debug_options.bg_disabled[i], ("Debug: Disabled BG%d.\n", i + 1), ("Debug: Enabled BG%d.\n", i + 1)) |
| 2752 | DEBUG_TOGGLE(4, m_debug_options.bg_disabled[SNES_OAM], ("Debug: Disabled OAM.\n"), ("Debug: Enabled OAM.\n")) |
| 2753 | DEBUG_TOGGLE(5, m_debug_options.draw_subscreen, ("Debug: Switched screens.\n"), ("Debug: Switched screens.\n")) |
| 2754 | DEBUG_TOGGLE(6, m_debug_options.colormath_disabled, ("Debug: Disabled Color Math.\n"), ("Debug: Enabled Color Math.\n")) |
| 2755 | DEBUG_TOGGLE(7, m_debug_options.windows_disabled, ("Debug: Disabled Window Masks.\n"), ("Debug: Enabled Window Masks.\n")) |
| 2756 | |
| 2757 | toggles = machine.root_device().ioport("DEBUG4")->read_safe(0); |
| 2758 | for (i = 0; i < 8; i++) |
| 2759 | DEBUG_TOGGLE(i, m_debug_options.mode_disabled[i], ("Debug: Disabled Mode %d drawing.\n", i), ("Debug: Enabled Mode %d drawing.\n", i)) |
| 2760 | |
| 2761 | toggles = machine.root_device().ioport("DEBUG3")->read_safe(0); |
| 2762 | DEBUG_TOGGLE(2, m_debug_options.mosaic_disabled, ("Debug: Disabled Mosaic.\n"), ("Debug: Enabled Mosaic.\n")) |
| 2763 | m_debug_options.sprite_reversed = BIT(toggles, 7); |
| 2764 | m_debug_options.select_pri[SNES_OAM] = (toggles & 0x70) >> 4; |
| 2765 | |
| 2766 | #ifdef MAME_DEBUG |
| 2767 | /* Once per frame, log video properties */ |
| 2768 | if (curline == 1) |
| 2769 | { |
| 2770 | static const char WINLOGIC[4] = { '|', '&', '^', '!' }; |
| 2771 | |
| 2772 | logerror("%s", m_debug_options.windows_disabled?" ":"W"); |
| 2773 | logerror("%s1 %s%s%s%s%s%c%s%s%d%s %d %4X %4X", |
| 2774 | m_debug_options.bg_disabled[0]?" ":"*", |
| 2775 | (PPU_REG(TM) & 0x1)?"M":" ", |
| 2776 | (PPU_REG(TS) & 0x1)?"S":" ", |
| 2777 | (PPU_REG(CGADSUB) & 0x1)?"B":" ", |
| 2778 | (PPU_REG(TMW) & 0x1)?"m":" ", |
| 2779 | (PPU_REG(TSW) & 0x1)?"s":" ", |
| 2780 | WINLOGIC[(PPU_REG(WBGLOG) & 0x3)], |
| 2781 | (PPU_REG(W12SEL) & 0x2)?((PPU_REG(W12SEL) & 0x1)?"o":"i"):" ", |
| 2782 | (PPU_REG(W12SEL) & 0x8)?((PPU_REG(W12SEL) & 0x4)?"o":"i"):" ", |
| 2783 | m_layer[SNES_BG1].tile_size + 1, |
| 2784 | (PPU_REG(MOSAIC) & 0x1)?"m":" ", |
| 2785 | PPU_REG(BG1SC) & 0x3, |
| 2786 | (PPU_REG(BG1SC) & 0xfc) << 9, |
| 2787 | m_layer[SNES_BG1].charmap << 13); |
| 2788 | logerror("%s2 %s%s%s%s%s%c%s%s%d%s %d %4X %4X", |
| 2789 | m_debug_options.bg_disabled[1]?" ":"*", |
| 2790 | (PPU_REG(TM) & 0x2)?"M":" ", |
| 2791 | (PPU_REG(TS) & 0x2)?"S":" ", |
| 2792 | (PPU_REG(CGADSUB) & 0x2)?"B":" ", |
| 2793 | (PPU_REG(TMW) & 0x2)?"m":" ", |
| 2794 | (PPU_REG(TSW) & 0x2)?"s":" ", |
| 2795 | WINLOGIC[(PPU_REG(WBGLOG) & 0xc) >> 2], |
| 2796 | (PPU_REG(W12SEL) & 0x20)?((PPU_REG(W12SEL) & 0x10)?"o":"i"):" ", |
| 2797 | (PPU_REG(W12SEL) & 0x80)?((PPU_REG(W12SEL) & 0x40)?"o":"i"):" ", |
| 2798 | m_layer[SNES_BG2].tile_size + 1, |
| 2799 | (PPU_REG(MOSAIC) & 0x2)?"m":" ", |
| 2800 | PPU_REG(BG2SC) & 0x3, |
| 2801 | (PPU_REG(BG2SC) & 0xfc) << 9, |
| 2802 | m_layer[SNES_BG2].charmap << 13); |
| 2803 | logerror("%s3 %s%s%s%s%s%c%s%s%d%s%s%d %4X %4X", |
| 2804 | m_debug_options.bg_disabled[2]?" ":"*", |
| 2805 | (PPU_REG(TM) & 0x4)?"M":" ", |
| 2806 | (PPU_REG(TS) & 0x4)?"S":" ", |
| 2807 | (PPU_REG(CGADSUB) & 0x4)?"B":" ", |
| 2808 | (PPU_REG(TMW) & 0x4)?"m":" ", |
| 2809 | (PPU_REG(TSW) & 0x4)?"s":" ", |
| 2810 | WINLOGIC[(PPU_REG(WBGLOG) & 0x30)>>4], |
| 2811 | (PPU_REG(W34SEL) & 0x2)?((PPU_REG(W34SEL) & 0x1)?"o":"i"):" ", |
| 2812 | (PPU_REG(W34SEL) & 0x8)?((PPU_REG(W34SEL) & 0x4)?"o":"i"):" ", |
| 2813 | m_layer[SNES_BG3].tile_size + 1, |
| 2814 | (PPU_REG(MOSAIC) & 0x4)?"m":" ", |
| 2815 | (PPU_REG(BGMODE) & 0x8)?"P":" ", |
| 2816 | PPU_REG(BG3SC) & 0x3, |
| 2817 | (PPU_REG(BG3SC) & 0xfc) << 9, |
| 2818 | m_layer[SNES_BG3].charmap << 13); |
| 2819 | logerror("%s4 %s%s%s%s%s%c%s%s%d%s %d %4X %4X", |
| 2820 | m_debug_options.bg_disabled[3]?" ":"*", |
| 2821 | (PPU_REG(TM) & 0x8)?"M":" ", |
| 2822 | (PPU_REG(TS) & 0x8)?"S":" ", |
| 2823 | (PPU_REG(CGADSUB) & 0x8)?"B":" ", |
| 2824 | (PPU_REG(TMW) & 0x8)?"m":" ", |
| 2825 | (PPU_REG(TSW) & 0x8)?"s":" ", |
| 2826 | WINLOGIC[(PPU_REG(WBGLOG) & 0xc0)>>6], |
| 2827 | (PPU_REG(W34SEL) & 0x20)?((PPU_REG(W34SEL) & 0x10)?"o":"i"):" ", |
| 2828 | (PPU_REG(W34SEL) & 0x80)?((PPU_REG(W34SEL) & 0x40)?"o":"i"):" ", |
| 2829 | m_layer[SNES_BG4].tile_size + 1, |
| 2830 | (PPU_REG(MOSAIC) & 0x8)?"m":" ", |
| 2831 | PPU_REG(BG4SC) & 0x3, |
| 2832 | (PPU_REG(BG4SC) & 0xfc) << 9, |
| 2833 | m_layer[SNES_BG4].charmap << 13 ); |
| 2834 | logerror("%sO %s%s%s%s%s%c%s%s %4X", |
| 2835 | m_debug_options.bg_disabled[4]?" ":"*", |
| 2836 | (PPU_REG(TM) & 0x10)?"M":" ", |
| 2837 | (PPU_REG(TS) & 0x10)?"S":" ", |
| 2838 | (PPU_REG(CGADSUB) & 0x10)?"B":" ", |
| 2839 | (PPU_REG(TMW) & 0x10)?"m":" ", |
| 2840 | (PPU_REG(TSW) & 0x10)?"s":" ", |
| 2841 | WINLOGIC[(PPU_REG(WOBJLOG) & 0x3)], |
| 2842 | (PPU_REG(WOBJSEL) & 0x2)?((PPU_REG(WOBJSEL) & 0x1)?"o":"i"):" ", |
| 2843 | (PPU_REG(WOBJSEL) & 0x8)?((PPU_REG(WOBJSEL) & 0x4)?"o":"i"):" ", |
| 2844 | m_layer[SNES_OAM].charmap << 13 ); |
| 2845 | logerror("%sB %s %c%s%s", |
| 2846 | m_debug_options.colormath_disabled?" ":"*", |
| 2847 | (PPU_REG(CGADSUB) & 0x20)?"B":" ", |
| 2848 | WINLOGIC[(PPU_REG(WOBJLOG) & 0xc)>>2], |
| 2849 | (PPU_REG(WOBJSEL) & 0x20)?((PPU_REG(WOBJSEL) & 0x10)?"o":"i"):" ", |
| 2850 | (PPU_REG(WOBJSEL) & 0x80)?((PPU_REG(WOBJSEL) & 0x40)?"o":"i"):" " ); |
| 2851 | logerror("Flags: %s%s%s %s %2d", (PPU_REG(CGWSEL) & 0x2)?"S":"F", (PPU_REG(CGADSUB) & 0x80)?"-":"+", (PPU_REG(CGADSUB) & 0x40)?" 50%":"100%",(PPU_REG(CGWSEL) & 0x1)?"D":"P", (PPU_REG(MOSAIC) & 0xf0) >> 4 ); |
| 2852 | logerror("SetINI: %s %s %s %s %s %s", (PPU_REG(SETINI) & 0x1)?" I":"NI", (PPU_REG(SETINI) & 0x2)?"P":"R", (PPU_REG(SETINI) & 0x4)?"240":"225",(PPU_REG(SETINI) & 0x8)?"512":"256",(PPU_REG(SETINI) & 0x40)?"E":"N",(PPU_REG(SETINI) & 0x80)?"ES":"NS" ); |
| 2853 | logerror("Mode7: A %5d B %5d", m_mode7.matrix_a, m_mode7.matrix_b ); |
| 2854 | logerror(" %s%s%s C %5d D %5d", (PPU_REG(M7SEL) & 0xc0)?((PPU_REG(M7SEL) & 0x40)?"0":"C"):"R", (PPU_REG(M7SEL) & 0x1)?"H":" ", (PPU_REG(M7SEL) & 0x2)?"V":" ", m_mode7.matrix_c, m_mode7.matrix_d ); |
| 2855 | logerror(" X %5d Y %5d", m_mode7.origin_x, m_mode7.origin_y ); |
| 2856 | } |
| 2857 | #endif |
| 2858 | |
| 2859 | return 0; |
| 2860 | } |
| 2861 | #endif /* SNES_LAYER_DEBUG */ |
branches/new_menus/src/mame/video/snes.c
| r29543 | r29544 | |
| 1 | | /*************************************************************************** |
| 2 | | |
| 3 | | snes.c |
| 4 | | |
| 5 | | Video file to handle emulation of the Nintendo Super NES. |
| 6 | | |
| 7 | | Anthony Kruize |
| 8 | | Based on the original code by Lee Hammerton (aka Savoury Snax) |
| 9 | | |
| 10 | | Some notes on the snes video hardware: |
| 11 | | |
| 12 | | Object Attribute Memory(OAM) is made up of 128 blocks of 32 bits, followed |
| 13 | | by 128 blocks of 2 bits. The format for each block is: |
| 14 | | -First Block---------------------------------------------------------------- |
| 15 | | | x pos | y pos |char no.| v flip | h flip |priority|palette |char no msb| |
| 16 | | +--------+--------+--------+--------+--------+--------+--------+-----------+ |
| 17 | | | 8 bits | 8 bits | 8 bits | 1 bit | 1 bit | 2 bits | 3 bits | 1 bit | |
| 18 | | -Second Block--------------------------------------------------------------- |
| 19 | | | size | x pos msb | |
| 20 | | +-------+-----------+ |
| 21 | | | 1 bit | 1 bit | |
| 22 | | --------------------- |
| 23 | | |
| 24 | | Video RAM contains information for character data and screen maps. |
| 25 | | Screen maps are made up of 32 x 32 blocks of 16 bits each. |
| 26 | | The format for each block is: |
| 27 | | ---------------------------------------------- |
| 28 | | | v flip | x flip |priority|palette |char no.| |
| 29 | | +--------+--------+--------+--------+--------+ |
| 30 | | | 1 bit | 1 bit | 1 bit | 3 bits |10 bits | |
| 31 | | ---------------------------------------------- |
| 32 | | Mode 7 is stored differently. Character data and screen map are interleaved. |
| 33 | | There are two formats: |
| 34 | | -Normal----------------- -EXTBG----------------------------- |
| 35 | | | char data | char no. | | priority | char data | char no. | |
| 36 | | +-----------+----------+ +----------+-----------+----------+ |
| 37 | | | 8 bits | 8 bits | | 1 bit | 7 bits | 8 bits | |
| 38 | | ------------------------ ----------------------------------- |
| 39 | | |
| 40 | | The screen layers are drawn with the following priorities (updated info courtesy of byuu): |
| 41 | | |
| 42 | | | | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | |
| 43 | | ------------------------------------------------------------------------------------------------------------- |
| 44 | | | Mode 0 | BG4B | BG3B | OAM0 | BG4A | BG3A | OAM1 | BG2B | BG1B | OAM2 | BG2A | BG1A | OAM3 | |
| 45 | | ------------------------------------------------------------------------------------------------------------- |
| 46 | | | Mode 1 (*)| BG3B | OAM0 | OAM1 | BG2B | BG1B | OAM2 | BG2A | BG1A | OAM3 | BG3A | | | |
| 47 | | ------------------------------------------------------------------------------------------------------------- |
| 48 | | | Mode 1 (!)| BG3B | OAM0 | BG3A | OAM1 | BG2B | BG1B | OAM2 | BG2A | BG1A | OAM3 | | | |
| 49 | | ------------------------------------------------------------------------------------------------------------- |
| 50 | | | Mode 2 | BG2B | OAM0 | BG1B | OAM1 | BG2A | OAM2 | BG1A | OAM3 | | | | | |
| 51 | | ------------------------------------------------------------------------------------------------------------- |
| 52 | | | Mode 3 | BG2B | OAM0 | BG1B | OAM1 | BG2A | OAM2 | BG1A | OAM3 | | | | | |
| 53 | | ------------------------------------------------------------------------------------------------------------- |
| 54 | | | Mode 4 | BG2B | OAM0 | BG1B | OAM1 | BG2A | OAM2 | BG1A | OAM3 | | | | | |
| 55 | | ------------------------------------------------------------------------------------------------------------- |
| 56 | | | Mode 5 | BG2B | OAM0 | BG1B | OAM1 | BG2A | OAM2 | BG1A | OAM3 | | | | | |
| 57 | | ------------------------------------------------------------------------------------------------------------- |
| 58 | | | Mode 6 | OAM0 | BG1B | OAM1 | OAM2 | BG1A | OAM3 | | | | | | | |
| 59 | | ------------------------------------------------------------------------------------------------------------- |
| 60 | | | Mode 7 (+)| OAM0 | BG1n | OAM1 | OAM2 | OAM3 | | | | | | | | |
| 61 | | ------------------------------------------------------------------------------------------------------------- |
| 62 | | | Mode 7 (-)| BG2B | OAM0 | BG1n | OAM1 | BG2A | OAM2 | OAM3 | | | | | | |
| 63 | | ------------------------------------------------------------------------------------------------------------- |
| 64 | | |
| 65 | | Where: |
| 66 | | - Mode 1 (*) is Mode 1 with bg3_pty = 1 |
| 67 | | - Mode 1 (!) is Mode 1 with bg3_pty = 0 |
| 68 | | - Mode 7 (+) is base Mode 7 |
| 69 | | - Mode 7 (-) is Mode 7 EXTBG |
| 70 | | |
| 71 | | ***************************************************************************/ |
| 72 | | |
| 73 | | #include "emu.h" |
| 74 | | #include "includes/snes.h" |
| 75 | | |
| 76 | | #define SNES_MAINSCREEN 0 |
| 77 | | #define SNES_SUBSCREEN 1 |
| 78 | | #define SNES_CLIP_NEVER 0 |
| 79 | | #define SNES_CLIP_IN 1 |
| 80 | | #define SNES_CLIP_OUT 2 |
| 81 | | #define SNES_CLIP_ALWAYS 3 |
| 82 | | |
| 83 | | #if SNES_LAYER_DEBUG |
| 84 | | /* red green blue purple yellow cyan grey white */ |
| 85 | | static const UINT16 dbg_mode_colours[8] = { 0x1f, 0x3e0, 0x7c00, 0x7c1f, 0x3ff, 0x7fe0, 0x4210, 0x7fff }; |
| 86 | | #endif /* SNES_LAYER_DEBUG */ |
| 87 | | |
| 88 | | static const UINT16 table_obj_offset[8][8] = |
| 89 | | { |
| 90 | | { (0*32), (0*32)+32, (0*32)+64, (0*32)+96, (0*32)+128, (0*32)+160, (0*32)+192, (0*32)+224 }, |
| 91 | | { (16*32), (16*32)+32, (16*32)+64, (16*32)+96, (16*32)+128, (16*32)+160, (16*32)+192, (16*32)+224 }, |
| 92 | | { (32*32), (32*32)+32, (32*32)+64, (32*32)+96, (32*32)+128, (32*32)+160, (32*32)+192, (32*32)+224 }, |
| 93 | | { (48*32), (48*32)+32, (48*32)+64, (48*32)+96, (48*32)+128, (48*32)+160, (48*32)+192, (48*32)+224 }, |
| 94 | | { (64*32), (64*32)+32, (64*32)+64, (64*32)+96, (64*32)+128, (64*32)+160, (64*32)+192, (64*32)+224 }, |
| 95 | | { (80*32), (80*32)+32, (80*32)+64, (80*32)+96, (80*32)+128, (80*32)+160, (80*32)+192, (80*32)+224 }, |
| 96 | | { (96*32), (96*32)+32, (96*32)+64, (96*32)+96, (96*32)+128, (96*32)+160, (96*32)+192, (96*32)+224 }, |
| 97 | | { (112*32), (112*32)+32, (112*32)+64, (112*32)+96, (112*32)+128, (112*32)+160, (112*32)+192, (112*32)+224 } |
| 98 | | }; |
| 99 | | |
| 100 | | |
| 101 | | enum |
| 102 | | { |
| 103 | | SNES_COLOR_DEPTH_2BPP = 0, |
| 104 | | SNES_COLOR_DEPTH_4BPP, |
| 105 | | SNES_COLOR_DEPTH_8BPP |
| 106 | | }; |
| 107 | | |
| 108 | | |
| 109 | | #define PPU_REG(a) m_regs[a - 0x2100] |
| 110 | | |
| 111 | | |
| 112 | | /***************************************** |
| 113 | | * get_bgcolor() |
| 114 | | * |
| 115 | | * Get the proper color (direct or from cgram) |
| 116 | | *****************************************/ |
| 117 | | |
| 118 | | inline UINT16 snes_ppu_class::get_bgcolor( UINT8 direct_colors, UINT16 palette, UINT8 color ) |
| 119 | | { |
| 120 | | UINT16 c = 0; |
| 121 | | |
| 122 | | if (direct_colors) |
| 123 | | { |
| 124 | | /* format is 0 | BBb00 | GGGg0 | RRRr0, HW confirms that the data is zero padded. */ |
| 125 | | c = ((color & 0x07) << 2) | ((color & 0x38) << 4) | ((color & 0xc0) << 7); |
| 126 | | c |= ((palette & 0x04) >> 1) | ((palette & 0x08) << 3) | ((palette & 0x10) << 8); |
| 127 | | } |
| 128 | | else |
| 129 | | c = m_cgram[(palette + color) % FIXED_COLOUR]; |
| 130 | | |
| 131 | | return c; |
| 132 | | } |
| 133 | | |
| 134 | | /***************************************** |
| 135 | | * set_scanline_pixel() |
| 136 | | * |
| 137 | | * Store pixel color, priority, layer and |
| 138 | | * color math exception (for OAM) in the |
| 139 | | * proper scanline |
| 140 | | *****************************************/ |
| 141 | | |
| 142 | | inline void snes_ppu_class::set_scanline_pixel( int screen, INT16 x, UINT16 color, UINT8 priority, UINT8 layer, int blend ) |
| 143 | | { |
| 144 | | m_scanlines[screen].buffer[x] = color; |
| 145 | | m_scanlines[screen].priority[x] = priority; |
| 146 | | m_scanlines[screen].layer[x] = layer; |
| 147 | | m_scanlines[screen].blend_exception[x] = blend; |
| 148 | | } |
| 149 | | |
| 150 | | /************************************************************************************************* |
| 151 | | * SNES tiles |
| 152 | | * |
| 153 | | * The way vram is accessed to draw tiles is basically the same for both BG and OAM tiles. Main |
| 154 | | * differences are bit planes (variable for BG and fixed for OAM) and a few details of the scanline |
| 155 | | * output (since OAM has neither mosaic, nor hires, nor direct colors). |
| 156 | | * Hence, we use a common function to take data from VRAM and then we call specific routines for |
| 157 | | * OAM vs BG vs Hi-Res BG tiles. |
| 158 | | *************************************************************************************************/ |
| 159 | | |
| 160 | | /***************************************** |
| 161 | | * draw_bgtile_lores() |
| 162 | | * draw_bgtile_hires() |
| 163 | | * draw_oamtile_() |
| 164 | | * |
| 165 | | * Check if a pixel is clipped or not, and |
| 166 | | * copy it to the scanline buffer when |
| 167 | | * appropriate. The actual way to perform |
| 168 | | * such operations depends on the source |
| 169 | | * (BG or OAM) and on the resolution (hires |
| 170 | | * or lores) |
| 171 | | *****************************************/ |
| 172 | | |
| 173 | | inline void snes_ppu_class::draw_bgtile_lores( UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority ) |
| 174 | | { |
| 175 | | int screen; |
| 176 | | UINT16 c; |
| 177 | | |
| 178 | | for (screen = SNES_MAINSCREEN; screen <= SNES_SUBSCREEN; screen++) |
| 179 | | { |
| 180 | | if (ii >= 0 && ii < SNES_SCR_WIDTH && m_scanlines[screen].enable) |
| 181 | | { |
| 182 | | if (m_scanlines[screen].priority[ii] <= priority) |
| 183 | | { |
| 184 | | UINT8 clr = colour; |
| 185 | | UINT8 clipmask = m_clipmasks[layer][ii]; |
| 186 | | |
| 187 | | #if SNES_LAYER_DEBUG |
| 188 | | if (m_debug_options.windows_disabled) |
| 189 | | clipmask = 0xff; |
| 190 | | #endif /* SNES_LAYER_DEBUG */ |
| 191 | | |
| 192 | | /* Clip to windows */ |
| 193 | | if (m_scanlines[screen].clip) |
| 194 | | clr &= clipmask; |
| 195 | | |
| 196 | | /* Only draw if we have a colour (0 == transparent) */ |
| 197 | | if (clr) |
| 198 | | { |
| 199 | | c = get_bgcolor(direct_colors, pal, clr); |
| 200 | | set_scanline_pixel(screen, ii, c, priority, layer, 0); |
| 201 | | } |
| 202 | | } |
| 203 | | } |
| 204 | | } |
| 205 | | } |
| 206 | | |
| 207 | | inline void snes_ppu_class::draw_bgtile_hires( UINT8 layer, INT16 ii, UINT8 colour, UINT16 pal, UINT8 direct_colors, UINT8 priority ) |
| 208 | | { |
| 209 | | int screen; |
| 210 | | UINT16 c; |
| 211 | | |
| 212 | | for (screen = SNES_MAINSCREEN; screen <= SNES_SUBSCREEN; screen++) |
| 213 | | { |
| 214 | | // odd pixels to main screen, even pixels to sub screen |
| 215 | | if (ii >= 0 && ii < (SNES_SCR_WIDTH << 1) && ((ii & 1) ^ screen) && m_scanlines[screen].enable) |
| 216 | | { |
| 217 | | if (m_scanlines[screen].priority[ii >> 1] <= priority) |
| 218 | | { |
| 219 | | UINT8 clr = colour; |
| 220 | | UINT8 clipmask = m_clipmasks[layer][ii >> 1]; |
| 221 | | |
| 222 | | #if SNES_LAYER_DEBUG |
| 223 | | if (m_debug_options.windows_disabled) |
| 224 | | clipmask = 0xff; |
| 225 | | #endif /* SNES_LAYER_DEBUG */ |
| 226 | | |
| 227 | | /* Clip to windows */ |
| 228 | | if (m_scanlines[screen].clip) |
| 229 | | clr &= clipmask; |
| 230 | | |
| 231 | | /* Only draw if we have a colour (0 == transparent) */ |
| 232 | | if (clr) |
| 233 | | { |
| 234 | | c = get_bgcolor(direct_colors, pal, clr); |
| 235 | | set_scanline_pixel(screen, ii >> 1, c, priority, layer, 0); |
| 236 | | } |
| 237 | | } |
| 238 | | } |
| 239 | | } |
| 240 | | } |
| 241 | | |
| 242 | | inline void snes_ppu_class::draw_oamtile( INT16 ii, UINT8 colour, UINT16 pal, UINT8 priority ) |
| 243 | | { |
| 244 | | int screen; |
| 245 | | int blend; |
| 246 | | UINT16 c; |
| 247 | | INT16 pos = ii & 0x1ff; |
| 248 | | |
| 249 | | for (screen = SNES_MAINSCREEN; screen <= SNES_SUBSCREEN; screen++) |
| 250 | | { |
| 251 | | if (pos >= 0 && pos < SNES_SCR_WIDTH && m_scanlines[screen].enable) |
| 252 | | { |
| 253 | | UINT8 clr = colour; |
| 254 | | UINT8 clipmask = m_clipmasks[SNES_OAM][pos]; |
| 255 | | |
| 256 | | #if SNES_LAYER_DEBUG |
| 257 | | if (m_debug_options.windows_disabled) |
| 258 | | clipmask = 0xff; |
| 259 | | #endif /* SNES_LAYER_DEBUG */ |
| 260 | | |
| 261 | | /* Clip to windows */ |
| 262 | | if (m_scanlines[screen].clip) |
| 263 | | clr &= clipmask; |
| 264 | | |
| 265 | | /* Only draw if we have a colour (0 == transparent) */ |
| 266 | | if (clr) |
| 267 | | { |
| 268 | | c = m_cgram[(pal + clr) % FIXED_COLOUR]; |
| 269 | | blend = (pal + clr < 192) ? 1 : 0; |
| 270 | | set_scanline_pixel(screen, pos, c, priority, SNES_OAM, blend); |
| 271 | | } |
| 272 | | } |
| 273 | | } |
| 274 | | } |
| 275 | | |
| 276 | | /***************************************** |
| 277 | | * draw_tile() |
| 278 | | * |
| 279 | | * Draw 8 pixels from the expected tile |
| 280 | | * by reading the color planes from vram |
| 281 | | * and by calling the appropriate routine |
| 282 | | * (depending on layer and resolution) |
| 283 | | *****************************************/ |
| 284 | | |
| 285 | | inline void snes_ppu_class::draw_tile( UINT8 planes, UINT8 layer, UINT32 tileaddr, INT16 x, UINT8 priority, UINT8 flip, UINT8 direct_colors, UINT16 pal, UINT8 hires ) |
| 286 | | { |
| 287 | | UINT8 plane[8]; |
| 288 | | INT16 ii, jj; |
| 289 | | int x_mos; |
| 290 | | |
| 291 | | for (ii = 0; ii < planes / 2; ii++) |
| 292 | | { |
| 293 | | plane[2 * ii + 0] = m_vram[(tileaddr + 16 * ii + 0) % SNES_VRAM_SIZE]; |
| 294 | | plane[2 * ii + 1] = m_vram[(tileaddr + 16 * ii + 1) % SNES_VRAM_SIZE]; |
| 295 | | } |
| 296 | | |
| 297 | | for (ii = x; ii < (x + 8); ii++) |
| 298 | | { |
| 299 | | UINT8 colour = 0; |
| 300 | | UINT8 mosaic = m_layer[layer].mosaic_enabled; |
| 301 | | |
| 302 | | #if SNES_LAYER_DEBUG |
| 303 | | if (m_debug_options.mosaic_disabled) |
| 304 | | mosaic = 0; |
| 305 | | #endif /* SNES_LAYER_DEBUG */ |
| 306 | | |
| 307 | | if (flip) |
| 308 | | { |
| 309 | | for (jj = 0; jj < planes; jj++) |
| 310 | | colour |= BIT(plane[jj], ii - x) ? (1 << jj) : 0; |
| 311 | | } |
| 312 | | else |
| 313 | | { |
| 314 | | for (jj = 0; jj < planes; jj++) |
| 315 | | colour |= BIT(plane[jj], 7 - (ii - x)) ? (1 << jj) : 0; |
| 316 | | } |
| 317 | | |
| 318 | | if (layer == SNES_OAM) |
| 319 | | draw_oamtile(ii, colour, pal, priority); |
| 320 | | else if (!hires) |
| 321 | | { |
| 322 | | if (mosaic) |
| 323 | | { |
| 324 | | for (x_mos = 0; x_mos < (m_mosaic_size + 1); x_mos++) |
| 325 | | draw_bgtile_lores(layer, ii + x_mos, colour, pal, direct_colors, priority); |
| 326 | | ii += x_mos - 1; |
| 327 | | } |
| 328 | | else |
| 329 | | draw_bgtile_lores(layer, ii, colour, pal, direct_colors, priority); |
| 330 | | } |
| 331 | | else /* hires */ |
| 332 | | { |
| 333 | | if (mosaic) |
| 334 | | { |
| 335 | | for (x_mos = 0; x_mos < (m_mosaic_size + 1); x_mos++) |
| 336 | | draw_bgtile_hires(layer, ii + x_mos, colour, pal, direct_colors, priority); |
| 337 | | ii += x_mos - 1; |
| 338 | | } |
| 339 | | else |
| 340 | | draw_bgtile_hires(layer, ii, colour, pal, direct_colors, priority); |
| 341 | | } |
| 342 | | } |
| 343 | | } |
| 344 | | |
| 345 | | /************************************************************************************************* |
| 346 | | * SNES BG layers |
| 347 | | * |
| 348 | | * BG drawing theory of each scanline is quite easy: depending on the graphics Mode (0-7), there |
| 349 | | * are up to 4 background layers. Pixels for each BG layer can have two different priorities. |
| 350 | | * Depending on the line and on the BGHOFS and BGVOFS PPU registers, we first determine the tile |
| 351 | | * address in m_vram (by determining x,y coord and tile size and by calling get_tmap_addr). |
| 352 | | * Then, we load the correspondent data and we determine the tile properties: which priority to |
| 353 | | * use, which palette etc. Finally, for each pixel of the tile appearing on screen, we check if |
| 354 | | * the tile priority is higher than the BG/OAM already stored in that pixel for that line. If so |
| 355 | | * we store the pixel in the buffer, otherwise we discard it. |
| 356 | | * |
| 357 | | * Of course, depending on the graphics Mode, it might be easier or harder to determine the proper |
| 358 | | * tile address in vram (Mode 7 uses different registers, Mode 2, 4 and 6 uses OPT effect, etc.), |
| 359 | | * but in general it works as described. |
| 360 | | *************************************************************************************************/ |
| 361 | | |
| 362 | | /********************************************* |
| 363 | | * get_tmap_addr() |
| 364 | | * |
| 365 | | * Find the address in VRAM of the tile (x,y) |
| 366 | | *********************************************/ |
| 367 | | |
| 368 | | inline UINT32 snes_ppu_class::get_tmap_addr( UINT8 layer, UINT8 tile_size, UINT32 base, UINT32 x, UINT32 y ) |
| 369 | | { |
| 370 | | UINT32 res = base; |
| 371 | | x >>= (3 + tile_size); |
| 372 | | y >>= (3 + tile_size); |
| 373 | | |
| 374 | | res += (m_layer[layer].tilemap_size & 2) ? ((y & 0x20) << ((m_layer[layer].tilemap_size & 1) ? 7 : 6)) : 0; |
| 375 | | /* Scroll vertically */ |
| 376 | | res += (y & 0x1f) << 6; |
| 377 | | /* Offset horizontally */ |
| 378 | | res += (m_layer[layer].tilemap_size & 1) ? ((x & 0x20) << 6) : 0; |
| 379 | | /* Scroll horizontally */ |
| 380 | | res += (x & 0x1f) << 1; |
| 381 | | |
| 382 | | return res; |
| 383 | | } |
| 384 | | |
| 385 | | /********************************************* |
| 386 | | * update_line() |
| 387 | | * |
| 388 | | * Update an entire line of tiles. |
| 389 | | *********************************************/ |
| 390 | | |
| 391 | | inline void snes_ppu_class::update_line( UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a, UINT8 color_depth, UINT8 hires, UINT8 offset_per_tile, UINT8 direct_colors ) |
| 392 | | { |
| 393 | | UINT32 tmap, tile, xoff, yoff, charaddr, addr; |
| 394 | | UINT16 ii = 0, vflip, hflip, pal, pal_direct, tilemap; |
| 395 | | UINT8 xscroll, priority; |
| 396 | | INT8 yscroll; |
| 397 | | int tile_incr = 0; |
| 398 | | UINT16 opt_bit = (layer == SNES_BG1) ? 13 : (layer == SNES_BG2) ? 14 : 0; |
| 399 | | UINT8 tile_size; |
| 400 | | /* variables depending on color_depth */ |
| 401 | | UINT8 color_planes = 2 << color_depth; |
| 402 | | /* below we cheat to simplify the code: 8BPP should have 0 pal offset, not 0x100 (but we take care of this by later using pal % FIXED_COLOUR) */ |
| 403 | | UINT8 color_shift = 2 << color_depth; |
| 404 | | |
| 405 | | #if SNES_LAYER_DEBUG |
| 406 | | if (m_debug_options.bg_disabled[layer]) |
| 407 | | return; |
| 408 | | #endif /* SNES_LAYER_DEBUG */ |
| 409 | | |
| 410 | | m_scanlines[SNES_MAINSCREEN].enable = m_layer[layer].main_bg_enabled; |
| 411 | | m_scanlines[SNES_SUBSCREEN].enable = m_layer[layer].sub_bg_enabled; |
| 412 | | m_scanlines[SNES_MAINSCREEN].clip = m_layer[layer].main_window_enabled; |
| 413 | | m_scanlines[SNES_SUBSCREEN].clip = m_layer[layer].sub_window_enabled; |
| 414 | | |
| 415 | | if (!m_scanlines[SNES_MAINSCREEN].enable && !m_scanlines[SNES_SUBSCREEN].enable) |
| 416 | | return; |
| 417 | | |
| 418 | | /* Handle Mosaic effects */ |
| 419 | | if (m_layer[layer].mosaic_enabled) |
| 420 | | curline -= (curline % (m_mosaic_size + 1)); |
| 421 | | |
| 422 | | if ((m_interlace == 2) && !hires && !m_pseudo_hires) |
| 423 | | curline /= 2; |
| 424 | | |
| 425 | | /* Find the size of the tiles (8x8 or 16x16) */ |
| 426 | | tile_size = m_layer[layer].tile_size; |
| 427 | | |
| 428 | | /* Find scroll info */ |
| 429 | | xoff = m_layer[layer].hoffs; |
| 430 | | yoff = m_layer[layer].voffs; |
| 431 | | |
| 432 | | xscroll = xoff & ((1 << (3 + tile_size)) - 1); |
| 433 | | |
| 434 | | /* Jump to base map address */ |
| 435 | | tmap = m_layer[layer].tilemap << 9; |
| 436 | | charaddr = m_layer[layer].charmap << 13; |
| 437 | | |
| 438 | | while (ii < 256 + (8 << tile_size)) |
| 439 | | { |
| 440 | | // determine the horizontal position (Bishojo Janshi Suchi Pai & Desert Figther have tile_size & hires == 1) |
| 441 | | UINT32 xpos = xoff + (ii << (tile_size * hires)); |
| 442 | | UINT32 ypos = yoff + curline; |
| 443 | | |
| 444 | | if (offset_per_tile != SNES_OPT_NONE) |
| 445 | | { |
| 446 | | int opt_x = ii + (xoff & 7); |
| 447 | | UINT32 haddr = 0, vaddr = 0; |
| 448 | | UINT16 hval = 0, vval = 0; |
| 449 | | |
| 450 | | if (opt_x >= 8) |
| 451 | | { |
| 452 | | switch (offset_per_tile) |
| 453 | | { |
| 454 | | case SNES_OPT_MODE2: |
| 455 | | case SNES_OPT_MODE6: |
| 456 | | haddr = 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)); |
| 457 | | vaddr = 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); |
| 458 | | hval = m_vram[haddr % SNES_VRAM_SIZE] | (m_vram[(haddr + 1) % SNES_VRAM_SIZE] << 8); |
| 459 | | vval = m_vram[vaddr % SNES_VRAM_SIZE] | (m_vram[(vaddr + 1) % SNES_VRAM_SIZE] << 8); |
| 460 | | if (BIT(hval, opt_bit)) |
| 461 | | xpos = opt_x + (hval & ~7); |
| 462 | | if (BIT(vval, opt_bit)) |
| 463 | | ypos = curline + vval; |
| 464 | | break; |
| 465 | | case SNES_OPT_MODE4: |
| 466 | | haddr = 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)); |
| 467 | | hval = m_vram[haddr % SNES_VRAM_SIZE] | (m_vram[(haddr + 1) % SNES_VRAM_SIZE] << 8); |
| 468 | | if (BIT(hval, opt_bit)) |
| 469 | | { |
| 470 | | if (!BIT(hval, 15)) |
| 471 | | xpos = opt_x + (hval & ~7); |
| 472 | | else |
| 473 | | ypos = curline + hval; |
| 474 | | } |
| 475 | | break; |
| 476 | | } |
| 477 | | } |
| 478 | | } |
| 479 | | |
| 480 | | addr = get_tmap_addr(layer, tile_size, tmap, xpos, ypos); |
| 481 | | |
| 482 | | /* |
| 483 | | Tilemap format |
| 484 | | vhopppcc cccccccc |
| 485 | | |
| 486 | | v/h = Vertical/Horizontal flip this tile. |
| 487 | | o = Tile priority. |
| 488 | | ppp = Tile palette. The number of entries in the palette depends on the Mode and the BG. |
| 489 | | cccccccccc = Tile number. |
| 490 | | */ |
| 491 | | tilemap = m_vram[addr % SNES_VRAM_SIZE] | (m_vram[(addr + 1) % SNES_VRAM_SIZE] << 8); |
| 492 | | vflip = BIT(tilemap, 15); |
| 493 | | hflip = BIT(tilemap, 14); |
| 494 | | priority = BIT(tilemap, 13) ? priority_a : priority_b; |
| 495 | | pal_direct = ((tilemap & 0x1c00) >> 8); |
| 496 | | tile = tilemap & 0x03ff; |
| 497 | | |
| 498 | | pal = ((pal_direct >> 2) << color_shift); |
| 499 | | |
| 500 | | /* Mode 0 palettes are layer specific */ |
| 501 | | if (m_mode == 0) |
| 502 | | { |
| 503 | | pal += (layer << 5); |
| 504 | | } |
| 505 | | |
| 506 | | #if SNES_LAYER_DEBUG |
| 507 | | /* if we want to draw only one of the priorities of this layer */ |
| 508 | | if (((m_debug_options.select_pri[layer] & 0x01) && (priority == priority_a)) || |
| 509 | | ((m_debug_options.select_pri[layer] & 0x02) && (priority == priority_b))) |
| 510 | | { |
| 511 | | if (!hires && tile_size) |
| 512 | | ii += 16; |
| 513 | | else |
| 514 | | ii += 8; |
| 515 | | continue; |
| 516 | | } |
| 517 | | #endif /* SNES_LAYER_DEBUG */ |
| 518 | | |
| 519 | | /* figure out which line to draw */ |
| 520 | | yscroll = ypos & ((8 << tile_size) - 1); |
| 521 | | |
| 522 | | if (tile_size) |
| 523 | | if (BIT(yscroll, 3) != vflip) |
| 524 | | tile += 16; |
| 525 | | |
| 526 | | if (yscroll > 7) |
| 527 | | yscroll &= 7; |
| 528 | | |
| 529 | | if (vflip) |
| 530 | | yscroll = 7 - yscroll; |
| 531 | | |
| 532 | | yscroll <<= 1; |
| 533 | | |
| 534 | | /* if we have to draw 16 pixels, set tile_incr and adjust tile for horizontal flip */ |
| 535 | | if (tile_size || hires) |
| 536 | | { |
| 537 | | if (hflip) |
| 538 | | { |
| 539 | | tile += 1; |
| 540 | | tile_incr = -1; // next 8 pixels from previous tile (because of hflip) |
| 541 | | } |
| 542 | | else |
| 543 | | tile_incr = 1; // next 8 pixels from next tile |
| 544 | | } |
| 545 | | |
| 546 | | if (hires) |
| 547 | | { |
| 548 | | /* draw 16 pixels (the routine will automatically send half of them to the mainscreen scanline and half to the subscreen one) */ |
| 549 | | draw_tile(color_planes, layer, charaddr + (((tile + 0) & 0x3ff) * 8 * color_planes) + yscroll, (ii - xscroll) * 2, priority, hflip, direct_colors, direct_colors ? pal_direct : pal, hires); |
| 550 | | draw_tile(color_planes, layer, charaddr + (((tile + tile_incr) & 0x3ff) * 8 * color_planes) + yscroll, (ii - xscroll) * 2 + 8, priority, hflip, direct_colors, direct_colors ? pal_direct : pal, hires); |
| 551 | | ii += 8; |
| 552 | | } |
| 553 | | else |
| 554 | | { |
| 555 | | draw_tile(color_planes, layer, charaddr + ((tile & 0x3ff) * 8 * color_planes) + yscroll, ii - xscroll, priority, hflip, direct_colors, direct_colors ? pal_direct : pal, hires); |
| 556 | | ii += 8; |
| 557 | | |
| 558 | | if (tile_size) |
| 559 | | { |
| 560 | | draw_tile(color_planes, layer, charaddr + (((tile + tile_incr) & 0x3ff) * 8 * color_planes) + yscroll, ii - xscroll, priority, hflip, direct_colors, direct_colors ? pal_direct : pal, hires); |
| 561 | | ii += 8; |
| 562 | | } |
| 563 | | } |
| 564 | | } |
| 565 | | } |
| 566 | | |
| 567 | | |
| 568 | | /********************************************* |
| 569 | | * update_line_mode7() |
| 570 | | * |
| 571 | | * Update an entire line of mode7 tiles. |
| 572 | | *********************************************/ |
| 573 | | |
| 574 | | #define MODE7_CLIP(x) (((x) & 0x2000) ? ((x) | ~0x03ff) : ((x) & 0x03ff)) |
| 575 | | |
| 576 | | void snes_ppu_class::update_line_mode7( UINT16 curline, UINT8 layer, UINT8 priority_b, UINT8 priority_a ) |
| 577 | | { |
| 578 | | UINT32 tiled; |
| 579 | | INT16 ma, mb, mc, md; |
| 580 | | INT32 xc, yc, tx, ty, sx, sy, hs, vs, xpos, xdir, x0, y0; |
| 581 | | UINT8 priority = priority_b; |
| 582 | | UINT8 colour = 0; |
| 583 | | UINT16 *mosaic_x, *mosaic_y; |
| 584 | | UINT16 c; |
| 585 | | int screen; |
| 586 | | |
| 587 | | #if SNES_LAYER_DEBUG |
| 588 | | if (m_debug_options.bg_disabled[layer]) |
| 589 | | return; |
| 590 | | #endif /* SNES_LAYER_DEBUG */ |
| 591 | | |
| 592 | | m_scanlines[SNES_MAINSCREEN].enable = m_layer[layer].main_bg_enabled; |
| 593 | | m_scanlines[SNES_SUBSCREEN].enable = m_layer[layer].sub_bg_enabled; |
| 594 | | m_scanlines[SNES_MAINSCREEN].clip = m_layer[layer].main_window_enabled; |
| 595 | | m_scanlines[SNES_SUBSCREEN].clip = m_layer[layer].sub_window_enabled; |
| 596 | | |
| 597 | | if (!m_scanlines[SNES_MAINSCREEN].enable && !m_scanlines[SNES_SUBSCREEN].enable) |
| 598 | | return; |
| 599 | | |
| 600 | | ma = m_mode7.matrix_a; |
| 601 | | mb = m_mode7.matrix_b; |
| 602 | | mc = m_mode7.matrix_c; |
| 603 | | md = m_mode7.matrix_d; |
| 604 | | xc = m_mode7.origin_x; |
| 605 | | yc = m_mode7.origin_y; |
| 606 | | hs = m_mode7.hor_offset; |
| 607 | | vs = m_mode7.ver_offset; |
| 608 | | |
| 609 | | /* Sign extend */ |
| 610 | | xc <<= 19; |
| 611 | | xc >>= 19; |
| 612 | | yc <<= 19; |
| 613 | | yc >>= 19; |
| 614 | | hs <<= 19; |
| 615 | | hs >>= 19; |
| 616 | | vs <<= 19; |
| 617 | | vs >>= 19; |
| 618 | | |
| 619 | | /* Vertical flip */ |
| 620 | | if (m_mode7.vflip) |
| 621 | | sy = 255 - curline; |
| 622 | | else |
| 623 | | sy = curline; |
| 624 | | |
| 625 | | /* Horizontal flip */ |
| 626 | | if (m_mode7.hflip) |
| 627 | | { |
| 628 | | xpos = 255; |
| 629 | | xdir = -1; |
| 630 | | } |
| 631 | | else |
| 632 | | { |
| 633 | | xpos = 0; |
| 634 | | xdir = 1; |
| 635 | | } |
| 636 | | |
| 637 | | /* MOSAIC - to be verified */ |
| 638 | | if (layer == SNES_BG2) // BG2 use two different bits for horizontal and vertical mosaic |
| 639 | | { |
| 640 | | mosaic_x = m_mosaic_table[m_layer[SNES_BG2].mosaic_enabled ? m_mosaic_size : 0]; |
| 641 | | mosaic_y = m_mosaic_table[m_layer[SNES_BG1].mosaic_enabled ? m_mosaic_size : 0]; |
| 642 | | } |
| 643 | | else // BG1 works as usual |
| 644 | | { |
| 645 | | mosaic_x = m_mosaic_table[m_layer[SNES_BG1].mosaic_enabled ? m_mosaic_size : 0]; |
| 646 | | mosaic_y = m_mosaic_table[m_layer[SNES_BG1].mosaic_enabled ? m_mosaic_size : 0]; |
| 647 | | } |
| 648 | | |
| 649 | | #if SNES_LAYER_DEBUG |
| 650 | | if (m_debug_options.mosaic_disabled) |
| 651 | | { |
| 652 | | mosaic_x = m_mosaic_table[0]; |
| 653 | | mosaic_y = m_mosaic_table[0]; |
| 654 | | } |
| 655 | | #endif /* SNES_LAYER_DEBUG */ |
| 656 | | |
| 657 | | /* Let's do some mode7 drawing huh? */ |
| 658 | | /* These can be computed only once, since they do not depend on sx */ |
| 659 | | x0 = ((ma * MODE7_CLIP(hs - xc)) & ~0x3f) + ((mb * mosaic_y[sy]) & ~0x3f) + ((mb * MODE7_CLIP(vs - yc)) & ~0x3f) + (xc << 8); |
| 660 | | y0 = ((mc * MODE7_CLIP(hs - xc)) & ~0x3f) + ((md * mosaic_y[sy]) & ~0x3f) + ((md * MODE7_CLIP(vs - yc)) & ~0x3f) + (yc << 8); |
| 661 | | |
| 662 | | for (sx = 0; sx < 256; sx++, xpos += xdir) |
| 663 | | { |
| 664 | | tx = (x0 + (ma * mosaic_x[sx])) >> 8; |
| 665 | | ty = (y0 + (mc * mosaic_x[sx])) >> 8; |
| 666 | | |
| 667 | | switch (m_mode7.repeat) |
| 668 | | { |
| 669 | | case 0x00: /* Repeat if outside screen area */ |
| 670 | | case 0x01: /* Repeat if outside screen area */ |
| 671 | | tx &= 0x3ff; |
| 672 | | ty &= 0x3ff; |
| 673 | | tiled = m_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 674 | | colour = m_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 675 | | break; |
| 676 | | case 0x02: /* Single colour backdrop screen if outside screen area */ |
| 677 | | if ((tx >= 0) && (tx < 1024) && (ty >= 0) && (ty < 1024)) |
| 678 | | { |
| 679 | | tiled = m_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 680 | | colour = m_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 681 | | } |
| 682 | | else |
| 683 | | colour = 0; |
| 684 | | break; |
| 685 | | case 0x03: /* Character 0x00 repeat if outside screen area */ |
| 686 | | if ((tx >= 0) && (tx < 1024) && (ty >= 0) && (ty < 1024)) |
| 687 | | tiled = m_vram[((((tx >> 3) & 0x7f) + (((ty >> 3) & 0x7f) * 128)) * 2) % SNES_VRAM_SIZE] << 7; |
| 688 | | else |
| 689 | | tiled = 0; |
| 690 | | |
| 691 | | colour = m_vram[(tiled + ((tx & 0x07) * 2) + ((ty & 0x07) * 16) + 1) % SNES_VRAM_SIZE]; |
| 692 | | break; |
| 693 | | } |
| 694 | | |
| 695 | | /* The last bit is for priority in EXTBG mode (used only for BG2) */ |
| 696 | | if (layer == SNES_BG2) |
| 697 | | { |
| 698 | | priority = ((colour & 0x80) >> 7) ? priority_a : priority_b; |
| 699 | | colour &= 0x7f; |
| 700 | | |
| 701 | | #if SNES_LAYER_DEBUG |
| 702 | | /* if we want to draw only one of the priorities of this layer */ |
| 703 | | if (((m_debug_options.select_pri[layer] & 0x01) && (priority == priority_a)) || |
| 704 | | ((m_debug_options.select_pri[layer] & 0x02) && (priority == priority_b))) |
| 705 | | continue; |
| 706 | | #endif /* SNES_LAYER_DEBUG */ |
| 707 | | } |
| 708 | | |
| 709 | | for (screen = SNES_MAINSCREEN; screen <= SNES_SUBSCREEN; screen++) |
| 710 | | { |
| 711 | | if (m_scanlines[screen].enable) |
| 712 | | { |
| 713 | | UINT8 clr = colour; |
| 714 | | UINT8 clipmask = m_clipmasks[layer][xpos]; |
| 715 | | |
| 716 | | #if SNES_LAYER_DEBUG |
| 717 | | if (m_debug_options.windows_disabled) |
| 718 | | clipmask = 0xff; |
| 719 | | #endif /* SNES_LAYER_DEBUG */ |
| 720 | | |
| 721 | | /* Clip to windows */ |
| 722 | | if (m_scanlines[screen].clip) |
| 723 | | clr &= clipmask; |
| 724 | | |
| 725 | | /* Draw pixel if appropriate */ |
| 726 | | if (m_scanlines[screen].priority[xpos] <= priority && clr > 0) |
| 727 | | { |
| 728 | | /* Direct select, but only outside EXTBG! */ |
| 729 | | // Direct color format is: 0 | BB000 | GGG00 | RRR00, HW confirms that the data is zero padded. |
| 730 | | // In other words, like normal direct color, with pal = 0 |
| 731 | | c = get_bgcolor(m_direct_color && layer == SNES_BG1, 0, clr); |
| 732 | | set_scanline_pixel(screen, xpos, c, priority, layer, 0); |
| 733 | | } |
| 734 | | } |
| 735 | | } |
| 736 | | } |
| 737 | | } |
| 738 | | |
| 739 | | /************************************************************************************************* |
| 740 | | * SNES Sprites |
| 741 | | * |
| 742 | | * 1. First of all: sprites are drawn one line in advance. We emulate this by caching the |
| 743 | | * starting vram address, the sprite size and the "name select" at each line, and by using |
| 744 | | * them the next line to output the proper sprites - see update_obsel. |
| 745 | | * |
| 746 | | * 2. Each line can select its sprites among 128 available ones in oam_ram, hence we start |
| 747 | | * by creating a list of the available objects (each one with its x,y coordinate, its size, |
| 748 | | * its tile address, etc.) - see oam_list_build. |
| 749 | | * |
| 750 | | * 3. Next, we start finding out which sprites will appear in the line: starting from |
| 751 | | * FirstSprite, we count 32 OBJs which intersect our line and we store their indexes in the |
| 752 | | * oam_itemlist array (if more than 32 sprites intersect our line, we set the Range Over |
| 753 | | * flag); then, selecting among these sprites, we count 34 8x8 tiles which are visible |
| 754 | | * in our line (i.e. whose x coord is between -size and 256) and we store the corresponding |
| 755 | | * coordinates/priorities/palettes/etc. in the oam_tilelist array (if more than 34 tiles would |
| 756 | | * appear on screen, we set the Time Over flag). |
| 757 | | * Notice that when we populate oam_tilelist, we proceed from oam_itemlist[31] (or from the last |
| 758 | | * item which intersects the scanline), towards oam_itemlist[0], i.e. the higher tiles (say |
| 759 | | * oam_tilelist[34], or the last tile which appear on screen) will contain FirstSprite object, |
| 760 | | * or the sprites with closer index to FirstSprite which get displayed. This will play an |
| 761 | | * important role for sprite priority - see update_objects_rto. |
| 762 | | * |
| 763 | | * 4. All the above happens at the beginning of each VIDEO_UPDATE. When we finally draw the |
| 764 | | * scanline, we pass through the oam_tilelist and we store the displayed pixels in our scanline |
| 765 | | * buffer. Notice that, for each pixel of a SNES sprite, only the priority of the topmost sprite |
| 766 | | * is tested against the priority of the BG pixel (because FirstSprite is on top of FirstSprite+1, |
| 767 | | * which is on top of FirstSprite+2, etc., and therefore other sprites are already covered by the |
| 768 | | * topmost one). To emulate this, we draw each tile over the previous ones no matter what |
| 769 | | * priorities are (differently from what we did with BGs): in the end, we will have in each pixel z |
| 770 | | * its topmost sprite and scanline.priority[z] will be the topmost sprite priority as expected. |
| 771 | | * Of course, sprite drawing must happen before BG drawing, so that afterwords BG pixels properly |
| 772 | | * test their priority with the one of the correct sprite - see update_objects. |
| 773 | | *************************************************************************************************/ |
| 774 | | |
| 775 | | |
| 776 | | /********************************************* |
| 777 | | * update_obsel() |
| 778 | | * |
| 779 | | * Update sprite settings for next line. |
| 780 | | *********************************************/ |
| 781 | | |
| 782 | | void snes_ppu_class::update_obsel( void ) |
| 783 | | { |
| 784 | | m_layer[SNES_OAM].charmap = m_oam.next_charmap; |
| 785 | | m_oam.name_select = m_oam.next_name_select; |
| 786 | | |
| 787 | | if (m_oam.size != m_oam.next_size) |
| 788 | | { |
| 789 | | m_oam.size = m_oam.next_size; |
| 790 | | m_update_oam_list = 1; |
| 791 | | } |
| 792 | | } |
| 793 | | |
| 794 | | /********************************************* |
| 795 | | * oam_list_build() |
| 796 | | * |
| 797 | | * Build a list of the available obj in OAM ram. |
| 798 | | *********************************************/ |
| 799 | | |
| 800 | | void snes_ppu_class::oam_list_build( void ) |
| 801 | | { |
| 802 | | UINT8 *oamram = (UINT8 *)m_oam_ram; |
| 803 | | INT16 oam = 0x1ff; |
| 804 | | UINT16 oam_extra = oam + 0x20; |
| 805 | | UINT16 extra = 0; |
| 806 | | int ii; |
| 807 | | |
| 808 | | m_update_oam_list = 0; // eventually, we can optimize the code by only calling this function when there is a change in size |
| 809 | | |
| 810 | | for (ii = 127; ii >= 0; ii--) |
| 811 | | { |
| 812 | | if (((ii + 1) % 4) == 0) |
| 813 | | extra = oamram[oam_extra--]; |
| 814 | | |
| 815 | | m_oam_spritelist[ii].vflip = (oamram[oam] & 0x80) >> 7; |
| 816 | | m_oam_spritelist[ii].hflip = (oamram[oam] & 0x40) >> 6; |
| 817 | | m_oam_spritelist[ii].priority_bits = (oamram[oam] & 0x30) >> 4; |
| 818 | | m_oam_spritelist[ii].pal = 128 + ((oamram[oam] & 0x0e) << 3); |
| 819 | | m_oam_spritelist[ii].tile = (oamram[oam--] & 0x1) << 8; |
| 820 | | m_oam_spritelist[ii].tile |= oamram[oam--]; |
| 821 | | m_oam_spritelist[ii].y = oamram[oam--] + 1; |
| 822 | | m_oam_spritelist[ii].x = oamram[oam--]; |
| 823 | | m_oam_spritelist[ii].size = (extra & 0x80) >> 7; |
| 824 | | extra <<= 1; |
| 825 | | m_oam_spritelist[ii].x |= ((extra & 0x80) << 1); |
| 826 | | extra <<= 1; |
| 827 | | |
| 828 | | m_oam_spritelist[ii].y *= m_obj_interlace; |
| 829 | | m_oam_spritelist[ii].y &= 0x1ff; |
| 830 | | |
| 831 | | m_oam_spritelist[ii].x &= 0x1ff; |
| 832 | | |
| 833 | | /* Determine object size */ |
| 834 | | switch (m_oam.size) |
| 835 | | { |
| 836 | | case 0: /* 8x8 or 16x16 */ |
| 837 | | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 2 : 1; |
| 838 | | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 2 : 1; |
| 839 | | break; |
| 840 | | case 1: /* 8x8 or 32x32 */ |
| 841 | | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 4 : 1; |
| 842 | | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 4 : 1; |
| 843 | | break; |
| 844 | | case 2: /* 8x8 or 64x64 */ |
| 845 | | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 8 : 1; |
| 846 | | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 8 : 1; |
| 847 | | break; |
| 848 | | case 3: /* 16x16 or 32x32 */ |
| 849 | | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 4 : 2; |
| 850 | | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 4 : 2; |
| 851 | | break; |
| 852 | | case 4: /* 16x16 or 64x64 */ |
| 853 | | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 8 : 2; |
| 854 | | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 8 : 2; |
| 855 | | break; |
| 856 | | case 5: /* 32x32 or 64x64 */ |
| 857 | | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 8 : 4; |
| 858 | | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 8 : 4; |
| 859 | | break; |
| 860 | | case 6: /* undocumented: 16x32 or 32x64 */ |
| 861 | | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 4 : 2; |
| 862 | | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 8 : 4; |
| 863 | | if (m_obj_interlace && !m_oam_spritelist[ii].size) |
| 864 | | m_oam_spritelist[ii].height = 2; |
| 865 | | break; |
| 866 | | case 7: /* undocumented: 16x32 or 32x32 */ |
| 867 | | m_oam_spritelist[ii].width = m_oam_spritelist[ii].size ? 4 : 2; |
| 868 | | m_oam_spritelist[ii].height = m_oam_spritelist[ii].size ? 4 : 4; |
| 869 | | if (m_obj_interlace && !m_oam_spritelist[ii].size) |
| 870 | | m_oam_spritelist[ii].height = 2; |
| 871 | | break; |
| 872 | | default: |
| 873 | | /* we should never enter here... */ |
| 874 | | logerror("Object size unsupported: %d\n", m_oam.size); |
| 875 | | break; |
| 876 | | } |
| 877 | | } |
| 878 | | } |
| 879 | | |
| 880 | | /********************************************* |
| 881 | | * is_sprite_on_scanline() |
| 882 | | * |
| 883 | | * Check if a given sprites intersect current |
| 884 | | * scanline |
| 885 | | *********************************************/ |
| 886 | | |
| 887 | | int snes_ppu_class::is_sprite_on_scanline( UINT16 curline, UINT8 sprite ) |
| 888 | | { |
| 889 | | //if sprite is entirely offscreen and doesn't wrap around to the left side of the screen, |
| 890 | | //then it is not counted. this *should* be 256, and not 255, even though dot 256 is offscreen. |
| 891 | | int spr_height = (m_oam_spritelist[sprite].height << 3); |
| 892 | | |
| 893 | | if (m_oam_spritelist[sprite].x > 256 && (m_oam_spritelist[sprite].x + (m_oam_spritelist[sprite].width << 3) - 1) < 512) |
| 894 | | return 0; |
| 895 | | |
| 896 | | if (curline >= m_oam_spritelist[sprite].y && curline < (m_oam_spritelist[sprite].y + spr_height)) |
| 897 | | return 1; |
| 898 | | |
| 899 | | if ((m_oam_spritelist[sprite].y + spr_height) >= 256 && curline < ((m_oam_spritelist[sprite].y + spr_height) & 255)) |
| 900 | | return 1; |
| 901 | | |
| 902 | | return 0; |
| 903 | | } |
| 904 | | |
| 905 | | /********************************************* |
| 906 | | * update_objects_rto() |
| 907 | | * |
| 908 | | * Determine which OBJs will be drawn on this |
| 909 | | * scanline. |
| 910 | | *********************************************/ |
| 911 | | |
| 912 | | void snes_ppu_class::update_objects_rto( UINT16 curline ) |
| 913 | | { |
| 914 | | int ii, jj, active_sprite; |
| 915 | | UINT8 range_over, time_over; |
| 916 | | INT8 xs, ys; |
| 917 | | UINT8 line; |
| 918 | | UINT8 height, width, vflip, hflip, priority, pal; |
| 919 | | UINT16 tile; |
| 920 | | INT16 x, y; |
| 921 | | UINT32 name_sel = 0; |
| 922 | | |
| 923 | | oam_list_build(); |
| 924 | | |
| 925 | | /* initialize counters */ |
| 926 | | range_over = 0; |
| 927 | | time_over = 0; |
| 928 | | |
| 929 | | /* setup the proper line */ |
| 930 | | curline /= m_interlace; |
| 931 | | curline *= m_obj_interlace; |
| 932 | | |
| 933 | | /* reset the list of first 32 objects which intersect current scanline */ |
| 934 | | memset(m_oam_itemlist, 0xff, 32); |
| 935 | | |
| 936 | | /* populate the list of 32 objects */ |
| 937 | | for (ii = 0; ii < 128; ii++) |
| 938 | | { |
| 939 | | active_sprite = (ii + m_oam.first_sprite) & 0x7f; |
| 940 | | |
| 941 | | if (!is_sprite_on_scanline(curline, active_sprite)) |
| 942 | | continue; |
| 943 | | |
| 944 | | if (range_over++ >= 32) |
| 945 | | break; |
| 946 | | |
| 947 | | m_oam_itemlist[range_over - 1] = active_sprite; |
| 948 | | } |
| 949 | | |
| 950 | | /* reset the list of first 34 tiles to be drawn */ |
| 951 | | for (ii = 0; ii < 34; ii++) |
| 952 | | m_oam_tilelist[ii].tileaddr = 0xffff; |
| 953 | | |
| 954 | | /* populate the list of 34 tiles */ |
| 955 | | for (ii = 31; ii >= 0; ii--) |
| 956 | | { |
| 957 | | if (m_oam_itemlist[ii] == 0xff) |
| 958 | | continue; |
| 959 | | |
| 960 | | active_sprite = m_oam_itemlist[ii]; |
| 961 | | |
| 962 | | tile = m_oam_spritelist[active_sprite].tile; |
| 963 | | x = m_oam_spritelist[active_sprite].x; |
| 964 | | y = m_oam_spritelist[active_sprite].y; |
| 965 | | height = m_oam_spritelist[active_sprite].height; |
| 966 | | width = m_oam_spritelist[active_sprite].width; |
| 967 | | vflip = m_oam_spritelist[active_sprite].vflip; |
| 968 | | hflip = m_oam_spritelist[active_sprite].hflip; |
| 969 | | priority = m_oam_spritelist[active_sprite].priority_bits; |
| 970 | | pal = m_oam_spritelist[active_sprite].pal; |
| 971 | | |
| 972 | | /* Adjust y, if past maximum position (for sprites which overlap between top & bottom) */ |
| 973 | | if (y >= (0x100 - 16) * m_interlace) |
| 974 | | y -= (0x100) * m_interlace; |
| 975 | | |
| 976 | | if (curline >= y && curline < (y + (height << 3))) |
| 977 | | { |
| 978 | | /* Only objects using tiles over 255 use name select */ |
| 979 | | name_sel = (tile < 256) ? 0 : m_oam.name_select; |
| 980 | | |
| 981 | | ys = (curline - y) >> 3; |
| 982 | | line = (curline - y) % 8; |
| 983 | | if (vflip) |
| 984 | | { |
| 985 | | ys = height - ys - 1; |
| 986 | | line = 7 - line; |
| 987 | | } |
| 988 | | line <<= 1; |
| 989 | | tile <<= 5; |
| 990 | | |
| 991 | | for (jj = 0; jj < width; jj++) |
| 992 | | { |
| 993 | | INT16 xx = (x + (jj << 3)) & 0x1ff; |
| 994 | | |
| 995 | | if (x != 256 && xx >= 256 && (xx + 7) < 512) |
| 996 | | continue; |
| 997 | | |
| 998 | | if (time_over++ >= 34) |
| 999 | | break; |
| 1000 | | |
| 1001 | | xs = (hflip) ? (width - 1 - jj) : jj; |
| 1002 | | m_oam_tilelist[time_over - 1].tileaddr = name_sel + tile + table_obj_offset[ys][xs] + line; |
| 1003 | | m_oam_tilelist[time_over - 1].hflip = hflip; |
| 1004 | | m_oam_tilelist[time_over - 1].x = xx; |
| 1005 | | m_oam_tilelist[time_over - 1].pal = pal; |
| 1006 | | m_oam_tilelist[time_over - 1].priority = priority; |
| 1007 | | } |
| 1008 | | } |
| 1009 | | } |
| 1010 | | |
| 1011 | | /* set Range Over flag if necessary */ |
| 1012 | | if (range_over > 32) |
| 1013 | | m_stat77 |= 0x40; |
| 1014 | | |
| 1015 | | /* set Time Over flag if necessary */ |
| 1016 | | if (time_over > 34) |
| 1017 | | m_stat77 |= 0x80; |
| 1018 | | } |
| 1019 | | |
| 1020 | | /********************************************* |
| 1021 | | * update_objects() |
| 1022 | | * |
| 1023 | | * Update an entire line of sprites. |
| 1024 | | *********************************************/ |
| 1025 | | |
| 1026 | | void snes_ppu_class::update_objects( UINT8 priority_oam0, UINT8 priority_oam1, UINT8 priority_oam2, UINT8 priority_oam3 ) |
| 1027 | | { |
| 1028 | | UINT8 pri, priority[4]; |
| 1029 | | UINT32 charaddr; |
| 1030 | | int ii; |
| 1031 | | |
| 1032 | | #if SNES_LAYER_DEBUG |
| 1033 | | if (m_debug_options.bg_disabled[SNES_OAM]) |
| 1034 | | return; |
| 1035 | | #endif /* SNES_LAYER_DEBUG */ |
| 1036 | | |
| 1037 | | m_scanlines[SNES_MAINSCREEN].enable = m_layer[SNES_OAM].main_bg_enabled; |
| 1038 | | m_scanlines[SNES_SUBSCREEN].enable = m_layer[SNES_OAM].sub_bg_enabled; |
| 1039 | | m_scanlines[SNES_MAINSCREEN].clip = m_layer[SNES_OAM].main_window_enabled; |
| 1040 | | m_scanlines[SNES_SUBSCREEN].clip = m_layer[SNES_OAM].sub_window_enabled; |
| 1041 | | |
| 1042 | | if (!m_scanlines[SNES_MAINSCREEN].enable && !m_scanlines[SNES_SUBSCREEN].enable) |
| 1043 | | return; |
| 1044 | | |
| 1045 | | charaddr = m_layer[SNES_OAM].charmap << 13; |
| 1046 | | |
| 1047 | | priority[0] = priority_oam0; |
| 1048 | | priority[1] = priority_oam1; |
| 1049 | | priority[2] = priority_oam2; |
| 1050 | | priority[3] = priority_oam3; |
| 1051 | | |
| 1052 | | /* finally draw the tiles from the tilelist */ |
| 1053 | | for (ii = 0; ii < 34; ii++) |
| 1054 | | { |
| 1055 | | int tile = ii; |
| 1056 | | #if SNES_LAYER_DEBUG |
| 1057 | | if (m_debug_options.sprite_reversed) |
| 1058 | | tile = 33 - ii; |
| 1059 | | #endif /* SNES_LAYER_DEBUG */ |
| 1060 | | |
| 1061 | | if (m_oam_tilelist[tile].tileaddr == 0xffff) |
| 1062 | | continue; |
| 1063 | | |
| 1064 | | pri = priority[m_oam_tilelist[tile].priority]; |
| 1065 | | |
| 1066 | | #if SNES_LAYER_DEBUG |
| 1067 | | if (m_debug_options.select_pri[SNES_OAM]) |
| 1068 | | { |
| 1069 | | int oam_draw = m_debug_options.select_pri[SNES_OAM] - 1; |
| 1070 | | if (oam_draw != m_oam_tilelist[tile].priority) |
| 1071 | | continue; |
| 1072 | | } |
| 1073 | | #endif /* SNES_LAYER_DEBUG */ |
| 1074 | | |
| 1075 | | /* OAM tiles have fixed planes (4), no direct color and no hires, but otherwise work the same as BG ones */ |
| 1076 | | draw_tile(4, SNES_OAM, charaddr + m_oam_tilelist[tile].tileaddr, m_oam_tilelist[tile].x, pri, m_oam_tilelist[tile].hflip, 0, m_oam_tilelist[tile].pal, 0); |
| 1077 | | } |
| 1078 | | } |
| 1079 | | |
| 1080 | | |
| 1081 | | /********************************************* |
| 1082 | | * snes_update_mode_X() |
| 1083 | | * |
| 1084 | | * Update Mode X line. |
| 1085 | | *********************************************/ |
| 1086 | | |
| 1087 | | void snes_ppu_class::update_mode_0( UINT16 curline ) |
| 1088 | | { |
| 1089 | | #if SNES_LAYER_DEBUG |
| 1090 | | if (m_debug_options.mode_disabled[0]) |
| 1091 | | return; |
| 1092 | | #endif /* SNES_LAYER_DEBUG */ |
| 1093 | | |
| 1094 | | update_objects(3, 6, 9, 12); |
| 1095 | | update_line(curline, SNES_BG1, 8, 11, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_NONE, 0); |
| 1096 | | update_line(curline, SNES_BG2, 7, 10, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_NONE, 0); |
| 1097 | | update_line(curline, SNES_BG3, 2, 5, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_NONE, 0); |
| 1098 | | update_line(curline, SNES_BG4, 1, 4, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_NONE, 0); |
| 1099 | | } |
| 1100 | | |
| 1101 | | void snes_ppu_class::update_mode_1( UINT16 curline ) |
| 1102 | | { |
| 1103 | | #if SNES_LAYER_DEBUG |
| 1104 | | if (m_debug_options.mode_disabled[1]) |
| 1105 | | return; |
| 1106 | | #endif /* SNES_LAYER_DEBUG */ |
| 1107 | | |
| 1108 | | if (!m_bg3_priority_bit) |
| 1109 | | { |
| 1110 | | update_objects(2, 4, 7, 10); |
| 1111 | | update_line(curline, SNES_BG1, 6, 9, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_NONE, 0); |
| 1112 | | update_line(curline, SNES_BG2, 5, 8, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_NONE, 0); |
| 1113 | | update_line(curline, SNES_BG3, 1, 3, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_NONE, 0); |
| 1114 | | } |
| 1115 | | else |
| 1116 | | { |
| 1117 | | update_objects(2, 3, 6, 9); |
| 1118 | | update_line(curline, SNES_BG1, 5, 8, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_NONE, 0); |
| 1119 | | update_line(curline, SNES_BG2, 4, 7, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_NONE, 0); |
| 1120 | | update_line(curline, SNES_BG3, 1, 10, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_NONE, 0); |
| 1121 | | } |
| 1122 | | } |
| 1123 | | |
| 1124 | | void snes_ppu_class::update_mode_2( UINT16 curline ) |
| 1125 | | { |
| 1126 | | #if SNES_LAYER_DEBUG |
| 1127 | | if (m_debug_options.mode_disabled[2]) |
| 1128 | | return; |
| 1129 | | #endif /* SNES_LAYER_DEBUG */ |
| 1130 | | |
| 1131 | | update_objects(2, 4, 6, 8); |
| 1132 | | update_line(curline, SNES_BG1, 3, 7, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_MODE2, 0); |
| 1133 | | update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_MODE2, 0); |
| 1134 | | } |
| 1135 | | |
| 1136 | | void snes_ppu_class::update_mode_3( UINT16 curline ) |
| 1137 | | { |
| 1138 | | #if SNES_LAYER_DEBUG |
| 1139 | | if (m_debug_options.mode_disabled[3]) |
| 1140 | | return; |
| 1141 | | #endif /* SNES_LAYER_DEBUG */ |
| 1142 | | |
| 1143 | | update_objects(2, 4, 6, 8); |
| 1144 | | update_line(curline, SNES_BG1, 3, 7, SNES_COLOR_DEPTH_8BPP, 0, SNES_OPT_NONE, m_direct_color); |
| 1145 | | update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_4BPP, 0, SNES_OPT_NONE, 0); |
| 1146 | | } |
| 1147 | | |
| 1148 | | void snes_ppu_class::update_mode_4( UINT16 curline ) |
| 1149 | | { |
| 1150 | | #if SNES_LAYER_DEBUG |
| 1151 | | if (m_debug_options.mode_disabled[4]) |
| 1152 | | return; |
| 1153 | | #endif /* SNES_LAYER_DEBUG */ |
| 1154 | | |
| 1155 | | update_objects(2, 4, 6, 8); |
| 1156 | | update_line(curline, SNES_BG1, 3, 7, SNES_COLOR_DEPTH_8BPP, 0, SNES_OPT_MODE4, m_direct_color); |
| 1157 | | update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_2BPP, 0, SNES_OPT_MODE4, 0); |
| 1158 | | } |
| 1159 | | |
| 1160 | | void snes_ppu_class::update_mode_5( UINT16 curline ) |
| 1161 | | { |
| 1162 | | #if SNES_LAYER_DEBUG |
| 1163 | | if (m_debug_options.mode_disabled[5]) |
| 1164 | | return; |
| 1165 | | #endif /* SNES_LAYER_DEBUG */ |
| 1166 | | |
| 1167 | | update_objects(2, 4, 6, 8); |
| 1168 | | update_line(curline, SNES_BG1, 3, 7, SNES_COLOR_DEPTH_4BPP, 1, SNES_OPT_NONE, 0); |
| 1169 | | update_line(curline, SNES_BG2, 1, 5, SNES_COLOR_DEPTH_2BPP, 1, SNES_OPT_NONE, 0); |
| 1170 | | } |
| 1171 | | |
| 1172 | | void snes_ppu_class::update_mode_6( UINT16 curline ) |
| 1173 | | { |
| 1174 | | #if SNES_LAYER_DEBUG |
| 1175 | | if (m_debug_options.mode_disabled[6]) |
| 1176 | | return; |
| 1177 | | #endif /* SNES_LAYER_DEBUG */ |
| 1178 | | |
| 1179 | | update_objects(1, 3, 4, 6); |
| 1180 | | update_line(curline, SNES_BG1, 2, 5, SNES_COLOR_DEPTH_4BPP, 1, SNES_OPT_MODE6, 0); |
| 1181 | | } |
| 1182 | | |
| 1183 | | void snes_ppu_class::update_mode_7( UINT16 curline ) |
| 1184 | | { |
| 1185 | | #if SNES_LAYER_DEBUG |
| 1186 | | if (m_debug_options.mode_disabled[7]) |
| 1187 | | return; |
| 1188 | | #endif /* SNES_LAYER_DEBUG */ |
| 1189 | | |
| 1190 | | if (!m_mode7.extbg) |
| 1191 | | { |
| 1192 | | update_objects(1, 3, 4, 5); |
| 1193 | | update_line_mode7(curline, SNES_BG1, 2, 2); |
| 1194 | | } |
| 1195 | | else |
| 1196 | | { |
| 1197 | | update_objects(2, 4, 6, 7); |
| 1198 | | update_line_mode7(curline, SNES_BG1, 3, 3); |
| 1199 | | update_line_mode7(curline, SNES_BG2, 1, 5); |
| 1200 | | } |
| 1201 | | } |
| 1202 | | |
| 1203 | | /********************************************* |
| 1204 | | * snes_draw_screens() |
| 1205 | | * |
| 1206 | | * Draw the whole screen (Mode 0 -> 7). |
| 1207 | | *********************************************/ |
| 1208 | | |
| 1209 | | void snes_ppu_class::draw_screens( UINT16 curline ) |
| 1210 | | { |
| 1211 | | switch (m_mode) |
| 1212 | | { |
| 1213 | | case 0: update_mode_0(curline); break; /* Mode 0 */ |
| 1214 | | case 1: update_mode_1(curline); break; /* Mode 1 */ |
| 1215 | | case 2: update_mode_2(curline); break; /* Mode 2 - Supports offset per tile */ |
| 1216 | | case 3: update_mode_3(curline); break; /* Mode 3 - Supports direct colour */ |
| 1217 | | case 4: update_mode_4(curline); break; /* Mode 4 - Supports offset per tile and direct colour */ |
| 1218 | | case 5: update_mode_5(curline); break; /* Mode 5 - Supports hires */ |
| 1219 | | case 6: update_mode_6(curline); break; /* Mode 6 - Supports offset per tile and hires */ |
| 1220 | | case 7: update_mode_7(curline); break; /* Mode 7 - Supports direct colour */ |
| 1221 | | } |
| 1222 | | } |
| 1223 | | |
| 1224 | | /********************************************* |
| 1225 | | * update_windowmasks() |
| 1226 | | * |
| 1227 | | * An example of how windows work: |
| 1228 | | * Win1: ...#####...... |
| 1229 | | * Win2: ......#####... |
| 1230 | | * IN OUT |
| 1231 | | * OR: ...########... ###........### |
| 1232 | | * AND: ......##...... ######..###### |
| 1233 | | * XOR: ...###..###... ###...##...### |
| 1234 | | * XNOR: ###...##...### ...###..###... |
| 1235 | | *********************************************/ |
| 1236 | | |
| 1237 | | void snes_ppu_class::update_windowmasks( void ) |
| 1238 | | { |
| 1239 | | UINT16 ii, jj; |
| 1240 | | INT8 w1, w2; |
| 1241 | | |
| 1242 | | m_update_windows = 0; /* reset the flag */ |
| 1243 | | |
| 1244 | | for (ii = 0; ii < SNES_SCR_WIDTH; ii++) |
| 1245 | | { |
| 1246 | | /* update bg 1, 2, 3, 4, obj & color windows */ |
| 1247 | | /* jj = layer */ |
| 1248 | | for (jj = 0; jj < 6; jj++) |
| 1249 | | { |
| 1250 | | m_clipmasks[jj][ii] = 0xff; /* let's start from un-masked */ |
| 1251 | | w1 = w2 = -1; |
| 1252 | | |
| 1253 | | if (m_layer[jj].window1_enabled) |
| 1254 | | { |
| 1255 | | /* Default to mask area inside */ |
| 1256 | | if ((ii < m_window1_left) || (ii > m_window1_right)) |
| 1257 | | w1 = 0; |
| 1258 | | else |
| 1259 | | w1 = 1; |
| 1260 | | |
| 1261 | | /* If mask area is outside then swap */ |
| 1262 | | if (m_layer[jj].window1_invert) |
| 1263 | | w1 = !w1; |
| 1264 | | } |
| 1265 | | |
| 1266 | | if (m_layer[jj].window2_enabled) |
| 1267 | | { |
| 1268 | | if ((ii < m_window2_left) || (ii > m_window2_right)) |
| 1269 | | w2 = 0; |
| 1270 | | else |
| 1271 | | w2 = 1; |
| 1272 | | if (m_layer[jj].window2_invert) |
| 1273 | | w2 = !w2; |
| 1274 | | } |
| 1275 | | |
| 1276 | | /* mask if the appropriate expression is true */ |
| 1277 | | if (w1 >= 0 && w2 >= 0) |
| 1278 | | { |
| 1279 | | switch (m_layer[jj].wlog_mask) |
| 1280 | | { |
| 1281 | | case 0x00: /* OR */ |
| 1282 | | m_clipmasks[jj][ii] = (w1 | w2) ? 0x00 : 0xff; |
| 1283 | | break; |
| 1284 | | case 0x01: /* AND */ |
| 1285 | | m_clipmasks[jj][ii] = (w1 & w2) ? 0x00 : 0xff; |
| 1286 | | break; |
| 1287 | | case 0x02: /* XOR */ |
| 1288 | | m_clipmasks[jj][ii] = (w1 ^ w2) ? 0x00 : 0xff; |
| 1289 | | break; |
| 1290 | | case 0x03: /* XNOR */ |
| 1291 | | m_clipmasks[jj][ii] = !(w1 ^ w2) ? 0x00 : 0xff; |
| 1292 | | break; |
| 1293 | | } |
| 1294 | | } |
| 1295 | | else if (w1 >= 0) |
| 1296 | | m_clipmasks[jj][ii] = w1 ? 0x00 : 0xff; |
| 1297 | | else if (w2 >= 0) |
| 1298 | | m_clipmasks[jj][ii] = w2 ? 0x00 : 0xff; |
| 1299 | | } |
| 1300 | | } |
| 1301 | | } |
| 1302 | | |
| 1303 | | /********************************************* |
| 1304 | | * update_offsets() |
| 1305 | | * |
| 1306 | | * Update the offsets with the latest changes. |
| 1307 | | * This is currently unused, but it could |
| 1308 | | * possibly be handy for some minor optimization |
| 1309 | | *********************************************/ |
| 1310 | | |
| 1311 | | void snes_ppu_class::update_offsets( void ) |
| 1312 | | { |
| 1313 | | int ii; |
| 1314 | | for (ii = 0; ii < 4; ii++) |
| 1315 | | { |
| 1316 | | } |
| 1317 | | m_update_offsets = 0; |
| 1318 | | } |
| 1319 | | |
| 1320 | | /***************************************** |
| 1321 | | * draw_blend() |
| 1322 | | * |
| 1323 | | * Routine for additive/subtractive blending |
| 1324 | | * between the main and sub screens, i.e. |
| 1325 | | * color math. |
| 1326 | | *****************************************/ |
| 1327 | | |
| 1328 | | inline void snes_ppu_class::draw_blend( UINT16 offset, UINT16 *colour, UINT8 prevent_color_math, UINT8 black_pen_clip, int switch_screens ) |
| 1329 | | { |
| 1330 | | #if SNES_LAYER_DEBUG |
| 1331 | | if (m_debug_options.colormath_disabled) |
| 1332 | | return; |
| 1333 | | #endif /* SNES_LAYER_DEBUG */ |
| 1334 | | |
| 1335 | | /* when color math is applied to subscreen pixels, the blending depends on the blending used by the previous mainscreen |
| 1336 | | pixel, except for subscreen pixel 0 which has no previous mainscreen pixel, see comments in refresh_scanline */ |
| 1337 | | if (switch_screens && offset > 0) |
| 1338 | | offset -= 1; |
| 1339 | | |
| 1340 | | if ((black_pen_clip == SNES_CLIP_ALWAYS) || |
| 1341 | | (black_pen_clip == SNES_CLIP_IN && m_clipmasks[SNES_COLOR][offset]) || |
| 1342 | | (black_pen_clip == SNES_CLIP_OUT && !m_clipmasks[SNES_COLOR][offset])) |
| 1343 | | *colour = 0; //clip to black before color math |
| 1344 | | |
| 1345 | | if (prevent_color_math == SNES_CLIP_ALWAYS) // blending mode 3 == always OFF |
| 1346 | | return; |
| 1347 | | |
| 1348 | | if ((prevent_color_math == SNES_CLIP_NEVER) || |
| 1349 | | (prevent_color_math == SNES_CLIP_IN && !m_clipmasks[SNES_COLOR][offset]) || |
| 1350 | | (prevent_color_math == SNES_CLIP_OUT && m_clipmasks[SNES_COLOR][offset])) |
| 1351 | | { |
| 1352 | | UINT16 r, g, b; |
| 1353 | | struct SNES_SCANLINE *subscreen; |
| 1354 | | int clip_max = 0; // if add then clip to 0x1f, if sub then clip to 0 |
| 1355 | | |
| 1356 | | #if SNES_LAYER_DEBUG |
| 1357 | | /* Toggle drawing of SNES_SUBSCREEN or SNES_MAINSCREEN */ |
| 1358 | | if (m_debug_options.draw_subscreen) |
| 1359 | | { |
| 1360 | | subscreen = switch_screens ? &m_scanlines[SNES_SUBSCREEN] : &m_scanlines[SNES_MAINSCREEN]; |
| 1361 | | } |
| 1362 | | else |
| 1363 | | #endif /* SNES_LAYER_DEBUG */ |
| 1364 | | { |
| 1365 | | subscreen = switch_screens ? &m_scanlines[SNES_MAINSCREEN] : &m_scanlines[SNES_SUBSCREEN]; |
| 1366 | | } |
| 1367 | | |
| 1368 | | if (m_sub_add_mode) /* SNES_SUBSCREEN*/ |
| 1369 | | { |
| 1370 | | if (!BIT(m_color_modes, 7)) |
| 1371 | | { |
| 1372 | | /* 0x00 add */ |
| 1373 | | r = (*colour & 0x1f) + (subscreen->buffer[offset] & 0x1f); |
| 1374 | | g = ((*colour & 0x3e0) >> 5) + ((subscreen->buffer[offset] & 0x3e0) >> 5); |
| 1375 | | b = ((*colour & 0x7c00) >> 10) + ((subscreen->buffer[offset] & 0x7c00) >> 10); |
| 1376 | | clip_max = 1; |
| 1377 | | } |
| 1378 | | else |
| 1379 | | { |
| 1380 | | /* 0x80 sub */ |
| 1381 | | r = (*colour & 0x1f) - (subscreen->buffer[offset] & 0x1f); |
| 1382 | | g = ((*colour & 0x3e0) >> 5) - ((subscreen->buffer[offset] & 0x3e0) >> 5); |
| 1383 | | b = ((*colour & 0x7c00) >> 10) - ((subscreen->buffer[offset] & 0x7c00) >> 10); |
| 1384 | | if (r > 0x1f) r = 0; |
| 1385 | | if (g > 0x1f) g = 0; |
| 1386 | | if (b > 0x1f) b = 0; |
| 1387 | | } |
| 1388 | | /* only halve if the color is not the back colour */ |
| 1389 | | if (BIT(m_color_modes, 6) && (subscreen->buffer[offset] != m_cgram[FIXED_COLOUR])) |
| 1390 | | { |
| 1391 | | r >>= 1; |
| 1392 | | g >>= 1; |
| 1393 | | b >>= 1; |
| 1394 | | } |
| 1395 | | } |
| 1396 | | else /* Fixed colour */ |
| 1397 | | { |
| 1398 | | if (!BIT(m_color_modes, 7)) |
| 1399 | | { |
| 1400 | | /* 0x00 add */ |
| 1401 | | r = (*colour & 0x1f) + (m_cgram[FIXED_COLOUR] & 0x1f); |
| 1402 | | g = ((*colour & 0x3e0) >> 5) + ((m_cgram[FIXED_COLOUR] & 0x3e0) >> 5); |
| 1403 | | b = ((*colour & 0x7c00) >> 10) + ((m_cgram[FIXED_COLOUR] & 0x7c00) >> 10); |
| 1404 | | clip_max = 1; |
| 1405 | | } |
| 1406 | | else |
| 1407 | | { |
| 1408 | | /* 0x80: sub */ |
| 1409 | | r = (*colour & 0x1f) - (m_cgram[FIXED_COLOUR] & 0x1f); |
| 1410 | | g = ((*colour & 0x3e0) >> 5) - ((m_cgram[FIXED_COLOUR] & 0x3e0) >> 5); |
| 1411 | | b = ((*colour & 0x7c00) >> 10) - ((m_cgram[FIXED_COLOUR] & 0x7c00) >> 10); |
| 1412 | | if (r > 0x1f) r = 0; |
| 1413 | | if (g > 0x1f) g = 0; |
| 1414 | | if (b > 0x1f) b = 0; |
| 1415 | | } |
| 1416 | | /* halve if necessary */ |
| 1417 | | if (BIT(m_color_modes, 6)) |
| 1418 | | { |
| 1419 | | r >>= 1; |
| 1420 | | g >>= 1; |
| 1421 | | b >>= 1; |
| 1422 | | } |
| 1423 | | } |
| 1424 | | |
| 1425 | | /* according to anomie's docs, after addition has been performed, division by 2 happens *before* clipping to max, hence we clip now */ |
| 1426 | | if (clip_max) |
| 1427 | | { |
| 1428 | | if (r > 0x1f) r = 0x1f; |
| 1429 | | if (g > 0x1f) g = 0x1f; |
| 1430 | | if (b > 0x1f) b = 0x1f; |
| 1431 | | } |
| 1432 | | |
| 1433 | | *colour = ((r & 0x1f) | ((g & 0x1f) << 5) | ((b & 0x1f) << 10)); |
| 1434 | | } |
| 1435 | | } |
| 1436 | | |
| 1437 | | /********************************************* |
| 1438 | | * refresh_scanline() |
| 1439 | | * |
| 1440 | | * Redraw the current line. |
| 1441 | | *********************************************/ |
| 1442 | | /********************************************* |
| 1443 | | * Notice that in hires and pseudo hires modes, |
| 1444 | | * i.e. when 512 different pixels are present |
| 1445 | | * in a scanline, a crt TV monitor would end |
| 1446 | | * up blending adjacent pixels. To mimic this, |
| 1447 | | * we add a small (optional) hack which enters |
| 1448 | | * only in the very last stage of the scanline |
| 1449 | | * drawing and which simulates the TV by |
| 1450 | | * replacing the exact pixel color with an |
| 1451 | | * average of the current and next pixel colors. |
| 1452 | | * Credits (and thanks) to Blargg and Byuu for |
| 1453 | | * the optimized averaging algorithm. |
| 1454 | | *********************************************/ |
| 1455 | | |
| 1456 | | void snes_ppu_class::refresh_scanline( running_machine &machine, bitmap_rgb32 &bitmap, UINT16 curline ) |
| 1457 | | { |
| 1458 | | UINT16 ii; |
| 1459 | | int x; |
| 1460 | | int fade; |
| 1461 | | struct SNES_SCANLINE *scanline1, *scanline2; |
| 1462 | | UINT16 c; |
| 1463 | | UINT16 prev_colour = 0; |
| 1464 | | int blurring = machine.root_device().ioport("OPTIONS")->read_safe(0) & 0x01; |
| 1465 | | |
| 1466 | | g_profiler.start(PROFILER_VIDEO); |
| 1467 | | |
| 1468 | | if (m_screen_disabled) /* screen is forced blank */ |
| 1469 | | for (x = 0; x < SNES_SCR_WIDTH * 2; x++) |
| 1470 | | bitmap.pix32(curline, x) = rgb_t::black; |
| 1471 | | else |
| 1472 | | { |
| 1473 | | /* Update clip window masks if necessary */ |
| 1474 | | if (m_update_windows) |
| 1475 | | update_windowmasks(); |
| 1476 | | /* Update the offsets if necessary */ |
| 1477 | | if (m_update_offsets) |
| 1478 | | update_offsets(); |
| 1479 | | |
| 1480 | | /* Clear priority */ |
| 1481 | | memset(m_scanlines[SNES_MAINSCREEN].priority, 0, SNES_SCR_WIDTH); |
| 1482 | | memset(m_scanlines[SNES_SUBSCREEN].priority, 0, SNES_SCR_WIDTH); |
| 1483 | | |
| 1484 | | /* Clear layers */ |
| 1485 | | memset(m_scanlines[SNES_MAINSCREEN].layer, SNES_COLOR, SNES_SCR_WIDTH); |
| 1486 | | memset(m_scanlines[SNES_SUBSCREEN].layer, SNES_COLOR, SNES_SCR_WIDTH); |
| 1487 | | |
| 1488 | | /* Clear blend_exception (only used for OAM) */ |
| 1489 | | memset(m_scanlines[SNES_MAINSCREEN].blend_exception, 0, SNES_SCR_WIDTH); |
| 1490 | | memset(m_scanlines[SNES_SUBSCREEN].blend_exception, 0, SNES_SCR_WIDTH); |
| 1491 | | |
| 1492 | | /* Draw back colour */ |
| 1493 | | for (ii = 0; ii < SNES_SCR_WIDTH; ii++) |
| 1494 | | { |
| 1495 | | if (m_mode == 5 || m_mode == 6 || m_pseudo_hires) |
| 1496 | | m_scanlines[SNES_SUBSCREEN].buffer[ii] = m_cgram[0]; |
| 1497 | | else |
| 1498 | | m_scanlines[SNES_SUBSCREEN].buffer[ii] = m_cgram[FIXED_COLOUR]; |
| 1499 | | |
| 1500 | | m_scanlines[SNES_MAINSCREEN].buffer[ii] = m_cgram[0]; |
| 1501 | | } |
| 1502 | | |
| 1503 | | /* Prepare OAM for this scanline */ |
| 1504 | | update_objects_rto(curline); |
| 1505 | | |
| 1506 | | /* Draw scanline */ |
| 1507 | | draw_screens(curline); |
| 1508 | | |
| 1509 | | update_obsel(); |
| 1510 | | |
| 1511 | | #if SNES_LAYER_DEBUG |
| 1512 | | if (dbg_video(machine, curline)) |
| 1513 | | { |
| 1514 | | g_profiler.stop(); |
| 1515 | | return; |
| 1516 | | } |
| 1517 | | |
| 1518 | | /* Toggle drawing of SNES_SUBSCREEN or SNES_MAINSCREEN */ |
| 1519 | | if (m_debug_options.draw_subscreen) |
| 1520 | | { |
| 1521 | | scanline1 = &m_scanlines[SNES_SUBSCREEN]; |
| 1522 | | scanline2 = &m_scanlines[SNES_MAINSCREEN]; |
| 1523 | | } |
| 1524 | | else |
| 1525 | | #endif /* SNES_LAYER_DEBUG */ |
| 1526 | | { |
| 1527 | | scanline1 = &m_scanlines[SNES_MAINSCREEN]; |
| 1528 | | scanline2 = &m_scanlines[SNES_SUBSCREEN]; |
| 1529 | | } |
| 1530 | | |
| 1531 | | /* Draw the scanline to screen */ |
| 1532 | | |
| 1533 | | fade = m_screen_brightness; |
| 1534 | | |
| 1535 | | for (x = 0; x < SNES_SCR_WIDTH; x++) |
| 1536 | | { |
| 1537 | | int r, g, b, hires; |
| 1538 | | UINT16 tmp_col[2]; |
| 1539 | | hires = (m_mode != 5 && m_mode != 6 && !m_pseudo_hires) ? 0 : 1; |
| 1540 | | |
| 1541 | | /* in hires, the first pixel (of 512) is subscreen pixel, then the first mainscreen pixel follows, and so on... */ |
| 1542 | | if (!hires) |
| 1543 | | { |
| 1544 | | c = scanline1->buffer[x]; |
| 1545 | | |
| 1546 | | /* perform color math if the layer wants it (except if it's an object > 192) */ |
| 1547 | | if (!scanline1->blend_exception[x] && m_layer[scanline1->layer[x]].color_math) |
| 1548 | | draw_blend(x, &c, m_prevent_color_math, m_clip_to_black, 0); |
| 1549 | | |
| 1550 | | r = ((c & 0x1f) * fade) >> 4; |
| 1551 | | g = (((c & 0x3e0) >> 5) * fade) >> 4; |
| 1552 | | b = (((c & 0x7c00) >> 10) * fade) >> 4; |
| 1553 | | |
| 1554 | | bitmap.pix32(curline, x * 2 + 0) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b)); |
| 1555 | | bitmap.pix32(curline, x * 2 + 1) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b)); |
| 1556 | | } |
| 1557 | | else |
| 1558 | | { |
| 1559 | | /* prepare the pixel from main screen */ |
| 1560 | | c = scanline1->buffer[x]; |
| 1561 | | |
| 1562 | | /* perform color math if the layer wants it (except if it's an object > 192) */ |
| 1563 | | if (!scanline1->blend_exception[x] && m_layer[scanline1->layer[x]].color_math) |
| 1564 | | draw_blend(x, &c, m_prevent_color_math, m_clip_to_black, 0); |
| 1565 | | |
| 1566 | | tmp_col[1] = c; |
| 1567 | | |
| 1568 | | /* prepare the pixel from sub screen */ |
| 1569 | | c = scanline2->buffer[x]; |
| 1570 | | |
| 1571 | | /* in hires/pseudo-hires, subscreen pixels are blended as well: for each subscreen pixel, color math |
| 1572 | | is applied if it had been applied to the previous mainscreen pixel. What happens at subscreen pixel 0 |
| 1573 | | (which has no previous mainscreen pixel) is undocumented. Until more info are discovered, we (arbitrarily) |
| 1574 | | apply to it the same color math as the *next* mainscreen pixel (i.e. mainscreen pixel 0), which seems as good as |
| 1575 | | any other choice */ |
| 1576 | | if (x == 0 && !scanline1->blend_exception[0] && m_layer[scanline1->layer[0]].color_math) |
| 1577 | | draw_blend(0, &c, m_prevent_color_math, m_clip_to_black, 1); |
| 1578 | | else if (x > 0 && !scanline1->blend_exception[x - 1] && m_layer[scanline1->layer[x - 1]].color_math) |
| 1579 | | draw_blend(x, &c, m_prevent_color_math, m_clip_to_black, 1); |
| 1580 | | |
| 1581 | | tmp_col[0] = c; |
| 1582 | | |
| 1583 | | /* average the first pixel if required, or draw it directly*/ |
| 1584 | | if (blurring) |
| 1585 | | c = (prev_colour + tmp_col[0] - ((prev_colour ^ tmp_col[0]) & 0x0421)) >> 1; // Hack code to mimic TV pixel blurring |
| 1586 | | else |
| 1587 | | c = tmp_col[0]; |
| 1588 | | |
| 1589 | | r = ((c & 0x1f) * fade) >> 4; |
| 1590 | | g = (((c & 0x3e0) >> 5) * fade) >> 4; |
| 1591 | | b = (((c & 0x7c00) >> 10) * fade) >> 4; |
| 1592 | | |
| 1593 | | bitmap.pix32(curline, x * 2 + 0) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b)); |
| 1594 | | prev_colour = tmp_col[0]; |
| 1595 | | |
| 1596 | | /* average the second pixel if required, or draw it directly*/ |
| 1597 | | if (blurring) |
| 1598 | | c = (prev_colour + tmp_col[1] - ((prev_colour ^ tmp_col[1]) & 0x0421)) >> 1; // Hack code to mimic TV pixel blurring |
| 1599 | | else |
| 1600 | | c = tmp_col[1]; |
| 1601 | | |
| 1602 | | r = ((c & 0x1f) * fade) >> 4; |
| 1603 | | g = (((c & 0x3e0) >> 5) * fade) >> 4; |
| 1604 | | b = (((c & 0x7c00) >> 10) * fade) >> 4; |
| 1605 | | |
| 1606 | | bitmap.pix32(curline, x * 2 + 1) = rgb_t(pal5bit(r), pal5bit(g), pal5bit(b)); |
| 1607 | | prev_colour = tmp_col[1]; |
| 1608 | | } |
| 1609 | | } |
| 1610 | | } |
| 1611 | | |
| 1612 | | g_profiler.stop(); |
| 1613 | | } |
| 1614 | | |
| 1615 | | void snes_ppu_class::ppu_start(screen_device &screen,snes_state *state) |
| 1616 | | { |
| 1617 | | m_screen = &screen; |
| 1618 | | running_machine &machine = screen.machine(); |
| 1619 | | m_state = state; |
| 1620 | | #if SNES_LAYER_DEBUG |
| 1621 | | memset(&m_debug_options, 0, sizeof(m_debug_options)); |
| 1622 | | #endif |
| 1623 | | |
| 1624 | | m_vram = auto_alloc_array(machine, UINT8, SNES_VRAM_SIZE); |
| 1625 | | m_cgram = auto_alloc_array(machine, UINT16, SNES_CGRAM_SIZE/2); |
| 1626 | | m_oam_ram = auto_alloc_array(machine, UINT16, SNES_OAM_SIZE/2); |
| 1627 | | |
| 1628 | | /* Inititialize registers/variables */ |
| 1629 | | m_update_windows = 1; |
| 1630 | | m_beam.latch_vert = 0; |
| 1631 | | m_beam.latch_horz = 0; |
| 1632 | | m_beam.current_vert = 0; |
| 1633 | | m_beam.current_horz = 0; |
| 1634 | | m_beam.last_visible_line = 225; /* TODO: PAL setting */ |
| 1635 | | m_mode = 0; |
| 1636 | | m_ppu1_version = 1; // 5C77 chip version number, read by STAT77, only '1' is known |
| 1637 | | m_ppu2_version = 3; // 5C78 chip version number, read by STAT78, only '2' & '3' encountered so far. |
| 1638 | | |
| 1639 | | m_cgram_address = 0; |
| 1640 | | m_read_ophct = 0; |
| 1641 | | m_read_opvct = 0; |
| 1642 | | |
| 1643 | | PPU_REG(VMAIN) = 0x80; |
| 1644 | | // what about other regs? |
| 1645 | | |
| 1646 | | /* Inititialize mosaic table */ |
| 1647 | | for (int j = 0; j < 16; j++) |
| 1648 | | { |
| 1649 | | for (int i = 0; i < 4096; i++) |
| 1650 | | m_mosaic_table[j][i] = (i / (j + 1)) * (j + 1); |
| 1651 | | } |
| 1652 | | |
| 1653 | | /* Init VRAM */ |
| 1654 | | memset(m_vram, 0, SNES_VRAM_SIZE); |
| 1655 | | |
| 1656 | | /* Init Palette RAM */ |
| 1657 | | memset((UINT8 *)m_cgram, 0, SNES_CGRAM_SIZE); |
| 1658 | | |
| 1659 | | /* Init oam RAM */ |
| 1660 | | memset((UINT8 *)m_oam_ram, 0xff, SNES_OAM_SIZE); |
| 1661 | | |
| 1662 | | |
| 1663 | | for (int i = 0; i < 2; i++) |
| 1664 | | { |
| 1665 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_scanlines[i].enable); |
| 1666 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_scanlines[i].clip); |
| 1667 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_scanlines[i].buffer); |
| 1668 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_scanlines[i].priority); |
| 1669 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_scanlines[i].layer); |
| 1670 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_scanlines[i].blend_exception); |
| 1671 | | } |
| 1672 | | |
| 1673 | | for (int i = 0; i < 6; i++) |
| 1674 | | { |
| 1675 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].window1_enabled); |
| 1676 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].window1_invert); |
| 1677 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].window2_enabled); |
| 1678 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].window2_invert); |
| 1679 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].wlog_mask); |
| 1680 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].color_math); |
| 1681 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].charmap); |
| 1682 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].tilemap); |
| 1683 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].tilemap_size); |
| 1684 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].tile_size); |
| 1685 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].mosaic_enabled); |
| 1686 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].main_window_enabled); |
| 1687 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].sub_window_enabled); |
| 1688 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].main_bg_enabled); |
| 1689 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].sub_bg_enabled); |
| 1690 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].hoffs); |
| 1691 | | state_save_register_item(machine, "snes_ppu", NULL, i, m_layer[i].voffs); |
| 1692 | | |
| 1693 | | state_save_register_item_array(machine, "snes_ppu", NULL, i, m_clipmasks[i]); |
| 1694 | | } |
| 1695 | | |
| 1696 | | machine.save().save_item(NAME(m_oam.address_low)); |
| 1697 | | machine.save().save_item(NAME(m_oam.address_high)); |
| 1698 | | machine.save().save_item(NAME(m_oam.saved_address_low)); |
| 1699 | | machine.save().save_item(NAME(m_oam.saved_address_high)); |
| 1700 | | machine.save().save_item(NAME(m_oam.address)); |
| 1701 | | machine.save().save_item(NAME(m_oam.priority_rotation)); |
| 1702 | | machine.save().save_item(NAME(m_oam.next_charmap)); |
| 1703 | | machine.save().save_item(NAME(m_oam.next_size)); |
| 1704 | | machine.save().save_item(NAME(m_oam.size)); |
| 1705 | | machine.save().save_item(NAME(m_oam.next_name_select)); |
| 1706 | | machine.save().save_item(NAME(m_oam.name_select)); |
| 1707 | | machine.save().save_item(NAME(m_oam.first_sprite)); |
| 1708 | | machine.save().save_item(NAME(m_oam.flip)); |
| 1709 | | machine.save().save_item(NAME(m_oam.write_latch)); |
| 1710 | | |
| 1711 | | machine.save().save_item(NAME(m_beam.latch_horz)); |
| 1712 | | machine.save().save_item(NAME(m_beam.latch_vert)); |
| 1713 | | machine.save().save_item(NAME(m_beam.current_horz)); |
| 1714 | | machine.save().save_item(NAME(m_beam.current_vert)); |
| 1715 | | machine.save().save_item(NAME(m_beam.last_visible_line)); |
| 1716 | | machine.save().save_item(NAME(m_beam.interlace_count)); |
| 1717 | | |
| 1718 | | machine.save().save_item(NAME(m_mode7.repeat)); |
| 1719 | | machine.save().save_item(NAME(m_mode7.hflip)); |
| 1720 | | machine.save().save_item(NAME(m_mode7.vflip)); |
| 1721 | | machine.save().save_item(NAME(m_mode7.matrix_a)); |
| 1722 | | machine.save().save_item(NAME(m_mode7.matrix_b)); |
| 1723 | | machine.save().save_item(NAME(m_mode7.matrix_c)); |
| 1724 | | machine.save().save_item(NAME(m_mode7.matrix_d)); |
| 1725 | | machine.save().save_item(NAME(m_mode7.origin_x)); |
| 1726 | | machine.save().save_item(NAME(m_mode7.origin_y)); |
| 1727 | | machine.save().save_item(NAME(m_mode7.hor_offset)); |
| 1728 | | machine.save().save_item(NAME(m_mode7.ver_offset)); |
| 1729 | | machine.save().save_item(NAME(m_mode7.extbg)); |
| 1730 | | |
| 1731 | | machine.save().save_item(NAME(m_mosaic_size)); |
| 1732 | | machine.save().save_item(NAME(m_clip_to_black)); |
| 1733 | | machine.save().save_item(NAME(m_prevent_color_math)); |
| 1734 | | machine.save().save_item(NAME(m_sub_add_mode)); |
| 1735 | | machine.save().save_item(NAME(m_bg3_priority_bit)); |
| 1736 | | machine.save().save_item(NAME(m_direct_color)); |
| 1737 | | machine.save().save_item(NAME(m_ppu_last_scroll)); |
| 1738 | | machine.save().save_item(NAME(m_mode7_last_scroll)); |
| 1739 | | |
| 1740 | | machine.save().save_item(NAME(m_ppu1_open_bus)); |
| 1741 | | machine.save().save_item(NAME(m_ppu2_open_bus)); |
| 1742 | | machine.save().save_item(NAME(m_ppu1_version)); |
| 1743 | | machine.save().save_item(NAME(m_ppu2_version)); |
| 1744 | | machine.save().save_item(NAME(m_window1_left)); |
| 1745 | | machine.save().save_item(NAME(m_window1_right)); |
| 1746 | | machine.save().save_item(NAME(m_window2_left)); |
| 1747 | | machine.save().save_item(NAME(m_window2_right)); |
| 1748 | | |
| 1749 | | machine.save().save_item(NAME(m_update_windows)); |
| 1750 | | machine.save().save_item(NAME(m_update_offsets)); |
| 1751 | | machine.save().save_item(NAME(m_update_oam_list)); |
| 1752 | | machine.save().save_item(NAME(m_mode)); |
| 1753 | | machine.save().save_item(NAME(m_interlace)); |
| 1754 | | machine.save().save_item(NAME(m_obj_interlace)); |
| 1755 | | machine.save().save_item(NAME(m_screen_brightness)); |
| 1756 | | machine.save().save_item(NAME(m_screen_disabled)); |
| 1757 | | machine.save().save_item(NAME(m_pseudo_hires)); |
| 1758 | | machine.save().save_item(NAME(m_color_modes)); |
| 1759 | | machine.save().save_item(NAME(m_stat77)); |
| 1760 | | machine.save().save_item(NAME(m_stat78)); |
| 1761 | | |
| 1762 | | machine.save().save_item(NAME(m_htmult)); |
| 1763 | | machine.save().save_item(NAME(m_cgram_address)); |
| 1764 | | machine.save().save_item(NAME(m_read_ophct)); |
| 1765 | | machine.save().save_item(NAME(m_read_opvct)); |
| 1766 | | machine.save().save_item(NAME(m_vram_fgr_high)); |
| 1767 | | machine.save().save_item(NAME(m_vram_fgr_increment)); |
| 1768 | | machine.save().save_item(NAME(m_vram_fgr_count)); |
| 1769 | | machine.save().save_item(NAME(m_vram_fgr_mask)); |
| 1770 | | machine.save().save_item(NAME(m_vram_fgr_shift)); |
| 1771 | | machine.save().save_item(NAME(m_vram_read_buffer)); |
| 1772 | | machine.save().save_item(NAME(m_vmadd)); |
| 1773 | | |
| 1774 | | machine.save().save_item(NAME(m_regs)); |
| 1775 | | |
| 1776 | | machine.save().save_pointer(NAME(m_vram), SNES_VRAM_SIZE); |
| 1777 | | machine.save().save_pointer(NAME(m_cgram), SNES_CGRAM_SIZE/2); |
| 1778 | | machine.save().save_pointer(NAME(m_oam_ram), SNES_OAM_SIZE/2); |
| 1779 | | } |
| 1780 | | |
| 1781 | | |
| 1782 | | /* CPU <-> PPU comms */ |
| 1783 | | |
| 1784 | | // full graphic variables |
| 1785 | | static const UINT16 vram_fgr_inctab[4] = { 1, 32, 128, 128 }; |
| 1786 | | static const UINT16 vram_fgr_inccnts[4] = { 0, 32, 64, 128 }; |
| 1787 | | static const UINT16 vram_fgr_shiftab[4] = { 0, 5, 6, 7 }; |
| 1788 | | |
| 1789 | | // utility function - latches the H/V counters. Used by IRQ, writes to WRIO, etc. |
| 1790 | | void snes_ppu_class::latch_counters( running_machine &machine ) |
| 1791 | | { |
| 1792 | | m_beam.current_horz = machine.first_screen()->hpos() / m_htmult; |
| 1793 | | m_beam.latch_vert = machine.first_screen()->vpos(); |
| 1794 | | m_beam.latch_horz = m_beam.current_horz; |
| 1795 | | m_stat78 |= 0x40; // indicate we latched |
| 1796 | | // m_read_ophct = m_read_opvct = 0; // clear read flags - 2009-08: I think we must clear these when STAT78 is read... |
| 1797 | | |
| 1798 | | // printf("latched @ H %d V %d\n", m_beam.latch_horz, m_beam.latch_vert); |
| 1799 | | } |
| 1800 | | |
| 1801 | | void snes_ppu_class::dynamic_res_change( running_machine &machine ) |
| 1802 | | { |
| 1803 | | rectangle visarea = machine.first_screen()->visible_area(); |
| 1804 | | attoseconds_t refresh; |
| 1805 | | |
| 1806 | | visarea.min_x = visarea.min_y = 0; |
| 1807 | | visarea.max_y = m_beam.last_visible_line * m_interlace - 1; |
| 1808 | | visarea.max_x = (SNES_SCR_WIDTH * 2) - 1; |
| 1809 | | |
| 1810 | | // fixme: should compensate for SNES_DBG_VIDEO |
| 1811 | | if (m_mode == 5 || m_mode == 6 || m_pseudo_hires) |
| 1812 | | m_htmult = 2; |
| 1813 | | else |
| 1814 | | m_htmult = 1; |
| 1815 | | |
| 1816 | | /* FIXME: does the timing changes when the gfx mode is equal to 5 or 6? */ |
| 1817 | | if ((m_stat78 & 0x10) == SNES_NTSC) |
| 1818 | | { |
| 1819 | | refresh = HZ_TO_ATTOSECONDS(DOTCLK_NTSC) * SNES_HTOTAL * SNES_VTOTAL_NTSC; |
| 1820 | | machine.first_screen()->configure(SNES_HTOTAL * 2, SNES_VTOTAL_NTSC * m_interlace, visarea, refresh); |
| 1821 | | } |
| 1822 | | else |
| 1823 | | { |
| 1824 | | refresh = HZ_TO_ATTOSECONDS(DOTCLK_PAL) * SNES_HTOTAL * SNES_VTOTAL_PAL; |
| 1825 | | machine.first_screen()->configure(SNES_HTOTAL * 2, SNES_VTOTAL_PAL * m_interlace, visarea, refresh); |
| 1826 | | } |
| 1827 | | } |
| 1828 | | |
| 1829 | | /************************************************* |
| 1830 | | |
| 1831 | | SNES VRAM accesses: |
| 1832 | | |
| 1833 | | VRAM accesses during active display are invalid. |
| 1834 | | Unlike OAM and CGRAM, they will not be written |
| 1835 | | anywhere at all. Thanks to byuu's researches, |
| 1836 | | the ranges where writes are invalid have been |
| 1837 | | validated on hardware, as has the edge case where |
| 1838 | | the S-CPU open bus can be written if the write |
| 1839 | | occurs during the very last clock cycle of |
| 1840 | | vblank. |
| 1841 | | Our implementation could be not 100% accurate |
| 1842 | | when interlace is active. |
| 1843 | | *************************************************/ |
| 1844 | | |
| 1845 | | inline UINT32 snes_ppu_class::get_vram_address( running_machine &machine ) |
| 1846 | | { |
| 1847 | | UINT32 addr = m_vmadd; |
| 1848 | | |
| 1849 | | if (m_vram_fgr_count) |
| 1850 | | { |
| 1851 | | UINT32 rem = addr & m_vram_fgr_mask; |
| 1852 | | UINT32 faddr = (addr & ~m_vram_fgr_mask) + (rem >> m_vram_fgr_shift) + ((rem & (m_vram_fgr_count - 1)) << 3); |
| 1853 | | return faddr << 1; |
| 1854 | | } |
| 1855 | | |
| 1856 | | return addr << 1; |
| 1857 | | } |
| 1858 | | |
| 1859 | | READ8_MEMBER( snes_ppu_class::vram_read ) |
| 1860 | | { |
| 1861 | | UINT8 res = 0; |
| 1862 | | offset &= 0xffff; // only 64KB are present on SNES |
| 1863 | | |
| 1864 | | if (m_screen_disabled) |
| 1865 | | res = m_vram[offset]; |
| 1866 | | else |
| 1867 | | { |
| 1868 | | UINT16 v = m_screen->vpos(); |
| 1869 | | UINT16 h = m_screen->hpos(); |
| 1870 | | UINT16 ls = (((m_stat78 & 0x10) == SNES_NTSC ? 525 : 625) >> 1) - 1; |
| 1871 | | |
| 1872 | | if (m_interlace == 2) |
| 1873 | | ls++; |
| 1874 | | |
| 1875 | | if (v == ls && h == 1362) |
| 1876 | | res = 0; |
| 1877 | | else if (v < m_beam.last_visible_line - 1) |
| 1878 | | res = 0; |
| 1879 | | else if (v == m_beam.last_visible_line - 1) |
| 1880 | | { |
| 1881 | | if (h == 1362) |
| 1882 | | res = m_vram[offset]; |
| 1883 | | else |
| 1884 | | { |
| 1885 | | //printf("%d %d VRAM read, CHECK!\n",h,v); |
| 1886 | | res = 0; |
| 1887 | | } |
| 1888 | | } |
| 1889 | | else |
| 1890 | | res = m_vram[offset]; |
| 1891 | | } |
| 1892 | | return res; |
| 1893 | | } |
| 1894 | | |
| 1895 | | WRITE8_MEMBER( snes_ppu_class::vram_write ) |
| 1896 | | { |
| 1897 | | offset &= 0xffff; // only 64KB are present on SNES, Robocop 3 relies on this |
| 1898 | | |
| 1899 | | if (m_screen_disabled) |
| 1900 | | m_vram[offset] = data; |
| 1901 | | else |
| 1902 | | { |
| 1903 | | UINT16 v = m_screen->vpos(); |
| 1904 | | UINT16 h = m_screen->hpos(); |
| 1905 | | if (v == 0) |
| 1906 | | { |
| 1907 | | if (h <= 4) |
| 1908 | | m_vram[offset] = data; |
| 1909 | | else if (h == 6) |
| 1910 | | m_vram[offset] = m_state->snes_open_bus_r(space, 0); |
| 1911 | | else |
| 1912 | | { |
| 1913 | | //printf("%d %d VRAM write, CHECK!\n",h,v); |
| 1914 | | //no write |
| 1915 | | } |
| 1916 | | } |
| 1917 | | else if (v < m_beam.last_visible_line) |
| 1918 | | { |
| 1919 | | //printf("%d %d VRAM write, CHECK!\n",h,v); |
| 1920 | | //no write |
| 1921 | | } |
| 1922 | | else if (v == m_beam.last_visible_line) |
| 1923 | | { |
| 1924 | | if (h <= 4) |
| 1925 | | { |
| 1926 | | //printf("%d %d VRAM write, CHECK!\n",h,v); |
| 1927 | | //no write |
| 1928 | | } |
| 1929 | | else |
| 1930 | | m_vram[offset] = data; |
| 1931 | | } |
| 1932 | | else |
| 1933 | | m_vram[offset] = data; |
| 1934 | | } |
| 1935 | | } |
| 1936 | | |
| 1937 | | /************************************************* |
| 1938 | | |
| 1939 | | SNES OAM accesses: |
| 1940 | | |
| 1941 | | OAM accesses during active display are allowed. |
| 1942 | | The actual address varies during rendering, as the |
| 1943 | | PPU reads in data itself for processing. |
| 1944 | | Unfortunately, no one has been able (yet) to |
| 1945 | | determine how this works. The only known game to |
| 1946 | | actually access OAM during active display is |
| 1947 | | Uniracers and it expects accesses to map to |
| 1948 | | offset 0x0218. Hence, following byuu's choice |
| 1949 | | we rerouted OAM accesses during active display |
| 1950 | | to 0x0218 (0x010c in our snes_oam). |
| 1951 | | This is a hack, but it is more accurate than |
| 1952 | | writing to the 'expected' address set by |
| 1953 | | $2102,$2103. |
| 1954 | | |
| 1955 | | Notice that, since PPU_REG(OAMDATA) is never |
| 1956 | | read/written directly, we use it as an index |
| 1957 | | to choose the high/low byte of the snes_oam word. |
| 1958 | | *************************************************/ |
| 1959 | | |
| 1960 | | READ8_MEMBER( snes_ppu_class::oam_read ) |
| 1961 | | { |
| 1962 | | offset &= 0x1ff; |
| 1963 | | |
| 1964 | | if (offset & 0x100) |
| 1965 | | offset &= 0x10f; |
| 1966 | | |
| 1967 | | if (!m_screen_disabled) |
| 1968 | | { |
| 1969 | | UINT16 v = m_screen->vpos(); |
| 1970 | | |
| 1971 | | if (v < m_beam.last_visible_line) |
| 1972 | | offset = 0x010c; |
| 1973 | | } |
| 1974 | | |
| 1975 | | return (m_oam_ram[offset] >> (PPU_REG(OAMDATA) << 3)) & 0xff; |
| 1976 | | } |
| 1977 | | |
| 1978 | | WRITE8_MEMBER( snes_ppu_class::oam_write ) |
| 1979 | | { |
| 1980 | | offset &= 0x1ff; |
| 1981 | | |
| 1982 | | if (offset & 0x100) |
| 1983 | | offset &= 0x10f; |
| 1984 | | |
| 1985 | | if (!m_screen_disabled) |
| 1986 | | { |
| 1987 | | UINT16 v = m_screen->vpos(); |
| 1988 | | |
| 1989 | | if (v < m_beam.last_visible_line) |
| 1990 | | offset = 0x010c; |
| 1991 | | } |
| 1992 | | |
| 1993 | | if (!(PPU_REG(OAMDATA))) |
| 1994 | | m_oam_ram[offset] = (m_oam_ram[offset] & 0xff00) | (data << 0); |
| 1995 | | else |
| 1996 | | m_oam_ram[offset] = (m_oam_ram[offset] & 0x00ff) | (data << 8); |
| 1997 | | } |
| 1998 | | |
| 1999 | | /************************************************* |
| 2000 | | |
| 2001 | | SNES CGRAM accesses: |
| 2002 | | |
| 2003 | | CGRAM writes during hblank are valid. During |
| 2004 | | active display, the actual address the data |
| 2005 | | is written to varies, as the PPU itself changes |
| 2006 | | the address. Like OAM, it is not known the exact |
| 2007 | | algorithm used, but no commercial software seems |
| 2008 | | to attempt this. While byuu, in his emu, maps |
| 2009 | | those accesses to 0x01ff, because it is more |
| 2010 | | accurate to invalidate the 'expected' address |
| 2011 | | than not, MESS has issues if we don't write to |
| 2012 | | the expected address (see e.g. Tokimeki Memorial). |
| 2013 | | This is because writes should work during hblank |
| 2014 | | (so that the game can produce color fading), but |
| 2015 | | ends up not working with the conditions below. |
| 2016 | | Hence, for the moment, we only document the |
| 2017 | | solution adopted by BSNES without enabling it. |
| 2018 | | *************************************************/ |
| 2019 | | |
| 2020 | | READ8_MEMBER( snes_ppu_class::cgram_read ) |
| 2021 | | { |
| 2022 | | UINT8 res = 0; |
| 2023 | | offset &= 0x1ff; |
| 2024 | | |
| 2025 | | #if 0 |
| 2026 | | if (!m_screen_disabled) |
| 2027 | | { |
| 2028 | | UINT16 v = m_screen->vpos(); |
| 2029 | | UINT16 h = m_screen->hpos(); |
| 2030 | | |
| 2031 | | if (v < m_beam.last_visible_line && h >= 128 && h < 1096) |
| 2032 | | offset = 0x1ff; |
| 2033 | | } |
| 2034 | | #endif |
| 2035 | | |
| 2036 | | res = ((UINT8 *)m_cgram)[offset]; |
| 2037 | | |
| 2038 | | // CGRAM palette data format is 15-bits (0,bbbbb,ggggg,rrrrr). |
| 2039 | | // Highest bit is simply ignored. |
| 2040 | | if (offset & 0x01) |
| 2041 | | res &= 0x7f; |
| 2042 | | |
| 2043 | | return res; |
| 2044 | | } |
| 2045 | | |
| 2046 | | WRITE8_MEMBER( snes_ppu_class::cgram_write ) |
| 2047 | | { |
| 2048 | | offset &= 0x1ff; |
| 2049 | | |
| 2050 | | #if 0 |
| 2051 | | // FIXME: this currently breaks some games (e.g. Tokimeki Memorial), |
| 2052 | | // even if it's expected to be more accurate than allowing for |
| 2053 | | // writes to the cgram address |
| 2054 | | if (!m_screen_disabled) |
| 2055 | | { |
| 2056 | | UINT16 v = m_screen->vpos(); |
| 2057 | | UINT16 h = m_screen->hpos(); |
| 2058 | | |
| 2059 | | if (v < m_beam.last_visible_line && h >= 128 && h < 1096) |
| 2060 | | offset = 0x1ff; |
| 2061 | | } |
| 2062 | | #endif |
| 2063 | | |
| 2064 | | // CGRAM palette data format is 15-bits (0,bbbbb,ggggg,rrrrr). |
| 2065 | | // Highest bit is simply ignored. |
| 2066 | | if (offset & 0x01) |
| 2067 | | data &= 0x7f; |
| 2068 | | |
| 2069 | | ((UINT8 *)m_cgram)[offset] = data; |
| 2070 | | } |
| 2071 | | |
| 2072 | | UINT8 snes_ppu_class::read(address_space &space, UINT32 offset, UINT8 wrio_bit7) |
| 2073 | | { |
| 2074 | | UINT8 value; |
| 2075 | | |
| 2076 | | switch (offset) |
| 2077 | | { |
| 2078 | | case OAMDATA: /* 21xy for x=0,1,2 and y=4,5,6,8,9,a returns PPU1 open bus*/ |
| 2079 | | case BGMODE: |
| 2080 | | case MOSAIC: |
| 2081 | | case BG2SC: |
| 2082 | | case BG3SC: |
| 2083 | | case BG4SC: |
| 2084 | | case BG4VOFS: |
| 2085 | | case VMAIN: |
| 2086 | | case VMADDL: |
| 2087 | | case VMDATAL: |
| 2088 | | case VMDATAH: |
| 2089 | | case M7SEL: |
| 2090 | | case W34SEL: |
| 2091 | | case WOBJSEL: |
| 2092 | | case WH0: |
| 2093 | | case WH2: |
| 2094 | | case WH3: |
| 2095 | | case WBGLOG: |
| 2096 | | return m_ppu1_open_bus; |
| 2097 | | |
| 2098 | | case MPYL: /* Multiplication result (low) */ |
| 2099 | | { |
| 2100 | | /* Perform 16bit * 8bit multiply */ |
| 2101 | | UINT32 c = (INT16)m_mode7.matrix_a * (INT8)(m_mode7.matrix_b >> 8); |
| 2102 | | m_ppu1_open_bus = c & 0xff; |
| 2103 | | return m_ppu1_open_bus; |
| 2104 | | } |
| 2105 | | case MPYM: /* Multiplication result (mid) */ |
| 2106 | | { |
| 2107 | | /* Perform 16bit * 8bit multiply */ |
| 2108 | | UINT32 c = (INT16)m_mode7.matrix_a * (INT8)(m_mode7.matrix_b >> 8); |
| 2109 | | m_ppu1_open_bus = (c >> 8) & 0xff; |
| 2110 | | return m_ppu1_open_bus; |
| 2111 | | } |
| 2112 | | case MPYH: /* Multiplication result (high) */ |
| 2113 | | { |
| 2114 | | /* Perform 16bit * 8bit multiply */ |
| 2115 | | UINT32 c = (INT16)m_mode7.matrix_a * (INT8)(m_mode7.matrix_b >> 8); |
| 2116 | | m_ppu1_open_bus = (c >> 16) & 0xff; |
| 2117 | | return m_ppu1_open_bus; |
| 2118 | | } |
| 2119 | | case SLHV: /* Software latch for H/V counter */ |
| 2120 | | latch_counters(space.machine()); |
| 2121 | | return m_state->snes_open_bus_r(space, 0); /* Return value is meaningless */ |
| 2122 | | case ROAMDATA: /* Read data from OAM (DR) */ |
| 2123 | | m_ppu1_open_bus = oam_read(space, m_oam.address); |
| 2124 | | PPU_REG(OAMDATA) = (PPU_REG(OAMDATA) + 1) % 2; |
| 2125 | | if (!PPU_REG(OAMDATA)) |
| 2126 | | { |
| 2127 | | m_oam.address++; |
| 2128 | | m_oam.address &= 0x1ff; |
| 2129 | | m_oam.first_sprite = m_oam.priority_rotation ? (m_oam.address >> 1) & 127 : 0; |
| 2130 | | } |
| 2131 | | return m_ppu1_open_bus; |
| 2132 | | case RVMDATAL: /* Read data from VRAM (low) */ |
| 2133 | | { |
| 2134 | | UINT32 addr = get_vram_address(space.machine()); |
| 2135 | | m_ppu1_open_bus = m_vram_read_buffer & 0xff; |
| 2136 | | |
| 2137 | | if (!m_vram_fgr_high) |
| 2138 | | { |
| 2139 | | m_vram_read_buffer = vram_read(space, addr); |
| 2140 | | m_vram_read_buffer |= (vram_read(space, addr + 1) << 8); |
| 2141 | | |
| 2142 | | m_vmadd = (m_vmadd + m_vram_fgr_increment) & 0xffff; |
| 2143 | | } |
| 2144 | | |
| 2145 | | return m_ppu1_open_bus; |
| 2146 | | } |
| 2147 | | case RVMDATAH: /* Read data from VRAM (high) */ |
| 2148 | | { |
| 2149 | | UINT32 addr = get_vram_address(space.machine()); |
| 2150 | | m_ppu1_open_bus = (m_vram_read_buffer >> 8) & 0xff; |
| 2151 | | |
| 2152 | | if (m_vram_fgr_high) |
| 2153 | | { |
| 2154 | | m_vram_read_buffer = vram_read(space, addr); |
| 2155 | | m_vram_read_buffer |= (vram_read(space, addr + 1) << 8); |
| 2156 | | |
| 2157 | | m_vmadd = (m_vmadd + m_vram_fgr_increment) & 0xffff; |
| 2158 | | } |
| 2159 | | |
| 2160 | | return m_ppu1_open_bus; |
| 2161 | | } |
| 2162 | | case RCGDATA: /* Read data from CGRAM */ |
| 2163 | | if (!(m_cgram_address & 0x01)) |
| 2164 | | m_ppu2_open_bus = cgram_read(space, m_cgram_address); |
| 2165 | | else |
| 2166 | | { |
| 2167 | | m_ppu2_open_bus &= 0x80; |
| 2168 | | m_ppu2_open_bus |= cgram_read(space, m_cgram_address) & 0x7f; |
| 2169 | | } |
| 2170 | | |
| 2171 | | m_cgram_address = (m_cgram_address + 1) % (SNES_CGRAM_SIZE - 2); |
| 2172 | | return m_ppu2_open_bus; |
| 2173 | | case OPHCT: /* Horizontal counter data by ext/soft latch */ |
| 2174 | | if (m_read_ophct) |
| 2175 | | { |
| 2176 | | m_ppu2_open_bus &= 0xfe; |
| 2177 | | m_ppu2_open_bus |= (m_beam.latch_horz >> 8) & 0x01; |
| 2178 | | } |
| 2179 | | else |
| 2180 | | { |
| 2181 | | m_ppu2_open_bus = m_beam.latch_horz & 0xff; |
| 2182 | | } |
| 2183 | | m_read_ophct ^= 1; |
| 2184 | | return m_ppu2_open_bus; |
| 2185 | | case OPVCT: /* Vertical counter data by ext/soft latch */ |
| 2186 | | if (m_read_opvct) |
| 2187 | | { |
| 2188 | | m_ppu2_open_bus &= 0xfe; |
| 2189 | | m_ppu2_open_bus |= (m_beam.latch_vert >> 8) & 0x01; |
| 2190 | | } |
| 2191 | | else |
| 2192 | | { |
| 2193 | | m_ppu2_open_bus = m_beam.latch_vert & 0xff; |
| 2194 | | } |
| 2195 | | m_read_opvct ^= 1; |
| 2196 | | return m_ppu2_open_bus; |
| 2197 | | case STAT77: /* PPU status flag and version number */ |
| 2198 | | value = m_stat77 & 0xc0; // 0x80 & 0x40 are Time Over / Range Over Sprite flags, set by the video code |
| 2199 | | // 0x20 - Master/slave mode select. Little is known about this bit. We always seem to read back 0 here. |
| 2200 | | value |= (m_ppu1_open_bus & 0x10); |
| 2201 | | value |= (m_ppu1_version & 0x0f); |
| 2202 | | m_stat77 = value; // not sure if this is needed... |
| 2203 | | m_ppu1_open_bus = value; |
| 2204 | | return m_ppu1_open_bus; |
| 2205 | | case STAT78: /* PPU status flag and version number */ |
| 2206 | | m_read_ophct = 0; |
| 2207 | | m_read_opvct = 0; |
| 2208 | | if (wrio_bit7) |
| 2209 | | m_stat78 &= ~0x40; //clear ext latch if bit 7 of WRIO is set |
| 2210 | | m_stat78 = (m_stat78 & ~0x2f) | (m_ppu2_open_bus & 0x20) | (m_ppu2_version & 0x0f); |
| 2211 | | m_ppu2_open_bus = m_stat78; |
| 2212 | | return m_ppu2_open_bus; |
| 2213 | | } |
| 2214 | | |
| 2215 | | /* note: remaining registers (Namely TM in Super Kick Boxing) returns MDR open bus, not PPU Open Bus! */ |
| 2216 | | return m_state->snes_open_bus_r(space, 0); |
| 2217 | | } |
| 2218 | | |
| 2219 | | |
| 2220 | | void snes_ppu_class::write(address_space &space, UINT32 offset, UINT8 data) |
| 2221 | | { |
| 2222 | | switch (offset) |
| 2223 | | { |
| 2224 | | case INIDISP: /* Initial settings for screen */ |
| 2225 | | if ((m_screen_disabled & 0x80) && (!(data & 0x80))) //a 1->0 force blank transition causes a reset OAM address |
| 2226 | | { |
| 2227 | | space.write_byte(OAMADDL, m_oam.saved_address_low); |
| 2228 | | space.write_byte(OAMADDH, m_oam.saved_address_high); |
| 2229 | | m_oam.first_sprite = m_oam.priority_rotation ? (m_oam.address >> 1) & 127 : 0; |
| 2230 | | } |
| 2231 | | m_screen_disabled = data & 0x80; |
| 2232 | | m_screen_brightness = (data & 0x0f) + 1; |
| 2233 | | break; |
| 2234 | | case OBSEL: /* Object size and data area designation */ |
| 2235 | | m_oam.next_charmap = (data & 0x03) << 1; |
| 2236 | | m_oam.next_name_select = (((data & 0x18) >> 3) * 0x1000) << 1; |
| 2237 | | m_oam.next_size = (data & 0xe0) >> 5; |
| 2238 | | break; |
| 2239 | | case OAMADDL: /* Address for accessing OAM (low) */ |
| 2240 | | m_oam.saved_address_low = data; |
| 2241 | | m_oam.address = (m_oam.address & 0xff00) + data; |
| 2242 | | m_oam.first_sprite = m_oam.priority_rotation ? (m_oam.address >> 1) & 127 : 0; |
| 2243 | | PPU_REG(OAMDATA) = 0; |
| 2244 | | break; |
| 2245 | | case OAMADDH: /* Address for accessing OAM (high) */ |
| 2246 | | m_oam.saved_address_high = data; |
| 2247 | | m_oam.address = (m_oam.address & 0x00ff) | ((data & 0x01) << 8); |
| 2248 | | m_oam.priority_rotation = BIT(data, 7); |
| 2249 | | m_oam.first_sprite = m_oam.priority_rotation ? (m_oam.address >> 1) & 127 : 0; |
| 2250 | | PPU_REG(OAMDATA) = 0; |
| 2251 | | break; |
| 2252 | | case OAMDATA: /* Data for OAM write (DW) */ |
| 2253 | | if (m_oam.address >= 0x100) |
| 2254 | | oam_write(space, m_oam.address, data); |
| 2255 | | else |
| 2256 | | { |
| 2257 | | if (!PPU_REG(OAMDATA)) |
| 2258 | | m_oam.write_latch = data; |
| 2259 | | else |
| 2260 | | { |
| 2261 | | // in this case, we not only write data to the upper byte of the word, |
| 2262 | | // but also m_oam.write_latch to the lower byte (recall that |
| 2263 | | // PPU_REG(OAMDATA) is used to select high/low byte) |
| 2264 | | oam_write(space, m_oam.address, data); |
| 2265 | | PPU_REG(OAMDATA) = 0; |
| 2266 | | oam_write(space, m_oam.address, m_oam.write_latch); |
| 2267 | | PPU_REG(OAMDATA) = 1; |
| 2268 | | } |
| 2269 | | } |
| 2270 | | PPU_REG(OAMDATA) = (PPU_REG(OAMDATA) + 1) % 2; |
| 2271 | | if (!PPU_REG(OAMDATA)) |
| 2272 | | { |
| 2273 | | m_oam.address++; |
| 2274 | | m_oam.address &= 0x1ff; |
| 2275 | | m_oam.first_sprite = m_oam.priority_rotation ? (m_oam.address >> 1) & 127 : 0; |
| 2276 | | } |
| 2277 | | return; |
| 2278 | | case BGMODE: /* BG mode and character size settings */ |
| 2279 | | m_mode = data & 0x07; |
| 2280 | | dynamic_res_change(space.machine()); |
| 2281 | | m_bg3_priority_bit = BIT(data, 3); |
| 2282 | | m_layer[SNES_BG1].tile_size = BIT(data, 4); |
| 2283 | | m_layer[SNES_BG2].tile_size = BIT(data, 5); |
| 2284 | | m_layer[SNES_BG3].tile_size = BIT(data, 6); |
| 2285 | | m_layer[SNES_BG4].tile_size = BIT(data, 7); |
| 2286 | | m_update_offsets = 1; |
| 2287 | | break; |
| 2288 | | case MOSAIC: /* Size and screen designation for mosaic */ |
| 2289 | | m_mosaic_size = (data & 0xf0) >> 4; |
| 2290 | | m_layer[SNES_BG1].mosaic_enabled = BIT(data, 0); |
| 2291 | | m_layer[SNES_BG2].mosaic_enabled = BIT(data, 1); |
| 2292 | | m_layer[SNES_BG3].mosaic_enabled = BIT(data, 2); |
| 2293 | | m_layer[SNES_BG4].mosaic_enabled = BIT(data, 3); |
| 2294 | | break; |
| 2295 | | case BG1SC: /* Address for storing SC data BG1 SC size designation */ |
| 2296 | | case BG2SC: /* Address for storing SC data BG2 SC size designation */ |
| 2297 | | case BG3SC: /* Address for storing SC data BG3 SC size designation */ |
| 2298 | | case BG4SC: /* Address for storing SC data BG4 SC size designation */ |
| 2299 | | m_layer[offset - BG1SC].tilemap = data & 0xfc; |
| 2300 | | m_layer[offset - BG1SC].tilemap_size = data & 0x3; |
| 2301 | | break; |
| 2302 | | case BG12NBA: /* Address for BG 1 and 2 character data */ |
| 2303 | | m_layer[SNES_BG1].charmap = (data & 0x0f); |
| 2304 | | m_layer[SNES_BG2].charmap = (data & 0xf0) >> 4; |
| 2305 | | break; |
| 2306 | | case BG34NBA: /* Address for BG 3 and 4 character data */ |
| 2307 | | m_layer[SNES_BG3].charmap = (data & 0x0f); |
| 2308 | | m_layer[SNES_BG4].charmap = (data & 0xf0) >> 4; |
| 2309 | | break; |
| 2310 | | |
| 2311 | | // 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! |
| 2312 | | case BG1HOFS: /* BG1 - horizontal scroll (DW) */ |
| 2313 | | /* In Mode 0->6 we use ppu_last_scroll as Prev */ |
| 2314 | | m_layer[SNES_BG1].hoffs = (data << 8) | (m_ppu_last_scroll & ~7) | ((m_layer[SNES_BG1].hoffs >> 8) & 7); |
| 2315 | | m_ppu_last_scroll = data; |
| 2316 | | /* In Mode 7 we use mode7_last_scroll as Prev */ |
| 2317 | | m_mode7.hor_offset = (data << 8) | (m_mode7_last_scroll & ~7) | ((m_mode7.hor_offset >> 8) & 7); |
| 2318 | | m_mode7_last_scroll = data; |
| 2319 | | m_update_offsets = 1; |
| 2320 | | return; |
| 2321 | | case BG1VOFS: /* BG1 - vertical scroll (DW) */ |
| 2322 | | /* In Mode 0->6 we use ppu_last_scroll as Prev */ |
| 2323 | | m_layer[SNES_BG1].voffs = (data << 8) | m_ppu_last_scroll; |
| 2324 | | m_ppu_last_scroll = data; |
| 2325 | | /* In Mode 7 we use mode7_last_scroll as Prev */ |
| 2326 | | m_mode7.ver_offset = (data << 8) | m_mode7_last_scroll; |
| 2327 | | m_mode7_last_scroll = data; |
| 2328 | | m_update_offsets = 1; |
| 2329 | | return; |
| 2330 | | case BG2HOFS: /* BG2 - horizontal scroll (DW) */ |
| 2331 | | m_layer[SNES_BG2].hoffs = (data << 8) | (m_ppu_last_scroll & ~7) | ((m_layer[SNES_BG2].hoffs >> 8) & 7); |
| 2332 | | m_ppu_last_scroll = data; |
| 2333 | | m_update_offsets = 1; |
| 2334 | | return; |
| 2335 | | case BG2VOFS: /* BG2 - vertical scroll (DW) */ |
| 2336 | | m_layer[SNES_BG2].voffs = (data << 8) | (m_ppu_last_scroll); |
| 2337 | | m_ppu_last_scroll = data; |
| 2338 | | m_update_offsets = 1; |
| 2339 | | return; |
| 2340 | | case BG3HOFS: /* BG3 - horizontal scroll (DW) */ |
| 2341 | | m_layer[SNES_BG3].hoffs = (data << 8) | (m_ppu_last_scroll & ~7) | ((m_layer[SNES_BG3].hoffs >> 8) & 7); |
| 2342 | | m_ppu_last_scroll = data; |
| 2343 | | m_update_offsets = 1; |
| 2344 | | return; |
| 2345 | | case BG3VOFS: /* BG3 - vertical scroll (DW) */ |
| 2346 | | m_layer[SNES_BG3].voffs = (data << 8) | (m_ppu_last_scroll); |
| 2347 | | m_ppu_last_scroll = data; |
| 2348 | | m_update_offsets = 1; |
| 2349 | | return; |
| 2350 | | case BG4HOFS: /* BG4 - horizontal scroll (DW) */ |
| 2351 | | m_layer[SNES_BG4].hoffs = (data << 8) | (m_ppu_last_scroll & ~7) | ((m_layer[SNES_BG4].hoffs >> 8) & 7); |
| 2352 | | m_ppu_last_scroll = data; |
| 2353 | | m_update_offsets = 1; |
| 2354 | | return; |
| 2355 | | case BG4VOFS: /* BG4 - vertical scroll (DW) */ |
| 2356 | | m_layer[SNES_BG4].voffs = (data << 8) | (m_ppu_last_scroll); |
| 2357 | | m_ppu_last_scroll = data; |
| 2358 | | m_update_offsets = 1; |
| 2359 | | return; |
| 2360 | | case VMAIN: /* VRAM address increment value designation */ |
| 2361 | | m_vram_fgr_high = (data & 0x80); |
| 2362 | | m_vram_fgr_increment = vram_fgr_inctab[data & 3]; |
| 2363 | | |
| 2364 | | if (data & 0xc) |
| 2365 | | { |
| 2366 | | int md = (data & 0xc) >> 2; |
| 2367 | | |
| 2368 | | m_vram_fgr_count = vram_fgr_inccnts[md]; // 0x20, 0x40, 0x80 |
| 2369 | | m_vram_fgr_mask = (m_vram_fgr_count * 8) - 1; // 0xff, 0x1ff, 0x2ff |
| 2370 | | m_vram_fgr_shift = vram_fgr_shiftab[md]; // 5, 6, 7 |
| 2371 | | } |
| 2372 | | else |
| 2373 | | { |
| 2374 | | m_vram_fgr_count = 0; |
| 2375 | | } |
| 2376 | | // printf("VMAIN: high %x inc %x count %x mask %x shift %x\n", m_vram_fgr_high, m_vram_fgr_increment, m_vram_fgr_count, m_vram_fgr_mask, m_vram_fgr_shift); |
| 2377 | | break; |
| 2378 | | case VMADDL: /* Address for VRAM read/write (low) */ |
| 2379 | | { |
| 2380 | | UINT32 addr; |
| 2381 | | m_vmadd = (m_vmadd & 0xff00) | (data << 0); |
| 2382 | | addr = get_vram_address(space.machine()); |
| 2383 | | m_vram_read_buffer = vram_read(space, addr); |
| 2384 | | m_vram_read_buffer |= (vram_read(space, addr + 1) << 8); |
| 2385 | | } |
| 2386 | | break; |
| 2387 | | case VMADDH: /* Address for VRAM read/write (high) */ |
| 2388 | | { |
| 2389 | | UINT32 addr; |
| 2390 | | m_vmadd = (m_vmadd & 0x00ff) | (data << 8); |
| 2391 | | addr = get_vram_address(space.machine()); |
| 2392 | | m_vram_read_buffer = vram_read(space, addr); |
| 2393 | | m_vram_read_buffer |= (vram_read(space, addr + 1) << 8); |
| 2394 | | } |
| 2395 | | break; |
| 2396 | | case VMDATAL: /* 2118: Data for VRAM write (low) */ |
| 2397 | | { |
| 2398 | | UINT32 addr = get_vram_address(space.machine()); |
| 2399 | | vram_write(space, addr, data); |
| 2400 | | |
| 2401 | | if (!m_vram_fgr_high) |
| 2402 | | m_vmadd = (m_vmadd + m_vram_fgr_increment) & 0xffff; |
| 2403 | | } |
| 2404 | | return; |
| 2405 | | case VMDATAH: /* 2119: Data for VRAM write (high) */ |
| 2406 | | { |
| 2407 | | UINT32 addr = get_vram_address(space.machine()); |
| 2408 | | vram_write(space, addr + 1, data); |
| 2409 | | |
| 2410 | | if (m_vram_fgr_high) |
| 2411 | | m_vmadd = (m_vmadd + m_vram_fgr_increment) & 0xffff; |
| 2412 | | } |
| 2413 | | return; |
| 2414 | | case M7SEL: /* Mode 7 initial settings */ |
| 2415 | | m_mode7.repeat = (data >> 6) & 3; |
| 2416 | | m_mode7.vflip = BIT(data, 1); |
| 2417 | | m_mode7.hflip = BIT(data, 0); |
| 2418 | | break; |
| 2419 | | /* 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 */ |
| 2420 | | case M7A: /* Mode 7 COS angle/x expansion (DW) */ |
| 2421 | | m_mode7.matrix_a = m_mode7_last_scroll + (data << 8); |
| 2422 | | m_mode7_last_scroll = data; |
| 2423 | | break; |
| 2424 | | case M7B: /* Mode 7 SIN angle/ x expansion (DW) */ |
| 2425 | | m_mode7.matrix_b = m_mode7_last_scroll + (data << 8); |
| 2426 | | m_mode7_last_scroll = data; |
| 2427 | | break; |
| 2428 | | case M7C: /* Mode 7 SIN angle/y expansion (DW) */ |
| 2429 | | m_mode7.matrix_c = m_mode7_last_scroll + (data << 8); |
| 2430 | | m_mode7_last_scroll = data; |
| 2431 | | break; |
| 2432 | | case M7D: /* Mode 7 COS angle/y expansion (DW) */ |
| 2433 | | m_mode7.matrix_d = m_mode7_last_scroll + (data << 8); |
| 2434 | | m_mode7_last_scroll = data; |
| 2435 | | break; |
| 2436 | | case M7X: /* Mode 7 x center position (DW) */ |
| 2437 | | m_mode7.origin_x = m_mode7_last_scroll + (data << 8); |
| 2438 | | m_mode7_last_scroll = data; |
| 2439 | | break; |
| 2440 | | case M7Y: /* Mode 7 y center position (DW) */ |
| 2441 | | m_mode7.origin_y = m_mode7_last_scroll + (data << 8); |
| 2442 | | m_mode7_last_scroll = data; |
| 2443 | | break; |
| 2444 | | case CGADD: /* Initial address for colour RAM writing */ |
| 2445 | | /* CGRAM is 16-bit, but when reading/writing we treat it as 8-bit, so we need to double the address */ |
| 2446 | | m_cgram_address = data << 1; |
| 2447 | | break; |
| 2448 | | case CGDATA: /* Data for colour RAM */ |
| 2449 | | cgram_write(space, m_cgram_address, data); |
| 2450 | | m_cgram_address = (m_cgram_address + 1) % (SNES_CGRAM_SIZE - 2); |
| 2451 | | break; |
| 2452 | | case W12SEL: /* Window mask settings for BG1-2 */ |
| 2453 | | if (data != PPU_REG(W12SEL)) |
| 2454 | | { |
| 2455 | | m_layer[SNES_BG1].window1_invert = BIT(data, 0); |
| 2456 | | m_layer[SNES_BG1].window1_enabled = BIT(data, 1); |
| 2457 | | m_layer[SNES_BG1].window2_invert = BIT(data, 2); |
| 2458 | | m_layer[SNES_BG1].window2_enabled = BIT(data, 3); |
| 2459 | | m_layer[SNES_BG2].window1_invert = BIT(data, 4); |
| 2460 | | m_layer[SNES_BG2].window1_enabled = BIT(data, 5); |
| 2461 | | m_layer[SNES_BG2].window2_invert = BIT(data, 6); |
| 2462 | | m_layer[SNES_BG2].window2_enabled = BIT(data, 7); |
| 2463 | | m_update_windows = 1; |
| 2464 | | } |
| 2465 | | break; |
| 2466 | | case W34SEL: /* Window mask settings for BG3-4 */ |
| 2467 | | if (data != PPU_REG(W34SEL)) |
| 2468 | | { |
| 2469 | | m_layer[SNES_BG3].window1_invert = BIT(data, 0); |
| 2470 | | m_layer[SNES_BG3].window1_enabled = BIT(data, 1); |
| 2471 | | m_layer[SNES_BG3].window2_invert = BIT(data, 2); |
| 2472 | | m_layer[SNES_BG3].window2_enabled = BIT(data, 3); |
| 2473 | | m_layer[SNES_BG4].window1_invert = BIT(data, 4); |
| 2474 | | m_layer[SNES_BG4].window1_enabled = BIT(data, 5); |
| 2475 | | m_layer[SNES_BG4].window2_invert = BIT(data, 6); |
| 2476 | | m_layer[SNES_BG4].window2_enabled = BIT(data, 7); |
| 2477 | | m_update_windows = 1; |
| 2478 | | } |
| 2479 | | break; |
| 2480 | | case WOBJSEL: /* Window mask settings for objects */ |
| 2481 | | if (data != PPU_REG(WOBJSEL)) |
| 2482 | | { |
| 2483 | | m_layer[SNES_OAM].window1_invert = BIT(data, 0); |
| 2484 | | m_layer[SNES_OAM].window1_enabled = BIT(data, 1); |
| 2485 | | m_layer[SNES_OAM].window2_invert = BIT(data, 2); |
| 2486 | | m_layer[SNES_OAM].window2_enabled = BIT(data, 3); |
| 2487 | | m_layer[SNES_COLOR].window1_invert = BIT(data, 4); |
| 2488 | | m_layer[SNES_COLOR].window1_enabled = BIT(data, 5); |
| 2489 | | m_layer[SNES_COLOR].window2_invert = BIT(data, 6); |
| 2490 | | m_layer[SNES_COLOR].window2_enabled = BIT(data, 7); |
| 2491 | | m_update_windows = 1; |
| 2492 | | } |
| 2493 | | break; |
| 2494 | | case WH0: /* Window 1 left position */ |
| 2495 | | if (data != PPU_REG(WH0)) |
| 2496 | | { |
| 2497 | | m_window1_left = data; |
| 2498 | | m_update_windows = 1; |
| 2499 | | } |
| 2500 | | break; |
| 2501 | | case WH1: /* Window 1 right position */ |
| 2502 | | if (data != PPU_REG(WH1)) |
| 2503 | | { |
| 2504 | | m_window1_right = data; |
| 2505 | | m_update_windows = 1; |
| 2506 | | } |
| 2507 | | break; |
| 2508 | | case WH2: /* Window 2 left position */ |
| 2509 | | if (data != PPU_REG(WH2)) |
| 2510 | | { |
| 2511 | | m_window2_left = data; |
| 2512 | | m_update_windows = 1; |
| 2513 | | } |
| 2514 | | break; |
| 2515 | | case WH3: /* Window 2 right position */ |
| 2516 | | if (data != PPU_REG(WH3)) |
| 2517 | | { |
| 2518 | | m_window2_right = data; |
| 2519 | | m_update_windows = 1; |
| 2520 | | } |
| 2521 | | break; |
| 2522 | | case WBGLOG: /* Window mask logic for BG's */ |
| 2523 | | if (data != PPU_REG(WBGLOG)) |
| 2524 | | { |
| 2525 | | m_layer[SNES_BG1].wlog_mask = data & 0x03; |
| 2526 | | m_layer[SNES_BG2].wlog_mask = (data & 0x0c) >> 2; |
| 2527 | | m_layer[SNES_BG3].wlog_mask = (data & 0x30) >> 4; |
| 2528 | | m_layer[SNES_BG4].wlog_mask = (data & 0xc0) >> 6; |
| 2529 | | m_update_windows = 1; |
| 2530 | | } |
| 2531 | | break; |
| 2532 | | case WOBJLOG: /* Window mask logic for objects */ |
| 2533 | | if (data != PPU_REG(WOBJLOG)) |
| 2534 | | { |
| 2535 | | m_layer[SNES_OAM].wlog_mask = data & 0x03; |
| 2536 | | m_layer[SNES_COLOR].wlog_mask = (data & 0x0c) >> 2; |
| 2537 | | m_update_windows = 1; |
| 2538 | | } |
| 2539 | | break; |
| 2540 | | case TM: /* Main screen designation */ |
| 2541 | | m_layer[SNES_BG1].main_bg_enabled = BIT(data, 0); |
| 2542 | | m_layer[SNES_BG2].main_bg_enabled = BIT(data, 1); |
| 2543 | | m_layer[SNES_BG3].main_bg_enabled = BIT(data, 2); |
| 2544 | | m_layer[SNES_BG4].main_bg_enabled = BIT(data, 3); |
| 2545 | | m_layer[SNES_OAM].main_bg_enabled = BIT(data, 4); |
| 2546 | | break; |
| 2547 | | case TS: /* Subscreen designation */ |
| 2548 | | m_layer[SNES_BG1].sub_bg_enabled = BIT(data, 0); |
| 2549 | | m_layer[SNES_BG2].sub_bg_enabled = BIT(data, 1); |
| 2550 | | m_layer[SNES_BG3].sub_bg_enabled = BIT(data, 2); |
| 2551 | | m_layer[SNES_BG4].sub_bg_enabled = BIT(data, 3); |
| 2552 | | m_layer[SNES_OAM].sub_bg_enabled = BIT(data, 4); |
| 2553 | | break; |
| 2554 | | case TMW: /* Window mask for main screen designation */ |
| 2555 | | m_layer[SNES_BG1].main_window_enabled = BIT(data, 0); |
| 2556 | | m_layer[SNES_BG2].main_window_enabled = BIT(data, 1); |
| 2557 | | m_layer[SNES_BG3].main_window_enabled = BIT(data, 2); |
| 2558 | | m_layer[SNES_BG4].main_window_enabled = BIT(data, 3); |
| 2559 | | m_layer[SNES_OAM].main_window_enabled = BIT(data, 4); |
| 2560 | | break; |
| 2561 | | case TSW: /* Window mask for subscreen designation */ |
| 2562 | | m_layer[SNES_BG1].sub_window_enabled = BIT(data, 0); |
| 2563 | | m_layer[SNES_BG2].sub_window_enabled = BIT(data, 1); |
| 2564 | | m_layer[SNES_BG3].sub_window_enabled = BIT(data, 2); |
| 2565 | | m_layer[SNES_BG4].sub_window_enabled = BIT(data, 3); |
| 2566 | | m_layer[SNES_OAM].sub_window_enabled = BIT(data, 4); |
| 2567 | | break; |
| 2568 | | case CGWSEL: /* Initial settings for Fixed colour addition or screen addition */ |
| 2569 | | m_clip_to_black = (data >> 6) & 0x03; |
| 2570 | | m_prevent_color_math = (data >> 4) & 0x03; |
| 2571 | | m_sub_add_mode = BIT(data, 1); |
| 2572 | | m_direct_color = BIT(data, 0); |
| 2573 | | #ifdef SNES_DBG_REG_W |
| 2574 | | if ((data & 0x2) != (PPU_REG(CGWSEL) & 0x2)) |
| 2575 | | mame_printf_debug("Add/Sub Layer: %s\n", ((data & 0x2) >> 1) ? "Subscreen" : "Fixed colour"); |
| 2576 | | #endif |
| 2577 | | break; |
| 2578 | | case CGADSUB: /* Addition/Subtraction designation for each screen */ |
| 2579 | | m_color_modes = data & 0xc0; |
| 2580 | | m_layer[SNES_BG1].color_math = BIT(data, 0); |
| 2581 | | m_layer[SNES_BG2].color_math = BIT(data, 1); |
| 2582 | | m_layer[SNES_BG3].color_math = BIT(data, 2); |
| 2583 | | m_layer[SNES_BG4].color_math = BIT(data, 3); |
| 2584 | | m_layer[SNES_OAM].color_math = BIT(data, 4); |
| 2585 | | m_layer[SNES_COLOR].color_math = BIT(data, 5); |
| 2586 | | break; |
| 2587 | | case COLDATA: /* Fixed colour data for fixed colour addition/subtraction */ |
| 2588 | | { |
| 2589 | | /* Store it in the extra space we made in the CGRAM. It doesn't really go there, but it's as good a place as any. */ |
| 2590 | | UINT8 r, g, b; |
| 2591 | | |
| 2592 | | /* Get existing value. */ |
| 2593 | | r = m_cgram[FIXED_COLOUR] & 0x1f; |
| 2594 | | g = (m_cgram[FIXED_COLOUR] & 0x3e0) >> 5; |
| 2595 | | b = (m_cgram[FIXED_COLOUR] & 0x7c00) >> 10; |
| 2596 | | /* Set new value */ |
| 2597 | | if (data & 0x20) |
| 2598 | | r = data & 0x1f; |
| 2599 | | if (data & 0x40) |
| 2600 | | g = data & 0x1f; |
| 2601 | | if (data & 0x80) |
| 2602 | | b = data & 0x1f; |
| 2603 | | m_cgram[FIXED_COLOUR] = (r | (g << 5) | (b << 10)); |
| 2604 | | } break; |
| 2605 | | case SETINI: /* Screen mode/video select */ |
| 2606 | | m_interlace = (data & 0x01) ? 2 : 1; |
| 2607 | | m_obj_interlace = (data & 0x02) ? 2 : 1; |
| 2608 | | m_beam.last_visible_line = (data & 0x04) ? 240 : 225; |
| 2609 | | m_pseudo_hires = BIT(data, 3); |
| 2610 | | m_mode7.extbg = BIT(data, 6); |
| 2611 | | dynamic_res_change(space.machine()); |
| 2612 | | #ifdef SNES_DBG_REG_W |
| 2613 | | if ((data & 0x8) != (PPU_REG(SETINI) & 0x8)) |
| 2614 | | mame_printf_debug("Pseudo 512 mode: %s\n", (data & 0x8) ? "on" : "off"); |
| 2615 | | #endif |
| 2616 | | break; |
| 2617 | | } |
| 2618 | | |
| 2619 | | PPU_REG(offset) = data; |
| 2620 | | } |
| 2621 | | |
| 2622 | | /***** Debug Functions *****/ |
| 2623 | | |
| 2624 | | #if SNES_LAYER_DEBUG |
| 2625 | | |
| 2626 | | #define DEBUG_TOGGLE(bit, debug_settings, MSG1, MSG2) \ |
| 2627 | | if (BIT(toggles, bit) && !debug_settings) \ |
| 2628 | | { \ |
| 2629 | | debug_settings = 1; \ |
| 2630 | | popmessage MSG1; \ |
| 2631 | | } \ |
| 2632 | | else if (!BIT(toggles, bit) && debug_settings) \ |
| 2633 | | { \ |
| 2634 | | debug_settings = 0; \ |
| 2635 | | popmessage MSG2; \ |
| 2636 | | } |
| 2637 | | |
| 2638 | | UINT8 snes_ppu_class::dbg_video( running_machine &machine, UINT16 curline ) |
| 2639 | | { |
| 2640 | | int i; |
| 2641 | | UINT8 toggles = machine.root_device().ioport("DEBUG1")->read_safe(0); |
| 2642 | | m_debug_options.select_pri[SNES_BG1] = (toggles & 0x03); |
| 2643 | | m_debug_options.select_pri[SNES_BG2] = (toggles & 0x0c) >> 2; |
| 2644 | | m_debug_options.select_pri[SNES_BG3] = (toggles & 0x30) >> 4; |
| 2645 | | m_debug_options.select_pri[SNES_BG4] = (toggles & 0xc0) >> 6; |
| 2646 | | |
| 2647 | | toggles = machine.root_device().ioport("DEBUG2")->read_safe(0); |
| 2648 | | for (i = 0; i < 4; i++) |
| 2649 | | DEBUG_TOGGLE(i, m_debug_options.bg_disabled[i], ("Debug: Disabled BG%d.\n", i + 1), ("Debug: Enabled BG%d.\n", i + 1)) |
| 2650 | | DEBUG_TOGGLE(4, m_debug_options.bg_disabled[SNES_OAM], ("Debug: Disabled OAM.\n"), ("Debug: Enabled OAM.\n")) |
| 2651 | | DEBUG_TOGGLE(5, m_debug_options.draw_subscreen, ("Debug: Switched screens.\n"), ("Debug: Switched screens.\n")) |
| 2652 | | DEBUG_TOGGLE(6, m_debug_options.colormath_disabled, ("Debug: Disabled Color Math.\n"), ("Debug: Enabled Color Math.\n")) |
| 2653 | | DEBUG_TOGGLE(7, m_debug_options.windows_disabled, ("Debug: Disabled Window Masks.\n"), ("Debug: Enabled Window Masks.\n")) |
| 2654 | | |
| 2655 | | toggles = machine.root_device().ioport("DEBUG4")->read_safe(0); |
| 2656 | | for (i = 0; i < 8; i++) |
| 2657 | | DEBUG_TOGGLE(i, m_debug_options.mode_disabled[i], ("Debug: Disabled Mode %d drawing.\n", i), ("Debug: Enabled Mode %d drawing.\n", i)) |
| 2658 | | |
| 2659 | | toggles = machine.root_device().ioport("DEBUG3")->read_safe(0); |
| 2660 | | DEBUG_TOGGLE(2, m_debug_options.mosaic_disabled, ("Debug: Disabled Mosaic.\n"), ("Debug: Enabled Mosaic.\n")) |
| 2661 | | m_debug_options.sprite_reversed = BIT(toggles, 7); |
| 2662 | | m_debug_options.select_pri[SNES_OAM] = (toggles & 0x70) >> 4; |
| 2663 | | |
| 2664 | | #ifdef MAME_DEBUG |
| 2665 | | /* Once per frame, log video properties */ |
| 2666 | | if (curline == 1) |
| 2667 | | { |
| 2668 | | static const char WINLOGIC[4] = { '|', '&', '^', '!' }; |
| 2669 | | |
| 2670 | | logerror("%s", m_debug_options.windows_disabled?" ":"W"); |
| 2671 | | logerror("%s1 %s%s%s%s%s%c%s%s%d%s %d %4X %4X", |
| 2672 | | m_debug_options.bg_disabled[0]?" ":"*", |
| 2673 | | (PPU_REG(TM) & 0x1)?"M":" ", |
| 2674 | | (PPU_REG(TS) & 0x1)?"S":" ", |
| 2675 | | (PPU_REG(CGADSUB) & 0x1)?"B":" ", |
| 2676 | | (PPU_REG(TMW) & 0x1)?"m":" ", |
| 2677 | | (PPU_REG(TSW) & 0x1)?"s":" ", |
| 2678 | | WINLOGIC[(PPU_REG(WBGLOG) & 0x3)], |
| 2679 | | (PPU_REG(W12SEL) & 0x2)?((PPU_REG(W12SEL) & 0x1)?"o":"i"):" ", |
| 2680 | | (PPU_REG(W12SEL) & 0x8)?((PPU_REG(W12SEL) & 0x4)?"o":"i"):" ", |
| 2681 | | m_layer[SNES_BG1].tile_size + 1, |
| 2682 | | (PPU_REG(MOSAIC) & 0x1)?"m":" ", |
| 2683 | | PPU_REG(BG1SC) & 0x3, |
| 2684 | | (PPU_REG(BG1SC) & 0xfc) << 9, |
| 2685 | | m_layer[SNES_BG1].charmap << 13); |
| 2686 | | logerror("%s2 %s%s%s%s%s%c%s%s%d%s %d %4X %4X", |
| 2687 | | m_debug_options.bg_disabled[1]?" ":"*", |
| 2688 | | (PPU_REG(TM) & 0x2)?"M":" ", |
| 2689 | | (PPU_REG(TS) & 0x2)?"S":" ", |
| 2690 | | (PPU_REG(CGADSUB) & 0x2)?"B":" ", |
| 2691 | | (PPU_REG(TMW) & 0x2)?"m":" ", |
| 2692 | | (PPU_REG(TSW) & 0x2)?"s":" ", |
| 2693 | | WINLOGIC[(PPU_REG(WBGLOG) & 0xc) >> 2], |
| 2694 | | (PPU_REG(W12SEL) & 0x20)?((PPU_REG(W12SEL) & 0x10)?"o":"i"):" ", |
| 2695 | | (PPU_REG(W12SEL) & 0x80)?((PPU_REG(W12SEL) & 0x40)?"o":"i"):" ", |
| 2696 | | m_layer[SNES_BG2].tile_size + 1, |
| 2697 | | (PPU_REG(MOSAIC) & 0x2)?"m":" ", |
| 2698 | | PPU_REG(BG2SC) & 0x3, |
| 2699 | | (PPU_REG(BG2SC) & 0xfc) << 9, |
| 2700 | | m_layer[SNES_BG2].charmap << 13); |
| 2701 | | logerror("%s3 %s%s%s%s%s%c%s%s%d%s%s%d %4X %4X", |
| 2702 | | m_debug_options.bg_disabled[2]?" ":"*", |
| 2703 | | (PPU_REG(TM) & 0x4)?"M":" ", |
| 2704 | | (PPU_REG(TS) & 0x4)?"S":" ", |
| 2705 | | (PPU_REG(CGADSUB) & 0x4)?"B":" ", |
| 2706 | | (PPU_REG(TMW) & 0x4)?"m":" ", |
| 2707 | | (PPU_REG(TSW) & 0x4)?"s":" ", |
| 2708 | | WINLOGIC[(PPU_REG(WBGLOG) & 0x30)>>4], |
| 2709 | | (PPU_REG(W34SEL) & 0x2)?((PPU_REG(W34SEL) & 0x1)?"o":"i"):" ", |
| 2710 | | (PPU_REG(W34SEL) & 0x8)?((PPU_REG(W34SEL) & 0x4)?"o":"i"):" ", |
| 2711 | | m_layer[SNES_BG3].tile_size + 1, |
| 2712 | | (PPU_REG(MOSAIC) & 0x4)?"m":" ", |
| 2713 | | (PPU_REG(BGMODE) & 0x8)?"P":" ", |
| 2714 | | PPU_REG(BG3SC) & 0x3, |
| 2715 | | (PPU_REG(BG3SC) & 0xfc) << 9, |
| 2716 | | m_layer[SNES_BG3].charmap << 13); |
| 2717 | | logerror("%s4 %s%s%s%s%s%c%s%s%d%s %d %4X %4X", |
| 2718 | | m_debug_options.bg_disabled[3]?" ":"*", |
| 2719 | | (PPU_REG(TM) & 0x8)?"M":" ", |
| 2720 | | (PPU_REG(TS) & 0x8)?"S":" ", |
| 2721 | | (PPU_REG(CGADSUB) & 0x8)?"B":" ", |
| 2722 | | (PPU_REG(TMW) & 0x8)?"m":" ", |
| 2723 | | (PPU_REG(TSW) & 0x8)?"s":" ", |
| 2724 | | WINLOGIC[(PPU_REG(WBGLOG) & 0xc0)>>6], |
| 2725 | | (PPU_REG(W34SEL) & 0x20)?((PPU_REG(W34SEL) & 0x10)?"o":"i"):" ", |
| 2726 | | (PPU_REG(W34SEL) & 0x80)?((PPU_REG(W34SEL) & 0x40)?"o":"i"):" ", |
| 2727 | | m_layer[SNES_BG4].tile_size + 1, |
| 2728 | | (PPU_REG(MOSAIC) & 0x8)?"m":" ", |
| 2729 | | PPU_REG(BG4SC) & 0x3, |
| 2730 | | (PPU_REG(BG4SC) & 0xfc) << 9, |
| 2731 | | m_layer[SNES_BG4].charmap << 13 ); |
| 2732 | | logerror("%sO %s%s%s%s%s%c%s%s %4X", |
| 2733 | | m_debug_options.bg_disabled[4]?" ":"*", |
| 2734 | | (PPU_REG(TM) & 0x10)?"M":" ", |
| 2735 | | (PPU_REG(TS) & 0x10)?"S":" ", |
| 2736 | | (PPU_REG(CGADSUB) & 0x10)?"B":" ", |
| 2737 | | (PPU_REG(TMW) & 0x10)?"m":" ", |
| 2738 | | (PPU_REG(TSW) & 0x10)?"s":" ", |
| 2739 | | WINLOGIC[(PPU_REG(WOBJLOG) & 0x3)], |
| 2740 | | (PPU_REG(WOBJSEL) & 0x2)?((PPU_REG(WOBJSEL) & 0x1)?"o":"i"):" ", |
| 2741 | | (PPU_REG(WOBJSEL) & 0x8)?((PPU_REG(WOBJSEL) & 0x4)?"o":"i"):" ", |
| 2742 | | m_layer[SNES_OAM].charmap << 13 ); |
| 2743 | | logerror("%sB %s %c%s%s", |
| 2744 | | m_debug_options.colormath_disabled?" ":"*", |
| 2745 | | (PPU_REG(CGADSUB) & 0x20)?"B":" ", |
| 2746 | | WINLOGIC[(PPU_REG(WOBJLOG) & 0xc)>>2], |
| 2747 | | (PPU_REG(WOBJSEL) & 0x20)?((PPU_REG(WOBJSEL) & 0x10)?"o":"i"):" ", |
| 2748 | | (PPU_REG(WOBJSEL) & 0x80)?((PPU_REG(WOBJSEL) & 0x40)?"o":"i"):" " ); |
| 2749 | | logerror("Flags: %s%s%s %s %2d", (PPU_REG(CGWSEL) & 0x2)?"S":"F", (PPU_REG(CGADSUB) & 0x80)?"-":"+", (PPU_REG(CGADSUB) & 0x40)?" 50%":"100%",(PPU_REG(CGWSEL) & 0x1)?"D":"P", (PPU_REG(MOSAIC) & 0xf0) >> 4 ); |
| 2750 | | logerror("SetINI: %s %s %s %s %s %s", (PPU_REG(SETINI) & 0x1)?" I":"NI", (PPU_REG(SETINI) & 0x2)?"P":"R", (PPU_REG(SETINI) & 0x4)?"240":"225",(PPU_REG(SETINI) & 0x8)?"512":"256",(PPU_REG(SETINI) & 0x40)?"E":"N",(PPU_REG(SETINI) & 0x80)?"ES":"NS" ); |
| 2751 | | logerror("Mode7: A %5d B %5d", m_mode7.matrix_a, m_mode7.matrix_b ); |
| 2752 | | logerror(" %s%s%s C %5d D %5d", (PPU_REG(M7SEL) & 0xc0)?((PPU_REG(M7SEL) & 0x40)?"0":"C"):"R", (PPU_REG(M7SEL) & 0x1)?"H":" ", (PPU_REG(M7SEL) & 0x2)?"V":" ", m_mode7.matrix_c, m_mode7.matrix_d ); |
| 2753 | | logerror(" X %5d Y %5d", m_mode7.origin_x, m_mode7.origin_y ); |
| 2754 | | } |
| 2755 | | #endif |
| 2756 | | |
| 2757 | | return 0; |
| 2758 | | } |
| 2759 | | #endif /* SNES_LAYER_DEBUG */ |
branches/new_menus/src/mame/drivers/namcona1.c
| r29543 | r29544 | |
| 300 | 300 | |
| 301 | 301 | if( source>=0x400000 && source<0xc00000 ) |
| 302 | 302 | { |
| 303 | | data = m_mpBank1[(source-0x400000)/2]; |
| 303 | data = m_maskrom[(source-0x400000)/2]; |
| 304 | 304 | } |
| 305 | 305 | else if( source>=0xc00000 && source<0xe00000 ) |
| 306 | 306 | { |
| 307 | | data = m_mpBank0[(source-0xc00000)/2]; |
| 307 | data = m_prgrom[(source-0xc00000)/2]; |
| 308 | 308 | } |
| 309 | 309 | else if( source<0x80000 && source>=0x1000 ) |
| 310 | 310 | { |
| r29543 | r29544 | |
| 540 | 540 | static ADDRESS_MAP_START( namcona1_main_map, AS_PROGRAM, 16, namcona1_state ) |
| 541 | 541 | AM_RANGE(0x000000, 0x07ffff) AM_RAM AM_SHARE("workram") |
| 542 | 542 | AM_RANGE(0x3f8000, 0x3fffff) AM_READWRITE(mcu_mailbox_r, mcu_mailbox_w_68k) |
| 543 | | AM_RANGE(0x400000, 0xbfffff) AM_ROM AM_REGION("maincpu", 0x280000) /* data */ |
| 544 | | AM_RANGE(0xc00000, 0xdfffff) AM_ROM AM_REGION("maincpu", 0x080000) /* code */ |
| 543 | AM_RANGE(0x400000, 0xbfffff) AM_ROM AM_REGION("maskrom", 0) // data |
| 544 | AM_RANGE(0xc00000, 0xdfffff) AM_ROM AM_REGION("maincpu", 0) // code |
| 545 | 545 | AM_RANGE(0xe00000, 0xe00fff) AM_DEVREADWRITE8("eeprom", eeprom_parallel_28xx_device, read, write, 0x00ff) |
| 546 | 546 | AM_RANGE(0xe40000, 0xe4000f) AM_READWRITE(custom_key_r, custom_key_w) |
| 547 | 547 | AM_RANGE(0xefff00, 0xefffff) AM_RAM_WRITE(namcona1_vreg_w) AM_SHARE("vreg") |
| r29543 | r29544 | |
| 555 | 555 | |
| 556 | 556 | |
| 557 | 557 | static ADDRESS_MAP_START( namcona2_main_map, AS_PROGRAM, 16, namcona1_state ) |
| 558 | | AM_RANGE(0x000000, 0x07ffff) AM_RAM AM_SHARE("workram") |
| 559 | | AM_RANGE(0x3f8000, 0x3fffff) AM_READWRITE(mcu_mailbox_r, mcu_mailbox_w_68k) |
| 560 | | AM_RANGE(0x400000, 0xbfffff) AM_ROM AM_REGION("maincpu", 0x280000) /* data */ |
| 558 | AM_IMPORT_FROM(namcona1_main_map) |
| 561 | 559 | AM_RANGE(0xd00000, 0xd00001) AM_WRITENOP /* xday: serial out? */ |
| 562 | 560 | AM_RANGE(0xd40000, 0xd40001) AM_WRITENOP /* xday: serial out? */ |
| 563 | 561 | AM_RANGE(0xd80000, 0xd80001) AM_WRITENOP /* xday: serial out? */ |
| 564 | 562 | AM_RANGE(0xdc0000, 0xdc001f) AM_WRITENOP /* xday: serial config? */ |
| 565 | | AM_RANGE(0xc00000, 0xdfffff) AM_ROM AM_REGION("maincpu", 0x080000) /* code */ |
| 566 | | AM_RANGE(0xe00000, 0xe00fff) AM_DEVREADWRITE8("eeprom", eeprom_parallel_28xx_device, read, write, 0x00ff) |
| 567 | 563 | /* xday: additional battery-backed ram at 00E024FA? */ |
| 568 | | AM_RANGE(0xe40000, 0xe4000f) AM_READWRITE(custom_key_r, custom_key_w) |
| 569 | | AM_RANGE(0xefff00, 0xefffff) AM_RAM_WRITE(namcona1_vreg_w) AM_SHARE("vreg") |
| 570 | | AM_RANGE(0xf00000, 0xf01fff) AM_RAM_WRITE(namcona1_paletteram_w) AM_SHARE("paletteram") |
| 571 | | AM_RANGE(0xf40000, 0xf7ffff) AM_READWRITE(namcona1_gfxram_r, namcona1_gfxram_w) AM_SHARE("cgram") |
| 572 | | AM_RANGE(0xff0000, 0xffbfff) AM_RAM_WRITE(namcona1_videoram_w) AM_SHARE("videoram") |
| 573 | | AM_RANGE(0xffd000, 0xffdfff) AM_RAM /* unknown */ |
| 574 | | AM_RANGE(0xffe000, 0xffefff) AM_RAM AM_SHARE("scroll") /* scroll registers */ |
| 575 | | AM_RANGE(0xfff000, 0xffffff) AM_RAM AM_SHARE("spriteram") /* spriteram */ |
| 576 | 564 | ADDRESS_MAP_END |
| 577 | 565 | |
| 578 | 566 | |
| r29543 | r29544 | |
| 580 | 568 | |
| 581 | 569 | READ16_MEMBER(namcona1_state::na1mcu_shared_r) |
| 582 | 570 | { |
| 583 | | UINT16 data; |
| 571 | UINT16 data = FLIPENDIAN_INT16(m_workram[offset]); |
| 584 | 572 | |
| 585 | | data = m_workram[offset]; |
| 586 | | |
| 587 | 573 | #if 0 |
| 588 | 574 | if (offset >= 0x70000/2) |
| 589 | 575 | { |
| 590 | | logerror("MD: %04x @ %x PC %x\n", ((data>>8)&0xff) | ((data<<8)&0xff00), offset*2, space.device().safe_pc()); |
| 576 | logerror("MD: %04x @ %x PC %x\n", data, offset*2, space.device().safe_pc()); |
| 591 | 577 | } |
| 592 | 578 | #endif |
| 593 | | |
| 594 | | return ((data>>8)&0xff) | ((data<<8)&0xff00); |
| 579 | return data; |
| 595 | 580 | } |
| 596 | 581 | |
| 597 | 582 | WRITE16_MEMBER(namcona1_state::na1mcu_shared_w) |
| r29543 | r29544 | |
| 714 | 699 | |
| 715 | 700 | void namcona1_state::machine_start() |
| 716 | 701 | { |
| 702 | m_prgrom = (UINT16 *)memregion("maincpu")->base(); |
| 703 | m_maskrom = (UINT16 *)memregion("maskrom")->base(); |
| 704 | m_mEnableInterrupts = 0; |
| 717 | 705 | m_c140->set_base(m_workram); |
| 718 | 706 | } |
| 719 | 707 | |
| 720 | | // for games with the MCU emulated, the MCU boots the 68000. don't allow it before that. |
| 708 | // the MCU boots the 68000 |
| 721 | 709 | void namcona1_state::machine_reset() |
| 722 | 710 | { |
| 723 | 711 | m_maincpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); |
| r29543 | r29544 | |
| 911 | 899 | |
| 912 | 900 | /***************************************************************************/ |
| 913 | 901 | |
| 902 | // MCU interrupts: IRQ 0 => process mail slot (probably set on mail slot write from 68k) |
| 903 | // IRQ 1 => |
| 904 | // IRQ 2 => |
| 905 | |
| 914 | 906 | TIMER_DEVICE_CALLBACK_MEMBER(namcona1_state::namcona1_interrupt) |
| 915 | 907 | { |
| 916 | 908 | int scanline = param; |
| 917 | 909 | int enabled = m_mEnableInterrupts ? ~m_vreg[0x1a/2] : 0; |
| 918 | 910 | |
| 911 | // adc (timing guessed, when does this trigger?) |
| 912 | if (scanline == 0) |
| 913 | m_mcu->set_input_line(M37710_LINE_ADC, HOLD_LINE); |
| 914 | |
| 919 | 915 | // vblank |
| 920 | 916 | if (scanline == 224) |
| 921 | 917 | { |
| 918 | m_mcu->set_input_line(M37710_LINE_IRQ1, HOLD_LINE); |
| 922 | 919 | simulate_mcu( ); |
| 923 | 920 | if (enabled & 8) |
| 924 | 921 | m_maincpu->set_input_line(4, HOLD_LINE); |
| r29543 | r29544 | |
| 935 | 932 | } |
| 936 | 933 | } |
| 937 | 934 | |
| 938 | | // MCU interrupts: IRQ 0 => process mail slot (probably set on mail slot write from 68k) |
| 939 | | // IRQ 1 => |
| 940 | | // IRQ 2 => |
| 941 | | |
| 942 | | TIMER_DEVICE_CALLBACK_MEMBER(namcona1_state::mcu_interrupt) |
| 943 | | { |
| 944 | | int scanline = param; |
| 945 | | |
| 946 | | // vblank |
| 947 | | if (scanline == 224) |
| 948 | | m_mcu->set_input_line(M37710_LINE_IRQ1, HOLD_LINE); |
| 949 | | |
| 950 | | // adc (timing guessed, when does this trigger?) |
| 951 | | if (scanline == 0) |
| 952 | | m_mcu->set_input_line(M37710_LINE_ADC, HOLD_LINE); |
| 953 | | } |
| 954 | | |
| 955 | | static const c140_interface C140_interface_typeA = |
| 956 | | { |
| 957 | | C140_TYPE_ASIC219 |
| 958 | | }; |
| 959 | | |
| 960 | 935 | /* cropped at sides */ |
| 961 | 936 | static MACHINE_CONFIG_START( namcona1, namcona1_state ) |
| 962 | 937 | |
| 963 | 938 | /* basic machine hardware */ |
| 964 | 939 | MCFG_CPU_ADD("maincpu", M68000, MASTER_CLOCK/4) |
| 965 | 940 | MCFG_CPU_PROGRAM_MAP(namcona1_main_map) |
| 966 | | MCFG_TIMER_DRIVER_ADD_SCANLINE("scan_main", namcona1_state, namcona1_interrupt, "screen", 0, 1) |
| 967 | 941 | |
| 968 | 942 | MCFG_CPU_ADD("mcu", M37702, MASTER_CLOCK/4) |
| 969 | 943 | MCFG_CPU_PROGRAM_MAP(namcona1_mcu_map) |
| 970 | 944 | MCFG_CPU_IO_MAP( namcona1_mcu_io_map) |
| 971 | | MCFG_TIMER_DRIVER_ADD_SCANLINE("scan_mcu", namcona1_state, mcu_interrupt, "screen", 0, 1) |
| 972 | 945 | |
| 946 | MCFG_TIMER_DRIVER_ADD_SCANLINE("scan_main", namcona1_state, namcona1_interrupt, "screen", 0, 1) |
| 947 | |
| 973 | 948 | MCFG_EEPROM_2816_ADD("eeprom") |
| 974 | | MCFG_QUANTUM_TIME(attotime::from_hz(2400)) |
| 975 | 949 | |
| 976 | 950 | /* video hardware */ |
| 977 | 951 | MCFG_SCREEN_ADD("screen", RASTER) |
| r29543 | r29544 | |
| 984 | 958 | |
| 985 | 959 | MCFG_PALETTE_ADD("palette", 0x2000) |
| 986 | 960 | MCFG_PALETTE_ENABLE_SHADOWS() |
| 961 | |
| 987 | 962 | MCFG_GFXDECODE_ADD("gfxdecode", "palette", namcona1) |
| 988 | 963 | |
| 989 | 964 | /* sound hardware */ |
| 990 | 965 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
| 991 | 966 | |
| 992 | 967 | MCFG_C140_ADD("c140", 44100) |
| 993 | | MCFG_SOUND_CONFIG(C140_interface_typeA) |
| 968 | MCFG_C140_BANK_TYPE(C140_TYPE_ASIC219) |
| 994 | 969 | MCFG_SOUND_ROUTE(0, "rspeaker", 1.00) |
| 995 | 970 | MCFG_SOUND_ROUTE(1, "lspeaker", 1.00) |
| 996 | 971 | MACHINE_CONFIG_END |
| r29543 | r29544 | |
| 1013 | 988 | MACHINE_CONFIG_END |
| 1014 | 989 | |
| 1015 | 990 | |
| 1016 | | void namcona1_state::init_namcona1( int gametype ) |
| 1017 | | { |
| 1018 | | UINT16 *pMem = (UINT16 *)memregion( "maincpu" )->base(); |
| 991 | DRIVER_INIT_MEMBER(namcona1_state,bkrtmaq) { m_gametype = NAMCO_BKRTMAQ; } |
| 992 | DRIVER_INIT_MEMBER(namcona1_state,cgangpzl) { m_gametype = NAMCO_CGANGPZL; } |
| 993 | DRIVER_INIT_MEMBER(namcona1_state,emeralda) { m_gametype = NAMCO_EMERALDA; } /* NA-2 Hardware */ |
| 994 | DRIVER_INIT_MEMBER(namcona1_state,emeraldj) { m_gametype = NAMCO_EMERALDA; } /* NA-1 Hardware */ |
| 995 | DRIVER_INIT_MEMBER(namcona1_state,exbania) { m_gametype = NAMCO_EXBANIA; } |
| 996 | DRIVER_INIT_MEMBER(namcona1_state,fa) { m_gametype = NAMCO_FA; } |
| 997 | DRIVER_INIT_MEMBER(namcona1_state,knckhead) { m_gametype = NAMCO_KNCKHEAD; } |
| 998 | DRIVER_INIT_MEMBER(namcona1_state,numanath) { m_gametype = NAMCO_NUMANATH; } |
| 999 | DRIVER_INIT_MEMBER(namcona1_state,quiztou) { m_gametype = NAMCO_QUIZTOU; } |
| 1000 | DRIVER_INIT_MEMBER(namcona1_state,swcourt) { m_gametype = NAMCO_SWCOURT; } |
| 1001 | DRIVER_INIT_MEMBER(namcona1_state,tinklpit) { m_gametype = NAMCO_TINKLPIT; } |
| 1002 | DRIVER_INIT_MEMBER(namcona1_state,xday2) { m_gametype = NAMCO_XDAY2; } |
| 1019 | 1003 | |
| 1020 | | m_gametype = gametype; |
| 1021 | | m_mpBank0 = &pMem[0x80000/2]; |
| 1022 | | m_mpBank1 = m_mpBank0 + 0x200000/2; |
| 1023 | | |
| 1024 | | m_mEnableInterrupts = 0; |
| 1025 | | } |
| 1026 | | |
| 1027 | | DRIVER_INIT_MEMBER(namcona1_state,bkrtmaq) { init_namcona1(NAMCO_BKRTMAQ); } |
| 1028 | | DRIVER_INIT_MEMBER(namcona1_state,cgangpzl) { init_namcona1(NAMCO_CGANGPZL); } |
| 1029 | | DRIVER_INIT_MEMBER(namcona1_state,emeralda) { init_namcona1(NAMCO_EMERALDA); } /* NA-2 Hardware */ |
| 1030 | | DRIVER_INIT_MEMBER(namcona1_state,emeraldj) { init_namcona1(NAMCO_EMERALDA); } /* NA-1 Hardware */ |
| 1031 | | DRIVER_INIT_MEMBER(namcona1_state,exbania) { init_namcona1(NAMCO_EXBANIA); } |
| 1032 | | DRIVER_INIT_MEMBER(namcona1_state,fa) { init_namcona1(NAMCO_FA); } |
| 1033 | | DRIVER_INIT_MEMBER(namcona1_state,knckhead) { init_namcona1(NAMCO_KNCKHEAD); } |
| 1034 | | DRIVER_INIT_MEMBER(namcona1_state,numanath) { init_namcona1(NAMCO_NUMANATH); } |
| 1035 | | DRIVER_INIT_MEMBER(namcona1_state,quiztou) { init_namcona1(NAMCO_QUIZTOU); } |
| 1036 | | DRIVER_INIT_MEMBER(namcona1_state,swcourt) { init_namcona1(NAMCO_SWCOURT); } |
| 1037 | | DRIVER_INIT_MEMBER(namcona1_state,tinklpit) { init_namcona1(NAMCO_TINKLPIT); } |
| 1038 | | DRIVER_INIT_MEMBER(namcona1_state,xday2) { init_namcona1(NAMCO_XDAY2); } |
| 1039 | | |
| 1040 | 1004 | ROM_START( bkrtmaq ) |
| 1041 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1042 | | ROM_LOAD16_BYTE( "mq1-ep0l.bin", 0x080001, 0x080000, CRC(f029bc57) SHA1(fdbf8b8b9f69d5755ca5197dda4f887b12dd66f4) ) /* 0xc00000 */ |
| 1043 | | ROM_LOAD16_BYTE( "mq1-ep0u.bin", 0x080000, 0x080000, CRC(4cff62b8) SHA1(5cac170dcfbeb3dcfa0840bdbe7541a9d2f44a14) ) |
| 1044 | | ROM_LOAD16_BYTE( "mq1-ep1l.bin", 0x180001, 0x080000, CRC(e3be6f4b) SHA1(75d9a4cff25e63a9d6c092aa6e241eccd1c61f91) ) |
| 1045 | | ROM_LOAD16_BYTE( "mq1-ep1u.bin", 0x180000, 0x080000, CRC(b44e31b2) SHA1(3d8c63789b98ada3663ba9e28c370815a9a9c3ed) ) |
| 1005 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1006 | ROM_LOAD16_BYTE( "mq1-ep0l.bin", 0x000001, 0x080000, CRC(f029bc57) SHA1(fdbf8b8b9f69d5755ca5197dda4f887b12dd66f4) ) /* 0xc00000 */ |
| 1007 | ROM_LOAD16_BYTE( "mq1-ep0u.bin", 0x000000, 0x080000, CRC(4cff62b8) SHA1(5cac170dcfbeb3dcfa0840bdbe7541a9d2f44a14) ) |
| 1008 | ROM_LOAD16_BYTE( "mq1-ep1l.bin", 0x100001, 0x080000, CRC(e3be6f4b) SHA1(75d9a4cff25e63a9d6c092aa6e241eccd1c61f91) ) |
| 1009 | ROM_LOAD16_BYTE( "mq1-ep1u.bin", 0x100000, 0x080000, CRC(b44e31b2) SHA1(3d8c63789b98ada3663ba9e28c370815a9a9c3ed) ) |
| 1046 | 1010 | |
| 1047 | | ROM_LOAD16_BYTE( "mq1-ma0l.bin", 0x280001, 0x100000, CRC(11fed35f) SHA1(511d98b6b42b330238a1874bca031b1892654a48) ) /* 0x400000 */ |
| 1048 | | ROM_LOAD16_BYTE( "mq1-ma0u.bin", 0x280000, 0x100000, CRC(23442ac0) SHA1(fac706f24045d51a2712f51530967140ea8e875f) ) |
| 1049 | | ROM_LOAD16_BYTE( "mq1-ma1l.bin", 0x480001, 0x100000, CRC(fe82205f) SHA1(860cc7a96ae3f848ce594077c1362e4e22a36908) ) |
| 1050 | | ROM_LOAD16_BYTE( "mq1-ma1u.bin", 0x480000, 0x100000, CRC(0cdb6bd0) SHA1(b8b398477c9654e96921110fb30c754240183897) ) |
| 1011 | ROM_REGION16_BE( 0x800000, "maskrom", 0 ) |
| 1012 | ROM_LOAD16_BYTE( "mq1-ma0l.bin", 0x000001, 0x100000, CRC(11fed35f) SHA1(511d98b6b42b330238a1874bca031b1892654a48) ) /* 0x400000 */ |
| 1013 | ROM_LOAD16_BYTE( "mq1-ma0u.bin", 0x000000, 0x100000, CRC(23442ac0) SHA1(fac706f24045d51a2712f51530967140ea8e875f) ) |
| 1014 | ROM_LOAD16_BYTE( "mq1-ma1l.bin", 0x200001, 0x100000, CRC(fe82205f) SHA1(860cc7a96ae3f848ce594077c1362e4e22a36908) ) |
| 1015 | ROM_LOAD16_BYTE( "mq1-ma1u.bin", 0x200000, 0x100000, CRC(0cdb6bd0) SHA1(b8b398477c9654e96921110fb30c754240183897) ) |
| 1051 | 1016 | |
| 1052 | 1017 | /* M37702 BIOS - labeled as Namco custom C69 */ |
| 1053 | 1018 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| r29543 | r29544 | |
| 1055 | 1020 | ROM_END |
| 1056 | 1021 | |
| 1057 | 1022 | ROM_START( cgangpzl ) |
| 1058 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1059 | | ROM_LOAD16_BYTE( "cp2-ep0l.bin", 0x080001, 0x80000, CRC(8f5cdcc5) SHA1(925db3f3f16224bc28f97a57aba0ab2b51c5067c) ) /* 0xc00000 */ |
| 1060 | | ROM_LOAD16_BYTE( "cp2-ep0u.bin", 0x080000, 0x80000, CRC(3a816140) SHA1(613c367e08a0a20ec62e1938faab0128743b26f8) ) |
| 1023 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1024 | ROM_LOAD16_BYTE( "cp2-ep0l.bin", 0x000001, 0x080000, CRC(8f5cdcc5) SHA1(925db3f3f16224bc28f97a57aba0ab2b51c5067c) ) /* 0xc00000 */ |
| 1025 | ROM_LOAD16_BYTE( "cp2-ep0u.bin", 0x000000, 0x080000, CRC(3a816140) SHA1(613c367e08a0a20ec62e1938faab0128743b26f8) ) |
| 1061 | 1026 | |
| 1027 | ROM_REGION16_BE( 0x800000, "maskrom", ROMREGION_ERASE00 ) |
| 1028 | /* no mask roms */ |
| 1029 | |
| 1062 | 1030 | /* M37702 BIOS - labeled as Namco custom C69 */ |
| 1063 | 1031 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| 1064 | 1032 | ROM_LOAD( "c69.bin", 0x000000, 0x004000, CRC(349134d9) SHA1(61a4981fc2716c228b6121fedcbf1ed6f34dc2de) ) |
| r29543 | r29544 | |
| 1068 | 1036 | ROM_END |
| 1069 | 1037 | |
| 1070 | 1038 | ROM_START( cgangpzlj ) |
| 1071 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1039 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1072 | 1040 | ROM_LOAD16_BYTE( "cp1-ep0l.bin", 0x080001, 0x80000, CRC(2825f7ba) SHA1(5f6f8df6bdf0f45656904411cdbb31fdcf8f3be0) ) /* 0xc00000 */ |
| 1073 | 1041 | ROM_LOAD16_BYTE( "cp1-ep0u.bin", 0x080000, 0x80000, CRC(94d7d6fc) SHA1(2460741e0dbb2ccff28f4fbc419a7507382467d2) ) |
| 1074 | 1042 | |
| 1043 | ROM_REGION16_BE( 0x800000, "maskrom", ROMREGION_ERASE00 ) |
| 1044 | /* no mask roms */ |
| 1045 | |
| 1075 | 1046 | /* M37702 BIOS - labeled as Namco custom C69 */ |
| 1076 | 1047 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| 1077 | 1048 | ROM_LOAD( "c69.bin", 0x000000, 0x004000, CRC(349134d9) SHA1(61a4981fc2716c228b6121fedcbf1ed6f34dc2de) ) |
| r29543 | r29544 | |
| 1081 | 1052 | ROM_END |
| 1082 | 1053 | |
| 1083 | 1054 | ROM_START( emeraldaj ) /* NA-1 Game PCB, parent is NA-2 version listed below */ |
| 1084 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1085 | | ROM_LOAD16_BYTE( "em1-ep0lb.bin", 0x080001, 0x080000, CRC(fcd55293) SHA1(fdabf9d5f528c37196ac1e031b097618b4c887b5) ) /* 0xc00000 */ |
| 1086 | | ROM_LOAD16_BYTE( "em1-ep0ub.bin", 0x080000, 0x080000, CRC(a52f00d5) SHA1(85f95d2a69a2df2e9195f55583645c064b0b6fe6) ) |
| 1087 | | ROM_LOAD16_BYTE( "em1-ep1l.bin", 0x180001, 0x080000, CRC(373c1c59) SHA1(385cb3bc056b798878de890dbff97a8bdd48fe4e) ) |
| 1088 | | ROM_LOAD16_BYTE( "em1-ep1u.bin", 0x180000, 0x080000, CRC(4e969152) SHA1(2c89ae5d43585f479f16cf8278f8fc001e077e45) ) |
| 1055 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1056 | ROM_LOAD16_BYTE( "em1-ep0lb.bin", 0x000001, 0x080000, CRC(fcd55293) SHA1(fdabf9d5f528c37196ac1e031b097618b4c887b5) ) /* 0xc00000 */ |
| 1057 | ROM_LOAD16_BYTE( "em1-ep0ub.bin", 0x000000, 0x080000, CRC(a52f00d5) SHA1(85f95d2a69a2df2e9195f55583645c064b0b6fe6) ) |
| 1058 | ROM_LOAD16_BYTE( "em1-ep1l.bin", 0x100001, 0x080000, CRC(373c1c59) SHA1(385cb3bc056b798878de890dbff97a8bdd48fe4e) ) |
| 1059 | ROM_LOAD16_BYTE( "em1-ep1u.bin", 0x100000, 0x080000, CRC(4e969152) SHA1(2c89ae5d43585f479f16cf8278f8fc001e077e45) ) |
| 1089 | 1060 | |
| 1061 | ROM_REGION16_BE( 0x800000, "maskrom", ROMREGION_ERASE00 ) |
| 1062 | /* no mask roms */ |
| 1063 | |
| 1090 | 1064 | /* M37702 BIOS - labeled as Namco custom C69 */ |
| 1091 | 1065 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| 1092 | 1066 | ROM_LOAD( "c69.bin", 0x000000, 0x004000, CRC(349134d9) SHA1(61a4981fc2716c228b6121fedcbf1ed6f34dc2de) ) |
| 1093 | 1067 | ROM_END |
| 1094 | 1068 | |
| 1095 | 1069 | ROM_START( emeraldaja ) /* NA-1 Game PCB, parent is NA-2 version listed below */ |
| 1096 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1097 | | ROM_LOAD16_BYTE( "em1-ep0l.bin", 0x080001, 0x080000, CRC(443f3fce) SHA1(35b6c834e5716c1e9b55f1e39f4e7336dbbe2d9b) ) /* 0xc00000 */ |
| 1098 | | ROM_LOAD16_BYTE( "em1-ep0u.bin", 0x080000, 0x080000, CRC(484a2a81) SHA1(1b60c18dfb2aebfd4aa8b2a85a1e90883a1f8e61) ) |
| 1099 | | ROM_LOAD16_BYTE( "em1-ep1l.bin", 0x180001, 0x080000, CRC(373c1c59) SHA1(385cb3bc056b798878de890dbff97a8bdd48fe4e) ) |
| 1100 | | ROM_LOAD16_BYTE( "em1-ep1u.bin", 0x180000, 0x080000, CRC(4e969152) SHA1(2c89ae5d43585f479f16cf8278f8fc001e077e45) ) |
| 1070 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1071 | ROM_LOAD16_BYTE( "em1-ep0l.bin", 0x000001, 0x080000, CRC(443f3fce) SHA1(35b6c834e5716c1e9b55f1e39f4e7336dbbe2d9b) ) /* 0xc00000 */ |
| 1072 | ROM_LOAD16_BYTE( "em1-ep0u.bin", 0x000000, 0x080000, CRC(484a2a81) SHA1(1b60c18dfb2aebfd4aa8b2a85a1e90883a1f8e61) ) |
| 1073 | ROM_LOAD16_BYTE( "em1-ep1l.bin", 0x100001, 0x080000, CRC(373c1c59) SHA1(385cb3bc056b798878de890dbff97a8bdd48fe4e) ) |
| 1074 | ROM_LOAD16_BYTE( "em1-ep1u.bin", 0x100000, 0x080000, CRC(4e969152) SHA1(2c89ae5d43585f479f16cf8278f8fc001e077e45) ) |
| 1101 | 1075 | |
| 1076 | ROM_REGION16_BE( 0x800000, "maskrom", ROMREGION_ERASE00 ) |
| 1077 | /* no mask roms */ |
| 1078 | |
| 1102 | 1079 | /* M37702 BIOS - labeled as Namco custom C69 */ |
| 1103 | 1080 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| 1104 | 1081 | ROM_LOAD( "c69.bin", 0x000000, 0x004000, CRC(349134d9) SHA1(61a4981fc2716c228b6121fedcbf1ed6f34dc2de) ) |
| 1105 | 1082 | ROM_END |
| 1106 | 1083 | |
| 1107 | 1084 | ROM_START( exvania ) |
| 1108 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1109 | | ROM_LOAD16_BYTE( "ex2-ep0l.4c", 0x080001, 0x080000, CRC(ccf46677) SHA1(f9d057a7b1c388323d49ef692f41242769f1a08c) ) /* 0xc00000 */ |
| 1110 | | ROM_LOAD16_BYTE( "ex2-ep0u.4f", 0x080000, 0x080000, CRC(37b8d890) SHA1(a0417a1b51d1206bd3eb5e7b58303a9a5691fa43) ) |
| 1085 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1086 | ROM_LOAD16_BYTE( "ex2-ep0l.4c", 0x000001, 0x080000, CRC(ccf46677) SHA1(f9d057a7b1c388323d49ef692f41242769f1a08c) ) /* 0xc00000 */ |
| 1087 | ROM_LOAD16_BYTE( "ex2-ep0u.4f", 0x000000, 0x080000, CRC(37b8d890) SHA1(a0417a1b51d1206bd3eb5e7b58303a9a5691fa43) ) |
| 1111 | 1088 | |
| 1112 | | ROM_LOAD16_BYTE( "ex1-ma0l.2c", 0x280001, 0x100000, CRC(17922cd4) SHA1(af92c2335e7110c0c5e712f3148c1534d22d3814) ) /* 0x400000 */ |
| 1113 | | ROM_LOAD16_BYTE( "ex1-ma0u.2f", 0x280000, 0x100000, CRC(93d66106) SHA1(c5d665db04ae0e8992ef46544e2cb7b0e27c8bfe) ) |
| 1114 | | ROM_LOAD16_BYTE( "ex1-ma1l.3c", 0x480001, 0x100000, CRC(e4bba6ed) SHA1(6483ef91e5a5b8ddd13a3d889936c39829fa50d6) ) |
| 1115 | | ROM_LOAD16_BYTE( "ex1-ma1u.3f", 0x480000, 0x100000, CRC(04e7c4b0) SHA1(78180d96cd1fae583617d4d227ed4ee24f2f9e29) ) |
| 1089 | ROM_REGION16_BE( 0x800000, "maskrom", 0 ) |
| 1090 | ROM_LOAD16_BYTE( "ex1-ma0l.2c", 0x000001, 0x100000, CRC(17922cd4) SHA1(af92c2335e7110c0c5e712f3148c1534d22d3814) ) /* 0x400000 */ |
| 1091 | ROM_LOAD16_BYTE( "ex1-ma0u.2f", 0x000000, 0x100000, CRC(93d66106) SHA1(c5d665db04ae0e8992ef46544e2cb7b0e27c8bfe) ) |
| 1092 | ROM_LOAD16_BYTE( "ex1-ma1l.3c", 0x200001, 0x100000, CRC(e4bba6ed) SHA1(6483ef91e5a5b8ddd13a3d889936c39829fa50d6) ) |
| 1093 | ROM_LOAD16_BYTE( "ex1-ma1u.3f", 0x200000, 0x100000, CRC(04e7c4b0) SHA1(78180d96cd1fae583617d4d227ed4ee24f2f9e29) ) |
| 1116 | 1094 | |
| 1117 | 1095 | /* M37702 BIOS - labeled as Namco custom C69 */ |
| 1118 | 1096 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| r29543 | r29544 | |
| 1123 | 1101 | ROM_END |
| 1124 | 1102 | |
| 1125 | 1103 | ROM_START( exvaniaj ) |
| 1126 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1127 | | ROM_LOAD16_BYTE( "ex1-ep0l.4c", 0x080001, 0x080000, CRC(18c12015) SHA1(e4f3524e798545c434549719b377c8b5863f580f) ) /* 0xc00000 */ |
| 1128 | | ROM_LOAD16_BYTE( "ex1-ep0u.4f", 0x080000, 0x080000, CRC(07d054d1) SHA1(e2d2cb81acd309c519686572804648bef4cbd191) ) |
| 1104 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1105 | ROM_LOAD16_BYTE( "ex1-ep0l.4c", 0x000001, 0x080000, CRC(18c12015) SHA1(e4f3524e798545c434549719b377c8b5863f580f) ) /* 0xc00000 */ |
| 1106 | ROM_LOAD16_BYTE( "ex1-ep0u.4f", 0x000000, 0x080000, CRC(07d054d1) SHA1(e2d2cb81acd309c519686572804648bef4cbd191) ) |
| 1129 | 1107 | |
| 1130 | | ROM_LOAD16_BYTE( "ex1-ma0l.2c", 0x280001, 0x100000, CRC(17922cd4) SHA1(af92c2335e7110c0c5e712f3148c1534d22d3814) ) /* 0x400000 */ |
| 1131 | | ROM_LOAD16_BYTE( "ex1-ma0u.2f", 0x280000, 0x100000, CRC(93d66106) SHA1(c5d665db04ae0e8992ef46544e2cb7b0e27c8bfe) ) |
| 1132 | | ROM_LOAD16_BYTE( "ex1-ma1l.3c", 0x480001, 0x100000, CRC(e4bba6ed) SHA1(6483ef91e5a5b8ddd13a3d889936c39829fa50d6) ) |
| 1133 | | ROM_LOAD16_BYTE( "ex1-ma1u.3f", 0x480000, 0x100000, CRC(04e7c4b0) SHA1(78180d96cd1fae583617d4d227ed4ee24f2f9e29) ) |
| 1108 | ROM_REGION16_BE( 0x800000, "maskrom", 0 ) |
| 1109 | ROM_LOAD16_BYTE( "ex1-ma0l.2c", 0x000001, 0x100000, CRC(17922cd4) SHA1(af92c2335e7110c0c5e712f3148c1534d22d3814) ) /* 0x400000 */ |
| 1110 | ROM_LOAD16_BYTE( "ex1-ma0u.2f", 0x000000, 0x100000, CRC(93d66106) SHA1(c5d665db04ae0e8992ef46544e2cb7b0e27c8bfe) ) |
| 1111 | ROM_LOAD16_BYTE( "ex1-ma1l.3c", 0x200001, 0x100000, CRC(e4bba6ed) SHA1(6483ef91e5a5b8ddd13a3d889936c39829fa50d6) ) |
| 1112 | ROM_LOAD16_BYTE( "ex1-ma1u.3f", 0x200000, 0x100000, CRC(04e7c4b0) SHA1(78180d96cd1fae583617d4d227ed4ee24f2f9e29) ) |
| 1134 | 1113 | |
| 1135 | 1114 | /* M37702 BIOS - labeled as Namco custom C69 */ |
| 1136 | 1115 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| r29543 | r29544 | |
| 1141 | 1120 | ROM_END |
| 1142 | 1121 | |
| 1143 | 1122 | ROM_START( fghtatck ) |
| 1144 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1145 | | ROM_LOAD16_BYTE( "fa2-ep0l.bin", 0x080001, 0x080000, CRC(8996db9c) SHA1(ebbe7d4cb2960a346cfbdf38c77638d71b6ba20e) ) /* 0xc00000 */ |
| 1146 | | ROM_LOAD16_BYTE( "fa2-ep0u.bin", 0x080000, 0x080000, CRC(58d5e090) SHA1(950219d4e9bf440f92e3c8765f47e23a9019d2d1) ) |
| 1147 | | ROM_LOAD16_BYTE( "fa1-ep1l.bin", 0x180001, 0x080000, CRC(b23a5b01) SHA1(4ba9bc2102fffc93a5ff73a107d557fc0f3beefd) ) |
| 1148 | | ROM_LOAD16_BYTE( "fa1-ep1u.bin", 0x180000, 0x080000, CRC(de2eb129) SHA1(912993cab1c2edcaf986478f2ae22a2f10edf807) ) |
| 1123 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1124 | ROM_LOAD16_BYTE( "fa2-ep0l.bin", 0x000001, 0x080000, CRC(8996db9c) SHA1(ebbe7d4cb2960a346cfbdf38c77638d71b6ba20e) ) /* 0xc00000 */ |
| 1125 | ROM_LOAD16_BYTE( "fa2-ep0u.bin", 0x000000, 0x080000, CRC(58d5e090) SHA1(950219d4e9bf440f92e3c8765f47e23a9019d2d1) ) |
| 1126 | ROM_LOAD16_BYTE( "fa1-ep1l.bin", 0x100001, 0x080000, CRC(b23a5b01) SHA1(4ba9bc2102fffc93a5ff73a107d557fc0f3beefd) ) |
| 1127 | ROM_LOAD16_BYTE( "fa1-ep1u.bin", 0x100000, 0x080000, CRC(de2eb129) SHA1(912993cab1c2edcaf986478f2ae22a2f10edf807) ) |
| 1149 | 1128 | |
| 1150 | | ROM_LOAD16_BYTE( "fa1-ma0l.bin", 0x280001, 0x100000, CRC(a0a95e54) SHA1(da35f8a6a5bc9e2b5b6cacf8eb0d900ef1073a67) ) /* 0x400000 */ |
| 1151 | | ROM_LOAD16_BYTE( "fa1-ma0u.bin", 0x280000, 0x100000, CRC(1d0135bd) SHA1(2a7f8d09c213629a68376ce0379be61b37711d0a) ) |
| 1152 | | ROM_LOAD16_BYTE( "fa1-ma1l.bin", 0x480001, 0x100000, CRC(c4adf0a2) SHA1(4cc7adc68b1db7e725a973b31d52720bd7dc1140) ) |
| 1153 | | ROM_LOAD16_BYTE( "fa1-ma1u.bin", 0x480000, 0x100000, CRC(900297be) SHA1(57bb2078ff104c6f631c67219f80f8ede5ddbd09) ) |
| 1129 | ROM_REGION16_BE( 0x800000, "maskrom", 0 ) |
| 1130 | ROM_LOAD16_BYTE( "fa1-ma0l.bin", 0x000001, 0x100000, CRC(a0a95e54) SHA1(da35f8a6a5bc9e2b5b6cacf8eb0d900ef1073a67) ) /* 0x400000 */ |
| 1131 | ROM_LOAD16_BYTE( "fa1-ma0u.bin", 0x000000, 0x100000, CRC(1d0135bd) SHA1(2a7f8d09c213629a68376ce0379be61b37711d0a) ) |
| 1132 | ROM_LOAD16_BYTE( "fa1-ma1l.bin", 0x200001, 0x100000, CRC(c4adf0a2) SHA1(4cc7adc68b1db7e725a973b31d52720bd7dc1140) ) |
| 1133 | ROM_LOAD16_BYTE( "fa1-ma1u.bin", 0x200000, 0x100000, CRC(900297be) SHA1(57bb2078ff104c6f631c67219f80f8ede5ddbd09) ) |
| 1154 | 1134 | |
| 1155 | 1135 | /* M37702 BIOS - labeled as Namco custom C69 */ |
| 1156 | 1136 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| r29543 | r29544 | |
| 1158 | 1138 | ROM_END |
| 1159 | 1139 | |
| 1160 | 1140 | ROM_START( fa ) |
| 1161 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1162 | | ROM_LOAD16_BYTE( "fa1-ep0l.bin", 0x080001, 0x080000, CRC(182eee5c) SHA1(49769e3b72b59fc3e7b73364fe97168977dbe66b) ) /* 0xc00000 */ |
| 1163 | | ROM_LOAD16_BYTE( "fa1-ep0u.bin", 0x080000, 0x080000, CRC(7ea7830e) SHA1(79390943eea0b8029b2b8869233caf27228e776a) ) |
| 1164 | | ROM_LOAD16_BYTE( "fa1-ep1l.bin", 0x180001, 0x080000, CRC(b23a5b01) SHA1(4ba9bc2102fffc93a5ff73a107d557fc0f3beefd) ) |
| 1165 | | ROM_LOAD16_BYTE( "fa1-ep1u.bin", 0x180000, 0x080000, CRC(de2eb129) SHA1(912993cab1c2edcaf986478f2ae22a2f10edf807) ) |
| 1141 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1142 | ROM_LOAD16_BYTE( "fa1-ep0l.bin", 0x000001, 0x080000, CRC(182eee5c) SHA1(49769e3b72b59fc3e7b73364fe97168977dbe66b) ) /* 0xc00000 */ |
| 1143 | ROM_LOAD16_BYTE( "fa1-ep0u.bin", 0x000000, 0x080000, CRC(7ea7830e) SHA1(79390943eea0b8029b2b8869233caf27228e776a) ) |
| 1144 | ROM_LOAD16_BYTE( "fa1-ep1l.bin", 0x100001, 0x080000, CRC(b23a5b01) SHA1(4ba9bc2102fffc93a5ff73a107d557fc0f3beefd) ) |
| 1145 | ROM_LOAD16_BYTE( "fa1-ep1u.bin", 0x100000, 0x080000, CRC(de2eb129) SHA1(912993cab1c2edcaf986478f2ae22a2f10edf807) ) |
| 1166 | 1146 | |
| 1167 | | ROM_LOAD16_BYTE( "fa1-ma0l.bin", 0x280001, 0x100000, CRC(a0a95e54) SHA1(da35f8a6a5bc9e2b5b6cacf8eb0d900ef1073a67) ) /* 0x400000 */ |
| 1168 | | ROM_LOAD16_BYTE( "fa1-ma0u.bin", 0x280000, 0x100000, CRC(1d0135bd) SHA1(2a7f8d09c213629a68376ce0379be61b37711d0a) ) |
| 1169 | | ROM_LOAD16_BYTE( "fa1-ma1l.bin", 0x480001, 0x100000, CRC(c4adf0a2) SHA1(4cc7adc68b1db7e725a973b31d52720bd7dc1140) ) |
| 1170 | | ROM_LOAD16_BYTE( "fa1-ma1u.bin", 0x480000, 0x100000, CRC(900297be) SHA1(57bb2078ff104c6f631c67219f80f8ede5ddbd09) ) |
| 1147 | ROM_REGION16_BE( 0x800000, "maskrom", 0 ) |
| 1148 | ROM_LOAD16_BYTE( "fa1-ma0l.bin", 0x000001, 0x100000, CRC(a0a95e54) SHA1(da35f8a6a5bc9e2b5b6cacf8eb0d900ef1073a67) ) /* 0x400000 */ |
| 1149 | ROM_LOAD16_BYTE( "fa1-ma0u.bin", 0x000000, 0x100000, CRC(1d0135bd) SHA1(2a7f8d09c213629a68376ce0379be61b37711d0a) ) |
| 1150 | ROM_LOAD16_BYTE( "fa1-ma1l.bin", 0x200001, 0x100000, CRC(c4adf0a2) SHA1(4cc7adc68b1db7e725a973b31d52720bd7dc1140) ) |
| 1151 | ROM_LOAD16_BYTE( "fa1-ma1u.bin", 0x200000, 0x100000, CRC(900297be) SHA1(57bb2078ff104c6f631c67219f80f8ede5ddbd09) ) |
| 1171 | 1152 | |
| 1172 | 1153 | /* M37702 BIOS - labeled as Namco custom C69 */ |
| 1173 | 1154 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| r29543 | r29544 | |
| 1175 | 1156 | ROM_END |
| 1176 | 1157 | |
| 1177 | 1158 | ROM_START( swcourt ) |
| 1178 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1179 | | ROM_LOAD16_BYTE( "sc2-ep0l.4c", 0x080001, 0x080000, CRC(5053a02e) SHA1(8ab5a085969cef5e01be01d8f531233002ea5bff) ) /* 0xc00000 */ |
| 1180 | | ROM_LOAD16_BYTE( "sc2-ep0u.4f", 0x080000, 0x080000, CRC(7b3fc7fa) SHA1(f96c03a03339b7677b8dc8689d907f2c8895886c) ) |
| 1181 | | ROM_LOAD16_BYTE( "sc1-ep1l.bin", 0x180001, 0x080000, CRC(fb45cf5f) SHA1(6ded351daa9b39d0b8149100caefc4fa0c598e79) ) |
| 1182 | | ROM_LOAD16_BYTE( "sc1-ep1u.bin", 0x180000, 0x080000, CRC(1ce07b15) SHA1(b1b28cc480301c9ad642597c7cdd8e9cdec996a6) ) |
| 1159 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1160 | ROM_LOAD16_BYTE( "sc2-ep0l.4c", 0x000001, 0x080000, CRC(5053a02e) SHA1(8ab5a085969cef5e01be01d8f531233002ea5bff) ) /* 0xc00000 */ |
| 1161 | ROM_LOAD16_BYTE( "sc2-ep0u.4f", 0x000000, 0x080000, CRC(7b3fc7fa) SHA1(f96c03a03339b7677b8dc8689d907f2c8895886c) ) |
| 1162 | ROM_LOAD16_BYTE( "sc1-ep1l.bin", 0x100001, 0x080000, CRC(fb45cf5f) SHA1(6ded351daa9b39d0b8149100caefc4fa0c598e79) ) |
| 1163 | ROM_LOAD16_BYTE( "sc1-ep1u.bin", 0x100000, 0x080000, CRC(1ce07b15) SHA1(b1b28cc480301c9ad642597c7cdd8e9cdec996a6) ) |
| 1183 | 1164 | |
| 1184 | | ROM_LOAD16_BYTE( "sc1-ma0l.bin", 0x280001, 0x100000, CRC(3e531f5e) SHA1(6da56630bdfbb19f1639c539779c180d106f6ee2) ) /* 0x400000 */ |
| 1185 | | ROM_LOAD16_BYTE( "sc1-ma0u.bin", 0x280000, 0x100000, CRC(31e76a45) SHA1(5c278c167c1025c648ce2da2c3764645e96dcd55) ) |
| 1186 | | ROM_LOAD16_BYTE( "sc1-ma1l.bin", 0x480001, 0x100000, CRC(8ba3a4ec) SHA1(f881e7b4728f388d18450ba85e13e233071fbc88) ) |
| 1187 | | ROM_LOAD16_BYTE( "sc1-ma1u.bin", 0x480000, 0x100000, CRC(252dc4b7) SHA1(f1be6bd045495c7a0ecd97f01d1dc8ad341fecfd) ) |
| 1165 | ROM_REGION16_BE( 0x800000, "maskrom", 0 ) |
| 1166 | ROM_LOAD16_BYTE( "sc1-ma0l.bin", 0x000001, 0x100000, CRC(3e531f5e) SHA1(6da56630bdfbb19f1639c539779c180d106f6ee2) ) /* 0x400000 */ |
| 1167 | ROM_LOAD16_BYTE( "sc1-ma0u.bin", 0x000000, 0x100000, CRC(31e76a45) SHA1(5c278c167c1025c648ce2da2c3764645e96dcd55) ) |
| 1168 | ROM_LOAD16_BYTE( "sc1-ma1l.bin", 0x200001, 0x100000, CRC(8ba3a4ec) SHA1(f881e7b4728f388d18450ba85e13e233071fbc88) ) |
| 1169 | ROM_LOAD16_BYTE( "sc1-ma1u.bin", 0x200000, 0x100000, CRC(252dc4b7) SHA1(f1be6bd045495c7a0ecd97f01d1dc8ad341fecfd) ) |
| 1188 | 1170 | |
| 1189 | 1171 | /* M37702 BIOS - labeled as Namco custom C69 */ |
| 1190 | 1172 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| r29543 | r29544 | |
| 1192 | 1174 | ROM_END |
| 1193 | 1175 | |
| 1194 | 1176 | ROM_START( swcourtj ) |
| 1195 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1196 | | ROM_LOAD16_BYTE( "sc1-ep0l.4c", 0x080001, 0x080000, CRC(145111dd) SHA1(f8f74f77fb80af2ea37ea8ddbf02c1f3fcaf3fdb) ) /* 0xc00000 */ |
| 1197 | | ROM_LOAD16_BYTE( "sc1-ep0u.4f", 0x080000, 0x080000, CRC(c721c138) SHA1(5d30d66629d982b54c3bb62118be940dc7b69a6b) ) |
| 1198 | | ROM_LOAD16_BYTE( "sc1-ep1l.bin", 0x180001, 0x080000, CRC(fb45cf5f) SHA1(6ded351daa9b39d0b8149100caefc4fa0c598e79) ) |
| 1199 | | ROM_LOAD16_BYTE( "sc1-ep1u.bin", 0x180000, 0x080000, CRC(1ce07b15) SHA1(b1b28cc480301c9ad642597c7cdd8e9cdec996a6) ) |
| 1177 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1178 | ROM_LOAD16_BYTE( "sc1-ep0l.4c", 0x000001, 0x080000, CRC(145111dd) SHA1(f8f74f77fb80af2ea37ea8ddbf02c1f3fcaf3fdb) ) /* 0xc00000 */ |
| 1179 | ROM_LOAD16_BYTE( "sc1-ep0u.4f", 0x000000, 0x080000, CRC(c721c138) SHA1(5d30d66629d982b54c3bb62118be940dc7b69a6b) ) |
| 1180 | ROM_LOAD16_BYTE( "sc1-ep1l.bin", 0x100001, 0x080000, CRC(fb45cf5f) SHA1(6ded351daa9b39d0b8149100caefc4fa0c598e79) ) |
| 1181 | ROM_LOAD16_BYTE( "sc1-ep1u.bin", 0x100000, 0x080000, CRC(1ce07b15) SHA1(b1b28cc480301c9ad642597c7cdd8e9cdec996a6) ) |
| 1200 | 1182 | |
| 1201 | | ROM_LOAD16_BYTE( "sc1-ma0l.bin", 0x280001, 0x100000, CRC(3e531f5e) SHA1(6da56630bdfbb19f1639c539779c180d106f6ee2) ) /* 0x400000 */ |
| 1202 | | ROM_LOAD16_BYTE( "sc1-ma0u.bin", 0x280000, 0x100000, CRC(31e76a45) SHA1(5c278c167c1025c648ce2da2c3764645e96dcd55) ) |
| 1203 | | ROM_LOAD16_BYTE( "sc1-ma1l.bin", 0x480001, 0x100000, CRC(8ba3a4ec) SHA1(f881e7b4728f388d18450ba85e13e233071fbc88) ) |
| 1204 | | ROM_LOAD16_BYTE( "sc1-ma1u.bin", 0x480000, 0x100000, CRC(252dc4b7) SHA1(f1be6bd045495c7a0ecd97f01d1dc8ad341fecfd) ) |
| 1183 | ROM_REGION16_BE( 0x800000, "maskrom", 0 ) |
| 1184 | ROM_LOAD16_BYTE( "sc1-ma0l.bin", 0x000001, 0x100000, CRC(3e531f5e) SHA1(6da56630bdfbb19f1639c539779c180d106f6ee2) ) /* 0x400000 */ |
| 1185 | ROM_LOAD16_BYTE( "sc1-ma0u.bin", 0x000000, 0x100000, CRC(31e76a45) SHA1(5c278c167c1025c648ce2da2c3764645e96dcd55) ) |
| 1186 | ROM_LOAD16_BYTE( "sc1-ma1l.bin", 0x200001, 0x100000, CRC(8ba3a4ec) SHA1(f881e7b4728f388d18450ba85e13e233071fbc88) ) |
| 1187 | ROM_LOAD16_BYTE( "sc1-ma1u.bin", 0x200000, 0x100000, CRC(252dc4b7) SHA1(f1be6bd045495c7a0ecd97f01d1dc8ad341fecfd) ) |
| 1205 | 1188 | |
| 1206 | 1189 | /* M37702 BIOS - labeled as Namco custom C69 */ |
| 1207 | 1190 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| r29543 | r29544 | |
| 1209 | 1192 | ROM_END |
| 1210 | 1193 | |
| 1211 | 1194 | ROM_START( tinklpit ) |
| 1212 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1213 | | ROM_LOAD16_BYTE( "tk1-ep0l.bin", 0x080001, 0x080000, CRC(fdccae42) SHA1(398384482ccb3eb08bfb9db495513272a5188d92) ) /* 0xc00000 */ |
| 1214 | | ROM_LOAD16_BYTE( "tk1-ep0u.bin", 0x080000, 0x080000, CRC(62cdb48c) SHA1(73c7b99b117b8dc567bc254b0ffcc117c9d42fb5) ) |
| 1215 | | ROM_LOAD16_BYTE( "tk1-ep1l.bin", 0x180001, 0x080000, CRC(7e90f104) SHA1(79e371426b2e32dc8f687e4d124d23c251198937) ) |
| 1216 | | ROM_LOAD16_BYTE( "tk1-ep1u.bin", 0x180000, 0x080000, CRC(9c0b70d6) SHA1(eac44d3470f4c2ddd9c41f82e6398bca0cc8a4fd) ) |
| 1195 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1196 | ROM_LOAD16_BYTE( "tk1-ep0l.bin", 0x000001, 0x080000, CRC(fdccae42) SHA1(398384482ccb3eb08bfb9db495513272a5188d92) ) /* 0xc00000 */ |
| 1197 | ROM_LOAD16_BYTE( "tk1-ep0u.bin", 0x000000, 0x080000, CRC(62cdb48c) SHA1(73c7b99b117b8dc567bc254b0ffcc117c9d42fb5) ) |
| 1198 | ROM_LOAD16_BYTE( "tk1-ep1l.bin", 0x100001, 0x080000, CRC(7e90f104) SHA1(79e371426b2e32dc8f687e4d124d23c251198937) ) |
| 1199 | ROM_LOAD16_BYTE( "tk1-ep1u.bin", 0x100000, 0x080000, CRC(9c0b70d6) SHA1(eac44d3470f4c2ddd9c41f82e6398bca0cc8a4fd) ) |
| 1217 | 1200 | |
| 1218 | | ROM_LOAD16_BYTE( "tk1-ma0l.bin", 0x280001, 0x100000, CRC(c6b4e15d) SHA1(55252ba4d904b14940436f1b4dc5e2a6bd163bdf) ) /* 0x400000 */ |
| 1219 | | ROM_LOAD16_BYTE( "tk1-ma0u.bin", 0x280000, 0x100000, CRC(a3ad6f67) SHA1(54289eed5347defb5464ec5a610a6748909159f6) ) |
| 1220 | | ROM_LOAD16_BYTE( "tk1-ma1l.bin", 0x480001, 0x100000, CRC(61cfb92a) SHA1(eacf0e7557f33d552045f43a116ff08c533a2771) ) |
| 1221 | | ROM_LOAD16_BYTE( "tk1-ma1u.bin", 0x480000, 0x100000, CRC(54b77816) SHA1(9341d07858623e1920eaae7b2b90126c7057297e) ) |
| 1222 | | ROM_LOAD16_BYTE( "tk1-ma2l.bin", 0x680001, 0x100000, CRC(087311d2) SHA1(6fe50f9e08551e57d15a15b01e3822a6cb7c8352) ) |
| 1223 | | ROM_LOAD16_BYTE( "tk1-ma2u.bin", 0x680000, 0x100000, CRC(5ce20c2c) SHA1(7eaff21714bae44f8b21b6db98f055e04bfbae18) ) |
| 1201 | ROM_REGION16_BE( 0x800000, "maskrom", 0 ) |
| 1202 | ROM_LOAD16_BYTE( "tk1-ma0l.bin", 0x000001, 0x100000, CRC(c6b4e15d) SHA1(55252ba4d904b14940436f1b4dc5e2a6bd163bdf) ) /* 0x400000 */ |
| 1203 | ROM_LOAD16_BYTE( "tk1-ma0u.bin", 0x000000, 0x100000, CRC(a3ad6f67) SHA1(54289eed5347defb5464ec5a610a6748909159f6) ) |
| 1204 | ROM_LOAD16_BYTE( "tk1-ma1l.bin", 0x200001, 0x100000, CRC(61cfb92a) SHA1(eacf0e7557f33d552045f43a116ff08c533a2771) ) |
| 1205 | ROM_LOAD16_BYTE( "tk1-ma1u.bin", 0x200000, 0x100000, CRC(54b77816) SHA1(9341d07858623e1920eaae7b2b90126c7057297e) ) |
| 1206 | ROM_LOAD16_BYTE( "tk1-ma2l.bin", 0x400001, 0x100000, CRC(087311d2) SHA1(6fe50f9e08551e57d15a15b01e3822a6cb7c8352) ) |
| 1207 | ROM_LOAD16_BYTE( "tk1-ma2u.bin", 0x400000, 0x100000, CRC(5ce20c2c) SHA1(7eaff21714bae44f8b21b6db98f055e04bfbae18) ) |
| 1224 | 1208 | |
| 1225 | 1209 | /* M37702 BIOS - labeled as Namco custom C69 */ |
| 1226 | 1210 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| r29543 | r29544 | |
| 1234 | 1218 | |
| 1235 | 1219 | |
| 1236 | 1220 | ROM_START( emeralda ) /* NA-2 Game PCB, clones are NA-1 based; see games listed above */ |
| 1237 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1238 | | ROM_LOAD16_BYTE( "em2-ep0l.6c", 0x080001, 0x080000, CRC(ff1479dc) SHA1(ea945d97ed909be13fb6e062742c7142c0d96c31) ) /* 0xc00000 */ |
| 1239 | | ROM_LOAD16_BYTE( "em2-ep0u.6f", 0x080000, 0x080000, CRC(ffe750a2) SHA1(d10d31489ae364572d7517dd515a6af2182ac764) ) |
| 1240 | | ROM_LOAD16_BYTE( "em2-ep1l.7c", 0x180001, 0x080000, CRC(6c3e5b53) SHA1(72b941e28c7fda8cb81240a8226386fe55c14e2d) ) |
| 1241 | | ROM_LOAD16_BYTE( "em2-ep1u.7f", 0x180000, 0x080000, CRC(dee15a81) SHA1(474a264029bd77e4205773a7461dea695e65933f) ) |
| 1221 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1222 | ROM_LOAD16_BYTE( "em2-ep0l.6c", 0x000001, 0x080000, CRC(ff1479dc) SHA1(ea945d97ed909be13fb6e062742c7142c0d96c31) ) /* 0xc00000 */ |
| 1223 | ROM_LOAD16_BYTE( "em2-ep0u.6f", 0x000000, 0x080000, CRC(ffe750a2) SHA1(d10d31489ae364572d7517dd515a6af2182ac764) ) |
| 1224 | ROM_LOAD16_BYTE( "em2-ep1l.7c", 0x100001, 0x080000, CRC(6c3e5b53) SHA1(72b941e28c7fda8cb81240a8226386fe55c14e2d) ) |
| 1225 | ROM_LOAD16_BYTE( "em2-ep1u.7f", 0x100000, 0x080000, CRC(dee15a81) SHA1(474a264029bd77e4205773a7461dea695e65933f) ) |
| 1242 | 1226 | |
| 1227 | ROM_REGION16_BE( 0x800000, "maskrom", ROMREGION_ERASE00 ) |
| 1228 | /* no mask roms */ |
| 1229 | |
| 1243 | 1230 | /* M37702 BIOS - labeled as Namco custom C70 */ |
| 1244 | 1231 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| 1245 | 1232 | ROM_LOAD( "c70.bin", 0x000000, 0x004000, CRC(b4015f23) SHA1(7ce91eda76e86b5cab625e2b67c463b7d143832e) ) |
| 1246 | 1233 | ROM_END |
| 1247 | 1234 | |
| 1248 | 1235 | ROM_START( knckhead ) |
| 1249 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1250 | | ROM_LOAD16_BYTE( "kh2-ep0l.6c", 0x080001, 0x080000, CRC(b4b88077) SHA1(9af03d1832ad6c77222e18427f4afca330a41ce6) ) /* 0xc00000 */ |
| 1251 | | ROM_LOAD16_BYTE( "kh2-ep0u.6f", 0x080000, 0x080000, CRC(a578d97e) SHA1(9a5bb6649cca7b98daf538a66c813f61cca2e2ec) ) |
| 1252 | | ROM_LOAD16_BYTE( "kh1-ep1l.7c", 0x180001, 0x080000, CRC(27e6ab4e) SHA1(66f397cc2117c1e73652c4800c0937e6d8116380) ) |
| 1253 | | ROM_LOAD16_BYTE( "kh1-ep1u.7f", 0x180000, 0x080000, CRC(487b2434) SHA1(2d62db85ceac1fca61c39e4db92c96ae80ba3323) ) |
| 1236 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1237 | ROM_LOAD16_BYTE( "kh2-ep0l.6c", 0x000001, 0x080000, CRC(b4b88077) SHA1(9af03d1832ad6c77222e18427f4afca330a41ce6) ) /* 0xc00000 */ |
| 1238 | ROM_LOAD16_BYTE( "kh2-ep0u.6f", 0x000000, 0x080000, CRC(a578d97e) SHA1(9a5bb6649cca7b98daf538a66c813f61cca2e2ec) ) |
| 1239 | ROM_LOAD16_BYTE( "kh1-ep1l.7c", 0x100001, 0x080000, CRC(27e6ab4e) SHA1(66f397cc2117c1e73652c4800c0937e6d8116380) ) |
| 1240 | ROM_LOAD16_BYTE( "kh1-ep1u.7f", 0x100000, 0x080000, CRC(487b2434) SHA1(2d62db85ceac1fca61c39e4db92c96ae80ba3323) ) |
| 1254 | 1241 | |
| 1255 | | ROM_LOAD16_BYTE( "kh1-ma0l.2c", 0x280001, 0x100000, CRC(7b2db5df) SHA1(ecc392c4683cf0718d986e73336b69952d324548) ) /* 0x400000 */ |
| 1256 | | ROM_LOAD16_BYTE( "kh1-ma0u.2f", 0x280000, 0x100000, CRC(6983228b) SHA1(5f3eeb780e9d91445b4c11da63d4ca580e654f34) ) |
| 1257 | | ROM_LOAD16_BYTE( "kh1-ma1l.3c", 0x480001, 0x100000, CRC(b24f93e6) SHA1(3d8951485dc8a2810da9ddf2f4896efa31779bf4) ) |
| 1258 | | ROM_LOAD16_BYTE( "kh1-ma1u.3f", 0x480000, 0x100000, CRC(18a60348) SHA1(298e0e0e7649e872791c3c99c81a19f273e9eb8a) ) |
| 1259 | | ROM_LOAD16_BYTE( "kh1-ma2l.4c", 0x680001, 0x100000, CRC(82064ee9) SHA1(0b984565d17e580f49fff982a1621ef90e14c064) ) |
| 1260 | | ROM_LOAD16_BYTE( "kh1-ma2u.4f", 0x680000, 0x100000, CRC(17fe8c3d) SHA1(88c45076477725faa5f8a23512e65a40385bb27d) ) |
| 1261 | | ROM_LOAD16_BYTE( "kh1-ma3l.5c", 0x880001, 0x100000, CRC(ad9a7807) SHA1(c40f18a68306e76acd89ccb3fc82b8106556912e) ) |
| 1262 | | ROM_LOAD16_BYTE( "kh1-ma3u.5f", 0x880000, 0x100000, CRC(efeb768d) SHA1(15d016244549f3ea0d19f5cfb04bcebd65ac6134) ) |
| 1242 | ROM_REGION16_BE( 0x800000, "maskrom", 0 ) |
| 1243 | ROM_LOAD16_BYTE( "kh1-ma0l.2c", 0x000001, 0x100000, CRC(7b2db5df) SHA1(ecc392c4683cf0718d986e73336b69952d324548) ) /* 0x400000 */ |
| 1244 | ROM_LOAD16_BYTE( "kh1-ma0u.2f", 0x000000, 0x100000, CRC(6983228b) SHA1(5f3eeb780e9d91445b4c11da63d4ca580e654f34) ) |
| 1245 | ROM_LOAD16_BYTE( "kh1-ma1l.3c", 0x200001, 0x100000, CRC(b24f93e6) SHA1(3d8951485dc8a2810da9ddf2f4896efa31779bf4) ) |
| 1246 | ROM_LOAD16_BYTE( "kh1-ma1u.3f", 0x200000, 0x100000, CRC(18a60348) SHA1(298e0e0e7649e872791c3c99c81a19f273e9eb8a) ) |
| 1247 | ROM_LOAD16_BYTE( "kh1-ma2l.4c", 0x400001, 0x100000, CRC(82064ee9) SHA1(0b984565d17e580f49fff982a1621ef90e14c064) ) |
| 1248 | ROM_LOAD16_BYTE( "kh1-ma2u.4f", 0x400000, 0x100000, CRC(17fe8c3d) SHA1(88c45076477725faa5f8a23512e65a40385bb27d) ) |
| 1249 | ROM_LOAD16_BYTE( "kh1-ma3l.5c", 0x600001, 0x100000, CRC(ad9a7807) SHA1(c40f18a68306e76acd89ccb3fc82b8106556912e) ) |
| 1250 | ROM_LOAD16_BYTE( "kh1-ma3u.5f", 0x600000, 0x100000, CRC(efeb768d) SHA1(15d016244549f3ea0d19f5cfb04bcebd65ac6134) ) |
| 1263 | 1251 | |
| 1264 | 1252 | /* M37702 BIOS - labeled as Namco custom C70 */ |
| 1265 | 1253 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| r29543 | r29544 | |
| 1267 | 1255 | ROM_END |
| 1268 | 1256 | |
| 1269 | 1257 | ROM_START( knckheadj ) |
| 1270 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1271 | | ROM_LOAD16_BYTE( "kh1-ep0l.6c", 0x080001, 0x080000, CRC(94660bec) SHA1(42fa23f759cf66b05f30c2fc03a12fd14ae1f796) ) /* 0xc00000 */ |
| 1272 | | ROM_LOAD16_BYTE( "kh1-ep0u.6f", 0x080000, 0x080000, CRC(ad640d69) SHA1(62595a9d1d5952cbe3dd7266cfda9292be51d269) ) |
| 1273 | | ROM_LOAD16_BYTE( "kh1-ep1l.7c", 0x180001, 0x080000, CRC(27e6ab4e) SHA1(66f397cc2117c1e73652c4800c0937e6d8116380) ) |
| 1274 | | ROM_LOAD16_BYTE( "kh1-ep1u.7f", 0x180000, 0x080000, CRC(487b2434) SHA1(2d62db85ceac1fca61c39e4db92c96ae80ba3323) ) |
| 1258 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1259 | ROM_LOAD16_BYTE( "kh1-ep0l.6c", 0x000001, 0x080000, CRC(94660bec) SHA1(42fa23f759cf66b05f30c2fc03a12fd14ae1f796) ) /* 0xc00000 */ |
| 1260 | ROM_LOAD16_BYTE( "kh1-ep0u.6f", 0x000000, 0x080000, CRC(ad640d69) SHA1(62595a9d1d5952cbe3dd7266cfda9292be51d269) ) |
| 1261 | ROM_LOAD16_BYTE( "kh1-ep1l.7c", 0x100001, 0x080000, CRC(27e6ab4e) SHA1(66f397cc2117c1e73652c4800c0937e6d8116380) ) |
| 1262 | ROM_LOAD16_BYTE( "kh1-ep1u.7f", 0x100000, 0x080000, CRC(487b2434) SHA1(2d62db85ceac1fca61c39e4db92c96ae80ba3323) ) |
| 1275 | 1263 | |
| 1276 | | ROM_LOAD16_BYTE( "kh1-ma0l.2c", 0x280001, 0x100000, CRC(7b2db5df) SHA1(ecc392c4683cf0718d986e73336b69952d324548) ) /* 0x400000 */ |
| 1277 | | ROM_LOAD16_BYTE( "kh1-ma0u.2f", 0x280000, 0x100000, CRC(6983228b) SHA1(5f3eeb780e9d91445b4c11da63d4ca580e654f34) ) |
| 1278 | | ROM_LOAD16_BYTE( "kh1-ma1l.3c", 0x480001, 0x100000, CRC(b24f93e6) SHA1(3d8951485dc8a2810da9ddf2f4896efa31779bf4) ) |
| 1279 | | ROM_LOAD16_BYTE( "kh1-ma1u.3f", 0x480000, 0x100000, CRC(18a60348) SHA1(298e0e0e7649e872791c3c99c81a19f273e9eb8a) ) |
| 1280 | | ROM_LOAD16_BYTE( "kh1-ma2l.4c", 0x680001, 0x100000, CRC(82064ee9) SHA1(0b984565d17e580f49fff982a1621ef90e14c064) ) |
| 1281 | | ROM_LOAD16_BYTE( "kh1-ma2u.4f", 0x680000, 0x100000, CRC(17fe8c3d) SHA1(88c45076477725faa5f8a23512e65a40385bb27d) ) |
| 1282 | | ROM_LOAD16_BYTE( "kh1-ma3l.5c", 0x880001, 0x100000, CRC(ad9a7807) SHA1(c40f18a68306e76acd89ccb3fc82b8106556912e) ) |
| 1283 | | ROM_LOAD16_BYTE( "kh1-ma3u.5f", 0x880000, 0x100000, CRC(efeb768d) SHA1(15d016244549f3ea0d19f5cfb04bcebd65ac6134) ) |
| 1264 | ROM_REGION16_BE( 0x800000, "maskrom", 0 ) |
| 1265 | ROM_LOAD16_BYTE( "kh1-ma0l.2c", 0x000001, 0x100000, CRC(7b2db5df) SHA1(ecc392c4683cf0718d986e73336b69952d324548) ) /* 0x400000 */ |
| 1266 | ROM_LOAD16_BYTE( "kh1-ma0u.2f", 0x000000, 0x100000, CRC(6983228b) SHA1(5f3eeb780e9d91445b4c11da63d4ca580e654f34) ) |
| 1267 | ROM_LOAD16_BYTE( "kh1-ma1l.3c", 0x200001, 0x100000, CRC(b24f93e6) SHA1(3d8951485dc8a2810da9ddf2f4896efa31779bf4) ) |
| 1268 | ROM_LOAD16_BYTE( "kh1-ma1u.3f", 0x200000, 0x100000, CRC(18a60348) SHA1(298e0e0e7649e872791c3c99c81a19f273e9eb8a) ) |
| 1269 | ROM_LOAD16_BYTE( "kh1-ma2l.4c", 0x400001, 0x100000, CRC(82064ee9) SHA1(0b984565d17e580f49fff982a1621ef90e14c064) ) |
| 1270 | ROM_LOAD16_BYTE( "kh1-ma2u.4f", 0x400000, 0x100000, CRC(17fe8c3d) SHA1(88c45076477725faa5f8a23512e65a40385bb27d) ) |
| 1271 | ROM_LOAD16_BYTE( "kh1-ma3l.5c", 0x600001, 0x100000, CRC(ad9a7807) SHA1(c40f18a68306e76acd89ccb3fc82b8106556912e) ) |
| 1272 | ROM_LOAD16_BYTE( "kh1-ma3u.5f", 0x600000, 0x100000, CRC(efeb768d) SHA1(15d016244549f3ea0d19f5cfb04bcebd65ac6134) ) |
| 1284 | 1273 | |
| 1285 | 1274 | /* M37702 BIOS - labeled as Namco custom C70 */ |
| 1286 | 1275 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| r29543 | r29544 | |
| 1288 | 1277 | ROM_END |
| 1289 | 1278 | |
| 1290 | 1279 | ROM_START( knckheadjp ) /* Older or possible prototype. Doesn't show rom test at boot up */ |
| 1291 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1292 | | ROM_LOAD16_BYTE( "2-10_9o.6c", 0x080001, 0x080000, CRC(600faf17) SHA1(21197ad1d54a68c1510d9ae6999ca41efaaed05d) ) /* handwritten label 2/10 9O */ /* 0xc00000 */ |
| 1293 | | ROM_LOAD16_BYTE( "2-10_9e.6f", 0x080000, 0x080000, CRC(16ccc0b0) SHA1(e9b98eae7ee47c7cce2cc3de9dc39428e0648a40) ) /* handwritten label 2/10 9E */ |
| 1294 | | ROM_LOAD16_BYTE( "2-10_8o.7c", 0x180001, 0x080000, CRC(27e6ab4e) SHA1(66f397cc2117c1e73652c4800c0937e6d8116380) ) /* handwritten label 2/10 8O */ |
| 1295 | | ROM_LOAD16_BYTE( "2-10_8e.7f", 0x180000, 0x080000, CRC(487b2434) SHA1(2d62db85ceac1fca61c39e4db92c96ae80ba3323) ) /* handwritten label 2/10 8E */ |
| 1280 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1281 | ROM_LOAD16_BYTE( "2-10_9o.6c", 0x000001, 0x080000, CRC(600faf17) SHA1(21197ad1d54a68c1510d9ae6999ca41efaaed05d) ) /* handwritten label 2/10 9O */ /* 0xc00000 */ |
| 1282 | ROM_LOAD16_BYTE( "2-10_9e.6f", 0x000000, 0x080000, CRC(16ccc0b0) SHA1(e9b98eae7ee47c7cce2cc3de9dc39428e0648a40) ) /* handwritten label 2/10 9E */ |
| 1283 | ROM_LOAD16_BYTE( "2-10_8o.7c", 0x100001, 0x080000, CRC(27e6ab4e) SHA1(66f397cc2117c1e73652c4800c0937e6d8116380) ) /* handwritten label 2/10 8O */ |
| 1284 | ROM_LOAD16_BYTE( "2-10_8e.7f", 0x100000, 0x080000, CRC(487b2434) SHA1(2d62db85ceac1fca61c39e4db92c96ae80ba3323) ) /* handwritten label 2/10 8E */ |
| 1296 | 1285 | |
| 1297 | | ROM_LOAD16_BYTE( "kh1-ma0l.2c", 0x280001, 0x100000, CRC(7b2db5df) SHA1(ecc392c4683cf0718d986e73336b69952d324548) ) /* 0x400000 */ |
| 1298 | | ROM_LOAD16_BYTE( "kh1-ma0u.2f", 0x280000, 0x100000, CRC(6983228b) SHA1(5f3eeb780e9d91445b4c11da63d4ca580e654f34) ) |
| 1299 | | ROM_LOAD16_BYTE( "kh1-ma1l.3c", 0x480001, 0x100000, CRC(b24f93e6) SHA1(3d8951485dc8a2810da9ddf2f4896efa31779bf4) ) |
| 1300 | | ROM_LOAD16_BYTE( "kh1-ma1u.3f", 0x480000, 0x100000, CRC(18a60348) SHA1(298e0e0e7649e872791c3c99c81a19f273e9eb8a) ) |
| 1301 | | ROM_LOAD16_BYTE( "kh1-ma2l.4c", 0x680001, 0x100000, CRC(82064ee9) SHA1(0b984565d17e580f49fff982a1621ef90e14c064) ) |
| 1302 | | ROM_LOAD16_BYTE( "kh1-ma2u.4f", 0x680000, 0x100000, CRC(17fe8c3d) SHA1(88c45076477725faa5f8a23512e65a40385bb27d) ) |
| 1303 | | ROM_LOAD16_BYTE( "kh1-ma3l.5c", 0x880001, 0x100000, CRC(ad9a7807) SHA1(c40f18a68306e76acd89ccb3fc82b8106556912e) ) |
| 1304 | | ROM_LOAD16_BYTE( "kh1-ma3u.5f", 0x880000, 0x100000, CRC(efeb768d) SHA1(15d016244549f3ea0d19f5cfb04bcebd65ac6134) ) |
| 1286 | ROM_REGION16_BE( 0x800000, "maskrom", 0 ) |
| 1287 | ROM_LOAD16_BYTE( "kh1-ma0l.2c", 0x000001, 0x100000, CRC(7b2db5df) SHA1(ecc392c4683cf0718d986e73336b69952d324548) ) /* 0x400000 */ |
| 1288 | ROM_LOAD16_BYTE( "kh1-ma0u.2f", 0x000000, 0x100000, CRC(6983228b) SHA1(5f3eeb780e9d91445b4c11da63d4ca580e654f34) ) |
| 1289 | ROM_LOAD16_BYTE( "kh1-ma1l.3c", 0x200001, 0x100000, CRC(b24f93e6) SHA1(3d8951485dc8a2810da9ddf2f4896efa31779bf4) ) |
| 1290 | ROM_LOAD16_BYTE( "kh1-ma1u.3f", 0x200000, 0x100000, CRC(18a60348) SHA1(298e0e0e7649e872791c3c99c81a19f273e9eb8a) ) |
| 1291 | ROM_LOAD16_BYTE( "kh1-ma2l.4c", 0x400001, 0x100000, CRC(82064ee9) SHA1(0b984565d17e580f49fff982a1621ef90e14c064) ) |
| 1292 | ROM_LOAD16_BYTE( "kh1-ma2u.4f", 0x400000, 0x100000, CRC(17fe8c3d) SHA1(88c45076477725faa5f8a23512e65a40385bb27d) ) |
| 1293 | ROM_LOAD16_BYTE( "kh1-ma3l.5c", 0x600001, 0x100000, CRC(ad9a7807) SHA1(c40f18a68306e76acd89ccb3fc82b8106556912e) ) |
| 1294 | ROM_LOAD16_BYTE( "kh1-ma3u.5f", 0x600000, 0x100000, CRC(efeb768d) SHA1(15d016244549f3ea0d19f5cfb04bcebd65ac6134) ) |
| 1305 | 1295 | |
| 1306 | 1296 | /* M37702 BIOS - labeled as Namco custom C70 */ |
| 1307 | 1297 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| r29543 | r29544 | |
| 1312 | 1302 | ROM_END |
| 1313 | 1303 | |
| 1314 | 1304 | ROM_START( numanath ) |
| 1315 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1316 | | ROM_LOAD16_BYTE( "nm2-ep0l.bin", 0x080001, 0x080000, CRC(f24414bb) SHA1(68b13dfdc2292afd5279edb891fe63972f991e7b) ) /* 0xc00000 */ |
| 1317 | | ROM_LOAD16_BYTE( "nm2-ep0u.bin", 0x080000, 0x080000, CRC(25c41616) SHA1(68ba67d3dd45f3bdddfa2fd21b574535306c1214) ) |
| 1318 | | ROM_LOAD16_BYTE( "nm1-ep1l.bin", 0x180001, 0x080000, CRC(4581dcb4) SHA1(1f46f98e63a7c9cdfde9e8ee2696a13c3f9bcc8e) ) |
| 1319 | | ROM_LOAD16_BYTE( "nm1-ep1u.bin", 0x180000, 0x080000, CRC(30cd589a) SHA1(74a14ec41fe4fc9f73e5357b0903f1199ed96337) ) |
| 1305 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1306 | ROM_LOAD16_BYTE( "nm2-ep0l.bin", 0x000001, 0x080000, CRC(f24414bb) SHA1(68b13dfdc2292afd5279edb891fe63972f991e7b) ) /* 0xc00000 */ |
| 1307 | ROM_LOAD16_BYTE( "nm2-ep0u.bin", 0x000000, 0x080000, CRC(25c41616) SHA1(68ba67d3dd45f3bdddfa2fd21b574535306c1214) ) |
| 1308 | ROM_LOAD16_BYTE( "nm1-ep1l.bin", 0x100001, 0x080000, CRC(4581dcb4) SHA1(1f46f98e63a7c9cdfde9e8ee2696a13c3f9bcc8e) ) |
| 1309 | ROM_LOAD16_BYTE( "nm1-ep1u.bin", 0x100000, 0x080000, CRC(30cd589a) SHA1(74a14ec41fe4fc9f73e5357b0903f1199ed96337) ) |
| 1320 | 1310 | |
| 1321 | | ROM_LOAD16_BYTE( "nm1-ma0l.bin", 0x280001, 0x100000, CRC(20faaa57) SHA1(9dbfc0dd48eec37b2c0715a5691c6e6f923fc7f7) ) /* 0x400000 */ |
| 1322 | | ROM_LOAD16_BYTE( "nm1-ma0u.bin", 0x280000, 0x100000, CRC(ed7c37f2) SHA1(829751af33754ade941f76982e196b494d56ab0a) ) |
| 1323 | | ROM_LOAD16_BYTE( "nm1-ma1l.bin", 0x480001, 0x100000, CRC(2232e3b4) SHA1(e9da3dc34eb2576c8a88e23cb9007129e885496d) ) |
| 1324 | | ROM_LOAD16_BYTE( "nm1-ma1u.bin", 0x480000, 0x100000, CRC(6cc9675c) SHA1(fec74da4479f2a088760efc6908e6acfaea3989f) ) |
| 1325 | | ROM_LOAD16_BYTE( "nm1-ma2l.bin", 0x680001, 0x100000, CRC(208abb39) SHA1(52d7247a71c6a14467f12f5270921bba1824cc3f) ) |
| 1326 | | ROM_LOAD16_BYTE( "nm1-ma2u.bin", 0x680000, 0x100000, CRC(03a3f204) SHA1(9cb0422c8ecc819d0cc8a65c29a228369d78d986) ) |
| 1327 | | ROM_LOAD16_BYTE( "nm1-ma3l.bin", 0x880001, 0x100000, CRC(42a539e9) SHA1(1c53a5a031648891ab7a37cf026c979404ce9589) ) |
| 1328 | | ROM_LOAD16_BYTE( "nm1-ma3u.bin", 0x880000, 0x100000, CRC(f79e2112) SHA1(8bb8639a9d3a5d3ac5c9bb78e72b3d76582a9c25) ) |
| 1311 | ROM_REGION16_BE( 0x800000, "maskrom", 0 ) |
| 1312 | ROM_LOAD16_BYTE( "nm1-ma0l.bin", 0x000001, 0x100000, CRC(20faaa57) SHA1(9dbfc0dd48eec37b2c0715a5691c6e6f923fc7f7) ) /* 0x400000 */ |
| 1313 | ROM_LOAD16_BYTE( "nm1-ma0u.bin", 0x000000, 0x100000, CRC(ed7c37f2) SHA1(829751af33754ade941f76982e196b494d56ab0a) ) |
| 1314 | ROM_LOAD16_BYTE( "nm1-ma1l.bin", 0x200001, 0x100000, CRC(2232e3b4) SHA1(e9da3dc34eb2576c8a88e23cb9007129e885496d) ) |
| 1315 | ROM_LOAD16_BYTE( "nm1-ma1u.bin", 0x200000, 0x100000, CRC(6cc9675c) SHA1(fec74da4479f2a088760efc6908e6acfaea3989f) ) |
| 1316 | ROM_LOAD16_BYTE( "nm1-ma2l.bin", 0x400001, 0x100000, CRC(208abb39) SHA1(52d7247a71c6a14467f12f5270921bba1824cc3f) ) |
| 1317 | ROM_LOAD16_BYTE( "nm1-ma2u.bin", 0x400000, 0x100000, CRC(03a3f204) SHA1(9cb0422c8ecc819d0cc8a65c29a228369d78d986) ) |
| 1318 | ROM_LOAD16_BYTE( "nm1-ma3l.bin", 0x600001, 0x100000, CRC(42a539e9) SHA1(1c53a5a031648891ab7a37cf026c979404ce9589) ) |
| 1319 | ROM_LOAD16_BYTE( "nm1-ma3u.bin", 0x600000, 0x100000, CRC(f79e2112) SHA1(8bb8639a9d3a5d3ac5c9bb78e72b3d76582a9c25) ) |
| 1329 | 1320 | |
| 1330 | 1321 | /* M37702 BIOS - labeled as Namco custom C70 */ |
| 1331 | 1322 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| r29543 | r29544 | |
| 1333 | 1324 | ROM_END |
| 1334 | 1325 | |
| 1335 | 1326 | ROM_START( numanathj ) |
| 1336 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1337 | | ROM_LOAD16_BYTE( "nm1-ep0l.bin", 0x080001, 0x080000, CRC(4398b898) SHA1(0d1517409ba181f796f7f413cac704c60085b505) ) /* 0xc00000 */ |
| 1338 | | ROM_LOAD16_BYTE( "nm1-ep0u.bin", 0x080000, 0x080000, CRC(be90aa79) SHA1(6884a8d72dd34c889527e8e653f5e5b4cf3fb5d6) ) |
| 1339 | | ROM_LOAD16_BYTE( "nm1-ep1l.bin", 0x180001, 0x080000, CRC(4581dcb4) SHA1(1f46f98e63a7c9cdfde9e8ee2696a13c3f9bcc8e) ) |
| 1340 | | ROM_LOAD16_BYTE( "nm1-ep1u.bin", 0x180000, 0x080000, CRC(30cd589a) SHA1(74a14ec41fe4fc9f73e5357b0903f1199ed96337) ) |
| 1327 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1328 | ROM_LOAD16_BYTE( "nm1-ep0l.bin", 0x000001, 0x080000, CRC(4398b898) SHA1(0d1517409ba181f796f7f413cac704c60085b505) ) /* 0xc00000 */ |
| 1329 | ROM_LOAD16_BYTE( "nm1-ep0u.bin", 0x000000, 0x080000, CRC(be90aa79) SHA1(6884a8d72dd34c889527e8e653f5e5b4cf3fb5d6) ) |
| 1330 | ROM_LOAD16_BYTE( "nm1-ep1l.bin", 0x100001, 0x080000, CRC(4581dcb4) SHA1(1f46f98e63a7c9cdfde9e8ee2696a13c3f9bcc8e) ) |
| 1331 | ROM_LOAD16_BYTE( "nm1-ep1u.bin", 0x100000, 0x080000, CRC(30cd589a) SHA1(74a14ec41fe4fc9f73e5357b0903f1199ed96337) ) |
| 1341 | 1332 | |
| 1342 | | ROM_LOAD16_BYTE( "nm1-ma0l.bin", 0x280001, 0x100000, CRC(20faaa57) SHA1(9dbfc0dd48eec37b2c0715a5691c6e6f923fc7f7) ) /* 0x400000 */ |
| 1343 | | ROM_LOAD16_BYTE( "nm1-ma0u.bin", 0x280000, 0x100000, CRC(ed7c37f2) SHA1(829751af33754ade941f76982e196b494d56ab0a) ) |
| 1344 | | ROM_LOAD16_BYTE( "nm1-ma1l.bin", 0x480001, 0x100000, CRC(2232e3b4) SHA1(e9da3dc34eb2576c8a88e23cb9007129e885496d) ) |
| 1345 | | ROM_LOAD16_BYTE( "nm1-ma1u.bin", 0x480000, 0x100000, CRC(6cc9675c) SHA1(fec74da4479f2a088760efc6908e6acfaea3989f) ) |
| 1346 | | ROM_LOAD16_BYTE( "nm1-ma2l.bin", 0x680001, 0x100000, CRC(208abb39) SHA1(52d7247a71c6a14467f12f5270921bba1824cc3f) ) |
| 1347 | | ROM_LOAD16_BYTE( "nm1-ma2u.bin", 0x680000, 0x100000, CRC(03a3f204) SHA1(9cb0422c8ecc819d0cc8a65c29a228369d78d986) ) |
| 1348 | | ROM_LOAD16_BYTE( "nm1-ma3l.bin", 0x880001, 0x100000, CRC(42a539e9) SHA1(1c53a5a031648891ab7a37cf026c979404ce9589) ) |
| 1349 | | ROM_LOAD16_BYTE( "nm1-ma3u.bin", 0x880000, 0x100000, CRC(f79e2112) SHA1(8bb8639a9d3a5d3ac5c9bb78e72b3d76582a9c25) ) |
| 1333 | ROM_REGION16_BE( 0x800000, "maskrom", 0 ) |
| 1334 | ROM_LOAD16_BYTE( "nm1-ma0l.bin", 0x000001, 0x100000, CRC(20faaa57) SHA1(9dbfc0dd48eec37b2c0715a5691c6e6f923fc7f7) ) /* 0x400000 */ |
| 1335 | ROM_LOAD16_BYTE( "nm1-ma0u.bin", 0x000000, 0x100000, CRC(ed7c37f2) SHA1(829751af33754ade941f76982e196b494d56ab0a) ) |
| 1336 | ROM_LOAD16_BYTE( "nm1-ma1l.bin", 0x200001, 0x100000, CRC(2232e3b4) SHA1(e9da3dc34eb2576c8a88e23cb9007129e885496d) ) |
| 1337 | ROM_LOAD16_BYTE( "nm1-ma1u.bin", 0x200000, 0x100000, CRC(6cc9675c) SHA1(fec74da4479f2a088760efc6908e6acfaea3989f) ) |
| 1338 | ROM_LOAD16_BYTE( "nm1-ma2l.bin", 0x400001, 0x100000, CRC(208abb39) SHA1(52d7247a71c6a14467f12f5270921bba1824cc3f) ) |
| 1339 | ROM_LOAD16_BYTE( "nm1-ma2u.bin", 0x400000, 0x100000, CRC(03a3f204) SHA1(9cb0422c8ecc819d0cc8a65c29a228369d78d986) ) |
| 1340 | ROM_LOAD16_BYTE( "nm1-ma3l.bin", 0x600001, 0x100000, CRC(42a539e9) SHA1(1c53a5a031648891ab7a37cf026c979404ce9589) ) |
| 1341 | ROM_LOAD16_BYTE( "nm1-ma3u.bin", 0x600000, 0x100000, CRC(f79e2112) SHA1(8bb8639a9d3a5d3ac5c9bb78e72b3d76582a9c25) ) |
| 1350 | 1342 | |
| 1351 | 1343 | /* M37702 BIOS - labeled as Namco custom C70 */ |
| 1352 | 1344 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| r29543 | r29544 | |
| 1354 | 1346 | ROM_END |
| 1355 | 1347 | |
| 1356 | 1348 | ROM_START( quiztou ) |
| 1357 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1358 | | ROM_LOAD16_BYTE( "qt1ep0l.6c", 0x080001, 0x080000, CRC(b680e543) SHA1(f10f38113a46c821d8e9d66f52d7311d9d52e595) ) /* 0xc00000 */ |
| 1359 | | ROM_LOAD16_BYTE( "qt1ep0u.6f", 0x080000, 0x080000, CRC(143c5e4d) SHA1(24c584986c97a5e6fe7e73f0e9af4af28ed20c4a) ) |
| 1360 | | ROM_LOAD16_BYTE( "qt1ep1l.7c", 0x180001, 0x080000, CRC(33a72242) SHA1(5d17f033878d28dbebba50931a549ccf84802c05) ) |
| 1361 | | ROM_LOAD16_BYTE( "qt1ep1u.7f", 0x180000, 0x080000, CRC(69f876cb) SHA1(d0c7e972a04c45d3ab34ef5be88614d6389189c6) ) |
| 1349 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1350 | ROM_LOAD16_BYTE( "qt1ep0l.6c", 0x000001, 0x080000, CRC(b680e543) SHA1(f10f38113a46c821d8e9d66f52d7311d9d52e595) ) /* 0xc00000 */ |
| 1351 | ROM_LOAD16_BYTE( "qt1ep0u.6f", 0x000000, 0x080000, CRC(143c5e4d) SHA1(24c584986c97a5e6fe7e73f0e9af4af28ed20c4a) ) |
| 1352 | ROM_LOAD16_BYTE( "qt1ep1l.7c", 0x100001, 0x080000, CRC(33a72242) SHA1(5d17f033878d28dbebba50931a549ccf84802c05) ) |
| 1353 | ROM_LOAD16_BYTE( "qt1ep1u.7f", 0x100000, 0x080000, CRC(69f876cb) SHA1(d0c7e972a04c45d3ab34ef5be88614d6389189c6) ) |
| 1362 | 1354 | |
| 1363 | | ROM_LOAD16_BYTE( "qt1ma0l.2c", 0x280001, 0x100000, CRC(5597f2b9) SHA1(747c4be867d4eb37ffab8303740729686a00b825) ) /* 0x400000 */ |
| 1364 | | ROM_LOAD16_BYTE( "qt1ma0u.2f", 0x280000, 0x100000, CRC(f0a4cb7d) SHA1(364e85af956e7cfc29c957da11574a4b389f7797) ) |
| 1365 | | ROM_LOAD16_BYTE( "qt1ma1l.3c", 0x480001, 0x100000, CRC(1b9ce7a6) SHA1(dac1da9dd8076f238211fed5c780b4b8bededf22) ) |
| 1366 | | ROM_LOAD16_BYTE( "qt1ma1u.3f", 0x480000, 0x100000, CRC(58910872) SHA1(c0acbd64e90672564c3839fd21870672aa32e439) ) |
| 1367 | | ROM_LOAD16_BYTE( "qt1ma2l.4c", 0x680001, 0x100000, CRC(94739917) SHA1(b5be5c9fd7223d3fb601f769cb80f56a5a586de0) ) |
| 1368 | | ROM_LOAD16_BYTE( "qt1ma2u.4f", 0x680000, 0x100000, CRC(6ba5b893) SHA1(071caed9cf261f1f8af7079875bd206177baef1a) ) |
| 1369 | | ROM_LOAD16_BYTE( "qt1ma3l.5c", 0x880001, 0x100000, CRC(aa9dc6ff) SHA1(c738f8c59bb5245874576c5bcf88c7138fa9a147) ) |
| 1370 | | ROM_LOAD16_BYTE( "qt1ma3u.5f", 0x880000, 0x100000, CRC(14a5a163) SHA1(1107f50e491bedeb4ab7ac3f32cfe47727274ba9) ) |
| 1355 | ROM_REGION16_BE( 0x800000, "maskrom", 0 ) |
| 1356 | ROM_LOAD16_BYTE( "qt1ma0l.2c", 0x000001, 0x100000, CRC(5597f2b9) SHA1(747c4be867d4eb37ffab8303740729686a00b825) ) /* 0x400000 */ |
| 1357 | ROM_LOAD16_BYTE( "qt1ma0u.2f", 0x000000, 0x100000, CRC(f0a4cb7d) SHA1(364e85af956e7cfc29c957da11574a4b389f7797) ) |
| 1358 | ROM_LOAD16_BYTE( "qt1ma1l.3c", 0x200001, 0x100000, CRC(1b9ce7a6) SHA1(dac1da9dd8076f238211fed5c780b4b8bededf22) ) |
| 1359 | ROM_LOAD16_BYTE( "qt1ma1u.3f", 0x200000, 0x100000, CRC(58910872) SHA1(c0acbd64e90672564c3839fd21870672aa32e439) ) |
| 1360 | ROM_LOAD16_BYTE( "qt1ma2l.4c", 0x400001, 0x100000, CRC(94739917) SHA1(b5be5c9fd7223d3fb601f769cb80f56a5a586de0) ) |
| 1361 | ROM_LOAD16_BYTE( "qt1ma2u.4f", 0x400000, 0x100000, CRC(6ba5b893) SHA1(071caed9cf261f1f8af7079875bd206177baef1a) ) |
| 1362 | ROM_LOAD16_BYTE( "qt1ma3l.5c", 0x600001, 0x100000, CRC(aa9dc6ff) SHA1(c738f8c59bb5245874576c5bcf88c7138fa9a147) ) |
| 1363 | ROM_LOAD16_BYTE( "qt1ma3u.5f", 0x600000, 0x100000, CRC(14a5a163) SHA1(1107f50e491bedeb4ab7ac3f32cfe47727274ba9) ) |
| 1371 | 1364 | |
| 1372 | 1365 | /* M37702 BIOS - labeled as Namco custom C70 */ |
| 1373 | 1366 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
| r29543 | r29544 | |
| 1378 | 1371 | ROM_END |
| 1379 | 1372 | |
| 1380 | 1373 | ROM_START( xday2 ) |
| 1381 | | ROM_REGION( 0xa80000, "maincpu", 0 ) |
| 1382 | | ROM_LOAD16_BYTE( "xds1-mpr0.4b", 0x080001, 0x080000, CRC(83539aaa) SHA1(42d97bb2daaf5ff48efac70f0ff37869c5ba177d) ) /* 0xc00000 */ |
| 1383 | | ROM_LOAD16_BYTE( "xds1-mpr1.8b", 0x080000, 0x080000, CRC(468b36de) SHA1(52817be9913a6938ce6add2834ba1a727b1d677e) ) |
| 1374 | ROM_REGION( 0x200000, "maincpu", 0 ) |
| 1375 | ROM_LOAD16_BYTE( "xds1-mpr0.4b", 0x000001, 0x080000, CRC(83539aaa) SHA1(42d97bb2daaf5ff48efac70f0ff37869c5ba177d) ) /* 0xc00000 */ |
| 1376 | ROM_LOAD16_BYTE( "xds1-mpr1.8b", 0x000000, 0x080000, CRC(468b36de) SHA1(52817be9913a6938ce6add2834ba1a727b1d677e) ) |
| 1384 | 1377 | |
| 1385 | | ROM_LOAD16_BYTE( "xds1-dat0.4b", 0x280001, 0x200000, CRC(42cecc8b) SHA1(7510f16b908dd0f7828887dcfa26c5e4643df66c) ) /* 0x400000 */ |
| 1386 | | ROM_LOAD16_BYTE( "xds1-dat1.8b", 0x280000, 0x200000, CRC(d250b7e8) SHA1(b99251ae8e25fae062d33e74ff800ab43fb308a2) ) |
| 1387 | | ROM_LOAD16_BYTE( "xds1-dat2.4c", 0x680001, 0x200000, CRC(99d72a08) SHA1(4615b43b9a81240ffee8b0f021037f554f4f1f24) ) |
| 1388 | | ROM_LOAD16_BYTE( "xds1-dat3.8c", 0x680000, 0x200000, CRC(8980acc4) SHA1(ecd94a3d3a38923e8e322cd8863671af26e30812) ) |
| 1378 | ROM_REGION16_BE( 0x800000, "maskrom", 0 ) |
| 1379 | ROM_LOAD16_BYTE( "xds1-dat0.4b", 0x000001, 0x200000, CRC(42cecc8b) SHA1(7510f16b908dd0f7828887dcfa26c5e4643df66c) ) /* 0x400000 */ |
| 1380 | ROM_LOAD16_BYTE( "xds1-dat1.8b", 0x000000, 0x200000, CRC(d250b7e8) SHA1(b99251ae8e25fae062d33e74ff800ab43fb308a2) ) |
| 1381 | ROM_LOAD16_BYTE( "xds1-dat2.4c", 0x400001, 0x200000, CRC(99d72a08) SHA1(4615b43b9a81240ffee8b0f021037f554f4f1f24) ) |
| 1382 | ROM_LOAD16_BYTE( "xds1-dat3.8c", 0x400000, 0x200000, CRC(8980acc4) SHA1(ecd94a3d3a38923e8e322cd8863671af26e30812) ) |
| 1389 | 1383 | |
| 1390 | 1384 | /* M37702 BIOS - labeled as Namco custom C70 */ |
| 1391 | 1385 | ROM_REGION16_LE( 0x4000, "mcu", 0 ) |
branches/new_menus/src/mame/drivers/peplus.c
| r29543 | r29544 | |
| 162 | 162 | illustration purposes and to archive the sets. |
| 163 | 163 | |
| 164 | 164 | NOTE: Currently some of the 32K sets read the "OPEN DOOR" and cycle too quickly to be played. Some can be played |
| 165 | | if the game thinks the door is closed when you start the game, like PP0120 Wild Sevens Poker. |
| 165 | if the door status is closed when you start the game, like PP0120 Wild Sevens Poker. |
| 166 | 166 | |
| 167 | 167 | ***********************************************************************************/ |
| 168 | 168 | |
| r29543 | r29544 | |
| 2486 | 2486 | w/D w/oD |
| 2487 | 2487 | PayTable 3K STR FL FH 4K SF 5K RF 4D RF (Bonus) |
| 2488 | 2488 | ---------------------------------------------------------- |
| 2489 | | P56A 1 2 3 3 4 8 10 20 200 250 800 |
| 2490 | | % Range: 89.4-91.4% Optimum: 93.4% Hit Frequency: 45.1% |
| 2491 | | Programs Available: PP0242 |
| 2489 | P47A 1 2 2 3 4 13 16 22 200 250 800 |
| 2490 | % Range: 92.8-94.8% Optimum: 96.8% Hit Frequency: 44.9% |
| 2491 | Programs Available: PP0290, X000224P & PP0224 - Non Double-up Only |
| 2492 | 2492 | */ |
| 2493 | 2493 | ROM_LOAD( "pp0224_a47-a76.u68", 0x00000, 0x10000, CRC(5d6881ad) SHA1(38953ffadea04df614b14c70177736039495c408) ) /* Game Version: A47, Library Version: A76 */ |
| 2494 | 2494 | |
| r29543 | r29544 | |
| 2508 | 2508 | w/D w/oD |
| 2509 | 2509 | PayTable 3K STR FL FH 4K SF 5K RF 4D RF (Bonus) |
| 2510 | 2510 | ---------------------------------------------------------- |
| 2511 | | P56A 1 2 3 3 4 8 10 20 200 250 800 |
| 2512 | | % Range: 89.4-91.4% Optimum: 93.4% Hit Frequency: 45.1% |
| 2513 | | Programs Available: PP0242 |
| 2511 | P47A 1 2 2 3 4 13 16 22 200 250 800 |
| 2512 | % Range: 92.8-94.8% Optimum: 96.8% Hit Frequency: 44.9% |
| 2513 | Programs Available: PP0290, X000224P & PP0224 - Non Double-up Only |
| 2514 | 2514 | */ |
| 2515 | 2515 | |
| 2516 | 2516 | ROM_LOAD( "pp0224_961-984.u68", 0x00000, 0x10000, CRC(71d5e112) SHA1(528f06ad7ea7e1e297939c7b3ca0bb7faa8ce8c1) ) /* Game Version: 961, Library Version: 984 */ |
| r29543 | r29544 | |
| 2539 | 2539 | ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) ) /* BPROM type DM74LS471 (compatible with N82S135N) verified */ |
| 2540 | 2540 | ROM_END |
| 2541 | 2541 | |
| 2542 | ROM_START( pepp0242 ) /* Normal board : Deuces Wild Poker (PP0242) - Multi Regional / Multi Currency in English / Spanish */ |
| 2543 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 2544 | /* |
| 2545 | w/D w/oD |
| 2546 | PayTable 3K STR FL FH 4K SF 5K RF 4D RF (Bonus) |
| 2547 | ---------------------------------------------------------- |
| 2548 | P56A 1 2 3 3 4 8 10 20 200 250 800 |
| 2549 | % Range: 89.4-91.4% Optimum: 93.4% Hit Frequency: 45.1% |
| 2550 | Programs Available: PP0242, X000242P |
| 2551 | */ |
| 2552 | |
| 2553 | ROM_LOAD( "pp0242_a1c-a31.u68", 0x00000, 0x10000, CRC(cb7cdf2b) SHA1(989db6bf860637ef0c9d38c4ec824e2ab92acb89) ) /* Game Version: A1C, Library Version: A31 */ |
| 2554 | |
| 2555 | ROM_REGION( 0x020000, "gfx1", 0 ) |
| 2556 | ROM_LOAD( "mro-cg1325.u72", 0x00000, 0x8000, CRC(ebb81436) SHA1(211cc0f881703b3cceb51c65209075154c9536db) ) |
| 2557 | ROM_LOAD( "mgo-cg1325.u73", 0x08000, 0x8000, CRC(ef86e83a) SHA1(854fc31173c7647a9ed986f2fe58ec3795eb8542) ) |
| 2558 | ROM_LOAD( "mbo-cg1325.u74", 0x10000, 0x8000, CRC(8387b4ba) SHA1(cab77982464e9e70e6ad4ecf51a5cafe7aefb478) ) |
| 2559 | ROM_LOAD( "mxo-cg1325.u75", 0x18000, 0x8000, CRC(9dddc501) SHA1(a0ab8b3866b0ae018b3f6e0199bdc756d4e5f967) ) |
| 2560 | |
| 2561 | ROM_REGION( 0x100, "proms", 0 ) |
| 2562 | ROM_LOAD( "cap1215.u50", 0x0000, 0x0100, CRC(294b7b10) SHA1(a405a4b8547b713c5c02dacb19e7354095a7b584) ) |
| 2563 | ROM_END |
| 2564 | |
| 2542 | 2565 | ROM_START( pepp0249 ) /* Normal board : Deuces Wild Poker (PP0249) */ |
| 2543 | 2566 | /* |
| 2544 | 2567 | w/D w/oD |
| r29543 | r29544 | |
| 2644 | 2667 | ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) ) /* BPROM type DM74LS471 (compatible with N82S135N) verified */ |
| 2645 | 2668 | ROM_END |
| 2646 | 2669 | |
| 2670 | ROM_START( pepp0288 ) /* Normal board : Standard Draw Poker (PP0288) - Spanish */ |
| 2671 | /* |
| 2672 | PayTable Js+ 2PR 3K STR FL FH 4K SF RF (Bonus) |
| 2673 | ---------------------------------------------------------- |
| 2674 | KK 1 2 3 4 6 9 25 50 500 500 |
| 2675 | % Range: 94.9-96.9% Optimum: 98.9% Hit Frequency: 45.5% |
| 2676 | Programs Available: PP0288 |
| 2677 | |
| 2678 | Spanish version of PP0150 |
| 2679 | */ |
| 2680 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 2681 | ROM_LOAD( "pp0288_964-988.u68", 0x00000, 0x10000, CRC(f7e1cb4c) SHA1(651c4306764200611aae7280ce0a9756d42ccb21) ) /* Game Version: 964, Library Version: 988 */ |
| 2682 | |
| 2683 | ROM_REGION( 0x020000, "gfx1", 0 ) |
| 2684 | ROM_LOAD( "mro-cg1152.u72", 0x00000, 0x8000, CRC(55aca7f6) SHA1(9a0b25908e4fee8346da4726f38993e233a2cb2f) ) |
| 2685 | ROM_LOAD( "mgo-cg1152.u73", 0x08000, 0x8000, CRC(c5185314) SHA1(7fc385d2b44e68364f2b5a3702737c5d5fea5ea2) ) |
| 2686 | ROM_LOAD( "mbo-cg1152.u74", 0x10000, 0x8000, CRC(bd19aef6) SHA1(77126ea73d0a5da4b8856b5ebcbbab84cfaef008) ) |
| 2687 | ROM_LOAD( "mxo-cg1152.u75", 0x18000, 0x8000, CRC(d65f7362) SHA1(d56fa0d13126f1599d538c81a2c7ea1f3c94b62f) ) |
| 2688 | |
| 2689 | ROM_REGION( 0x100, "proms", 0 ) |
| 2690 | ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) ) /* BPROM type DM74LS471 (compatible with N82S135N) verified */ |
| 2691 | ROM_END |
| 2692 | |
| 2647 | 2693 | ROM_START( pepp0290 ) /* Normal board : Deuces Wild Poker (PP0290) */ |
| 2648 | 2694 | /* |
| 2649 | 2695 | w/D w/oD |
| r29543 | r29544 | |
| 2905 | 2951 | ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) ) /* BPROM type DM74LS471 (compatible with N82S135N) verified */ |
| 2906 | 2952 | ROM_END |
| 2907 | 2953 | |
| 2954 | ROM_START( pepp0431 ) /* Normal board : Deuces Joker Wild Poker (PP0431) */ |
| 2955 | /* |
| 2956 | With w/o w/o With |
| 2957 | Wild JKR Wild JKR |
| 2958 | PayTable 3K STR FL FH 4K SF 5K RF 4D RF 4D (Bonus) |
| 2959 | -------------------------------------------------------------------- |
| 2960 | P76N 1 1 3 3 3 6 9 12 25 800 1000 2000 |
| 2961 | % Range: 95.1-97.1% Optimum: 99.1% Hit Frequency: 50.4% |
| 2962 | Programs Available: PP0431, PP0812, PP0813, X000225P & PP0225 - Non Double-up Only |
| 2963 | */ |
| 2964 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 2965 | ROM_LOAD( "pp0431_a47-a76.u68", 0x00000, 0x10000, CRC(2997aaac) SHA1(b52525154f4ae39a341ecf829c33449f31a8ce07) ) /* Game Version: A47, Library Version: A76 */ |
| 2966 | |
| 2967 | ROM_REGION( 0x020000, "gfx1", 0 ) |
| 2968 | ROM_LOAD( "mro-cg1215.u72", 0x00000, 0x8000, CRC(425f57be) SHA1(6d53ae86bec7189a35671a7f691e101a2ed4d8c4) ) /* 06/09/93 @ IGT L93-1585 */ |
| 2969 | ROM_LOAD( "mgo-cg1215.u73", 0x08000, 0x8000, CRC(0f66cd94) SHA1(9ac0cd01aca87e045c4fd6045ed907a092d6b2ee) ) |
| 2970 | ROM_LOAD( "mbo-cg1215.u74", 0x10000, 0x8000, CRC(10f89e44) SHA1(cdc34970b0325a24cfd5c187a4b4dbf42be8fc93) ) |
| 2971 | ROM_LOAD( "mxo-cg1215.u75", 0x18000, 0x8000, CRC(73c24e43) SHA1(f09beaf374ad371db2701767ce6ac5bdb13c445a) ) |
| 2972 | |
| 2973 | ROM_REGION( 0x100, "proms", 0 ) |
| 2974 | ROM_LOAD( "cap1215.u50", 0x0000, 0x0100, CRC(294b7b10) SHA1(a405a4b8547b713c5c02dacb19e7354095a7b584) ) |
| 2975 | ROM_END |
| 2976 | |
| 2908 | 2977 | ROM_START( pepp0434 ) /* Normal board : Bonus Poker Deluxe (PP0434) */ |
| 2909 | 2978 | /* |
| 2910 | 2979 | PayTable Js+ 2PR 3K STR FL FH 4K SF RF (Bonus) |
| r29543 | r29544 | |
| 2989 | 3058 | ROM_LOAD( "cap740.u50", 0x0000, 0x0100, CRC(6fe619c4) SHA1(49e43dafd010ce0fe9b2a63b96a4ddedcb933c6d) ) /* BPROM type DM74LS471 (compatible with N82S135N) verified */ |
| 2990 | 3059 | ROM_END |
| 2991 | 3060 | |
| 3061 | ROM_START( pepp0449a ) /* Normal board : Standard Draw Poker (PP0449) - Multi Regional / Multi Currency in English / Spanish */ |
| 3062 | /* |
| 3063 | PayTable Js+ 2PR 3K STR FL FH 4K SF RF (Bonus) |
| 3064 | ---------------------------------------------------------- |
| 3065 | P11A 1 2 3 4 5 9 25 50 250 800 |
| 3066 | % Range: 92.1-94.1% Optimum: 96.1% Hit Frequency: 45.5% |
| 3067 | Programs Available: PP0449, X000449P & PP0221 - Non Double-up Only |
| 3068 | */ |
| 3069 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 3070 | ROM_LOAD( "pp0449_a19-a2x.u68", 0x00000, 0x10000, CRC(0bde4a5b) SHA1(dacce2a56ede8145fc22cad4cc75967aaea3b6e4) ) /* Game Version: A19, Library Version: A2X */ |
| 3071 | |
| 3072 | ROM_REGION( 0x020000, "gfx1", 0 ) |
| 3073 | ROM_LOAD( "mro-cg1426.u74", 0x00000, 0x8000, CRC(b99b3856) SHA1(a7de74bc712c68ae3da2d546c49dcd70e54c26a1) ) |
| 3074 | ROM_LOAD( "mgo-cg1426.u73", 0x08000, 0x8000, CRC(d7145ea0) SHA1(7b23cf7840bab11f7ba9229e990e2c9dd995d59f) ) |
| 3075 | ROM_LOAD( "mbo-cg1426.u72", 0x10000, 0x8000, CRC(5fd94bc5) SHA1(b2a23a6a8eb23fbefd7b16e7afb7eddad5f6656c) ) |
| 3076 | ROM_LOAD( "mxo-cg1426.u75", 0x18000, 0x8000, CRC(74bc1556) SHA1(9afc00ec4643baa448e0131e1c7aeb3da4739f59) ) |
| 3077 | |
| 3078 | |
| 3079 | ROM_REGION( 0x100, "proms", 0 ) |
| 3080 | ROM_LOAD( "cap904.u50", 0x0000, 0x0100, CRC(0eec8336) SHA1(a6585c978dbc2f4f3818e3a5b92f8c28be23c4c0) ) /* BPROM type N82S135N verified */ |
| 3081 | ROM_END |
| 3082 | |
| 2992 | 3083 | ROM_START( pepp0452 ) /* Normal board : Double Deuces Wild Poker (PP0452) */ |
| 2993 | 3084 | /* |
| 2994 | 3085 | w/D wo/D |
| r29543 | r29544 | |
| 4252 | 4343 | ROM_LOAD( "x000055p.u66", 0x00000, 0x10000, CRC(e06819df) SHA1(36590c4588b8036908e63714fbb3e77d23e60eae) ) /* Deuces Wild Poker */ |
| 4253 | 4344 | |
| 4254 | 4345 | ROM_REGION( 0x020000, "gfx1", 0 ) |
| 4255 | | ROM_LOAD( "mro-cg2185.u77", 0x00000, 0x8000, CRC(7e64bd1a) SHA1(e988a380ee58078bf5bdc7747e83aed1393cfad8) ) /* 07/10/95 @ IGT L95-1506 */ |
| 4256 | | ROM_LOAD( "mgo-cg2185.u78", 0x08000, 0x8000, CRC(d4127893) SHA1(75039c45ba6fd171a66876c91abc3191c7feddfc) ) |
| 4257 | | ROM_LOAD( "mbo-cg2185.u79", 0x10000, 0x8000, CRC(17dba955) SHA1(5f77379c88839b3a04e235e4fb0120c77e17b60e) ) |
| 4258 | | ROM_LOAD( "mxo-cg2185.u80", 0x18000, 0x8000, CRC(583eb3b1) SHA1(4a2952424969917fb1594698a779fe5a1e99bff5) ) |
| 4346 | ROM_LOAD( "mro-cg2399.u72", 0x00000, 0x8000, CRC(0424f4ba) SHA1(c8b192a6f63c8c9937cb3923d27b9ba2c39823cd) ) /* Custom The Fun Ships graphics */ |
| 4347 | ROM_LOAD( "mgo-cg2399.u73", 0x08000, 0x8000, CRC(5848a2fa) SHA1(4173a473016b7a776d2b59bf3ded0be35bd43721) ) |
| 4348 | ROM_LOAD( "mbo-cg2399.u74", 0x10000, 0x8000, CRC(5c3e16f6) SHA1(a4aa457f239527bffa6472e0d6f9d836f796b326) ) |
| 4349 | ROM_LOAD( "mxo-cg2399.u75", 0x18000, 0x8000, CRC(bd7669d5) SHA1(4343a9764fd563e2e1cdd8558f2f53f77006b159) ) |
| 4259 | 4350 | |
| 4260 | 4351 | ROM_REGION( 0x200, "proms", 0 ) |
| 4261 | 4352 | ROM_LOAD( "capx1321.u43", 0x0000, 0x0200, CRC(4b57569f) SHA1(fa29c0f627e7ce79951ec6dadec114864144f37d) ) |
| r29543 | r29544 | |
| 4685 | 4776 | ROM_LOAD( "capx1321.u43", 0x0000, 0x0200, CRC(4b57569f) SHA1(fa29c0f627e7ce79951ec6dadec114864144f37d) ) |
| 4686 | 4777 | ROM_END |
| 4687 | 4778 | |
| 4779 | ROM_START( pex0150p ) /* Superboard : Standard Draw Poker (X000150P+XP000038) */ |
| 4780 | /* |
| 4781 | PayTable Js+ 2PR 3K STR FL FH 4K SF RF (Bonus) |
| 4782 | ---------------------------------------------------------- |
| 4783 | KK 1 2 3 4 6 9 25 50 500 500 |
| 4784 | % Range: 94.9-96.9% Optimum: 98.9% Hit Frequency: 45.5% |
| 4785 | Programs Available: PP0150, X000150P |
| 4786 | */ |
| 4787 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 4788 | ROM_LOAD( "xp000038.u67", 0x00000, 0x10000, CRC(8707ab9e) SHA1(3e00a2ad8017e1495c6d6fe900d0efa68a1772b8) ) /* 07/01/96 @IGT L96-1119 */ |
| 4789 | |
| 4790 | ROM_REGION( 0x10000, "user1", 0 ) |
| 4791 | ROM_LOAD( "x000150p.u66", 0x00000, 0x10000, CRC(d10759fa) SHA1(eae633d03ac9db86520a70825ac0a59ee9ebc819) ) /* Standard Draw Poker */ |
| 4792 | |
| 4793 | ROM_REGION( 0x020000, "gfx1", 0 ) |
| 4794 | ROM_LOAD( "mro-cg2185.u77", 0x00000, 0x8000, CRC(7e64bd1a) SHA1(e988a380ee58078bf5bdc7747e83aed1393cfad8) ) /* 07/10/95 @ IGT L95-1506 */ |
| 4795 | ROM_LOAD( "mgo-cg2185.u78", 0x08000, 0x8000, CRC(d4127893) SHA1(75039c45ba6fd171a66876c91abc3191c7feddfc) ) |
| 4796 | ROM_LOAD( "mbo-cg2185.u79", 0x10000, 0x8000, CRC(17dba955) SHA1(5f77379c88839b3a04e235e4fb0120c77e17b60e) ) |
| 4797 | ROM_LOAD( "mxo-cg2185.u80", 0x18000, 0x8000, CRC(583eb3b1) SHA1(4a2952424969917fb1594698a779fe5a1e99bff5) ) |
| 4798 | |
| 4799 | ROM_REGION( 0x200, "proms", 0 ) |
| 4800 | ROM_LOAD( "capx1321.u43", 0x0000, 0x0200, CRC(4b57569f) SHA1(fa29c0f627e7ce79951ec6dadec114864144f37d) ) |
| 4801 | ROM_END |
| 4802 | |
| 4688 | 4803 | ROM_START( pex0158p ) /* Superboard : 4 of a Kind Bonus Poker (X000158P+XP000038) */ |
| 4689 | 4804 | /* |
| 4690 | 4805 | 5-K 2-4 |
| r29543 | r29544 | |
| 4884 | 4999 | ROM_LOAD( "capx1321.u43", 0x0000, 0x0200, CRC(4b57569f) SHA1(fa29c0f627e7ce79951ec6dadec114864144f37d) ) |
| 4885 | 5000 | ROM_END |
| 4886 | 5001 | |
| 5002 | ROM_START( pex0242p ) /* Superboard : Deuces Wild Poker (X000242P+XP000053) */ |
| 5003 | /* |
| 5004 | w/D w/oD |
| 5005 | PayTable 3K STR FL FH 4K SF 5K RF 4D RF (Bonus) |
| 5006 | ---------------------------------------------------------- |
| 5007 | P56A 1 2 3 3 4 8 10 20 200 250 800 |
| 5008 | % Range: 89.4-91.4% Optimum: 93.4% Hit Frequency: 45.1% |
| 5009 | Programs Available: PP0242, X000242P |
| 5010 | */ |
| 5011 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 5012 | ROM_LOAD( "xp000053.u67", 0x00000, 0x10000, CRC(f4f1f986) SHA1(84cfc2c4a10ed24d3a971fe75041a4108ec1d7f2) ) |
| 5013 | |
| 5014 | ROM_REGION( 0x10000, "user1", 0 ) |
| 5015 | ROM_LOAD( "x000242p.u66", 0x00000, 0x10000, CRC(e0292d63) SHA1(8d8ec5dc1abaf8e8a8a7451d3a814023d8195fb5) ) /* Deuces Wild Poker */ |
| 5016 | |
| 5017 | ROM_REGION( 0x020000, "gfx1", 0 ) |
| 5018 | ROM_LOAD( "mro-cg2185.u77", 0x00000, 0x8000, CRC(7e64bd1a) SHA1(e988a380ee58078bf5bdc7747e83aed1393cfad8) ) /* 07/10/95 @ IGT L95-1506 */ |
| 5019 | ROM_LOAD( "mgo-cg2185.u78", 0x08000, 0x8000, CRC(d4127893) SHA1(75039c45ba6fd171a66876c91abc3191c7feddfc) ) |
| 5020 | ROM_LOAD( "mbo-cg2185.u79", 0x10000, 0x8000, CRC(17dba955) SHA1(5f77379c88839b3a04e235e4fb0120c77e17b60e) ) |
| 5021 | ROM_LOAD( "mxo-cg2185.u80", 0x18000, 0x8000, CRC(583eb3b1) SHA1(4a2952424969917fb1594698a779fe5a1e99bff5) ) |
| 5022 | |
| 5023 | ROM_REGION( 0x200, "proms", 0 ) |
| 5024 | ROM_LOAD( "capx1321.u43", 0x0000, 0x0200, CRC(4b57569f) SHA1(fa29c0f627e7ce79951ec6dadec114864144f37d) ) |
| 5025 | ROM_END |
| 5026 | |
| 4887 | 5027 | ROM_START( pex0265p ) /* Superboard : 4 of a Kind Bonus Poker (X000265P+XP000038) */ |
| 4888 | 5028 | /* |
| 4889 | 5029 | 5-K 2-4 |
| r29543 | r29544 | |
| 5280 | 5420 | ROM_LOAD( "capx1321.u43", 0x0000, 0x0200, CRC(4b57569f) SHA1(fa29c0f627e7ce79951ec6dadec114864144f37d) ) |
| 5281 | 5421 | ROM_END |
| 5282 | 5422 | |
| 5423 | ROM_START( pex0516p ) /* Superboard : Double Double Bonus Poker (X000516P+XP000038) */ |
| 5424 | /* |
| 5425 | 5-K 2-4 |
| 5426 | PayTable Js+ 2PR 3K STR FL FH 4K 4K 4A SF RF (Bonus) |
| 5427 | ----------------------------------------------------------------- |
| 5428 | P325A 1 2 3 4 5 8 50 80 160 50 250 800 |
| 5429 | % Range: 93.8-95.8% Optimum: 97.8% Hit Frequency: 44.5% |
| 5430 | Programs Available: PP0516, X000516P & PP0540 - Non Double-up Only |
| 5431 | */ |
| 5432 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 5433 | ROM_LOAD( "xp000038.u67", 0x00000, 0x10000, CRC(8707ab9e) SHA1(3e00a2ad8017e1495c6d6fe900d0efa68a1772b8) ) /* 07/01/96 @IGT L96-1119 */ |
| 5434 | |
| 5435 | ROM_REGION( 0x10000, "user1", 0 ) |
| 5436 | ROM_LOAD( "x000516p.u66", 0x00000, 0x10000, CRC(37f84ce7) SHA1(2e5157d02febec0ff31eb5a23254f7c49a486cf5) ) /* Double Bonus Poker */ |
| 5437 | |
| 5438 | ROM_REGION( 0x020000, "gfx1", 0 ) |
| 5439 | ROM_LOAD( "mro-cg2185.u77", 0x00000, 0x8000, CRC(7e64bd1a) SHA1(e988a380ee58078bf5bdc7747e83aed1393cfad8) ) /* 07/10/95 @ IGT L95-1506 */ |
| 5440 | ROM_LOAD( "mgo-cg2185.u78", 0x08000, 0x8000, CRC(d4127893) SHA1(75039c45ba6fd171a66876c91abc3191c7feddfc) ) |
| 5441 | ROM_LOAD( "mbo-cg2185.u79", 0x10000, 0x8000, CRC(17dba955) SHA1(5f77379c88839b3a04e235e4fb0120c77e17b60e) ) |
| 5442 | ROM_LOAD( "mxo-cg2185.u80", 0x18000, 0x8000, CRC(583eb3b1) SHA1(4a2952424969917fb1594698a779fe5a1e99bff5) ) |
| 5443 | |
| 5444 | ROM_REGION( 0x200, "proms", 0 ) |
| 5445 | ROM_LOAD( "capx1321.u43", 0x0000, 0x0200, CRC(4b57569f) SHA1(fa29c0f627e7ce79951ec6dadec114864144f37d) ) |
| 5446 | ROM_END |
| 5447 | |
| 5283 | 5448 | ROM_START( pex0536p ) /* Superboard : Joker Poker (X000536P+XP000038) */ |
| 5284 | 5449 | /* |
| 5285 | 5450 | w/J w/oJ |
| r29543 | r29544 | |
| 5707 | 5872 | ROM_LOAD( "capx2174.u43", 0x0000, 0x0200, CRC(50bdad55) SHA1(958d463c7effb3457c1f9c44c9b7822339c04e8b) ) |
| 5708 | 5873 | ROM_END |
| 5709 | 5874 | |
| 5875 | ROM_START( pex2038p ) /* Superboard : Nevada Bonus Poker (X002038P+XP000038) */ |
| 5876 | /* |
| 5877 | 2-K |
| 5878 | PayTable Js+ 2PR 3K 3A STR FL FH 4K 4A SF RF (Bonus) |
| 5879 | ----------------------------------------------------------------- |
| 5880 | P576A 1 1 3 6 5 7 10 25 200 100 250 800 |
| 5881 | % Range: 93.2-95.2% Optimum: 97.2% Hit Frequency: 43.4% |
| 5882 | Programs Available: X002038P |
| 5883 | */ |
| 5884 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 5885 | ROM_LOAD( "xp000038.u67", 0x00000, 0x10000, CRC(8707ab9e) SHA1(3e00a2ad8017e1495c6d6fe900d0efa68a1772b8) ) /* 07/01/96 @IGT L96-1119 */ |
| 5886 | |
| 5887 | ROM_REGION( 0x10000, "user1", 0 ) |
| 5888 | ROM_LOAD( "x002038p.u66", 0x00000, 0x10000, CRC(58d01ba5) SHA1(6d4cde9c9e55967db2b661c7123cce9958a00639) ) /* Nevada Bonus Poker */ |
| 5889 | |
| 5890 | ROM_REGION( 0x020000, "gfx1", 0 ) |
| 5891 | ROM_LOAD( "mro-cg2185.u77", 0x00000, 0x8000, CRC(7e64bd1a) SHA1(e988a380ee58078bf5bdc7747e83aed1393cfad8) ) /* 07/10/95 @ IGT L95-1506 */ |
| 5892 | ROM_LOAD( "mgo-cg2185.u78", 0x08000, 0x8000, CRC(d4127893) SHA1(75039c45ba6fd171a66876c91abc3191c7feddfc) ) |
| 5893 | ROM_LOAD( "mbo-cg2185.u79", 0x10000, 0x8000, CRC(17dba955) SHA1(5f77379c88839b3a04e235e4fb0120c77e17b60e) ) |
| 5894 | ROM_LOAD( "mxo-cg2185.u80", 0x18000, 0x8000, CRC(583eb3b1) SHA1(4a2952424969917fb1594698a779fe5a1e99bff5) ) |
| 5895 | |
| 5896 | ROM_REGION( 0x200, "proms", 0 ) |
| 5897 | ROM_LOAD( "capx1321.u43", 0x0000, 0x0200, CRC(4b57569f) SHA1(fa29c0f627e7ce79951ec6dadec114864144f37d) ) |
| 5898 | ROM_END |
| 5899 | |
| 5710 | 5900 | ROM_START( pex2040p ) /* Superboard : Nevada Bonus Poker (X002040P+XP000038) */ |
| 5711 | 5901 | /* |
| 5712 | 5902 | 2-K |
| r29543 | r29544 | |
| 5782 | 5972 | ROM_LOAD( "capx1321.u43", 0x0000, 0x0200, CRC(4b57569f) SHA1(fa29c0f627e7ce79951ec6dadec114864144f37d) ) |
| 5783 | 5973 | ROM_END |
| 5784 | 5974 | |
| 5975 | ROM_START( pex2044p ) /* Superboard : Triple Bonus Poker (X002044P+XP000038) */ |
| 5976 | /* |
| 5977 | 5-K 2-4 |
| 5978 | PayTable Js+ 2PR 3K STR FL FH 4K 4K 4A SF RF (Bonus) |
| 5979 | ----------------------------------------------------------------- |
| 5980 | P606A 1 1 3 4 7 9 75 120 240 50 250 800 |
| 5981 | % Range: 93.5-95.5% Optimum: 97.5% Hit Frequency: 34.7% |
| 5982 | Programs Available: X002044P |
| 5983 | */ |
| 5984 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 5985 | ROM_LOAD( "xp000038.u67", 0x00000, 0x10000, CRC(8707ab9e) SHA1(3e00a2ad8017e1495c6d6fe900d0efa68a1772b8) ) /* 07/01/96 @IGT L96-1119 */ |
| 5986 | |
| 5987 | ROM_REGION( 0x10000, "user1", 0 ) |
| 5988 | ROM_LOAD( "x002044p.u66", 0x00000, 0x10000, CRC(158af97f) SHA1(452247d981f1202da8c44a31f0d3343184d3db41) ) /* Triple Bonus Poker */ |
| 5989 | |
| 5990 | ROM_REGION( 0x020000, "gfx1", 0 ) |
| 5991 | ROM_LOAD( "mro-cg2275.u77", 0x00000, 0x8000, CRC(15d5d6b8) SHA1(61b6821d4cc059732bc3831bf19bf01aa3910b31) ) |
| 5992 | ROM_LOAD( "mgo-cg2275.u78", 0x08000, 0x8000, CRC(bcb49579) SHA1(d5d9f523304582fa6f0a0c69aade77629bdec006) ) |
| 5993 | ROM_LOAD( "mbo-cg2275.u79", 0x10000, 0x8000, CRC(9f893787) SHA1(0b79d5cbac920394d5f5c04d0d9d3727e0060366) ) |
| 5994 | ROM_LOAD( "mxo-cg2275.u80", 0x18000, 0x8000, CRC(6187c68b) SHA1(7777b141fd1379d37d93a228b2e2159476c2b89e) ) |
| 5995 | |
| 5996 | ROM_REGION( 0x200, "proms", 0 ) |
| 5997 | ROM_LOAD( "capx1321.u43", 0x0000, 0x0200, CRC(4b57569f) SHA1(fa29c0f627e7ce79951ec6dadec114864144f37d) ) |
| 5998 | ROM_END |
| 5999 | |
| 5785 | 6000 | ROM_START( pex2045p ) /* Superboard : Triple Bonus Poker (X002045P+XP000038) */ |
| 5786 | 6001 | /* |
| 5787 | 6002 | 5-K 2-4 |
| r29543 | r29544 | |
| 6209 | 6424 | ROM_LOAD( "capx2309.u43", 0x0000, 0x0200, CRC(5da912cc) SHA1(6294f8be682e70e9052c9ae5f6865467e9dba2e3) ) |
| 6210 | 6425 | ROM_END |
| 6211 | 6426 | |
| 6427 | ROM_START( pex2272p ) /* Superboard : Black Jack Bonus Poker (X002272P+XP000055) */ |
| 6428 | /* |
| 6429 | Black Jack as in Jack of Spades/Clubs, not 21 With With |
| 6430 | BJ BJ With |
| 6431 | 5-K 2-4 5-K 2-4 BJ |
| 6432 | PayTable Js+ 2PR STR FL FH 4K SF 4K 4K 4A 4K 4K 4A RF (Bonus) |
| 6433 | ----------------------------------------------------------------------------- |
| 6434 | P870BB 1 1 3 4 7 9 50 25 80 160 160 400 400 400 800 |
| 6435 | % Range: 95.4-97.4% Optimum: 99.4% Hit Frequency: ???% |
| 6436 | Programs Available: X002272P |
| 6437 | */ |
| 6438 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 6439 | ROM_LOAD( "xp000055.u67", 0x00000, 0x10000, CRC(339821e0) SHA1(127d4eff01136feaf1e3242d57433349afb7b6ca) ) |
| 6440 | |
| 6441 | ROM_REGION( 0x10000, "user1", 0 ) |
| 6442 | ROM_LOAD( "x002272p.u66", 0x00000, 0x10000, CRC(ee4f27b9) SHA1(1ee105430358ea27badd943bb6b18663e4029388) ) /* Black Jack Bonus Poker */ |
| 6443 | |
| 6444 | ROM_REGION( 0x020000, "gfx1", 0 ) |
| 6445 | ROM_LOAD( "mro-cg2324.u77", 0x00000, 0x8000, CRC(6eceef42) SHA1(a2ddd2a3290c41e510f483c6b633fe0002694d0b) ) |
| 6446 | ROM_LOAD( "mgo-cg2324.u78", 0x08000, 0x8000, CRC(26d0acbe) SHA1(09a9127deb88185cd5b748bac657461eadb2f48f) ) |
| 6447 | ROM_LOAD( "mbo-cg2324.u79", 0x10000, 0x8000, CRC(47baee32) SHA1(d8af09022ccb5fc06aa3aa4c200a734b66cbee00) ) |
| 6448 | ROM_LOAD( "mxo-cg2324.u80", 0x18000, 0x8000, CRC(60449fc0) SHA1(251d1e04786b70c1d2bc7b02f3b69cd58ac76398) ) |
| 6449 | |
| 6450 | ROM_REGION( 0x200, "proms", 0 ) |
| 6451 | ROM_LOAD( "capx1321.u43", 0x0000, 0x0200, CRC(4b57569f) SHA1(fa29c0f627e7ce79951ec6dadec114864144f37d) ) |
| 6452 | ROM_END |
| 6453 | |
| 6454 | ROM_START( pex2275p ) /* Superboard : Black Jack Bonus Poker (X002275P+XP000055) */ |
| 6455 | /* |
| 6456 | Black Jack as in Jack of Spades/Clubs, not 21 With With |
| 6457 | BJ BJ With |
| 6458 | 5-K 2-4 5-K 2-4 BJ |
| 6459 | PayTable Js+ 2PR STR FL FH 4K SF 4K 4K 4A 4K 4K 4A RF (Bonus) |
| 6460 | ----------------------------------------------------------------------------- |
| 6461 | P873BB 1 1 3 4 5 8 50 25 80 160 160 400 400 400 800 |
| 6462 | % Range: 92.0-94.0% Optimum: 96.0% Hit Frequency: ???% |
| 6463 | Programs Available: X002275P |
| 6464 | */ |
| 6465 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 6466 | ROM_LOAD( "xp000055.u67", 0x00000, 0x10000, CRC(339821e0) SHA1(127d4eff01136feaf1e3242d57433349afb7b6ca) ) |
| 6467 | |
| 6468 | ROM_REGION( 0x10000, "user1", 0 ) |
| 6469 | ROM_LOAD( "x002275p.u66", 0x00000, 0x10000, CRC(5ba4f5ab) SHA1(def069025ec4aa340646dfd7cfacc8ce836a210c) ) /* Black Jack Bonus Poker */ |
| 6470 | |
| 6471 | ROM_REGION( 0x020000, "gfx1", 0 ) |
| 6472 | ROM_LOAD( "mro-cg2324.u77", 0x00000, 0x8000, CRC(6eceef42) SHA1(a2ddd2a3290c41e510f483c6b633fe0002694d0b) ) |
| 6473 | ROM_LOAD( "mgo-cg2324.u78", 0x08000, 0x8000, CRC(26d0acbe) SHA1(09a9127deb88185cd5b748bac657461eadb2f48f) ) |
| 6474 | ROM_LOAD( "mbo-cg2324.u79", 0x10000, 0x8000, CRC(47baee32) SHA1(d8af09022ccb5fc06aa3aa4c200a734b66cbee00) ) |
| 6475 | ROM_LOAD( "mxo-cg2324.u80", 0x18000, 0x8000, CRC(60449fc0) SHA1(251d1e04786b70c1d2bc7b02f3b69cd58ac76398) ) |
| 6476 | |
| 6477 | ROM_REGION( 0x200, "proms", 0 ) |
| 6478 | ROM_LOAD( "capx1321.u43", 0x0000, 0x0200, CRC(4b57569f) SHA1(fa29c0f627e7ce79951ec6dadec114864144f37d) ) |
| 6479 | ROM_END |
| 6480 | |
| 6212 | 6481 | ROM_START( pex2283p ) /* Superboard : Dealt Deuces Wild Bonus (X002283P+XP000057) */ |
| 6213 | 6482 | /* |
| 6214 | 6483 | w/D 6-K 3-5 w/A w/oD |
| r29543 | r29544 | |
| 6326 | 6595 | ROM_LOAD( "capx2174.u43", 0x0000, 0x0200, CRC(50bdad55) SHA1(958d463c7effb3457c1f9c44c9b7822339c04e8b) ) |
| 6327 | 6596 | ROM_END |
| 6328 | 6597 | |
| 6598 | ROM_START( pex2306p ) /* Superboard : Triple Double Bonus Poker (X002306P+XP000112) */ |
| 6599 | /* |
| 6600 | 2-4 |
| 6601 | 4K 4A |
| 6602 | 5-K 2-4 with with |
| 6603 | PayTable Js+ 2PR 3K STR FL FH 4K 4K 4A A,2-4 2-4 SF RF (Bonus) |
| 6604 | ----------------------------------------------------------------------------- |
| 6605 | P908BM 1 1 2 4 7 9 50 80 160 400 400 50 400 800 |
| 6606 | % Range: 95.6-97.6% Optimum: 99.6% Hit Frequency: 43.3% |
| 6607 | Programs Available: X002306P |
| 6608 | */ |
| 6609 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 6610 | ROM_LOAD( "xp000112.u67", 0x00000, 0x10000, CRC(c1ae96ad) SHA1(da109602f0fbe9b225cdcd60be0613fd41014864) ) |
| 6611 | |
| 6612 | ROM_REGION( 0x10000, "user1", 0 ) |
| 6613 | ROM_LOAD( "x002306p.u66", 0x00000, 0x10000, CRC(ef36ea67) SHA1(8914ad20526fd63e14d9fa1901e9c779a11eb29d) ) /* Triple Double Bonus Poker */ |
| 6614 | |
| 6615 | ROM_REGION( 0x020000, "gfx1", 0 ) |
| 6616 | ROM_LOAD( "mro-cg2324.u77", 0x00000, 0x8000, CRC(6eceef42) SHA1(a2ddd2a3290c41e510f483c6b633fe0002694d0b) ) |
| 6617 | ROM_LOAD( "mgo-cg2324.u78", 0x08000, 0x8000, CRC(26d0acbe) SHA1(09a9127deb88185cd5b748bac657461eadb2f48f) ) |
| 6618 | ROM_LOAD( "mbo-cg2324.u79", 0x10000, 0x8000, CRC(47baee32) SHA1(d8af09022ccb5fc06aa3aa4c200a734b66cbee00) ) |
| 6619 | ROM_LOAD( "mxo-cg2324.u80", 0x18000, 0x8000, CRC(60449fc0) SHA1(251d1e04786b70c1d2bc7b02f3b69cd58ac76398) ) |
| 6620 | |
| 6621 | ROM_REGION( 0x200, "proms", 0 ) |
| 6622 | ROM_LOAD( "capx2174.u43", 0x0000, 0x0200, CRC(50bdad55) SHA1(958d463c7effb3457c1f9c44c9b7822339c04e8b) ) |
| 6623 | ROM_END |
| 6624 | |
| 6329 | 6625 | ROM_START( pex2307p ) /* Superboard : Triple Double Bonus Poker (X002307P+XP000112) */ |
| 6330 | 6626 | /* |
| 6331 | 6627 | 2-4 |
| r29543 | r29544 | |
| 6353 | 6649 | ROM_LOAD( "capx2174.u43", 0x0000, 0x0200, CRC(50bdad55) SHA1(958d463c7effb3457c1f9c44c9b7822339c04e8b) ) |
| 6354 | 6650 | ROM_END |
| 6355 | 6651 | |
| 6652 | ROM_START( pex2310p ) /* Superboard : Triple Double Bonus Poker (X002310P+XP000112) */ |
| 6653 | /* |
| 6654 | 2-4 |
| 6655 | 4K 4A |
| 6656 | 5-K 2-4 with with |
| 6657 | PayTable Js+ 2PR 3K STR FL FH 4K 4K 4A A,2-4 2-4 SF RF (Bonus) |
| 6658 | ----------------------------------------------------------------------------- |
| 6659 | P908BM 1 1 2 4 5 7 50 80 160 400 400 50 400 800 |
| 6660 | % Range: 90.9-92.9% Optimum: 94.9% Hit Frequency: 44.5% |
| 6661 | Programs Available: X002310P |
| 6662 | */ |
| 6663 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 6664 | ROM_LOAD( "xp000112.u67", 0x00000, 0x10000, CRC(c1ae96ad) SHA1(da109602f0fbe9b225cdcd60be0613fd41014864) ) |
| 6665 | |
| 6666 | ROM_REGION( 0x10000, "user1", 0 ) |
| 6667 | ROM_LOAD( "x002310p.u66", 0x00000, 0x10000, CRC(c006c3f1) SHA1(45c87a2f882147d1d132237cfa12ae47b202264f) ) /* Triple Double Bonus Poker */ |
| 6668 | |
| 6669 | ROM_REGION( 0x020000, "gfx1", 0 ) |
| 6670 | ROM_LOAD( "mro-cg2324.u77", 0x00000, 0x8000, CRC(6eceef42) SHA1(a2ddd2a3290c41e510f483c6b633fe0002694d0b) ) |
| 6671 | ROM_LOAD( "mgo-cg2324.u78", 0x08000, 0x8000, CRC(26d0acbe) SHA1(09a9127deb88185cd5b748bac657461eadb2f48f) ) |
| 6672 | ROM_LOAD( "mbo-cg2324.u79", 0x10000, 0x8000, CRC(47baee32) SHA1(d8af09022ccb5fc06aa3aa4c200a734b66cbee00) ) |
| 6673 | ROM_LOAD( "mxo-cg2324.u80", 0x18000, 0x8000, CRC(60449fc0) SHA1(251d1e04786b70c1d2bc7b02f3b69cd58ac76398) ) |
| 6674 | |
| 6675 | ROM_REGION( 0x200, "proms", 0 ) |
| 6676 | ROM_LOAD( "capx2174.u43", 0x0000, 0x0200, CRC(50bdad55) SHA1(958d463c7effb3457c1f9c44c9b7822339c04e8b) ) |
| 6677 | ROM_END |
| 6678 | |
| 6356 | 6679 | ROM_START( pex2314p ) /* Superboard : Triple Bonus Poker Plus (X002314P+XP000112) */ |
| 6357 | 6680 | /* |
| 6358 | 6681 | 5-K 2-4 |
| r29543 | r29544 | |
| 6723 | 7046 | ROM_LOAD( "capx2174.u43", 0x0000, 0x0200, CRC(50bdad55) SHA1(958d463c7effb3457c1f9c44c9b7822339c04e8b) ) |
| 6724 | 7047 | ROM_END |
| 6725 | 7048 | |
| 7049 | ROM_START( pexmp013 ) /* Superboard : 5-in-1 Wingboard (XMP00013) Program in Spanish, Requires Spanish Wingboard CG rom set */ |
| 7050 | /* |
| 7051 | |
| 7052 | Known Wingboard compatible program roms: |
| 7053 | XMP00013 - Spanish |
| 7054 | XMP00014 (not dumped) |
| 7055 | XMP00017 |
| 7056 | XMP00026 - Spanish |
| 7057 | XMP00030 |
| 7058 | |
| 7059 | The CG2346 set seems to support all games supported in CG2298 as well as graphics support for the following XnnnnnnP Data game types: |
| 7060 | Triple Double Bonus |
| 7061 | Black Jack Bonus (comes up as Back Jack Poker) |
| 7062 | |
| 7063 | */ |
| 7064 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 7065 | ROM_LOAD( "xmp00013.u67", 0x00000, 0x10000, CRC(76ca7c2b) SHA1(cdcbfc648d007362bb50541e6415354c07815d66) ) |
| 7066 | |
| 7067 | ROM_REGION( 0x10000, "user1", 0 ) |
| 7068 | ROM_LOAD( "x000055p.u66", 0x00000, 0x10000, CRC(e06819df) SHA1(36590c4588b8036908e63714fbb3e77d23e60eae) ) /* Deuces Wild Poker */ |
| 7069 | |
| 7070 | ROM_REGION( 0x10000, "user2", 0 ) |
| 7071 | ROM_LOAD( "x000188p.u66", 0x00000, 0x10000, CRC(3eb7580e) SHA1(86f2280542fb8a55767efd391d0fb04a12ed9408) ) /* Standard Draw Poker */ |
| 7072 | |
| 7073 | ROM_REGION( 0x10000, "user3", 0 ) |
| 7074 | ROM_LOAD( "x000516p.u66", 0x00000, 0x10000, CRC(37f84ce7) SHA1(2e5157d02febec0ff31eb5a23254f7c49a486cf5) ) /* Double Bonus Poker */ |
| 7075 | |
| 7076 | ROM_REGION( 0x10000, "user4", 0 ) |
| 7077 | ROM_LOAD( "x002275p.u66", 0x00000, 0x10000, CRC(5ba4f5ab) SHA1(def069025ec4aa340646dfd7cfacc8ce836a210c) ) /* Black Jack Bonus Poker */ |
| 7078 | |
| 7079 | ROM_REGION( 0x10000, "user5", 0 ) |
| 7080 | ROM_LOAD( "x002310p.u66", 0x00000, 0x10000, CRC(c006c3f1) SHA1(45c87a2f882147d1d132237cfa12ae47b202264f) ) /* Triple Double Bonus Poker */ |
| 7081 | |
| 7082 | ROM_REGION( 0x040000, "gfx1", 0 ) |
| 7083 | ROM_LOAD( "mro-cg2346.u77", 0x00000, 0x10000, CRC(3d721779) SHA1(01ac540eddeab5ecdba9b543c69fe7f4b53151a4) ) /* Game titles in English */ |
| 7084 | ROM_LOAD( "mgo-cg2346.u78", 0x10000, 0x10000, CRC(a4a4856b) SHA1(db0e7528a63c80fab02b463dfb366d32061a93bb) ) /* Poker hands in Spanish */ |
| 7085 | ROM_LOAD( "mbo-cg2346.u79", 0x20000, 0x10000, CRC(15253b57) SHA1(503b5cb514d9552ed7cf09f236aec63c81cfd828) ) |
| 7086 | ROM_LOAD( "mxo-cg2346.u80", 0x30000, 0x10000, CRC(68ffb37e) SHA1(b6de07452e52a8c6f8657fbefef081aa9d86dbf0) ) |
| 7087 | |
| 7088 | ROM_REGION( 0x200, "proms", 0 ) |
| 7089 | ROM_LOAD( "capx2346.u43", 0x0000, 0x0200, CRC(8df8ad29) SHA1(2d6a598fdc4290abe83a3d95c0ec8da6eb0f0e84) ) |
| 7090 | ROM_END |
| 7091 | |
| 6726 | 7092 | ROM_START( pexmp017 ) /* Superboard : 5-in-1 Wingboard (XMP00017) */ |
| 6727 | 7093 | /* |
| 6728 | 7094 | |
| 6729 | 7095 | Known Wingboard compatible program roms: |
| 7096 | XMP00013 - Spanish |
| 6730 | 7097 | XMP00014 (not dumped) |
| 6731 | 7098 | XMP00017 |
| 7099 | XMP00026 - Spanish |
| 6732 | 7100 | XMP00030 |
| 6733 | 7101 | |
| 6734 | 7102 | XMP00017 is not compatible with: |
| r29543 | r29544 | |
| 6812 | 7180 | /* |
| 6813 | 7181 | |
| 6814 | 7182 | The CG2426 set supersedes both CG2298 & CG2352 and adds graphics support for the following XnnnnnnP Data game types: |
| 7183 | Black Jack Bonus |
| 7184 | Super Double Bonus |
| 6815 | 7185 | Triple Double Bonus |
| 6816 | | Super Double Bonus |
| 6817 | 7186 | |
| 6818 | 7187 | */ |
| 6819 | 7188 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 6820 | 7189 | ROM_LOAD( "xmp00017.u67", 0x00000, 0x10000, CRC(129e6eaa) SHA1(1dd2b83a672a618f338b553a6cbd598b6d4ce672) ) |
| 6821 | 7190 | |
| 6822 | 7191 | ROM_REGION( 0x10000, "user1", 0 ) |
| 6823 | | ROM_LOAD( "x000045p.u66", 0x00000, 0x10000, CRC(5412e1f9) SHA1(a962b7731df2f534ea79b6d3e376abf45104df37) ) /* Standard Draw Poker (10's or Better) */ |
| 7192 | ROM_LOAD( "x002272p.u66", 0x00000, 0x10000, CRC(ee4f27b9) SHA1(1ee105430358ea27badd943bb6b18663e4029388) ) /* Black Jack Bonus Poker */ |
| 6824 | 7193 | |
| 6825 | 7194 | ROM_REGION( 0x10000, "user2", 0 ) |
| 6826 | 7195 | ROM_LOAD( "x002029p.u66", 0x00000, 0x10000, CRC(e2f6fb89) SHA1(4b60b580b00b4268d1cb9065ffe0d21f8fa6a931) ) /* Deuces Wild Bonus Poker */ |
| 6827 | 7196 | |
| 6828 | 7197 | ROM_REGION( 0x10000, "user3", 0 ) |
| 6829 | | ROM_LOAD( "x002307p.u66", 0x00000, 0x10000, CRC(c6d5db70) SHA1(017e1e382fb789e4cd8b410362ad5e82b61f61db) ) /* Triple Double Bonus Poker */ |
| 7198 | ROM_LOAD( "x002040p.u66", 0x00000, 0x10000, CRC(38acb477) SHA1(894f5861ac84323e50e8972602251f2873988e6c) ) /* Nevada Bonus Poker */ |
| 6830 | 7199 | |
| 6831 | 7200 | ROM_REGION( 0x10000, "user4", 0 ) |
| 6832 | | ROM_LOAD( "x002040p.u66", 0x00000, 0x10000, CRC(38acb477) SHA1(894f5861ac84323e50e8972602251f2873988e6c) ) /* Nevada Bonus Poker */ |
| 7201 | ROM_LOAD( "x002018p.u66", 0x00000, 0x10000, CRC(a7b79cfa) SHA1(89216fafffc64fda22a016a906483b76174c3f02) ) /* Full House Bonus Poker */ |
| 6833 | 7202 | |
| 6834 | 7203 | ROM_REGION( 0x10000, "user5", 0 ) |
| 6835 | | ROM_LOAD( "x002018p.u66", 0x00000, 0x10000, CRC(a7b79cfa) SHA1(89216fafffc64fda22a016a906483b76174c3f02) ) /* Full House Bonus Poker */ |
| 7204 | ROM_LOAD( "x002307p.u66", 0x00000, 0x10000, CRC(c6d5db70) SHA1(017e1e382fb789e4cd8b410362ad5e82b61f61db) ) /* Triple Double Bonus Poker */ |
| 6836 | 7205 | |
| 6837 | 7206 | ROM_REGION( 0x040000, "gfx1", 0 ) |
| 6838 | 7207 | ROM_LOAD( "mro-cg2426.u77", 0x00000, 0x10000, CRC(e7622901) SHA1(f653aaf02de840aef56d3efd7680572356e94da7) ) |
| r29543 | r29544 | |
| 6844 | 7213 | ROM_LOAD( "capx2298.u43", 0x0000, 0x0200, CRC(77856036) SHA1(820487c8494965408402ddee6a54511906218e66) ) |
| 6845 | 7214 | ROM_END |
| 6846 | 7215 | |
| 7216 | ROM_START( pexmp026 ) /* Superboard : 5-in-1 Wingboard (XMP00026) Program in Spanish, Requires Spanish Wingboard CG rom set */ |
| 7217 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 7218 | ROM_LOAD( "xmp00026.u67", 0x00000, 0x10000, CRC(0b82387f) SHA1(8348c586cf692c5cbecfe7b52a4271e5aec55027) ) |
| 7219 | |
| 7220 | ROM_REGION( 0x10000, "user1", 0 ) |
| 7221 | ROM_LOAD( "x000242p.u66", 0x00000, 0x10000, CRC(e0292d63) SHA1(8d8ec5dc1abaf8e8a8a7451d3a814023d8195fb5) ) /* Deuces Wild Poker */ |
| 7222 | |
| 7223 | ROM_REGION( 0x10000, "user2", 0 ) |
| 7224 | ROM_LOAD( "x000150p.u66", 0x00000, 0x10000, CRC(d10759fa) SHA1(eae633d03ac9db86520a70825ac0a59ee9ebc819) ) /* Standard Draw Poker */ |
| 7225 | |
| 7226 | ROM_REGION( 0x10000, "user3", 0 ) |
| 7227 | ROM_LOAD( "x002044p.u66", 0x00000, 0x10000, CRC(158af97f) SHA1(452247d981f1202da8c44a31f0d3343184d3db41) ) /* Triple Bonus Poker */ |
| 7228 | |
| 7229 | ROM_REGION( 0x10000, "user4", 0 ) |
| 7230 | ROM_LOAD( "x002038p.u66", 0x00000, 0x10000, CRC(58d01ba5) SHA1(6d4cde9c9e55967db2b661c7123cce9958a00639) ) /* Nevada Bonus Poker */ |
| 7231 | |
| 7232 | ROM_REGION( 0x10000, "user5", 0 ) |
| 7233 | ROM_LOAD( "x002306p.u66", 0x00000, 0x10000, CRC(ef36ea67) SHA1(8914ad20526fd63e14d9fa1901e9c779a11eb29d) ) /* Triple Double Bonus Poker */ |
| 7234 | |
| 7235 | ROM_REGION( 0x040000, "gfx1", 0 ) |
| 7236 | ROM_LOAD( "mro-cg2346.u77", 0x00000, 0x10000, CRC(3d721779) SHA1(01ac540eddeab5ecdba9b543c69fe7f4b53151a4) ) /* Game titles in English */ |
| 7237 | ROM_LOAD( "mgo-cg2346.u78", 0x10000, 0x10000, CRC(a4a4856b) SHA1(db0e7528a63c80fab02b463dfb366d32061a93bb) ) /* Poker hands in Spanish */ |
| 7238 | ROM_LOAD( "mbo-cg2346.u79", 0x20000, 0x10000, CRC(15253b57) SHA1(503b5cb514d9552ed7cf09f236aec63c81cfd828) ) |
| 7239 | ROM_LOAD( "mxo-cg2346.u80", 0x30000, 0x10000, CRC(68ffb37e) SHA1(b6de07452e52a8c6f8657fbefef081aa9d86dbf0) ) |
| 7240 | |
| 7241 | ROM_REGION( 0x200, "proms", 0 ) |
| 7242 | ROM_LOAD( "capx2346.u43", 0x0000, 0x0200, CRC(8df8ad29) SHA1(2d6a598fdc4290abe83a3d95c0ec8da6eb0f0e84) ) |
| 7243 | ROM_END |
| 7244 | |
| 6847 | 7245 | ROM_START( pexmp030 ) /* Superboard : 5-in-1 Wingboard (XMP00030) */ |
| 6848 | 7246 | ROM_REGION( 0x10000, "maincpu", 0 ) |
| 6849 | 7247 | ROM_LOAD( "xmp00030.u67", 0x00000, 0x10000, CRC(da3fcb6f) SHA1(114e581e5ebb5c40c3f3da2784122d3281f269ee) ) /* 11/12/00 @ IGT L01-0197 */ |
| r29543 | r29544 | |
| 6938 | 7336 | GAMEL(1987, pepp0224, pepp0055, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0224) Deuces Wild Poker (set 1)", 0, layout_pe_poker ) |
| 6939 | 7337 | GAMEL(1987, pepp0224a, pepp0055, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0224) Deuces Wild Poker (set 2)", 0, layout_pe_poker ) |
| 6940 | 7338 | GAMEL(1987, pepp0230, pepp0002, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0230) Standard Draw Poker", 0, layout_pe_poker ) |
| 7339 | GAMEL(1987, pepp0242, pepp0055, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0242) Deuces Wild Poker (International English/Spanish)", 0, layout_pe_poker ) |
| 6941 | 7340 | GAMEL(1987, pepp0249, pepp0055, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0249) Deuces Wild Poker", 0, layout_pe_poker ) |
| 6942 | 7341 | GAMEL(1987, pepp0250, 0, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0250) Double Down Stud Poker", 0, layout_pe_poker ) |
| 6943 | 7342 | GAMEL(1987, pepp0265, pepp0158, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0265) 4 of a Kind Bonus Poker (set 1)", 0, layout_pe_poker ) |
| 6944 | 7343 | GAMEL(1987, pepp0265a, pepp0158, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0265) 4 of a Kind Bonus Poker (set 2)", 0, layout_pe_poker ) |
| 6945 | 7344 | GAMEL(1987, pepp0274, pepp0002, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0274) Standard Draw Poker", 0, layout_pe_poker ) |
| 7345 | GAMEL(1987, pepp0288, pepp0002, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0288) Standard Draw Poker (Spanish)", 0, layout_pe_poker ) |
| 6946 | 7346 | GAMEL(1987, pepp0290, pepp0055, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0290) Deuces Wild Poker", 0, layout_pe_poker ) |
| 6947 | 7347 | GAMEL(1987, pepp0291, pepp0055, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0291) Deuces Wild Poker", 0, layout_pe_poker ) |
| 6948 | 7348 | GAMEL(1987, pepp0409, pepp0158, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0409) 4 of a Kind Bonus Poker", 0, layout_pe_poker ) |
| r29543 | r29544 | |
| 6955 | 7355 | GAMEL(1987, pepp0426, pepp0053, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0426) Joker Poker", 0, layout_pe_poker ) |
| 6956 | 7356 | GAMEL(1987, pepp0428, pepp0053, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0428) Joker Poker", 0, layout_pe_poker ) |
| 6957 | 7357 | GAMEL(1987, pepp0429, pepp0053, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0429) Joker Poker (Aces or Better)", 0, layout_pe_poker ) |
| 7358 | GAMEL(1987, pepp0431, pepp0127, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0431) Deuces Joker Wild Poker", 0, layout_pe_poker ) |
| 6958 | 7359 | GAMEL(1987, pepp0434, 0, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0434) Bonus Poker Deluxe", 0, layout_pe_poker ) |
| 6959 | 7360 | GAMEL(1987, pepp0447, pepp0002, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0447) Standard Draw Poker (set 1)", 0, layout_pe_poker ) |
| 6960 | 7361 | GAMEL(1987, pepp0447a, pepp0002, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0447) Standard Draw Poker (set 2)", 0, layout_pe_poker ) |
| 6961 | 7362 | GAMEL(1987, pepp0449, pepp0002, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0449) Standard Draw Poker", 0, layout_pe_poker ) |
| 7363 | GAMEL(1987, pepp0449a, pepp0002, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0449) Standard Draw Poker (International English/Spanish)", 0, layout_pe_poker ) |
| 6962 | 7364 | GAMEL(1987, pepp0452, 0, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0452) Double Deuces Wild Poker", 0, layout_pe_poker ) |
| 6963 | 7365 | GAMEL(1987, pepp0454, pepp0434, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0454) Bonus Poker Deluxe", 0, layout_pe_poker ) |
| 6964 | 7366 | GAMEL(1987, pepp0455, pepp0053, peplus, peplus_poker, peplus_state, peplus, ROT0, "IGT - International Game Technology", "Player's Edge Plus (PP0455) Joker Poker", 0, layout_pe_poker ) |
| r29543 | r29544 | |
| 7033 | 7435 | GAMEL(1995, pex0054p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000054P+XP000038) Deuces Wild Poker", 0, layout_pe_poker ) |
| 7034 | 7436 | GAMEL(1995, pex0055p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000055P+XP000019) Deuces Wild Poker", 0, layout_pe_poker ) |
| 7035 | 7437 | GAMEL(1995, pex0055pa, pex0055p, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000055P+XP000022) Deuces Wild Poker (The Orleans)", 0, layout_pe_poker ) |
| 7036 | | GAMEL(1995, pex0055pb, pex0055p, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000055P+XP000023) Deuces Wild Poker", 0, layout_pe_poker ) |
| 7438 | GAMEL(1995, pex0055pb, pex0055p, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000055P+XP000023) Deuces Wild Poker (The Fun Ships)", 0, layout_pe_poker ) |
| 7037 | 7439 | GAMEL(1995, pex0055pc, pex0055p, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000055P+XP000028) Deuces Wild Poker", 0, layout_pe_poker ) |
| 7038 | 7440 | GAMEL(1995, pex0055pd, pex0055p, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000055P+XP000035) Deuces Wild Poker", 0, layout_pe_poker ) |
| 7039 | 7441 | GAMEL(1995, pex0055pe, pex0055p, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000055P+XP000038) Deuces Wild Poker", 0, layout_pe_poker ) |
| r29543 | r29544 | |
| 7051 | 7453 | GAMEL(1995, pex0055pq, pex0055p, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000055P+XP000112) Deuces Wild Poker", 0, layout_pe_poker ) |
| 7052 | 7454 | GAMEL(1995, pex0055pr, pex0055p, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000055P+XP000126) Deuces Wild Poker", 0, layout_pe_poker ) |
| 7053 | 7455 | GAMEL(1995, pex0060p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000060P+XP000038) Standard Draw Poker", 0, layout_pe_poker ) |
| 7456 | GAMEL(1995, pex0150p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000150P+XP000038) Standard Draw Poker", 0, layout_pe_poker ) |
| 7054 | 7457 | GAMEL(1995, pex0158p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000158P+XP000038) 4 of a Kind Bonus Poker", 0, layout_pe_poker ) |
| 7055 | 7458 | GAMEL(1995, pex0171p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000171P+XP000038) Joker Poker", 0, layout_pe_poker ) |
| 7056 | 7459 | GAMEL(1995, pex0188p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000188P+XP000038) Standard Draw Poker", 0, layout_pe_poker ) |
| r29543 | r29544 | |
| 7059 | 7462 | GAMEL(1995, pex0203p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000203P+XP000038) 4 of a Kind Bonus Poker", 0, layout_pe_poker ) |
| 7060 | 7463 | GAMEL(1995, pex0224p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000224P+XP000053) Deuces Wild Poker", 0, layout_pe_poker ) |
| 7061 | 7464 | GAMEL(1995, pex0225p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000225P+XP000079) Dueces Joker Wild Poker", 0,layout_pe_poker ) |
| 7465 | GAMEL(1995, pex0242p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000242P+XP000053) Deuces Wild Poker", 0, layout_pe_poker ) |
| 7062 | 7466 | GAMEL(1995, pex0265p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000265P+XP000038) 4 of a Kind Bonus Poker", 0, layout_pe_poker ) |
| 7063 | 7467 | GAMEL(1995, pex0291p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000291P+XP000053) Deuces Wild Poker", 0, layout_pe_poker ) |
| 7064 | 7468 | GAMEL(1995, pex0417p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000417P+XP000053) Deuces Wild Poker", 0, layout_pe_poker ) |
| r29543 | r29544 | |
| 7075 | 7479 | GAMEL(1995, pex0508p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000508P+XP000038) Loose Deuce Deuces Wild! Poker", 0, layout_pe_poker ) |
| 7076 | 7480 | GAMEL(1995, pex0514p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000514P+XP000038) Double Bonus Poker", 0, layout_pe_poker ) |
| 7077 | 7481 | GAMEL(1995, pex0515p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000515P+XP000038) Double Bonus Poker", 0, layout_pe_poker ) |
| 7482 | GAMEL(1995, pex0516p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000516P+XP000038) Double Bonus Poker", 0, layout_pe_poker ) |
| 7078 | 7483 | GAMEL(1995, pex0536p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000536P+XP000038) Joker Poker", 0, layout_pe_poker ) |
| 7079 | 7484 | GAMEL(1995, pex0537p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000537P+XP000038) Standard Draw Poker", 0, layout_pe_poker ) |
| 7080 | 7485 | GAMEL(1995, pex0568p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X000568P+XP000038) Joker Poker", 0, layout_pe_poker ) |
| r29543 | r29544 | |
| 7092 | 7497 | GAMEL(1995, pex2031p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002031P+XP000112) Lucky Deal Poker", 0, layout_pe_poker ) |
| 7093 | 7498 | GAMEL(1995, pex2035p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002035P+XP000112) White Hot Aces Poker", 0, layout_pe_poker ) |
| 7094 | 7499 | GAMEL(1995, pex2036p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002036P+XP000112) White Hot Aces Poker", 0, layout_pe_poker ) |
| 7500 | GAMEL(1995, pex2038p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002038P+XP000038) Nevada Bonus Poker", 0, layout_pe_poker ) |
| 7095 | 7501 | GAMEL(1995, pex2040p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002040P+XP000038) Nevada Bonus Poker", 0, layout_pe_poker ) |
| 7096 | 7502 | GAMEL(1995, pex2042p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002042P+XP000038) Triple Bonus Poker", 0, layout_pe_poker ) |
| 7097 | 7503 | GAMEL(1995, pex2043p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002043P+XP000038) Triple Bonus Poker", 0, layout_pe_poker ) |
| 7504 | GAMEL(1995, pex2044p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002044P+XP000038) Triple Bonus Poker", 0, layout_pe_poker ) |
| 7098 | 7505 | GAMEL(1995, pex2045p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002045P+XP000038) Triple Bonus Poker", 0, layout_pe_poker ) |
| 7099 | 7506 | GAMEL(1995, pex2066p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002066P+XP000038) Double Double Bonus Poker", 0, layout_pe_poker ) |
| 7100 | 7507 | GAMEL(1995, pex2067p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002067P+XP000038) Double Double Bonus Poker", 0, layout_pe_poker ) |
| r29543 | r29544 | |
| 7112 | 7519 | GAMEL(1995, pex2245pa, pex2245p, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002245P+XP000079) Standard Draw Poker", 0,layout_pe_poker ) |
| 7113 | 7520 | GAMEL(1995, pex2250p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002250P+XP000050) Shockwave Poker", 0, layout_pe_poker ) |
| 7114 | 7521 | GAMEL(1995, pex2251p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002251P+XP000050) Shockwave Poker", 0, layout_pe_poker ) |
| 7522 | GAMEL(1995, pex2272p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002272P+XP000055) Black Jack Bonus Poker", 0, layout_pe_poker ) |
| 7523 | GAMEL(1995, pex2275p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002275P+XP000055) Black Jack Bonus Poker", 0, layout_pe_poker ) |
| 7115 | 7524 | GAMEL(1995, pex2283p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002283P+XP000057) Dealt Deuces Wild Bonus Poker", 0, layout_pe_poker ) /* Undumped color CAP but should have correct colors anyways */ |
| 7116 | 7525 | GAMEL(1995, pex2284p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002284P+XP000057) Barbaric Decues Wild Bonus Poker", 0, layout_pe_poker ) /* Undumped color CAP but should have correct colors anyways */ |
| 7117 | 7526 | GAMEL(1995, pex2302p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002302P+XP000038) Bonus Poker Deluxe", 0, layout_pe_poker ) |
| 7118 | 7527 | GAMEL(1995, pex2303p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002303P+XP000112) White Hot Aces Poker", 0, layout_pe_poker ) |
| 7528 | GAMEL(1995, pex2306p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002306P+XP000112) Triple Double Bonus Poker", 0, layout_pe_poker ) |
| 7119 | 7529 | GAMEL(1995, pex2307p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002307P+XP000112) Triple Double Bonus Poker", 0, layout_pe_poker ) |
| 7530 | GAMEL(1995, pex2310p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002310P+XP000112) Triple Double Bonus Poker", 0, layout_pe_poker ) |
| 7120 | 7531 | GAMEL(1995, pex2314p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002314P+XP000112) Triple Bonus Poker Plus", 0, layout_pe_poker ) |
| 7121 | 7532 | GAMEL(1995, pex2374p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002374P+XP000112) Super Aces Poker (Horseshoe)", 0, layout_pe_poker ) |
| 7122 | 7533 | GAMEL(1995, pex2377p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (X002377P+XP000112) Super Double Bonus Poker", 0, layout_pe_poker ) |
| r29543 | r29544 | |
| 7135 | 7546 | GAMEL(1995, pexm008p, 0, peplus, peplus_poker, peplus_state, peplussb, ROT0, "IGT - International Game Technology", "Player's Edge Plus (XM00008P+XMP00006) Multi-Poker", GAME_IMPERFECT_GRAPHICS, layout_pe_poker ) /* Needs CG2228 graphics roms for correct MENU game banners */ |
| 7136 | 7547 | |
| 7137 | 7548 | /* Superboard : Multi-Poker (Wingboard) */ |
| 7549 | GAMEL(1995, pexmp013, 0, peplus, peplus_poker, peplus_state, peplussbw,ROT0, "IGT - International Game Technology", "Player's Edge Plus (XMP00013) 5-in-1 Wingboard (CG2346) - Spanish", 0, layout_pe_poker ) |
| 7138 | 7550 | GAMEL(1995, pexmp017, 0, peplus, peplus_poker, peplus_state, peplussbw,ROT0, "IGT - International Game Technology", "Player's Edge Plus (XMP00017) 5-in-1 Wingboard (CG2298)", 0, layout_pe_poker ) |
| 7139 | 7551 | GAMEL(1995, pexmp017a, pexmp017, peplus, peplus_poker, peplus_state, peplussbw,ROT0, "IGT - International Game Technology", "Player's Edge Plus (XMP00017) 5-in-1 Wingboard (CG2352)", 0, layout_pe_poker ) |
| 7140 | 7552 | GAMEL(1995, pexmp017b, pexmp017, peplus, peplus_poker, peplus_state, peplussbw,ROT0, "IGT - International Game Technology", "Player's Edge Plus (XMP00017) 5-in-1 Wingboard (CG2426)", 0, layout_pe_poker ) |
| 7553 | GAMEL(1995, pexmp026, 0, peplus, peplus_poker, peplus_state, peplussbw,ROT0, "IGT - International Game Technology", "Player's Edge Plus (XMP00026) 5-in-1 Wingboard (CG2346) - Spanish", 0, layout_pe_poker ) |
| 7141 | 7554 | GAMEL(1995, pexmp030, 0, peplus, peplus_poker, peplus_state, peplussbw,ROT0, "IGT - International Game Technology", "Player's Edge Plus (XMP00030) 5-in-1 Wingboard (CG2426)", 0, layout_pe_poker ) |
| 7142 | 7555 | |
| 7143 | 7556 | /* Superboard : Slots machine */ |
branches/new_menus/src/mame/drivers/chihiro.c
| r29543 | r29544 | |
| 416 | 416 | void dword_write_le(UINT8 *addr,UINT32 d); |
| 417 | 417 | void word_write_le(UINT8 *addr,UINT16 d); |
| 418 | 418 | void debug_generate_irq(int irq,bool active); |
| 419 | void debug_grab_texture(int type, char *filename); |
| 419 | 420 | |
| 420 | 421 | void vblank_callback(screen_device &screen, bool state); |
| 421 | 422 | UINT32 screen_update_callback(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); |
| r29543 | r29544 | |
| 445 | 446 | UINT32 words[256/4]; |
| 446 | 447 | } smbusst; |
| 447 | 448 | struct apu_state { |
| 448 | | UINT32 memory0_sgaddress; |
| 449 | | UINT32 memory0_sgblocks; |
| 450 | | UINT32 memory0_address; |
| 451 | | UINT32 memory1_sgaddress; |
| 452 | | UINT32 memory1_sgblocks; |
| 449 | UINT32 memory[0x60000/4]; |
| 450 | UINT32 gpdsp_sgaddress; // global processor scatter-gather |
| 451 | UINT32 gpdsp_sgblocks; |
| 452 | UINT32 gpdsp_address; |
| 453 | UINT32 epdsp_sgaddress; // encoder processor scatter-gather |
| 454 | UINT32 epdsp_sgblocks; |
| 455 | UINT32 unknown_sgaddress; |
| 456 | UINT32 unknown_sgblocks; |
| 457 | int voice_number; |
| 458 | UINT32 voices_heap_blockaddr[1024]; |
| 459 | UINT64 voices_active[4]; //one bit for each voice: 1 playing 0 not |
| 460 | UINT32 voicedata_address; |
| 461 | int voices_frequency[256]; // sample rate |
| 462 | int voices_position[256]; // position in samples * 1000 |
| 463 | int voices_position_start[256]; // position in samples * 1000 |
| 464 | int voices_position_end[256]; // position in samples * 1000 |
| 465 | int voices_position_increment[256]; // position increment every 1ms * 1000 |
| 453 | 466 | emu_timer *timer; |
| 454 | 467 | address_space *space; |
| 455 | 468 | } apust; |
| r29543 | r29544 | |
| 503 | 516 | combiner.used=0; |
| 504 | 517 | combiner.lock=osd_lock_alloc(); |
| 505 | 518 | enabled_vertex_attributes=0; |
| 506 | | memset(words_vertex_attributes,0,sizeof(words_vertex_attributes)); |
| 519 | indexesleft_count = 0; |
| 520 | debug_grab_texttype = -1; |
| 521 | debug_grab_textfile = NULL; |
| 522 | memset(words_vertex_attributes, 0, sizeof(words_vertex_attributes)); |
| 507 | 523 | } |
| 508 | 524 | DECLARE_READ32_MEMBER( geforce_r ); |
| 509 | 525 | DECLARE_WRITE32_MEMBER( geforce_w ); |
| r29543 | r29544 | |
| 546 | 562 | void computedilated(void); |
| 547 | 563 | void putpixtex(int xp,int yp,int up,int vp); |
| 548 | 564 | int toggle_register_combiners_usage(); |
| 565 | void debug_grab_texture(int type, const char *filename); |
| 549 | 566 | void savestate_items(); |
| 550 | 567 | |
| 551 | 568 | struct { |
| r29543 | r29544 | |
| 570 | 587 | int rectangle_pitch; |
| 571 | 588 | void *buffer; |
| 572 | 589 | } texture[4]; |
| 590 | int primitives_count; |
| 591 | int indexesleft_count; |
| 592 | UINT32 indexesleft[8]; |
| 573 | 593 | struct { |
| 574 | 594 | float variable_A[4]; // 0=R 1=G 2=B 3=A |
| 575 | 595 | float variable_B[4]; |
| r29543 | r29544 | |
| 673 | 693 | int used; |
| 674 | 694 | osd_lock *lock; |
| 675 | 695 | } combiner; |
| 696 | struct { |
| 697 | float modelview[16]; |
| 698 | float modelview_inverse[16]; |
| 699 | float projection[16]; |
| 700 | float translate[4]; |
| 701 | float scale[4]; |
| 702 | } matrix; |
| 703 | struct { |
| 704 | UINT32 instruction[1024]; |
| 705 | int instructions; |
| 706 | int upload_instruction; |
| 707 | UINT32 parameter[1024]; |
| 708 | int upload_parameter; |
| 709 | } vertexprogram; |
| 676 | 710 | int enabled_vertex_attributes; |
| 677 | 711 | int words_vertex_attributes[16]; |
| 678 | 712 | bitmap_rgb32 fb; |
| r29543 | r29544 | |
| 680 | 714 | UINT32 dilated1[16][2048]; |
| 681 | 715 | int dilatechose[256]; |
| 682 | 716 | nvidia_object_data *objectdata; |
| 717 | int debug_grab_texttype; |
| 718 | char *debug_grab_textfile; |
| 683 | 719 | |
| 684 | 720 | enum NV2A_BEGIN_END { |
| 685 | 721 | STOP=0, |
| r29543 | r29544 | |
| 1052 | 1088 | debug_console_printf(machine,"Register combiners disabled\n"); |
| 1053 | 1089 | } |
| 1054 | 1090 | |
| 1091 | static void grab_texture_command(running_machine &machine, int ref, int params, const char **param) |
| 1092 | { |
| 1093 | UINT64 type; |
| 1094 | chihiro_state *chst = machine.driver_data<chihiro_state>(); |
| 1095 | |
| 1096 | if (params < 2) |
| 1097 | return; |
| 1098 | if (!debug_command_parameter_number(machine, param[0], &type)) |
| 1099 | return; |
| 1100 | if ((param[1][0] == 0) || (strlen(param[1]) > 127)) |
| 1101 | return; |
| 1102 | chst->nvidia_nv2a->debug_grab_texture((int)type,param[1]); |
| 1103 | } |
| 1104 | |
| 1055 | 1105 | static void help_command(running_machine &machine, int ref, int params, const char **param) |
| 1056 | 1106 | { |
| 1057 | 1107 | debug_console_printf(machine,"Available Chihiro commands:\n"); |
| r29543 | r29544 | |
| 1062 | 1112 | debug_console_printf(machine," chihiro curthread -- Print information about current thread\n"); |
| 1063 | 1113 | debug_console_printf(machine," chihiro irq,<number> -- Generate interrupt with irq number 0-15\n"); |
| 1064 | 1114 | debug_console_printf(machine," chihiro nv2a_combiners -- Toggle use of register combiners\n"); |
| 1115 | debug_console_printf(machine," chihiro grab_texture,<type>,<filename> -- Save to <filename> the next used texture of type <type>\n"); |
| 1065 | 1116 | debug_console_printf(machine," chihiro help -- this list\n"); |
| 1066 | 1117 | } |
| 1067 | 1118 | |
| r29543 | r29544 | |
| 1083 | 1134 | generate_irq_command(machine,ref,params-1,param+1); |
| 1084 | 1135 | else if (strcmp("nv2a_combiners",param[0]) == 0) |
| 1085 | 1136 | nv2a_combiners_command(machine,ref,params-1,param+1); |
| 1137 | else if (strcmp("grab_texture", param[0]) == 0) |
| 1138 | grab_texture_command(machine, ref, params - 1, param + 1); |
| 1086 | 1139 | else |
| 1087 | 1140 | help_command(machine,ref,params-1,param+1); |
| 1088 | 1141 | } |
| r29543 | r29544 | |
| 1256 | 1309 | |
| 1257 | 1310 | UINT32 nv2a_renderer::texture_get_texel(int number,int x,int y) |
| 1258 | 1311 | { |
| 1259 | | UINT32 to,s,c,sa,ca; |
| 1260 | | UINT32 a4r4g4b4,a1r5g5b5,r5g6b5; |
| 1261 | | int bx,by; |
| 1262 | | int color0,color1,color0m2,color1m2; |
| 1312 | UINT32 to, s, c, sa, ca; |
| 1313 | UINT32 a4r4g4b4, a1r5g5b5, r5g6b5; |
| 1314 | int bx, by; |
| 1315 | int color0, color1, color0m2, color1m2, alpha0, alpha1; |
| 1263 | 1316 | UINT32 codes; |
| 1264 | 1317 | UINT64 alphas; |
| 1265 | | int cr,cg,cb; |
| 1318 | int cr, cg, cb; |
| 1266 | 1319 | |
| 1320 | // force to [0,size-1] |
| 1321 | x = (unsigned int)x & (texture[number].sizeu - 1); |
| 1322 | y = (unsigned int)y & (texture[number].sizev - 1); |
| 1267 | 1323 | switch (texture[number].format) { |
| 1268 | | case A8R8G8B8: |
| 1269 | | to=dilated0[texture[number].dilate][x]+dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 1270 | | return *(((UINT32 *)texture[number].buffer)+to); // get texel color |
| 1271 | | case DXT1: |
| 1272 | | bx=x >> 2; |
| 1273 | | by=y >> 2; |
| 1274 | | x=x & 3; |
| 1275 | | y=y & 3; |
| 1276 | | //to=dilated0[texture[number].dilate][bx]+dilated1[texture[number].dilate][by]; // swizzle 4x4 blocks ? |
| 1277 | | to=bx+by*(texture[number].sizeu >> 2); |
| 1278 | | color0=*((UINT16 *)(((UINT64 *)texture[number].buffer)+to)+0); |
| 1279 | | color1=*((UINT16 *)(((UINT64 *)texture[number].buffer)+to)+1); |
| 1280 | | codes=*((UINT32 *)(((UINT64 *)texture[number].buffer)+to)+1); |
| 1281 | | s=(y << 3)+(x << 1); |
| 1282 | | c=(codes >> s) & 3; |
| 1283 | | c=c+(color0 > color1 ? 0 : 4); |
| 1284 | | color0m2=color0 << 1; |
| 1285 | | color1m2=color1 << 1; |
| 1286 | | switch (c) { |
| 1287 | | case 0: |
| 1288 | | return 0xff000000+convert_r5g6b5_r8g8b8(color0); |
| 1289 | | break; |
| 1290 | | case 1: |
| 1291 | | return 0xff000000+convert_r5g6b5_r8g8b8(color1); |
| 1292 | | break; |
| 1293 | | case 2: |
| 1294 | | cb=pal5bit(((color0m2 & 0x003e)+(color1 & 0x001f))/3); |
| 1295 | | cg=pal6bit(((color0m2 & 0x0fc0)+(color1 & 0x07e0))/3 >> 5); |
| 1296 | | cr=pal5bit(((color0m2 & 0x1f000)+color1)/3 >> 11); |
| 1297 | | return 0xff000000|(cr<<16)|(cg<<8)|(cb); |
| 1298 | | break; |
| 1299 | | case 3: |
| 1300 | | cb=pal5bit(((color1m2 & 0x003e)+(color0 & 0x001f))/3); |
| 1301 | | cg=pal6bit(((color1m2 & 0x0fc0)+(color0 & 0x07e0))/3 >> 5); |
| 1302 | | cr=pal5bit(((color1m2 & 0x1f000)+color0)/3 >> 11); |
| 1303 | | return 0xff000000|(cr<<16)|(cg<<8)|(cb); |
| 1304 | | break; |
| 1305 | | case 4: |
| 1306 | | return 0xff000000+convert_r5g6b5_r8g8b8(color0); |
| 1307 | | break; |
| 1308 | | case 5: |
| 1309 | | return 0xff000000+convert_r5g6b5_r8g8b8(color1); |
| 1310 | | break; |
| 1311 | | case 6: |
| 1312 | | cb=pal5bit(((color0 & 0x001f)+(color1 & 0x001f))/2); |
| 1313 | | cg=pal6bit(((color0 & 0x07e0)+(color1 & 0x07e0))/2 >> 5); |
| 1314 | | cr=pal5bit((color0+color1)/2 >> 11); |
| 1315 | | return 0xff000000|(cr<<16)|(cg<<8)|(cb); |
| 1316 | | break; |
| 1317 | | default: |
| 1318 | | return 0xff000000; |
| 1319 | | break; |
| 1320 | | } |
| 1321 | | case DXT3: |
| 1322 | | bx=x >> 2; |
| 1323 | | by=y >> 2; |
| 1324 | | x=x & 3; |
| 1325 | | y=y & 3; |
| 1326 | | //to=(dilated0[texture[number].dilate][bx]+dilated1[texture[number].dilate][by]) << 1; // swizzle 4x4 blocks ? |
| 1327 | | to=(bx+by*(texture[number].sizeu >> 2)) << 1; |
| 1328 | | color0=*((UINT16 *)(((UINT64 *)texture[number].buffer)+to)+4); |
| 1329 | | color1=*((UINT16 *)(((UINT64 *)texture[number].buffer)+to)+5); |
| 1330 | | codes=*((UINT32 *)(((UINT64 *)texture[number].buffer)+to)+3); |
| 1331 | | alphas=*(((UINT64 *)texture[number].buffer)+to); |
| 1332 | | s=(y << 3)+(x << 1); |
| 1333 | | sa=((y << 2)+x) << 2; |
| 1334 | | c=(codes >> s) & 3; |
| 1335 | | ca=(alphas >> sa) & 15; |
| 1336 | | switch (c) { |
| 1337 | | case 0: |
| 1338 | | return ((ca+(ca << 4)) << 24)+convert_r5g6b5_r8g8b8(color0); |
| 1339 | | break; |
| 1340 | | case 1: |
| 1341 | | return ((ca+(ca << 4)) << 24)+convert_r5g6b5_r8g8b8(color1); |
| 1342 | | break; |
| 1343 | | case 2: |
| 1344 | | cb=pal5bit(((color0 & 0x001f)+(color1 & 0x001f))/2); |
| 1345 | | cg=pal6bit(((color0 & 0x07e0)+(color1 & 0x07e0))/2 >> 5); |
| 1346 | | cr=pal5bit((color0+color1)/2 >> 11); |
| 1347 | | return ((ca+(ca << 4)) << 24)|(cr<<16)|(cg<<8)|(cb); |
| 1348 | | break; |
| 1349 | | default: |
| 1350 | | return (ca+(ca << 4)) << 24; |
| 1351 | | break; |
| 1352 | | } |
| 1324 | case A8R8G8B8: |
| 1325 | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 1326 | return *(((UINT32 *)texture[number].buffer) + to); // get texel color |
| 1327 | case DXT1: |
| 1328 | bx = x >> 2; |
| 1329 | by = y >> 2; |
| 1330 | x = x & 3; |
| 1331 | y = y & 3; |
| 1332 | to = bx + by*(texture[number].sizeu >> 2); |
| 1333 | color0 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 0); |
| 1334 | color1 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 1); |
| 1335 | codes = *((UINT32 *)(((UINT64 *)texture[number].buffer) + to) + 1); |
| 1336 | s = (y << 3) + (x << 1); |
| 1337 | c = (codes >> s) & 3; |
| 1338 | c = c + (color0 > color1 ? 0 : 4); |
| 1339 | color0m2 = color0 << 1; |
| 1340 | color1m2 = color1 << 1; |
| 1341 | switch (c) { |
| 1342 | case 0: |
| 1343 | return 0xff000000 + convert_r5g6b5_r8g8b8(color0); |
| 1353 | 1344 | break; |
| 1354 | | case A4R4G4B4: |
| 1355 | | to=dilated0[texture[number].dilate][x]+dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 1356 | | a4r4g4b4=*(((UINT16 *)texture[number].buffer)+to); // get texel color |
| 1357 | | return convert_a4r4g4b4_a8r8g8b8(a4r4g4b4); |
| 1358 | | case A1R5G5B5: |
| 1359 | | to=dilated0[texture[number].dilate][x]+dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 1360 | | a1r5g5b5=*(((UINT16 *)texture[number].buffer)+to); // get texel color |
| 1361 | | return convert_a1r5g5b5_a8r8g8b8(a1r5g5b5); |
| 1362 | | case R5G6B5: |
| 1363 | | to=dilated0[texture[number].dilate][x]+dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 1364 | | r5g6b5=*(((UINT16 *)texture[number].buffer)+to); // get texel color |
| 1365 | | return 0xff000000+convert_r5g6b5_r8g8b8(r5g6b5); |
| 1366 | | case R8G8B8_RECT: |
| 1367 | | to=texture[number].rectangle_pitch*y+(x << 2); |
| 1368 | | return *((UINT32 *)(((UINT8 *)texture[number].buffer)+to)); |
| 1345 | case 1: |
| 1346 | return 0xff000000 + convert_r5g6b5_r8g8b8(color1); |
| 1347 | break; |
| 1348 | case 2: |
| 1349 | cb = pal5bit(((color0m2 & 0x003e) + (color1 & 0x001f)) / 3); |
| 1350 | cg = pal6bit(((color0m2 & 0x0fc0) + (color1 & 0x07e0)) / 3 >> 5); |
| 1351 | cr = pal5bit(((color0m2 & 0x1f000) + color1) / 3 >> 11); |
| 1352 | return 0xff000000 | (cr << 16) | (cg << 8) | (cb); |
| 1353 | break; |
| 1354 | case 3: |
| 1355 | cb = pal5bit(((color1m2 & 0x003e) + (color0 & 0x001f)) / 3); |
| 1356 | cg = pal6bit(((color1m2 & 0x0fc0) + (color0 & 0x07e0)) / 3 >> 5); |
| 1357 | cr = pal5bit(((color1m2 & 0x1f000) + color0) / 3 >> 11); |
| 1358 | return 0xff000000 | (cr << 16) | (cg << 8) | (cb); |
| 1359 | break; |
| 1360 | case 4: |
| 1361 | return 0xff000000 + convert_r5g6b5_r8g8b8(color0); |
| 1362 | break; |
| 1363 | case 5: |
| 1364 | return 0xff000000 + convert_r5g6b5_r8g8b8(color1); |
| 1365 | break; |
| 1366 | case 6: |
| 1367 | cb = pal5bit(((color0 & 0x001f) + (color1 & 0x001f)) / 2); |
| 1368 | cg = pal6bit(((color0 & 0x07e0) + (color1 & 0x07e0)) / 2 >> 5); |
| 1369 | cr = pal5bit(((color0 & 0xf800) + (color1 & 0xf800)) / 2 >> 11); |
| 1370 | return 0xff000000 | (cr << 16) | (cg << 8) | (cb); |
| 1371 | break; |
| 1369 | 1372 | default: |
| 1370 | | return 0xff00ff00; |
| 1373 | return 0xff000000; |
| 1374 | break; |
| 1375 | } |
| 1376 | case DXT3: |
| 1377 | bx = x >> 2; |
| 1378 | by = y >> 2; |
| 1379 | x = x & 3; |
| 1380 | y = y & 3; |
| 1381 | to = (bx + by*(texture[number].sizeu >> 2)) << 1; |
| 1382 | color0 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 4); |
| 1383 | color1 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 5); |
| 1384 | codes = *((UINT32 *)(((UINT64 *)texture[number].buffer) + to) + 3); |
| 1385 | alphas = *(((UINT64 *)texture[number].buffer) + to); |
| 1386 | s = (y << 3) + (x << 1); |
| 1387 | sa = ((y << 2) + x) << 2; |
| 1388 | c = (codes >> s) & 3; |
| 1389 | ca = (alphas >> sa) & 15; |
| 1390 | switch (c) { |
| 1391 | case 0: |
| 1392 | return ((ca + (ca << 4)) << 24) + convert_r5g6b5_r8g8b8(color0); |
| 1393 | break; |
| 1394 | case 1: |
| 1395 | return ((ca + (ca << 4)) << 24) + convert_r5g6b5_r8g8b8(color1); |
| 1396 | break; |
| 1397 | case 2: |
| 1398 | cb = pal5bit((2 * (color0 & 0x001f) + (color1 & 0x001f)) / 3); |
| 1399 | cg = pal6bit((2 * (color0 & 0x07e0) + (color1 & 0x07e0)) / 3 >> 5); |
| 1400 | cr = pal5bit((2 * (color0 & 0xf800) + (color1 & 0xf800)) / 3 >> 11); |
| 1401 | return ((ca + (ca << 4)) << 24) | (cr << 16) | (cg << 8) | (cb); |
| 1402 | break; |
| 1403 | default: |
| 1404 | cb = pal5bit(((color0 & 0x001f) + 2 * (color1 & 0x001f)) / 3); |
| 1405 | cg = pal6bit(((color0 & 0x07e0) + 2 * (color1 & 0x07e0)) / 3 >> 5); |
| 1406 | cr = pal5bit(((color0 & 0xf800) + 2 * (color1 & 0xf800)) / 3 >> 11); |
| 1407 | return ((ca + (ca << 4)) << 24) | (cr << 16) | (cg << 8) | (cb); |
| 1408 | break; |
| 1409 | } |
| 1410 | break; |
| 1411 | case A4R4G4B4: |
| 1412 | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 1413 | a4r4g4b4 = *(((UINT16 *)texture[number].buffer) + to); // get texel color |
| 1414 | return convert_a4r4g4b4_a8r8g8b8(a4r4g4b4); |
| 1415 | case A1R5G5B5: |
| 1416 | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 1417 | a1r5g5b5 = *(((UINT16 *)texture[number].buffer) + to); // get texel color |
| 1418 | return convert_a1r5g5b5_a8r8g8b8(a1r5g5b5); |
| 1419 | case R5G6B5: |
| 1420 | to = dilated0[texture[number].dilate][x] + dilated1[texture[number].dilate][y]; // offset of texel in texture memory |
| 1421 | r5g6b5 = *(((UINT16 *)texture[number].buffer) + to); // get texel color |
| 1422 | return 0xff000000 + convert_r5g6b5_r8g8b8(r5g6b5); |
| 1423 | case R8G8B8_RECT: |
| 1424 | to = texture[number].rectangle_pitch*y + (x << 2); |
| 1425 | return *((UINT32 *)(((UINT8 *)texture[number].buffer) + to)); |
| 1426 | case A8R8G8B8_RECT: |
| 1427 | to = texture[number].rectangle_pitch*y + (x << 2); |
| 1428 | return *((UINT32 *)(((UINT8 *)texture[number].buffer) + to)); |
| 1429 | case DXT5: |
| 1430 | bx = x >> 2; |
| 1431 | by = y >> 2; |
| 1432 | x = x & 3; |
| 1433 | y = y & 3; |
| 1434 | to = (bx + by*(texture[number].sizeu >> 2)) << 1; |
| 1435 | color0 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 4); |
| 1436 | color1 = *((UINT16 *)(((UINT64 *)texture[number].buffer) + to) + 5); |
| 1437 | codes = *((UINT32 *)(((UINT64 *)texture[number].buffer) + to) + 3); |
| 1438 | alpha0 = *((UINT8 *)(((UINT64 *)texture[number].buffer) + to) + 0); |
| 1439 | alpha1 = *((UINT8 *)(((UINT64 *)texture[number].buffer) + to) + 1); |
| 1440 | alphas = *(((UINT64 *)texture[number].buffer) + to); |
| 1441 | s = (y << 3) + (x << 1); |
| 1442 | sa = ((y << 2) + x) * 3; |
| 1443 | c = (codes >> s) & 3; |
| 1444 | ca = (alphas >> sa) & 7; |
| 1445 | ca = ca + (alpha0 > alpha1 ? 0 : 8); |
| 1446 | switch (ca) { |
| 1447 | case 0: |
| 1448 | ca = alpha0; |
| 1449 | break; |
| 1450 | case 1: |
| 1451 | ca = alpha1; |
| 1452 | break; |
| 1453 | case 2: |
| 1454 | ca = (6 * alpha0 + 1 * alpha1) / 7; |
| 1455 | break; |
| 1456 | case 3: |
| 1457 | ca = (5 * alpha0 + 2 * alpha1) / 7; |
| 1458 | break; |
| 1459 | case 4: |
| 1460 | ca = (4 * alpha0 + 3 * alpha1) / 7; |
| 1461 | break; |
| 1462 | case 5: |
| 1463 | ca = (3 * alpha0 + 4 * alpha1) / 7; |
| 1464 | break; |
| 1465 | case 6: |
| 1466 | ca = (2 * alpha0 + 5 * alpha1) / 7; |
| 1467 | break; |
| 1468 | case 7: |
| 1469 | ca = (1 * alpha0 + 6 * alpha1) / 7; |
| 1470 | break; |
| 1471 | case 8: |
| 1472 | ca = alpha0; |
| 1473 | break; |
| 1474 | case 9: |
| 1475 | ca = alpha1; |
| 1476 | break; |
| 1477 | case 10: |
| 1478 | ca = (4 * alpha0 + 1 * alpha1) / 5; |
| 1479 | break; |
| 1480 | case 11: |
| 1481 | ca = (3 * alpha0 + 2 * alpha1) / 5; |
| 1482 | break; |
| 1483 | case 12: |
| 1484 | ca = (2 * alpha0 + 3 * alpha1) / 5; |
| 1485 | break; |
| 1486 | case 13: |
| 1487 | ca = (1 * alpha0 + 4 * alpha1) / 5; |
| 1488 | break; |
| 1489 | case 14: |
| 1490 | ca = 0; |
| 1491 | break; |
| 1492 | case 15: |
| 1493 | ca = 255; |
| 1494 | break; |
| 1495 | } |
| 1496 | switch (c) { |
| 1497 | case 0: |
| 1498 | return (ca << 24) + convert_r5g6b5_r8g8b8(color0); |
| 1499 | break; |
| 1500 | case 1: |
| 1501 | return (ca << 24) + convert_r5g6b5_r8g8b8(color1); |
| 1502 | break; |
| 1503 | case 2: |
| 1504 | cb = pal5bit((2 * (color0 & 0x001f) + (color1 & 0x001f)) / 3); |
| 1505 | cg = pal6bit((2 * (color0 & 0x07e0) + (color1 & 0x07e0)) / 3 >> 5); |
| 1506 | cr = pal5bit((2 * (color0 & 0xf800) + (color1 & 0xf800)) / 3 >> 11); |
| 1507 | return (ca << 24) | (cr << 16) | (cg << 8) | (cb); |
| 1508 | break; |
| 1509 | default: |
| 1510 | cb = pal5bit(((color0 & 0x001f) + 2 * (color1 & 0x001f)) / 3); |
| 1511 | cg = pal6bit(((color0 & 0x07e0) + 2 * (color1 & 0x07e0)) / 3 >> 5); |
| 1512 | cr = pal5bit(((color0 & 0xf800) + 2 * (color1 & 0xf800)) / 3 >> 11); |
| 1513 | return (ca << 24) | (cr << 16) | (cg << 8) | (cb); |
| 1514 | break; |
| 1515 | } |
| 1516 | default: |
| 1517 | return 0xff00ff00; |
| 1371 | 1518 | } |
| 1372 | 1519 | } |
| 1373 | 1520 | |
| r29543 | r29544 | |
| 1616 | 1763 | maddress=method*4; |
| 1617 | 1764 | data=space.read_dword(address); |
| 1618 | 1765 | channel[chanel][subchannel].object.method[method]=data; |
| 1766 | if (maddress == 0x17fc) { |
| 1767 | indexesleft_count = 0; |
| 1768 | primitives_count = 0; |
| 1769 | countlen--; |
| 1770 | } |
| 1619 | 1771 | if (maddress == 0x1810) { |
| 1620 | 1772 | // draw vertices |
| 1621 | 1773 | int offset,count,type; |
| r29543 | r29544 | |
| 1629 | 1781 | offset=data & 0xffffff; |
| 1630 | 1782 | count=(data >> 24) & 0xff; |
| 1631 | 1783 | type=channel[chanel][subchannel].object.method[0x17fc/4]; |
| 1632 | | tmp=channel[chanel][subchannel].object.method[0x1720/4]; |
| 1633 | 1784 | dmahand[0]=channel[chanel][subchannel].object.method[0x019c/4]; |
| 1634 | 1785 | dmahand[1]=channel[chanel][subchannel].object.method[0x01a0/4]; |
| 1635 | 1786 | geforce_read_dma_object(dmahand[0],dmaoff[0],smasiz[0]); |
| r29543 | r29544 | |
| 1674 | 1825 | *((UINT32 *)(&xy[m].y))=space.read_dword(vtxbuf_address[0]+(n+m+offset)*vtxbuf_stride[0]+4); |
| 1675 | 1826 | *((UINT32 *)(&z[m]))=space.read_dword(vtxbuf_address[0]+(n+m+offset)*vtxbuf_stride[0]+8); |
| 1676 | 1827 | *((UINT32 *)(&w[m]))=space.read_dword(vtxbuf_address[0]+(n+m+offset)*vtxbuf_stride[0]+12); |
| 1677 | | c[m]=space.read_dword(vtxbuf_address[3]+(n+m+offset)*vtxbuf_stride[0]+0); // color |
| 1828 | c[m]=space.read_dword(vtxbuf_address[3]+(n+m+offset)*vtxbuf_stride[3]+0); // color |
| 1678 | 1829 | xy[m].p[0]=c[m] & 0xff; // b |
| 1679 | 1830 | xy[m].p[1]=(c[m] & 0xff00) >> 8; // g |
| 1680 | 1831 | xy[m].p[2]=(c[m] & 0xff0000) >> 16; // r |
| r29543 | r29544 | |
| 1711 | 1862 | *((UINT32 *)(&xy[m].y))=space.read_dword(vtxbuf_address[0]+(m+offset)*vtxbuf_stride[0]+4); |
| 1712 | 1863 | *((UINT32 *)(&z[m]))=space.read_dword(vtxbuf_address[0]+(m+offset)*vtxbuf_stride[0]+8); |
| 1713 | 1864 | *((UINT32 *)(&w[m]))=space.read_dword(vtxbuf_address[0]+(m+offset)*vtxbuf_stride[0]+12); |
| 1714 | | c[m]=space.read_dword(vtxbuf_address[3]+(m+offset)*vtxbuf_stride[0]+0); // color |
| 1865 | c[m]=space.read_dword(vtxbuf_address[3]+(m+offset)*vtxbuf_stride[3]+0); // color |
| 1715 | 1866 | xy[m].p[0]=c[m] & 0xff; // b |
| 1716 | 1867 | xy[m].p[1]=(c[m] & 0xff00) >> 8; // g |
| 1717 | 1868 | xy[m].p[2]=(c[m] & 0xff0000) >> 16; // r |
| r29543 | r29544 | |
| 1731 | 1882 | *((UINT32 *)(&xy[2].y))=space.read_dword(vtxbuf_address[0]+(n+offset)*vtxbuf_stride[0]+4); |
| 1732 | 1883 | *((UINT32 *)(&z[2]))=space.read_dword(vtxbuf_address[0]+(n+offset)*vtxbuf_stride[0]+8); |
| 1733 | 1884 | *((UINT32 *)(&w[2]))=space.read_dword(vtxbuf_address[0]+(n+offset)*vtxbuf_stride[0]+12); |
| 1734 | | c[2]=space.read_dword(vtxbuf_address[3]+(n+offset)*vtxbuf_stride[0]+0); // color |
| 1885 | c[2]=space.read_dword(vtxbuf_address[3]+(n+offset)*vtxbuf_stride[3]+0); // color |
| 1735 | 1886 | xy[2].p[0]=c[2] & 0xff; // b |
| 1736 | 1887 | xy[2].p[1]=(c[2] & 0xff00) >> 8; // g |
| 1737 | 1888 | xy[2].p[2]=(c[2] & 0xff0000) >> 16; // r |
| r29543 | r29544 | |
| 1760 | 1911 | } |
| 1761 | 1912 | countlen--; |
| 1762 | 1913 | } |
| 1914 | if (maddress == 0x1800) { |
| 1915 | int vtxbuf_stride[16]; |
| 1916 | UINT32 vtxbuf_address[16]; |
| 1917 | UINT32 dmahand[2], dmaoff[2], smasiz[2]; |
| 1918 | UINT32 type, tmp, n, m, u; |
| 1919 | render_delegate renderspans; |
| 1920 | |
| 1921 | // vertices are selected from the vertex buffer using an array of indexes |
| 1922 | // each dword after 1800 contains two 16 bit index values to select the vartices |
| 1923 | type = channel[chanel][subchannel].object.method[0x17fc / 4]; |
| 1924 | dmahand[0] = channel[chanel][subchannel].object.method[0x019c / 4]; |
| 1925 | dmahand[1] = channel[chanel][subchannel].object.method[0x01a0 / 4]; |
| 1926 | geforce_read_dma_object(dmahand[0], dmaoff[0], smasiz[0]); |
| 1927 | geforce_read_dma_object(dmahand[1], dmaoff[1], smasiz[1]); |
| 1928 | if (((channel[chanel][subchannel].object.method[0x1e60 / 4] & 7) > 0) && (combiner.used != 0)) { |
| 1929 | renderspans = render_delegate(FUNC(nv2a_renderer::render_register_combiners), this); |
| 1930 | } |
| 1931 | else if (texture[0].enabled) { |
| 1932 | renderspans = render_delegate(FUNC(nv2a_renderer::render_texture_simple), this); |
| 1933 | } |
| 1934 | else |
| 1935 | renderspans = render_delegate(FUNC(nv2a_renderer::render_color), this); |
| 1936 | #ifdef LOG_NV2A |
| 1937 | printf("vertex %d %d %d\n\r", type, offset, count); |
| 1938 | #endif |
| 1939 | for (n = 0; n < 16; n++) { |
| 1940 | #ifdef LOG_NV2A |
| 1941 | printf(" %08X %08X\n\r", channel[chanel][subchannel].object.method[0x1720 / 4 + n], channel[chanel][subchannel].object.method[0x1760 / 4 + n]); |
| 1942 | #endif |
| 1943 | tmp = channel[chanel][subchannel].object.method[0x1760 / 4 + n]; // VTXBUF_FMT |
| 1944 | //vtxbuf_kind[n]=tmp & 15; |
| 1945 | //vtxbuf_size[n]=(tmp >> 4) & 15; |
| 1946 | vtxbuf_stride[n] = (tmp >> 8) & 255; |
| 1947 | tmp = channel[chanel][subchannel].object.method[0x1720 / 4 + n]; // VTXBUF_OFFSET |
| 1948 | if (tmp & 0x80000000) |
| 1949 | vtxbuf_address[n] = (tmp & 0x0fffffff) + dmaoff[1]; |
| 1950 | else |
| 1951 | vtxbuf_address[n] = (tmp & 0x0fffffff) + dmaoff[0]; |
| 1952 | } |
| 1953 | if (type == nv2a_renderer::QUADS) { |
| 1954 | while (1) { |
| 1955 | vertex_t xy[4]; |
| 1956 | float z[4], w[4]; |
| 1957 | UINT32 c[4]; |
| 1958 | |
| 1959 | // need 4 per object |
| 1960 | // get remaining |
| 1961 | while ((indexesleft_count < 4) && (countlen > 0)) { |
| 1962 | indexesleft[indexesleft_count] = data & 0xffff; |
| 1963 | indexesleft[indexesleft_count+ 1] = (data >> 16) & 0xffff; |
| 1964 | indexesleft_count+=2; |
| 1965 | countlen--; |
| 1966 | address = address + 4; |
| 1967 | data = space.read_dword(address); |
| 1968 | } |
| 1969 | if ((indexesleft_count < 4) && (countlen == 0)) |
| 1970 | break; |
| 1971 | //printf("draw quad\n\r"); |
| 1972 | for (m = 0; m < 4; m++) { |
| 1973 | *((UINT32 *)(&xy[m].x)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 0); |
| 1974 | *((UINT32 *)(&xy[m].y)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 4); |
| 1975 | *((UINT32 *)(&z[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 8); |
| 1976 | *((UINT32 *)(&w[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 12); |
| 1977 | c[m] = space.read_dword(vtxbuf_address[3] + indexesleft[m] * vtxbuf_stride[3] + 0); // color |
| 1978 | xy[m].p[0] = c[m] & 0xff; // b |
| 1979 | xy[m].p[1] = (c[m] & 0xff00) >> 8; // g |
| 1980 | xy[m].p[2] = (c[m] & 0xff0000) >> 16; // r |
| 1981 | xy[m].p[3] = (c[m] & 0xff000000) >> 24; // a |
| 1982 | for (u = 0; u < 4; u++) { |
| 1983 | xy[m].p[4 + u * 2] = 0; |
| 1984 | xy[m].p[5 + u * 2] = 0; |
| 1985 | if (texture[u].enabled) { |
| 1986 | *((UINT32 *)(&xy[m].p[4 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 0); |
| 1987 | *((UINT32 *)(&xy[m].p[5 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 4); |
| 1988 | } |
| 1989 | } |
| 1990 | } |
| 1991 | |
| 1992 | render_polygon<4>(fb.cliprect(), renderspans, 4 + 4 * 2, xy); // 4 rgba, 4 texture units 2 uv |
| 1993 | /*myline(fb,xy[0].x,xy[0].y,xy[1].x,xy[1].y); |
| 1994 | myline(fb,xy[1].x,xy[1].y,xy[2].x,xy[2].y); |
| 1995 | myline(fb,xy[2].x,xy[2].y,xy[3].x,xy[3].y); |
| 1996 | myline(fb,xy[3].x,xy[3].y,xy[0].x,xy[0].y);*/ |
| 1997 | #ifdef LOG_NV2A |
| 1998 | printf(" (%f,%f,%f)-(%f,%f,%f)-(%f,%f,%f)-(%f,%f,%f)\n\r", xy[0].x, xy[0].y, z[0], xy[1].x, xy[1].y, z[1], xy[2].x, xy[2].y, z[2], xy[3].x, xy[3].y, z[3]); |
| 1999 | #endif |
| 2000 | for (m = 4; m < indexesleft_count; m++) |
| 2001 | indexesleft[m - 4] = indexesleft[m]; |
| 2002 | indexesleft_count = indexesleft_count - 4; |
| 2003 | } |
| 2004 | wait(); |
| 2005 | } |
| 2006 | else if (type == nv2a_renderer::TRIANGLES) { |
| 2007 | while (1) { |
| 2008 | vertex_t xy[4]; |
| 2009 | float z[4], w[4]; |
| 2010 | UINT32 c[4]; |
| 2011 | |
| 2012 | // need 3 dwords per object |
| 2013 | // get remaining |
| 2014 | while ((indexesleft_count < 3) && (countlen > 0)) { |
| 2015 | indexesleft[indexesleft_count] = data & 0xffff; |
| 2016 | indexesleft[indexesleft_count + 1] = (data >> 16) & 0xffff; |
| 2017 | indexesleft_count += 2; |
| 2018 | countlen--; |
| 2019 | address = address + 4; |
| 2020 | data = space.read_dword(address); |
| 2021 | } |
| 2022 | if ((indexesleft_count < 3) && (countlen == 0)) |
| 2023 | break; |
| 2024 | //printf("draw triangle\n\r"); |
| 2025 | for (m = 0; m < 3; m++) { |
| 2026 | *((UINT32 *)(&xy[m].x)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 0); |
| 2027 | *((UINT32 *)(&xy[m].y)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 4); |
| 2028 | *((UINT32 *)(&z[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 8); |
| 2029 | *((UINT32 *)(&w[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 12); |
| 2030 | c[m] = space.read_dword(vtxbuf_address[3] + indexesleft[m] * vtxbuf_stride[3] + 0); // color |
| 2031 | xy[m].p[0] = c[m] & 0xff; // b |
| 2032 | xy[m].p[1] = (c[m] & 0xff00) >> 8; // g |
| 2033 | xy[m].p[2] = (c[m] & 0xff0000) >> 16; // r |
| 2034 | xy[m].p[3] = (c[m] & 0xff000000) >> 24; // a |
| 2035 | for (u = 0; u < 4; u++) { |
| 2036 | xy[m].p[4 + u * 2] = 0; |
| 2037 | xy[m].p[5 + u * 2] = 0; |
| 2038 | if (texture[u].enabled) { |
| 2039 | *((UINT32 *)(&xy[m].p[4 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 0); |
| 2040 | *((UINT32 *)(&xy[m].p[5 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 4); |
| 2041 | } |
| 2042 | } |
| 2043 | } |
| 2044 | |
| 2045 | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[0], xy[1], xy[2]); // 4 rgba, 4 texture units 2 uv |
| 2046 | /*myline(fb,xy[0].x,xy[0].y,xy[1].x,xy[1].y); |
| 2047 | myline(fb,xy[1].x,xy[1].y,xy[2].x,xy[2].y); |
| 2048 | myline(fb,xy[2].x,xy[2].y,xy[3].x,xy[3].y);*/ |
| 2049 | #ifdef LOG_NV2A |
| 2050 | printf(" (%f,%f,%f)-(%f,%f,%f)-(%f,%f,%f)\n\r", xy[0].x, xy[0].y, z[0], xy[1].x, xy[1].y, z[1], xy[2].x, xy[2].y, z[2]); |
| 2051 | #endif |
| 2052 | for (m = 3; m < indexesleft_count; m++) |
| 2053 | indexesleft[m - 3] = indexesleft[m]; |
| 2054 | indexesleft_count = indexesleft_count - 3; |
| 2055 | } |
| 2056 | wait(); |
| 2057 | } |
| 2058 | else if (type == nv2a_renderer::TRIANGLE_STRIP) { |
| 2059 | while (1) { |
| 2060 | vertex_t xy[4]; |
| 2061 | float z[4], w[4]; |
| 2062 | UINT32 c[4]; |
| 2063 | |
| 2064 | // need 3 dwords per object |
| 2065 | // get remaining |
| 2066 | while ((indexesleft_count < 3) && (countlen > 0)) { |
| 2067 | indexesleft[indexesleft_count] = data & 0xffff; |
| 2068 | indexesleft[indexesleft_count + 1] = (data >> 16) & 0xffff; |
| 2069 | indexesleft_count += 2; |
| 2070 | countlen--; |
| 2071 | address = address + 4; |
| 2072 | data = space.read_dword(address); |
| 2073 | } |
| 2074 | if ((indexesleft_count < 3) && (countlen == 0)) |
| 2075 | break; |
| 2076 | //printf("draw triangle\n\r"); |
| 2077 | for (m = 0; m < 3; m++) { |
| 2078 | *((UINT32 *)(&xy[m].x)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 0); |
| 2079 | *((UINT32 *)(&xy[m].y)) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 4); |
| 2080 | *((UINT32 *)(&z[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 8); |
| 2081 | *((UINT32 *)(&w[m])) = space.read_dword(vtxbuf_address[0] + indexesleft[m] * vtxbuf_stride[0] + 12); |
| 2082 | c[m] = space.read_dword(vtxbuf_address[3] + indexesleft[m] * vtxbuf_stride[3] + 0); // color |
| 2083 | xy[m].p[0] = c[m] & 0xff; // b |
| 2084 | xy[m].p[1] = (c[m] & 0xff00) >> 8; // g |
| 2085 | xy[m].p[2] = (c[m] & 0xff0000) >> 16; // r |
| 2086 | xy[m].p[3] = (c[m] & 0xff000000) >> 24; // a |
| 2087 | for (u = 0; u < 4; u++) { |
| 2088 | xy[m].p[4 + u * 2] = 0; |
| 2089 | xy[m].p[5 + u * 2] = 0; |
| 2090 | if (texture[u].enabled) { |
| 2091 | *((UINT32 *)(&xy[m].p[4 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 0); |
| 2092 | *((UINT32 *)(&xy[m].p[5 + u * 2])) = space.read_dword(vtxbuf_address[9 + u] + indexesleft[m] * vtxbuf_stride[9 + u] + 4); |
| 2093 | } |
| 2094 | } |
| 2095 | } |
| 2096 | |
| 2097 | render_triangle(fb.cliprect(), renderspans, 4 + 4 * 2, xy[primitives_count & 1], xy[~primitives_count & 1], xy[2]); // 012,102,012,102... |
| 2098 | /*myline(fb,xy[0].x,xy[0].y,xy[1].x,xy[1].y); |
| 2099 | myline(fb,xy[1].x,xy[1].y,xy[2].x,xy[2].y); |
| 2100 | myline(fb,xy[2].x,xy[2].y,xy[3].x,xy[3].y);*/ |
| 2101 | #ifdef LOG_NV2A |
| 2102 | printf(" (%f,%f,%f)-(%f,%f,%f)-(%f,%f,%f)\n\r", xy[0].x, xy[0].y, z[0], xy[1].x, xy[1].y, z[1], xy[2].x, xy[2].y, z[2]); |
| 2103 | #endif |
| 2104 | primitives_count++; |
| 2105 | for (m = 1; m < indexesleft_count; m++) |
| 2106 | indexesleft[m - 1] = indexesleft[m]; |
| 2107 | indexesleft_count = indexesleft_count - 1; |
| 2108 | } |
| 2109 | wait(); |
| 2110 | } |
| 2111 | else { |
| 2112 | logerror("Unsupported primitive %d for method 0x1800\n", type); |
| 2113 | countlen = 0; |
| 2114 | } |
| 2115 | } |
| 1763 | 2116 | if (maddress == 0x1818) { |
| 1764 | 2117 | int n,m,u,vwords; |
| 1765 | 2118 | int vattrpos[16]; |
| r29543 | r29544 | |
| 1900 | 2253 | } |
| 1901 | 2254 | for (n=2;countlen > 0;n++) { |
| 1902 | 2255 | // put vertex n data in element 2 of arrays |
| 1903 | | // put vertex n data in element 2 of arrays |
| 1904 | 2256 | // position |
| 1905 | 2257 | *((UINT32 *)(&xy[2].x))=space.read_dword(address+vattrpos[0]*4+0); |
| 1906 | 2258 | *((UINT32 *)(&xy[2].y))=space.read_dword(address+vattrpos[0]*4+4); |
| r29543 | r29544 | |
| 2055 | 2407 | wait(); |
| 2056 | 2408 | } else { |
| 2057 | 2409 | logerror("Unsupported primitive %d for method 0x1818\n",type); |
| 2410 | countlen = 0; |
| 2058 | 2411 | } |
| 2059 | 2412 | } |
| 2413 | if ((maddress >= 0x1760) && (maddress < 0x17A0)) { |
| 2414 | int bit=method-0x1760/4; |
| 2415 | |
| 2416 | data=data & 255; |
| 2417 | if (data > 15) |
| 2418 | enabled_vertex_attributes |= (1 << bit); |
| 2419 | else |
| 2420 | enabled_vertex_attributes &= ~(1 << bit); |
| 2421 | switch (data & 15) { |
| 2422 | case 0: |
| 2423 | words_vertex_attributes[bit]=(((data >> 4) + 3) & 15) >> 2; |
| 2424 | break; |
| 2425 | case nv2a_renderer::FLOAT: |
| 2426 | words_vertex_attributes[bit]=(data >> 4); |
| 2427 | break; |
| 2428 | case nv2a_renderer::UBYTE: |
| 2429 | words_vertex_attributes[bit]=(((data >> 4) + 3) & 15) >> 2; |
| 2430 | break; |
| 2431 | case nv2a_renderer::USHORT: |
| 2432 | words_vertex_attributes[bit]=(((data >> 4) + 1) & 15) >> 1; |
| 2433 | break; |
| 2434 | default: |
| 2435 | words_vertex_attributes[bit]=0; |
| 2436 | } |
| 2437 | countlen--; |
| 2438 | } |
| 2060 | 2439 | if ((maddress == 0x1d6c) || (maddress == 0x1d70) || (maddress == 0x1a4)) |
| 2061 | 2440 | countlen--; |
| 2062 | 2441 | if (maddress == 0x1d70) { |
| r29543 | r29544 | |
| 2124 | 2503 | texture[unit].sizew=1 << basesizew; |
| 2125 | 2504 | texture[unit].dilate=dilatechose[(basesizeu << 4)+basesizev]; |
| 2126 | 2505 | texture[unit].format=format; |
| 2506 | if (debug_grab_texttype == format) { |
| 2507 | FILE *f; |
| 2508 | int written; |
| 2509 | |
| 2510 | debug_grab_texttype = -1; |
| 2511 | f = fopen(debug_grab_textfile, "wb"); |
| 2512 | if (f) { |
| 2513 | written=(int)fwrite(texture[unit].buffer, texture[unit].sizeu*texture[unit].sizev*4, 1, f); |
| 2514 | fclose(f); |
| 2515 | logerror("Written %d bytes of texture to specified file\n", written); |
| 2516 | } else |
| 2517 | logerror("Unable to save texture to specified file\n"); |
| 2518 | } |
| 2127 | 2519 | } |
| 2128 | 2520 | if (maddress == 0x1b0c) { |
| 2129 | 2521 | // enable texture |
| r29543 | r29544 | |
| 2137 | 2529 | } |
| 2138 | 2530 | countlen--; |
| 2139 | 2531 | } |
| 2140 | | if ((maddress >= 0x1760) && (maddress < 0x17A0)) { |
| 2141 | | int bit=method-0x1760/4; |
| 2142 | | |
| 2143 | | data=data & 255; |
| 2144 | | if (data > 15) |
| 2145 | | enabled_vertex_attributes |= (1 << bit); |
| 2532 | // modelview matrix |
| 2533 | if ((maddress >= 0x0480) && (maddress < 0x04c0)) { |
| 2534 | maddress = (maddress - 0x0480) / 4; |
| 2535 | *(UINT32 *)(&matrix.modelview[maddress]) = data; |
| 2536 | countlen--; |
| 2537 | } |
| 2538 | // inverse modelview matrix |
| 2539 | if ((maddress >= 0x0580) && (maddress < 0x05c0)) { |
| 2540 | maddress = (maddress - 0x0580) / 4; |
| 2541 | *(UINT32 *)(&matrix.modelview_inverse[maddress]) = data; |
| 2542 | countlen--; |
| 2543 | } |
| 2544 | // projection matrix |
| 2545 | if ((maddress >= 0x0680) && (maddress < 0x06c0)) { |
| 2546 | maddress = (maddress - 0x0680) / 4; |
| 2547 | *(UINT32 *)(&matrix.projection[maddress]) = data; |
| 2548 | countlen--; |
| 2549 | } |
| 2550 | // viewport translate |
| 2551 | if ((maddress >= 0x0a20) && (maddress < 0x0a30)) { |
| 2552 | maddress = (maddress - 0x0a20) / 4; |
| 2553 | *(UINT32 *)(&matrix.translate[maddress]) = data; |
| 2554 | countlen--; |
| 2555 | } |
| 2556 | // viewport scale |
| 2557 | if ((maddress >= 0x0af0) && (maddress < 0x0b00)) { |
| 2558 | maddress = (maddress - 0x0af0) / 4; |
| 2559 | *(UINT32 *)(&matrix.scale[maddress]) = data; |
| 2560 | countlen--; |
| 2561 | } |
| 2562 | // Vertex program (shader) |
| 2563 | if (maddress == 0x1e94) { |
| 2564 | /*if (data == 2) |
| 2565 | logerror("Enabled vertex program\n"); |
| 2566 | else if (data == 4) |
| 2567 | logerror("Enabled fixed function pipeline\n"); |
| 2568 | else if (data == 6) |
| 2569 | logerror("Enabled both fixed function pipeline and vertex program ?\n"); |
| 2146 | 2570 | else |
| 2147 | | enabled_vertex_attributes &= ~(1 << bit); |
| 2148 | | switch (data & 15) { |
| 2149 | | case 0: |
| 2150 | | words_vertex_attributes[bit]=(((data >> 4) + 3) & 15) >> 2; |
| 2151 | | break; |
| 2152 | | case nv2a_renderer::FLOAT: |
| 2153 | | words_vertex_attributes[bit]=(data >> 4); |
| 2154 | | break; |
| 2155 | | case nv2a_renderer::UBYTE: |
| 2156 | | words_vertex_attributes[bit]=(((data >> 4) + 3) & 15) >> 2; |
| 2157 | | break; |
| 2158 | | case nv2a_renderer::USHORT: |
| 2159 | | words_vertex_attributes[bit]=(((data >> 4) + 1) & 15) >> 1; |
| 2160 | | break; |
| 2161 | | default: |
| 2162 | | words_vertex_attributes[bit]=0; |
| 2163 | | } |
| 2571 | logerror("Unknown value %d to method 0x1e94\n",data);*/ |
| 2572 | countlen--; |
| 2164 | 2573 | } |
| 2574 | if (maddress == 0x1e9c) { |
| 2575 | //logerror("VP_UPLOAD_FROM_ID %d\n",data); |
| 2576 | vertexprogram.upload_instruction=data*4; |
| 2577 | countlen--; |
| 2578 | } |
| 2579 | if (maddress == 0x1ea0) { |
| 2580 | //logerror("VP_START_FROM_ID %d\n",data); |
| 2581 | vertexprogram.instructions=vertexprogram.upload_instruction/4; |
| 2582 | countlen--; |
| 2583 | } |
| 2584 | if (maddress == 0x1ea4) { |
| 2585 | //logerror("VP_UPLOAD_CONST_ID %d\n",data); |
| 2586 | vertexprogram.upload_parameter=data; |
| 2587 | countlen--; |
| 2588 | } |
| 2589 | if ((maddress >= 0x0b00) && (maddress < 0x0b80)) { |
| 2590 | //logerror("VP_UPLOAD_INST\n"); |
| 2591 | if (vertexprogram.upload_instruction < 1024) |
| 2592 | vertexprogram.instruction[vertexprogram.upload_instruction]=data; |
| 2593 | else |
| 2594 | logerror("Need to increase size of vertexprogram.instruction to %d\n\r", vertexprogram.upload_parameter); |
| 2595 | vertexprogram.upload_instruction++; |
| 2596 | } |
| 2597 | if ((maddress >= 0x0b80) && (maddress < 0x0c00)) { |
| 2598 | //logerror("VP_UPLOAD_CONST\n"); |
| 2599 | if (vertexprogram.upload_parameter < 1024) |
| 2600 | vertexprogram.parameter[vertexprogram.upload_parameter] = data; |
| 2601 | else |
| 2602 | logerror("Need to increase size of vertexprogram.parameter to %d\n\r", vertexprogram.upload_parameter); |
| 2603 | vertexprogram.upload_parameter++; |
| 2604 | } |
| 2605 | // Register combiners |
| 2165 | 2606 | if (maddress == 0x1e60) { |
| 2166 | 2607 | combiner.stages=data & 15; |
| 2167 | 2608 | countlen--; |
| r29543 | r29544 | |
| 2290 | 2731 | return combiner.used; |
| 2291 | 2732 | } |
| 2292 | 2733 | |
| 2734 | void nv2a_renderer::debug_grab_texture(int type, const char *filename) |
| 2735 | { |
| 2736 | debug_grab_texttype = type; |
| 2737 | if (debug_grab_textfile == NULL) |
| 2738 | debug_grab_textfile = (char *)malloc(128); |
| 2739 | strncpy(debug_grab_textfile, filename, 127); |
| 2740 | } |
| 2741 | |
| 2293 | 2742 | void nv2a_renderer::savestate_items() |
| 2294 | 2743 | { |
| 2295 | 2744 | } |
| r29543 | r29544 | |
| 3008 | 3457 | } |
| 3009 | 3458 | } |
| 3010 | 3459 | |
| 3460 | void chihiro_state::debug_grab_texture(int type, char *filename) |
| 3461 | { |
| 3462 | nvidia_nv2a->debug_grab_texture(type, filename); |
| 3463 | } |
| 3464 | |
| 3011 | 3465 | void chihiro_state::vblank_callback(screen_device &screen, bool state) |
| 3012 | 3466 | { |
| 3013 | 3467 | nvidia_nv2a->vblank_callback(screen,state); |
| r29543 | r29544 | |
| 3338 | 3792 | READ32_MEMBER( chihiro_state::audio_apu_r ) |
| 3339 | 3793 | { |
| 3340 | 3794 | logerror("Audio_APU: read from %08X mask %08X\n",0xfe800000+offset*4,mem_mask); |
| 3341 | | if (offset == 0x20010/4) |
| 3795 | if (offset == 0x20010/4) // some kind of internal counter or state value |
| 3342 | 3796 | return 0x20+4+8+0x48+0x80; |
| 3343 | | return 0; |
| 3797 | return apust.memory[offset]; |
| 3344 | 3798 | } |
| 3345 | 3799 | |
| 3346 | 3800 | WRITE32_MEMBER( chihiro_state::audio_apu_w ) |
| 3347 | 3801 | { |
| 3802 | //UINT32 old; |
| 3803 | UINT32 v; |
| 3804 | |
| 3348 | 3805 | logerror("Audio_APU: write at %08X mask %08X value %08X\n",0xfe800000+offset*4,mem_mask,data); |
| 3349 | | if (offset == 0x2040/4) |
| 3350 | | apust.memory0_sgaddress=data; |
| 3351 | | if (offset == 0x20d4/4) { |
| 3352 | | apust.memory0_sgblocks=data; |
| 3353 | | apust.memory0_address=apust.space->read_dword(apust.memory0_sgaddress); |
| 3806 | //old = apust.memory[offset]; |
| 3807 | apust.memory[offset] = data; |
| 3808 | if (offset == 0x02040/4) // address of memory area with scatter-gather info (gpdsp scratch dma) |
| 3809 | apust.gpdsp_sgaddress=data; |
| 3810 | if (offset == 0x020d4/4) { // block count (gpdsp) |
| 3811 | apust.gpdsp_sgblocks=data; |
| 3812 | apust.gpdsp_address=apust.space->read_dword(apust.gpdsp_sgaddress); // memory address of first block |
| 3354 | 3813 | apust.timer->enable(); |
| 3355 | 3814 | apust.timer->adjust(attotime::from_msec(1),0,attotime::from_msec(1)); |
| 3356 | 3815 | } |
| 3357 | | if (offset == 0x2048/4) |
| 3358 | | apust.memory1_sgaddress=data; |
| 3359 | | if (offset == 0x20dc/4) |
| 3360 | | apust.memory1_sgblocks=data; |
| 3816 | if (offset == 0x02048 / 4) // (epdsp scratch dma) |
| 3817 | apust.epdsp_sgaddress=data; |
| 3818 | if (offset == 0x020dc / 4) // (epdsp) |
| 3819 | apust.epdsp_sgblocks=data; |
| 3820 | if (offset == 0x0204c / 4) // address of memory area with information about blocks |
| 3821 | apust.unknown_sgaddress = data; |
| 3822 | if (offset == 0x020e0 / 4) // block count - 1 |
| 3823 | apust.unknown_sgblocks = data; |
| 3824 | if (offset == 0x0202c / 4) { // address of memory area with 0x80 bytes for each voice |
| 3825 | apust.voicedata_address = data; |
| 3826 | return; |
| 3827 | } |
| 3828 | if (offset == 0x04024 / 4) // offset in memory area indicated by 0x204c (analog output ?) |
| 3829 | return; |
| 3830 | if (offset == 0x04034 / 4) // size |
| 3831 | return; |
| 3832 | if (offset == 0x04028 / 4) // offset in memory area indicated by 0x204c (digital output ?) |
| 3833 | return; |
| 3834 | if (offset == 0x04038 / 4) // size |
| 3835 | return; |
| 3836 | if (offset == 0x20804 / 4) { // block number for scatter-gather heap that stores sampled audio to be played |
| 3837 | if (data >= 1024) { |
| 3838 | logerror("Audio_APU: sg block number too high, increase size of voices_heap_blockaddr\n"); |
| 3839 | apust.memory[offset] = 1023; |
| 3840 | } |
| 3841 | return; |
| 3842 | } |
| 3843 | if (offset == 0x20808 / 4) { // block address for scatter-gather heap that stores sampled audio to be played |
| 3844 | apust.voices_heap_blockaddr[apust.memory[0x20804 / 4]] = data; |
| 3845 | return; |
| 3846 | } |
| 3847 | if (offset == 0x202f8 / 4) { // voice number for parameters ? |
| 3848 | apust.voice_number = data; |
| 3849 | return; |
| 3850 | } |
| 3851 | if (offset == 0x202fc / 4) // 1 when accessing voice parameters 0 otherwise |
| 3852 | return; |
| 3853 | if (offset == 0x20304 / 4) { // format |
| 3854 | /* |
| 3855 | bits 28-31 sample format: |
| 3856 | 0 8-bit pcm |
| 3857 | 5 16-bit pcm |
| 3858 | 10 adpcm ? |
| 3859 | 14 24-bit pcm |
| 3860 | 15 32-bit pcm |
| 3861 | bits 16-20 number of channels - 1: |
| 3862 | 0 mono |
| 3863 | 1 stereo |
| 3864 | */ |
| 3865 | return; |
| 3866 | } |
| 3867 | if (offset == 0x2037c / 4) { // value related to sample rate |
| 3868 | INT16 v = (INT16)(data >> 16); // upper 16 bits as a signed 16 bit value |
| 3869 | float vv = ((float)v) / 4096.0; // divide by 4096 |
| 3870 | float vvv = powf(2, vv); // two to the vv |
| 3871 | int f = vvv*48000.0; // sample rate |
| 3872 | apust.voices_frequency[apust.voice_number] = f; |
| 3873 | return; |
| 3874 | } |
| 3875 | if (offset == 0x203a0 / 4) // start offset of data in scatter-gather heap |
| 3876 | return; |
| 3877 | if (offset == 0x203a4 / 4) { // first sample to play |
| 3878 | apust.voices_position_start[apust.voice_number] = data*1000; |
| 3879 | return; |
| 3880 | } |
| 3881 | if (offset == 0x203dc / 4) { // last sample to play |
| 3882 | apust.voices_position_end[apust.voice_number] = data*1000; |
| 3883 | return; |
| 3884 | } |
| 3885 | if (offset == 0x2010c / 4) // voice processor 0 idle 1 not idle ? |
| 3886 | return; |
| 3887 | if (offset == 0x20124 / 4) { // voice number to activate ? |
| 3888 | v = apust.voice_number; |
| 3889 | apust.voices_active[v >> 6] |= ((UINT64)1 << (v & 63)); |
| 3890 | apust.voices_position[v] = apust.voices_position_start[apust.voice_number]; |
| 3891 | apust.voices_position_increment[apust.voice_number] = apust.voices_frequency[apust.voice_number]; |
| 3892 | return; |
| 3893 | } |
| 3894 | if (offset == 0x20128 / 4) { // voice number to deactivate ? |
| 3895 | v = apust.voice_number; |
| 3896 | apust.voices_active[v >> 6] &= ~(1 << (v & 63)); |
| 3897 | return; |
| 3898 | } |
| 3899 | if (offset == 0x20140 / 4) // voice number to ? |
| 3900 | return; |
| 3901 | if ((offset >= 0x20200 / 4) && (offset < 0x20280 / 4)) // headroom for each of the 32 mixbins |
| 3902 | return; |
| 3903 | if (offset == 0x20280 / 4) // hrtf headroom ? |
| 3904 | return; |
| 3361 | 3905 | } |
| 3362 | 3906 | |
| 3363 | 3907 | READ32_MEMBER( chihiro_state::audio_ac93_r ) |
| r29543 | r29544 | |
| 3405 | 3949 | |
| 3406 | 3950 | TIMER_CALLBACK_MEMBER(chihiro_state::audio_apu_timer) |
| 3407 | 3951 | { |
| 3408 | | int cmd=apust.space->read_dword(apust.memory0_address+0x800+0x10); |
| 3952 | int cmd; |
| 3953 | int bb, b, v; |
| 3954 | UINT64 bv; |
| 3955 | UINT32 phys; |
| 3956 | |
| 3957 | cmd=apust.space->read_dword(apust.gpdsp_address+0x800+0x10); |
| 3409 | 3958 | if (cmd == 3) |
| 3410 | | apust.space->write_dword(apust.memory0_address+0x800+0x10,0); |
| 3959 | apust.space->write_dword(apust.gpdsp_address+0x800+0x10,0); |
| 3411 | 3960 | /*else |
| 3412 | | logerror("Audio_APU: unexpected value at address %d\n",apust.memory0_address+0x800+0x10);*/ |
| 3961 | logerror("Audio_APU: unexpected value at address %d\n",apust.gpdsp_address+0x800+0x10);*/ |
| 3962 | for (b = 0; b < 4; b++) { |
| 3963 | bv = 1; |
| 3964 | for (bb = 0; bb < 64; bb++) { |
| 3965 | if (apust.voices_active[b] & bv) { |
| 3966 | v = bb + (b << 6); |
| 3967 | apust.voices_position[v] += apust.voices_position_increment[v]; |
| 3968 | while (apust.voices_position[v] >= apust.voices_position_end[v]) |
| 3969 | apust.voices_position[v] = apust.voices_position_start[v] + apust.voices_position[v] - apust.voices_position_end[v] - 1000; |
| 3970 | phys = apust.voicedata_address + 0x80 * v; |
| 3971 | apust.space->write_dword(phys + 0x58, apust.voices_position[v] / 1000); |
| 3972 | } |
| 3973 | bv = bv << 1; |
| 3974 | } |
| 3975 | } |
| 3413 | 3976 | } |
| 3414 | 3977 | |
| 3415 | 3978 | /* |
| r29543 | r29544 | |
| 3902 | 4465 | if (chihiro_devs.dimmboard != NULL) { |
| 3903 | 4466 | dimm_board_memory=chihiro_devs.dimmboard->memory(dimm_board_memory_size); |
| 3904 | 4467 | } |
| 3905 | | apust.space=&m_maincpu->space(); |
| 4468 | memset(apust.memory, 0, sizeof(apust.memory)); |
| 4469 | memset(apust.voices_heap_blockaddr, 0, sizeof(apust.voices_heap_blockaddr)); |
| 4470 | memset(apust.voices_active, 0, sizeof(apust.voices_active)); |
| 4471 | memset(apust.voices_position, 0, sizeof(apust.voices_position)); |
| 4472 | memset(apust.voices_position_start, 0, sizeof(apust.voices_position_start)); |
| 4473 | memset(apust.voices_position_end, 0, sizeof(apust.voices_position_end)); |
| 4474 | memset(apust.voices_position_increment, 0, sizeof(apust.voices_position_increment)); |
| 4475 | apust.space = &m_maincpu->space(); |
| 3906 | 4476 | apust.timer=machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(chihiro_state::audio_apu_timer),this),(void *)"APU Timer"); |
| 3907 | 4477 | apust.timer->enable(false); |
| 3908 | 4478 | if (machine().debug_flags & DEBUG_FLAG_ENABLED) |