trunk/src/emu/cpu/h6280/h6280ops.h
| r19741 | r19742 | |
| 21 | 21 | #define _fN 0x80 |
| 22 | 22 | |
| 23 | 23 | /* some shortcuts for improved readability */ |
| 24 | | #define A cpustate->a |
| 25 | | #define X cpustate->x |
| 26 | | #define Y cpustate->y |
| 27 | | #define P cpustate->p |
| 28 | | #define S cpustate->sp.b.l |
| 24 | #define A m_a |
| 25 | #define X m_x |
| 26 | #define Y m_y |
| 27 | #define P m_p |
| 28 | #define S m_sp.b.l |
| 29 | 29 | |
| 30 | | #define TRANSLATED(addr) ((cpustate->mmr[(addr)>>13&7] << 13) | ((addr)&0x1fff)) |
| 31 | | #define H6280_CYCLES(cyc) \ |
| 32 | | { \ |
| 33 | | cpustate->ICount -= ((cyc) * cpustate->clocks_per_cycle); \ |
| 34 | | cpustate->timer_value -= ((cyc) * cpustate->clocks_per_cycle); \ |
| 30 | #define TRANSLATED(addr) ((m_mmr[(addr) >> 13 & 7] << 13) | ((addr) & 0x1fff)) |
| 31 | #define H6280_CYCLES(cyc) \ |
| 32 | { \ |
| 33 | m_icount -= ((cyc) * m_clocks_per_cycle); \ |
| 34 | m_timer_value -= ((cyc) * m_clocks_per_cycle); \ |
| 35 | 35 | } |
| 36 | 36 | |
| 37 | 37 | #if LAZY_FLAGS |
| 38 | 38 | |
| 39 | | #define NZ cpustate->NZ |
| 39 | #define NZ m_NZ |
| 40 | 40 | #define SET_NZ(n) \ |
| 41 | 41 | P &= ~_fT; \ |
| 42 | 42 | NZ = ((n & _fN) << 8) | n |
| r19741 | r19742 | |
| 50 | 50 | |
| 51 | 51 | #endif |
| 52 | 52 | |
| 53 | | #define EAL cpustate->ea.b.l |
| 54 | | #define EAH cpustate->ea.b.h |
| 55 | | #define EAW cpustate->ea.w.l |
| 56 | | #define EAD cpustate->ea.d |
| 53 | #define EAL m_ea.b.l |
| 54 | #define EAH m_ea.b.h |
| 55 | #define EAW m_ea.w.l |
| 56 | #define EAD m_ea.d |
| 57 | 57 | |
| 58 | | #define ZPL cpustate->zp.b.l |
| 59 | | #define ZPH cpustate->zp.b.h |
| 60 | | #define ZPW cpustate->zp.w.l |
| 61 | | #define ZPD cpustate->zp.d |
| 58 | #define ZPL m_zp.b.l |
| 59 | #define ZPH m_zp.b.h |
| 60 | #define ZPW m_zp.w.l |
| 61 | #define ZPD m_zp.d |
| 62 | 62 | |
| 63 | | #define PCL cpustate->pc.b.l |
| 64 | | #define PCH cpustate->pc.b.h |
| 65 | | #define PCW cpustate->pc.w.l |
| 66 | | #define PCD cpustate->pc.d |
| 63 | #define PCL m_pc.b.l |
| 64 | #define PCH m_pc.b.h |
| 65 | #define PCW m_pc.w.l |
| 66 | #define PCD m_pc.d |
| 67 | 67 | |
| 68 | 68 | #define CLEAR_T \ |
| 69 | 69 | P &= ~_fT; |
| r19741 | r19742 | |
| 71 | 71 | #define DO_INTERRUPT(vector) \ |
| 72 | 72 | { \ |
| 73 | 73 | H6280_CYCLES(7); /* 7 cycles for an int */ \ |
| 74 | | PUSH(PCH); \ |
| 75 | | PUSH(PCL); \ |
| 76 | | COMPOSE_P(0,_fB); \ |
| 77 | | PUSH(P); \ |
| 74 | push(PCH); \ |
| 75 | push(PCL); \ |
| 76 | COMPOSE_P(0, _fB); \ |
| 77 | push(P); \ |
| 78 | 78 | P = (P & ~_fD) | _fI; /* knock out D and set I flag */ \ |
| 79 | | PCL = RDMEM(cpustate, vector); \ |
| 80 | | PCH = RDMEM(cpustate, (vector+1)); \ |
| 79 | PCL = program_read8(vector); \ |
| 80 | PCH = program_read8(vector + 1); \ |
| 81 | 81 | } |
| 82 | 82 | |
| 83 | | #define CHECK_AND_TAKE_IRQ_LINES \ |
| 84 | | if ( cpustate->nmi_state != CLEAR_LINE ) { \ |
| 85 | | cpustate->nmi_state = CLEAR_LINE; \ |
| 86 | | DO_INTERRUPT(H6280_NMI_VEC); \ |
| 87 | | } \ |
| 88 | | else if( !(P & _fI) ) \ |
| 89 | | { \ |
| 90 | | if ( cpustate->irq_state[2] != CLEAR_LINE && \ |
| 91 | | !(cpustate->irq_mask & 0x4) ) \ |
| 92 | | { \ |
| 93 | | DO_INTERRUPT(H6280_TIMER_VEC); \ |
| 94 | | } else \ |
| 95 | | if ( cpustate->irq_state[0] != CLEAR_LINE && \ |
| 96 | | !(cpustate->irq_mask & 0x2) ) \ |
| 97 | | { \ |
| 98 | | DO_INTERRUPT(H6280_IRQ1_VEC); \ |
| 99 | | (*cpustate->irq_callback)(cpustate->device, 0); \ |
| 100 | | } else \ |
| 101 | | if ( cpustate->irq_state[1] != CLEAR_LINE && \ |
| 102 | | !(cpustate->irq_mask & 0x1) ) \ |
| 103 | | { \ |
| 104 | | DO_INTERRUPT(H6280_IRQ2_VEC); \ |
| 105 | | (*cpustate->irq_callback)(cpustate->device, 1); \ |
| 106 | | } \ |
| 83 | #define CHECK_AND_TAKE_IRQ_LINES \ |
| 84 | if ( m_nmi_state != CLEAR_LINE ) { \ |
| 85 | m_nmi_state = CLEAR_LINE; \ |
| 86 | DO_INTERRUPT(H6280_NMI_VEC); \ |
| 87 | } \ |
| 88 | else if( !(P & _fI) ) \ |
| 89 | { \ |
| 90 | if ( m_irq_state[2] != CLEAR_LINE && \ |
| 91 | !(m_irq_mask & 0x4) ) \ |
| 92 | { \ |
| 93 | DO_INTERRUPT(H6280_TIMER_VEC); \ |
| 94 | } else \ |
| 95 | if ( m_irq_state[0] != CLEAR_LINE && \ |
| 96 | !(m_irq_mask & 0x2) ) \ |
| 97 | { \ |
| 98 | DO_INTERRUPT(H6280_IRQ1_VEC); \ |
| 99 | standard_irq_callback(0); \ |
| 100 | } else \ |
| 101 | if ( m_irq_state[1] != CLEAR_LINE && \ |
| 102 | !(m_irq_mask & 0x1) ) \ |
| 103 | { \ |
| 104 | DO_INTERRUPT(H6280_IRQ2_VEC); \ |
| 105 | standard_irq_callback(1); \ |
| 106 | } \ |
| 107 | 107 | } |
| 108 | 108 | |
| 109 | | #define CHECK_IRQ_LINES \ |
| 110 | | if ( ! cpustate->irq_pending ) \ |
| 111 | | cpustate->irq_pending = 2; |
| 109 | #define CHECK_IRQ_LINES \ |
| 110 | if (!m_irq_pending) \ |
| 111 | m_irq_pending = 2; |
| 112 | 112 | |
| 113 | 113 | /*************************************************************** |
| 114 | 114 | * CHECK_VDC_VCE_PENALTY |
| r19741 | r19742 | |
| 121 | 121 | } |
| 122 | 122 | |
| 123 | 123 | /*************************************************************** |
| 124 | | * RDMEM read memory |
| 125 | | ***************************************************************/ |
| 126 | | INLINE UINT8 RDMEM(h6280_Regs* cpustate, offs_t addr) { |
| 127 | | CHECK_VDC_VCE_PENALTY(addr); |
| 128 | | return cpustate->program->read_byte(TRANSLATED(addr)); |
| 129 | | } |
| 130 | | |
| 131 | | /*************************************************************** |
| 132 | | * WRMEM write memory |
| 133 | | ***************************************************************/ |
| 134 | | INLINE void WRMEM(h6280_Regs* cpustate, offs_t addr, UINT8 data) { |
| 135 | | CHECK_VDC_VCE_PENALTY(addr); |
| 136 | | cpustate->program->write_byte(TRANSLATED(addr),data); |
| 137 | | } |
| 138 | | |
| 139 | | /*************************************************************** |
| 140 | | * RDMEMZ read memory - zero page |
| 141 | | ***************************************************************/ |
| 142 | | #define RDMEMZ(addr) \ |
| 143 | | cpustate->program->read_byte((cpustate->mmr[1] << 13) | ((addr)&0x1fff)); |
| 144 | | |
| 145 | | /*************************************************************** |
| 146 | | * WRMEMZ write memory - zero page |
| 147 | | ***************************************************************/ |
| 148 | | #define WRMEMZ(addr,data) \ |
| 149 | | cpustate->program->write_byte((cpustate->mmr[1] << 13) | ((addr)&0x1fff),data); |
| 150 | | |
| 151 | | /*************************************************************** |
| 152 | | * RDMEMW read word from memory |
| 153 | | ***************************************************************/ |
| 154 | | #define RDMEMW(addr) \ |
| 155 | | cpustate->program->read_byte(TRANSLATED(addr)) \ |
| 156 | | | ( cpustate->program->read_byte(TRANSLATED(addr+1)) << 8 ) |
| 157 | | |
| 158 | | /*************************************************************** |
| 159 | | * RDZPWORD read a word from a zero page address |
| 160 | | ***************************************************************/ |
| 161 | | #define RDZPWORD(addr) \ |
| 162 | | ((addr&0xff)==0xff) ? \ |
| 163 | | cpustate->program->read_byte((cpustate->mmr[1] << 13) | ((addr)&0x1fff)) \ |
| 164 | | +(cpustate->program->read_byte((cpustate->mmr[1] << 13) | ((addr-0xff)&0x1fff))<<8) : \ |
| 165 | | cpustate->program->read_byte((cpustate->mmr[1] << 13) | ((addr)&0x1fff)) \ |
| 166 | | +(cpustate->program->read_byte((cpustate->mmr[1] << 13) | ((addr+1)&0x1fff))<<8) |
| 167 | | |
| 168 | | |
| 169 | | /*************************************************************** |
| 170 | | * push a register onto the stack |
| 171 | | ***************************************************************/ |
| 172 | | #define PUSH(Rg) cpustate->program->write_byte((cpustate->mmr[1] << 13) | cpustate->sp.d,Rg); S-- |
| 173 | | |
| 174 | | /*************************************************************** |
| 175 | | * pull a register from the stack |
| 176 | | ***************************************************************/ |
| 177 | | #define PULL(Rg) S++; Rg = cpustate->program->read_byte((cpustate->mmr[1] << 13) | cpustate->sp.d) |
| 178 | | |
| 179 | | /*************************************************************** |
| 180 | | * RDOP read an opcode |
| 181 | | ***************************************************************/ |
| 182 | | #define RDOP() \ |
| 183 | | cpustate->direct->read_decrypted_byte(TRANSLATED(PCW)) |
| 184 | | |
| 185 | | /*************************************************************** |
| 186 | | * RDOPARG read an opcode argument |
| 187 | | ***************************************************************/ |
| 188 | | #define RDOPARG() \ |
| 189 | | cpustate->direct->read_raw_byte(TRANSLATED(PCW)) |
| 190 | | |
| 191 | | /*************************************************************** |
| 192 | 124 | * BRA branch relative |
| 193 | 125 | ***************************************************************/ |
| 194 | 126 | #define BRA(cond) \ |
| r19741 | r19742 | |
| 196 | 128 | if (cond) \ |
| 197 | 129 | { \ |
| 198 | 130 | H6280_CYCLES(4); \ |
| 199 | | tmp = RDOPARG(); \ |
| 131 | tmp = read_opcode_arg(); \ |
| 200 | 132 | PCW++; \ |
| 201 | 133 | EAW = PCW + (signed char)tmp; \ |
| 202 | 134 | PCD = EAD; \ |
| r19741 | r19742 | |
| 217 | 149 | * EA = zero page address |
| 218 | 150 | ***************************************************************/ |
| 219 | 151 | #define EA_ZPG \ |
| 220 | | ZPL = RDOPARG(); \ |
| 152 | ZPL = read_opcode_arg(); \ |
| 221 | 153 | PCW++; \ |
| 222 | 154 | EAD = ZPD |
| 223 | 155 | |
| r19741 | r19742 | |
| 232 | 164 | * EA = zero page address + X |
| 233 | 165 | ***************************************************************/ |
| 234 | 166 | #define EA_ZPX \ |
| 235 | | ZPL = RDOPARG() + X; \ |
| 167 | ZPL = read_opcode_arg() + X; \ |
| 236 | 168 | PCW++; \ |
| 237 | 169 | EAD = ZPD |
| 238 | 170 | |
| r19741 | r19742 | |
| 240 | 172 | * EA = zero page address + Y |
| 241 | 173 | ***************************************************************/ |
| 242 | 174 | #define EA_ZPY \ |
| 243 | | ZPL = RDOPARG() + Y; \ |
| 175 | ZPL = read_opcode_arg() + Y; \ |
| 244 | 176 | PCW++; \ |
| 245 | 177 | EAD = ZPD |
| 246 | 178 | |
| r19741 | r19742 | |
| 248 | 180 | * EA = absolute address |
| 249 | 181 | ***************************************************************/ |
| 250 | 182 | #define EA_ABS \ |
| 251 | | EAL = RDOPARG(); \ |
| 183 | EAL = read_opcode_arg(); \ |
| 252 | 184 | PCW++; \ |
| 253 | | EAH = RDOPARG(); \ |
| 185 | EAH = read_opcode_arg(); \ |
| 254 | 186 | PCW++ |
| 255 | 187 | |
| 256 | 188 | /*************************************************************** |
| r19741 | r19742 | |
| 271 | 203 | * EA = zero page indirect (65c02 pre indexed w/o X) |
| 272 | 204 | ***************************************************************/ |
| 273 | 205 | #define EA_ZPI \ |
| 274 | | ZPL = RDOPARG(); \ |
| 206 | ZPL = read_opcode_arg(); \ |
| 275 | 207 | PCW++; \ |
| 276 | | EAD = RDZPWORD(ZPD) |
| 208 | EAD = program_read16z(ZPD); |
| 277 | 209 | |
| 278 | 210 | /*************************************************************** |
| 279 | 211 | * EA = zero page + X indirect (pre indexed) |
| 280 | 212 | ***************************************************************/ |
| 281 | 213 | #define EA_IDX \ |
| 282 | | ZPL = RDOPARG() + X; \ |
| 214 | ZPL = read_opcode_arg() + X; \ |
| 283 | 215 | PCW++; \ |
| 284 | | EAD = RDZPWORD(ZPD); |
| 216 | EAD = program_read16z(ZPD); |
| 285 | 217 | |
| 286 | 218 | /*************************************************************** |
| 287 | 219 | * EA = zero page indirect + Y (post indexed) |
| 288 | 220 | ***************************************************************/ |
| 289 | 221 | #define EA_IDY \ |
| 290 | | ZPL = RDOPARG(); \ |
| 222 | ZPL = read_opcode_arg(); \ |
| 291 | 223 | PCW++; \ |
| 292 | | EAD = RDZPWORD(ZPD); \ |
| 224 | EAD = program_read16z(ZPD); \ |
| 293 | 225 | EAW += Y |
| 294 | 226 | |
| 295 | 227 | /*************************************************************** |
| r19741 | r19742 | |
| 297 | 229 | ***************************************************************/ |
| 298 | 230 | #define EA_IND \ |
| 299 | 231 | EA_ABS; \ |
| 300 | | tmp = RDMEM(cpustate, EAD); \ |
| 232 | tmp = program_read8(EAD); \ |
| 301 | 233 | EAD++; \ |
| 302 | | EAH = RDMEM(cpustate, EAD); \ |
| 234 | EAH = program_read8(EAD); \ |
| 303 | 235 | EAL = tmp |
| 304 | 236 | |
| 305 | 237 | /*************************************************************** |
| r19741 | r19742 | |
| 308 | 240 | #define EA_IAX \ |
| 309 | 241 | EA_ABS; \ |
| 310 | 242 | EAD+=X; \ |
| 311 | | tmp = RDMEM(cpustate, EAD); \ |
| 243 | tmp = program_read8(EAD); \ |
| 312 | 244 | EAD++; \ |
| 313 | | EAH = RDMEM(cpustate, EAD); \ |
| 245 | EAH = program_read8(EAD); \ |
| 314 | 246 | EAL = tmp |
| 315 | 247 | |
| 316 | 248 | /* read a value into tmp */ |
| 317 | | #define RD_IMM tmp = RDOPARG(); PCW++ |
| 318 | | #define RD_IMM2 tmp2 = RDOPARG(); PCW++ |
| 249 | #define RD_IMM tmp = read_opcode_arg(); PCW++ |
| 250 | #define RD_IMM2 tmp2 = read_opcode_arg(); PCW++ |
| 319 | 251 | #define RD_ACC tmp = A |
| 320 | | #define RD_ZPG EA_ZPG; tmp = RDMEMZ(EAD) |
| 321 | | #define RD_ZPX EA_ZPX; tmp = RDMEMZ(EAD) |
| 322 | | #define RD_ZPY EA_ZPY; tmp = RDMEMZ(EAD) |
| 323 | | #define RD_ABS EA_ABS; tmp = RDMEM(cpustate, EAD) |
| 324 | | #define RD_ABX EA_ABX; tmp = RDMEM(cpustate, EAD) |
| 325 | | #define RD_ABY EA_ABY; tmp = RDMEM(cpustate, EAD) |
| 326 | | #define RD_ZPI EA_ZPI; tmp = RDMEM(cpustate, EAD) |
| 327 | | #define RD_IDX EA_IDX; tmp = RDMEM(cpustate, EAD) |
| 328 | | #define RD_IDY EA_IDY; tmp = RDMEM(cpustate, EAD) |
| 329 | | #define RD_TFL EA_TFLG; tflagtemp = RDMEMZ(EAD) |
| 252 | #define RD_ZPG EA_ZPG; tmp = program_read8z(EAD) |
| 253 | #define RD_ZPX EA_ZPX; tmp = program_read8z(EAD) |
| 254 | #define RD_ZPY EA_ZPY; tmp = program_read8z(EAD) |
| 255 | #define RD_ABS EA_ABS; tmp = program_read8(EAD) |
| 256 | #define RD_ABX EA_ABX; tmp = program_read8(EAD) |
| 257 | #define RD_ABY EA_ABY; tmp = program_read8(EAD) |
| 258 | #define RD_ZPI EA_ZPI; tmp = program_read8(EAD) |
| 259 | #define RD_IDX EA_IDX; tmp = program_read8(EAD) |
| 260 | #define RD_IDY EA_IDY; tmp = program_read8(EAD) |
| 261 | #define RD_TFL EA_TFLG; tflagtemp = program_read8z(EAD) |
| 330 | 262 | |
| 331 | 263 | /* write a value from tmp */ |
| 332 | | #define WR_ZPG EA_ZPG; WRMEMZ(EAD, tmp) |
| 333 | | #define WR_ZPX EA_ZPX; WRMEMZ(EAD, tmp) |
| 334 | | #define WR_ZPY EA_ZPY; WRMEMZ(EAD, tmp) |
| 335 | | #define WR_ABS EA_ABS; WRMEM(cpustate, EAD, tmp) |
| 336 | | #define WR_ABX EA_ABX; WRMEM(cpustate, EAD, tmp) |
| 337 | | #define WR_ABY EA_ABY; WRMEM(cpustate, EAD, tmp) |
| 338 | | #define WR_ZPI EA_ZPI; WRMEM(cpustate, EAD, tmp) |
| 339 | | #define WR_IDX EA_IDX; WRMEM(cpustate, EAD, tmp) |
| 340 | | #define WR_IDY EA_IDY; WRMEM(cpustate, EAD, tmp) |
| 264 | #define WR_ZPG EA_ZPG; program_write8z(EAD, tmp) |
| 265 | #define WR_ZPX EA_ZPX; program_write8z(EAD, tmp) |
| 266 | #define WR_ZPY EA_ZPY; program_write8z(EAD, tmp) |
| 267 | #define WR_ABS EA_ABS; program_write8(EAD, tmp) |
| 268 | #define WR_ABX EA_ABX; program_write8(EAD, tmp) |
| 269 | #define WR_ABY EA_ABY; program_write8(EAD, tmp) |
| 270 | #define WR_ZPI EA_ZPI; program_write8(EAD, tmp) |
| 271 | #define WR_IDX EA_IDX; program_write8(EAD, tmp) |
| 272 | #define WR_IDY EA_IDY; program_write8(EAD, tmp) |
| 341 | 273 | |
| 342 | 274 | /* write back a value from tmp to the last EA */ |
| 343 | 275 | #define WB_ACC A = (UINT8)tmp; |
| 344 | | #define WB_EA WRMEM(cpustate, EAD, tmp) |
| 345 | | #define WB_EAZ WRMEMZ(EAD, tmp) |
| 346 | | #define WB_TFL WRMEMZ(EAD, tflagtemp) |
| 276 | #define WB_EA program_write8(EAD, tmp) |
| 277 | #define WB_EAZ program_write8z(EAD, tmp) |
| 278 | #define WB_TFL program_write8z(EAD, tflagtemp) |
| 347 | 279 | |
| 348 | 280 | /*************************************************************** |
| 349 | 281 | * |
| r19741 | r19742 | |
| 515 | 447 | /* 6280 ******************************************************** |
| 516 | 448 | * BIT Bit test |
| 517 | 449 | ***************************************************************/ |
| 518 | | #undef BIT |
| 519 | | #define BIT \ |
| 450 | #define HBIT \ |
| 520 | 451 | P = (P & ~(_fN|_fV|_fT|_fZ)) \ |
| 521 | 452 | | ((tmp&0x80) ? _fN:0) \ |
| 522 | 453 | | ((tmp&0x40) ? _fV:0) \ |
| r19741 | r19742 | |
| 558 | 489 | logerror("BRK %04x\n",PCW); \ |
| 559 | 490 | CLEAR_T; \ |
| 560 | 491 | PCW++; \ |
| 561 | | PUSH(PCH); \ |
| 562 | | PUSH(PCL); \ |
| 563 | | PUSH(P); \ |
| 492 | push(PCH); \ |
| 493 | push(PCL); \ |
| 494 | push(P); \ |
| 564 | 495 | P = (P & ~_fD) | _fI; \ |
| 565 | | PCL = RDMEM(cpustate, H6280_IRQ2_VEC); \ |
| 566 | | PCH = RDMEM(cpustate, H6280_IRQ2_VEC+1); \ |
| 496 | PCL = program_read8(H6280_IRQ2_VEC); \ |
| 497 | PCH = program_read8(H6280_IRQ2_VEC+1); \ |
| 567 | 498 | |
| 568 | 499 | /* 6280 ******************************************************** |
| 569 | 500 | * BSR Branch to subroutine |
| 570 | 501 | ***************************************************************/ |
| 571 | 502 | #define BSR \ |
| 572 | | PUSH(PCH); \ |
| 573 | | PUSH(PCL); \ |
| 503 | push(PCH); \ |
| 504 | push(PCL); \ |
| 574 | 505 | H6280_CYCLES(4); /* 4 cycles here, 4 in BRA */ \ |
| 575 | 506 | BRA(1) |
| 576 | 507 | |
| r19741 | r19742 | |
| 770 | 701 | #define JSR \ |
| 771 | 702 | CLEAR_T; \ |
| 772 | 703 | PCW--; \ |
| 773 | | PUSH(PCH); \ |
| 774 | | PUSH(PCL); \ |
| 704 | push(PCH); \ |
| 705 | push(PCL); \ |
| 775 | 706 | PCD = EAD; \ |
| 776 | 707 | |
| 777 | 708 | /* 6280 ******************************************************** |
| r19741 | r19742 | |
| 841 | 772 | ***************************************************************/ |
| 842 | 773 | #define PHA \ |
| 843 | 774 | CLEAR_T; \ |
| 844 | | PUSH(A) |
| 775 | push(A) |
| 845 | 776 | |
| 846 | 777 | /* 6280 ******************************************************** |
| 847 | 778 | * PHP Push processor status (flags) |
| r19741 | r19742 | |
| 849 | 780 | #define PHP \ |
| 850 | 781 | CLEAR_T; \ |
| 851 | 782 | COMPOSE_P(0,0); \ |
| 852 | | PUSH(P) |
| 783 | push(P) |
| 853 | 784 | |
| 854 | 785 | /* 6280 ******************************************************** |
| 855 | 786 | * PHX Push index X |
| 856 | 787 | ***************************************************************/ |
| 857 | 788 | #define PHX \ |
| 858 | 789 | CLEAR_T; \ |
| 859 | | PUSH(X) |
| 790 | push(X) |
| 860 | 791 | |
| 861 | 792 | /* 6280 ******************************************************** |
| 862 | 793 | * PHY Push index Y |
| 863 | 794 | ***************************************************************/ |
| 864 | 795 | #define PHY \ |
| 865 | 796 | CLEAR_T; \ |
| 866 | | PUSH(Y) |
| 797 | push(Y) |
| 867 | 798 | |
| 868 | 799 | /* 6280 ******************************************************** |
| 869 | 800 | * PLA Pull accumulator |
| 870 | 801 | ***************************************************************/ |
| 871 | 802 | #define PLA \ |
| 872 | 803 | CLEAR_T; \ |
| 873 | | PULL(A); \ |
| 804 | pull(A); \ |
| 874 | 805 | SET_NZ(A) |
| 875 | 806 | |
| 876 | 807 | /* 6280 ******************************************************** |
| r19741 | r19742 | |
| 879 | 810 | #if LAZY_FLAGS |
| 880 | 811 | |
| 881 | 812 | #define PLP \ |
| 882 | | PULL(P); \ |
| 813 | pull(P); \ |
| 883 | 814 | P |= _fB; \ |
| 884 | 815 | NZ = ((P & _fN) << 8) | \ |
| 885 | 816 | ((P & _fZ) ^ _fZ); \ |
| r19741 | r19742 | |
| 888 | 819 | #else |
| 889 | 820 | |
| 890 | 821 | #define PLP \ |
| 891 | | PULL(P); \ |
| 822 | pull(P); \ |
| 892 | 823 | P |= _fB; \ |
| 893 | 824 | CHECK_IRQ_LINES |
| 894 | 825 | #endif |
| r19741 | r19742 | |
| 898 | 829 | ***************************************************************/ |
| 899 | 830 | #define PLX \ |
| 900 | 831 | CLEAR_T; \ |
| 901 | | PULL(X); \ |
| 832 | pull(X); \ |
| 902 | 833 | SET_NZ(X) |
| 903 | 834 | |
| 904 | 835 | /* 6280 ******************************************************** |
| r19741 | r19742 | |
| 906 | 837 | ***************************************************************/ |
| 907 | 838 | #define PLY \ |
| 908 | 839 | CLEAR_T; \ |
| 909 | | PULL(Y); \ |
| 840 | pull(Y); \ |
| 910 | 841 | SET_NZ(Y) |
| 911 | 842 | |
| 912 | 843 | /* 6280 ******************************************************** |
| r19741 | r19742 | |
| 945 | 876 | #if LAZY_FLAGS |
| 946 | 877 | |
| 947 | 878 | #define RTI \ |
| 948 | | PULL(P); \ |
| 879 | pull(P); \ |
| 949 | 880 | P |= _fB; \ |
| 950 | 881 | NZ = ((P & _fN) << 8) | \ |
| 951 | 882 | ((P & _fZ) ^ _fZ); \ |
| 952 | | PULL(PCL); \ |
| 953 | | PULL(PCH); \ |
| 883 | pull(PCL); \ |
| 884 | pull(PCH); \ |
| 954 | 885 | CHECK_IRQ_LINES |
| 955 | 886 | #else |
| 956 | 887 | |
| 957 | 888 | #define RTI \ |
| 958 | | PULL(P); \ |
| 889 | pull(P); \ |
| 959 | 890 | P |= _fB; \ |
| 960 | | PULL(PCL); \ |
| 961 | | PULL(PCH); \ |
| 891 | pull(PCL); \ |
| 892 | pull(PCH); \ |
| 962 | 893 | CHECK_IRQ_LINES |
| 963 | 894 | #endif |
| 964 | 895 | |
| r19741 | r19742 | |
| 968 | 899 | ***************************************************************/ |
| 969 | 900 | #define RTS \ |
| 970 | 901 | CLEAR_T; \ |
| 971 | | PULL(PCL); \ |
| 972 | | PULL(PCH); \ |
| 902 | pull(PCL); \ |
| 903 | pull(PCH); \ |
| 973 | 904 | PCW++; |
| 974 | 905 | |
| 975 | 906 | /* 6280 ******************************************************** |
| r19741 | r19742 | |
| 1110 | 1041 | ***************************************************************/ |
| 1111 | 1042 | #define ST0 \ |
| 1112 | 1043 | CLEAR_T; \ |
| 1113 | | cpustate->io->write_byte(0x0000,tmp) |
| 1044 | m_io->write_byte(0x0000,tmp) |
| 1114 | 1045 | |
| 1115 | 1046 | /* 6280 ******************************************************** |
| 1116 | 1047 | * ST1 Store at hardware address 2 |
| 1117 | 1048 | ***************************************************************/ |
| 1118 | 1049 | #define ST1 \ |
| 1119 | 1050 | CLEAR_T; \ |
| 1120 | | cpustate->io->write_byte(0x0002,tmp) |
| 1051 | m_io->write_byte(0x0002,tmp) |
| 1121 | 1052 | |
| 1122 | 1053 | /* 6280 ******************************************************** |
| 1123 | 1054 | * ST2 Store at hardware address 3 |
| 1124 | 1055 | ***************************************************************/ |
| 1125 | 1056 | #define ST2 \ |
| 1126 | 1057 | CLEAR_T; \ |
| 1127 | | cpustate->io->write_byte(0x0003,tmp) |
| 1058 | m_io->write_byte(0x0003,tmp) |
| 1128 | 1059 | |
| 1129 | 1060 | /* 6280 ******************************************************** |
| 1130 | 1061 | * STA Store accumulator |
| r19741 | r19742 | |
| 1168 | 1099 | ***************************************************************/ |
| 1169 | 1100 | #define TAI \ |
| 1170 | 1101 | CLEAR_T; \ |
| 1171 | | from=RDMEMW(PCW); \ |
| 1172 | | to =RDMEMW(PCW+2); \ |
| 1173 | | length=RDMEMW(PCW+4); \ |
| 1174 | | PCW+=6; \ |
| 1175 | | alternate=0; \ |
| 1102 | from = program_read16(PCW); \ |
| 1103 | to = program_read16(PCW + 2); \ |
| 1104 | length = program_read16(PCW + 4); \ |
| 1105 | PCW += 6; \ |
| 1106 | alternate = 0; \ |
| 1176 | 1107 | if (!length) length = 0x10000; \ |
| 1177 | 1108 | H6280_CYCLES( ((6 * length) + 17) ); \ |
| 1178 | | while ((length--) != 0) { \ |
| 1179 | | WRMEM(cpustate, to,RDMEM(cpustate, from+alternate)); \ |
| 1109 | while ((length--) != 0) \ |
| 1110 | { \ |
| 1111 | program_write8(to, program_read8(from + alternate)); \ |
| 1180 | 1112 | to++; \ |
| 1181 | 1113 | alternate ^= 1; \ |
| 1182 | 1114 | } |
| r19741 | r19742 | |
| 1186 | 1118 | ***************************************************************/ |
| 1187 | 1119 | #define TAM \ |
| 1188 | 1120 | CLEAR_T; \ |
| 1189 | | if (tmp&0x01) cpustate->mmr[0] = A; \ |
| 1190 | | if (tmp&0x02) cpustate->mmr[1] = A; \ |
| 1191 | | if (tmp&0x04) cpustate->mmr[2] = A; \ |
| 1192 | | if (tmp&0x08) cpustate->mmr[3] = A; \ |
| 1193 | | if (tmp&0x10) cpustate->mmr[4] = A; \ |
| 1194 | | if (tmp&0x20) cpustate->mmr[5] = A; \ |
| 1195 | | if (tmp&0x40) cpustate->mmr[6] = A; \ |
| 1196 | | if (tmp&0x80) cpustate->mmr[7] = A |
| 1121 | if (tmp&0x01) m_mmr[0] = A; \ |
| 1122 | if (tmp&0x02) m_mmr[1] = A; \ |
| 1123 | if (tmp&0x04) m_mmr[2] = A; \ |
| 1124 | if (tmp&0x08) m_mmr[3] = A; \ |
| 1125 | if (tmp&0x10) m_mmr[4] = A; \ |
| 1126 | if (tmp&0x20) m_mmr[5] = A; \ |
| 1127 | if (tmp&0x40) m_mmr[6] = A; \ |
| 1128 | if (tmp&0x80) m_mmr[7] = A |
| 1197 | 1129 | |
| 1198 | 1130 | /* 6280 ******************************************************** |
| 1199 | 1131 | * TAX Transfer accumulator to index X |
| r19741 | r19742 | |
| 1216 | 1148 | ***************************************************************/ |
| 1217 | 1149 | #define TDD \ |
| 1218 | 1150 | CLEAR_T; \ |
| 1219 | | from=RDMEMW(PCW); \ |
| 1220 | | to =RDMEMW(PCW+2); \ |
| 1221 | | length=RDMEMW(PCW+4); \ |
| 1151 | from = program_read16(PCW); \ |
| 1152 | to = program_read16(PCW + 2); \ |
| 1153 | length = program_read16(PCW + 4); \ |
| 1222 | 1154 | PCW+=6; \ |
| 1223 | 1155 | if (!length) length = 0x10000; \ |
| 1224 | 1156 | H6280_CYCLES( ((6 * length) + 17) ); \ |
| 1225 | 1157 | while ((length--) != 0) { \ |
| 1226 | | WRMEM(cpustate, to,RDMEM(cpustate, from)); \ |
| 1158 | program_write8(to, program_read8(from)); \ |
| 1227 | 1159 | to--; \ |
| 1228 | 1160 | from--; \ |
| 1229 | 1161 | } |
| r19741 | r19742 | |
| 1233 | 1165 | ***************************************************************/ |
| 1234 | 1166 | #define TIA \ |
| 1235 | 1167 | CLEAR_T; \ |
| 1236 | | from=RDMEMW(PCW); \ |
| 1237 | | to =RDMEMW(PCW+2); \ |
| 1238 | | length=RDMEMW(PCW+4); \ |
| 1168 | from = program_read16(PCW); \ |
| 1169 | to = program_read16(PCW + 2); \ |
| 1170 | length = program_read16(PCW + 4); \ |
| 1239 | 1171 | PCW+=6; \ |
| 1240 | 1172 | alternate=0; \ |
| 1241 | 1173 | if (!length) length = 0x10000; \ |
| 1242 | 1174 | H6280_CYCLES( ((6 * length) + 17) ); \ |
| 1243 | 1175 | while ((length--) != 0) { \ |
| 1244 | | WRMEM(cpustate, to+alternate,RDMEM(cpustate, from)); \ |
| 1176 | program_write8(to + alternate, program_read8(from)); \ |
| 1245 | 1177 | from++; \ |
| 1246 | 1178 | alternate ^= 1; \ |
| 1247 | 1179 | } |
| r19741 | r19742 | |
| 1251 | 1183 | ***************************************************************/ |
| 1252 | 1184 | #define TII \ |
| 1253 | 1185 | CLEAR_T; \ |
| 1254 | | from=RDMEMW(PCW); \ |
| 1255 | | to =RDMEMW(PCW+2); \ |
| 1256 | | length=RDMEMW(PCW+4); \ |
| 1257 | | PCW+=6; \ |
| 1186 | from = program_read16(PCW); \ |
| 1187 | to = program_read16(PCW + 2); \ |
| 1188 | length = program_read16(PCW + 4); \ |
| 1189 | PCW += 6; \ |
| 1258 | 1190 | if (!length) length = 0x10000; \ |
| 1259 | 1191 | H6280_CYCLES( ((6 * length) + 17) ); \ |
| 1260 | 1192 | while ((length--) != 0) { \ |
| 1261 | | WRMEM(cpustate, to,RDMEM(cpustate, from)); \ |
| 1193 | program_write8(to, program_read8(from)); \ |
| 1262 | 1194 | to++; \ |
| 1263 | 1195 | from++; \ |
| 1264 | 1196 | } |
| r19741 | r19742 | |
| 1268 | 1200 | ***************************************************************/ |
| 1269 | 1201 | #define TIN \ |
| 1270 | 1202 | CLEAR_T; \ |
| 1271 | | from=RDMEMW(PCW); \ |
| 1272 | | to =RDMEMW(PCW+2); \ |
| 1273 | | length=RDMEMW(PCW+4); \ |
| 1203 | from = program_read16(PCW); \ |
| 1204 | to = program_read16(PCW + 2); \ |
| 1205 | length = program_read16(PCW + 4); \ |
| 1274 | 1206 | PCW+=6; \ |
| 1275 | 1207 | if (!length) length = 0x10000; \ |
| 1276 | 1208 | H6280_CYCLES( ((6 * length) + 17) ); \ |
| 1277 | 1209 | while ((length--) != 0) { \ |
| 1278 | | WRMEM(cpustate, to,RDMEM(cpustate, from)); \ |
| 1210 | program_write8(to, program_read8(from)); \ |
| 1279 | 1211 | from++; \ |
| 1280 | 1212 | } |
| 1281 | 1213 | |
| r19741 | r19742 | |
| 1285 | 1217 | ***************************************************************/ |
| 1286 | 1218 | #define TMA \ |
| 1287 | 1219 | CLEAR_T; \ |
| 1288 | | if (tmp&0x01) A = cpustate->mmr[0]; \ |
| 1289 | | if (tmp&0x02) A = cpustate->mmr[1]; \ |
| 1290 | | if (tmp&0x04) A = cpustate->mmr[2]; \ |
| 1291 | | if (tmp&0x08) A = cpustate->mmr[3]; \ |
| 1292 | | if (tmp&0x10) A = cpustate->mmr[4]; \ |
| 1293 | | if (tmp&0x20) A = cpustate->mmr[5]; \ |
| 1294 | | if (tmp&0x40) A = cpustate->mmr[6]; \ |
| 1295 | | if (tmp&0x80) A = cpustate->mmr[7] |
| 1220 | if (tmp&0x01) A = m_mmr[0]; \ |
| 1221 | if (tmp&0x02) A = m_mmr[1]; \ |
| 1222 | if (tmp&0x04) A = m_mmr[2]; \ |
| 1223 | if (tmp&0x08) A = m_mmr[3]; \ |
| 1224 | if (tmp&0x10) A = m_mmr[4]; \ |
| 1225 | if (tmp&0x20) A = m_mmr[5]; \ |
| 1226 | if (tmp&0x40) A = m_mmr[6]; \ |
| 1227 | if (tmp&0x80) A = m_mmr[7] |
| 1296 | 1228 | |
| 1297 | 1229 | /* 6280 ******************************************************** |
| 1298 | 1230 | * TRB Test and reset bits |
| r19741 | r19742 | |
| 1361 | 1293 | * CSH Set CPU in high speed mode |
| 1362 | 1294 | ***************************************************************/ |
| 1363 | 1295 | #define CSH \ |
| 1364 | | cpustate->clocks_per_cycle = 1; |
| 1296 | m_clocks_per_cycle = 1; |
| 1365 | 1297 | |
| 1366 | 1298 | /* 6280 ******************************************************** |
| 1367 | 1299 | * CSL Set CPU in low speed mode |
| 1368 | 1300 | ***************************************************************/ |
| 1369 | 1301 | #define CSL \ |
| 1370 | | cpustate->clocks_per_cycle = 4; |
| 1302 | m_clocks_per_cycle = 4; |
trunk/src/emu/cpu/h6280/h6280.c
| r19741 | r19742 | |
| 112 | 112 | #include "debugger.h" |
| 113 | 113 | #include "h6280.h" |
| 114 | 114 | |
| 115 | | static void set_irq_line(h6280_Regs* cpustate, int irqline, int state); |
| 115 | //static void set_irq_line(h6280_Regs* cpustate, int irqline, int state); |
| 116 | 116 | |
| 117 | | /* include the macros */ |
| 118 | | #include "h6280ops.h" |
| 117 | //************************************************************************** |
| 118 | // DEVICE INTERFACE |
| 119 | //************************************************************************** |
| 119 | 120 | |
| 120 | | INLINE h6280_Regs *get_safe_token(device_t *device) |
| 121 | const device_type H6280 = &device_creator<h6280_device>; |
| 122 | |
| 123 | //------------------------------------------------- |
| 124 | // h6280_device - constructor |
| 125 | //------------------------------------------------- |
| 126 | |
| 127 | h6280_device::h6280_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 128 | : cpu_device(mconfig, H6280, "H6280", tag, owner, clock), |
| 129 | m_program_config("program", ENDIANNESS_LITTLE, 8, 21), |
| 130 | m_io_config("io", ENDIANNESS_LITTLE, 8, 2) |
| 121 | 131 | { |
| 122 | | assert(device != NULL); |
| 123 | | assert(device->type() == H6280); |
| 124 | | return (h6280_Regs *)downcast<legacy_cpu_device *>(device)->token(); |
| 132 | // build the opcode table |
| 133 | for (int op = 0; op < 256; op++) |
| 134 | m_opcode[op] = s_opcodetable[op]; |
| 125 | 135 | } |
| 126 | 136 | |
| 127 | | /* include the opcode macros, functions and function pointer tables */ |
| 128 | | #include "tblh6280.c" |
| 129 | 137 | |
| 130 | | /*****************************************************************************/ |
| 131 | | static CPU_INIT( h6280 ) |
| 138 | const h6280_device::ophandler h6280_device::s_opcodetable[256] = |
| 132 | 139 | { |
| 133 | | h6280_Regs* cpustate = get_safe_token(device); |
| 140 | &h6280_device::op_000, &h6280_device::op_001, &h6280_device::op_002, &h6280_device::op_003, &h6280_device::op_004, &h6280_device::op_005, &h6280_device::op_006, &h6280_device::op_007, |
| 141 | &h6280_device::op_008, &h6280_device::op_009, &h6280_device::op_00a, &h6280_device::op_00b, &h6280_device::op_00c, &h6280_device::op_00d, &h6280_device::op_00e, &h6280_device::op_00f, |
| 142 | &h6280_device::op_010, &h6280_device::op_011, &h6280_device::op_012, &h6280_device::op_013, &h6280_device::op_014, &h6280_device::op_015, &h6280_device::op_016, &h6280_device::op_017, |
| 143 | &h6280_device::op_018, &h6280_device::op_019, &h6280_device::op_01a, &h6280_device::op_01b, &h6280_device::op_01c, &h6280_device::op_01d, &h6280_device::op_01e, &h6280_device::op_01f, |
| 144 | &h6280_device::op_020, &h6280_device::op_021, &h6280_device::op_022, &h6280_device::op_023, &h6280_device::op_024, &h6280_device::op_025, &h6280_device::op_026, &h6280_device::op_027, |
| 145 | &h6280_device::op_028, &h6280_device::op_029, &h6280_device::op_02a, &h6280_device::op_02b, &h6280_device::op_02c, &h6280_device::op_02d, &h6280_device::op_02e, &h6280_device::op_02f, |
| 146 | &h6280_device::op_030, &h6280_device::op_031, &h6280_device::op_032, &h6280_device::op_033, &h6280_device::op_034, &h6280_device::op_035, &h6280_device::op_036, &h6280_device::op_037, |
| 147 | &h6280_device::op_038, &h6280_device::op_039, &h6280_device::op_03a, &h6280_device::op_03b, &h6280_device::op_03c, &h6280_device::op_03d, &h6280_device::op_03e, &h6280_device::op_03f, |
| 148 | &h6280_device::op_040, &h6280_device::op_041, &h6280_device::op_042, &h6280_device::op_043, &h6280_device::op_044, &h6280_device::op_045, &h6280_device::op_046, &h6280_device::op_047, |
| 149 | &h6280_device::op_048, &h6280_device::op_049, &h6280_device::op_04a, &h6280_device::op_04b, &h6280_device::op_04c, &h6280_device::op_04d, &h6280_device::op_04e, &h6280_device::op_04f, |
| 150 | &h6280_device::op_050, &h6280_device::op_051, &h6280_device::op_052, &h6280_device::op_053, &h6280_device::op_054, &h6280_device::op_055, &h6280_device::op_056, &h6280_device::op_057, |
| 151 | &h6280_device::op_058, &h6280_device::op_059, &h6280_device::op_05a, &h6280_device::op_05b, &h6280_device::op_05c, &h6280_device::op_05d, &h6280_device::op_05e, &h6280_device::op_05f, |
| 152 | &h6280_device::op_060, &h6280_device::op_061, &h6280_device::op_062, &h6280_device::op_063, &h6280_device::op_064, &h6280_device::op_065, &h6280_device::op_066, &h6280_device::op_067, |
| 153 | &h6280_device::op_068, &h6280_device::op_069, &h6280_device::op_06a, &h6280_device::op_06b, &h6280_device::op_06c, &h6280_device::op_06d, &h6280_device::op_06e, &h6280_device::op_06f, |
| 154 | &h6280_device::op_070, &h6280_device::op_071, &h6280_device::op_072, &h6280_device::op_073, &h6280_device::op_074, &h6280_device::op_075, &h6280_device::op_076, &h6280_device::op_077, |
| 155 | &h6280_device::op_078, &h6280_device::op_079, &h6280_device::op_07a, &h6280_device::op_07b, &h6280_device::op_07c, &h6280_device::op_07d, &h6280_device::op_07e, &h6280_device::op_07f, |
| 156 | &h6280_device::op_080, &h6280_device::op_081, &h6280_device::op_082, &h6280_device::op_083, &h6280_device::op_084, &h6280_device::op_085, &h6280_device::op_086, &h6280_device::op_087, |
| 157 | &h6280_device::op_088, &h6280_device::op_089, &h6280_device::op_08a, &h6280_device::op_08b, &h6280_device::op_08c, &h6280_device::op_08d, &h6280_device::op_08e, &h6280_device::op_08f, |
| 158 | &h6280_device::op_090, &h6280_device::op_091, &h6280_device::op_092, &h6280_device::op_093, &h6280_device::op_094, &h6280_device::op_095, &h6280_device::op_096, &h6280_device::op_097, |
| 159 | &h6280_device::op_098, &h6280_device::op_099, &h6280_device::op_09a, &h6280_device::op_09b, &h6280_device::op_09c, &h6280_device::op_09d, &h6280_device::op_09e, &h6280_device::op_09f, |
| 160 | &h6280_device::op_0a0, &h6280_device::op_0a1, &h6280_device::op_0a2, &h6280_device::op_0a3, &h6280_device::op_0a4, &h6280_device::op_0a5, &h6280_device::op_0a6, &h6280_device::op_0a7, |
| 161 | &h6280_device::op_0a8, &h6280_device::op_0a9, &h6280_device::op_0aa, &h6280_device::op_0ab, &h6280_device::op_0ac, &h6280_device::op_0ad, &h6280_device::op_0ae, &h6280_device::op_0af, |
| 162 | &h6280_device::op_0b0, &h6280_device::op_0b1, &h6280_device::op_0b2, &h6280_device::op_0b3, &h6280_device::op_0b4, &h6280_device::op_0b5, &h6280_device::op_0b6, &h6280_device::op_0b7, |
| 163 | &h6280_device::op_0b8, &h6280_device::op_0b9, &h6280_device::op_0ba, &h6280_device::op_0bb, &h6280_device::op_0bc, &h6280_device::op_0bd, &h6280_device::op_0be, &h6280_device::op_0bf, |
| 164 | &h6280_device::op_0c0, &h6280_device::op_0c1, &h6280_device::op_0c2, &h6280_device::op_0c3, &h6280_device::op_0c4, &h6280_device::op_0c5, &h6280_device::op_0c6, &h6280_device::op_0c7, |
| 165 | &h6280_device::op_0c8, &h6280_device::op_0c9, &h6280_device::op_0ca, &h6280_device::op_0cb, &h6280_device::op_0cc, &h6280_device::op_0cd, &h6280_device::op_0ce, &h6280_device::op_0cf, |
| 166 | &h6280_device::op_0d0, &h6280_device::op_0d1, &h6280_device::op_0d2, &h6280_device::op_0d3, &h6280_device::op_0d4, &h6280_device::op_0d5, &h6280_device::op_0d6, &h6280_device::op_0d7, |
| 167 | &h6280_device::op_0d8, &h6280_device::op_0d9, &h6280_device::op_0da, &h6280_device::op_0db, &h6280_device::op_0dc, &h6280_device::op_0dd, &h6280_device::op_0de, &h6280_device::op_0df, |
| 168 | &h6280_device::op_0e0, &h6280_device::op_0e1, &h6280_device::op_0e2, &h6280_device::op_0e3, &h6280_device::op_0e4, &h6280_device::op_0e5, &h6280_device::op_0e6, &h6280_device::op_0e7, |
| 169 | &h6280_device::op_0e8, &h6280_device::op_0e9, &h6280_device::op_0ea, &h6280_device::op_0eb, &h6280_device::op_0ec, &h6280_device::op_0ed, &h6280_device::op_0ee, &h6280_device::op_0ef, |
| 170 | &h6280_device::op_0f0, &h6280_device::op_0f1, &h6280_device::op_0f2, &h6280_device::op_0f3, &h6280_device::op_0f4, &h6280_device::op_0f5, &h6280_device::op_0f6, &h6280_device::op_0f7, |
| 171 | &h6280_device::op_0f8, &h6280_device::op_0f9, &h6280_device::op_0fa, &h6280_device::op_0fb, &h6280_device::op_0fc, &h6280_device::op_0fd, &h6280_device::op_0fe, &h6280_device::op_0ff |
| 172 | }; |
| 134 | 173 | |
| 135 | | device->save_item(NAME(cpustate->ppc.w.l)); |
| 136 | | device->save_item(NAME(cpustate->pc.w.l)); |
| 137 | | device->save_item(NAME(cpustate->sp.w.l)); |
| 138 | | device->save_item(NAME(cpustate->zp.w.l)); |
| 139 | | device->save_item(NAME(cpustate->ea.w.l)); |
| 140 | | device->save_item(NAME(cpustate->a)); |
| 141 | | device->save_item(NAME(cpustate->x)); |
| 142 | | device->save_item(NAME(cpustate->y)); |
| 143 | | device->save_item(NAME(cpustate->p)); |
| 144 | | device->save_item(NAME(cpustate->mmr)); |
| 145 | | device->save_item(NAME(cpustate->irq_mask)); |
| 146 | | device->save_item(NAME(cpustate->timer_status)); |
| 147 | | device->save_item(NAME(cpustate->timer_ack)); |
| 148 | | device->save_item(NAME(cpustate->clocks_per_cycle)); |
| 149 | | device->save_item(NAME(cpustate->timer_value)); |
| 150 | | device->save_item(NAME(cpustate->timer_load)); |
| 151 | | device->save_item(NAME(cpustate->nmi_state)); |
| 152 | | device->save_item(NAME(cpustate->irq_state[0])); |
| 153 | | device->save_item(NAME(cpustate->irq_state[1])); |
| 154 | | device->save_item(NAME(cpustate->irq_state[2])); |
| 155 | | device->save_item(NAME(cpustate->irq_pending)); |
| 174 | void h6280_device::device_start() |
| 175 | { |
| 176 | // register our state for the debugger |
| 177 | state_add(STATE_GENPC, "GENPC", m_pc.w.l).noshow(); |
| 178 | state_add(STATE_GENFLAGS, "GENFLAGS", m_p).callimport().callexport().formatstr("%8s").noshow(); |
| 179 | state_add(H6280_PC, "PC:", m_pc.d).mask(0xffff); |
| 180 | state_add(H6280_S, "S:", m_sp.b.l).mask(0xff); |
| 181 | state_add(H6280_P, "P:", m_p).mask(0xff); |
| 182 | state_add(H6280_A, "A:", m_a).mask(0xff); |
| 183 | state_add(H6280_X, "X:", m_x).mask(0xff); |
| 184 | state_add(H6280_Y, "Y:", m_y).mask(0xff); |
| 185 | state_add(H6280_IRQ_MASK, "IM:", m_irq_mask).mask(0xff); |
| 186 | state_add(H6280_TIMER_STATE,"TMR:", m_timer_status).mask(0xff); |
| 187 | state_add(H6280_NMI_STATE, "NMI:", m_nmi_state).mask(0xf); |
| 188 | state_add(H6280_IRQ1_STATE, "IRQ1:", m_irq_state[0]).mask(0xf); |
| 189 | state_add(H6280_IRQ2_STATE, "IRQ2:", m_irq_state[1]).mask(0xf); |
| 190 | state_add(H6280_IRQT_STATE, "IRQT:", m_irq_state[2]).mask(0xf); |
| 191 | state_add(H6280_M1, "M1:", m_mmr[0]).mask(0xff); |
| 192 | state_add(H6280_M2, "M2:", m_mmr[1]).mask(0xff); |
| 193 | state_add(H6280_M3, "M3:", m_mmr[2]).mask(0xff); |
| 194 | state_add(H6280_M4, "M4:", m_mmr[3]).mask(0xff); |
| 195 | state_add(H6280_M5, "M5:", m_mmr[4]).mask(0xff); |
| 196 | state_add(H6280_M6, "M6:", m_mmr[5]).mask(0xff); |
| 197 | state_add(H6280_M7, "M7:", m_mmr[6]).mask(0xff); |
| 198 | state_add(H6280_M8, "M8:", m_mmr[7]).mask(0xff); |
| 156 | 199 | |
| 200 | save_item(NAME(m_ppc.w.l)); |
| 201 | save_item(NAME(m_pc.w.l)); |
| 202 | save_item(NAME(m_sp.w.l)); |
| 203 | save_item(NAME(m_zp.w.l)); |
| 204 | save_item(NAME(m_ea.w.l)); |
| 205 | save_item(NAME(m_a)); |
| 206 | save_item(NAME(m_x)); |
| 207 | save_item(NAME(m_y)); |
| 208 | save_item(NAME(m_p)); |
| 209 | save_item(NAME(m_mmr)); |
| 210 | save_item(NAME(m_irq_mask)); |
| 211 | save_item(NAME(m_timer_status)); |
| 212 | save_item(NAME(m_timer_ack)); |
| 213 | save_item(NAME(m_clocks_per_cycle)); |
| 214 | save_item(NAME(m_timer_value)); |
| 215 | save_item(NAME(m_timer_load)); |
| 216 | save_item(NAME(m_nmi_state)); |
| 217 | save_item(NAME(m_irq_state[0])); |
| 218 | save_item(NAME(m_irq_state[1])); |
| 219 | save_item(NAME(m_irq_state[2])); |
| 220 | save_item(NAME(m_irq_pending)); |
| 221 | |
| 157 | 222 | #if LAZY_FLAGS |
| 158 | | device->save_item(NAME(cpustate->NZ)); |
| 223 | save_item(NAME(m_nz)); |
| 159 | 224 | #endif |
| 160 | | device->save_item(NAME(cpustate->io_buffer)); |
| 225 | save_item(NAME(m_io_buffer)); |
| 161 | 226 | |
| 162 | | cpustate->irq_callback = irqcallback; |
| 163 | | cpustate->device = device; |
| 164 | | cpustate->program = &device->space(AS_PROGRAM); |
| 165 | | cpustate->direct = &cpustate->program->direct(); |
| 166 | | cpustate->io = &device->space(AS_IO); |
| 227 | // set our instruction counter |
| 228 | m_icountptr = &m_icount; |
| 167 | 229 | } |
| 168 | 230 | |
| 169 | | static CPU_RESET( h6280 ) |
| 231 | void h6280_device::device_reset() |
| 170 | 232 | { |
| 171 | | h6280_Regs* cpustate = get_safe_token(device); |
| 233 | /* wipe out the h6280 structure */ |
| 234 | m_ppc.d = 0; |
| 235 | m_pc.d = 0; |
| 236 | m_zp.d = 0; |
| 237 | m_ea.d = 0; |
| 238 | m_a = 0; |
| 239 | m_x = 0; |
| 240 | m_y = 0; |
| 241 | m_p = 0; |
| 242 | memset(m_mmr, 0, sizeof(UINT8) * 8); |
| 243 | m_irq_mask = 0; |
| 244 | m_timer_ack = 0; |
| 245 | m_timer_value = 0; |
| 246 | #if LAZY_FLAGS |
| 247 | m_nz = 0; |
| 248 | #endif |
| 249 | m_io_buffer = 0; |
| 172 | 250 | |
| 173 | | device_irq_acknowledge_callback save_irqcallback; |
| 174 | | int i; |
| 251 | m_program = &space(AS_PROGRAM); |
| 252 | m_direct = &m_program->direct(); |
| 253 | m_io = &space(AS_IO); |
| 175 | 254 | |
| 176 | | /* wipe out the h6280 structure */ |
| 177 | | save_irqcallback = cpustate->irq_callback; |
| 178 | | memset(cpustate, 0, sizeof(h6280_Regs)); |
| 179 | | cpustate->irq_callback = save_irqcallback; |
| 180 | | cpustate->device = device; |
| 181 | | cpustate->program = &device->space(AS_PROGRAM); |
| 182 | | cpustate->direct = &cpustate->program->direct(); |
| 183 | | cpustate->io = &device->space(AS_IO); |
| 184 | | |
| 185 | 255 | /* set I and B flags */ |
| 186 | 256 | P = _fI | _fB; |
| 187 | 257 | |
| 188 | 258 | /* stack starts at 0x01ff */ |
| 189 | | cpustate->sp.d = 0x1ff; |
| 259 | m_sp.d = 0x1ff; |
| 190 | 260 | |
| 191 | 261 | /* read the reset vector into PC */ |
| 192 | | PCL = RDMEM(cpustate, H6280_RESET_VEC); |
| 193 | | PCH = RDMEM(cpustate, (H6280_RESET_VEC+1)); |
| 262 | PCL = program_read8(H6280_RESET_VEC); |
| 263 | PCH = program_read8(H6280_RESET_VEC + 1); |
| 194 | 264 | |
| 195 | 265 | /* CPU starts in low speed mode */ |
| 196 | | cpustate->clocks_per_cycle = 4; |
| 266 | m_clocks_per_cycle = 4; |
| 197 | 267 | |
| 198 | 268 | /* timer off by default */ |
| 199 | | cpustate->timer_status=0; |
| 200 | | cpustate->timer_load = 128 * 1024; |
| 269 | m_timer_status = 0; |
| 270 | m_timer_load = 128 * 1024; |
| 201 | 271 | |
| 202 | 272 | /* clear pending interrupts */ |
| 203 | | for (i = 0; i < 3; i++) |
| 204 | | cpustate->irq_state[i] = CLEAR_LINE; |
| 205 | | cpustate->nmi_state = CLEAR_LINE; |
| 273 | for (int i = 0; i < 3; i++) |
| 274 | { |
| 275 | m_irq_state[i] = CLEAR_LINE; |
| 276 | } |
| 277 | m_nmi_state = CLEAR_LINE; |
| 206 | 278 | |
| 207 | | cpustate->irq_pending = 0; |
| 279 | m_irq_pending = 0; |
| 208 | 280 | } |
| 209 | 281 | |
| 210 | | static CPU_EXIT( h6280 ) |
| 282 | void h6280_device::device_stop() |
| 211 | 283 | { |
| 212 | 284 | /* nothing */ |
| 213 | 285 | } |
| 214 | 286 | |
| 215 | | static CPU_EXECUTE( h6280 ) |
| 287 | |
| 288 | //------------------------------------------------- |
| 289 | // memory_space_config - return the configuration |
| 290 | // of the specified address space, or NULL if |
| 291 | // the space doesn't exist |
| 292 | //------------------------------------------------- |
| 293 | |
| 294 | const address_space_config *h6280_device::memory_space_config(address_spacenum spacenum) const |
| 216 | 295 | { |
| 296 | if (spacenum == AS_PROGRAM) |
| 297 | { |
| 298 | return &m_program_config; |
| 299 | } |
| 300 | else if (spacenum == AS_IO) |
| 301 | { |
| 302 | return &m_io_config; |
| 303 | } |
| 304 | return NULL; |
| 305 | } |
| 306 | |
| 307 | |
| 308 | //------------------------------------------------- |
| 309 | // state_string_export - export state as a string |
| 310 | // for the debugger |
| 311 | //------------------------------------------------- |
| 312 | |
| 313 | void h6280_device::state_string_export(const device_state_entry &entry, astring &string) |
| 314 | { |
| 315 | switch (entry.index()) |
| 316 | { |
| 317 | case STATE_GENFLAGS: |
| 318 | string.printf("%c%c%c%c%c%c%c%c", |
| 319 | (m_p & 0x80) ? 'N':'.', |
| 320 | (m_p & 0x40) ? 'V':'.', |
| 321 | (m_p & 0x20) ? 'R':'.', |
| 322 | (m_p & 0x10) ? 'B':'.', |
| 323 | (m_p & 0x08) ? 'D':'.', |
| 324 | (m_p & 0x04) ? 'I':'.', |
| 325 | (m_p & 0x02) ? 'Z':'.', |
| 326 | (m_p & 0x01) ? 'C':'.'); |
| 327 | break; |
| 328 | } |
| 329 | } |
| 330 | |
| 331 | |
| 332 | //------------------------------------------------- |
| 333 | // disasm_min_opcode_bytes - return the length |
| 334 | // of the shortest instruction, in bytes |
| 335 | //------------------------------------------------- |
| 336 | |
| 337 | UINT32 h6280_device::disasm_min_opcode_bytes() const |
| 338 | { |
| 339 | return 1; |
| 340 | } |
| 341 | |
| 342 | |
| 343 | //------------------------------------------------- |
| 344 | // disasm_max_opcode_bytes - return the length |
| 345 | // of the longest instruction, in bytes |
| 346 | //------------------------------------------------- |
| 347 | |
| 348 | UINT32 h6280_device::disasm_max_opcode_bytes() const |
| 349 | { |
| 350 | return 7; |
| 351 | } |
| 352 | |
| 353 | |
| 354 | //------------------------------------------------- |
| 355 | // disasm_disassemble - call the disassembly |
| 356 | // helper function |
| 357 | //------------------------------------------------- |
| 358 | |
| 359 | offs_t h6280_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
| 360 | { |
| 361 | extern CPU_DISASSEMBLE( h6280 ); |
| 362 | return disassemble(buffer, pc, oprom, opram, 0); |
| 363 | } |
| 364 | |
| 365 | |
| 366 | //------------------------------------------------- |
| 367 | // execute_min_cycles - return minimum number of |
| 368 | // cycles it takes for one instruction to execute |
| 369 | //------------------------------------------------- |
| 370 | |
| 371 | UINT32 h6280_device::execute_min_cycles() const |
| 372 | { |
| 373 | return 2; |
| 374 | } |
| 375 | |
| 376 | |
| 377 | //------------------------------------------------- |
| 378 | // execute_max_cycles - return maximum number of |
| 379 | // cycles it takes for one instruction to execute |
| 380 | //------------------------------------------------- |
| 381 | |
| 382 | UINT32 h6280_device::execute_max_cycles() const |
| 383 | { |
| 384 | return 17 + 6*65536; |
| 385 | } |
| 386 | |
| 387 | |
| 388 | //------------------------------------------------- |
| 389 | // execute_input_lines - return the number of |
| 390 | // input/interrupt lines |
| 391 | //------------------------------------------------- |
| 392 | |
| 393 | UINT32 h6280_device::execute_input_lines() const |
| 394 | { |
| 395 | return 4; |
| 396 | } |
| 397 | |
| 398 | |
| 399 | //------------------------------------------------- |
| 400 | // execute_set_input - act on a changed input/ |
| 401 | // interrupt line |
| 402 | //------------------------------------------------- |
| 403 | |
| 404 | void h6280_device::execute_set_input(int inputnum, int state) |
| 405 | { |
| 406 | switch(inputnum) |
| 407 | { |
| 408 | case H6280_IRQ1_STATE: |
| 409 | case 0: |
| 410 | set_irq_line(0, state); |
| 411 | break; |
| 412 | case H6280_IRQ2_STATE: |
| 413 | case 1: |
| 414 | set_irq_line(1, state); |
| 415 | break; |
| 416 | case H6280_IRQT_STATE: |
| 417 | case 2: |
| 418 | set_irq_line(2, state); |
| 419 | break; |
| 420 | case H6280_NMI_STATE: |
| 421 | case INPUT_LINE_NMI: |
| 422 | set_irq_line(INPUT_LINE_NMI, state); |
| 423 | break; |
| 424 | } |
| 425 | } |
| 426 | |
| 427 | /*************************************************************** |
| 428 | * program_read8 read memory |
| 429 | ***************************************************************/ |
| 430 | UINT8 h6280_device::program_read8(offs_t addr) |
| 431 | { |
| 432 | CHECK_VDC_VCE_PENALTY(addr); |
| 433 | return m_program->read_byte(TRANSLATED(addr)); |
| 434 | } |
| 435 | |
| 436 | /*************************************************************** |
| 437 | * program_write8 write memory |
| 438 | ***************************************************************/ |
| 439 | void h6280_device::program_write8(offs_t addr, UINT8 data) |
| 440 | { |
| 441 | CHECK_VDC_VCE_PENALTY(addr); |
| 442 | m_program->write_byte(TRANSLATED(addr), data); |
| 443 | } |
| 444 | |
| 445 | /*************************************************************** |
| 446 | * program_read8z read memory - zero page |
| 447 | ***************************************************************/ |
| 448 | UINT8 h6280_device::program_read8z(offs_t addr) |
| 449 | { |
| 450 | return m_program->read_byte((m_mmr[1] << 13) | (addr & 0x1fff)); |
| 451 | } |
| 452 | |
| 453 | /*************************************************************** |
| 454 | * program_write8z write memory - zero page |
| 455 | ***************************************************************/ |
| 456 | void h6280_device::program_write8z(offs_t addr, UINT8 data) |
| 457 | { |
| 458 | m_program->write_byte((m_mmr[1] << 13) | (addr & 0x1fff), data); |
| 459 | } |
| 460 | |
| 461 | /*************************************************************** |
| 462 | * program_read16 read word from memory |
| 463 | ***************************************************************/ |
| 464 | UINT16 h6280_device::program_read16(offs_t addr) |
| 465 | { |
| 466 | return m_program->read_byte(TRANSLATED(addr)); |
| 467 | (m_program->read_byte(TRANSLATED(addr + 1)) << 8); |
| 468 | } |
| 469 | |
| 470 | /*************************************************************** |
| 471 | * program_read16z read a word from a zero page address |
| 472 | ***************************************************************/ |
| 473 | UINT16 h6280_device::program_read16z(offs_t addr) |
| 474 | { |
| 475 | if ((addr & 0xff) == 0xff) |
| 476 | { |
| 477 | return m_program->read_byte((m_mmr[1] << 13) | (addr & 0x1fff)) | |
| 478 | (m_program->read_byte((m_mmr[1] << 13) | ((addr - 0xff) & 0x1fff)) << 8); |
| 479 | } |
| 480 | else |
| 481 | { |
| 482 | return m_program->read_byte((m_mmr[1] << 13) | (addr & 0x1fff)) | |
| 483 | (m_program->read_byte((m_mmr[1] << 13) | ((addr + 1) & 0x1fff)) << 8); |
| 484 | } |
| 485 | } |
| 486 | |
| 487 | /*************************************************************** |
| 488 | * push a register onto the stack |
| 489 | ***************************************************************/ |
| 490 | void h6280_device::push(UINT8 value) |
| 491 | { |
| 492 | m_program->write_byte((m_mmr[1] << 13) | m_sp.d, value); |
| 493 | S--; |
| 494 | } |
| 495 | |
| 496 | /*************************************************************** |
| 497 | * pull a register from the stack |
| 498 | ***************************************************************/ |
| 499 | void h6280_device::pull(UINT8 &value) |
| 500 | { |
| 501 | S++; |
| 502 | value = m_program->read_byte((m_mmr[1] << 13) | m_sp.d); |
| 503 | } |
| 504 | |
| 505 | /*************************************************************** |
| 506 | * read_opcode read an opcode |
| 507 | ***************************************************************/ |
| 508 | UINT8 h6280_device::read_opcode() |
| 509 | { |
| 510 | return m_direct->read_decrypted_byte(TRANSLATED(PCW)); |
| 511 | } |
| 512 | |
| 513 | /*************************************************************** |
| 514 | * read_opcode_arg read an opcode argument |
| 515 | ***************************************************************/ |
| 516 | UINT8 h6280_device::read_opcode_arg() |
| 517 | { |
| 518 | return m_direct->read_raw_byte(TRANSLATED(PCW)); |
| 519 | } |
| 520 | |
| 521 | |
| 522 | //------------------------------------------------- |
| 523 | // execute_run - execute a timeslice's worth of |
| 524 | // opcodes |
| 525 | //------------------------------------------------- |
| 526 | |
| 527 | void h6280_device::execute_run() |
| 528 | { |
| 217 | 529 | int in; |
| 218 | | h6280_Regs* cpustate = get_safe_token(device); |
| 219 | 530 | |
| 220 | | if ( cpustate->irq_pending == 2 ) { |
| 221 | | cpustate->irq_pending--; |
| 531 | if (m_irq_pending == 2) |
| 532 | { |
| 533 | m_irq_pending--; |
| 222 | 534 | } |
| 223 | 535 | |
| 224 | 536 | /* Execute instructions */ |
| 225 | 537 | do |
| 226 | 538 | { |
| 227 | | cpustate->ppc = cpustate->pc; |
| 539 | m_ppc = m_pc; |
| 228 | 540 | |
| 229 | | debugger_instruction_hook(device, PCW); |
| 541 | debugger_instruction_hook(this, PCW); |
| 230 | 542 | |
| 231 | 543 | /* Execute 1 instruction */ |
| 232 | | in=RDOP(); |
| 544 | in = read_opcode(); |
| 233 | 545 | PCW++; |
| 234 | | insnh6280[in](cpustate); |
| 546 | (this->*m_opcode[in])(); |
| 235 | 547 | |
| 236 | | if ( cpustate->irq_pending ) { |
| 237 | | if ( cpustate->irq_pending == 1 ) { |
| 238 | | if ( !(P & _fI) ) { |
| 239 | | cpustate->irq_pending--; |
| 548 | if (m_irq_pending) |
| 549 | { |
| 550 | if (m_irq_pending == 1) |
| 551 | { |
| 552 | if (!(P & _fI)) |
| 553 | { |
| 554 | m_irq_pending--; |
| 240 | 555 | CHECK_AND_TAKE_IRQ_LINES; |
| 241 | 556 | } |
| 242 | | } else { |
| 243 | | cpustate->irq_pending--; |
| 244 | 557 | } |
| 558 | else |
| 559 | { |
| 560 | m_irq_pending--; |
| 561 | } |
| 245 | 562 | } |
| 246 | 563 | |
| 247 | 564 | /* Check internal timer */ |
| 248 | | if(cpustate->timer_status) |
| 565 | if (m_timer_status) |
| 249 | 566 | { |
| 250 | | if(cpustate->timer_value<=0) |
| 567 | if (m_timer_value<=0) |
| 251 | 568 | { |
| 252 | | if ( ! cpustate->irq_pending ) |
| 253 | | cpustate->irq_pending = 1; |
| 254 | | while( cpustate->timer_value <= 0 ) |
| 255 | | cpustate->timer_value += cpustate->timer_load; |
| 256 | | set_irq_line(cpustate, 2,ASSERT_LINE); |
| 569 | if (!m_irq_pending) |
| 570 | { |
| 571 | m_irq_pending = 1; |
| 572 | } |
| 573 | while (m_timer_value <= 0) |
| 574 | { |
| 575 | m_timer_value += m_timer_load; |
| 576 | } |
| 577 | set_irq_line(2, ASSERT_LINE); |
| 257 | 578 | } |
| 258 | 579 | } |
| 259 | | } while (cpustate->ICount > 0); |
| 580 | } while (m_icount > 0); |
| 260 | 581 | } |
| 261 | 582 | |
| 262 | | /*****************************************************************************/ |
| 263 | 583 | |
| 264 | | static void set_irq_line(h6280_Regs* cpustate, int irqline, int state) |
| 584 | //************************************************************************** |
| 585 | // IRQ HANDLING |
| 586 | //************************************************************************** |
| 587 | |
| 588 | void h6280_device::set_irq_line(int irqline, int state) |
| 265 | 589 | { |
| 266 | 590 | if (irqline == INPUT_LINE_NMI) |
| 267 | 591 | { |
| 268 | | if ( state != ASSERT_LINE ) return; |
| 269 | | cpustate->nmi_state = state; |
| 592 | if (state != ASSERT_LINE) |
| 593 | return; |
| 594 | m_nmi_state = state; |
| 270 | 595 | CHECK_IRQ_LINES; |
| 271 | 596 | } |
| 272 | 597 | else if (irqline < 3) |
| 273 | 598 | { |
| 274 | 599 | /* If the state has not changed, just return */ |
| 275 | | if ( cpustate->irq_state[irqline] == state ) |
| 600 | if (m_irq_state[irqline] == state) |
| 276 | 601 | return; |
| 277 | 602 | |
| 278 | | cpustate->irq_state[irqline] = state; |
| 603 | m_irq_state[irqline] = state; |
| 279 | 604 | |
| 280 | 605 | CHECK_IRQ_LINES; |
| 281 | 606 | } |
| 282 | 607 | } |
| 283 | 608 | |
| 284 | 609 | |
| 610 | //************************************************************************** |
| 611 | // REGISTER HANDLING |
| 612 | //************************************************************************** |
| 285 | 613 | |
| 286 | | /*****************************************************************************/ |
| 287 | | |
| 288 | | READ8_HANDLER( h6280_irq_status_r ) |
| 614 | READ8_MEMBER( h6280_device::irq_status_r ) |
| 289 | 615 | { |
| 290 | 616 | int status; |
| 291 | | h6280_Regs *cpustate = get_safe_token(&space.device()); |
| 292 | 617 | |
| 293 | | switch (offset&3) |
| 618 | switch (offset & 3) |
| 294 | 619 | { |
| 295 | | default: return cpustate->io_buffer; |
| 620 | default: |
| 621 | return m_io_buffer; |
| 296 | 622 | case 3: |
| 297 | 623 | { |
| 298 | | status=0; |
| 299 | | if(cpustate->irq_state[1]!=CLEAR_LINE) status|=1; /* IRQ 2 */ |
| 300 | | if(cpustate->irq_state[0]!=CLEAR_LINE) status|=2; /* IRQ 1 */ |
| 301 | | if(cpustate->irq_state[2]!=CLEAR_LINE) status|=4; /* TIMER */ |
| 302 | | return status|(cpustate->io_buffer&(~H6280_IRQ_MASK)); |
| 624 | status = 0; |
| 625 | if (m_irq_state[1] != CLEAR_LINE) |
| 626 | status |= 1; /* IRQ 2 */ |
| 627 | if (m_irq_state[0] != CLEAR_LINE) |
| 628 | status |= 2; /* IRQ 1 */ |
| 629 | if (m_irq_state[2] != CLEAR_LINE) |
| 630 | status |= 4; /* TIMER */ |
| 631 | return status | (m_io_buffer & (~H6280_IRQ_MASK)); |
| 303 | 632 | } |
| 304 | | case 2: return cpustate->irq_mask|(cpustate->io_buffer&(~H6280_IRQ_MASK)); |
| 633 | case 2: |
| 634 | return m_irq_mask | (m_io_buffer & (~H6280_IRQ_MASK)); |
| 305 | 635 | } |
| 306 | 636 | } |
| 307 | 637 | |
| 308 | | WRITE8_HANDLER( h6280_irq_status_w ) |
| 638 | WRITE8_MEMBER( h6280_device::irq_status_w ) |
| 309 | 639 | { |
| 310 | | h6280_Regs *cpustate = get_safe_token(&space.device()); |
| 311 | | cpustate->io_buffer=data; |
| 312 | | switch (offset&3) |
| 640 | m_io_buffer = data; |
| 641 | switch (offset & 3) |
| 313 | 642 | { |
| 314 | | default:cpustate->io_buffer=data;break; |
| 643 | default: |
| 644 | m_io_buffer = data; |
| 645 | break; |
| 646 | |
| 315 | 647 | case 2: /* Write irq mask */ |
| 316 | | cpustate->irq_mask=data&0x7; |
| 648 | m_irq_mask = data & 0x7; |
| 317 | 649 | CHECK_IRQ_LINES; |
| 318 | 650 | break; |
| 319 | 651 | |
| 320 | 652 | case 3: /* Timer irq ack */ |
| 321 | | set_irq_line(cpustate, 2, CLEAR_LINE); |
| 653 | set_irq_line(2, CLEAR_LINE); |
| 322 | 654 | break; |
| 323 | 655 | } |
| 324 | 656 | } |
| 325 | 657 | |
| 326 | | READ8_HANDLER( h6280_timer_r ) |
| 658 | READ8_MEMBER( h6280_device::timer_r ) |
| 327 | 659 | { |
| 328 | 660 | /* only returns countdown */ |
| 329 | | h6280_Regs *cpustate = get_safe_token(&space.device()); |
| 330 | | return ((cpustate->timer_value >> 10)&0x7F)|(cpustate->io_buffer&0x80); |
| 661 | return ((m_timer_value >> 10) & 0x7F) | (m_io_buffer & 0x80); |
| 331 | 662 | } |
| 332 | 663 | |
| 333 | | WRITE8_HANDLER( h6280_timer_w ) |
| 664 | WRITE8_MEMBER( h6280_device::timer_w ) |
| 334 | 665 | { |
| 335 | | h6280_Regs *cpustate = get_safe_token(&space.device()); |
| 336 | | cpustate->io_buffer=data; |
| 337 | | switch (offset & 1) { |
| 666 | m_io_buffer = data; |
| 667 | switch (offset & 1) |
| 668 | { |
| 338 | 669 | case 0: /* Counter preload */ |
| 339 | | cpustate->timer_load=cpustate->timer_value=((data&127)+1)*1024; |
| 670 | m_timer_load = m_timer_value = ((data & 127) + 1) * 1024; |
| 340 | 671 | return; |
| 341 | 672 | |
| 342 | 673 | case 1: /* Counter enable */ |
| 343 | | if(data&1) |
| 674 | if (data & 1) |
| 344 | 675 | { /* stop -> start causes reload */ |
| 345 | | if(cpustate->timer_status==0) cpustate->timer_value=cpustate->timer_load; |
| 676 | if(m_timer_status == 0) |
| 677 | m_timer_value = m_timer_load; |
| 346 | 678 | } |
| 347 | | cpustate->timer_status=data&1; |
| 679 | m_timer_status = data & 1; |
| 348 | 680 | return; |
| 349 | 681 | } |
| 350 | 682 | } |
| 351 | 683 | |
| 352 | | static CPU_TRANSLATE( h6280 ) |
| 684 | bool h6280_device::memory_translate(address_spacenum spacenum, int intention, offs_t &address) |
| 353 | 685 | { |
| 354 | | h6280_Regs* cpustate = get_safe_token(device); |
| 686 | if (spacenum == AS_PROGRAM) |
| 687 | address = TRANSLATED(address); |
| 355 | 688 | |
| 356 | | if (space == AS_PROGRAM) |
| 357 | | *address = TRANSLATED(*address); |
| 358 | | |
| 359 | 689 | return TRUE; |
| 360 | 690 | } |
| 361 | 691 | |
| 362 | | UINT8 h6280io_get_buffer(device_t *device) |
| 692 | UINT8 h6280_device::io_get_buffer() |
| 363 | 693 | { |
| 364 | | h6280_Regs* cpustate = get_safe_token(device); |
| 365 | | return cpustate->io_buffer; |
| 694 | return m_io_buffer; |
| 366 | 695 | } |
| 367 | | void h6280io_set_buffer(device_t *device, UINT8 data) |
| 368 | | { |
| 369 | | h6280_Regs* cpustate = get_safe_token(device); |
| 370 | | cpustate->io_buffer=data; |
| 371 | | } |
| 372 | 696 | |
| 373 | | |
| 374 | | /*****************************************************************************/ |
| 375 | | |
| 376 | | /************************************************************************** |
| 377 | | * Generic set_info |
| 378 | | **************************************************************************/ |
| 379 | | |
| 380 | | static CPU_SET_INFO( h6280 ) |
| 697 | void h6280_device::io_set_buffer(UINT8 data) |
| 381 | 698 | { |
| 382 | | h6280_Regs* cpustate = get_safe_token(device); |
| 383 | | |
| 384 | | switch (state) |
| 385 | | { |
| 386 | | /* --- the following bits of info are set as 64-bit signed integers --- */ |
| 387 | | case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(cpustate, 0, info->i); break; |
| 388 | | case CPUINFO_INT_INPUT_STATE + 1: set_irq_line(cpustate, 1, info->i); break; |
| 389 | | case CPUINFO_INT_INPUT_STATE + 2: set_irq_line(cpustate, 2, info->i); break; |
| 390 | | case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: set_irq_line(cpustate, INPUT_LINE_NMI, info->i); break; |
| 391 | | |
| 392 | | case CPUINFO_INT_PC: |
| 393 | | case CPUINFO_INT_REGISTER + H6280_PC: PCW = info->i; break; |
| 394 | | case CPUINFO_INT_SP: |
| 395 | | case CPUINFO_INT_REGISTER + H6280_S: S = info->i; break; |
| 396 | | case CPUINFO_INT_REGISTER + H6280_P: P = info->i; break; |
| 397 | | case CPUINFO_INT_REGISTER + H6280_A: A = info->i; break; |
| 398 | | case CPUINFO_INT_REGISTER + H6280_X: X = info->i; break; |
| 399 | | case CPUINFO_INT_REGISTER + H6280_Y: Y = info->i; break; |
| 400 | | case CPUINFO_INT_REGISTER + H6280_IRQ_MASK: cpustate->irq_mask = info->i; CHECK_IRQ_LINES; break; |
| 401 | | case CPUINFO_INT_REGISTER + H6280_TIMER_STATE: cpustate->timer_status = info->i; break; |
| 402 | | case CPUINFO_INT_REGISTER + H6280_NMI_STATE: set_irq_line( cpustate, INPUT_LINE_NMI, info->i ); break; |
| 403 | | case CPUINFO_INT_REGISTER + H6280_IRQ1_STATE: set_irq_line( cpustate, 0, info->i ); break; |
| 404 | | case CPUINFO_INT_REGISTER + H6280_IRQ2_STATE: set_irq_line( cpustate, 1, info->i ); break; |
| 405 | | case CPUINFO_INT_REGISTER + H6280_IRQT_STATE: set_irq_line( cpustate, 2, info->i ); break; |
| 406 | | case CPUINFO_INT_REGISTER + H6280_M1: cpustate->mmr[0] = info->i; break; |
| 407 | | case CPUINFO_INT_REGISTER + H6280_M2: cpustate->mmr[1] = info->i; break; |
| 408 | | case CPUINFO_INT_REGISTER + H6280_M3: cpustate->mmr[2] = info->i; break; |
| 409 | | case CPUINFO_INT_REGISTER + H6280_M4: cpustate->mmr[3] = info->i; break; |
| 410 | | case CPUINFO_INT_REGISTER + H6280_M5: cpustate->mmr[4] = info->i; break; |
| 411 | | case CPUINFO_INT_REGISTER + H6280_M6: cpustate->mmr[5] = info->i; break; |
| 412 | | case CPUINFO_INT_REGISTER + H6280_M7: cpustate->mmr[6] = info->i; break; |
| 413 | | case CPUINFO_INT_REGISTER + H6280_M8: cpustate->mmr[7] = info->i; break; |
| 414 | | } |
| 699 | m_io_buffer = data; |
| 415 | 700 | } |
| 416 | | |
| 417 | | |
| 418 | | |
| 419 | | /************************************************************************** |
| 420 | | * Generic get_info |
| 421 | | **************************************************************************/ |
| 422 | | |
| 423 | | CPU_GET_INFO( h6280 ) |
| 424 | | { |
| 425 | | h6280_Regs* cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; |
| 426 | | |
| 427 | | switch (state) |
| 428 | | { |
| 429 | | /* --- the following bits of info are returned as 64-bit signed integers --- */ |
| 430 | | case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(h6280_Regs); break; |
| 431 | | case CPUINFO_INT_INPUT_LINES: info->i = 3; break; |
| 432 | | case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; |
| 433 | | case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break; |
| 434 | | case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; |
| 435 | | case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; |
| 436 | | case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break; |
| 437 | | case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 7; break; |
| 438 | | case CPUINFO_INT_MIN_CYCLES: info->i = 2; break; |
| 439 | | case CPUINFO_INT_MAX_CYCLES: info->i = 17 + 6*65536; break; |
| 440 | | |
| 441 | | case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break; |
| 442 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 21; break; |
| 443 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break; |
| 444 | | case CPUINFO_INT_LOGADDR_WIDTH_PROGRAM: info->i = 16; break; |
| 445 | | case CPUINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break; |
| 446 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break; |
| 447 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; |
| 448 | | case CPUINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 8; break; |
| 449 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 2; break; |
| 450 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; |
| 451 | | |
| 452 | | case CPUINFO_INT_INPUT_STATE + 0: info->i = cpustate->irq_state[0]; break; |
| 453 | | case CPUINFO_INT_INPUT_STATE + 1: info->i = cpustate->irq_state[1]; break; |
| 454 | | case CPUINFO_INT_INPUT_STATE + 2: info->i = cpustate->irq_state[2]; break; |
| 455 | | case CPUINFO_INT_INPUT_STATE + INPUT_LINE_NMI: info->i = cpustate->nmi_state; break; |
| 456 | | |
| 457 | | case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->ppc.d; break; |
| 458 | | |
| 459 | | case CPUINFO_INT_PC: |
| 460 | | case CPUINFO_INT_REGISTER + H6280_PC: info->i = PCD; break; |
| 461 | | case CPUINFO_INT_SP: |
| 462 | | case CPUINFO_INT_REGISTER + H6280_S: info->i = S; break; |
| 463 | | case CPUINFO_INT_REGISTER + H6280_P: info->i = P; break; |
| 464 | | case CPUINFO_INT_REGISTER + H6280_A: info->i = A; break; |
| 465 | | case CPUINFO_INT_REGISTER + H6280_X: info->i = X; break; |
| 466 | | case CPUINFO_INT_REGISTER + H6280_Y: info->i = Y; break; |
| 467 | | case CPUINFO_INT_REGISTER + H6280_IRQ_MASK: info->i = cpustate->irq_mask; break; |
| 468 | | case CPUINFO_INT_REGISTER + H6280_TIMER_STATE: info->i = cpustate->timer_status; break; |
| 469 | | case CPUINFO_INT_REGISTER + H6280_NMI_STATE: info->i = cpustate->nmi_state; break; |
| 470 | | case CPUINFO_INT_REGISTER + H6280_IRQ1_STATE: info->i = cpustate->irq_state[0]; break; |
| 471 | | case CPUINFO_INT_REGISTER + H6280_IRQ2_STATE: info->i = cpustate->irq_state[1]; break; |
| 472 | | case CPUINFO_INT_REGISTER + H6280_IRQT_STATE: info->i = cpustate->irq_state[2]; break; |
| 473 | | case CPUINFO_INT_REGISTER + H6280_M1: info->i = cpustate->mmr[0]; break; |
| 474 | | case CPUINFO_INT_REGISTER + H6280_M2: info->i = cpustate->mmr[1]; break; |
| 475 | | case CPUINFO_INT_REGISTER + H6280_M3: info->i = cpustate->mmr[2]; break; |
| 476 | | case CPUINFO_INT_REGISTER + H6280_M4: info->i = cpustate->mmr[3]; break; |
| 477 | | case CPUINFO_INT_REGISTER + H6280_M5: info->i = cpustate->mmr[4]; break; |
| 478 | | case CPUINFO_INT_REGISTER + H6280_M6: info->i = cpustate->mmr[5]; break; |
| 479 | | case CPUINFO_INT_REGISTER + H6280_M7: info->i = cpustate->mmr[6]; break; |
| 480 | | case CPUINFO_INT_REGISTER + H6280_M8: info->i = cpustate->mmr[7]; break; |
| 481 | | |
| 482 | | /* --- the following bits of info are returned as pointers to data or functions --- */ |
| 483 | | case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(h6280); break; |
| 484 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(h6280); break; |
| 485 | | case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(h6280); break; |
| 486 | | case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(h6280); break; |
| 487 | | case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(h6280); break; |
| 488 | | case CPUINFO_FCT_BURN: info->burn = NULL; break; |
| 489 | | case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(h6280);break; |
| 490 | | case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->ICount; break; |
| 491 | | case CPUINFO_FCT_TRANSLATE: info->translate = CPU_TRANSLATE_NAME(h6280); break; |
| 492 | | |
| 493 | | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 494 | | case CPUINFO_STR_NAME: strcpy(info->s, "HuC6280"); break; |
| 495 | | case CPUINFO_STR_FAMILY: strcpy(info->s, "Hudsonsoft 6280"); break; |
| 496 | | case CPUINFO_STR_VERSION: strcpy(info->s, "1.11"); break; |
| 497 | | case CPUINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; |
| 498 | | case CPUINFO_STR_CREDITS: strcpy(info->s, "Copyright Bryan McPhail, mish@tendril.co.uk"); break; |
| 499 | | |
| 500 | | case CPUINFO_STR_FLAGS: |
| 501 | | sprintf(info->s, "%c%c%c%c%c%c%c%c", |
| 502 | | cpustate->p & 0x80 ? 'N':'.', |
| 503 | | cpustate->p & 0x40 ? 'V':'.', |
| 504 | | cpustate->p & 0x20 ? 'R':'.', |
| 505 | | cpustate->p & 0x10 ? 'B':'.', |
| 506 | | cpustate->p & 0x08 ? 'D':'.', |
| 507 | | cpustate->p & 0x04 ? 'I':'.', |
| 508 | | cpustate->p & 0x02 ? 'Z':'.', |
| 509 | | cpustate->p & 0x01 ? 'C':'.'); |
| 510 | | break; |
| 511 | | |
| 512 | | case CPUINFO_STR_REGISTER + H6280_PC: sprintf(info->s, "PC:%04X", cpustate->pc.d); break; |
| 513 | | case CPUINFO_STR_REGISTER + H6280_S: sprintf(info->s, "S:%02X", cpustate->sp.b.l); break; |
| 514 | | case CPUINFO_STR_REGISTER + H6280_P: sprintf(info->s, "P:%02X", cpustate->p); break; |
| 515 | | case CPUINFO_STR_REGISTER + H6280_A: sprintf(info->s, "A:%02X", cpustate->a); break; |
| 516 | | case CPUINFO_STR_REGISTER + H6280_X: sprintf(info->s, "X:%02X", cpustate->x); break; |
| 517 | | case CPUINFO_STR_REGISTER + H6280_Y: sprintf(info->s, "Y:%02X", cpustate->y); break; |
| 518 | | case CPUINFO_STR_REGISTER + H6280_IRQ_MASK: sprintf(info->s, "IM:%02X", cpustate->irq_mask);break; |
| 519 | | case CPUINFO_STR_REGISTER + H6280_TIMER_STATE: sprintf(info->s, "TMR:%02X", cpustate->timer_status); break; |
| 520 | | case CPUINFO_STR_REGISTER + H6280_NMI_STATE: sprintf(info->s, "NMI:%X", cpustate->nmi_state); break; |
| 521 | | case CPUINFO_STR_REGISTER + H6280_IRQ1_STATE: sprintf(info->s, "IRQ1:%X", cpustate->irq_state[0]); break; |
| 522 | | case CPUINFO_STR_REGISTER + H6280_IRQ2_STATE: sprintf(info->s, "IRQ2:%X", cpustate->irq_state[1]); break; |
| 523 | | case CPUINFO_STR_REGISTER + H6280_IRQT_STATE: sprintf(info->s, "IRQT:%X", cpustate->irq_state[2]); break; |
| 524 | | case CPUINFO_STR_REGISTER + H6280_M1: sprintf(info->s, "M1:%02X", cpustate->mmr[0]); break; |
| 525 | | case CPUINFO_STR_REGISTER + H6280_M2: sprintf(info->s, "M2:%02X", cpustate->mmr[1]); break; |
| 526 | | case CPUINFO_STR_REGISTER + H6280_M3: sprintf(info->s, "M3:%02X", cpustate->mmr[2]); break; |
| 527 | | case CPUINFO_STR_REGISTER + H6280_M4: sprintf(info->s, "M4:%02X", cpustate->mmr[3]); break; |
| 528 | | case CPUINFO_STR_REGISTER + H6280_M5: sprintf(info->s, "M5:%02X", cpustate->mmr[4]); break; |
| 529 | | case CPUINFO_STR_REGISTER + H6280_M6: sprintf(info->s, "M6:%02X", cpustate->mmr[5]); break; |
| 530 | | case CPUINFO_STR_REGISTER + H6280_M7: sprintf(info->s, "M7:%02X", cpustate->mmr[6]); break; |
| 531 | | case CPUINFO_STR_REGISTER + H6280_M8: sprintf(info->s, "M8:%02X", cpustate->mmr[7]); break; |
| 532 | | } |
| 533 | | } |
| 534 | | |
| 535 | | DEFINE_LEGACY_CPU_DEVICE(H6280, h6280); |
trunk/src/emu/cpu/h6280/tblh6280.c
| r19741 | r19742 | |
| 11 | 11 | ******************************************************************************/ |
| 12 | 12 | |
| 13 | 13 | #undef OP |
| 14 | | #define OP(nnn) INLINE void h6280##nnn(h6280_Regs* cpustate) |
| 14 | #define OP(nnn) inline void op##nnn() |
| 15 | 15 | |
| 16 | 16 | /***************************************************************************** |
| 17 | 17 | ***************************************************************************** |
| r19741 | r19742 | |
| 93 | 93 | OP(_0f3) { int to,from,length,alternate; TAI; } // 6*l+17 TAI XFER |
| 94 | 94 | |
| 95 | 95 | OP(_004) { int tmp; H6280_CYCLES(6); RD_ZPG; TSB; WB_EAZ; } // 6 TSB ZPG |
| 96 | | OP(_024) { int tmp; H6280_CYCLES(4); RD_ZPG; BIT; } // 4 BIT ZPG |
| 96 | OP(_024) { int tmp; H6280_CYCLES(4); RD_ZPG; HBIT; } // 4 BIT ZPG |
| 97 | 97 | OP(_044) { int tmp; BSR; } // 8 BSR REL |
| 98 | 98 | OP(_064) { int tmp; H6280_CYCLES(4); STZ; WR_ZPG; } // 4 STZ ZPG |
| 99 | 99 | OP(_084) { int tmp; H6280_CYCLES(4); STY; WR_ZPG; } // 4 STY ZPG |
| r19741 | r19742 | |
| 102 | 102 | OP(_0e4) { int tmp; H6280_CYCLES(4); RD_ZPG; CPX; } // 4 CPX ZPG |
| 103 | 103 | |
| 104 | 104 | OP(_014) { int tmp; H6280_CYCLES(6); RD_ZPG; TRB; WB_EAZ; } // 6 TRB ZPG |
| 105 | | OP(_034) { int tmp; H6280_CYCLES(4); RD_ZPX; BIT; } // 4 BIT ZPX |
| 105 | OP(_034) { int tmp; H6280_CYCLES(4); RD_ZPX; HBIT; } // 4 BIT ZPX |
| 106 | 106 | OP(_054) { H6280_CYCLES(3); CSL; } // 3 CSL |
| 107 | 107 | OP(_074) { int tmp; H6280_CYCLES(4); STZ; WR_ZPX; } // 4 STZ ZPX |
| 108 | 108 | OP(_094) { int tmp; H6280_CYCLES(4); STY; WR_ZPX; } // 4 STY ZPX |
| r19741 | r19742 | |
| 137 | 137 | OP(_0c6) { int tmp; H6280_CYCLES(6); RD_ZPG; DEC; WB_EAZ; } // 6 DEC ZPG |
| 138 | 138 | OP(_0e6) { int tmp; H6280_CYCLES(6); RD_ZPG; INC; WB_EAZ; } // 6 INC ZPG |
| 139 | 139 | |
| 140 | | OP(_016) { int tmp; H6280_CYCLES(6); RD_ZPX; ASL; WB_EAZ } // 6 ASL ZPX |
| 141 | | OP(_036) { int tmp; H6280_CYCLES(6); RD_ZPX; ROL; WB_EAZ } // 6 ROL ZPX |
| 142 | | OP(_056) { int tmp; H6280_CYCLES(6); RD_ZPX; LSR; WB_EAZ } // 6 LSR ZPX |
| 143 | | OP(_076) { int tmp; H6280_CYCLES(6); RD_ZPX; ROR; WB_EAZ } // 6 ROR ZPX |
| 140 | OP(_016) { int tmp; H6280_CYCLES(6); RD_ZPX; ASL; WB_EAZ; } // 6 ASL ZPX |
| 141 | OP(_036) { int tmp; H6280_CYCLES(6); RD_ZPX; ROL; WB_EAZ; } // 6 ROL ZPX |
| 142 | OP(_056) { int tmp; H6280_CYCLES(6); RD_ZPX; LSR; WB_EAZ; } // 6 LSR ZPX |
| 143 | OP(_076) { int tmp; H6280_CYCLES(6); RD_ZPX; ROR; WB_EAZ; } // 6 ROR ZPX |
| 144 | 144 | OP(_096) { int tmp; H6280_CYCLES(4); STX; WR_ZPY; } // 4 STX ZPY |
| 145 | 145 | OP(_0b6) { int tmp; H6280_CYCLES(4); RD_ZPY; LDX; } // 4 LDX ZPY |
| 146 | 146 | OP(_0d6) { int tmp; H6280_CYCLES(6); RD_ZPX; DEC; WB_EAZ; } // 6 DEC ZPX |
| r19741 | r19742 | |
| 186 | 186 | OP(_029) { int tmp; H6280_CYCLES(2); RD_IMM; AND; } // 2 AND IMM |
| 187 | 187 | OP(_049) { int tmp; H6280_CYCLES(2); RD_IMM; EOR; } // 2 EOR IMM |
| 188 | 188 | OP(_069) { int tmp; H6280_CYCLES(2); RD_IMM; ADC; } // 2 ADC IMM |
| 189 | | OP(_089) { int tmp; H6280_CYCLES(2); RD_IMM; BIT; } // 2 BIT IMM |
| 189 | OP(_089) { int tmp; H6280_CYCLES(2); RD_IMM; HBIT; } // 2 BIT IMM |
| 190 | 190 | OP(_0a9) { int tmp; H6280_CYCLES(2); RD_IMM; LDA; } // 2 LDA IMM |
| 191 | 191 | OP(_0c9) { int tmp; H6280_CYCLES(2); RD_IMM; CMP; } // 2 CMP IMM |
| 192 | 192 | OP(_0e9) { int tmp; H6280_CYCLES(2); RD_IMM; SBC; } // 2 SBC IMM |
| r19741 | r19742 | |
| 237 | 237 | OP(_0fb) { H6280_CYCLES(2); NOP; } // 2 NOP |
| 238 | 238 | |
| 239 | 239 | OP(_00c) { int tmp; H6280_CYCLES(7); RD_ABS; TSB; WB_EA; } // 7 TSB ABS |
| 240 | | OP(_02c) { int tmp; H6280_CYCLES(5); RD_ABS; BIT; } // 5 BIT ABS |
| 240 | OP(_02c) { int tmp; H6280_CYCLES(5); RD_ABS; HBIT; } // 5 BIT ABS |
| 241 | 241 | OP(_04c) { H6280_CYCLES(4); EA_ABS; JMP; } // 4 JMP ABS |
| 242 | 242 | OP(_06c) { int tmp; H6280_CYCLES(7); EA_IND; JMP; } // 7 JMP IND |
| 243 | 243 | OP(_08c) { int tmp; H6280_CYCLES(5); STY; WR_ABS; } // 5 STY ABS |
| r19741 | r19742 | |
| 246 | 246 | OP(_0ec) { int tmp; H6280_CYCLES(5); RD_ABS; CPX; } // 5 CPX ABS |
| 247 | 247 | |
| 248 | 248 | OP(_01c) { int tmp; H6280_CYCLES(7); RD_ABS; TRB; WB_EA; } // 7 TRB ABS |
| 249 | | OP(_03c) { int tmp; H6280_CYCLES(5); RD_ABX; BIT; } // 5 BIT ABX |
| 249 | OP(_03c) { int tmp; H6280_CYCLES(5); RD_ABX; HBIT; } // 5 BIT ABX |
| 250 | 250 | OP(_05c) { H6280_CYCLES(2); NOP; } // 2 NOP |
| 251 | 251 | OP(_07c) { int tmp; H6280_CYCLES(7); EA_IAX; JMP; } // 7 JMP IAX |
| 252 | 252 | OP(_09c) { int tmp; H6280_CYCLES(5); STZ; WR_ABS; } // 5 STZ ABS |
| r19741 | r19742 | |
| 307 | 307 | OP(_0bf) { int tmp; H6280_CYCLES(4); RD_ZPG; BBS(3); } // 6/8 BBS3 ZPG,REL |
| 308 | 308 | OP(_0df) { int tmp; H6280_CYCLES(4); RD_ZPG; BBS(5); } // 6/8 BBS5 ZPG,REL |
| 309 | 309 | OP(_0ff) { int tmp; H6280_CYCLES(4); RD_ZPG; BBS(7); } // 6/8 BBS7 ZPG,REL |
| 310 | | |
| 311 | | static void (*const insnh6280[0x100])(h6280_Regs* cpustate) = { |
| 312 | | h6280_000,h6280_001,h6280_002,h6280_003,h6280_004,h6280_005,h6280_006,h6280_007, |
| 313 | | h6280_008,h6280_009,h6280_00a,h6280_00b,h6280_00c,h6280_00d,h6280_00e,h6280_00f, |
| 314 | | h6280_010,h6280_011,h6280_012,h6280_013,h6280_014,h6280_015,h6280_016,h6280_017, |
| 315 | | h6280_018,h6280_019,h6280_01a,h6280_01b,h6280_01c,h6280_01d,h6280_01e,h6280_01f, |
| 316 | | h6280_020,h6280_021,h6280_022,h6280_023,h6280_024,h6280_025,h6280_026,h6280_027, |
| 317 | | h6280_028,h6280_029,h6280_02a,h6280_02b,h6280_02c,h6280_02d,h6280_02e,h6280_02f, |
| 318 | | h6280_030,h6280_031,h6280_032,h6280_033,h6280_034,h6280_035,h6280_036,h6280_037, |
| 319 | | h6280_038,h6280_039,h6280_03a,h6280_03b,h6280_03c,h6280_03d,h6280_03e,h6280_03f, |
| 320 | | h6280_040,h6280_041,h6280_042,h6280_043,h6280_044,h6280_045,h6280_046,h6280_047, |
| 321 | | h6280_048,h6280_049,h6280_04a,h6280_04b,h6280_04c,h6280_04d,h6280_04e,h6280_04f, |
| 322 | | h6280_050,h6280_051,h6280_052,h6280_053,h6280_054,h6280_055,h6280_056,h6280_057, |
| 323 | | h6280_058,h6280_059,h6280_05a,h6280_05b,h6280_05c,h6280_05d,h6280_05e,h6280_05f, |
| 324 | | h6280_060,h6280_061,h6280_062,h6280_063,h6280_064,h6280_065,h6280_066,h6280_067, |
| 325 | | h6280_068,h6280_069,h6280_06a,h6280_06b,h6280_06c,h6280_06d,h6280_06e,h6280_06f, |
| 326 | | h6280_070,h6280_071,h6280_072,h6280_073,h6280_074,h6280_075,h6280_076,h6280_077, |
| 327 | | h6280_078,h6280_079,h6280_07a,h6280_07b,h6280_07c,h6280_07d,h6280_07e,h6280_07f, |
| 328 | | h6280_080,h6280_081,h6280_082,h6280_083,h6280_084,h6280_085,h6280_086,h6280_087, |
| 329 | | h6280_088,h6280_089,h6280_08a,h6280_08b,h6280_08c,h6280_08d,h6280_08e,h6280_08f, |
| 330 | | h6280_090,h6280_091,h6280_092,h6280_093,h6280_094,h6280_095,h6280_096,h6280_097, |
| 331 | | h6280_098,h6280_099,h6280_09a,h6280_09b,h6280_09c,h6280_09d,h6280_09e,h6280_09f, |
| 332 | | h6280_0a0,h6280_0a1,h6280_0a2,h6280_0a3,h6280_0a4,h6280_0a5,h6280_0a6,h6280_0a7, |
| 333 | | h6280_0a8,h6280_0a9,h6280_0aa,h6280_0ab,h6280_0ac,h6280_0ad,h6280_0ae,h6280_0af, |
| 334 | | h6280_0b0,h6280_0b1,h6280_0b2,h6280_0b3,h6280_0b4,h6280_0b5,h6280_0b6,h6280_0b7, |
| 335 | | h6280_0b8,h6280_0b9,h6280_0ba,h6280_0bb,h6280_0bc,h6280_0bd,h6280_0be,h6280_0bf, |
| 336 | | h6280_0c0,h6280_0c1,h6280_0c2,h6280_0c3,h6280_0c4,h6280_0c5,h6280_0c6,h6280_0c7, |
| 337 | | h6280_0c8,h6280_0c9,h6280_0ca,h6280_0cb,h6280_0cc,h6280_0cd,h6280_0ce,h6280_0cf, |
| 338 | | h6280_0d0,h6280_0d1,h6280_0d2,h6280_0d3,h6280_0d4,h6280_0d5,h6280_0d6,h6280_0d7, |
| 339 | | h6280_0d8,h6280_0d9,h6280_0da,h6280_0db,h6280_0dc,h6280_0dd,h6280_0de,h6280_0df, |
| 340 | | h6280_0e0,h6280_0e1,h6280_0e2,h6280_0e3,h6280_0e4,h6280_0e5,h6280_0e6,h6280_0e7, |
| 341 | | h6280_0e8,h6280_0e9,h6280_0ea,h6280_0eb,h6280_0ec,h6280_0ed,h6280_0ee,h6280_0ef, |
| 342 | | h6280_0f0,h6280_0f1,h6280_0f2,h6280_0f3,h6280_0f4,h6280_0f5,h6280_0f6,h6280_0f7, |
| 343 | | h6280_0f8,h6280_0f9,h6280_0fa,h6280_0fb,h6280_0fc,h6280_0fd,h6280_0fe,h6280_0ff |
| 344 | | }; |
trunk/src/emu/sound/c6280.c
| r19741 | r19742 | |
| 56 | 56 | #include "emu.h" |
| 57 | 57 | #include "c6280.h" |
| 58 | 58 | |
| 59 | | struct t_channel { |
| 60 | | UINT16 frequency; |
| 61 | | UINT8 control; |
| 62 | | UINT8 balance; |
| 63 | | UINT8 waveform[32]; |
| 64 | | UINT8 index; |
| 65 | | INT16 dda; |
| 66 | | UINT8 noise_control; |
| 67 | | UINT32 noise_counter; |
| 68 | | UINT32 counter; |
| 69 | | }; |
| 70 | | |
| 71 | | struct c6280_t { |
| 72 | | sound_stream *stream; |
| 73 | | device_t *device; |
| 74 | | device_t *cpudevice; |
| 75 | | UINT8 select; |
| 76 | | UINT8 balance; |
| 77 | | UINT8 lfo_frequency; |
| 78 | | UINT8 lfo_control; |
| 79 | | t_channel channel[8]; |
| 80 | | INT16 volume_table[32]; |
| 81 | | UINT32 noise_freq_tab[32]; |
| 82 | | UINT32 wave_freq_tab[4096]; |
| 83 | | }; |
| 84 | | |
| 85 | | INLINE c6280_t *get_safe_token(device_t *device) |
| 86 | | { |
| 87 | | assert(device != NULL); |
| 88 | | assert(device->type() == C6280); |
| 89 | | return (c6280_t *)downcast<c6280_device *>(device)->token(); |
| 90 | | } |
| 91 | | |
| 92 | | |
| 93 | 59 | /* only needed for io_buffer */ |
| 94 | 60 | #include "cpu/h6280/h6280.h" |
| 95 | 61 | |
| 96 | 62 | |
| 97 | | static void c6280_init(device_t *device, c6280_t *p, double clk, double rate) |
| 63 | void c6280_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 98 | 64 | { |
| 99 | | const c6280_interface *intf = (const c6280_interface *)device->static_config(); |
| 100 | | int i; |
| 101 | | double step; |
| 65 | static const int scale_tab[] = { |
| 66 | 0x00, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, |
| 67 | 0x10, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F |
| 68 | }; |
| 102 | 69 | |
| 103 | | /* Loudest volume level for table */ |
| 104 | | double level = 65535.0 / 6.0 / 32.0; |
| 70 | int lmal = (m_balance >> 4) & 0x0F; |
| 71 | int rmal = (m_balance >> 0) & 0x0F; |
| 105 | 72 | |
| 106 | | /* Clear context */ |
| 107 | | memset(p, 0, sizeof(c6280_t)); |
| 73 | lmal = scale_tab[lmal]; |
| 74 | rmal = scale_tab[rmal]; |
| 108 | 75 | |
| 109 | | p->device = device; |
| 110 | | p->cpudevice = device->machine().device(intf->cpu); |
| 111 | | if (p->cpudevice == NULL) |
| 112 | | fatalerror("c6280_init: no CPU found with tag of '%s'\n", device->tag()); |
| 113 | | |
| 114 | | /* Make waveform frequency table */ |
| 115 | | for(i = 0; i < 4096; i += 1) |
| 76 | /* Clear buffer */ |
| 77 | for (int i = 0; i < samples; i++) |
| 116 | 78 | { |
| 117 | | step = ((clk / rate) * 4096) / (i+1); |
| 118 | | p->wave_freq_tab[(1 + i) & 0xFFF] = (UINT32)step; |
| 79 | outputs[0][i] = 0; |
| 80 | outputs[1][i] = 0; |
| 119 | 81 | } |
| 120 | 82 | |
| 121 | | /* Make noise frequency table */ |
| 122 | | for(i = 0; i < 32; i += 1) |
| 83 | for (int ch = 0; ch < 6; ch++) |
| 123 | 84 | { |
| 124 | | step = ((clk / rate) * 32) / (i+1); |
| 125 | | p->noise_freq_tab[i] = (UINT32)step; |
| 126 | | } |
| 85 | /* Only look at enabled channels */ |
| 86 | if(m_channel[ch].m_control & 0x80) |
| 87 | { |
| 88 | int lal = (m_channel[ch].m_balance >> 4) & 0x0F; |
| 89 | int ral = (m_channel[ch].m_balance >> 0) & 0x0F; |
| 90 | int al = m_channel[ch].m_control & 0x1F; |
| 127 | 91 | |
| 128 | | /* Make volume table */ |
| 129 | | /* PSG has 48dB volume range spread over 32 steps */ |
| 130 | | step = 48.0 / 32.0; |
| 131 | | for(i = 0; i < 31; i++) |
| 132 | | { |
| 133 | | p->volume_table[i] = (UINT16)level; |
| 134 | | level /= pow(10.0, step / 20.0); |
| 92 | lal = scale_tab[lal]; |
| 93 | ral = scale_tab[ral]; |
| 94 | |
| 95 | /* Calculate volume just as the patent says */ |
| 96 | int vll = (0x1F - lal) + (0x1F - al) + (0x1F - lmal); |
| 97 | if(vll > 0x1F) vll = 0x1F; |
| 98 | |
| 99 | int vlr = (0x1F - ral) + (0x1F - al) + (0x1F - rmal); |
| 100 | if(vlr > 0x1F) vlr = 0x1F; |
| 101 | |
| 102 | vll = m_volume_table[vll]; |
| 103 | vlr = m_volume_table[vlr]; |
| 104 | |
| 105 | /* Check channel mode */ |
| 106 | if((ch >= 4) && (m_channel[ch].m_noise_control & 0x80)) |
| 107 | { |
| 108 | /* Noise mode */ |
| 109 | UINT32 step = m_noise_freq_tab[(m_channel[ch].m_noise_control & 0x1F) ^ 0x1F]; |
| 110 | for (int i = 0; i < samples; i += 1) |
| 111 | { |
| 112 | static int data = 0; |
| 113 | m_channel[ch].m_noise_counter += step; |
| 114 | if(m_channel[ch].m_noise_counter >= 0x800) |
| 115 | { |
| 116 | data = (machine().rand() & 1) ? 0x1F : 0; |
| 117 | } |
| 118 | m_channel[ch].m_noise_counter &= 0x7FF; |
| 119 | outputs[0][i] += (INT16)(vll * (data - 16)); |
| 120 | outputs[1][i] += (INT16)(vlr * (data - 16)); |
| 121 | } |
| 122 | } |
| 123 | else |
| 124 | if(m_channel[ch].m_control & 0x40) |
| 125 | { |
| 126 | /* DDA mode */ |
| 127 | for (int i = 0; i < samples; i++) |
| 128 | { |
| 129 | outputs[0][i] += (INT16)(vll * (m_channel[ch].m_dda - 16)); |
| 130 | outputs[1][i] += (INT16)(vlr * (m_channel[ch].m_dda - 16)); |
| 131 | } |
| 132 | } |
| 133 | else |
| 134 | { |
| 135 | /* Waveform mode */ |
| 136 | UINT32 step = m_wave_freq_tab[m_channel[ch].m_frequency]; |
| 137 | for (int i = 0; i < samples; i += 1) |
| 138 | { |
| 139 | int offset; |
| 140 | INT16 data; |
| 141 | offset = (m_channel[ch].m_counter >> 12) & 0x1F; |
| 142 | m_channel[ch].m_counter += step; |
| 143 | m_channel[ch].m_counter &= 0x1FFFF; |
| 144 | data = m_channel[ch].m_waveform[offset]; |
| 145 | outputs[0][i] += (INT16)(vll * (data - 16)); |
| 146 | outputs[1][i] += (INT16)(vlr * (data - 16)); |
| 147 | } |
| 148 | } |
| 149 | } |
| 135 | 150 | } |
| 136 | | p->volume_table[31] = 0; |
| 137 | 151 | } |
| 138 | 152 | |
| 139 | 153 | |
| 140 | | static void c6280_write(c6280_t *p, int offset, int data) |
| 154 | /*--------------------------------------------------------------------------*/ |
| 155 | /* MAME specific code */ |
| 156 | /*--------------------------------------------------------------------------*/ |
| 157 | |
| 158 | READ8_MEMBER( c6280_device::c6280_r ) |
| 141 | 159 | { |
| 142 | | t_channel *q = &p->channel[p->select]; |
| 160 | return m_cpudevice->io_get_buffer(); |
| 161 | } |
| 143 | 162 | |
| 163 | WRITE8_MEMBER( c6280_device::c6280_w ) |
| 164 | { |
| 165 | m_cpudevice->io_set_buffer(data); |
| 166 | |
| 167 | channel *chan = &m_channel[m_select]; |
| 168 | |
| 144 | 169 | /* Update stream */ |
| 145 | | p->stream->update(); |
| 170 | m_stream->update(); |
| 146 | 171 | |
| 147 | 172 | switch(offset & 0x0F) |
| 148 | 173 | { |
| 149 | 174 | case 0x00: /* Channel select */ |
| 150 | | p->select = data & 0x07; |
| 175 | m_select = data & 0x07; |
| 151 | 176 | break; |
| 152 | 177 | |
| 153 | 178 | case 0x01: /* Global balance */ |
| 154 | | p->balance = data; |
| 179 | m_balance = data; |
| 155 | 180 | break; |
| 156 | 181 | |
| 157 | 182 | case 0x02: /* Channel frequency (LSB) */ |
| 158 | | q->frequency = (q->frequency & 0x0F00) | data; |
| 159 | | q->frequency &= 0x0FFF; |
| 183 | chan->m_frequency = (chan->m_frequency & 0x0F00) | data; |
| 184 | chan->m_frequency &= 0x0FFF; |
| 160 | 185 | break; |
| 161 | 186 | |
| 162 | 187 | case 0x03: /* Channel frequency (MSB) */ |
| 163 | | q->frequency = (q->frequency & 0x00FF) | (data << 8); |
| 164 | | q->frequency &= 0x0FFF; |
| 188 | chan->m_frequency = (chan->m_frequency & 0x00FF) | (data << 8); |
| 189 | chan->m_frequency &= 0x0FFF; |
| 165 | 190 | break; |
| 166 | 191 | |
| 167 | 192 | case 0x04: /* Channel control (key-on, DDA mode, volume) */ |
| 168 | 193 | |
| 169 | 194 | /* 1-to-0 transition of DDA bit resets waveform index */ |
| 170 | | if((q->control & 0x40) && ((data & 0x40) == 0)) |
| 195 | if((chan->m_control & 0x40) && ((data & 0x40) == 0)) |
| 171 | 196 | { |
| 172 | | q->index = 0; |
| 197 | chan->m_index = 0; |
| 173 | 198 | } |
| 174 | | q->control = data; |
| 199 | chan->m_control = data; |
| 175 | 200 | break; |
| 176 | 201 | |
| 177 | 202 | case 0x05: /* Channel balance */ |
| 178 | | q->balance = data; |
| 203 | chan->m_balance = data; |
| 179 | 204 | break; |
| 180 | 205 | |
| 181 | 206 | case 0x06: /* Channel waveform data */ |
| 182 | 207 | |
| 183 | | switch(q->control & 0xC0) |
| 208 | switch(chan->m_control & 0xC0) |
| 184 | 209 | { |
| 185 | 210 | case 0x00: |
| 186 | | q->waveform[q->index & 0x1F] = data & 0x1F; |
| 187 | | q->index = (q->index + 1) & 0x1F; |
| 211 | chan->m_waveform[chan->m_index & 0x1F] = data & 0x1F; |
| 212 | chan->m_index = (chan->m_index + 1) & 0x1F; |
| 188 | 213 | break; |
| 189 | 214 | |
| 190 | 215 | case 0x40: |
| 191 | 216 | break; |
| 192 | 217 | |
| 193 | 218 | case 0x80: |
| 194 | | q->waveform[q->index & 0x1F] = data & 0x1F; |
| 195 | | q->index = (q->index + 1) & 0x1F; |
| 219 | chan->m_waveform[chan->m_index & 0x1F] = data & 0x1F; |
| 220 | chan->m_index = (chan->m_index + 1) & 0x1F; |
| 196 | 221 | break; |
| 197 | 222 | |
| 198 | 223 | case 0xC0: |
| 199 | | q->dda = data & 0x1F; |
| 224 | chan->m_dda = data & 0x1F; |
| 200 | 225 | break; |
| 201 | 226 | } |
| 202 | 227 | |
| 203 | 228 | break; |
| 204 | 229 | |
| 205 | 230 | case 0x07: /* Noise control (enable, frequency) */ |
| 206 | | q->noise_control = data; |
| 231 | chan->m_noise_control = data; |
| 207 | 232 | break; |
| 208 | 233 | |
| 209 | 234 | case 0x08: /* LFO frequency */ |
| 210 | | p->lfo_frequency = data; |
| 235 | m_lfo_frequency = data; |
| 211 | 236 | break; |
| 212 | 237 | |
| 213 | 238 | case 0x09: /* LFO control (enable, mode) */ |
| 214 | | p->lfo_control = data; |
| 239 | m_lfo_control = data; |
| 215 | 240 | break; |
| 216 | 241 | |
| 217 | 242 | default: |
| r19741 | r19742 | |
| 219 | 244 | } |
| 220 | 245 | } |
| 221 | 246 | |
| 222 | | |
| 223 | | static STREAM_UPDATE( c6280_update ) |
| 224 | | { |
| 225 | | static const int scale_tab[] = { |
| 226 | | 0x00, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, |
| 227 | | 0x10, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F |
| 228 | | }; |
| 229 | | int ch; |
| 230 | | int i; |
| 231 | | c6280_t *p = (c6280_t *)param; |
| 232 | | |
| 233 | | int lmal = (p->balance >> 4) & 0x0F; |
| 234 | | int rmal = (p->balance >> 0) & 0x0F; |
| 235 | | int vll, vlr; |
| 236 | | |
| 237 | | lmal = scale_tab[lmal]; |
| 238 | | rmal = scale_tab[rmal]; |
| 239 | | |
| 240 | | /* Clear buffer */ |
| 241 | | for(i = 0; i < samples; i++) |
| 242 | | { |
| 243 | | outputs[0][i] = 0; |
| 244 | | outputs[1][i] = 0; |
| 245 | | } |
| 246 | | |
| 247 | | for(ch = 0; ch < 6; ch++) |
| 248 | | { |
| 249 | | /* Only look at enabled channels */ |
| 250 | | if(p->channel[ch].control & 0x80) |
| 251 | | { |
| 252 | | int lal = (p->channel[ch].balance >> 4) & 0x0F; |
| 253 | | int ral = (p->channel[ch].balance >> 0) & 0x0F; |
| 254 | | int al = p->channel[ch].control & 0x1F; |
| 255 | | |
| 256 | | lal = scale_tab[lal]; |
| 257 | | ral = scale_tab[ral]; |
| 258 | | |
| 259 | | /* Calculate volume just as the patent says */ |
| 260 | | vll = (0x1F - lal) + (0x1F - al) + (0x1F - lmal); |
| 261 | | if(vll > 0x1F) vll = 0x1F; |
| 262 | | |
| 263 | | vlr = (0x1F - ral) + (0x1F - al) + (0x1F - rmal); |
| 264 | | if(vlr > 0x1F) vlr = 0x1F; |
| 265 | | |
| 266 | | vll = p->volume_table[vll]; |
| 267 | | vlr = p->volume_table[vlr]; |
| 268 | | |
| 269 | | /* Check channel mode */ |
| 270 | | if((ch >= 4) && (p->channel[ch].noise_control & 0x80)) |
| 271 | | { |
| 272 | | /* Noise mode */ |
| 273 | | UINT32 step = p->noise_freq_tab[(p->channel[ch].noise_control & 0x1F) ^ 0x1F]; |
| 274 | | for(i = 0; i < samples; i += 1) |
| 275 | | { |
| 276 | | static int data = 0; |
| 277 | | p->channel[ch].noise_counter += step; |
| 278 | | if(p->channel[ch].noise_counter >= 0x800) |
| 279 | | { |
| 280 | | data = (p->device->machine().rand() & 1) ? 0x1F : 0; |
| 281 | | } |
| 282 | | p->channel[ch].noise_counter &= 0x7FF; |
| 283 | | outputs[0][i] += (INT16)(vll * (data - 16)); |
| 284 | | outputs[1][i] += (INT16)(vlr * (data - 16)); |
| 285 | | } |
| 286 | | } |
| 287 | | else |
| 288 | | if(p->channel[ch].control & 0x40) |
| 289 | | { |
| 290 | | /* DDA mode */ |
| 291 | | for(i = 0; i < samples; i++) |
| 292 | | { |
| 293 | | outputs[0][i] += (INT16)(vll * (p->channel[ch].dda - 16)); |
| 294 | | outputs[1][i] += (INT16)(vlr * (p->channel[ch].dda - 16)); |
| 295 | | } |
| 296 | | } |
| 297 | | else |
| 298 | | { |
| 299 | | /* Waveform mode */ |
| 300 | | UINT32 step = p->wave_freq_tab[p->channel[ch].frequency]; |
| 301 | | for(i = 0; i < samples; i += 1) |
| 302 | | { |
| 303 | | int offset; |
| 304 | | INT16 data; |
| 305 | | offset = (p->channel[ch].counter >> 12) & 0x1F; |
| 306 | | p->channel[ch].counter += step; |
| 307 | | p->channel[ch].counter &= 0x1FFFF; |
| 308 | | data = p->channel[ch].waveform[offset]; |
| 309 | | outputs[0][i] += (INT16)(vll * (data - 16)); |
| 310 | | outputs[1][i] += (INT16)(vlr * (data - 16)); |
| 311 | | } |
| 312 | | } |
| 313 | | } |
| 314 | | } |
| 315 | | } |
| 316 | | |
| 317 | | |
| 318 | | /*--------------------------------------------------------------------------*/ |
| 319 | | /* MAME specific code */ |
| 320 | | /*--------------------------------------------------------------------------*/ |
| 321 | | |
| 322 | | static DEVICE_START( c6280 ) |
| 323 | | { |
| 324 | | int rate = device->clock()/16; |
| 325 | | c6280_t *info = get_safe_token(device); |
| 326 | | |
| 327 | | /* Initialize PSG emulator */ |
| 328 | | c6280_init(device, info, device->clock(), rate); |
| 329 | | |
| 330 | | /* Create stereo stream */ |
| 331 | | info->stream = device->machine().sound().stream_alloc(*device, 0, 2, rate, info, c6280_update); |
| 332 | | } |
| 333 | | |
| 334 | | READ8_DEVICE_HANDLER( c6280_r ) |
| 335 | | { |
| 336 | | c6280_t *info = get_safe_token(device); |
| 337 | | return h6280io_get_buffer(info->cpudevice); |
| 338 | | } |
| 339 | | |
| 340 | | WRITE8_DEVICE_HANDLER( c6280_w ) |
| 341 | | { |
| 342 | | c6280_t *info = get_safe_token(device); |
| 343 | | h6280io_set_buffer(info->cpudevice, data); |
| 344 | | c6280_write(info, offset, data); |
| 345 | | } |
| 346 | | |
| 347 | 247 | const device_type C6280 = &device_creator<c6280_device>; |
| 348 | 248 | |
| 349 | 249 | c6280_device::c6280_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 350 | 250 | : device_t(mconfig, C6280, "HuC6280", tag, owner, clock), |
| 351 | 251 | device_sound_interface(mconfig, *this) |
| 352 | 252 | { |
| 353 | | m_token = global_alloc_clear(c6280_t); |
| 354 | 253 | } |
| 355 | 254 | |
| 356 | 255 | //------------------------------------------------- |
| r19741 | r19742 | |
| 369 | 268 | |
| 370 | 269 | void c6280_device::device_start() |
| 371 | 270 | { |
| 372 | | DEVICE_START_NAME( c6280 )(this); |
| 373 | | } |
| 271 | int rate = clock() / 16; |
| 374 | 272 | |
| 375 | | //------------------------------------------------- |
| 376 | | // sound_stream_update - handle a stream update |
| 377 | | //------------------------------------------------- |
| 273 | /* Create stereo stream */ |
| 274 | m_stream = machine().sound().stream_alloc(*this, 0, 2, rate, this); |
| 378 | 275 | |
| 379 | | void c6280_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
| 380 | | { |
| 381 | | // should never get here |
| 382 | | fatalerror("sound_stream_update called; not applicable to legacy sound devices\n"); |
| 383 | | } |
| 276 | const c6280_interface *intf = (const c6280_interface *)static_config(); |
| 384 | 277 | |
| 278 | /* Loudest volume level for table */ |
| 279 | double level = 65535.0 / 6.0 / 32.0; |
| 385 | 280 | |
| 281 | /* Clear context */ |
| 282 | m_select = 0; |
| 283 | m_balance = 0; |
| 284 | m_lfo_frequency = 0; |
| 285 | m_lfo_control = 0; |
| 286 | memset(m_channel, 0, sizeof(channel) * 8); |
| 287 | |
| 288 | m_cpudevice = machine().device<h6280_device>(intf->cpu); |
| 289 | if (m_cpudevice == NULL) |
| 290 | { |
| 291 | fatalerror("c6280_init: no CPU found with tag of '%s'\n", tag()); |
| 292 | } |
| 293 | |
| 294 | /* Make waveform frequency table */ |
| 295 | for (int i = 0; i < 4096; i += 1) |
| 296 | { |
| 297 | double step = ((clock() / rate) * 4096) / (i + 1); |
| 298 | m_wave_freq_tab[(1 + i) & 0xFFF] = (UINT32)step; |
| 299 | } |
| 300 | |
| 301 | /* Make noise frequency table */ |
| 302 | for (int i = 0; i < 32; i += 1) |
| 303 | { |
| 304 | double step = ((clock() / rate) * 32) / (i+1); |
| 305 | m_noise_freq_tab[i] = (UINT32)step; |
| 306 | } |
| 307 | |
| 308 | /* Make volume table */ |
| 309 | /* PSG has 48dB volume range spread over 32 steps */ |
| 310 | double step = 48.0 / 32.0; |
| 311 | for (int i = 0; i < 31; i++) |
| 312 | { |
| 313 | m_volume_table[i] = (UINT16)level; |
| 314 | level /= pow(10.0, step / 20.0); |
| 315 | } |
| 316 | m_volume_table[31] = 0; |
| 317 | } |