trunk/src/mame/drivers/kurukuru.c
| r19557 | r19558 | |
| 105 | 105 | public: |
| 106 | 106 | kurukuru_state(const machine_config &mconfig, device_type type, const char *tag) |
| 107 | 107 | : driver_device(mconfig, type, tag), |
| 108 | | m_v9938(*this, "v9938") { } |
| 108 | m_audiocpu(*this, "audiocpu"), |
| 109 | m_v9938(*this, "v9938") |
| 110 | { } |
| 109 | 111 | |
| 112 | required_device<cpu_device> m_audiocpu; |
| 110 | 113 | required_device<v9938_device> m_v9938; |
| 111 | | |
| 114 | |
| 115 | UINT8 m_sound_irq_cause; |
| 116 | UINT8 m_sound_irq_mask; |
| 117 | |
| 112 | 118 | DECLARE_WRITE8_MEMBER(kurukuru_bankswitch_w); |
| 113 | | DECLARE_WRITE8_MEMBER(kurukuru_samples_w); |
| 114 | | DECLARE_WRITE8_MEMBER(kurukuru_outport_w); |
| 119 | DECLARE_WRITE8_MEMBER(kurukuru_soundlatch_w); |
| 120 | DECLARE_READ8_MEMBER(kurukuru_soundlatch_r); |
| 121 | DECLARE_WRITE8_MEMBER(kurukuru_sound_irqmask_w); |
| 122 | DECLARE_READ8_MEMBER(kurukuru_sound_timer_irqack_r); |
| 115 | 123 | |
| 124 | void update_sound_irq(UINT8 cause); |
| 116 | 125 | virtual void machine_start(); |
| 117 | 126 | virtual void machine_reset(); |
| 118 | | TIMER_DEVICE_CALLBACK_MEMBER(kurukuru_interrupt); |
| 127 | TIMER_DEVICE_CALLBACK_MEMBER(kurukuru_vdp_scanline); |
| 128 | INTERRUPT_GEN_MEMBER(kurukuru_sound_timer_irq); |
| 119 | 129 | }; |
| 120 | 130 | |
| 121 | 131 | #define MAIN_CLOCK XTAL_21_4772MHz |
| r19557 | r19558 | |
| 132 | 142 | |
| 133 | 143 | |
| 134 | 144 | /************************************************* |
| 135 | | * Video Hardware * |
| 145 | * Interrupts * |
| 136 | 146 | *************************************************/ |
| 137 | 147 | |
| 138 | | static void kurukuru_vdp0_interrupt(device_t *, v99x8_device &device, int i) |
| 148 | static void kurukuru_vdp_interrupt(device_t *, v99x8_device &device, int i) |
| 139 | 149 | { |
| 140 | | device.machine().device("maincpu")->execute().set_input_line(0, (i ? HOLD_LINE : CLEAR_LINE)); |
| 150 | device.machine().device("maincpu")->execute().set_input_line(0, (i ? ASSERT_LINE : CLEAR_LINE)); |
| 141 | 151 | } |
| 142 | 152 | |
| 143 | 153 | |
| 144 | | /************************************************* |
| 145 | | * I/O * |
| 146 | | *************************************************/ |
| 147 | | |
| 148 | | WRITE8_MEMBER(kurukuru_state::kurukuru_bankswitch_w) |
| 154 | TIMER_DEVICE_CALLBACK_MEMBER(kurukuru_state::kurukuru_vdp_scanline) |
| 149 | 155 | { |
| 150 | | // d4,d5: bank |
| 151 | | membank("bank1")->set_entry(data >> 4 & 3); |
| 152 | | |
| 153 | | // d3: ? |
| 154 | | // other bits: always set |
| 156 | m_v9938->set_resolution(0); |
| 157 | m_v9938->interrupt(); |
| 155 | 158 | } |
| 156 | 159 | |
| 157 | 160 | |
| 158 | | WRITE8_MEMBER(kurukuru_state::kurukuru_outport_w) |
| 161 | void kurukuru_state::update_sound_irq(UINT8 cause) |
| 159 | 162 | { |
| 160 | | // logerror("%02x\n", data); |
| 163 | m_sound_irq_cause = cause & 3; |
| 164 | UINT8 mask = m_sound_irq_cause & m_sound_irq_mask; |
| 165 | if (mask) |
| 166 | { |
| 167 | // use bit 0 for latch irq, and bit 1 for timer irq |
| 168 | // latch irq vector is $ef (rst $28) |
| 169 | // timer irq vector is $f7 (rst $30) |
| 170 | // if both are asserted, the vector becomes $f7 AND $ef = $e7 (rst $20) |
| 171 | const UINT8 irq_vector[4] = { 0x00, 0xef, 0xf7, 0xe7 }; |
| 172 | m_audiocpu->set_input_line_and_vector(0, ASSERT_LINE, irq_vector[mask]); |
| 173 | } |
| 174 | else |
| 175 | { |
| 176 | m_audiocpu->set_input_line(0, CLEAR_LINE); |
| 177 | } |
| 161 | 178 | } |
| 162 | 179 | |
| 163 | 180 | |
| 164 | | WRITE8_MEMBER(kurukuru_state::kurukuru_samples_w) |
| 181 | INTERRUPT_GEN_MEMBER(kurukuru_state::kurukuru_sound_timer_irq) |
| 165 | 182 | { |
| 166 | | popmessage("triggered sample: %02X", data); |
| 183 | update_sound_irq(m_sound_irq_cause | 2); |
| 167 | 184 | } |
| 168 | 185 | |
| 169 | 186 | |
| 170 | 187 | /************************************************* |
| 171 | | * Memory Map * |
| 188 | * Memory Map / I/O * |
| 172 | 189 | *************************************************/ |
| 173 | 190 | |
| 191 | // Main CPU |
| 192 | |
| 193 | WRITE8_MEMBER(kurukuru_state::kurukuru_bankswitch_w) |
| 194 | { |
| 195 | // d4,d5: bank |
| 196 | // other bits: ? |
| 197 | membank("bank1")->set_entry(data >> 4 & 3); |
| 198 | } |
| 199 | |
| 200 | WRITE8_MEMBER(kurukuru_state::kurukuru_soundlatch_w) |
| 201 | { |
| 202 | soundlatch_byte_w(space, 0, data); |
| 203 | update_sound_irq(m_sound_irq_cause | 1); |
| 204 | } |
| 205 | |
| 206 | |
| 174 | 207 | static ADDRESS_MAP_START( kurukuru_map, AS_PROGRAM, 8, kurukuru_state ) |
| 175 | 208 | AM_RANGE(0x0000, 0x3fff) AM_ROM |
| 176 | 209 | AM_RANGE(0x6000, 0xdfff) AM_ROMBANK("bank1") |
| r19557 | r19558 | |
| 179 | 212 | |
| 180 | 213 | static ADDRESS_MAP_START( kurukuru_io, AS_IO, 8, kurukuru_state ) |
| 181 | 214 | ADDRESS_MAP_GLOBAL_MASK(0xff) |
| 182 | | // AM_RANGE(0x00, 0x00) AM_WRITENOP // seems for switch cpu... or irq? |
| 215 | // AM_RANGE(0x00, 0x00) AM_WRITENOP // seems for switch cpu... or irq? or hopper? |
| 183 | 216 | AM_RANGE(0x10, 0x10) AM_READ_PORT("DSW1") |
| 184 | | AM_RANGE(0x20, 0x20) AM_WRITE(kurukuru_samples_w) // trigger the m5205 sample number. |
| 217 | AM_RANGE(0x20, 0x20) AM_WRITE(kurukuru_soundlatch_w) |
| 185 | 218 | AM_RANGE(0x80, 0x83) AM_DEVREADWRITE( "v9938", v9938_device, read, write ) |
| 186 | 219 | AM_RANGE(0x90, 0x90) AM_WRITE(kurukuru_bankswitch_w) |
| 187 | 220 | AM_RANGE(0xa0, 0xa0) AM_READ_PORT("IN0") |
| r19557 | r19558 | |
| 203 | 236 | */ |
| 204 | 237 | |
| 205 | 238 | |
| 239 | // Audio CPU |
| 240 | |
| 241 | WRITE8_MEMBER(kurukuru_state::kurukuru_sound_irqmask_w) |
| 242 | { |
| 243 | // d0: sound latch irq enable |
| 244 | // d1: sound timer irq enable |
| 245 | // other bits: ? |
| 246 | m_sound_irq_mask = data; |
| 247 | update_sound_irq(m_sound_irq_cause); |
| 248 | } |
| 249 | |
| 250 | READ8_MEMBER(kurukuru_state::kurukuru_soundlatch_r) |
| 251 | { |
| 252 | update_sound_irq(m_sound_irq_cause & ~1); |
| 253 | return soundlatch_byte_r(space, 0); |
| 254 | } |
| 255 | |
| 256 | READ8_MEMBER(kurukuru_state::kurukuru_sound_timer_irqack_r) |
| 257 | { |
| 258 | update_sound_irq(m_sound_irq_cause & ~2); |
| 259 | return 0; |
| 260 | } |
| 261 | |
| 262 | |
| 206 | 263 | static ADDRESS_MAP_START( audio_map, AS_PROGRAM, 8, kurukuru_state ) |
| 207 | 264 | AM_RANGE(0x0000, 0xbfff) AM_ROM |
| 208 | 265 | AM_RANGE(0xf800, 0xffff) AM_RAM |
| r19557 | r19558 | |
| 210 | 267 | |
| 211 | 268 | static ADDRESS_MAP_START( audio_io, AS_IO, 8, kurukuru_state ) |
| 212 | 269 | ADDRESS_MAP_GLOBAL_MASK(0xff) |
| 213 | | // AM_RANGE(0x00, 0x00) seems for switch cpu... or irqack? |
| 214 | | // AM_RANGE(0xff, 0xff) AM_WRITE(kurukuru_outport_w) |
| 270 | // AM_RANGE(0x40, 0x40) AM_WRITENOP |
| 271 | AM_RANGE(0x50, 0x50) AM_WRITE(kurukuru_sound_irqmask_w) |
| 272 | AM_RANGE(0x60, 0x60) AM_READ(kurukuru_soundlatch_r) |
| 273 | AM_RANGE(0x70, 0x70) AM_READ(kurukuru_sound_timer_irqack_r) |
| 215 | 274 | ADDRESS_MAP_END |
| 216 | 275 | |
| 217 | | /* |
| 218 | | 0x40 Write |
| 219 | | 0x50 Write (0x0b) |
| 220 | | 0x60 Read |
| 221 | | 0x70 Read |
| 222 | | */ |
| 223 | 276 | |
| 224 | | /* |
| 225 | | Interrupts for audio CPU |
| 226 | | Vectors for IM0 |
| 227 | | 20h - 28h - 30h |
| 228 | | |
| 229 | | 20h: |
| 230 | | |
| 231 | | 0020 jp $0093 |
| 232 | | 008e ld a,$0b |
| 233 | | 0090 out ($50),a |
| 234 | | 0092 ret |
| 235 | | 0093 out ($40),a |
| 236 | | 0095 in a,($70) ; maybe irqack? |
| 237 | | 0097 in a,($60) ; soundlatch? |
| 238 | | 0099 cp $0e |
| 239 | | 009b jr nc,$00aa |
| 240 | | 009d ld ($f800),a |
| 241 | | 00a0 call $008e |
| 242 | | 00a3 ld sp,$0000 |
| 243 | | 00a6 ld hl,$0033 |
| 244 | | 00a9 push hl |
| 245 | | 00aa ei |
| 246 | | 00ab reti |
| 247 | | |
| 248 | | 28h: |
| 249 | | |
| 250 | | 0028 jp $0097 |
| 251 | | 0097 -> see above |
| 252 | | |
| 253 | | 30h: |
| 254 | | |
| 255 | | 0030 jp $00ad |
| 256 | | 00ad out ($40),a |
| 257 | | 00af in a,($70) |
| 258 | | 00b1 ei |
| 259 | | 00b2 reti |
| 260 | | |
| 261 | | */ |
| 262 | | |
| 263 | | |
| 264 | 277 | /************************************************* |
| 265 | 278 | * Input Ports Definitions * |
| 266 | 279 | *************************************************/ |
| r19557 | r19558 | |
| 350 | 363 | |
| 351 | 364 | void kurukuru_state::machine_reset() |
| 352 | 365 | { |
| 366 | m_sound_irq_mask = 0; |
| 367 | update_sound_irq(0); |
| 353 | 368 | } |
| 354 | 369 | |
| 355 | 370 | |
| 356 | 371 | /************************************************* |
| 357 | | * R/W Handlers and Interrupt Routines * |
| 358 | | *************************************************/ |
| 359 | | |
| 360 | | TIMER_DEVICE_CALLBACK_MEMBER(kurukuru_state::kurukuru_interrupt) |
| 361 | | { |
| 362 | | m_v9938->set_resolution(0); |
| 363 | | m_v9938->interrupt(); |
| 364 | | } |
| 365 | | |
| 366 | | |
| 367 | | /************************************************* |
| 368 | 372 | * Sound Interfaces * |
| 369 | 373 | *************************************************/ |
| 370 | 374 | |
| r19557 | r19558 | |
| 389 | 393 | MCFG_CPU_ADD("maincpu",Z80,MAIN_CLOCK/6) |
| 390 | 394 | MCFG_CPU_PROGRAM_MAP(kurukuru_map) |
| 391 | 395 | MCFG_CPU_IO_MAP(kurukuru_io) |
| 392 | | MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", kurukuru_state, kurukuru_interrupt, "screen", 0, 1) |
| 396 | MCFG_TIMER_DRIVER_ADD_SCANLINE("scantimer", kurukuru_state, kurukuru_vdp_scanline, "screen", 0, 1) |
| 393 | 397 | |
| 394 | 398 | MCFG_CPU_ADD("audiocpu", Z80, MAIN_CLOCK/6) |
| 395 | 399 | MCFG_CPU_PROGRAM_MAP(audio_map) |
| 396 | 400 | MCFG_CPU_IO_MAP(audio_io) |
| 397 | | // need interrupts... |
| 401 | MCFG_CPU_PERIODIC_INT_DRIVER(kurukuru_state, kurukuru_sound_timer_irq, 4*60) // from M5205? need to fix that |
| 398 | 402 | |
| 399 | 403 | MCFG_NVRAM_ADD_0FILL("nvram") |
| 400 | 404 | |
| 401 | | |
| 402 | 405 | /* video hardware */ |
| 403 | 406 | MCFG_VIDEO_ATTRIBUTES(VIDEO_UPDATE_BEFORE_VBLANK) |
| 404 | 407 | |
| 405 | 408 | MCFG_V9938_ADD("v9938", "screen", VDP_MEM) |
| 406 | | MCFG_V99X8_INTERRUPT_CALLBACK_STATIC(kurukuru_vdp0_interrupt) |
| 409 | MCFG_V99X8_INTERRUPT_CALLBACK_STATIC(kurukuru_vdp_interrupt) |
| 407 | 410 | |
| 408 | 411 | MCFG_SCREEN_ADD("screen",RASTER) |
| 409 | 412 | MCFG_SCREEN_REFRESH_RATE(60) |