trunk/src/mess/machine/megacd.c
| r29441 | r29442 | |
| 2 | 2 | #include "machine/megacd.h" |
| 3 | 3 | #include "machine/nvram.h" |
| 4 | 4 | #include "megacd.lh" |
| 5 | | #include "sound/rf5c68.h" |
| 6 | 5 | |
| 7 | 6 | |
| 7 | const device_type SEGA_SEGACD_US = &device_creator<sega_segacd_us_device>; |
| 8 | const device_type SEGA_SEGACD_JAPAN = &device_creator<sega_segacd_japan_device>; |
| 9 | const device_type SEGA_SEGACD_EUROPE = &device_creator<sega_segacd_europe_device>; |
| 10 | |
| 11 | |
| 8 | 12 | /* Callback when the genesis enters interrupt code */ |
| 9 | 13 | IRQ_CALLBACK_MEMBER(sega_segacd_device::segacd_sub_int_callback) |
| 10 | 14 | { |
| r29441 | r29442 | |
| 19 | 23 | } |
| 20 | 24 | |
| 21 | 25 | |
| 22 | | const device_type SEGA_SEGACD_US = &device_creator<sega_segacd_us_device>; |
| 23 | | const device_type SEGA_SEGACD_JAPAN = &device_creator<sega_segacd_japan_device>; |
| 24 | | const device_type SEGA_SEGACD_EUROPE = &device_creator<sega_segacd_europe_device>; |
| 25 | | |
| 26 | | sega_segacd_device::sega_segacd_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) |
| 27 | | : device_t(mconfig, type, name, tag, owner, clock, shortname, source), |
| 28 | | m_scdcpu(*this, "segacd_68k"), |
| 29 | | m_gfxdecode(*this, "gfxdecode") |
| 26 | TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::irq3_timer_callback ) |
| 30 | 27 | { |
| 31 | | } |
| 32 | | |
| 33 | | sega_segacd_us_device::sega_segacd_us_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 34 | | : sega_segacd_device(mconfig, SEGA_SEGACD_US, "sega_segacd_us", tag, owner, clock, "sega_segacd_us", __FILE__) |
| 35 | | { |
| 36 | | } |
| 37 | | |
| 38 | | sega_segacd_japan_device::sega_segacd_japan_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 39 | | : sega_segacd_device(mconfig, SEGA_SEGACD_JAPAN, "sega_segacd_japan", tag, owner, clock, "sega_segacd_japan", __FILE__) |
| 40 | | { |
| 41 | | } |
| 42 | | |
| 43 | | sega_segacd_europe_device::sega_segacd_europe_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 44 | | : sega_segacd_device(mconfig, SEGA_SEGACD_EUROPE, "sega_segacd_europe", tag, owner, clock, "sega_segacd_europe", __FILE__) |
| 45 | | { |
| 46 | | } |
| 47 | | |
| 48 | | |
| 49 | | TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::segacd_irq3_timer_callback ) |
| 50 | | { |
| 51 | 28 | CHECK_SCD_LV3_INTERRUPT |
| 52 | | segacd_irq3_timer->adjust(SEGACD_IRQ3_TIMER_SPEED); |
| 29 | m_irq3_timer->adjust(SEGACD_IRQ3_TIMER_SPEED); |
| 53 | 30 | } |
| 54 | 31 | |
| 55 | 32 | |
| 56 | | TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::segacd_gfx_conversion_timer_callback ) |
| 33 | TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::stamp_timer_callback ) |
| 57 | 34 | { |
| 58 | | //printf("segacd_gfx_conversion_timer_callback\n"); |
| 35 | //printf("stamp_timer_callback\n"); |
| 59 | 36 | |
| 60 | 37 | CHECK_SCD_LV1_INTERRUPT |
| 61 | 38 | |
| r29441 | r29442 | |
| 66 | 43 | } |
| 67 | 44 | |
| 68 | 45 | |
| 69 | | |
| 70 | | |
| 71 | | ADDRESS_MAP_START( segacd_map, AS_PROGRAM, 16, sega_segacd_device ) |
| 72 | | AM_RANGE(0x000000, 0x07ffff) AM_RAM AM_SHARE("segacd_program") |
| 73 | | |
| 46 | static ADDRESS_MAP_START( segacd_map, AS_PROGRAM, 16, sega_segacd_device ) |
| 47 | AM_RANGE(0x000000, 0x07ffff) AM_RAM AM_SHARE("prgram") |
| 74 | 48 | AM_RANGE(0x080000, 0x0bffff) AM_READWRITE(segacd_sub_dataram_part1_r, segacd_sub_dataram_part1_w) AM_SHARE("dataram") |
| 75 | 49 | AM_RANGE(0x0c0000, 0x0dffff) AM_READWRITE(segacd_sub_dataram_part2_r, segacd_sub_dataram_part2_w) //AM_SHARE("dataram2") |
| 76 | 50 | |
| 77 | | AM_RANGE(0xfe0000, 0xfe3fff) AM_READWRITE(segacd_backupram_r,segacd_backupram_w) AM_SHARE("backupram") // backup RAM, odd bytes only! |
| 51 | AM_RANGE(0xfe0000, 0xfe3fff) AM_READWRITE8(backupram_r, backupram_w, 0x00ff) // backup RAM, odd bytes only! |
| 78 | 52 | |
| 79 | 53 | AM_RANGE(0xff0000, 0xff001f) AM_DEVWRITE8("rfsnd", rf5c68_device, rf5c68_w, 0x00ff) // PCM, RF5C164 |
| 80 | 54 | AM_RANGE(0xff0020, 0xff003f) AM_DEVREAD8("rfsnd", rf5c68_device, rf5c68_r, 0x00ff) |
| 81 | 55 | AM_RANGE(0xff2000, 0xff3fff) AM_DEVREADWRITE8("rfsnd", rf5c68_device, rf5c68_mem_r, rf5c68_mem_w,0x00ff) // PCM, RF5C164 |
| 82 | 56 | |
| 83 | | |
| 84 | 57 | AM_RANGE(0xff8000 ,0xff8001) AM_READWRITE(segacd_sub_led_ready_r, segacd_sub_led_ready_w) |
| 85 | 58 | AM_RANGE(0xff8002 ,0xff8003) AM_READWRITE(segacd_sub_memory_mode_r, segacd_sub_memory_mode_w) |
| 86 | 59 | |
| r29441 | r29442 | |
| 98 | 71 | AM_RANGE(0xff8036, 0xff8037) AM_DEVREADWRITE("tempcdc",lc89510_temp_device,segacd_cdd_ctrl_r,segacd_cdd_ctrl_w) |
| 99 | 72 | AM_RANGE(0xff8038, 0xff8041) AM_DEVREAD8("tempcdc",lc89510_temp_device,segacd_cdd_rx_r,0xffff) |
| 100 | 73 | AM_RANGE(0xff8042, 0xff804b) AM_DEVWRITE8("tempcdc",lc89510_temp_device,segacd_cdd_tx_w,0xffff) |
| 101 | | AM_RANGE(0xff804c, 0xff804d) AM_READWRITE(segacd_font_color_r, segacd_font_color_w) |
| 102 | | AM_RANGE(0xff804e, 0xff804f) AM_RAM AM_SHARE("segacd_font") |
| 103 | | AM_RANGE(0xff8050, 0xff8057) AM_READ(segacd_font_converted_r) |
| 74 | AM_RANGE(0xff804c, 0xff804d) AM_READWRITE8(font_color_r, font_color_w, 0x00ff) |
| 75 | AM_RANGE(0xff804e, 0xff804f) AM_RAM AM_SHARE("font_bits") |
| 76 | AM_RANGE(0xff8050, 0xff8057) AM_READ(font_converted_r) |
| 104 | 77 | AM_RANGE(0xff8058, 0xff8059) AM_READWRITE(segacd_stampsize_r, segacd_stampsize_w) // Stamp size |
| 105 | 78 | AM_RANGE(0xff805a, 0xff805b) AM_READWRITE(segacd_stampmap_base_address_r, segacd_stampmap_base_address_w) // Stamp map base address |
| 106 | 79 | AM_RANGE(0xff805c, 0xff805d) AM_READWRITE(segacd_imagebuffer_vcell_size_r, segacd_imagebuffer_vcell_size_w)// Image buffer V cell size |
| r29441 | r29442 | |
| 126 | 99 | #define SEGACD_NUM_TILES16 (0x40000/SEGACD_BYTES_PER_TILE16) |
| 127 | 100 | #define SEGACD_NUM_TILES32 (0x40000/SEGACD_BYTES_PER_TILE32) |
| 128 | 101 | |
| 129 | | #define _16x16_SEQUENCE_1 { 8,12,0,4,24,28,16,20, 512+8, 512+12, 512+0, 512+4, 512+24, 512+28, 512+16, 512+20 }, |
| 130 | | #define _16x16_SEQUENCE_1_FLIP { 512+20,512+16,512+28,512+24,512+4,512+0, 512+12,512+8, 20,16,28,24,4,0,12,8 }, |
| 102 | #define _16x16_SEQUENCE_1 { STEP8(0, 4), STEP8(512, 4) }, |
| 103 | #define _16x16_SEQUENCE_1_FLIP { STEP8(512+28, -4), STEP8(28, -4) }, |
| 131 | 104 | |
| 132 | | #define _16x16_SEQUENCE_2 { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32, 8*32, 9*32,10*32,11*32,12*32,13*32,14*32,15*32 }, |
| 133 | | #define _16x16_SEQUENCE_2_FLIP { 15*32, 14*32, 13*32, 12*32, 11*32, 10*32, 9*32, 8*32, 7*32, 6*32, 5*32, 4*32, 3*32, 2*32, 1*32, 0*32 }, |
| 105 | #define _16x16_SEQUENCE_2 { STEP16(0, 32) }, |
| 106 | #define _16x16_SEQUENCE_2_FLIP { STEP16(15*32, -32) }, |
| 134 | 107 | |
| 135 | 108 | |
| 136 | 109 | #define _16x16_START \ |
| r29441 | r29442 | |
| 153 | 126 | 8*512 \ |
| 154 | 127 | }; |
| 155 | 128 | |
| 129 | #define _32x32_SEQUENCE_1 { STEP8(0, 4), STEP8(1024, 4), STEP8(2048, 4), STEP8(3072, 4) }, |
| 130 | #define _32x32_SEQUENCE_1_FLIP { STEP8(3072+28, -4), STEP8(2048+28, -4), STEP8(1024+28, -4), STEP8(28, -4) }, |
| 156 | 131 | |
| 157 | | #define _32x32_SEQUENCE_1 \ |
| 158 | | { 8,12,0,4,24,28,16,20, \ |
| 159 | | 1024+8, 1024+12, 1024+0, 1024+4, 1024+24, 1024+28, 1024+16, 1024+20, \ |
| 160 | | 2048+8, 2048+12, 2048+0, 2048+4, 2048+24, 2048+28, 2048+16, 2048+20, \ |
| 161 | | 3072+8, 3072+12, 3072+0, 3072+4, 3072+24, 3072+28, 3072+16, 3072+20 \ |
| 162 | | }, |
| 163 | | #define _32x32_SEQUENCE_1_FLIP \ |
| 164 | | { 3072+20, 3072+16, 3072+28, 3072+24, 3072+4, 3072+0, 3072+12, 3072+8, \ |
| 165 | | 2048+20, 2048+16, 2048+28, 2048+24, 2048+4, 2048+0, 2048+12, 2048+8, \ |
| 166 | | 1024+20, 1024+16, 1024+28, 1024+24, 1024+4, 1024+0, 1024+12, 1024+8, \ |
| 167 | | 20, 16, 28, 24, 4, 0, 12, 8}, |
| 132 | #define _32x32_SEQUENCE_2 { STEP32(0, 32) }, |
| 133 | #define _32x32_SEQUENCE_2_FLIP { STEP32(31*32, -32) }, |
| 168 | 134 | |
| 169 | | #define _32x32_SEQUENCE_2 \ |
| 170 | | { 0*32, 1*32, 2*32, 3*32, 4*32, 5*32, 6*32, 7*32, \ |
| 171 | | 8*32, 9*32, 10*32, 11*32, 12*32, 13*32, 14*32, 15*32, \ |
| 172 | | 16*32,17*32,18*32,19*32,20*32,21*32,22*32,23*32, \ |
| 173 | | 24*32,25*32, 26*32, 27*32, 28*32, 29*32, 30*32, 31*32}, |
| 174 | | #define _32x32_SEQUENCE_2_FLIP \ |
| 175 | | { 31*32, 30*32, 29*32, 28*32, 27*32, 26*32, 25*32, 24*32, \ |
| 176 | | 23*32, 22*32, 21*32, 20*32, 19*32, 18*32, 17*32, 16*32, \ |
| 177 | | 15*32, 14*32, 13*32, 12*32, 11*32, 10*32, 9*32 , 8*32 , \ |
| 178 | | 7*32 , 6*32 , 5*32 , 4*32 , 3*32 , 2*32 , 1*32 , 0*32}, |
| 179 | 135 | |
| 180 | 136 | /* 16x16 decodes */ |
| 181 | 137 | static const gfx_layout sega_16x16_r00_f0_layout = |
| r29441 | r29442 | |
| 275 | 231 | _32x32_SEQUENCE_1_FLIP |
| 276 | 232 | _32x32_END |
| 277 | 233 | |
| 278 | | GFXDECODE_START( segacd ) |
| 279 | | GFXDECODE_ENTRY( NULL, 0, sega_16x16_r00_f0_layout, 0, 0 ) |
| 280 | | GFXDECODE_ENTRY( NULL, 0, sega_16x16_r01_f0_layout, 0, 0 ) |
| 281 | | GFXDECODE_ENTRY( NULL, 0, sega_16x16_r10_f0_layout, 0, 0 ) |
| 282 | | GFXDECODE_ENTRY( NULL, 0, sega_16x16_r11_f0_layout, 0, 0 ) |
| 283 | | GFXDECODE_ENTRY( NULL, 0, sega_16x16_r00_f1_layout, 0, 0 ) |
| 284 | | GFXDECODE_ENTRY( NULL, 0, sega_16x16_r11_f1_layout, 0, 0 ) |
| 285 | | GFXDECODE_ENTRY( NULL, 0, sega_16x16_r10_f1_layout, 0, 0 ) |
| 286 | | GFXDECODE_ENTRY( NULL, 0, sega_16x16_r01_f1_layout, 0, 0 ) |
| 287 | | GFXDECODE_ENTRY( NULL, 0, sega_32x32_r00_f0_layout, 0, 0 ) |
| 288 | | GFXDECODE_ENTRY( NULL, 0, sega_32x32_r01_f0_layout, 0, 0 ) |
| 289 | | GFXDECODE_ENTRY( NULL, 0, sega_32x32_r10_f0_layout, 0, 0 ) |
| 290 | | GFXDECODE_ENTRY( NULL, 0, sega_32x32_r11_f0_layout, 0, 0 ) |
| 291 | | GFXDECODE_ENTRY( NULL, 0, sega_32x32_r00_f1_layout, 0, 0 ) |
| 292 | | GFXDECODE_ENTRY( NULL, 0, sega_32x32_r11_f1_layout, 0, 0 ) |
| 293 | | GFXDECODE_ENTRY( NULL, 0, sega_32x32_r10_f1_layout, 0, 0 ) |
| 294 | | GFXDECODE_ENTRY( NULL, 0, sega_32x32_r01_f1_layout, 0, 0 ) |
| 234 | static GFXDECODE_START( segacd ) |
| 235 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r00_f0_layout, 0, 0 ) |
| 236 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r01_f0_layout, 0, 0 ) |
| 237 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r10_f0_layout, 0, 0 ) |
| 238 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r11_f0_layout, 0, 0 ) |
| 239 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r00_f1_layout, 0, 0 ) |
| 240 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r11_f1_layout, 0, 0 ) |
| 241 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r10_f1_layout, 0, 0 ) |
| 242 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_16x16_r01_f1_layout, 0, 0 ) |
| 243 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r00_f0_layout, 0, 0 ) |
| 244 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r01_f0_layout, 0, 0 ) |
| 245 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r10_f0_layout, 0, 0 ) |
| 246 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r11_f0_layout, 0, 0 ) |
| 247 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r00_f1_layout, 0, 0 ) |
| 248 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r11_f1_layout, 0, 0 ) |
| 249 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r10_f1_layout, 0, 0 ) |
| 250 | GFXDECODE_DEVICE_RAM( "dataram", 0, sega_32x32_r01_f1_layout, 0, 0 ) |
| 295 | 251 | GFXDECODE_END |
| 296 | 252 | |
| 297 | 253 | |
| 298 | | |
| 299 | 254 | static MACHINE_CONFIG_FRAGMENT( segacd_fragment ) |
| 300 | 255 | |
| 301 | 256 | MCFG_CPU_ADD("segacd_68k", M68000, SEGACD_CLOCK ) /* 12.5 MHz */ |
| r29441 | r29442 | |
| 308 | 263 | MCFG_SEGACD_HACK_SET_CDC_DO_DMA( sega_segacd_device, SegaCD_CDC_Do_DMA ) // hack |
| 309 | 264 | |
| 310 | 265 | MCFG_TIMER_ADD_NONE("sw_timer") //stopwatch timer |
| 311 | | MCFG_TIMER_DRIVER_ADD("irq3_timer", sega_segacd_device, segacd_irq3_timer_callback) |
| 312 | | MCFG_TIMER_DRIVER_ADD("stamp_timer", sega_segacd_device, segacd_gfx_conversion_timer_callback) |
| 313 | | MCFG_TIMER_DRIVER_ADD("scd_dma_timer", sega_segacd_device, scd_dma_timer_callback) |
| 266 | MCFG_TIMER_DRIVER_ADD("stamp_timer", sega_segacd_device, stamp_timer_callback) |
| 267 | MCFG_TIMER_DRIVER_ADD("irq3_timer", sega_segacd_device, irq3_timer_callback) |
| 268 | MCFG_TIMER_DRIVER_ADD("dma_timer", sega_segacd_device, dma_timer_callback) |
| 314 | 269 | |
| 315 | | MCFG_GFXDECODE_ADD("gfxdecode", "^gen_vdp:palette", segacd) // FIXME |
| 316 | | |
| 317 | 270 | MCFG_DEFAULT_LAYOUT( layout_megacd ) |
| 318 | 271 | |
| 319 | 272 | MCFG_RF5C68_ADD("rfsnd", SEGACD_CLOCK) // RF5C164! |
| r29441 | r29442 | |
| 333 | 286 | } |
| 334 | 287 | |
| 335 | 288 | |
| 289 | sega_segacd_device::sega_segacd_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source) |
| 290 | : device_t(mconfig, type, name, tag, owner, clock, shortname, source), |
| 291 | device_gfx_interface(mconfig, *this, GFXDECODE_NAME( segacd )), |
| 292 | m_scdcpu(*this, "segacd_68k"), |
| 293 | m_rfsnd(*this, "rfsnd"), |
| 294 | m_lc89510_temp(*this, "tempcdc"), |
| 295 | m_stopwatch_timer(*this, "sw_timer"), |
| 296 | m_stamp_timer(*this, "stamp_timer"), |
| 297 | m_irq3_timer(*this, "irq3_timer"), |
| 298 | m_dma_timer(*this, "dma_timer"), |
| 299 | m_prgram(*this, "prgram"), |
| 300 | m_dataram(*this, "dataram"), |
| 301 | m_font_bits(*this, "font_bits") |
| 302 | { |
| 303 | } |
| 336 | 304 | |
| 305 | sega_segacd_us_device::sega_segacd_us_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 306 | : sega_segacd_device(mconfig, SEGA_SEGACD_US, "sega_segacd_us", tag, owner, clock, "sega_segacd_us", __FILE__) |
| 307 | { |
| 308 | } |
| 337 | 309 | |
| 310 | sega_segacd_japan_device::sega_segacd_japan_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 311 | : sega_segacd_device(mconfig, SEGA_SEGACD_JAPAN, "sega_segacd_japan", tag, owner, clock, "sega_segacd_japan", __FILE__) |
| 312 | { |
| 313 | } |
| 338 | 314 | |
| 315 | sega_segacd_europe_device::sega_segacd_europe_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 316 | : sega_segacd_device(mconfig, SEGA_SEGACD_EUROPE, "sega_segacd_europe", tag, owner, clock, "sega_segacd_europe", __FILE__) |
| 317 | { |
| 318 | } |
| 339 | 319 | |
| 340 | | inline void sega_segacd_device::write_pixel(running_machine& machine, UINT8 pix, int pixeloffset ) |
| 320 | |
| 321 | inline void sega_segacd_device::write_pixel(UINT8 pix, int pixeloffset) |
| 341 | 322 | { |
| 342 | 323 | int shift = 12-(4*(pixeloffset&0x3)); |
| 343 | 324 | UINT16 datamask = (0x000f) << shift; |
| r29441 | r29442 | |
| 350 | 331 | switch (segacd_memory_priority_mode) |
| 351 | 332 | { |
| 352 | 333 | case 0x00: // normal write, just write the data |
| 353 | | segacd_dataram[offset] = segacd_dataram[offset] &~ datamask; |
| 354 | | segacd_dataram[offset] |= pix << shift; |
| 334 | m_dataram[offset] = m_dataram[offset] &~ datamask; |
| 335 | m_dataram[offset] |= pix << shift; |
| 355 | 336 | break; |
| 356 | 337 | |
| 357 | 338 | case 0x01: // underwrite, only write if the existing data is 0 |
| 358 | | if ((segacd_dataram[offset]&datamask) == 0x0000) |
| 339 | if ((m_dataram[offset]&datamask) == 0x0000) |
| 359 | 340 | { |
| 360 | | segacd_dataram[offset] = segacd_dataram[offset] &~ datamask; |
| 361 | | segacd_dataram[offset] |= pix << shift; |
| 341 | m_dataram[offset] = m_dataram[offset] &~ datamask; |
| 342 | m_dataram[offset] |= pix << shift; |
| 362 | 343 | } |
| 363 | 344 | break; |
| 364 | 345 | |
| 365 | 346 | case 0x02: // overwrite, only write non-zero data |
| 366 | 347 | if (pix) |
| 367 | 348 | { |
| 368 | | segacd_dataram[offset] = segacd_dataram[offset] &~ datamask; |
| 369 | | segacd_dataram[offset] |= pix << shift; |
| 349 | m_dataram[offset] = m_dataram[offset] &~ datamask; |
| 350 | m_dataram[offset] |= pix << shift; |
| 370 | 351 | } |
| 371 | 352 | break; |
| 372 | 353 | |
| 373 | 354 | default: |
| 374 | 355 | case 0x03: |
| 375 | | pix = machine.rand() & 0x000f; |
| 376 | | segacd_dataram[offset] = segacd_dataram[offset] &~ datamask; |
| 377 | | segacd_dataram[offset] |= pix << shift; |
| 356 | pix = machine().rand() & 0x000f; |
| 357 | m_dataram[offset] = m_dataram[offset] &~ datamask; |
| 358 | m_dataram[offset] |= pix << shift; |
| 378 | 359 | break; |
| 379 | 360 | |
| 380 | 361 | } |
| r29441 | r29442 | |
| 393 | 374 | |
| 394 | 375 | offset &=0x1ffff; |
| 395 | 376 | |
| 396 | | return segacd_dataram[offset]; |
| 377 | return m_dataram[offset]; |
| 397 | 378 | } |
| 398 | 379 | |
| 399 | 380 | |
| r29441 | r29442 | |
| 413 | 394 | switch (segacd_memory_priority_mode) |
| 414 | 395 | { |
| 415 | 396 | case 0x00: // normal write, just write the data |
| 416 | | COMBINE_DATA(&segacd_dataram[offset]); |
| 397 | COMBINE_DATA(&m_dataram[offset]); |
| 417 | 398 | break; |
| 418 | 399 | |
| 419 | 400 | case 0x01: // underwrite, only write if the existing data is 0 |
| 420 | 401 | if (ACCESSING_BITS_8_15) |
| 421 | 402 | { |
| 422 | | if ((segacd_dataram[offset]&0xf000) == 0x0000) segacd_dataram[offset] |= (data)&0xf000; |
| 423 | | if ((segacd_dataram[offset]&0x0f00) == 0x0000) segacd_dataram[offset] |= (data)&0x0f00; |
| 403 | if ((m_dataram[offset]&0xf000) == 0x0000) m_dataram[offset] |= (data)&0xf000; |
| 404 | if ((m_dataram[offset]&0x0f00) == 0x0000) m_dataram[offset] |= (data)&0x0f00; |
| 424 | 405 | } |
| 425 | 406 | if (ACCESSING_BITS_0_7) |
| 426 | 407 | { |
| 427 | | if ((segacd_dataram[offset]&0x00f0) == 0x0000) segacd_dataram[offset] |= (data)&0x00f0; |
| 428 | | if ((segacd_dataram[offset]&0x000f) == 0x0000) segacd_dataram[offset] |= (data)&0x000f; |
| 408 | if ((m_dataram[offset]&0x00f0) == 0x0000) m_dataram[offset] |= (data)&0x00f0; |
| 409 | if ((m_dataram[offset]&0x000f) == 0x0000) m_dataram[offset] |= (data)&0x000f; |
| 429 | 410 | } |
| 430 | 411 | break; |
| 431 | 412 | |
| 432 | 413 | case 0x02: // overwrite, only write non-zero data |
| 433 | 414 | if (ACCESSING_BITS_8_15) |
| 434 | 415 | { |
| 435 | | if ((data)&0xf000) segacd_dataram[offset] = (segacd_dataram[offset] & 0x0fff) | ((data)&0xf000); |
| 436 | | if ((data)&0x0f00) segacd_dataram[offset] = (segacd_dataram[offset] & 0xf0ff) | ((data)&0x0f00); |
| 416 | if ((data)&0xf000) m_dataram[offset] = (m_dataram[offset] & 0x0fff) | ((data)&0xf000); |
| 417 | if ((data)&0x0f00) m_dataram[offset] = (m_dataram[offset] & 0xf0ff) | ((data)&0x0f00); |
| 437 | 418 | } |
| 438 | 419 | if (ACCESSING_BITS_0_7) |
| 439 | 420 | { |
| 440 | | if ((data)&0x00f0) segacd_dataram[offset] = (segacd_dataram[offset] & 0xff0f) | ((data)&0x00f0); |
| 441 | | if ((data)&0x000f) segacd_dataram[offset] = (segacd_dataram[offset] & 0xfff0) | ((data)&0x000f); |
| 421 | if ((data)&0x00f0) m_dataram[offset] = (m_dataram[offset] & 0xff0f) | ((data)&0x00f0); |
| 422 | if ((data)&0x000f) m_dataram[offset] = (m_dataram[offset] & 0xfff0) | ((data)&0x000f); |
| 442 | 423 | } |
| 443 | 424 | break; |
| 444 | 425 | |
| 445 | 426 | default: |
| 446 | 427 | case 0x03: // invalid? |
| 447 | | COMBINE_DATA(&segacd_dataram[offset]); |
| 428 | COMBINE_DATA(&m_dataram[offset]); |
| 448 | 429 | break; |
| 449 | 430 | |
| 450 | 431 | } |
| 451 | 432 | } |
| 452 | 433 | else |
| 453 | 434 | { |
| 454 | | COMBINE_DATA(&segacd_dataram[offset]); |
| 435 | COMBINE_DATA(&m_dataram[offset]); |
| 455 | 436 | } |
| 456 | 437 | } |
| 457 | 438 | |
| r29441 | r29442 | |
| 731 | 712 | READ16_MEMBER( sega_segacd_device::scd_4m_prgbank_ram_r ) |
| 732 | 713 | { |
| 733 | 714 | UINT16 realoffset = ((segacd_4meg_prgbank * 0x20000)/2) + offset; |
| 734 | | return segacd_4meg_prgram[realoffset]; |
| 715 | return m_prgram[realoffset]; |
| 735 | 716 | |
| 736 | 717 | } |
| 737 | 718 | |
| r29441 | r29442 | |
| 742 | 723 | // todo: |
| 743 | 724 | // check for write protection? (or does that only apply to writes on the SubCPU side? |
| 744 | 725 | |
| 745 | | COMBINE_DATA(&segacd_4meg_prgram[realoffset]); |
| 726 | COMBINE_DATA(&m_prgram[realoffset]); |
| 746 | 727 | |
| 747 | 728 | } |
| 748 | 729 | |
| r29441 | r29442 | |
| 797 | 778 | // is this correct? |
| 798 | 779 | if (!(scd_rammode&1)) |
| 799 | 780 | { |
| 800 | | //printf("segacd_main_dataram_part1_r in mode 0 %08x %04x\n", offset*2, segacd_dataram[offset]); |
| 781 | //printf("segacd_main_dataram_part1_r in mode 0 %08x %04x\n", offset*2, m_dataram[offset]); |
| 801 | 782 | |
| 802 | | return segacd_dataram[offset]; |
| 783 | return m_dataram[offset]; |
| 803 | 784 | |
| 804 | 785 | } |
| 805 | 786 | else |
| r29441 | r29442 | |
| 864 | 845 | // is this correct? |
| 865 | 846 | if (!(scd_rammode&1)) |
| 866 | 847 | { |
| 867 | | COMBINE_DATA(&segacd_dataram[offset]); |
| 868 | | segacd_mark_tiles_dirty(space.machine(), offset); |
| 848 | COMBINE_DATA(&m_dataram[offset]); |
| 849 | segacd_mark_tiles_dirty(offset); |
| 869 | 850 | } |
| 870 | 851 | else |
| 871 | 852 | { |
| r29441 | r29442 | |
| 925 | 906 | } |
| 926 | 907 | |
| 927 | 908 | |
| 928 | | |
| 929 | | |
| 930 | | |
| 931 | | |
| 932 | | void sega_segacd_device::segacd_mark_tiles_dirty(running_machine& machine, int offset) |
| 909 | void sega_segacd_device::segacd_mark_tiles_dirty(int offset) |
| 933 | 910 | { |
| 934 | | m_gfxdecode->gfx(0)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 935 | | m_gfxdecode->gfx(1)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 936 | | m_gfxdecode->gfx(2)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 937 | | m_gfxdecode->gfx(3)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 938 | | m_gfxdecode->gfx(4)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 939 | | m_gfxdecode->gfx(5)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 940 | | m_gfxdecode->gfx(6)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 941 | | m_gfxdecode->gfx(7)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 911 | gfx(0)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 912 | gfx(1)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 913 | gfx(2)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 914 | gfx(3)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 915 | gfx(4)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 916 | gfx(5)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 917 | gfx(6)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 918 | gfx(7)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE16)); |
| 942 | 919 | |
| 943 | | m_gfxdecode->gfx(8)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 944 | | m_gfxdecode->gfx(9)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 945 | | m_gfxdecode->gfx(10)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 946 | | m_gfxdecode->gfx(11)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 947 | | m_gfxdecode->gfx(12)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 948 | | m_gfxdecode->gfx(13)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 949 | | m_gfxdecode->gfx(14)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 950 | | m_gfxdecode->gfx(15)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 920 | gfx(8)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 921 | gfx(9)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 922 | gfx(10)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 923 | gfx(11)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 924 | gfx(12)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 925 | gfx(13)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 926 | gfx(14)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 927 | gfx(15)->mark_dirty((offset*2)/(SEGACD_BYTES_PER_TILE32)); |
| 951 | 928 | } |
| 952 | 929 | |
| 953 | 930 | |
| r29441 | r29442 | |
| 964 | 941 | tile_region = 0; // 16x16 tiles |
| 965 | 942 | int tile_base = (segacd_stampmap_base_address & 0xff80) * 4; |
| 966 | 943 | |
| 967 | | int tiledat = segacd_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; |
| 944 | int tiledat = m_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; |
| 968 | 945 | tileno = tiledat & 0x07ff; |
| 969 | 946 | int xflip = tiledat & 0x8000; |
| 970 | 947 | int roll = (tiledat & 0x6000)>>13; |
| r29441 | r29442 | |
| 978 | 955 | tile_region = 8; // 32x32 tiles |
| 979 | 956 | int tile_base = (segacd_stampmap_base_address & 0xffe0) * 4; |
| 980 | 957 | |
| 981 | | int tiledat = segacd_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; |
| 958 | int tiledat = m_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; |
| 982 | 959 | tileno = (tiledat & 0x07fc)>>2; |
| 983 | 960 | int xflip = tiledat & 0x8000; |
| 984 | 961 | int roll = (tiledat & 0x6000)>>13; |
| r29441 | r29442 | |
| 993 | 970 | tile_region = 0; // 16x16 tiles |
| 994 | 971 | int tile_base = (0x8000) * 4; // fixed address in this mode |
| 995 | 972 | |
| 996 | | int tiledat = segacd_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; |
| 973 | int tiledat = m_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; |
| 997 | 974 | tileno = tiledat & 0x07ff; |
| 998 | 975 | int xflip = tiledat & 0x8000; |
| 999 | 976 | int roll = (tiledat & 0x6000)>>13; |
| r29441 | r29442 | |
| 1008 | 985 | tile_region = 8; // 32x32 tiles |
| 1009 | 986 | int tile_base = (segacd_stampmap_base_address & 0xe000) * 4; |
| 1010 | 987 | |
| 1011 | | int tiledat = segacd_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; |
| 988 | int tiledat = m_dataram[((tile_base>>1)+tile_index) & 0x1ffff]; |
| 1012 | 989 | tileno = (tiledat & 0x07fc)>>2; |
| 1013 | 990 | int xflip = tiledat & 0x8000; |
| 1014 | 991 | int roll = (tiledat & 0x6000)>>13; |
| r29441 | r29442 | |
| 1052 | 1029 | |
| 1053 | 1030 | // non-tilemap functions to get a pixel from a 'tilemap' based on the above, but looking up each pixel, as to avoid the heavy cache bitmap |
| 1054 | 1031 | |
| 1055 | | inline UINT8 sega_segacd_device::get_stampmap_16x16_1x1_tile_info_pixel(running_machine& machine, int xpos, int ypos) |
| 1032 | inline UINT8 sega_segacd_device::get_stampmap_16x16_1x1_tile_info_pixel(int xpos, int ypos) |
| 1056 | 1033 | { |
| 1057 | 1034 | const int tilesize = 4; // 0xf pixels |
| 1058 | 1035 | const int tilemapsize = 0x0f; |
| r29441 | r29442 | |
| 1082 | 1059 | int tile_region, tileno; |
| 1083 | 1060 | SCD_GET_TILE_INFO_16x16_1x1(tile_region,tileno,(int)tile_index); |
| 1084 | 1061 | |
| 1085 | | gfx_element *gfx = m_gfxdecode->gfx(tile_region); |
| 1086 | | tileno %= gfx->elements(); |
| 1062 | tileno %= gfx(tile_region)->elements(); |
| 1087 | 1063 | |
| 1088 | 1064 | if (tileno==0) return 0x00; |
| 1089 | 1065 | |
| 1090 | | const UINT8* srcdata = gfx->get_data(tileno); |
| 1066 | const UINT8* srcdata = gfx(tile_region)->get_data(tileno); |
| 1091 | 1067 | return srcdata[((ypos&((1<<tilesize)-1))*(1<<tilesize))+(xpos&((1<<tilesize)-1))]; |
| 1092 | 1068 | } |
| 1093 | 1069 | |
| 1094 | | inline UINT8 sega_segacd_device::get_stampmap_32x32_1x1_tile_info_pixel(running_machine& machine, int xpos, int ypos) |
| 1070 | inline UINT8 sega_segacd_device::get_stampmap_32x32_1x1_tile_info_pixel(int xpos, int ypos) |
| 1095 | 1071 | { |
| 1096 | 1072 | const int tilesize = 5; // 0x1f pixels |
| 1097 | 1073 | const int tilemapsize = 0x07; |
| r29441 | r29442 | |
| 1121 | 1097 | int tile_region, tileno; |
| 1122 | 1098 | SCD_GET_TILE_INFO_32x32_1x1(tile_region,tileno,(int)tile_index); |
| 1123 | 1099 | |
| 1124 | | gfx_element *gfx = m_gfxdecode->gfx(tile_region); |
| 1125 | | tileno %= gfx->elements(); |
| 1100 | tileno %= gfx(tile_region)->elements(); |
| 1126 | 1101 | |
| 1127 | 1102 | if (tileno==0) return 0x00; // does this apply in this mode? |
| 1128 | 1103 | |
| 1129 | | const UINT8* srcdata = gfx->get_data(tileno); |
| 1104 | const UINT8* srcdata = gfx(tile_region)->get_data(tileno); |
| 1130 | 1105 | return srcdata[((ypos&((1<<tilesize)-1))*(1<<tilesize))+(xpos&((1<<tilesize)-1))]; |
| 1131 | 1106 | } |
| 1132 | 1107 | |
| 1133 | | inline UINT8 sega_segacd_device::get_stampmap_16x16_16x16_tile_info_pixel(running_machine& machine, int xpos, int ypos) |
| 1108 | inline UINT8 sega_segacd_device::get_stampmap_16x16_16x16_tile_info_pixel(int xpos, int ypos) |
| 1134 | 1109 | { |
| 1135 | 1110 | const int tilesize = 4; // 0xf pixels |
| 1136 | 1111 | const int tilemapsize = 0xff; |
| r29441 | r29442 | |
| 1160 | 1135 | int tile_region, tileno; |
| 1161 | 1136 | SCD_GET_TILE_INFO_16x16_16x16(tile_region,tileno,(int)tile_index); |
| 1162 | 1137 | |
| 1163 | | gfx_element *gfx = m_gfxdecode->gfx(tile_region); |
| 1164 | | tileno %= gfx->elements(); |
| 1138 | tileno %= gfx(tile_region)->elements(); |
| 1165 | 1139 | |
| 1166 | 1140 | if (tileno==0) return 0x00; // does this apply in this mode |
| 1167 | 1141 | |
| 1168 | | const UINT8* srcdata = gfx->get_data(tileno); |
| 1142 | const UINT8* srcdata = gfx(tile_region)->get_data(tileno); |
| 1169 | 1143 | return srcdata[((ypos&((1<<tilesize)-1))*(1<<tilesize))+(xpos&((1<<tilesize)-1))]; |
| 1170 | 1144 | } |
| 1171 | 1145 | |
| 1172 | | inline UINT8 sega_segacd_device::get_stampmap_32x32_16x16_tile_info_pixel(running_machine& machine, int xpos, int ypos) |
| 1146 | inline UINT8 sega_segacd_device::get_stampmap_32x32_16x16_tile_info_pixel(int xpos, int ypos) |
| 1173 | 1147 | { |
| 1174 | 1148 | const int tilesize = 5; // 0x1f pixels |
| 1175 | 1149 | const int tilemapsize = 0x7f; |
| r29441 | r29442 | |
| 1199 | 1173 | int tile_region, tileno; |
| 1200 | 1174 | SCD_GET_TILE_INFO_32x32_16x16(tile_region,tileno,(int)tile_index); |
| 1201 | 1175 | |
| 1202 | | gfx_element *gfx = m_gfxdecode->gfx(tile_region); |
| 1203 | | tileno %= gfx->elements(); |
| 1176 | tileno %= gfx(tile_region)->elements(); |
| 1204 | 1177 | |
| 1205 | 1178 | if (tileno==0) return 0x00; |
| 1206 | 1179 | |
| 1207 | | const UINT8* srcdata = gfx->get_data(tileno); |
| 1180 | const UINT8* srcdata = gfx(tile_region)->get_data(tileno); |
| 1208 | 1181 | return srcdata[((ypos&((1<<tilesize)-1))*(1<<tilesize))+(xpos&((1<<tilesize)-1))]; |
| 1209 | 1182 | } |
| 1210 | 1183 | |
| r29441 | r29442 | |
| 1213 | 1186 | WRITE16_MEMBER( sega_segacd_device::segacd_stopwatch_timer_w ) |
| 1214 | 1187 | { |
| 1215 | 1188 | if(data == 0) |
| 1216 | | stopwatch_timer->reset(); |
| 1189 | m_stopwatch_timer->reset(); |
| 1217 | 1190 | else |
| 1218 | 1191 | printf("Stopwatch timer %04x\n",data); |
| 1219 | 1192 | } |
| 1220 | 1193 | |
| 1221 | 1194 | READ16_MEMBER( sega_segacd_device::segacd_stopwatch_timer_r ) |
| 1222 | 1195 | { |
| 1223 | | INT32 result = (stopwatch_timer->time_elapsed() * ATTOSECONDS_TO_HZ(ATTOSECONDS_IN_USEC(30.72))).as_double(); |
| 1196 | INT32 result = (m_stopwatch_timer->time_elapsed() * ATTOSECONDS_TO_HZ(ATTOSECONDS_IN_USEC(30.72))).as_double(); |
| 1224 | 1197 | |
| 1225 | 1198 | return result & 0xfff; |
| 1226 | 1199 | } |
| r29441 | r29442 | |
| 1279 | 1252 | { |
| 1280 | 1253 | // is this correct? |
| 1281 | 1254 | if (scd_rammode&1) |
| 1282 | | return segacd_dataram[offset]; |
| 1255 | return m_dataram[offset]; |
| 1283 | 1256 | else |
| 1284 | 1257 | { |
| 1285 | 1258 | //printf("Illegal: segacd_sub_dataram_part1_r in mode 0 without permission\n"); |
| r29441 | r29442 | |
| 1322 | 1295 | // is this correct? |
| 1323 | 1296 | if (scd_rammode&1) |
| 1324 | 1297 | { |
| 1325 | | COMBINE_DATA(&segacd_dataram[offset]); |
| 1326 | | segacd_mark_tiles_dirty(space.machine(), offset); |
| 1298 | COMBINE_DATA(&m_dataram[offset]); |
| 1299 | segacd_mark_tiles_dirty(offset); |
| 1327 | 1300 | } |
| 1328 | 1301 | else |
| 1329 | 1302 | { |
| r29441 | r29442 | |
| 1452 | 1425 | // the lower 3 bits of segacd_imagebuffer_hdot_size are set |
| 1453 | 1426 | |
| 1454 | 1427 | // this really needs to be doing it's own lookups rather than depending on the inefficient MAME cache.. |
| 1455 | | inline UINT8 sega_segacd_device::read_pixel_from_stampmap( running_machine& machine, bitmap_ind16* srcbitmap, int x, int y) |
| 1428 | inline UINT8 sega_segacd_device::read_pixel_from_stampmap(bitmap_ind16* srcbitmap, int x, int y) |
| 1456 | 1429 | { |
| 1457 | 1430 | /* |
| 1458 | 1431 | if (!srcbitmap) |
| r29441 | r29442 | |
| 1470 | 1443 | |
| 1471 | 1444 | switch (segacd_get_active_stampmap_tilemap()&3) |
| 1472 | 1445 | { |
| 1473 | | case 0x00: return get_stampmap_16x16_1x1_tile_info_pixel( machine, x, y ); |
| 1474 | | case 0x01: return get_stampmap_32x32_1x1_tile_info_pixel( machine, x, y ); |
| 1475 | | case 0x02: return get_stampmap_16x16_16x16_tile_info_pixel( machine, x, y ); |
| 1476 | | case 0x03: return get_stampmap_32x32_16x16_tile_info_pixel( machine, x, y ); |
| 1446 | case 0x00: return get_stampmap_16x16_1x1_tile_info_pixel( x, y ); |
| 1447 | case 0x01: return get_stampmap_32x32_1x1_tile_info_pixel( x, y ); |
| 1448 | case 0x02: return get_stampmap_16x16_16x16_tile_info_pixel( x, y ); |
| 1449 | case 0x03: return get_stampmap_32x32_16x16_tile_info_pixel( x, y ); |
| 1477 | 1450 | } |
| 1478 | 1451 | |
| 1479 | 1452 | return 0; |
| r29441 | r29442 | |
| 1504 | 1477 | segacd_conversion_active = 1; |
| 1505 | 1478 | |
| 1506 | 1479 | // todo: proper time calculation |
| 1507 | | segacd_gfx_conversion_timer->adjust(attotime::from_nsec(30000)); |
| 1480 | m_stamp_timer->adjust(attotime::from_nsec(30000)); |
| 1508 | 1481 | |
| 1509 | 1482 | |
| 1510 | 1483 | |
| r29441 | r29442 | |
| 1521 | 1494 | INT16 tilemapxoffs,tilemapyoffs; |
| 1522 | 1495 | INT16 deltax,deltay; |
| 1523 | 1496 | |
| 1524 | | tilemapxoffs = segacd_dataram[(currbase+0x0)>>1]; |
| 1525 | | tilemapyoffs = segacd_dataram[(currbase+0x2)>>1]; |
| 1526 | | deltax = segacd_dataram[(currbase+0x4)>>1]; // x-zoom |
| 1527 | | deltay = segacd_dataram[(currbase+0x6)>>1]; // rotation |
| 1497 | tilemapxoffs = m_dataram[(currbase+0x0)>>1]; |
| 1498 | tilemapyoffs = m_dataram[(currbase+0x2)>>1]; |
| 1499 | deltax = m_dataram[(currbase+0x4)>>1]; // x-zoom |
| 1500 | deltay = m_dataram[(currbase+0x6)>>1]; // rotation |
| 1528 | 1501 | |
| 1529 | 1502 | //printf("%06x: %04x (%d) %04x (%d) %04x %04x\n", currbase, tilemapxoffs, tilemapxoffs>>3, tilemapyoffs, tilemapyoffs>>3, deltax, deltay); |
| 1530 | 1503 | |
| r29441 | r29442 | |
| 1537 | 1510 | //int i; |
| 1538 | 1511 | UINT8 pix = 0x0; |
| 1539 | 1512 | |
| 1540 | | pix = read_pixel_from_stampmap(space.machine(), srcbitmap, xbase>>(3+8), ybase>>(3+8)); |
| 1513 | pix = read_pixel_from_stampmap(srcbitmap, xbase>>(3+8), ybase>>(3+8)); |
| 1541 | 1514 | |
| 1542 | 1515 | xbase += deltax; |
| 1543 | 1516 | ybase += deltay; |
| r29441 | r29442 | |
| 1557 | 1530 | |
| 1558 | 1531 | offset+=countx & 0x7; |
| 1559 | 1532 | |
| 1560 | | write_pixel( space.machine(), pix, offset ); |
| 1533 | write_pixel( pix, offset ); |
| 1561 | 1534 | |
| 1562 | | segacd_mark_tiles_dirty(space.machine(), (offset>>3)); |
| 1563 | | segacd_mark_tiles_dirty(space.machine(), (offset>>3)+1); |
| 1535 | segacd_mark_tiles_dirty(offset>>3); |
| 1536 | segacd_mark_tiles_dirty((offset>>3)+1); |
| 1564 | 1537 | |
| 1565 | 1538 | } |
| 1566 | 1539 | |
| r29441 | r29442 | |
| 1648 | 1621 | |
| 1649 | 1622 | READ16_MEMBER( sega_segacd_device::segacd_irq3timer_r ) |
| 1650 | 1623 | { |
| 1651 | | return segacd_irq3_timer_reg; // always returns value written, not current counter! |
| 1624 | return m_irq3_timer_reg; // always returns value written, not current counter! |
| 1652 | 1625 | } |
| 1653 | 1626 | |
| 1654 | 1627 | |
| r29441 | r29442 | |
| 1656 | 1629 | { |
| 1657 | 1630 | if (ACCESSING_BITS_0_7) |
| 1658 | 1631 | { |
| 1659 | | segacd_irq3_timer_reg = data & 0xff; |
| 1632 | m_irq3_timer_reg = data & 0xff; |
| 1660 | 1633 | |
| 1661 | 1634 | // time = reg * 30.72 us |
| 1662 | 1635 | |
| 1663 | | if (segacd_irq3_timer_reg) |
| 1664 | | segacd_irq3_timer->adjust(SEGACD_IRQ3_TIMER_SPEED); |
| 1636 | if (m_irq3_timer_reg) |
| 1637 | m_irq3_timer->adjust(SEGACD_IRQ3_TIMER_SPEED); |
| 1665 | 1638 | else |
| 1666 | | segacd_irq3_timer->adjust(attotime::never); |
| 1639 | m_irq3_timer->adjust(attotime::never); |
| 1667 | 1640 | |
| 1668 | | //printf("segacd_irq3timer_w %02x\n", segacd_irq3_timer_reg); |
| 1641 | //printf("segacd_irq3timer_w %02x\n", segacd_m_irq3_timer_reg); |
| 1669 | 1642 | } |
| 1670 | 1643 | } |
| 1671 | 1644 | |
| 1672 | 1645 | |
| 1673 | | |
| 1674 | | |
| 1675 | | |
| 1676 | | |
| 1677 | | |
| 1678 | | READ16_MEMBER( sega_segacd_device::segacd_backupram_r ) |
| 1646 | READ8_MEMBER( sega_segacd_device::backupram_r ) |
| 1679 | 1647 | { |
| 1680 | | if(ACCESSING_BITS_8_15 && !(space.debugger_access())) |
| 1681 | | printf("Warning: read to backupram even bytes! [%04x]\n",offset); |
| 1682 | | |
| 1683 | | return segacd_backupram[offset] & 0xff; |
| 1648 | return m_backupram[offset]; |
| 1684 | 1649 | } |
| 1685 | 1650 | |
| 1686 | | WRITE16_MEMBER( sega_segacd_device::segacd_backupram_w ) |
| 1651 | WRITE8_MEMBER( sega_segacd_device::backupram_w ) |
| 1687 | 1652 | { |
| 1688 | | if(ACCESSING_BITS_0_7) |
| 1689 | | segacd_backupram[offset] = data; |
| 1690 | | |
| 1691 | | if(ACCESSING_BITS_8_15 && !(space.debugger_access())) |
| 1692 | | printf("Warning: write to backupram even bytes! [%04x] %02x\n",offset,data); |
| 1653 | m_backupram[offset] = data; |
| 1693 | 1654 | } |
| 1694 | 1655 | |
| 1695 | | READ16_MEMBER( sega_segacd_device::segacd_font_color_r ) |
| 1656 | READ8_MEMBER( sega_segacd_device::font_color_r ) |
| 1696 | 1657 | { |
| 1697 | | return segacd_font_color; |
| 1658 | return m_font_color; |
| 1698 | 1659 | } |
| 1699 | 1660 | |
| 1700 | | WRITE16_MEMBER( sega_segacd_device::segacd_font_color_w ) |
| 1661 | WRITE8_MEMBER( sega_segacd_device::font_color_w ) |
| 1701 | 1662 | { |
| 1702 | | if (ACCESSING_BITS_0_7) |
| 1703 | | { |
| 1704 | | segacd_font_color = data & 0xff; |
| 1705 | | } |
| 1663 | m_font_color = data; |
| 1706 | 1664 | } |
| 1707 | 1665 | |
| 1708 | | READ16_MEMBER( sega_segacd_device::segacd_font_converted_r ) |
| 1666 | READ16_MEMBER( sega_segacd_device::font_converted_r ) |
| 1709 | 1667 | { |
| 1710 | | int scbg = (segacd_font_color & 0x0f); |
| 1711 | | int scfg = (segacd_font_color & 0xf0)>>4; |
| 1668 | int scbg = (m_font_color & 0x0f); |
| 1669 | int scfg = (m_font_color & 0xf0)>>4; |
| 1712 | 1670 | UINT16 retdata = 0; |
| 1713 | 1671 | int bit; |
| 1714 | 1672 | |
| 1715 | 1673 | for (bit=0;bit<4;bit++) |
| 1716 | 1674 | { |
| 1717 | | if (*segacd_font_bits&((0x1000>>offset*4)<<bit)) |
| 1675 | if (*m_font_bits&((0x1000>>offset*4)<<bit)) |
| 1718 | 1676 | retdata |= scfg << (bit*4); |
| 1719 | 1677 | else |
| 1720 | 1678 | retdata |= scbg << (bit*4); |
| r29441 | r29442 | |
| 1729 | 1687 | |
| 1730 | 1688 | void sega_segacd_device::device_start() |
| 1731 | 1689 | { |
| 1732 | | if (!m_gfxdecode->started()) |
| 1733 | | throw device_missing_dependencies(); |
| 1734 | | |
| 1735 | | segacd_gfx_conversion_timer = machine().device<timer_device>(":segacd:stamp_timer"); |
| 1736 | | segacd_irq3_timer = machine().device<timer_device>(":segacd:irq3_timer"); |
| 1737 | | scd_dma_timer = machine().device<timer_device>(":segacd:scd_dma_timer"); |
| 1738 | | |
| 1739 | 1690 | address_space& space = machine().device("maincpu")->memory().space(AS_PROGRAM); |
| 1740 | 1691 | |
| 1741 | | segacd_font_bits = reinterpret_cast<UINT16 *>(memshare(":segacd:segacd_font")->ptr()); |
| 1742 | | segacd_backupram = reinterpret_cast<UINT16 *>(memshare(":segacd:backupram")->ptr()); |
| 1743 | | segacd_dataram = reinterpret_cast<UINT16 *>(memshare(":segacd:dataram")->ptr()); |
| 1744 | | // segacd_dataram2 = reinterpret_cast<UINT16 *>(memshare(":segacd:dataram2")->ptr()); |
| 1745 | | segacd_4meg_prgram = reinterpret_cast<UINT16 *>(memshare(":segacd:segacd_program")->ptr()); |
| 1692 | m_backupram.resize(0x2000); |
| 1693 | subdevice<nvram_device>("backupram")->set_base(m_backupram, 0x2000); |
| 1746 | 1694 | |
| 1747 | 1695 | segacd_4meg_prgbank = 0; |
| 1748 | 1696 | |
| 1749 | | |
| 1750 | 1697 | space.unmap_readwrite (0x020000,0x3fffff); |
| 1751 | 1698 | |
| 1752 | | |
| 1753 | 1699 | space.install_read_handler (0x0020000, 0x003ffff, read16_delegate(FUNC(sega_segacd_device::scd_4m_prgbank_ram_r),this) ); |
| 1754 | 1700 | space.install_write_handler (0x0020000, 0x003ffff, write16_delegate(FUNC(sega_segacd_device::scd_4m_prgbank_ram_w),this) ); |
| 1755 | 1701 | |
| r29441 | r29442 | |
| 1775 | 1721 | |
| 1776 | 1722 | space.install_read_handler (0x0000070, 0x0000073, read16_delegate(FUNC(sega_segacd_device::scd_hint_vector_r),this) ); |
| 1777 | 1723 | |
| 1778 | | /* create the char set (gfx will then be updated dynamically from RAM) */ |
| 1779 | | for (int i = 0; i < 16; i++) |
| 1780 | | m_gfxdecode->gfx(i)->set_source((UINT8 *)segacd_dataram); |
| 1724 | segacd_stampmap[0] = &machine().tilemap().create(*this, tilemap_get_info_delegate(FUNC(sega_segacd_device::get_stampmap_16x16_1x1_tile_info),this), TILEMAP_SCAN_ROWS, 16, 16, 16, 16); |
| 1725 | segacd_stampmap[1] = &machine().tilemap().create(*this, tilemap_get_info_delegate(FUNC(sega_segacd_device::get_stampmap_32x32_1x1_tile_info),this), TILEMAP_SCAN_ROWS, 32, 32, 8, 8); |
| 1726 | segacd_stampmap[2] = &machine().tilemap().create(*this, tilemap_get_info_delegate(FUNC(sega_segacd_device::get_stampmap_16x16_16x16_tile_info),this), TILEMAP_SCAN_ROWS, 16, 16, 256, 256); // 128kb! |
| 1727 | segacd_stampmap[3] = &machine().tilemap().create(*this, tilemap_get_info_delegate(FUNC(sega_segacd_device::get_stampmap_32x32_16x16_tile_info),this), TILEMAP_SCAN_ROWS, 32, 32, 128, 128); // 32kb! |
| 1781 | 1728 | |
| 1782 | | segacd_stampmap[0] = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(sega_segacd_device::get_stampmap_16x16_1x1_tile_info),this), TILEMAP_SCAN_ROWS, 16, 16, 16, 16); |
| 1783 | | segacd_stampmap[1] = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(sega_segacd_device::get_stampmap_32x32_1x1_tile_info),this), TILEMAP_SCAN_ROWS, 32, 32, 8, 8); |
| 1784 | | segacd_stampmap[2] = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(sega_segacd_device::get_stampmap_16x16_16x16_tile_info),this), TILEMAP_SCAN_ROWS, 16, 16, 256, 256); // 128kb! |
| 1785 | | segacd_stampmap[3] = &machine().tilemap().create(m_gfxdecode, tilemap_get_info_delegate(FUNC(sega_segacd_device::get_stampmap_32x32_16x16_tile_info),this), TILEMAP_SCAN_ROWS, 32, 32, 128, 128); // 32kb! |
| 1786 | | |
| 1787 | 1729 | // todo register save state stuff |
| 1788 | 1730 | } |
| 1789 | 1731 | |
| r29441 | r29442 | |
| 1809 | 1751 | scd_rammode = 0; |
| 1810 | 1752 | scd_mode_dmna_ret_flags = 0x5421; |
| 1811 | 1753 | |
| 1812 | | lc89510_temp = machine().device<lc89510_temp_device>(":segacd:tempcdc"); |
| 1813 | | lc89510_temp->reset_cd(); |
| 1754 | m_lc89510_temp->reset_cd(); |
| 1814 | 1755 | m_dmaaddr = 0; |
| 1815 | | scd_dma_timer->adjust(attotime::zero); |
| 1756 | m_dma_timer->adjust(attotime::zero); |
| 1816 | 1757 | |
| 1817 | | stopwatch_timer = machine().device<timer_device>(":segacd:sw_timer"); |
| 1818 | | |
| 1819 | 1758 | m_total_scanlines = 262; |
| 1820 | 1759 | |
| 1821 | 1760 | // HACK!!!! timegal, anettfut, roadaven end up with the SubCPU waiting in a loop for *something* |
| r29441 | r29442 | |
| 1848 | 1787 | segacd_redled = 0; |
| 1849 | 1788 | segacd_greenled = 0; |
| 1850 | 1789 | segacd_ready = 1; // actually set 100ms after startup? |
| 1851 | | segacd_irq3_timer_reg = 0; |
| 1790 | m_irq3_timer_reg = 0; |
| 1852 | 1791 | |
| 1853 | | segacd_gfx_conversion_timer->adjust(attotime::never); |
| 1854 | | segacd_irq3_timer->adjust(attotime::never); |
| 1792 | m_stamp_timer->adjust(attotime::never); |
| 1793 | m_irq3_timer->adjust(attotime::never); |
| 1855 | 1794 | |
| 1856 | 1795 | } |
| 1857 | 1796 | |
| 1858 | 1797 | |
| 1859 | 1798 | // todo: tidy up |
| 1860 | | TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::scd_dma_timer_callback ) |
| 1799 | TIMER_DEVICE_CALLBACK_MEMBER( sega_segacd_device::dma_timer_callback ) |
| 1861 | 1800 | { |
| 1862 | 1801 | // todo: accurate timing of this! |
| 1863 | 1802 | |
| 1864 | 1803 | #define RATE 256 |
| 1865 | | lc89510_temp->CDC_Do_DMA(machine(), RATE); |
| 1804 | m_lc89510_temp->CDC_Do_DMA(machine(), RATE); |
| 1866 | 1805 | |
| 1867 | 1806 | // timed reset of flags |
| 1868 | 1807 | scd_mode_dmna_ret_flags |= 0x0021; |
| 1869 | 1808 | |
| 1870 | | scd_dma_timer->adjust(attotime::from_hz(m_framerate) / m_total_scanlines); |
| 1809 | m_dma_timer->adjust(attotime::from_hz(m_framerate) / m_total_scanlines); |
| 1871 | 1810 | |
| 1872 | 1811 | } |
| 1873 | 1812 | |
| r29441 | r29442 | |
| 1875 | 1814 | void sega_segacd_device::SegaCD_CDC_Do_DMA(int &dmacount, UINT8 *CDC_BUFFER, UINT16 &dma_addrc, UINT16 &destination ) |
| 1876 | 1815 | { |
| 1877 | 1816 | int length = dmacount; |
| 1878 | | UINT8 *dest; |
| 1817 | UINT16 *dest; |
| 1879 | 1818 | int srcoffset = 0; |
| 1880 | 1819 | int dstoffset = 0; |
| 1881 | 1820 | address_space& space = m_scdcpu->space(AS_PROGRAM); |
| r29441 | r29442 | |
| 1899 | 1838 | |
| 1900 | 1839 | if (destination==DMA_PRG) |
| 1901 | 1840 | { |
| 1902 | | dest = (UINT8 *) segacd_4meg_prgram; |
| 1841 | dest = m_prgram; |
| 1903 | 1842 | } |
| 1904 | 1843 | else if (destination==DMA_WRAM) |
| 1905 | 1844 | { |
| 1906 | | dest = (UINT8*)segacd_dataram; |
| 1845 | dest = m_dataram; |
| 1907 | 1846 | } |
| 1908 | 1847 | else if (destination==DMA_PCM) |
| 1909 | 1848 | { |
| r29441 | r29442 | |
| 1916 | 1855 | |
| 1917 | 1856 | if (PCM_DMA) |
| 1918 | 1857 | { |
| 1919 | | space.write_byte(0xff2000+(((dstoffset*2)+1)&0x1fff),data >> 8); |
| 1920 | | space.write_byte(0xff2000+(((dstoffset*2)+3)&0x1fff),data & 0xff); |
| 1858 | m_rfsnd->rf5c68_mem_w(space, dstoffset & 0xfff, data >> 8); |
| 1859 | m_rfsnd->rf5c68_mem_w(space, (dstoffset+1) & 0xfff, data); |
| 1921 | 1860 | // printf("PCM_DMA writing %04x %04x\n",0xff2000+(dstoffset*2), data); |
| 1922 | 1861 | } |
| 1923 | 1862 | else |
| r29441 | r29442 | |
| 1930 | 1869 | { |
| 1931 | 1870 | dstoffset &= 0x3ffff; |
| 1932 | 1871 | |
| 1933 | | dest[dstoffset+1] = data >>8; |
| 1934 | | dest[dstoffset+0] = data&0xff; |
| 1872 | dest[dstoffset/2] = data; |
| 1935 | 1873 | |
| 1936 | | segacd_mark_tiles_dirty(space.machine(), dstoffset/2); |
| 1874 | segacd_mark_tiles_dirty(dstoffset/2); |
| 1937 | 1875 | } |
| 1938 | 1876 | else |
| 1939 | 1877 | { |
| r29441 | r29442 | |
| 1953 | 1891 | else |
| 1954 | 1892 | { |
| 1955 | 1893 | // main ram |
| 1956 | | dest[dstoffset+1] = data >>8; |
| 1957 | | dest[dstoffset+0] = data&0xff; |
| 1894 | dest[dstoffset/2] = data; |
| 1958 | 1895 | } |
| 1959 | 1896 | |
| 1960 | 1897 | } |