src/emu/cpu/sm8500/sm8500.c
| r8731 | r8732 | |
| 27 | 27 | { |
| 28 | 28 | SM8500_CONFIG config; |
| 29 | 29 | UINT16 PC; |
| 30 | | UINT8 *register_base; |
| 31 | 30 | UINT8 IE0; |
| 32 | 31 | UINT8 IE1; |
| 33 | 32 | UINT8 IR0; |
| 34 | 33 | UINT8 IR1; |
| 35 | | UINT8 P0; |
| 36 | | UINT8 P1; |
| 37 | | UINT8 P2; |
| 38 | | UINT8 P3; |
| 39 | 34 | UINT8 SYS; |
| 40 | 35 | UINT8 CKC; |
| 41 | 36 | UINT8 clock_changed; |
| 42 | 37 | UINT16 SP; |
| 43 | 38 | UINT8 PS0; |
| 44 | 39 | UINT8 PS1; |
| 45 | | UINT8 P0C; |
| 46 | | UINT8 P1C; |
| 47 | | UINT8 P2C; |
| 48 | | UINT8 P3C; |
| 49 | 40 | UINT8 IFLAGS; |
| 50 | 41 | UINT8 CheckInterrupts; |
| 51 | 42 | int halted; |
| r8731 | r8732 | |
| 53 | 44 | device_irq_callback irq_callback; |
| 54 | 45 | legacy_cpu_device *device; |
| 55 | 46 | const address_space *program; |
| 56 | | UINT8 internal_ram[0x500]; |
| 47 | UINT16 oldpc; |
| 57 | 48 | }; |
| 58 | 49 | |
| 59 | 50 | INLINE sm8500_state *get_safe_token(running_device *device) |
| r8731 | r8732 | |
| 67 | 58 | 0, 8, 2, 10, 4, 12, 6, 14 |
| 68 | 59 | }; |
| 69 | 60 | |
| 61 | INLINE void sm8500_get_sp( sm8500_state *cpustate ) |
| 62 | { |
| 63 | UINT16 data = memory_read_byte( cpustate->program, 0x1c) << 8; |
| 64 | cpustate->SP = memory_read_byte( cpustate->program, 0x1d); |
| 65 | if (cpustate->SYS&0x40) cpustate->SP |= data; |
| 66 | } |
| 67 | |
| 70 | 68 | static UINT8 sm85cpu_mem_readbyte( sm8500_state *cpustate, UINT32 offset ) { |
| 71 | | return ( offset < 0x10 ) ? cpustate->register_base[offset] : memory_read_byte_8be( cpustate->program, offset ); |
| 69 | if (offset < 0x10) offset+= cpustate->PS0 & 0xf8; |
| 70 | return memory_read_byte( cpustate->program, offset ); |
| 72 | 71 | } |
| 73 | 72 | |
| 74 | 73 | static void sm85cpu_mem_writebyte( sm8500_state *cpustate, UINT32 offset, UINT8 data ) { |
| 75 | | if ( offset < 0x10 ) { |
| 76 | | cpustate->register_base[offset] = data; |
| 77 | | } else { |
| 78 | | memory_write_byte_8be( cpustate->program, offset, data ); |
| 74 | if (offset < 0x10) offset+= cpustate->PS0 & 0xf8; |
| 75 | memory_write_byte( cpustate->program, offset, data ); |
| 76 | switch (offset) |
| 77 | { |
| 78 | case 0x10: cpustate->IE0 = data; break; |
| 79 | case 0x11: cpustate->IE1 = data; break; |
| 80 | case 0x12: cpustate->IR0 = data; break; |
| 81 | case 0x13: cpustate->IR1 = data; break; |
| 82 | case 0x19: cpustate->SYS = data; break; |
| 83 | case 0x1a: cpustate->CKC = data; break; |
| 84 | case 0x1c: |
| 85 | case 0x1d: sm8500_get_sp(cpustate); break; |
| 86 | case 0x1e: cpustate->PS0 = data; break; |
| 87 | case 0x1f: cpustate->PS1 = data; break; |
| 79 | 88 | } |
| 80 | 89 | } |
| 81 | 90 | |
| 91 | |
| 82 | 92 | INLINE UINT16 sm85cpu_mem_readword( sm8500_state *cpustate, UINT32 address ) |
| 83 | 93 | { |
| 84 | 94 | UINT16 value = (UINT16) sm85cpu_mem_readbyte( cpustate, address ) << 8; |
| r8731 | r8732 | |
| 106 | 116 | cpustate->config.handle_dma = NULL; |
| 107 | 117 | cpustate->config.handle_timers = NULL; |
| 108 | 118 | } |
| 109 | | cpustate->register_base = cpustate->internal_ram; |
| 110 | 119 | } |
| 111 | 120 | |
| 112 | 121 | static CPU_RESET( sm8500 ) |
| r8731 | r8732 | |
| 114 | 123 | sm8500_state *cpustate = get_safe_token(device); |
| 115 | 124 | |
| 116 | 125 | cpustate->PC = 0x1020; |
| 117 | | cpustate->IE0 = 0; |
| 118 | | cpustate->IE1 = 0; |
| 119 | | cpustate->IR0 = 0; |
| 120 | | cpustate->IR1 = 0; |
| 121 | | cpustate->P0 = 0xFF; |
| 122 | | cpustate->P1 = 0xFF; |
| 123 | | cpustate->P2 = 0xFF; |
| 124 | | cpustate->P3 = 0; |
| 125 | | cpustate->SYS = 0; |
| 126 | | cpustate->CKC = 0; cpustate->clock_changed = 0; |
| 127 | | cpustate->PS1 = 0; |
| 128 | | cpustate->register_base = cpustate->internal_ram; |
| 126 | cpustate->clock_changed = 0; |
| 129 | 127 | cpustate->halted = 0; |
| 128 | sm85cpu_mem_writeword(cpustate, 0x10, 0); // IE0, IE1 |
| 129 | sm85cpu_mem_writeword(cpustate, 0x12, 0); // IR0, IR1 |
| 130 | sm85cpu_mem_writeword(cpustate, 0x14, 0xffff); // P0, P1 |
| 131 | sm85cpu_mem_writeword(cpustate, 0x16, 0xff00); // P2, P3 |
| 132 | sm85cpu_mem_writebyte(cpustate, 0x19, 0); // SYS |
| 133 | sm85cpu_mem_writebyte(cpustate, 0x1a, 0); // CKC |
| 134 | sm85cpu_mem_writebyte(cpustate, 0x1f, 0); // PS1 |
| 135 | sm85cpu_mem_writebyte(cpustate, 0x2b, 0xff); // URTT |
| 136 | sm85cpu_mem_writebyte(cpustate, 0x2d, 0x42); // URTS |
| 137 | sm85cpu_mem_writebyte(cpustate, 0x5f, 0x38); // WDTC |
| 130 | 138 | } |
| 131 | 139 | |
| 132 | 140 | static CPU_EXIT( sm8500 ) |
| 133 | 141 | { |
| 134 | 142 | } |
| 135 | 143 | |
| 136 | | #define PUSH_BYTE(X) cpustate->SP = cpustate->SP - 1; \ |
| 137 | | if ( ( cpustate->SYS & 0x40 ) == 0 ) { \ |
| 138 | | cpustate->SP = cpustate->SP & 0xFF; \ |
| 139 | | } \ |
| 144 | #define PUSH_BYTE(X) cpustate->SP--; \ |
| 145 | if ( ( cpustate->SYS & 0x40 ) == 0 ) cpustate->SP &= 0xFF; \ |
| 140 | 146 | sm85cpu_mem_writebyte( cpustate, cpustate->SP, X ); |
| 141 | 147 | |
| 142 | 148 | INLINE void sm8500_do_interrupt(sm8500_state *cpustate, UINT16 vector) { |
| 149 | /* Get regs from ram */ |
| 150 | sm8500_get_sp(cpustate); |
| 151 | cpustate->SYS = memory_read_byte(cpustate->program, 0x19); |
| 152 | cpustate->PS1 = memory_read_byte(cpustate->program, 0x1f); |
| 143 | 153 | /* Push PC */ |
| 144 | 154 | PUSH_BYTE( cpustate->PC & 0xFF ); |
| 145 | 155 | PUSH_BYTE( cpustate->PC >> 8 ); |
| r8731 | r8732 | |
| 147 | 157 | PUSH_BYTE( cpustate->PS1 ); |
| 148 | 158 | /* Clear I flag */ |
| 149 | 159 | cpustate->PS1 &= ~ 0x01; |
| 160 | /* save regs to ram */ |
| 161 | memory_write_byte(cpustate->program, 0x1f, cpustate->PS1); |
| 162 | memory_write_byte(cpustate->program, 0x1d, cpustate->SP&0xFF); |
| 163 | if (cpustate->SYS&0x40) memory_write_byte(cpustate->program, 0x1c, cpustate->SP>>8); |
| 150 | 164 | /* Change PC to address stored at "vector" */ |
| 151 | 165 | cpustate->PC = sm85cpu_mem_readword( cpustate, vector ); |
| 152 | 166 | } |
| r8731 | r8732 | |
| 157 | 171 | while( irqline < 11 ) { |
| 158 | 172 | if ( cpustate->IFLAGS & ( 1 << irqline ) ) { |
| 159 | 173 | cpustate->halted = 0; |
| 174 | cpustate->IE0 = memory_read_byte(cpustate->program, 0x10); |
| 175 | cpustate->IE1 = memory_read_byte(cpustate->program, 0x11); |
| 176 | cpustate->IR0 = memory_read_byte(cpustate->program, 0x12); |
| 177 | cpustate->IR1 = memory_read_byte(cpustate->program, 0x13); |
| 178 | cpustate->PS0 = memory_read_byte(cpustate->program, 0x1e); |
| 179 | cpustate->PS1 = memory_read_byte(cpustate->program, 0x1f); |
| 160 | 180 | switch( irqline ) { |
| 161 | | case ILL_INT: |
| 181 | case WDT_INT: |
| 162 | 182 | sm8500_do_interrupt( cpustate, 0x101C ); |
| 163 | 183 | break; |
| 164 | | case WDT_INT: |
| 165 | | sm8500_do_interrupt( cpustate, 0x101E ); |
| 166 | | break; |
| 184 | case ILL_INT: |
| 167 | 185 | case NMI_INT: |
| 168 | 186 | sm8500_do_interrupt( cpustate, 0x101E ); |
| 169 | 187 | break; |
| r8731 | r8732 | |
| 217 | 235 | break; |
| 218 | 236 | } |
| 219 | 237 | cpustate->IFLAGS &= ~ ( 1 << irqline ); |
| 238 | memory_write_byte(cpustate->program, 0x12, cpustate->IR0); |
| 239 | memory_write_byte(cpustate->program, 0x13, cpustate->IR1); |
| 220 | 240 | } |
| 221 | 241 | irqline++; |
| 222 | 242 | } |
| r8731 | r8732 | |
| 227 | 247 | { |
| 228 | 248 | sm8500_state *cpustate = get_safe_token(device); |
| 229 | 249 | UINT8 op; |
| 230 | | UINT16 oldpc; |
| 231 | 250 | int mycycles; |
| 232 | 251 | |
| 233 | 252 | do |
| r8731 | r8732 | |
| 238 | 257 | UINT32 res; |
| 239 | 258 | |
| 240 | 259 | debugger_instruction_hook(device, cpustate->PC); |
| 241 | | oldpc = cpustate->PC; |
| 260 | cpustate->oldpc = cpustate->PC; |
| 242 | 261 | mycycles = 0; |
| 243 | 262 | sm8500_process_interrupts(cpustate); |
| 244 | 263 | if ( !cpustate->halted ) { |
| 245 | 264 | op = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ ); |
| 265 | cpustate->SYS = memory_read_byte(cpustate->program, 0x19); |
| 266 | cpustate->PS0 = memory_read_byte(cpustate->program, 0x1e); |
| 267 | cpustate->PS1 = memory_read_byte(cpustate->program, 0x1f); |
| 268 | sm8500_get_sp(cpustate); |
| 246 | 269 | switch( op ) |
| 247 | 270 | { |
| 248 | 271 | #include "sm85ops.h" |
| 249 | 272 | } |
| 273 | if (cpustate->SYS&0x40) memory_write_byte(cpustate->program,0x1c,cpustate->SP>>8); |
| 274 | memory_write_byte(cpustate->program,0x1d,cpustate->SP&0xFF); |
| 275 | memory_write_byte(cpustate->program,0x1e,cpustate->PS0); |
| 276 | memory_write_byte(cpustate->program,0x1f,cpustate->PS1); |
| 250 | 277 | } else { |
| 251 | 278 | mycycles = 4; |
| 252 | 279 | if ( cpustate->config.handle_dma ) { |
| r8731 | r8732 | |
| 278 | 305 | case STATE_GENPC: |
| 279 | 306 | case SM8500_PC: return cpustate->PC; |
| 280 | 307 | case STATE_GENSP: |
| 281 | | case SM8500_SP: return ( cpustate->SYS & 0x40 ) ? cpustate->SP : cpustate->SP & 0xFF ; |
| 282 | | case SM8500_PS: return ( cpustate->PS0 << 8 ) | cpustate->PS1; |
| 308 | case SM8500_SP: return cpustate->SP; |
| 309 | case SM8500_PS: return sm85cpu_mem_readword( cpustate, 0x1e ); |
| 283 | 310 | case SM8500_SYS16: return cpustate->SYS; |
| 284 | 311 | case SM8500_RR0: return sm85cpu_mem_readword( cpustate, 0x00 ); |
| 285 | 312 | case SM8500_RR2: return sm85cpu_mem_readword( cpustate, 0x02 ); |
| r8731 | r8732 | |
| 289 | 316 | case SM8500_RR10: return sm85cpu_mem_readword( cpustate, 0x0A ); |
| 290 | 317 | case SM8500_RR12: return sm85cpu_mem_readword( cpustate, 0x0C ); |
| 291 | 318 | case SM8500_RR14: return sm85cpu_mem_readword( cpustate, 0x0E ); |
| 292 | | case SM8500_IE0: return cpustate->IE0; |
| 293 | | case SM8500_IE1: return cpustate->IE1; |
| 294 | | case SM8500_IR0: return cpustate->IR0; |
| 295 | | case SM8500_IR1: return cpustate->IR1; |
| 296 | | case SM8500_P0: return cpustate->P0; |
| 297 | | case SM8500_P1: return cpustate->P1; |
| 298 | | case SM8500_P2: return cpustate->P2; |
| 299 | | case SM8500_P3: return cpustate->P3; |
| 300 | | case SM8500_SYS: return cpustate->SYS; |
| 301 | | case SM8500_CKC: return cpustate->CKC; |
| 302 | | case SM8500_SPH: return (cpustate->SP >> 8); |
| 303 | | case SM8500_SPL: return cpustate->SP & 0xFF; |
| 304 | | case SM8500_PS0: return cpustate->PS0; |
| 305 | | case SM8500_PS1: return cpustate->PS1; |
| 306 | | case SM8500_P0C: return cpustate->P0C; |
| 307 | | case SM8500_P1C: return cpustate->P1C; |
| 308 | | case SM8500_P2C: return cpustate->P2C; |
| 309 | | case SM8500_P3C: return cpustate->P3C; |
| 319 | case SM8500_IE0: return sm85cpu_mem_readbyte( cpustate, 0x10 ); |
| 320 | case SM8500_IE1: return sm85cpu_mem_readbyte( cpustate, 0x11 ); |
| 321 | case SM8500_IR0: return sm85cpu_mem_readbyte( cpustate, 0x12 ); |
| 322 | case SM8500_IR1: return sm85cpu_mem_readbyte( cpustate, 0x13 ); |
| 323 | case SM8500_P0: return sm85cpu_mem_readbyte( cpustate, 0x14 ); |
| 324 | case SM8500_P1: return sm85cpu_mem_readbyte( cpustate, 0x15 ); |
| 325 | case SM8500_P2: return sm85cpu_mem_readbyte( cpustate, 0x16 ); |
| 326 | case SM8500_P3: return sm85cpu_mem_readbyte( cpustate, 0x17 ); |
| 327 | case SM8500_SYS: return sm85cpu_mem_readbyte( cpustate, 0x19 ); |
| 328 | case SM8500_CKC: return sm85cpu_mem_readbyte( cpustate, 0x1a ); |
| 329 | case SM8500_SPH: return sm85cpu_mem_readbyte( cpustate, 0x1c ); |
| 330 | case SM8500_SPL: return sm85cpu_mem_readbyte( cpustate, 0x1d ); |
| 331 | case SM8500_PS0: return sm85cpu_mem_readbyte( cpustate, 0x1e ); |
| 332 | case SM8500_PS1: return sm85cpu_mem_readbyte( cpustate, 0x1f ); |
| 333 | case SM8500_P0C: return sm85cpu_mem_readbyte( cpustate, 0x20 ); |
| 334 | case SM8500_P1C: return sm85cpu_mem_readbyte( cpustate, 0x21 ); |
| 335 | case SM8500_P2C: return sm85cpu_mem_readbyte( cpustate, 0x22 ); |
| 336 | case SM8500_P3C: return sm85cpu_mem_readbyte( cpustate, 0x23 ); |
| 310 | 337 | } |
| 311 | 338 | return 0; |
| 312 | 339 | } |
| r8731 | r8732 | |
| 318 | 345 | case STATE_GENPC: |
| 319 | 346 | case SM8500_PC: cpustate->PC = val; break; |
| 320 | 347 | case STATE_GENSP: |
| 321 | | case SM8500_SP: cpustate->SP = val; break; |
| 322 | | case SM8500_PS: sm8500_set_reg( cpustate, SM8500_PS0, ( val >> 8 ) & 0xFF ); sm8500_set_reg( cpustate, SM8500_PS1, val & 0xFF ); break; |
| 323 | | case SM8500_SYS16: cpustate->SYS = val; break; |
| 348 | case SM8500_SP: cpustate->SP = val; memory_write_byte( cpustate->program, 0x1d, val&0xff); if (cpustate->SYS&0x40) memory_write_byte( cpustate->program, 0x1c, val>>8); break; |
| 349 | case SM8500_PS: sm85cpu_mem_writeword( cpustate, 0x1e, val); break; |
| 350 | case SM8500_SYS16: val&=0xff; sm85cpu_mem_writebyte( cpustate, 0x19, val); break; |
| 324 | 351 | case SM8500_RR0: sm85cpu_mem_writeword( cpustate, 0x00, val); break; |
| 325 | 352 | case SM8500_RR2: sm85cpu_mem_writeword( cpustate, 0x02, val); break; |
| 326 | 353 | case SM8500_RR4: sm85cpu_mem_writeword( cpustate, 0x04, val); break; |
| r8731 | r8732 | |
| 329 | 356 | case SM8500_RR10: sm85cpu_mem_writeword( cpustate, 0x0A, val); break; |
| 330 | 357 | case SM8500_RR12: sm85cpu_mem_writeword( cpustate, 0x0C, val); break; |
| 331 | 358 | case SM8500_RR14: sm85cpu_mem_writeword( cpustate, 0x0E, val); break; |
| 332 | | case SM8500_IE0: cpustate->IE0 = val; break; |
| 333 | | case SM8500_IE1: cpustate->IE1 = val; break; |
| 334 | | case SM8500_IR0: cpustate->IR0 = val; break; |
| 335 | | case SM8500_IR1: cpustate->IR1 = val; break; |
| 336 | | case SM8500_P0: cpustate->P0 = val; break; |
| 337 | | case SM8500_P1: cpustate->P1 = val; break; |
| 338 | | case SM8500_P2: cpustate->P2 = val; break; |
| 339 | | case SM8500_P3: cpustate->P3 = val; break; |
| 340 | | case SM8500_SYS: cpustate->SYS = val; break; |
| 341 | | case SM8500_CKC: cpustate->CKC = val; if ( val & 0x80 ) { cpustate->clock_changed = 1; }; break; |
| 342 | | case SM8500_SPH: cpustate->SP = ( ( val & 0xFF ) << 8 ) | ( cpustate->SP & 0xFF ); break; |
| 343 | | case SM8500_SPL: cpustate->SP = ( cpustate->SP & 0xFF00 ) | ( val & 0xFF ); break; |
| 344 | | case SM8500_PS0: cpustate->PS0 = val; cpustate->register_base = cpustate->internal_ram + ( val & 0xF8 ); break; |
| 345 | | case SM8500_PS1: cpustate->PS1 = val; break; |
| 346 | | case SM8500_P0C: cpustate->P0C = val; break; |
| 347 | | case SM8500_P1C: cpustate->P1C = val; break; |
| 348 | | case SM8500_P2C: cpustate->P2C = val; break; |
| 349 | | case SM8500_P3C: cpustate->P3C = val; break; |
| 359 | case SM8500_IE0: sm85cpu_mem_writebyte( cpustate, 0x10, val); break; |
| 360 | case SM8500_IE1: sm85cpu_mem_writebyte( cpustate, 0x11, val); break; |
| 361 | case SM8500_IR0: sm85cpu_mem_writebyte( cpustate, 0x12, val); break; |
| 362 | case SM8500_IR1: sm85cpu_mem_writebyte( cpustate, 0x13, val); break; |
| 363 | case SM8500_P0: sm85cpu_mem_writebyte( cpustate, 0x14, val); break; |
| 364 | case SM8500_P1: sm85cpu_mem_writebyte( cpustate, 0x15, val); break; |
| 365 | case SM8500_P2: sm85cpu_mem_writebyte( cpustate, 0x16, val); break; |
| 366 | case SM8500_P3: sm85cpu_mem_writebyte( cpustate, 0x17, val); break; |
| 367 | case SM8500_SYS: sm85cpu_mem_writebyte( cpustate, 0x19, val); break; |
| 368 | case SM8500_CKC: sm85cpu_mem_writebyte( cpustate, 0x1a, val); if ( val & 0x80 ) { cpustate->clock_changed = 1; }; break; |
| 369 | case SM8500_SPH: sm85cpu_mem_writebyte( cpustate, 0x1c, val); break; |
| 370 | case SM8500_SPL: sm85cpu_mem_writebyte( cpustate, 0x1d, val); break; |
| 371 | case SM8500_PS0: sm85cpu_mem_writebyte( cpustate, 0x1e, val); break; |
| 372 | case SM8500_PS1: sm85cpu_mem_writebyte( cpustate, 0x1f, val); break; |
| 373 | case SM8500_P0C: sm85cpu_mem_writebyte( cpustate, 0x20, val); break; |
| 374 | case SM8500_P1C: sm85cpu_mem_writebyte( cpustate, 0x21, val); break; |
| 375 | case SM8500_P2C: sm85cpu_mem_writebyte( cpustate, 0x22, val); break; |
| 376 | case SM8500_P3C: sm85cpu_mem_writebyte( cpustate, 0x23, val); break; |
| 350 | 377 | } |
| 351 | 378 | } |
| 352 | 379 | |
| 353 | 380 | static void sm8500_set_irq_line( sm8500_state *cpustate, int irqline, int state ) |
| 354 | 381 | { |
| 382 | cpustate->IR0 = memory_read_byte(cpustate->program, 0x12); |
| 383 | cpustate->IR1 = memory_read_byte(cpustate->program, 0x13); |
| 355 | 384 | if ( state == ASSERT_LINE ) { |
| 356 | 385 | cpustate->IFLAGS |= ( 0x01 << irqline ); |
| 357 | 386 | cpustate->CheckInterrupts = 1; |
| r8731 | r8732 | |
| 381 | 410 | cpustate->CheckInterrupts = 0; |
| 382 | 411 | } |
| 383 | 412 | } |
| 413 | memory_write_byte(cpustate->program, 0x12, cpustate->IR0); |
| 414 | memory_write_byte(cpustate->program, 0x13, cpustate->IR1); |
| 384 | 415 | } |
| 385 | 416 | |
| 386 | | UINT8 *sm8500_get_internal_ram(legacy_cpu_device *device) |
| 387 | | { |
| 388 | | sm8500_state *cpustate = get_safe_token(device); |
| 389 | | return cpustate->internal_ram; |
| 390 | | } |
| 391 | | |
| 392 | 417 | static CPU_SET_INFO( sm8500 ) |
| 393 | 418 | { |
| 394 | 419 | sm8500_state *cpustate = get_safe_token(device); |
| r8731 | r8732 | |
| 438 | 463 | case CPUINFO_INT_REGISTER + SM8500_P1C: |
| 439 | 464 | case CPUINFO_INT_REGISTER + SM8500_P2C: |
| 440 | 465 | case CPUINFO_INT_REGISTER + SM8500_P3C: |
| 441 | | sm8500_set_reg( cpustate, state - CPUINFO_INT_REGISTER, info->i ); break; |
| 466 | sm8500_set_reg( cpustate, state - CPUINFO_INT_REGISTER, info->i ); break; |
| 442 | 467 | |
| 443 | 468 | } |
| 444 | 469 | } |
| r8731 | r8732 | |
| 509 | 534 | info->i = sm8500_get_reg( cpustate, state - CPUINFO_INT_REGISTER ); break; |
| 510 | 535 | case CPUINFO_INT_REGISTER + STATE_GENPC: info->i = sm8500_get_reg( cpustate, SM8500_PC ); break; |
| 511 | 536 | case CPUINFO_INT_REGISTER + STATE_GENSP: info->i = sm8500_get_reg( cpustate, SM8500_SP ); break; |
| 512 | | case CPUINFO_INT_PREVIOUSPC: info->i = 0x0000; break; |
| 537 | case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->oldpc; break; |
| 513 | 538 | |
| 514 | 539 | |
| 515 | 540 | case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(sm8500); break; |
| r8731 | r8732 | |
| 548 | 573 | case CPUINFO_STR_REGISTER + SM8500_PC: sprintf(info->s, "PC:%04X", cpustate->PC); break; |
| 549 | 574 | case CPUINFO_STR_REGISTER + SM8500_SP: sprintf(info->s, "SP:%04X", cpustate->SP); break; |
| 550 | 575 | case CPUINFO_STR_REGISTER + SM8500_PS: sprintf(info->s, "PS:%04X", ( cpustate->PS0 << 8 ) | cpustate->PS1 ); break; |
| 551 | | case CPUINFO_STR_REGISTER + SM8500_SYS16: sprintf(info->s, "SYS:%04X", cpustate->SYS ); break; |
| 576 | case CPUINFO_STR_REGISTER + SM8500_SYS16: sprintf(info->s, "SYS:%02X", cpustate->SYS ); break; |
| 552 | 577 | } |
| 553 | 578 | } |
| 554 | 579 | |
src/mess/machine/gamecom.c
| r8731 | r8732 | |
| 58 | 58 | UINT8 sg1w[16]; |
| 59 | 59 | } gamecom_sound_t; |
| 60 | 60 | |
| 61 | | UINT8 gamecom_internal_registers[0x80]; |
| 62 | 61 | static UINT8 *cartridge1 = NULL; |
| 63 | 62 | static UINT8 *cartridge2 = NULL; |
| 64 | 63 | static UINT8 *cartridge = NULL; |
| r8731 | r8732 | |
| 70 | 69 | |
| 71 | 70 | //static const int gamecom_timer_limit[8] = { 2/2, 1024/2, 2048/2, 4096/2, 8192/2, 16384/2, 32768/2, 65536/2 }; |
| 72 | 71 | static const int gamecom_timer_limit[8] = { 2, 1024, 2048, 4096, 8192, 16384, 32768, 65536 }; |
| 73 | | static running_device *gamecom_cpu; |
| 74 | 72 | |
| 75 | 73 | |
| 76 | 74 | static void gamecom_dma_init(running_machine *machine); |
| 77 | 75 | |
| 78 | 76 | static TIMER_CALLBACK(gamecom_clock_timer_callback) |
| 79 | 77 | { |
| 80 | | UINT8 val = ( ( gamecom_internal_registers[SM8521_CLKT] & 0x3F ) + 1 ) & 0x3F; |
| 81 | | gamecom_internal_registers[SM8521_CLKT] = ( gamecom_internal_registers[SM8521_CLKT] & 0xC0 ) | val; |
| 78 | UINT8 * RAM = memory_region(machine, "maincpu"); |
| 79 | UINT8 val = ( ( RAM[SM8521_CLKT] & 0x3F ) + 1 ) & 0x3F; |
| 80 | RAM[SM8521_CLKT] = ( RAM[SM8521_CLKT] & 0xC0 ) | val; |
| 82 | 81 | cputag_set_input_line(machine, "maincpu", CK_INT, ASSERT_LINE ); |
| 83 | 82 | } |
| 84 | 83 | |
| r8731 | r8732 | |
| 93 | 92 | cartridge = NULL; |
| 94 | 93 | /* disable DMA and timer */ |
| 95 | 94 | gamecom_dma.enabled = 0; |
| 96 | | |
| 97 | | memset( gamecom_internal_registers, 0x00, sizeof(gamecom_internal_registers) ); |
| 98 | | gamecom_internal_w( cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), SM8521_URTT, 0xFF ); |
| 99 | | gamecom_internal_w( cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), SM8521_URTS, 0x42 ); |
| 100 | | gamecom_internal_w( cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), SM8521_WDTC, 0x38 ); |
| 101 | 95 | } |
| 102 | 96 | |
| 103 | 97 | static void gamecom_set_mmu( running_machine *machine, int mmu, UINT8 data ) |
| r8731 | r8732 | |
| 119 | 113 | |
| 120 | 114 | static void handle_stylus_press( running_machine *machine, UINT8 column ) |
| 121 | 115 | { |
| 116 | UINT8 * RAM = memory_region(machine, "maincpu"); |
| 122 | 117 | static const UINT16 row_data[10] = { 0x3FE, 0x3FD, 0x3FB, 0x3F7, 0x3EF, 0x3DF, 0x3BF, 0x37F, 0x2FF, 0x1FF }; |
| 123 | 118 | static UINT32 stylus_x; |
| 124 | 119 | static UINT32 stylus_y; |
| r8731 | r8732 | |
| 139 | 134 | |
| 140 | 135 | if ( stylus_x == column ) |
| 141 | 136 | { |
| 142 | | cpu_set_reg( gamecom_cpu, SM8500_P0, row_data[stylus_y] & 0xFF ); |
| 143 | | cpu_set_reg( gamecom_cpu, SM8500_P1, ( cpu_get_reg( gamecom_cpu, SM8500_P1 ) & 0xFC ) | ( ( row_data[stylus_y] >> 8 ) & 0x03 ) ); |
| 137 | RAM[SM8500_P0] = row_data[stylus_y] & 0xFF; |
| 138 | RAM[SM8500_P1] = ( RAM[SM8500_P1] & 0xFC ) | ( ( row_data[stylus_y] >> 8 ) & 3 ); |
| 144 | 139 | } |
| 145 | 140 | else |
| 146 | 141 | { |
| 147 | | cpu_set_reg( gamecom_cpu, SM8500_P0, 0xFF ); |
| 148 | | cpu_set_reg( gamecom_cpu, SM8500_P1, ( cpu_get_reg( gamecom_cpu, SM8500_P1 ) & 0xFC ) | 0x03 ); |
| 142 | RAM[SM8500_P0] = 0xFF; |
| 143 | RAM[SM8500_P1] = ( RAM[SM8500_P1] & 0xFC ) | 3; |
| 149 | 144 | } |
| 150 | 145 | } |
| 151 | 146 | |
| 152 | 147 | WRITE8_HANDLER( gamecom_internal_w ) |
| 153 | 148 | { |
| 149 | UINT8 * RAM = memory_region(space->machine, "maincpu"); |
| 150 | offset += 0x20; |
| 154 | 151 | switch( offset ) |
| 155 | 152 | { |
| 156 | | case SM8521_IE0: cpu_set_reg( gamecom_cpu, SM8500_IE0, data ); return; |
| 157 | | case SM8521_IE1: cpu_set_reg( gamecom_cpu, SM8500_IE1, data ); return; |
| 158 | | case SM8521_IR0: cpu_set_reg( gamecom_cpu, SM8500_IR0, data ); return; |
| 159 | | case SM8521_IR1: cpu_set_reg( gamecom_cpu, SM8500_IR1, data ); return; |
| 160 | | case SM8521_P0: cpu_set_reg( gamecom_cpu, SM8500_P0, data ); return; |
| 161 | | case SM8521_P1: cpu_set_reg( gamecom_cpu, SM8500_P1, data ); return; |
| 162 | | case SM8521_P2: cpu_set_reg( gamecom_cpu, SM8500_P2, data ); |
| 163 | | switch( ( cpu_get_reg( gamecom_cpu, SM8500_P1 ) << 8 ) | data ) |
| 164 | | { |
| 165 | | case 0xFBFF: /* column #0 */ |
| 166 | | /* P0 bit 0 cleared => 01 */ |
| 167 | | /* P0 bit 1 cleared => 0E */ |
| 168 | | /* P0 bit 2 cleared => 1B */ |
| 169 | | /* P0 bit 3 cleared => etc */ |
| 170 | | /* P0 bit 4 cleared => */ |
| 171 | | /* P0 bit 5 cleared => */ |
| 172 | | /* P0 bit 6 cleared => */ |
| 173 | | /* P0 bit 7 cleared => */ |
| 174 | | /* P1 bit 0 cleared => */ |
| 175 | | /* P1 bit 1 cleared => */ |
| 176 | | handle_stylus_press( space->machine, 0 ); |
| 177 | | break; |
| 178 | | case 0xF7FF: /* column #1 */ |
| 179 | | handle_stylus_press( space->machine, 1 ); |
| 180 | | break; |
| 181 | | case 0xEFFF: /* column #2 */ |
| 182 | | handle_stylus_press( space->machine, 2 ); |
| 183 | | break; |
| 184 | | case 0xDFFF: /* column #3 */ |
| 185 | | handle_stylus_press( space->machine, 3 ); |
| 186 | | break; |
| 187 | | case 0xBFFF: /* column #4 */ |
| 188 | | handle_stylus_press( space->machine, 4 ); |
| 189 | | break; |
| 190 | | case 0x7FFF: /* column #5 */ |
| 191 | | handle_stylus_press( space->machine, 5 ); |
| 192 | | break; |
| 193 | | case 0xFFFE: /* column #6 */ |
| 194 | | handle_stylus_press( space->machine, 6 ); |
| 195 | | break; |
| 196 | | case 0xFFFD: /* column #7 */ |
| 197 | | handle_stylus_press( space->machine, 7 ); |
| 198 | | break; |
| 199 | | case 0xFFFB: /* column #8 */ |
| 200 | | handle_stylus_press( space->machine, 8 ); |
| 201 | | break; |
| 202 | | case 0xFFF7: /* column #9 */ |
| 203 | | handle_stylus_press( space->machine, 9 ); |
| 204 | | break; |
| 205 | | case 0xFFEF: /* column #10 */ |
| 206 | | handle_stylus_press( space->machine, 10 ); |
| 207 | | break; |
| 208 | | case 0xFFDF: /* column #11 */ |
| 209 | | handle_stylus_press( space->machine, 11 ); |
| 210 | | break; |
| 211 | | case 0xFFBF: /* column #12 */ |
| 212 | | handle_stylus_press( space->machine, 12 ); |
| 213 | | break; |
| 214 | | case 0xFF7F: /* keys #1 */ |
| 215 | | /* P0 bit 0 cleared => 83 (up) */ |
| 216 | | /* P0 bit 1 cleared => 84 (down) */ |
| 217 | | /* P0 bit 2 cleared => 85 (left) */ |
| 218 | | /* P0 bit 3 cleared => 86 (right) */ |
| 219 | | /* P0 bit 4 cleared => 87 (menu) */ |
| 220 | | /* P0 bit 5 cleared => 8A (pause) */ |
| 221 | | /* P0 bit 6 cleared => 89 (sound) */ |
| 222 | | /* P0 bit 7 cleared => 8B (button A) */ |
| 223 | | /* P1 bit 0 cleared => 8C (button B) */ |
| 224 | | /* P1 bit 1 cleared => 8D (button C) */ |
| 225 | | cpu_set_reg( gamecom_cpu, SM8500_P0, input_port_read(space->machine, "IN0") ); |
| 226 | | cpu_set_reg( gamecom_cpu, SM8500_P1, ( cpu_get_reg( gamecom_cpu, SM8500_P1 ) & 0xFC ) | ( input_port_read(space->machine, "IN1") & 0x03 ) ); |
| 227 | | break; |
| 228 | | case 0xFFFF: /* keys #2 */ |
| 229 | | /* P0 bit 0 cleared => 88 (power) */ |
| 230 | | /* P0 bit 1 cleared => 8E (button D) */ |
| 231 | | /* P0 bit 2 cleared => A0 */ |
| 232 | | /* P0 bit 3 cleared => A0 */ |
| 233 | | /* P0 bit 4 cleared => A0 */ |
| 234 | | /* P0 bit 5 cleared => A0 */ |
| 235 | | /* P0 bit 6 cleared => A0 */ |
| 236 | | /* P0 bit 7 cleared => A0 */ |
| 237 | | /* P1 bit 0 cleared => A0 */ |
| 238 | | /* P1 bit 1 cleared => A0 */ |
| 239 | | cpu_set_reg( gamecom_cpu, SM8500_P0, ( cpu_get_reg( gamecom_cpu, SM8500_P0 ) & 0xFC ) | ( input_port_read(space->machine, "IN2") & 0x03 ) ); |
| 240 | | cpu_set_reg( gamecom_cpu, SM8500_P1, 0xFF ); |
| 241 | | break; |
| 242 | | } |
| 243 | | return; |
| 244 | | case SM8521_P3: |
| 245 | | /* P3 bit7 clear, bit6 set -> enable cartridge port #0? */ |
| 246 | | /* P3 bit6 clear, bit7 set -> enable cartridge port #1? */ |
| 247 | | cpu_set_reg( gamecom_cpu, SM8500_P3, data ); |
| 248 | | switch( data & 0xc0 ) |
| 249 | | { |
| 250 | | case 0x40: cartridge = cartridge1; break; |
| 251 | | case 0x80: cartridge = cartridge2; break; |
| 252 | | default: cartridge = NULL; break; |
| 253 | | } |
| 254 | | return; |
| 255 | | case SM8521_SYS: cpu_set_reg( gamecom_cpu, SM8500_SYS, data ); return; |
| 256 | | case SM8521_CKC: cpu_set_reg( gamecom_cpu, SM8500_CKC, data ); return; |
| 257 | | case SM8521_SPH: cpu_set_reg( gamecom_cpu, SM8500_SPH, data ); return; |
| 258 | | case SM8521_SPL: cpu_set_reg( gamecom_cpu, SM8500_SPL, data ); return; |
| 259 | | case SM8521_PS0: cpu_set_reg( gamecom_cpu, SM8500_PS0, data ); return; |
| 260 | | case SM8521_PS1: cpu_set_reg( gamecom_cpu, SM8500_PS1, data ); return; |
| 261 | | case SM8521_P0C: cpu_set_reg( gamecom_cpu, SM8500_P0C, data ); return; |
| 262 | | case SM8521_P1C: cpu_set_reg( gamecom_cpu, SM8500_P1C, data ); return; |
| 263 | | case SM8521_P2C: cpu_set_reg( gamecom_cpu, SM8500_P2C, data ); return; |
| 264 | | case SM8521_P3C: cpu_set_reg( gamecom_cpu, SM8500_P3C, data ); return; |
| 265 | 153 | case SM8521_MMU0: /* disable bootstrap ROM? most likely not written to on game.com */ |
| 266 | 154 | logerror( "Write to MMU0\n" ); |
| 267 | 155 | break; |
| r8731 | r8732 | |
| 441 | 329 | logerror( "%X: Write to reserved address (0x%02X). Value written: 0x%02X\n", cpu_get_pc(space->cpu), offset, data ); |
| 442 | 330 | break; |
| 443 | 331 | } |
| 444 | | gamecom_internal_registers[offset] = data; |
| 332 | RAM[offset] = data; |
| 445 | 333 | } |
| 446 | 334 | |
| 447 | 335 | READ8_HANDLER( gamecom_internal_r ) |
| 448 | 336 | { |
| 449 | 337 | /* NPW 22-Dec-2008 - Shouldn't this entire function be moved to an internal memory map of the CPU core? */ |
| 338 | UINT8 * RAM = memory_region(space->machine, "maincpu"); |
| 339 | offset += 0x20; |
| 340 | UINT8 data = RAM[offset]; |
| 450 | 341 | switch( offset ) |
| 451 | 342 | { |
| 452 | | case SM8521_IE0: return cpu_get_reg( gamecom_cpu, SM8500_IE0 ); |
| 453 | | case SM8521_IE1: return cpu_get_reg( gamecom_cpu, SM8500_IE1 ); |
| 454 | | case SM8521_IR0: return cpu_get_reg( gamecom_cpu, SM8500_IR0 ); |
| 455 | | case SM8521_IR1: return cpu_get_reg( gamecom_cpu, SM8500_IR1 ); |
| 456 | | case SM8521_P0: return cpu_get_reg( gamecom_cpu, SM8500_P0 ); |
| 457 | | case SM8521_P1: return cpu_get_reg( gamecom_cpu, SM8500_P1 ); |
| 458 | | case SM8521_P2: return cpu_get_reg( gamecom_cpu, SM8500_P2 ); |
| 459 | | case SM8521_P3: return cpu_get_reg( gamecom_cpu, SM8500_P3 ); |
| 460 | | case SM8521_SYS: return cpu_get_reg( gamecom_cpu, SM8500_SYS ); |
| 461 | | case SM8521_CKC: return cpu_get_reg( gamecom_cpu, SM8500_CKC ); |
| 462 | | case SM8521_SPH: return cpu_get_reg( gamecom_cpu, SM8500_SPH ); |
| 463 | | case SM8521_SPL: return cpu_get_reg( gamecom_cpu, SM8500_SPL ); |
| 464 | | case SM8521_PS0: return cpu_get_reg( gamecom_cpu, SM8500_PS0 ); |
| 465 | | case SM8521_PS1: return cpu_get_reg( gamecom_cpu, SM8500_PS1 ); |
| 466 | | case SM8521_P0C: return cpu_get_reg( gamecom_cpu, SM8500_P0C ); |
| 467 | | case SM8521_P1C: return cpu_get_reg( gamecom_cpu, SM8500_P1C ); |
| 468 | | case SM8521_P2C: return cpu_get_reg( gamecom_cpu, SM8500_P2C ); |
| 469 | | case SM8521_P3C: return cpu_get_reg( gamecom_cpu, SM8500_P3C ); |
| 470 | 343 | case SM8521_TM0D: return gamecom_timer[0].counter; |
| 471 | 344 | case SM8521_TM1D: return gamecom_timer[1].counter; |
| 472 | 345 | // case SM8521_CLKT: /* bit 0-5 read only, 6-7 read/write */ |
| 473 | | // return ( gamecom_internal_registers[offset] & 0xC0 ) | ( clock_timer_val & 0x3F ); |
| 346 | // return ( RAM[offset] & 0xC0 ) | ( clock_timer_val & 0x3F ); |
| 347 | } |
| 348 | return data; |
| 349 | } |
| 474 | 350 | |
| 475 | | /* Reserved addresses */ |
| 476 | | case SM8521_18: case SM8521_1B: |
| 477 | | case SM8521_29: case SM8521_2A: case SM8521_2F: |
| 478 | | case SM8521_33: case SM8521_3E: case SM8521_3F: |
| 479 | | case SM8521_41: case SM8521_43: case SM8521_45: case SM8521_4B: |
| 480 | | case SM8521_4F: |
| 481 | | case SM8521_55: case SM8521_56: case SM8521_57: case SM8521_58: |
| 482 | | case SM8521_59: case SM8521_5A: case SM8521_5B: case SM8521_5C: |
| 483 | | case SM8521_5D: |
| 484 | | // logerror( "%X: Read from reserved address (0x%02X)\n", cpu_get_pc(space->cpu), offset ); |
| 485 | | break; |
| 486 | | |
| 351 | WRITE8_HANDLER( gamecom_pio_w ) |
| 352 | { |
| 353 | UINT8 * RAM = memory_region(space->machine, "maincpu"); |
| 354 | offset += 0x14; |
| 355 | RAM[offset] = data; |
| 356 | switch( offset ) |
| 357 | { |
| 358 | case SM8521_P2: switch( ( RAM[SM8521_P0] << 8 ) | data ) |
| 359 | { |
| 360 | case 0xFBFF: /* column #0 */ |
| 361 | /* P0 bit 0 cleared => 01 */ |
| 362 | /* P0 bit 1 cleared => 0E */ |
| 363 | /* P0 bit 2 cleared => 1B */ |
| 364 | /* P0 bit 3 cleared => etc */ |
| 365 | /* P0 bit 4 cleared => */ |
| 366 | /* P0 bit 5 cleared => */ |
| 367 | /* P0 bit 6 cleared => */ |
| 368 | /* P0 bit 7 cleared => */ |
| 369 | /* P1 bit 0 cleared => */ |
| 370 | /* P1 bit 1 cleared => */ |
| 371 | handle_stylus_press( space->machine, 0 ); |
| 372 | break; |
| 373 | case 0xF7FF: /* column #1 */ |
| 374 | handle_stylus_press( space->machine, 1 ); |
| 375 | break; |
| 376 | case 0xEFFF: /* column #2 */ |
| 377 | handle_stylus_press( space->machine, 2 ); |
| 378 | break; |
| 379 | case 0xDFFF: /* column #3 */ |
| 380 | handle_stylus_press( space->machine, 3 ); |
| 381 | break; |
| 382 | case 0xBFFF: /* column #4 */ |
| 383 | handle_stylus_press( space->machine, 4 ); |
| 384 | break; |
| 385 | case 0x7FFF: /* column #5 */ |
| 386 | handle_stylus_press( space->machine, 5 ); |
| 387 | break; |
| 388 | case 0xFFFE: /* column #6 */ |
| 389 | handle_stylus_press( space->machine, 6 ); |
| 390 | break; |
| 391 | case 0xFFFD: /* column #7 */ |
| 392 | handle_stylus_press( space->machine, 7 ); |
| 393 | break; |
| 394 | case 0xFFFB: /* column #8 */ |
| 395 | handle_stylus_press( space->machine, 8 ); |
| 396 | break; |
| 397 | case 0xFFF7: /* column #9 */ |
| 398 | handle_stylus_press( space->machine, 9 ); |
| 399 | break; |
| 400 | case 0xFFEF: /* column #10 */ |
| 401 | handle_stylus_press( space->machine, 10 ); |
| 402 | break; |
| 403 | case 0xFFDF: /* column #11 */ |
| 404 | handle_stylus_press( space->machine, 11 ); |
| 405 | break; |
| 406 | case 0xFFBF: /* column #12 */ |
| 407 | handle_stylus_press( space->machine, 12 ); |
| 408 | break; |
| 409 | case 0xFF7F: /* keys #1 */ |
| 410 | /* P0 bit 0 cleared => 83 (up) */ |
| 411 | /* P0 bit 1 cleared => 84 (down) */ |
| 412 | /* P0 bit 2 cleared => 85 (left) */ |
| 413 | /* P0 bit 3 cleared => 86 (right) */ |
| 414 | /* P0 bit 4 cleared => 87 (menu) */ |
| 415 | /* P0 bit 5 cleared => 8A (pause) */ |
| 416 | /* P0 bit 6 cleared => 89 (sound) */ |
| 417 | /* P0 bit 7 cleared => 8B (button A) */ |
| 418 | /* P1 bit 0 cleared => 8C (button B) */ |
| 419 | /* P1 bit 1 cleared => 8D (button C) */ |
| 420 | RAM[SM8521_P0] = input_port_read(space->machine, "IN0"); |
| 421 | RAM[SM8521_P1] = (RAM[SM8521_P1] & 0xFC) | ( input_port_read(space->machine, "IN1") & 3 ); |
| 422 | break; |
| 423 | case 0xFFFF: /* keys #2 */ |
| 424 | /* P0 bit 0 cleared => 88 (power) */ |
| 425 | /* P0 bit 1 cleared => 8E (button D) */ |
| 426 | /* P0 bit 2 cleared => A0 */ |
| 427 | /* P0 bit 3 cleared => A0 */ |
| 428 | /* P0 bit 4 cleared => A0 */ |
| 429 | /* P0 bit 5 cleared => A0 */ |
| 430 | /* P0 bit 6 cleared => A0 */ |
| 431 | /* P0 bit 7 cleared => A0 */ |
| 432 | /* P1 bit 0 cleared => A0 */ |
| 433 | /* P1 bit 1 cleared => A0 */ |
| 434 | RAM[SM8521_P0] = (RAM[SM8521_P0] & 0xFC) | ( input_port_read(space->machine, "IN2") & 3 ); |
| 435 | RAM[SM8521_P1] = 0xFF; |
| 436 | break; |
| 437 | } |
| 438 | return; |
| 439 | case SM8521_P3: |
| 440 | /* P3 bit7 clear, bit6 set -> enable cartridge port #0? */ |
| 441 | /* P3 bit6 clear, bit7 set -> enable cartridge port #1? */ |
| 442 | switch( data & 0xc0 ) |
| 443 | { |
| 444 | case 0x40: cartridge = cartridge1; break; |
| 445 | case 0x80: cartridge = cartridge2; break; |
| 446 | default: cartridge = NULL; break; |
| 447 | } |
| 448 | return; |
| 487 | 449 | } |
| 488 | | return gamecom_internal_registers[offset]; |
| 489 | 450 | } |
| 490 | 451 | |
| 452 | READ8_HANDLER( gamecom_pio_r ) |
| 453 | { |
| 454 | UINT8 * RAM = memory_region(space->machine, "maincpu"); |
| 455 | return RAM[offset + 0x14]; |
| 456 | } |
| 457 | |
| 491 | 458 | /* The manual is not conclusive as to which bit of the DMVP register (offset 0x3D) determines |
| 492 | 459 | which page for source or destination is used */ |
| 493 | 460 | static void gamecom_dma_init(running_machine *machine) |
| 494 | 461 | { |
| 462 | UINT8 * RAM = memory_region(machine, "maincpu"); |
| 495 | 463 | if ( gamecom_dma.decrement_x || gamecom_dma.decrement_y ) |
| 496 | 464 | { |
| 497 | 465 | logerror( "TODO: Decrement-x and decrement-y are not supported yet\n" ); |
| 498 | 466 | } |
| 499 | | gamecom_dma.width_x = gamecom_internal_registers[SM8521_DMDX]; |
| 467 | gamecom_dma.width_x = RAM[SM8521_DMDX]; |
| 500 | 468 | gamecom_dma.width_x_count = 0; |
| 501 | | gamecom_dma.width_y = gamecom_internal_registers[SM8521_DMDY]; |
| 469 | gamecom_dma.width_y = RAM[SM8521_DMDY]; |
| 502 | 470 | gamecom_dma.width_y_count = 0; |
| 503 | | gamecom_dma.source_x = gamecom_internal_registers[SM8521_DMX1]; |
| 471 | gamecom_dma.source_x = RAM[SM8521_DMX1]; |
| 504 | 472 | gamecom_dma.source_x_current = gamecom_dma.source_x; |
| 505 | | gamecom_dma.source_y = gamecom_internal_registers[SM8521_DMY1]; |
| 506 | | gamecom_dma.source_width = ( gamecom_internal_registers[SM8521_LCH] & 0x20 ) ? 50 : 40; |
| 507 | | gamecom_dma.dest_x = gamecom_internal_registers[SM8521_DMX2]; |
| 473 | gamecom_dma.source_y = RAM[SM8521_DMY1]; |
| 474 | gamecom_dma.source_width = ( RAM[SM8521_LCH] & 0x20 ) ? 50 : 40; |
| 475 | gamecom_dma.dest_x = RAM[SM8521_DMX2]; |
| 508 | 476 | gamecom_dma.dest_x_current = gamecom_dma.dest_x; |
| 509 | | gamecom_dma.dest_y = gamecom_internal_registers[SM8521_DMY2]; |
| 510 | | gamecom_dma.dest_width = ( gamecom_internal_registers[SM8521_LCH] & 0x20 ) ? 50 : 40; |
| 511 | | gamecom_dma.palette[0] = ( gamecom_internal_registers[SM8521_DMPL] & 0x03 ); |
| 512 | | gamecom_dma.palette[1] = ( gamecom_internal_registers[SM8521_DMPL] & 0x0C ) >> 2; |
| 513 | | gamecom_dma.palette[2] = ( gamecom_internal_registers[SM8521_DMPL] & 0x30 ) >> 4; |
| 514 | | gamecom_dma.palette[3] = ( gamecom_internal_registers[SM8521_DMPL] & 0xC0 ) >> 6; |
| 477 | gamecom_dma.dest_y = RAM[SM8521_DMY2]; |
| 478 | gamecom_dma.dest_width = ( RAM[SM8521_LCH] & 0x20 ) ? 50 : 40; |
| 479 | gamecom_dma.palette[0] = ( RAM[SM8521_DMPL] & 0x03 ); |
| 480 | gamecom_dma.palette[1] = ( RAM[SM8521_DMPL] & 0x0C ) >> 2; |
| 481 | gamecom_dma.palette[2] = ( RAM[SM8521_DMPL] & 0x30 ) >> 4; |
| 482 | gamecom_dma.palette[3] = ( RAM[SM8521_DMPL] & 0xC0 ) >> 6; |
| 515 | 483 | gamecom_dma.source_mask = 0x1FFF; |
| 516 | 484 | gamecom_dma.dest_mask = 0x1FFF; |
| 517 | | // logerror("DMA: width %Xx%X, source (%X,%X), dest (%X,%X), transfer_mode %X, banks %X \n", gamecom_dma.width_x, gamecom_dma.width_y, gamecom_dma.source_x, gamecom_dma.source_y, gamecom_dma.dest_x, gamecom_dma.dest_y, gamecom_dma.transfer_mode, gamecom_internal_registers[SM8521_DMVP] ); |
| 485 | // logerror("DMA: width %Xx%X, source (%X,%X), dest (%X,%X), transfer_mode %X, banks %X \n", gamecom_dma.width_x, gamecom_dma.width_y, gamecom_dma.source_x, gamecom_dma.source_y, gamecom_dma.dest_x, gamecom_dma.dest_y, gamecom_dma.transfer_mode, RAM[SM8521_DMVP] ); |
| 518 | 486 | // logerror( " Palette: %d, %d, %d, %d\n", gamecom_dma.palette[0], gamecom_dma.palette[1], gamecom_dma.palette[2], gamecom_dma.palette[3] ); |
| 519 | 487 | switch( gamecom_dma.transfer_mode ) |
| 520 | 488 | { |
| 521 | 489 | case 0x00: |
| 522 | 490 | /* VRAM->VRAM */ |
| 523 | | gamecom_dma.source_bank = &gamecom_vram[(gamecom_internal_registers[SM8521_DMVP] & 0x01) ? 0x2000 : 0x0000]; |
| 524 | | gamecom_dma.dest_bank = &gamecom_vram[(gamecom_internal_registers[SM8521_DMVP] & 0x02) ? 0x2000 : 0x0000]; |
| 491 | gamecom_dma.source_bank = &gamecom_vram[(RAM[SM8521_DMVP] & 0x01) ? 0x2000 : 0x0000]; |
| 492 | gamecom_dma.dest_bank = &gamecom_vram[(RAM[SM8521_DMVP] & 0x02) ? 0x2000 : 0x0000]; |
| 525 | 493 | break; |
| 526 | 494 | case 0x02: |
| 527 | 495 | /* ROM->VRAM */ |
| 528 | | // logerror( "DMA DMBR = %X\n", gamecom_internal_registers[SM8521_DMBR] ); |
| 496 | // logerror( "DMA DMBR = %X\n", RAM[SM8521_DMBR] ); |
| 529 | 497 | gamecom_dma.source_width = 64; |
| 530 | 498 | gamecom_dma.source_mask = 0x3FFF; |
| 531 | | if ( gamecom_internal_registers[SM8521_DMBR] < 16 ) |
| 499 | if ( RAM[SM8521_DMBR] < 16 ) |
| 532 | 500 | { |
| 533 | | gamecom_dma.source_bank = memory_region(machine, "user1") + (gamecom_internal_registers[SM8521_DMBR] << 14); |
| 501 | gamecom_dma.source_bank = memory_region(machine, "user1") + (RAM[SM8521_DMBR] << 14); |
| 534 | 502 | } |
| 535 | 503 | else |
| 536 | 504 | { |
| 537 | 505 | if (cartridge) |
| 538 | | gamecom_dma.source_bank = cartridge + (gamecom_internal_registers[SM8521_DMBR] << 14); |
| 506 | gamecom_dma.source_bank = cartridge + (RAM[SM8521_DMBR] << 14); |
| 539 | 507 | } |
| 540 | | gamecom_dma.dest_bank = &gamecom_vram[(gamecom_internal_registers[SM8521_DMVP] & 0x02) ? 0x2000 : 0x0000]; |
| 508 | gamecom_dma.dest_bank = &gamecom_vram[(RAM[SM8521_DMVP] & 0x02) ? 0x2000 : 0x0000]; |
| 541 | 509 | break; |
| 542 | 510 | case 0x04: |
| 543 | 511 | /* Extend RAM->VRAM */ |
| 544 | 512 | gamecom_dma.source_width = 64; |
| 545 | 513 | gamecom_dma.source_bank = (UINT8*)memory_get_read_ptr(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xE000 ); |
| 546 | | gamecom_dma.dest_bank = &gamecom_vram[(gamecom_internal_registers[SM8521_DMVP] & 0x02) ? 0x2000 : 0x0000]; |
| 514 | gamecom_dma.dest_bank = &gamecom_vram[(RAM[SM8521_DMVP] & 0x02) ? 0x2000 : 0x0000]; |
| 547 | 515 | break; |
| 548 | 516 | case 0x06: |
| 549 | 517 | /* VRAM->Extend RAM */ |
| 550 | | gamecom_dma.source_bank = &gamecom_vram[(gamecom_internal_registers[SM8521_DMVP] & 0x01) ? 0x2000 : 0x0000]; |
| 518 | gamecom_dma.source_bank = &gamecom_vram[(RAM[SM8521_DMVP] & 0x01) ? 0x2000 : 0x0000]; |
| 551 | 519 | gamecom_dma.dest_width = 64; |
| 552 | 520 | gamecom_dma.dest_bank = (UINT8*)memory_get_read_ptr(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), 0xE000 ); |
| 553 | 521 | break; |
| r8731 | r8732 | |
| 693 | 661 | |
| 694 | 662 | DRIVER_INIT( gamecom ) |
| 695 | 663 | { |
| 696 | | gamecom_cpu = machine->device("maincpu"); |
| 697 | | gamecom_iram = sm8500_get_internal_ram(machine->device<legacy_cpu_device>("maincpu")); |
| 698 | 664 | gamecom_clock_timer = timer_alloc(machine, gamecom_clock_timer_callback , NULL); |
| 699 | 665 | } |
| 700 | 666 | |