/*************************************************************************** Atari I, Robot hardware ***************************************************************************/ #include "driver.h" #include "profiler.h" #include "cpu/m6809/m6809.h" #include "irobot.h" /* Note: * There's probably something wrong with the way the Mathbox gets started. * Try compiling with IR_TIMING=1, run with logging on and take a look at * the resulting logilfe. * The mathbox is started in short intervals (<10 scanlines) without (!) * checking its idle status. * It also seems that the mathbox in this emulation would have to cope with * approx. 5000 instructions per scanline [look at the number of instructions * and the number of scanlines to the next mathbox start]. This seems a bit * too high. */ #define IR_TIMING 1 /* try to emulate MB and VG running time */ #define DISASSEMBLE_MB_ROM 0 /* generate a disassembly of the mathbox ROMs */ #define IR_CPU_STATE \ logerror(\ "pc: %4x, scanline: %d\n", activecpu_get_previouspc(), video_screen_get_vpos(0)) UINT8 irobot_vg_clear; static UINT8 irvg_vblank; static UINT8 irvg_running; static UINT8 irmb_running; #if IR_TIMING static mame_timer *irvg_timer; static mame_timer *irmb_timer; #endif static UINT8 *comRAM[2], *mbRAM, *mbROM; static UINT8 irobot_control_num = 0; static UINT8 irobot_statwr; static UINT8 irobot_out0; static UINT8 irobot_outx,irobot_mpage; static UINT8 *irobot_combase_mb; UINT8 *irobot_combase; UINT8 irobot_bufsel; UINT8 irobot_alphamap; static void irmb_run(void); /***********************************************************************/ READ8_HANDLER( irobot_sharedmem_r ) { if (irobot_outx == 3) return mbRAM[BYTE_XOR_BE(offset)]; if (irobot_outx == 2) return irobot_combase[BYTE_XOR_BE(offset & 0xFFF)]; if (irobot_outx == 0) return mbROM[((irobot_mpage & 1) << 13) + BYTE_XOR_BE(offset)]; if (irobot_outx == 1) return mbROM[0x4000 + ((irobot_mpage & 3) << 13) + BYTE_XOR_BE(offset)]; return 0xFF; } /* Comment out the mbRAM =, comRAM2 = or comRAM1 = and it will start working */ WRITE8_HANDLER( irobot_sharedmem_w ) { if (irobot_outx == 3) mbRAM[BYTE_XOR_BE(offset)] = data; if (irobot_outx == 2) irobot_combase[BYTE_XOR_BE(offset & 0xFFF)] = data; } static TIMER_CALLBACK( irvg_done_callback ) { logerror("vg done. "); irvg_running = 0; } WRITE8_HANDLER( irobot_statwr_w ) { logerror("write %2x ", data); IR_CPU_STATE; irobot_combase = comRAM[data >> 7]; irobot_combase_mb = comRAM[(data >> 7) ^ 1]; irobot_bufsel = data & 0x02; if (((data & 0x01) == 0x01) && (irobot_vg_clear == 0)) irobot_poly_clear(); irobot_vg_clear = data & 0x01; if ((data & 0x04) && !(irobot_statwr & 0x04)) { irobot_run_video(); #if IR_TIMING if (irvg_running == 0) logerror("vg start "); else logerror("vg start [busy!] "); IR_CPU_STATE; mame_timer_adjust(irvg_timer, MAME_TIME_IN_MSEC(10), 0, time_zero); #endif irvg_running=1; } if ((data & 0x10) && !(irobot_statwr & 0x10)) irmb_run(); irobot_statwr = data; } WRITE8_HANDLER( irobot_out0_w ) { UINT8 *RAM = memory_region(REGION_CPU1); irobot_out0 = data; switch (data & 0x60) { case 0: memory_set_bankptr(2, &RAM[0x1C000]); break; case 0x20: memory_set_bankptr(2, &RAM[0x1C800]); break; case 0x40: memory_set_bankptr(2, &RAM[0x1D000]); break; } irobot_outx = (data & 0x18) >> 3; irobot_mpage = (data & 0x06) >> 1; irobot_alphamap = (data & 0x80); } WRITE8_HANDLER( irobot_rom_banksel_w ) { UINT8 *RAM = memory_region(REGION_CPU1); switch ((data & 0x0E) >> 1) { case 0: memory_set_bankptr(1, &RAM[0x10000]); break; case 1: memory_set_bankptr(1, &RAM[0x12000]); break; case 2: memory_set_bankptr(1, &RAM[0x14000]); break; case 3: memory_set_bankptr(1, &RAM[0x16000]); break; case 4: memory_set_bankptr(1, &RAM[0x18000]); break; case 5: memory_set_bankptr(1, &RAM[0x1A000]); break; } set_led_status(0,data & 0x10); set_led_status(1,data & 0x20); } static TIMER_CALLBACK( scanline_callback ) { int scanline = param; if (scanline == 0) irvg_vblank=0; if (scanline == 224) irvg_vblank=1; logerror("SCANLINE CALLBACK %d\n",scanline); /* set the IRQ line state based on the 32V line state */ cpunum_set_input_line(0, M6809_IRQ_LINE, (scanline & 32) ? ASSERT_LINE : CLEAR_LINE); /* set a callback for the next 32-scanline increment */ scanline += 32; if (scanline >= 256) scanline = 0; mame_timer_set(video_screen_get_time_until_pos(0, scanline, 0), scanline, scanline_callback); } static TIMER_CALLBACK( irmb_done_callback ); MACHINE_RESET( irobot ) { UINT8 *MB = memory_region(REGION_CPU2); /* initialize the memory regions */ mbROM = MB + 0x00000; mbRAM = MB + 0x0c000; comRAM[0] = MB + 0x0e000; comRAM[1] = MB + 0x0f000; irvg_vblank=0; irvg_running = 0; irvg_timer = mame_timer_alloc(irvg_done_callback); irmb_running = 0; irmb_timer = mame_timer_alloc(irmb_done_callback); /* set an initial timer to go off on scanline 0 */ mame_timer_set(video_screen_get_time_until_pos(0, 0, 0), 0, scanline_callback); irobot_rom_banksel_w(0,0); irobot_out0_w(0,0); irobot_combase = comRAM[0]; irobot_combase_mb = comRAM[1]; irobot_outx = 0; } WRITE8_HANDLER( irobot_control_w ) { irobot_control_num = offset & 0x03; } READ8_HANDLER( irobot_control_r ) { if (irobot_control_num == 0) return readinputport (5); else if (irobot_control_num == 1) return readinputport (6); return 0; } /* we allow irmb_running and irvg_running to appear running before clearing them to simulate the mathbox and vector generator running in real time */ READ8_HANDLER( irobot_status_r ) { int d=0; logerror("status read. "); IR_CPU_STATE; if (!irmb_running) d |= 0x20; if (irvg_running) d |= 0x40; // d = (irmb_running * 0x20) | (irvg_running * 0x40); if (irvg_vblank) d = d | 0x80; #if IR_TIMING /* flags are cleared by callbacks */ #else irmb_running=0; irvg_running=0; #endif return d; } /*********************************************************************** I-Robot Mathbox Based on 4 2901 chips slice processors connected to form a 16-bit ALU Microcode roms: 6N: bits 0..3: Address of ALU A register 5P: bits 0..3: Address of ALU B register 6M: bits 0..3: ALU Function bits 5..8 7N: bits 0..3: ALU Function bits 1..4 8N: bits 0,1: Memory write timing bit 2: Hardware multiply mode bit 3: ALU Function bit 0 6P: bits 0,1: Direct addressing bits 0,1 bits 2,3: Jump address bits 0,1 8M: bits 0..3: Jump address bits 6..9 9N: bits 0..3: Jump address bits 2..5 8P: bits 0..3: Memory address bits 2..5 9M: bit 0: Shift control bits 1..3: Jump type 0 = No Jump 1 = On carry 2 = On zero 3 = On positive 4 = On negative 5 = Unconditional 6 = Jump to Subroutine 7 = Return from Subroutine 7M: Bit 0: Mathbox memory enable Bit 1: Latch data to address bus Bit 2: Carry in select Bit 3: Carry in value (if 2,3 = 11 then mathbox is done) 9P: Bit 0: Hardware divide enable Bits 1,2: Memory select Bit 3: Memory R/W 7P: Bits 0,1: Direct addressing bits 6,7 Bits 2,3: Unused ***********************************************************************/ #define FL_MULT 0x01 #define FL_shift 0x02 #define FL_MBMEMDEC 0x04 #define FL_ADDEN 0x08 #define FL_DPSEL 0x10 #define FL_carry 0x20 #define FL_DIV 0x40 #define FL_MBRW 0x80 typedef struct irmb_ops { const struct irmb_ops *nxtop; UINT32 func; UINT32 diradd; UINT32 latchmask; UINT32 *areg; UINT32 *breg; UINT8 cycles; UINT8 diren; UINT8 flags; UINT8 ramsel; } irmb_ops; static irmb_ops *mbops; static const irmb_ops *irmb_stack[16]; static UINT32 irmb_regs[16]; static UINT32 irmb_latch; #if DISASSEMBLE_MB_ROM static void disassemble_instruction(irmb_ops *op); #endif static UINT32 irmb_din(const irmb_ops *curop) { UINT32 d = 0; if (!(curop->flags & FL_MBMEMDEC) && (curop->flags & FL_MBRW)) { UINT32 ad = curop->diradd | (irmb_latch & curop->latchmask); if (curop->diren || (irmb_latch & 0x6000) == 0) d = ((UINT16 *)mbRAM)[ad & 0xfff]; /* MB RAM read */ else if (irmb_latch & 0x4000) d = ((UINT16 *)mbROM)[ad + 0x2000]; /* MB ROM read, CEMATH = 1 */ else d = ((UINT16 *)mbROM)[ad & 0x1fff]; /* MB ROM read, CEMATH = 0 */ } return d; } static void irmb_dout(const irmb_ops *curop, UINT32 d) { /* Write to video com ram */ if (curop->ramsel == 3) ((UINT16 *)irobot_combase_mb)[irmb_latch & 0x7ff] = d; /* Write to mathox ram */ if (!(curop->flags & FL_MBMEMDEC)) { UINT32 ad = curop->diradd | (irmb_latch & curop->latchmask); if (curop->diren || (irmb_latch & 0x6000) == 0) ((UINT16 *)mbRAM)[ad & 0xfff] = d; /* MB RAM write */ } } /* Convert microcode roms to a more usable form */ static void load_oproms(void) { UINT8 *MB = memory_region(REGION_PROMS) + 0x20; int i; /* allocate RAM */ mbops = auto_malloc(sizeof(irmb_ops) * 1024); for (i = 0; i < 1024; i++) { int nxtadd, func, ramsel, diradd, latchmask, dirmask, time; mbops[i].areg = &irmb_regs[MB[0x0000 + i] & 0x0F]; mbops[i].breg = &irmb_regs[MB[0x0400 + i] & 0x0F]; func = (MB[0x0800 + i] & 0x0F) << 5; func |= ((MB[0x0C00 +i] & 0x0F) << 1); func |= (MB[0x1000 + i] & 0x08) >> 3; time = MB[0x1000 + i] & 0x03; mbops[i].flags = (MB[0x1000 + i] & 0x04) >> 2; nxtadd = (MB[0x1400 + i] & 0x0C) >> 2; diradd = MB[0x1400 + i] & 0x03; nxtadd |= ((MB[0x1800 + i] & 0x0F) << 6); nxtadd |= ((MB[0x1C00 + i] & 0x0F) << 2); diradd |= (MB[0x2000 + i] & 0x0F) << 2; func |= (MB[0x2400 + i] & 0x0E) << 9; mbops[i].flags |= (MB[0x2400 + i] & 0x01) << 1; mbops[i].flags |= (MB[0x2800 + i] & 0x0F) << 2; mbops[i].flags |= ((MB[0x2C00 + i] & 0x01) << 6); mbops[i].flags |= (MB[0x2C00 + i] & 0x08) << 4; ramsel = (MB[0x2C00 + i] & 0x06) >> 1; diradd |= (MB[0x3000 + i] & 0x03) << 6; if (mbops[i].flags & FL_shift) func |= 0x200; mbops[i].func = func; mbops[i].nxtop = &mbops[nxtadd]; /* determine the number of 12MHz cycles for this operation */ if (time == 3) mbops[i].cycles = 2; else mbops[i].cycles = 3 + time; /* precompute the hardcoded address bits and the mask to be used on the latch value */ if (ramsel == 0) { dirmask = 0x00FC; latchmask = 0x3000; } else { dirmask = 0x0000; latchmask = 0x3FFC; } if (ramsel & 2) latchmask |= 0x0003; else dirmask |= 0x0003; mbops[i].ramsel = ramsel; mbops[i].diradd = diradd & dirmask; mbops[i].latchmask = latchmask; mbops[i].diren = (ramsel == 0); #if DISASSEMBLE_MB_ROM disassemble_instruction(&mbops[i]); #endif } } /* Init mathbox (only called once) */ DRIVER_INIT( irobot ) { int i; for (i = 0; i < 16; i++) { irmb_stack[i] = &mbops[0]; irmb_regs[i] = 0; } irmb_latch=0; load_oproms(); } static TIMER_CALLBACK( irmb_done_callback ) { logerror("mb done. "); irmb_running = 0; cpunum_set_input_line(0, M6809_FIRQ_LINE, ASSERT_LINE); } #define COMPUTE_CI \ CI = 0;\ if (curop->flags & FL_DPSEL)\ CI = cflag;\ else\ {\ if (curop->flags & FL_carry)\ CI = 1;\ if (!(prevop->flags & FL_DIV) && !nflag)\ CI = 1;\ } #define ADD(r,s) \ COMPUTE_CI;\ result = r + s + CI;\ cflag = (result >> 16) & 1;\ vflag = (((r & 0x7fff) + (s & 0x7fff) + CI) >> 15) ^ cflag #define SUBR(r,s) \ COMPUTE_CI;\ result = (r ^ 0xFFFF) + s + CI; /*S - R + CI - 1*/ \ cflag = (result >> 16) & 1;\ vflag = (((s & 0x7fff) + ((r ^ 0xffff) & 0x7fff) + CI) >> 15) ^ cflag #define SUB(r,s) \ COMPUTE_CI;\ result = r + (s ^ 0xFFFF) + CI; /*R - S + CI - 1*/ \ cflag = (result >> 16) & 1;\ vflag = (((r & 0x7fff) + ((s ^ 0xffff) & 0x7fff) + CI) >> 15) ^ cflag #define OR(r,s) \ result = r | s;\ vflag = cflag = 0 #define AND(r,s) \ result = r & s;\ vflag = cflag = 0 #define IAND(r,s) \ result = (r ^ 0xFFFF) & s;\ vflag = cflag = 0 #define XOR(r,s) \ result = r ^ s;\ vflag = cflag = 0 #define IXOR(r,s) \ result = (r ^ s) ^ 0xFFFF;\ vflag = cflag = 0 #define DEST0 \ Q = Y = zresult #define DEST1 \ Y = zresult #define DEST2 \ Y = *curop->areg;\ *curop->breg = zresult #define DEST3 \ *curop->breg = zresult;\ Y = zresult #define DEST4_NOSHIFT \ *curop->breg = (zresult >> 1) | ((curop->flags & 0x20) << 10);\ Q = (Q >> 1) | ((curop->flags & 0x20) << 10);\ Y = zresult #define DEST4_SHIFT \ *curop->breg = (zresult >> 1) | ((nflag ^ vflag) << 15);\ Q = (Q >> 1) | ((zresult & 0x01) << 15);\ Y = zresult #define DEST5_NOSHIFT \ *curop->breg = (zresult >> 1) | ((curop->flags & 0x20) << 10);\ Y = zresult #define DEST5_SHIFT \ *curop->breg = (zresult >> 1) | ((nflag ^ vflag) << 15);\ Y = zresult #define DEST6_NOSHIFT \ *curop->breg = zresult << 1;\ Q = ((Q << 1) & 0xffff) | (nflag ^ 1);\ Y = zresult #define DEST6_SHIFT \ *curop->breg = (zresult << 1) | ((Q & 0x8000) >> 15);\ Q = (Q << 1) & 0xffff;\ Y = zresult #define DEST7_NOSHIFT \ *curop->breg = zresult << 1;\ Y = zresult #define DEST7_SHIFT \ *curop->breg = (zresult << 1) | ((Q & 0x8000) >> 15);\ Y = zresult #define JUMP0 curop++; #define JUMP1 if (cflag) curop = curop->nxtop; else curop++; #define JUMP2 if (!zresult) curop = curop->nxtop; else curop++; #define JUMP3 if (!nflag) curop = curop->nxtop; else curop++; #define JUMP4 if (nflag) curop = curop->nxtop; else curop++; #define JUMP5 curop = curop->nxtop; #define JUMP6 irmb_stack[SP] = curop + 1; SP = (SP + 1) & 15; curop = curop->nxtop; #define JUMP7 SP = (SP - 1) & 15; curop = irmb_stack[SP]; /* Run mathbox */ static void irmb_run(void) { const irmb_ops *prevop = &mbops[0]; const irmb_ops *curop = &mbops[0]; UINT32 Q = 0; UINT32 Y = 0; UINT32 nflag = 0; UINT32 vflag = 0; UINT32 cflag = 0; UINT32 zresult = 1; UINT32 CI = 0; UINT32 SP = 0; UINT32 icount = 0; profiler_mark(PROFILER_USER1); while ((prevop->flags & (FL_DPSEL | FL_carry)) != (FL_DPSEL | FL_carry)) { UINT32 result; UINT32 fu; UINT32 tmp; icount += curop->cycles; /* Get function code */ fu = curop->func; /* Modify function for MULT */ if (!(prevop->flags & FL_MULT) || (Q & 1)) fu = fu ^ 0x02; else fu = fu | 0x02; /* Modify function for DIV */ if ((prevop->flags & FL_DIV) || nflag) fu = fu ^ 0x08; else fu = fu | 0x08; /* Do source and operation */ switch (fu & 0x03f) { case 0x00: ADD(*curop->areg, Q); break; case 0x01: ADD(*curop->areg, *curop->breg); break; case 0x02: ADD(0, Q); break; case 0x03: ADD(0, *curop->breg); break; case 0x04: ADD(0, *curop->areg); break; case 0x05: tmp = irmb_din(curop); ADD(tmp, *curop->areg); break; case 0x06: tmp = irmb_din(curop); ADD(tmp, Q); break; case 0x07: tmp = irmb_din(curop); ADD(tmp, 0); break; case 0x08: SUBR(*curop->areg, Q); break; case 0x09: SUBR(*curop->areg, *curop->breg); break; case 0x0a: SUBR(0, Q); break; case 0x0b: SUBR(0, *curop->breg); break; case 0x0c: SUBR(0, *curop->areg); break; case 0x0d: tmp = irmb_din(curop); SUBR(tmp, *curop->areg); break; case 0x0e: tmp = irmb_din(curop); SUBR(tmp, Q); break; case 0x0f: tmp = irmb_din(curop); SUBR(tmp, 0); break; case 0x10: SUB(*curop->areg, Q); break; case 0x11: SUB(*curop->areg, *curop->breg); break; case 0x12: SUB(0, Q); break; case 0x13: SUB(0, *curop->breg); break; case 0x14: SUB(0, *curop->areg); break; case 0x15: tmp = irmb_din(curop); SUB(tmp, *curop->areg); break; case 0x16: tmp = irmb_din(curop); SUB(tmp, Q); break; case 0x17: tmp = irmb_din(curop); SUB(tmp, 0); break; case 0x18: OR(*curop->areg, Q); break; case 0x19: OR(*curop->areg, *curop->breg); break; case 0x1a: OR(0, Q); break; case 0x1b: OR(0, *curop->breg); break; case 0x1c: OR(0, *curop->areg); break; case 0x1d: OR(irmb_din(curop), *curop->areg); break; case 0x1e: OR(irmb_din(curop), Q); break; case 0x1f: OR(irmb_din(curop), 0); break; case 0x20: AND(*curop->areg, Q); break; case 0x21: AND(*curop->areg, *curop->breg); break; case 0x22: AND(0, Q); break; case 0x23: AND(0, *curop->breg); break; case 0x24: AND(0, *curop->areg); break; case 0x25: AND(irmb_din(curop), *curop->areg); break; case 0x26: AND(irmb_din(curop), Q); break; case 0x27: AND(irmb_din(curop), 0); break; case 0x28: IAND(*curop->areg, Q); break; case 0x29: IAND(*curop->areg, *curop->breg); break; case 0x2a: IAND(0, Q); break; case 0x2b: IAND(0, *curop->breg); break; case 0x2c: IAND(0, *curop->areg); break; case 0x2d: IAND(irmb_din(curop), *curop->areg); break; case 0x2e: IAND(irmb_din(curop), Q); break; case 0x2f: IAND(irmb_din(curop), 0); break; case 0x30: XOR(*curop->areg, Q); break; case 0x31: XOR(*curop->areg, *curop->breg); break; case 0x32: XOR(0, Q); break; case 0x33: XOR(0, *curop->breg); break; case 0x34: XOR(0, *curop->areg); break; case 0x35: XOR(irmb_din(curop), *curop->areg); break; case 0x36: XOR(irmb_din(curop), Q); break; case 0x37: XOR(irmb_din(curop), 0); break; case 0x38: IXOR(*curop->areg, Q); break; case 0x39: IXOR(*curop->areg, *curop->breg); break; case 0x3a: IXOR(0, Q); break; case 0x3b: IXOR(0, *curop->breg); break; case 0x3c: IXOR(0, *curop->areg); break; case 0x3d: IXOR(irmb_din(curop), *curop->areg); break; case 0x3e: IXOR(irmb_din(curop), Q); break; default: case 0x3f: IXOR(irmb_din(curop), 0); break; } /* Evaluate flags */ zresult = result & 0xFFFF; nflag = zresult >> 15; prevop = curop; /* Do destination and jump */ switch (fu >> 6) { case 0x00: case 0x08: DEST0; JUMP0; break; case 0x01: case 0x09: DEST1; JUMP0; break; case 0x02: case 0x0a: DEST2; JUMP0; break; case 0x03: case 0x0b: DEST3; JUMP0; break; case 0x04: DEST4_NOSHIFT; JUMP0; break; case 0x05: DEST5_NOSHIFT; JUMP0; break; case 0x06: DEST6_NOSHIFT; JUMP0; break; case 0x07: DEST7_NOSHIFT; JUMP0; break; case 0x0c: DEST4_SHIFT; JUMP0; break; case 0x0d: DEST5_SHIFT; JUMP0; break; case 0x0e: DEST6_SHIFT; JUMP0; break; case 0x0f: DEST7_SHIFT; JUMP0; break; case 0x10: case 0x18: DEST0; JUMP1; break; case 0x11: case 0x19: DEST1; JUMP1; break; case 0x12: case 0x1a: DEST2; JUMP1; break; case 0x13: case 0x1b: DEST3; JUMP1; break; case 0x14: DEST4_NOSHIFT; JUMP1; break; case 0x15: DEST5_NOSHIFT; JUMP1; break; case 0x16: DEST6_NOSHIFT; JUMP1; break; case 0x17: DEST7_NOSHIFT; JUMP1; break; case 0x1c: DEST4_SHIFT; JUMP1; break; case 0x1d: DEST5_SHIFT; JUMP1; break; case 0x1e: DEST6_SHIFT; JUMP1; break; case 0x1f: DEST7_SHIFT; JUMP1; break; case 0x20: case 0x28: DEST0; JUMP2; break; case 0x21: case 0x29: DEST1; JUMP2; break; case 0x22: case 0x2a: DEST2; JUMP2; break; case 0x23: case 0x2b: DEST3; JUMP2; break; case 0x24: DEST4_NOSHIFT; JUMP2; break; case 0x25: DEST5_NOSHIFT; JUMP2; break; case 0x26: DEST6_NOSHIFT; JUMP2; break; case 0x27: DEST7_NOSHIFT; JUMP2; break; case 0x2c: DEST4_SHIFT; JUMP2; break; case 0x2d: DEST5_SHIFT; JUMP2; break; case 0x2e: DEST6_SHIFT; JUMP2; break; case 0x2f: DEST7_SHIFT; JUMP2; break; case 0x30: case 0x38: DEST0; JUMP3; break; case 0x31: case 0x39: DEST1; JUMP3; break; case 0x32: case 0x3a: DEST2; JUMP3; break; case 0x33: case 0x3b: DEST3; JUMP3; break; case 0x34: DEST4_NOSHIFT; JUMP3; break; case 0x35: DEST5_NOSHIFT; JUMP3; break; case 0x36: DEST6_NOSHIFT; JUMP3; break; case 0x37: DEST7_NOSHIFT; JUMP3; break; case 0x3c: DEST4_SHIFT; JUMP3; break; case 0x3d: DEST5_SHIFT; JUMP3; break; case 0x3e: DEST6_SHIFT; JUMP3; break; case 0x3f: DEST7_SHIFT; JUMP3; break; case 0x40: case 0x48: DEST0; JUMP4; break; case 0x41: case 0x49: DEST1; JUMP4; break; case 0x42: case 0x4a: DEST2; JUMP4; break; case 0x43: case 0x4b: DEST3; JUMP4; break; case 0x44: DEST4_NOSHIFT; JUMP4; break; case 0x45: DEST5_NOSHIFT; JUMP4; break; case 0x46: DEST6_NOSHIFT; JUMP4; break; case 0x47: DEST7_NOSHIFT; JUMP4; break; case 0x4c: DEST4_SHIFT; JUMP4; break; case 0x4d: DEST5_SHIFT; JUMP4; break; case 0x4e: DEST6_SHIFT; JUMP4; break; case 0x4f: DEST7_SHIFT; JUMP4; break; case 0x50: case 0x58: DEST0; JUMP5; break; case 0x51: case 0x59: DEST1; JUMP5; break; case 0x52: case 0x5a: DEST2; JUMP5; break; case 0x53: case 0x5b: DEST3; JUMP5; break; case 0x54: DEST4_NOSHIFT; JUMP5; break; case 0x55: DEST5_NOSHIFT; JUMP5; break; case 0x56: DEST6_NOSHIFT; JUMP5; break; case 0x57: DEST7_NOSHIFT; JUMP5; break; case 0x5c: DEST4_SHIFT; JUMP5; break; case 0x5d: DEST5_SHIFT; JUMP5; break; case 0x5e: DEST6_SHIFT; JUMP5; break; case 0x5f: DEST7_SHIFT; JUMP5; break; case 0x60: case 0x68: DEST0; JUMP6; break; case 0x61: case 0x69: DEST1; JUMP6; break; case 0x62: case 0x6a: DEST2; JUMP6; break; case 0x63: case 0x6b: DEST3; JUMP6; break; case 0x64: DEST4_NOSHIFT; JUMP6; break; case 0x65: DEST5_NOSHIFT; JUMP6; break; case 0x66: DEST6_NOSHIFT; JUMP6; break; case 0x67: DEST7_NOSHIFT; JUMP6; break; case 0x6c: DEST4_SHIFT; JUMP6; break; case 0x6d: DEST5_SHIFT; JUMP6; break; case 0x6e: DEST6_SHIFT; JUMP6; break; case 0x6f: DEST7_SHIFT; JUMP6; break; case 0x70: case 0x78: DEST0; JUMP7; break; case 0x71: case 0x79: DEST1; JUMP7; break; case 0x72: case 0x7a: DEST2; JUMP7; break; case 0x73: case 0x7b: DEST3; JUMP7; break; case 0x74: DEST4_NOSHIFT; JUMP7; break; case 0x75: DEST5_NOSHIFT; JUMP7; break; case 0x76: DEST6_NOSHIFT; JUMP7; break; case 0x77: DEST7_NOSHIFT; JUMP7; break; case 0x7c: DEST4_SHIFT; JUMP7; break; case 0x7d: DEST5_SHIFT; JUMP7; break; case 0x7e: DEST6_SHIFT; JUMP7; break; case 0x7f: DEST7_SHIFT; JUMP7; break; } /* Do write */ if (!(prevop->flags & FL_MBRW)) irmb_dout(prevop, Y); /* ADDEN */ if (!(prevop->flags & FL_ADDEN)) { if (prevop->flags & FL_MBRW) irmb_latch = irmb_din(prevop); else irmb_latch = Y; } } profiler_mark(PROFILER_END); logerror("%d instructions for Mathbox \n", icount); #if IR_TIMING if (irmb_running == 0) { mame_timer_adjust(irmb_timer, scale_up_mame_time(MAME_TIME_IN_HZ(12000000), icount), 0, time_zero); logerror("mb start "); IR_CPU_STATE; } else { logerror("mb start [busy!] "); IR_CPU_STATE; mame_timer_adjust(irmb_timer, scale_up_mame_time(MAME_TIME_IN_NSEC(200), icount), 0, time_zero); } #else cpunum_set_input_line(0, M6809_FIRQ_LINE, ASSERT_LINE); #endif irmb_running=1; } #if DISASSEMBLE_MB_ROM static void disassemble_instruction(irmb_ops *op) { int lp; if (i==0) logerror(" Address a b func stor: Q :Y, R, S RDCSAESM da m rs\n"); logerror("%04X : ",i); logerror("%X ",op->areg); logerror("%X ",op->breg); lp=(op->func & 0x38)>>3; if ((lp&1)==0) lp|=1; else if((op->flags & FL_DIV) != 0) lp&=6; else logerror("*"); switch (lp) { case 0: logerror("ADD "); break; case 1: logerror("SUBR "); break; case 2: logerror("SUB "); break; case 3: logerror("OR "); break; case 4: logerror("AND "); break; case 5: logerror("AND "); break; case 6: logerror("XOR "); break; case 7: logerror("XNOR "); break; } switch ((op->func & 0x1c0)>>6) { case 0: logerror(" - : Q :F,"); break; case 1: logerror(" - : - :F,"); break; case 2: logerror(" R%x: - :A,",op->breg); break; case 3: logerror(" R%x: - :F,",op->breg); break; case 4: logerror(">>R%x:>>Q:F,",op->breg); break; case 5: logerror(">>R%x: - :F,",op->breg); break; case 6: logerror("<breg); break; case 7: logerror("<breg); break; } lp=(op->func & 0x7); if ((lp&2)==0) lp|=2; else if((op->flags & FL_MULT) == 0) lp&=5; else logerror("*"); switch (lp) { case 0: logerror("R%x, Q ",op->areg); break; case 1: logerror("R%x,R%x ",op->areg,op->breg); break; case 2: logerror("00, Q "); break; case 3: logerror("00,R%x ",op->breg); break; case 4: logerror("00,R%x ",op->areg); break; case 5: logerror(" D,R%x ",op->areg); break; case 6: logerror(" D, Q "); break; case 7: logerror(" D,00 "); break; } for (lp=0;lp<8;lp++) if (op->flags & (0x80>>lp)) logerror("1"); else logerror("0"); logerror(" %02X ",op->diradd); logerror("%X\n",op->ramsel); if (op->jtype) { logerror(" "); switch (op->jtype) { case 1: logerror("BO "); break; case 2: logerror("BZ "); break; case 3: logerror("BH "); break; case 4: logerror("BL "); break; case 5: logerror("B "); break; case 6: logerror("Cl "); break; case 7: logerror("Return\n\n"); break; } if (op->jtype != 7) logerror(" %04X \n",op->nxtadd); if (op->jtype == 5) logerror("\n"); } } } #endif