/*************************************************************************** cubeqcpu.c Implementation of the Cube Quest AM2901-based CPUs TODO: * Tidy up diassembly (split into different files?) ***************************************************************************/ #include "debugger.h" #include "cubeqcpu.h" #include "driver.h" /*************************************************************************** CONSTANTS ***************************************************************************/ /* Am2901 Instruction Fields */ static const char *const ins[] = { "ADD ", "SUBR ", "SUBS ", "OR ", "AND ", "NOTRS", "EXOR ", "EXNOR", }; static const char *const src[] = { "A,Q", "A,B", "0,Q", "0,B", "0,A", "D,A", "D,Q", "D,0", }; static const char *const dst[] = { "QREG ", "NOP ", "RAMA ", "RAMF ", "RAMQD", "RAMD ", "RAMQU", "RAMU ", }; enum alu_src { AQ = 0, AB = 1, ZQ = 2, ZB = 3, ZA = 4, DA = 5, DQ = 6, DZ = 7, }; enum alu_ins { ADD = 0, SUBR = 1, SUBS = 2, OR = 3, AND = 4, NOTRS = 5, EXOR = 6, EXNOR = 7, }; enum alu_dst { QREG = 0, NOP = 1, RAMA = 2, RAMF = 3, RAMQD = 4, RAMD = 5, RAMQU = 6, RAMU = 7, }; /*************************************************************************** MACROS ***************************************************************************/ #define _BIT(x, n) ((x) & (1 << (n))) /*************************************************************************** STRUCTURES & TYPEDEFS ***************************************************************************/ typedef struct { /* AM2901 internals */ UINT16 ram[16]; UINT16 q; UINT16 f; UINT16 y; UINT32 cflag; UINT32 vflag; UINT8 pc; /* 2 x LS161 @ 6E, 6F */ UINT16 platch; UINT8 rtnlatch; /* LS374 @ 5F */ UINT8 adrcntr; /* 2 x LS161 */ UINT16 adrlatch; UINT16 dinlatch; UINT16 ramwlatch; UINT16 *sram; int prev_ipram; int prev_ipwrt; cubeqst_dac_w_func dac_w; UINT16 *sound_data; const device_config *device; const address_space *program; int icount; } cquestsnd_state; typedef struct { /* AM2901 internals */ UINT16 ram[16]; UINT16 q; UINT16 f; UINT16 y; UINT32 cflag; UINT32 vflag; UINT16 pc; /* 12-bit, but only 9 used */ UINT8 seqcnt; /* 4-bit counter */ UINT8 dsrclatch; UINT8 rsrclatch; UINT16 dynaddr; /* LS374 at 2D, 8D */ UINT16 dyndata; /* LS374 at 10B, 9B */ UINT16 yrlatch; /* LS374 at 9D, 10D */ UINT16 ydlatch; /* LS374 at 9C, 10C */ UINT16 dinlatch; UINT8 divreg; /* LS74 at ? */ UINT16 linedata; UINT16 lineaddr; UINT16 *dram; UINT16 *sram; UINT8 prev_dred; UINT8 prev_dwrt; UINT8 wc; UINT8 rc; UINT8 clkcnt; const device_config *device; const device_config *lindevice; const address_space *program; int icount; } cquestrot_state; typedef struct { /* 12-bit AM2901 internals */ UINT16 ram[16]; UINT16 q; UINT16 f; UINT16 y; UINT32 cflag; UINT32 vflag; UINT8 pc[2]; /* Two program counters; one for FG, other for BG */ UINT16 seqcnt; /* 12-bit */ UINT16 clatch; /* LS374 at 9E and 1-bit FF */ UINT8 zlatch; /* LS374 at 4H */ UINT16 xcnt; UINT16 ycnt; UINT8 sreg; UINT16 fadlatch; UINT16 badlatch; UINT16 sramdlatch; UINT8 fglatch; UINT8 bglatch; UINT8 gt0reg; UINT8 fdxreg; UINT32 field; UINT32 clkcnt; /* RAM */ UINT16 *sram; UINT8 *ptr_ram; UINT32 *e_stack; UINT32 *o_stack; const device_config *device; const device_config *rotdevice; const address_space *program; int icount; } cquestlin_state; /*************************************************************************** MEMORY ACCESSORS FOR 68000 ***************************************************************************/ WRITE16_DEVICE_HANDLER( cubeqcpu_sndram_w ) { cquestsnd_state *cpustate = device->token; COMBINE_DATA(&cpustate->sram[offset]); } READ16_DEVICE_HANDLER( cubeqcpu_sndram_r ) { cquestsnd_state *cpustate = device->token; return cpustate->sram[offset]; } WRITE16_DEVICE_HANDLER( cubeqcpu_rotram_w ) { cquestrot_state *cpustate = device->token; COMBINE_DATA(&cpustate->dram[offset]); } READ16_DEVICE_HANDLER( cubeqcpu_rotram_r ) { cquestrot_state *cpustate = device->token; return cpustate->dram[offset]; } /*************************************************************************** SOUND INITIALIZATION AND SHUTDOWN ***************************************************************************/ static STATE_POSTLOAD( cquestsnd_postload ) { } static void cquestsnd_state_register(const device_config *device) { cquestsnd_state *cpustate = device->token; state_save_register_device_item_array(device, 0, cpustate->ram); state_save_register_device_item(device, 0, cpustate->q); state_save_register_device_item(device, 0, cpustate->f); state_save_register_device_item(device, 0, cpustate->y); state_save_register_device_item(device, 0, cpustate->cflag); state_save_register_device_item(device, 0, cpustate->vflag); state_save_register_device_item(device, 0, cpustate->pc); state_save_register_device_item(device, 0, cpustate->platch); state_save_register_device_item(device, 0, cpustate->rtnlatch); state_save_register_device_item(device, 0, cpustate->adrcntr); state_save_register_device_item(device, 0, cpustate->adrlatch); state_save_register_device_item(device, 0, cpustate->dinlatch); state_save_register_device_item(device, 0, cpustate->ramwlatch); state_save_register_device_item(device, 0, cpustate->prev_ipram); state_save_register_device_item(device, 0, cpustate->prev_ipwrt); state_save_register_postload(device->machine, cquestsnd_postload, (void *)device); } static CPU_INIT( cquestsnd ) { cquestsnd_state *cpustate = device->token; cubeqst_snd_config* _config = (cubeqst_snd_config*)device->static_config; memset(cpustate, 0, sizeof(*cpustate)); cpustate->dac_w = _config->dac_w; cpustate->sound_data = (UINT16*)memory_region(device->machine, _config->sound_data_region); cpustate->device = device; cpustate->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM); /* Allocate RAM shared with 68000 */ cpustate->sram = auto_malloc(4096); cquestsnd_state_register(device); } static CPU_RESET( cquestsnd ) { cquestsnd_state *cpustate = device->token; cpustate->pc = 0; } static CPU_EXIT( cquestsnd ) { } /*************************************************************************** ROTATE INITIALIZATION AND SHUTDOWN ***************************************************************************/ static STATE_POSTLOAD( cquestrot_postload ) { } static void cquestrot_state_register(const device_config *device) { cquestrot_state *cpustate = device->token; state_save_register_device_item_array(device, 0, cpustate->ram); state_save_register_device_item(device, 0, cpustate->q); state_save_register_device_item(device, 0, cpustate->f); state_save_register_device_item(device, 0, cpustate->y); state_save_register_device_item(device, 0, cpustate->cflag); state_save_register_device_item(device, 0, cpustate->vflag); state_save_register_device_item(device, 0, cpustate->pc); state_save_register_device_item(device, 0, cpustate->seqcnt); state_save_register_device_item(device, 0, cpustate->dsrclatch); state_save_register_device_item(device, 0, cpustate->rsrclatch); state_save_register_device_item(device, 0, cpustate->dynaddr); state_save_register_device_item(device, 0, cpustate->dyndata); state_save_register_device_item(device, 0, cpustate->yrlatch); state_save_register_device_item(device, 0, cpustate->ydlatch); state_save_register_device_item(device, 0, cpustate->dinlatch); state_save_register_device_item(device, 0, cpustate->divreg); state_save_register_device_item(device, 0, cpustate->linedata); state_save_register_device_item(device, 0, cpustate->lineaddr); state_save_register_device_item(device, 0, cpustate->prev_dred); state_save_register_device_item(device, 0, cpustate->prev_dwrt); state_save_register_device_item(device, 0, cpustate->wc); state_save_register_device_item_pointer(device, 0, cpustate->dram, 16384); state_save_register_device_item_pointer(device, 0, cpustate->sram, 2048); state_save_register_postload(device->machine, cquestrot_postload, (void *)device); } static CPU_INIT( cquestrot ) { const cubeqst_rot_config *rotconfig = device->static_config; cquestrot_state *cpustate = device->token; memset(cpustate, 0, sizeof(*cpustate)); /* Allocate RAM */ cpustate->dram = auto_malloc(16384 * sizeof(UINT16)); /* Shared with 68000 */ cpustate->sram = auto_malloc(2048 * sizeof(UINT16)); /* Private */ cpustate->device = device; cpustate->lindevice = cputag_get_cpu(device->machine, rotconfig->lin_cpu_tag); cpustate->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM); cquestrot_state_register(device); } static CPU_RESET( cquestrot ) { cquestrot_state *cpustate = device->token; cpustate->pc = 0; cpustate->wc = 0; cpustate->prev_dred = 1; cpustate->prev_dwrt = 1; } static CPU_EXIT( cquestrot ) { } /*************************************************************************** LINE DRAWER INITIALIZATION AND SHUTDOWN ***************************************************************************/ #define FOREGROUND 0 #define BACKGROUND 1 #define ODD_FIELD 0 #define EVEN_FIELD 1 static STATE_POSTLOAD( cquestlin_postload ) { } static void cquestlin_state_register(const device_config *device) { cquestlin_state *cpustate = device->token; state_save_register_device_item_array(device, 0, cpustate->ram); state_save_register_device_item(device, 0, cpustate->q); state_save_register_device_item(device, 0, cpustate->f); state_save_register_device_item(device, 0, cpustate->y); state_save_register_device_item(device, 0, cpustate->cflag); state_save_register_device_item(device, 0, cpustate->vflag); state_save_register_device_item(device, 0, cpustate->pc[0]); state_save_register_device_item(device, 0, cpustate->pc[1]); state_save_register_device_item(device, 0, cpustate->seqcnt); state_save_register_device_item(device, 0, cpustate->clatch); state_save_register_device_item(device, 0, cpustate->zlatch); state_save_register_device_item(device, 0, cpustate->xcnt); state_save_register_device_item(device, 0, cpustate->ycnt); state_save_register_device_item(device, 0, cpustate->sreg); state_save_register_device_item(device, 0, cpustate->fadlatch); state_save_register_device_item(device, 0, cpustate->badlatch); state_save_register_device_item(device, 0, cpustate->sramdlatch); state_save_register_device_item(device, 0, cpustate->fglatch); state_save_register_device_item(device, 0, cpustate->bglatch); state_save_register_device_item(device, 0, cpustate->gt0reg); state_save_register_device_item(device, 0, cpustate->fdxreg); state_save_register_device_item(device, 0, cpustate->field); state_save_register_device_item(device, 0, cpustate->clkcnt); state_save_register_device_item_pointer(device, 0, cpustate->sram, 4096); state_save_register_device_item_pointer(device, 0, cpustate->ptr_ram, 1024); state_save_register_device_item_pointer(device, 0, cpustate->e_stack, 32768); state_save_register_device_item_pointer(device, 0, cpustate->o_stack, 32768); state_save_register_postload(device->machine, cquestlin_postload, (void *)device); } static CPU_INIT( cquestlin ) { const cubeqst_lin_config *linconfig = device->static_config; cquestlin_state *cpustate = device->token; memset(cpustate, 0, sizeof(*cpustate)); /* Allocate RAM */ cpustate->sram = auto_malloc(4096 * sizeof(UINT16)); /* Shared with rotate CPU */ cpustate->ptr_ram = auto_malloc(1024); /* Pointer RAM */ cpustate->e_stack = auto_malloc(32768 * sizeof(UINT32)); /* Stack DRAM: 32kx20 */ cpustate->o_stack = auto_malloc(32768 * sizeof(UINT32)); /* Stack DRAM: 32kx20 */ cpustate->device = device; cpustate->rotdevice = cputag_get_cpu(device->machine, linconfig->rot_cpu_tag); cpustate->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM); cquestlin_state_register(device); } static CPU_RESET( cquestlin ) { cquestlin_state *cpustate = device->token; cpustate->clkcnt = 0; cpustate->pc[FOREGROUND] = 0; cpustate->pc[BACKGROUND] = 0x80; } static CPU_EXIT( cquestlin ) { } /*************************************************************************** SOUND CORE EXECUTION LOOP ***************************************************************************/ #define SND_PC (cpustate->pc) #define SND_DATA_IN (_ramen ? cpustate->sound_data[cpustate->platch] : cpustate->dinlatch) enum snd_latch_type { PLTCH = 0, DAC = 1, ADLATCH = 2, }; static int do_sndjmp(cquestsnd_state *cpustate, int jmp) { switch (jmp) { /* JUMP */ case 0: return 1; /* MSB */ case 2: return cpustate->f & 0x8000 ? 0 : 1; /* !MSB */ case 3: return cpustate->f & 0x8000 ? 1 : 0; /* ZERO */ case 5: return cpustate->f == 0 ? 0 : 1; /* OVR */ case 6: return cpustate->vflag ? 0 : 1; /* LOOP */ case 7: return cpustate->adrcntr & 0x80 ? 0: 1; } return 0; } static CPU_EXECUTE( cquestsnd ) { cquestsnd_state *cpustate = device->token; int calldebugger = ((device->machine->debug_flags & DEBUG_FLAG_ENABLED) != 0); cpustate->icount = cycles; /* Core execution loop */ do { /* Decode the instruction */ UINT64 inst = memory_decrypted_read_qword(cpustate->program, SND_PC << 3); UINT32 inslow = inst & 0xffffffff; UINT32 inshig = inst >> 32; int t = (inshig >> 24) & 0xff; int b = (inshig >> 20) & 0xf; int a = (inshig >> 16) & 0xf; int ci = (inshig >> 15) & 1; int i5_3 = (inshig >> 12) & 7; int _ramen = (inshig >> 11) & 1; int i2_0 = (inshig >> 8) & 7; int rtnltch = (inshig >> 7) & 1; int jmp = (inshig >> 4) & 7; int inca = (inshig >> 3) & 1; int i8_6 = (inshig >> 0) & 7; int _ipram = (inslow >> 31) & 1; int _ipwrt = (inslow >> 30) & 1; int latch = (inslow >> 28) & 3; int rtn = (inslow >> 27) & 1; int _rin = (inslow >> 26) & 1; if (calldebugger) debugger_instruction_hook(device, cpustate->pc); /* Don't think this matters, but just in case */ if (rtn) t = cpustate->rtnlatch; /* Handle the AM2901 ALU instruction */ { UINT16 r = 0; UINT16 s = 0; UINT32 res = 0; UINT32 cflag = 0; UINT32 vflag = 0; /* Determine the ALU sources */ switch (i2_0) { case AQ: r = cpustate->ram[a]; s = cpustate->q; break; case AB: r = cpustate->ram[a]; s = cpustate->ram[b]; break; case ZQ: r = 0; s = cpustate->q; break; case ZB: r = 0; s = cpustate->ram[b]; break; case ZA: r = 0; s = cpustate->ram[a]; break; case DA: r = SND_DATA_IN; s = cpustate->ram[a]; break; case DQ: r = SND_DATA_IN; s = cpustate->q; break; case DZ: r = SND_DATA_IN; s = 0; break; } /* Perform the ALU operation */ switch (i5_3) { case ADD: res = r + s + ci; cflag = (res >> 16) & 1; vflag = (((r & 0x7fff) + (s & 0x7fff) + ci) >> 15) ^ cflag; break; case SUBR: res = ~r + s + ci; cflag = (res >> 16) & 1; vflag = (((s & 0x7fff) + (~r & 0x7fff) + ci) >> 15) ^ cflag; break; case SUBS: res = r + ~s + ci; cflag = (res >> 16) & 1; vflag = (((r & 0x7fff) + (~s & 0x7fff) + ci) >> 15) ^ cflag; break; case OR: res = r | s; break; case AND: res = r & s; break; case NOTRS: res = ~r & s; break; case EXOR: res = r ^ s; break; case EXNOR: res = ~(r ^ s); break; } cpustate->f = res; cpustate->cflag = cflag; cpustate->vflag = vflag; switch (i8_6) { case QREG: cpustate->q = cpustate->f; cpustate->y = cpustate->f; break; case NOP: cpustate->y = cpustate->f; break; case RAMA: cpustate->y = cpustate->ram[a]; cpustate->ram[b] = cpustate->f; break; case RAMF: cpustate->ram[b] = cpustate->f; cpustate->y = cpustate->f; break; case RAMQD: { UINT16 qin; cpustate->ram[b] = (_rin ? 0 : 0x8000) | (cpustate->f >> 1); cpustate->q >>= 1; cpustate->y = cpustate->f; /* When right shifting Q, we need to OR in a value */ qin = (((cpustate->y >> 15) ^ (cpustate->y >> 1)) & 1) ? 0 : 0x8000; cpustate->q |= qin; break; } case RAMD: cpustate->ram[b] = (_rin ? 0 : 0x8000) | (cpustate->f >> 1); cpustate->y = cpustate->f; break; case RAMQU: cpustate->ram[b] = (cpustate->f << 1) | (_rin ? 0 : 0x0001); cpustate->q <<= 1; cpustate->y = cpustate->f; break; case RAMU: cpustate->ram[b] = (cpustate->f << 1) | (_rin ? 0 : 0x0001); cpustate->y = cpustate->f; break; } } /* Now handle any SRAM accesses from the previous cycle */ if (!cpustate->prev_ipram) { UINT16 addr = cpustate->adrlatch | (cpustate->adrcntr & 0x7f); if (!cpustate->prev_ipwrt) cpustate->sram[addr] = cpustate->ramwlatch; else cpustate->dinlatch = cpustate->sram[addr]; } /* Handle latches */ if (latch == PLTCH) { cpustate->platch = ((t & 3) << 9) | ((cpustate->y >> 6) & 0x1ff); } else if (latch == DAC) { cpustate->dac_w(cpustate->device, (cpustate->y & 0xfff0) | ((cpustate->adrcntr >> 3) & 0xf)); } else if (latch == ADLATCH) { /* Load the SRAM address counter - this value is instantly loaded */ cpustate->adrcntr = cpustate->y & 0x7f; /* Also load the SRAM address latch */ cpustate->adrlatch = cpustate->y & 0x780; } /* Check for jump/return */ if ( do_sndjmp(cpustate, jmp) ) cpustate->pc = rtn ? cpustate->rtnlatch : t; else cpustate->pc++; /* Load the return latch? (Obviously a load and a ret in the same cycle are invalid) */ if (rtnltch) cpustate->rtnlatch = t; /* Only increment the sound counter if not loading */ if (inca && latch != ADLATCH) cpustate->adrcntr++; /* Latch data for a RAM write (do actual write on the next cycle) */ if (!_ipwrt) cpustate->ramwlatch = cpustate->y; /* Save level sensitive bits */ cpustate->prev_ipram = _ipram; cpustate->prev_ipwrt = _ipwrt; cpustate->icount--; } while (cpustate->icount > 0); return cycles - cpustate->icount; } /*************************************************************************** SOUND DISASSEMBLY HOOK ***************************************************************************/ static CPU_DISASSEMBLE( cquestsnd ) { static const char *const jmps[] = { "JUMP ", " ", "JMSB ", "JNMSB", " ", "JZERO", "JOVR ", "JLOOP", }; static const char *const latches[] = { "PLTCH ", "DAC ", "ADLATCH", " ", }; UINT64 inst = BIG_ENDIANIZE_INT64(*(UINT64 *)oprom); UINT32 inslow = inst & 0xffffffff; UINT32 inshig = inst >> 32; int t = (inshig >> 24) & 0xff; int b = (inshig >> 20) & 0xf; int a = (inshig >> 16) & 0xf; int ci = (inshig >> 15) & 1; int i5_3 = (inshig >> 12) & 7; int _ramen = (inshig >> 11) & 1; int i2_0 = (inshig >> 8) & 7; int rtnltch = (inshig >> 7) & 1; int jmp = (inshig >> 4) & 7; int inca = (inshig >> 3) & 1; int i8_6 = (inshig >> 0) & 7; int _ipram = (inslow >> 31) & 1; int _ipwrt = (inslow >> 30) & 1; int latch = (inslow >> 28) & 3; int rtn = (inslow >> 27) & 1; int _rin = (inslow >> 26) & 1; sprintf(buffer, "%s %s %s %x,%x,%c %.2x %s %s %.2x %s %s %s %c %c %c\n", ins[i5_3], src[i2_0], dst[i8_6], a, b, ci ? 'C' : ' ', _rin, jmps[jmp], rtn ? "RET" : " ", t, latches[latch], rtnltch ? "RTLATCH" : " ", _ramen ? "PROM" : "RAM ", _ipram ? ' ' : 'R', _ipwrt ? ' ' : 'W', inca ? 'I' : ' '); return 1 | DASMFLAG_SUPPORTED; } /*************************************************************************** ROTATE CORE EXECUTION LOOP ***************************************************************************/ #define ROT_PC (cpustate->pc & 0x1ff) enum rot_spf { SPF_UNUSED0 = 0, SPF_UNUSED1 = 1, SPF_OP = 2, SPF_RET = 3, SPF_SQLTCH = 4, SPF_SWRT = 5, SPF_DIV = 6, SPF_MULT = 7, SPF_DRED = 8, SPF_DWRT = 9, }; enum rot_yout { YOUT_UNUSED0 = 0, YOUT_UNUSED1 = 1, YOUT_Y2LDA = 2, YOUT_Y2LDD = 3, YOUT_Y2DAD = 4, YOUT_Y2DYN = 5, YOUT_Y2R = 6, YOUT_Y2D = 7, }; /* Sync is asserted for the duration of every fourth cycle */ /* The Dynamic RAM latch clocks in a value at the end of this cycle */ /* So CPU waits for sync before reading from DRAM */ INLINE int do_rotjmp(cquestrot_state *cpustate, int jmp) { int ret = 0; switch (jmp & 7) { /* */ case 0: ret = 0; break; /* SEQ */ case 1: ret = (cpustate->seqcnt == 0xf); break; /* CAROUT */ case 2: ret = cpustate->cflag; break; /* SYNC */ case 3: ret = !(cpustate->clkcnt & 0x3); break; /* LDWAIT */ case 4: ret = 0; break; /* MSB */ case 5: ret = BIT(cpustate->f, 15); break; /* >=1 */ case 6: ret = (!_BIT(cpustate->f, 15) && !(cpustate->f == 0)); break; /* ZERO */ case 7: ret = (cpustate->f == 0); break; } return !(!ret ^ BIT(jmp, 3)); } #define ROT_SRAM_ADDRESS ((cpustate->dsrclatch & 2) ? cpustate->yrlatch : (cpustate->rsrclatch | 0x700)) static CPU_EXECUTE( cquestrot ) { cquestrot_state *cpustate = device->token; cquestlin_state *lincpustate = cpustate->lindevice->token; int calldebugger = ((device->machine->debug_flags & DEBUG_FLAG_ENABLED) != 0); cpustate->icount = cycles; /* Core execution loop */ do { /* Decode the instruction */ UINT64 inst = memory_decrypted_read_qword(cpustate->program, ROT_PC << 3); UINT32 inslow = inst & 0xffffffff; UINT32 inshig = inst >> 32; int t = (inshig >> 20) & 0xfff; int jmp = (inshig >> 16) & 0xf; int spf = (inshig >> 12) & 0xf; int rsrc = (inshig >> 11) & 0x1; int yout = (inshig >> 8) & 0x7; int sel = (inshig >> 6) & 0x3; int dsrc = (inshig >> 4) & 0x3; int b = (inshig >> 0) & 0xf; int a = (inslow >> 28) & 0xf; int i8_6 = (inslow >> 24) & 0x7; int ci = (inslow >> 23) & 0x1; int i5_3 = (inslow >> 20) & 0x7; int _sex = (inslow >> 19) & 0x1; int i2_0 = (inslow >> 16) & 0x7; int dsrclatch; UINT16 data_in = 0xffff; if (calldebugger) debugger_instruction_hook(device, ROT_PC); /* Handle DRAM accesses - I ought to check this... */ if (!(cpustate->clkcnt & 3)) { if (cpustate->wc) { cpustate->wc = 0; cpustate->dram[cpustate->dynaddr & 0x3fff] = cpustate->dyndata; } if (cpustate->rc) { cpustate->rc = 0; cpustate->dinlatch = cpustate->dram[cpustate->dynaddr & 0x3fff]; } } /* Flag pending DRAM accesses */ if (!cpustate->prev_dwrt) cpustate->wc = 1; else if (!cpustate->prev_dred) cpustate->rc = 1; /* What's on the D-Bus? */ if (~cpustate->dsrclatch & 0x10) data_in = cpustate->dinlatch; else if (~cpustate->dsrclatch & 0x20) data_in = cpustate->sram[ROT_SRAM_ADDRESS]; else if (~cpustate->dsrclatch & 0x40) data_in = cpustate->ydlatch; else if (~cpustate->dsrclatch & 0x80) data_in = t & 0xfff; /* What's on the T-Bus? */ if ((spf == SPF_RET) && (cpustate->dsrclatch & 0x80)) t = data_in; else if (spf == SPF_OP) t = (t & ~0xf) | (data_in >> 12); if (~cpustate->dsrclatch & 1) cpustate->sram[ROT_SRAM_ADDRESS] = data_in; /* Sign extend ALU input? */ if (!_sex) data_in = (data_in & ~0xf000) | ((data_in & 0x800) ? 0xf000 : 0); /* No do the ALU operation */ { UINT16 r = 0; UINT16 s = 0; UINT32 res = 0; UINT32 cflag = 0; UINT32 vflag = 0; /* First, determine correct I1 bit */ if ((spf == SPF_MULT) && !_BIT(cpustate->q, 0)) i2_0 |= 2; /* Determine the ALU sources */ switch (i2_0) { case 0: r = cpustate->ram[a]; s = cpustate->q; break; case 1: r = cpustate->ram[a]; s = cpustate->ram[b]; break; case 2: r = 0; s = cpustate->q; break; case 3: r = 0; s = cpustate->ram[b]; break; case 4: r = 0; s = cpustate->ram[a]; break; case 5: r = data_in; s = cpustate->ram[a]; break; case 6: r = data_in; s = cpustate->q; break; case 7: r = data_in; s = 0; break; } /* Next, determine the I3 and carry bits */ if ((spf == SPF_DIV) && cpustate->divreg) { i5_3 |= 1; ci = 1; } /* Perform the ALU operation */ switch (i5_3) { case ADD: res = r + s + ci; cflag = (res >> 16) & 1; vflag = (((r & 0x7fff) + (s & 0x7fff) + ci) >> 15) ^ cflag; break; case SUBR: res = ~r + s + ci; cflag = (res >> 16) & 1; vflag = (((s & 0x7fff) + (~r & 0x7fff) + ci) >> 15) ^ cflag; break; case SUBS: res = r + ~s + ci; cflag = (res >> 16) & 1; vflag = (((r & 0x7fff) + (~s & 0x7fff) + ci) >> 15) ^ cflag; break; case OR: res = r | s; break; case AND: res = r & s; break; case NOTRS: res = ~r & s; break; case EXOR: res = r ^ s; break; case EXNOR: res = ~(r ^ s); break; } cpustate->f = res; cpustate->cflag = cflag; cpustate->vflag = vflag; switch (i8_6) { case QREG: cpustate->q = cpustate->f; cpustate->y = cpustate->f; break; case NOP: cpustate->y = cpustate->f; break; case RAMA: cpustate->y = cpustate->ram[a]; cpustate->ram[b] = cpustate->f; break; case RAMF: cpustate->ram[b] = cpustate->f; cpustate->y = cpustate->f; break; case RAMQD: { UINT16 q0 = cpustate->q & 1; UINT16 r0 = cpustate->f & 1; UINT16 q15 = 0; UINT16 r15 = 0; /* Determine Q15 and RAM15 */ switch (sel) { case 0: q15 = r15 = 0; break; case 1: q15 = r15 = 0x8000; break; case 2: q15 = q0 << 15; r15 = r0 << 15; break; case 3: q15 = r0 << 15; r15 = (cpustate->vflag ^ BIT(cpustate->f, 15)) << 15; break; } cpustate->ram[b] = r15 | (cpustate->f >> 1); cpustate->q = q15 | (cpustate->q >> 1); cpustate->y = cpustate->f; break; } case RAMD: { UINT16 r0 = cpustate->f & 1; UINT16 r15 = 0; switch (sel) { case 0: r15 = 0; break; case 1: r15 = 0x8000; break; case 2: r15 = r0 << 15; break; case 3: r15 = (cpustate->vflag ^ BIT(cpustate->f, 15)) << 15; break; } cpustate->ram[b] = r15 | (cpustate->f >> 1); cpustate->y = cpustate->f; break; } case RAMQU: { UINT16 q15 = BIT(cpustate->q, 15); UINT16 r15 = BIT(cpustate->f, 15); UINT16 q0 = 0; UINT16 r0 = 0; switch (sel) { case 0: q0 = 0; r0 = 0; break; case 1: q0 = 1; r0 = 1; break; case 2: q0 = q15; r0 = r15; break; case 3: { q0 = (spf == SPF_DIV) && !BIT(cpustate->f, 15); r0 = q15; break; } } cpustate->ram[b] = (cpustate->f << 1) | r0; cpustate->q = (cpustate->q << 1) | q0; cpustate->y = cpustate->f; break; } case RAMU: { UINT16 q15 = BIT(cpustate->q, 15); UINT16 r15 = BIT(cpustate->f, 15); UINT16 r0 = 0; switch (sel) { case 0: r0 = 0; break; case 1: r0 = 1; break; case 2: r0 = r15; break; case 3: r0 = q15; break; } cpustate->ram[b] = (cpustate->f << 1) | r0; cpustate->y = cpustate->f; break; } } } /* Check for jump */ if ( do_rotjmp(cpustate, jmp) ) cpustate->pc = t; else cpustate->pc = (cpustate->pc + 1) & 0xfff; /* Rising edge; update the sequence counter */ if (spf == SPF_SQLTCH) cpustate->seqcnt = t & 0xf; else if ( (spf == SPF_MULT) || (spf == SPF_DIV) ) cpustate->seqcnt = (cpustate->seqcnt + 1) & 0xf; /* Rising edge; write data source reg */ dsrclatch = (~(0x10 << dsrc) & 0xf0) | (rsrc ? 0x04 : 0x02) | !(spf == SPF_SWRT); /* R-latch is written on rising edge of dsrclatch bit 2 */ if (!_BIT(cpustate->dsrclatch, 2) && _BIT(dsrclatch, 2)) cpustate->rsrclatch = t & 0xff; cpustate->dsrclatch = dsrclatch; /* Handle latching on rising edge */ switch (yout) { case YOUT_Y2LDA: { cpustate->lineaddr = cpustate->y & 0xfff; break; } case YOUT_Y2LDD: { cpustate->linedata = ((t & 0xf) << 12) | (cpustate->y & 0xfff); lincpustate->sram[cpustate->lineaddr] = cpustate->linedata; break; } case YOUT_Y2DAD: cpustate->dynaddr = cpustate->y & 0x3fff; break; case YOUT_Y2DYN: cpustate->dyndata = cpustate->y & 0xffff; break; case YOUT_Y2R: cpustate->yrlatch = cpustate->y & 0x7ff; break; case YOUT_Y2D: cpustate->ydlatch = cpustate->y; break; } /* Clock in the divide register */ cpustate->divreg = (spf == SPF_DIV) && !_BIT(cpustate->f, 15); /* DRAM accessing */ cpustate->prev_dred = !(spf == SPF_DRED); cpustate->prev_dwrt = !(spf == SPF_DWRT); cpustate->clkcnt++; cpustate->icount--; } while (cpustate->icount > 0); return cycles - cpustate->icount; } /*************************************************************************** ROTATE DISASSEMBLY HOOK ***************************************************************************/ static CPU_DISASSEMBLE( cquestrot ) { static const char *const jmps[] = { " ", "JSEQ ", "JC ", "JSYNC ", "JLDWAIT", "JMSB ", "JGEONE ", "JZERO ", "JUMP ", "JNSEQ ", "JNC ", "JNSYNC ", "JNLDWAI", "JNMSB ", "JLTONE ", "JNZERO ", }; static const char *const youts[] = { " ", " ", "Y2LDA", "Y2LDD", "Y2DAD", "Y2DIN", "Y2R ", "Y2D ", }; static const char *const spfs[] = { " ", " ", "OP ", "RET ", "SQLTCH", "SWRT ", "DIV ", "MULT ", "DRED ", "DWRT ", "??? ", "??? ", "??? ", "??? ", "??? ", "??? " }; UINT64 inst = BIG_ENDIANIZE_INT64(*(UINT64 *)oprom); UINT32 inslow = inst & 0xffffffff; UINT32 inshig = inst >> 32; int t = (inshig >> 20) & 0xfff; int jmp = (inshig >> 16) & 0xf; int spf = (inshig >> 12) & 0xf; // int rsrc = (inshig >> 11) & 0x1; int yout = (inshig >> 8) & 0x7; int sel = (inshig >> 6) & 0x3; // int dsrc = (inshig >> 4) & 0x3; int b = (inshig >> 0) & 0xf; int a = (inslow >> 28) & 0xf; int i8_6 = (inslow >> 24) & 0x7; int ci = (inslow >> 23) & 0x1; int i5_3 = (inslow >> 20) & 0x7; // int _sex = (inslow >> 19) & 0x1; int i2_0 = (inslow >> 16) & 0x7; sprintf(buffer, "%s %s,%s %x,%x,%c %d %s %s %s %.2x\n", ins[i5_3], src[i2_0], dst[i8_6], a, b, ci ? 'C' : ' ', sel, jmps[jmp], youts[yout], spfs[spf], t); return 1 | DASMFLAG_SUPPORTED; } /*************************************************************************** LINE DRAWER CORE EXECUTION LOOP ***************************************************************************/ #define VISIBLE_FIELD !cpustate->field enum line_spf { LSPF_UNUSUED = 0, LSPF_FSTOP = 1, LSPF_SREG = 2, LSPF_FSTRT = 3, LSPF_PWRT = 4, LSPF_MULT = 5, LSPF_LSTOP = 6, LSPF_BRES = 7, }; enum line_latch { LLATCH_UNUSED = 0, LLATCH_SEQLATCH = 1, LLATCH_XLATCH = 2, LLATCH_YLATCH = 3, LLATCH_BADLATCH = 4, LLATCH_FADLATCH = 5, LLATCH_CLATCH = 6, LLATCH_ZLATCH = 7, }; enum sreg_bits { SREG_E0 = 0, SREG_DX_DY = 1, SREG_DY = 2, SREG_DX = 3, SREG_LE0 = 4, SREG_LDX_DY = 5, SREG_LDY = 6, SREG_LDX = 7, }; INLINE int do_linjmp(cquestlin_state *cpustate, int jmp) { int ret = 0; switch (jmp & 7) { /* */ case 0: ret = 0; break; /* MSB */ case 1: ret = BIT(cpustate->f, 11); break; /* SEQ */ case 2: ret = (cpustate->seqcnt == 0xfff); break; /* >0 */ case 3: ret = !(cpustate->f == 0) && !_BIT(cpustate->f, 11); break; /* CAROUT */ case 4: ret = (cpustate->cflag); break; /* ZERO */ case 5: ret = (cpustate->f == 0); break; } return !(!ret ^ BIT(jmp, 3)); } void cubeqcpu_swap_line_banks(const device_config *device) { cquestlin_state *cpustate = device->token; cpustate->field = cpustate->field ^ 1; } void cubeqcpu_clear_stack(const device_config *device) { cquestlin_state *cpustate = device->token; memset(&cpustate->ptr_ram[cpustate->field * 256], 0, 256); } UINT8 cubeqcpu_get_ptr_ram_val(const device_config *device, int i) { cquestlin_state *cpustate = device->token; return cpustate->ptr_ram[(VISIBLE_FIELD * 256) + i]; } UINT32* cubeqcpu_get_stack_ram(const device_config *device) { cquestlin_state *cpustate = device->token; if (VISIBLE_FIELD == ODD_FIELD) return cpustate->o_stack; else return cpustate->e_stack; } static CPU_EXECUTE( cquestlin ) { #define LINE_PC ((cpustate->pc[prog] & 0x7f) | ((prog == BACKGROUND) ? 0x80 : 0)) cquestlin_state *cpustate = device->token; cquestrot_state *rotcpustate = cpustate->rotdevice->token; int calldebugger = ((device->machine->debug_flags & DEBUG_FLAG_ENABLED) != 0); UINT32 *stack_ram; UINT8 *ptr_ram; /* Check the field and set the stack/pointer RAM pointers appropriately */ if (cpustate->field == ODD_FIELD) { stack_ram = cpustate->o_stack; ptr_ram = &cpustate->ptr_ram[0]; } else { stack_ram = cpustate->e_stack; ptr_ram = &cpustate->ptr_ram[0x100]; } cpustate->icount = cycles; /* Core execution loop */ do { /* Are we executing the foreground or backgroud program? */ int prog = (cpustate->clkcnt & 3) ? BACKGROUND : FOREGROUND; UINT64 inst = memory_decrypted_read_qword(cpustate->program, LINE_PC << 3); UINT32 inslow = inst & 0xffffffff; UINT32 inshig = inst >> 32; int t = (inshig >> 24) & 0xff; int jmp = (inshig >> 20) & 0xf; int latch = (inshig >> 16) & 0x7; int op = (inshig >> 15) & 0x1; int spf = (inshig >> 12) & 0x7; int b = (inshig >> 8) & 0xf; int a = (inshig >> 4) & 0xf; int i8_6 = (inshig >> 0) & 0x7; int ci = (inslow >> 31) & 0x1; int i5_3 = (inslow >> 28) & 0x7; int _pbcs = (inslow >> 27) & 0x1; int i2_0 = (inslow >> 24) & 0x7; UINT16 data_in = 0; if (calldebugger) debugger_instruction_hook(device, cpustate->pc[prog]); /* Handle accesses to and from shared SRAM */ if (prog == FOREGROUND) { if (!_BIT(cpustate->fglatch, 5)) data_in = cpustate->sram[cpustate->fadlatch]; else data_in = rotcpustate->linedata; } else { if (!_BIT(cpustate->bglatch, 4)) cpustate->sram[cpustate->badlatch] = cpustate->sramdlatch; else if (_BIT(cpustate->bglatch, 2)) data_in = cpustate->sram[cpustate->badlatch]; else data_in = rotcpustate->linedata; } /* Handle a write to stack RAM (/DOWRT) */ if ((cpustate->clkcnt & 3) == 1) { if (_BIT(cpustate->fglatch, 4) && (cpustate->ycnt < 256)) { /* 20-bit words */ UINT32 data; UINT16 h = cpustate->xcnt; UINT8 v = cpustate->ycnt & 0xff; /* Clamp H between 0 and 319 */ if (h >= 320) h = (h & 0x800) ? 0 : 319; /* Stack word type depends on STOP/#START bit */ if ( _BIT(cpustate->fglatch, 3) ) data = (0 << 19) | (h << 8) | cpustate->zlatch; else data = (1 << 19) | ((cpustate->clatch & 0x100) << 9) | (h << 8) | (cpustate->clatch & 0xff); stack_ram[(v << 7) | (ptr_ram[v] & 0x7f)] = data; /* Also increment the pointer RAM entry. Note that it cannot exceed 128 */ ptr_ram[v] = (ptr_ram[v] + 1) & 0x7f; } } /* Override T3-0? */ if (op) t = (t & ~0xf) | (data_in >> 12); /* Determine the correct I1 bit */ if ((spf == LSPF_MULT) && !_BIT(cpustate->q, 0)) i2_0 |= 2; /* Determine A0 (BRESA0) */ if ((prog == FOREGROUND) && !_BIT(cpustate->fglatch, 2)) a |= cpustate->gt0reg; /* Now do the ALU operation */ { UINT16 r = 0; UINT16 s = 0; UINT16 res = 0; UINT32 cflag = 0; UINT32 vflag = 0; /* Determine the ALU sources */ switch (i2_0) { case 0: r = cpustate->ram[a]; s = cpustate->q; break; case 1: r = cpustate->ram[a]; s = cpustate->ram[b]; break; case 2: r = 0; s = cpustate->q; break; case 3: r = 0; s = cpustate->ram[b]; break; case 4: r = 0; s = cpustate->ram[a]; break; case 5: r = data_in; s = cpustate->ram[a]; break; case 6: r = data_in; s = cpustate->q; break; case 7: r = data_in; s = 0; break; } /* 12-bits */ r &= 0xfff; s &= 0xfff; /* Perform the 12-bit ALU operation */ switch (i5_3) { case ADD: res = r + s + ci; cflag = (res >> 12) & 1; vflag = (((r & 0x7ff) + (s & 0x7ff) + ci) >> 11) ^ cflag; break; case SUBR: res = (r ^ 0x0FFF) + s + ci; cflag = (res >> 12) & 1; vflag = (((s & 0x7ff) + (~r & 0x7ff) + ci) >> 11) ^ cflag; break; case SUBS: res = r + (s ^ 0x0FFF) + ci; cflag = (res >> 12) & 1; vflag = (((r & 0x7ff) + (~s & 0x7ff) + ci) >> 11) ^ cflag; break; case OR: res = r | s; break; case AND: res = r & s; break; case NOTRS: res = ~r & s; break; case EXOR: res = r ^ s; break; case EXNOR: res = ~(r ^ s); break; } cpustate->f = res & 0xfff; cpustate->cflag = cflag; cpustate->vflag = vflag; switch (i8_6) { case QREG: cpustate->q = cpustate->f; cpustate->y = cpustate->f; break; case NOP: cpustate->y = cpustate->f; break; case RAMA: cpustate->y = cpustate->ram[a]; cpustate->ram[b] = cpustate->f; break; case RAMF: cpustate->ram[b] = cpustate->f; cpustate->y = cpustate->f; break; case RAMQD: { UINT16 r11 = (BIT(cpustate->f, 11) ^ cpustate->vflag) ? 0x800 : 0; UINT16 q11 = (prog == BACKGROUND) ? 0x800 : 0; cpustate->ram[b] = r11 | (cpustate->f >> 1); cpustate->q = q11 | (cpustate->q >> 1); cpustate->y = cpustate->f; break; } case RAMD: { UINT16 r11 = (BIT(cpustate->f, 11) ^ cpustate->vflag) ? 0x800 : 0; cpustate->ram[b] = r11 | (cpustate->f >> 1); cpustate->y = cpustate->f; break; } case RAMQU: { /* Determine shift inputs */ UINT16 r0 = (prog == BACKGROUND); /* This should never happen - Q0 will be invalid */ cpustate->ram[b] = (cpustate->f << 1) | r0; cpustate->q = (cpustate->q << 1) | 0; cpustate->y = cpustate->f; break; } case RAMU: { UINT16 r0 = (prog == BACKGROUND); cpustate->ram[b] = (cpustate->f << 1) | r0; cpustate->y = cpustate->f; break; } } } /* Adjust program counter */ if ( do_linjmp(cpustate, jmp) ) cpustate->pc[prog] = t & 0x7f; else cpustate->pc[prog] = (cpustate->pc[prog] + 1) & 0x7f; if (prog == BACKGROUND) cpustate->pc[prog] |= 0x80; else { /* Handle events that happen during FG execution */ if (latch == LLATCH_XLATCH) cpustate->xcnt = cpustate->y & 0xfff; else { int _xcet; int mux_sel = (BIT(cpustate->sreg, SREG_DX_DY) << 1) | (BIT(cpustate->sreg, SREG_DX) ^ BIT(cpustate->sreg, SREG_DY)); if (mux_sel == 0) _xcet = !(spf == LSPF_BRES); else if (mux_sel == 1) _xcet = _BIT(cpustate->fglatch, 1); else if (mux_sel == 2) _xcet = !(cpustate->gt0reg && (spf == LSPF_BRES)); else _xcet = _BIT(cpustate->fglatch, 0); if (!_xcet) cpustate->xcnt = (cpustate->xcnt + (_BIT(cpustate->sreg, SREG_DX) ? 1 : -1)) & 0xfff; } if (latch == LLATCH_YLATCH) cpustate->ycnt = cpustate->y & 0xfff; else { int _ycet; int mux_sel = (BIT(cpustate->sreg, SREG_DX_DY) << 1) | (BIT(cpustate->sreg, SREG_DX) ^ BIT(cpustate->sreg, SREG_DY)); if (mux_sel == 0) _ycet = !(cpustate->gt0reg && (spf == LSPF_BRES)); else if (mux_sel == 1) _ycet = _BIT(cpustate->fglatch, 0); else if (mux_sel == 2) _ycet = !(spf == LSPF_BRES); else _ycet = _BIT(cpustate->fglatch, 1); if (!_ycet) cpustate->ycnt = (cpustate->ycnt + (_BIT(cpustate->sreg, SREG_DY) ? 1 : -1)) & 0xfff; } } if (latch == LLATCH_CLATCH) cpustate->clatch = cpustate->y & 0x1ff; else if (latch == LLATCH_ZLATCH) cpustate->zlatch = cpustate->y & 0xff; else if (latch == LLATCH_FADLATCH) cpustate->fadlatch = cpustate->y & 0xfff; else if (latch == LLATCH_BADLATCH) cpustate->badlatch = cpustate->y & 0xfff; /* What about the SRAM dlatch? */ if ( !_BIT(cpustate->bglatch, 5) ) cpustate->sramdlatch = ((t & 0xf) << 12) | (cpustate->y & 0x0fff); /* BG and FG latches */ if (prog == FOREGROUND) { int mux_sel = (!(spf == LSPF_FSTOP) << 1) | !(spf == LSPF_LSTOP); int dowrt; int start_stop; /* Handle the stack write and start/stop mux */ if (mux_sel == 0) { dowrt = 0; start_stop = 0; } else if (mux_sel == 1) { dowrt = cpustate->fdxreg ^ BIT(cpustate->sreg, SREG_DX); start_stop = cpustate->fdxreg; } else if (mux_sel == 2) { dowrt = BIT(cpustate->sreg, SREG_LDX) ^ BIT(cpustate->sreg, SREG_DX); start_stop = BIT(cpustate->sreg, SREG_DX); } else { dowrt = (spf == LSPF_BRES) && (_BIT(cpustate->sreg, SREG_DX_DY) || cpustate->gt0reg); start_stop = BIT(cpustate->sreg, SREG_DY); } cpustate->fglatch = (!(latch == LLATCH_FADLATCH) << 5) | (dowrt << 4) | (start_stop << 3) | (_pbcs << 2) | (!(spf == LSPF_BRES) << 1) | !(cpustate->gt0reg && (spf == LSPF_BRES)); } else { int _lpwrt = BIT(cpustate->bglatch, 5); cpustate->bglatch = (!(spf == LSPF_PWRT) << 5) | (_lpwrt << 4) | ((!_lpwrt || (!(spf == LSPF_PWRT) && (latch == LLATCH_BADLATCH))) << 2); } /* Clock-in another bit into the sign bit shifter? */ if (spf == LSPF_SREG) { /* The sign bit is inverted */ cpustate->sreg = (cpustate->sreg << 1) | !BIT(cpustate->f, 11); /* Also latch the >0 reg */ cpustate->gt0reg = !(cpustate->f == 0) && !_BIT(cpustate->f, 11); } else if (spf == LSPF_FSTRT) { cpustate->fdxreg = BIT(cpustate->sreg, 3); } /* Load or increment sequence counter? */ if (latch == LLATCH_SEQLATCH) { cpustate->seqcnt = cpustate->y & 0xfff; } else if (spf == LSPF_BRES) { cpustate->seqcnt = (cpustate->seqcnt + 1) & 0xfff; /* Also latch the >0 reg */ cpustate->gt0reg = !(cpustate->f == 0) && !_BIT(cpustate->f, 11); } cpustate->icount--; cpustate->clkcnt++; } while (cpustate->icount > 0); return cycles - cpustate->icount; } /*************************************************************************** LINE DRAWER DISASSEMBLY HOOK ***************************************************************************/ static CPU_DISASSEMBLE( cquestlin ) { static const char *const jmps[] = { " ", "JMSB ", "JSEQ ", "JGTZ ", "JC ", "JZ ", "?????", "?????", "JUMP ", "JNMSB", "JNSEQ", "JLEZ ", "JNC ", "JNZ ", "?????", "?????", }; static const char *const latches[] = { " ", "SEQLTCH", "XLTCH ", "YLTCH ", "BGLTCH ", "FGLTCH ", "CLTCH ", "ZLTCH ", }; static const char *const spfs[] = { " ", "FSTOP ", "FREG ", "FSTART", "PWRT ", "MULT ", "LSTOP ", "BRES ", }; UINT64 inst = BIG_ENDIANIZE_INT64(*(UINT64 *)oprom); UINT32 inslow = inst & 0xffffffff; UINT32 inshig = inst >> 32; int t = (inshig >> 24) & 0xff; int jmp = (inshig >> 20) & 0xf; int latch = (inshig >> 16) & 0x7; int op = (inshig >> 15) & 0x1; int spf = (inshig >> 12) & 0x7; int b = (inshig >> 8) & 0xf; int a = (inshig >> 4) & 0xf; int i8_6 = (inshig >> 0) & 0x7; int ci = (inslow >> 31) & 0x1; int i5_3 = (inslow >> 28) & 0x7; int _pbcs = (inslow >> 27) & 0x1; int i2_0 = (inslow >> 24) & 0x7; sprintf(buffer, "%s %s,%s %x,%x %c %s %.2x %s %s %s %s\n", ins[i5_3], src[i2_0], dst[i8_6], a, b, ci ? 'C' : ' ', jmps[jmp], t, latches[latch], op ? "OP" : " ", _pbcs ? " " : "PB", spfs[spf]); return 1 | DASMFLAG_SUPPORTED; } /************************************************************************** * Sound set_info **************************************************************************/ static CPU_SET_INFO( cquestsnd ) { cquestsnd_state *cpustate = device->token; switch (state) { /* --- the following bits of info are set as 64-bit signed integers --- */ case CPUINFO_INT_PC: case CPUINFO_INT_REGISTER + CQUESTSND_PC: cpustate->pc = info->i; break; case CPUINFO_INT_REGISTER + CQUESTSND_Q: cpustate->q = info->i; break; case CPUINFO_INT_REGISTER + CQUESTSND_RTNLATCH: cpustate->rtnlatch = info->i; break; case CPUINFO_INT_REGISTER + CQUESTSND_ADRCNTR: cpustate->adrcntr = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_DINLATCH: cpustate->dinlatch = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM0: cpustate->ram[0x0] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM1: cpustate->ram[0x1] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM2: cpustate->ram[0x2] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM3: cpustate->ram[0x3] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM4: cpustate->ram[0x4] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM5: cpustate->ram[0x5] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM6: cpustate->ram[0x6] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM7: cpustate->ram[0x7] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM8: cpustate->ram[0x8] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM9: cpustate->ram[0x9] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAMA: cpustate->ram[0xa] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAMB: cpustate->ram[0xb] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAMC: cpustate->ram[0xc] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAMD: cpustate->ram[0xd] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAME: cpustate->ram[0xe] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTSND_RAMF: cpustate->ram[0xf] = info->i; break; } } /************************************************************************** * Sound get_info **************************************************************************/ CPU_GET_INFO( cquestsnd ) { cquestsnd_state *cpustate = (device != NULL) ? device->token : NULL; switch (state) { /* --- the following bits of info are returned as 64-bit signed integers --- */ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(cquestsnd_state); break; case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break; case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 8; break; case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break; case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; case CPUINFO_INT_MAX_CYCLES: info->i = 1; break; case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 64; break; case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break; case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = -3; break; case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; case CPUINFO_INT_PC: case CPUINFO_INT_REGISTER + CQUESTSND_PC: info->i = cpustate->pc; break; case CPUINFO_INT_REGISTER + CQUESTSND_RTNLATCH: info->i = cpustate->rtnlatch; break; case CPUINFO_INT_REGISTER + CQUESTSND_ADRCNTR: info->i = cpustate->adrcntr; break; /* --- the following bits of info are returned as pointers to data or functions --- */ case CPUINFO_PTR_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(cquestsnd); break; case CPUINFO_PTR_INIT: info->init = CPU_INIT_NAME(cquestsnd); break; case CPUINFO_PTR_RESET: info->reset = CPU_RESET_NAME(cquestsnd); break; case CPUINFO_PTR_EXIT: info->exit = CPU_EXIT_NAME(cquestsnd); break; case CPUINFO_PTR_EXECUTE: info->execute = CPU_EXECUTE_NAME(cquestsnd); break; case CPUINFO_PTR_BURN: info->burn = NULL; break; case CPUINFO_PTR_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cquestsnd); break; case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break; /* --- the following bits of info are returned as NULL-terminated strings --- */ case CPUINFO_STR_NAME: strcpy(info->s, "Sound CPU");break; case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Cube Quest"); break; case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.0"); break; case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Philip J Bennett"); break; case CPUINFO_STR_FLAGS: sprintf(info->s, "......."); break; case CPUINFO_STR_REGISTER + CQUESTSND_PC: sprintf(info->s, "PC: %02X", cpustate->pc); break; case CPUINFO_STR_REGISTER + CQUESTSND_Q: sprintf(info->s, "Q: %04X", cpustate->q); break; case CPUINFO_STR_REGISTER + CQUESTSND_RTNLATCH: sprintf(info->s, "RTN: %02X", cpustate->rtnlatch); break; case CPUINFO_STR_REGISTER + CQUESTSND_ADRCNTR: sprintf(info->s, "CNT: %02X", cpustate->adrcntr); break; case CPUINFO_STR_REGISTER + CQUESTSND_DINLATCH: sprintf(info->s, "DIN: %04X", cpustate->dinlatch); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM0: sprintf(info->s, "RAM[0]: %04X", cpustate->ram[0x0]); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM1: sprintf(info->s, "RAM[1]: %04X", cpustate->ram[0x1]); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM2: sprintf(info->s, "RAM[2]: %04X", cpustate->ram[0x2]); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM3: sprintf(info->s, "RAM[3]: %04X", cpustate->ram[0x3]); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM4: sprintf(info->s, "RAM[4]: %04X", cpustate->ram[0x4]); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM5: sprintf(info->s, "RAM[5]: %04X", cpustate->ram[0x5]); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM6: sprintf(info->s, "RAM[6]: %04X", cpustate->ram[0x6]); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM7: sprintf(info->s, "RAM[7]: %04X", cpustate->ram[0x7]); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM8: sprintf(info->s, "RAM[8]: %04X", cpustate->ram[0x8]); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAM9: sprintf(info->s, "RAM[9]: %04X", cpustate->ram[0x9]); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAMA: sprintf(info->s, "RAM[A]: %04X", cpustate->ram[0xa]); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAMB: sprintf(info->s, "RAM[B]: %04X", cpustate->ram[0xb]); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAMC: sprintf(info->s, "RAM[C]: %04X", cpustate->ram[0xc]); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAMD: sprintf(info->s, "RAM[D]: %04X", cpustate->ram[0xd]); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAME: sprintf(info->s, "RAM[E]: %04X", cpustate->ram[0xe]); break; case CPUINFO_STR_REGISTER + CQUESTSND_RAMF: sprintf(info->s, "RAM[F]: %04X", cpustate->ram[0xf]); break; } } /************************************************************************** * Rotate set_info **************************************************************************/ static CPU_SET_INFO( cquestrot ) { cquestrot_state *cpustate = device->token; switch (state) { /* --- the following bits of info are set as 64-bit signed integers --- */ case CPUINFO_INT_PC: case CPUINFO_INT_REGISTER + CQUESTROT_PC: cpustate->pc = info->i; break; case CPUINFO_INT_REGISTER + CQUESTROT_Q: cpustate->q = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM0: cpustate->ram[0x0] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM1: cpustate->ram[0x1] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM2: cpustate->ram[0x2] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM3: cpustate->ram[0x3] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM4: cpustate->ram[0x4] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM5: cpustate->ram[0x5] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM6: cpustate->ram[0x6] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM7: cpustate->ram[0x7] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM8: cpustate->ram[0x8] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM9: cpustate->ram[0x9] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAMA: cpustate->ram[0xa] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAMB: cpustate->ram[0xb] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAMC: cpustate->ram[0xc] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAMD: cpustate->ram[0xd] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAME: cpustate->ram[0xe] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RAMF: cpustate->ram[0xf] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_SEQCNT: cpustate->seqcnt = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_DYNADDR: cpustate->dynaddr = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_DYNDATA: cpustate->dyndata = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_YRLATCH: cpustate->yrlatch = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_YDLATCH: cpustate->ydlatch = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_DINLATCH: cpustate->dinlatch = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_DSRCLATCH:cpustate->dsrclatch = info->i; break; case CPUINFO_STR_REGISTER + CQUESTROT_RSRCLATCH:cpustate->rsrclatch = info->i; break; } } /************************************************************************** * Rotate get_info **************************************************************************/ CPU_GET_INFO( cquestrot ) { cquestrot_state *cpustate = (device != NULL) ? device->token : NULL; switch (state) { /* --- the following bits of info are returned as 64-bit signed integers --- */ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(cquestrot_state); break; case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break; case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 8; break; case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break; case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; case CPUINFO_INT_MAX_CYCLES: info->i = 1; break; case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 64; break; case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 9; break; case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = -3; break; case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; case CPUINFO_INT_PC: case CPUINFO_INT_REGISTER + CQUESTROT_PC: info->i = cpustate->pc; break; /* --- the following bits of info are returned as pointers to data or functions --- */ case CPUINFO_PTR_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(cquestrot); break; case CPUINFO_PTR_INIT: info->init = CPU_INIT_NAME(cquestrot); break; case CPUINFO_PTR_RESET: info->reset = CPU_RESET_NAME(cquestrot); break; case CPUINFO_PTR_EXIT: info->exit = CPU_EXIT_NAME(cquestrot); break; case CPUINFO_PTR_EXECUTE: info->execute = CPU_EXECUTE_NAME(cquestrot); break; case CPUINFO_PTR_BURN: info->burn = NULL; break; case CPUINFO_PTR_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cquestrot); break; case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break; /* --- the following bits of info are returned as NULL-terminated strings --- */ case CPUINFO_STR_NAME: strcpy(info->s, "Rotate CPU");break; case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Cube Quest"); break; case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.0"); break; case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Philip J Bennett"); break; case CPUINFO_STR_FLAGS: sprintf(info->s, "%c%c%c", cpustate->cflag ? 'C' : '.', cpustate->vflag ? 'V' : '.', cpustate->f ? '.' : 'Z'); break; case CPUINFO_STR_REGISTER + CQUESTROT_PC: sprintf(info->s, "PC: %02X", cpustate->pc); break; case CPUINFO_STR_REGISTER + CQUESTROT_Q: sprintf(info->s, "Q: %04X", cpustate->q); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM0: sprintf(info->s, "RAM[0]: %04X", cpustate->ram[0x0]); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM1: sprintf(info->s, "RAM[1]: %04X", cpustate->ram[0x1]); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM2: sprintf(info->s, "RAM[2]: %04X", cpustate->ram[0x2]); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM3: sprintf(info->s, "RAM[3]: %04X", cpustate->ram[0x3]); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM4: sprintf(info->s, "RAM[4]: %04X", cpustate->ram[0x4]); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM5: sprintf(info->s, "RAM[5]: %04X", cpustate->ram[0x5]); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM6: sprintf(info->s, "RAM[6]: %04X", cpustate->ram[0x6]); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM7: sprintf(info->s, "RAM[7]: %04X", cpustate->ram[0x7]); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM8: sprintf(info->s, "RAM[8]: %04X", cpustate->ram[0x8]); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAM9: sprintf(info->s, "RAM[9]: %04X", cpustate->ram[0x9]); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAMA: sprintf(info->s, "RAM[A]: %04X", cpustate->ram[0xa]); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAMB: sprintf(info->s, "RAM[B]: %04X", cpustate->ram[0xb]); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAMC: sprintf(info->s, "RAM[C]: %04X", cpustate->ram[0xc]); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAMD: sprintf(info->s, "RAM[D]: %04X", cpustate->ram[0xd]); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAME: sprintf(info->s, "RAM[E]: %04X", cpustate->ram[0xe]); break; case CPUINFO_STR_REGISTER + CQUESTROT_RAMF: sprintf(info->s, "RAM[F]: %04X", cpustate->ram[0xf]); break; case CPUINFO_STR_REGISTER + CQUESTROT_SEQCNT: sprintf(info->s, "SEQCNT: %01X", cpustate->seqcnt); break; case CPUINFO_STR_REGISTER + CQUESTROT_DYNADDR: sprintf(info->s, "DYNADDR: %04X", cpustate->dynaddr); break; case CPUINFO_STR_REGISTER + CQUESTROT_DYNDATA: sprintf(info->s, "DYNDATA: %04X", cpustate->dyndata); break; case CPUINFO_STR_REGISTER + CQUESTROT_YRLATCH: sprintf(info->s, "YRLATCH: %04X", cpustate->yrlatch); break; case CPUINFO_STR_REGISTER + CQUESTROT_YDLATCH: sprintf(info->s, "YDLATCH: %04X", cpustate->ydlatch); break; case CPUINFO_STR_REGISTER + CQUESTROT_DINLATCH: sprintf(info->s, "DINLATCH: %04X", cpustate->dinlatch); break; case CPUINFO_STR_REGISTER + CQUESTROT_DSRCLATCH:sprintf(info->s, "DSRCLATCH: %04X", cpustate->dsrclatch); break; case CPUINFO_STR_REGISTER + CQUESTROT_RSRCLATCH:sprintf(info->s, "RSRCLATCH: %04X", cpustate->rsrclatch); break; case CPUINFO_STR_REGISTER + CQUESTROT_LDADDR: sprintf(info->s, "LDADDR : %04X", cpustate->lineaddr); break; case CPUINFO_STR_REGISTER + CQUESTROT_LDDATA: sprintf(info->s, "LDDATA : %04X", cpustate->linedata); break; } } /************************************************************************** * Line drawer set_info **************************************************************************/ static CPU_SET_INFO( cquestlin ) { cquestlin_state *cpustate = device->token; switch (state) { /* --- the following bits of info are set as 64-bit signed integers --- */ case CPUINFO_INT_PC: case CPUINFO_INT_REGISTER + CQUESTLIN_FGPC: cpustate->pc[FOREGROUND] = info->i; break; case CPUINFO_INT_REGISTER + CQUESTLIN_BGPC: cpustate->pc[BACKGROUND] = info->i; break; case CPUINFO_INT_REGISTER + CQUESTLIN_Q: cpustate->q = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM0: cpustate->ram[0x0] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM1: cpustate->ram[0x1] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM2: cpustate->ram[0x2] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM3: cpustate->ram[0x3] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM4: cpustate->ram[0x4] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM5: cpustate->ram[0x5] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM6: cpustate->ram[0x6] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM7: cpustate->ram[0x7] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM8: cpustate->ram[0x8] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM9: cpustate->ram[0x9] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAMA: cpustate->ram[0xa] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAMB: cpustate->ram[0xb] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAMC: cpustate->ram[0xc] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAMD: cpustate->ram[0xd] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAME: cpustate->ram[0xe] = info->i; break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAMF: cpustate->ram[0xf] = info->i; break; } } /************************************************************************** * Line drawer get_info **************************************************************************/ CPU_GET_INFO( cquestlin ) { cquestlin_state *cpustate = (device != NULL) ? device->token : NULL; switch (state) { /* --- the following bits of info are returned as 64-bit signed integers --- */ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(cquestlin_state); break; case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break; case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 8; break; case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 8; break; case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; case CPUINFO_INT_MAX_CYCLES: info->i = 1; break; case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 64; break; case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break; case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = -3; break; case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break; case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break; case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break; case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break; case CPUINFO_INT_PC: case CPUINFO_INT_REGISTER + CQUESTLIN_FGPC: info->i = cpustate->pc[cpustate->clkcnt & 3 ? BACKGROUND : FOREGROUND]; break; /* --- the following bits of info are returned as pointers to data or functions --- */ case CPUINFO_PTR_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(cquestlin); break; case CPUINFO_PTR_INIT: info->init = CPU_INIT_NAME(cquestlin); break; case CPUINFO_PTR_RESET: info->reset = CPU_RESET_NAME(cquestlin); break; case CPUINFO_PTR_EXIT: info->exit = CPU_EXIT_NAME(cquestlin); break; case CPUINFO_PTR_EXECUTE: info->execute = CPU_EXECUTE_NAME(cquestlin); break; case CPUINFO_PTR_BURN: info->burn = NULL; break; case CPUINFO_PTR_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(cquestlin); break; case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break; /* --- the following bits of info are returned as NULL-terminated strings --- */ case CPUINFO_STR_NAME: strcpy(info->s, "Line CPU"); break; case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Cube Quest"); break; case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.0"); break; case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break; case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Philip J Bennett"); break; case CPUINFO_STR_FLAGS: sprintf(info->s, "%c%c%c|%cG", cpustate->cflag ? 'C' : '.', cpustate->vflag ? 'V' : '.', cpustate->f ? '.' : 'Z', cpustate->clkcnt & 3 ? 'B' : 'F'); break; case CPUINFO_STR_REGISTER + CQUESTLIN_FGPC: sprintf(info->s, "FPC: %02X", cpustate->pc[FOREGROUND]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_BGPC: sprintf(info->s, "BPC: %02X", cpustate->pc[BACKGROUND]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_Q: sprintf(info->s, "Q: %04X", cpustate->q); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM0: sprintf(info->s, "RAM[0]: %04X", cpustate->ram[0x0]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM1: sprintf(info->s, "RAM[1]: %04X", cpustate->ram[0x1]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM2: sprintf(info->s, "RAM[2]: %04X", cpustate->ram[0x2]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM3: sprintf(info->s, "RAM[3]: %04X", cpustate->ram[0x3]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM4: sprintf(info->s, "RAM[4]: %04X", cpustate->ram[0x4]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM5: sprintf(info->s, "RAM[5]: %04X", cpustate->ram[0x5]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM6: sprintf(info->s, "RAM[6]: %04X", cpustate->ram[0x6]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM7: sprintf(info->s, "RAM[7]: %04X", cpustate->ram[0x7]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM8: sprintf(info->s, "RAM[8]: %04X", cpustate->ram[0x8]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAM9: sprintf(info->s, "RAM[9]: %04X", cpustate->ram[0x9]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAMA: sprintf(info->s, "RAM[A]: %04X", cpustate->ram[0xa]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAMB: sprintf(info->s, "RAM[B]: %04X", cpustate->ram[0xb]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAMC: sprintf(info->s, "RAM[C]: %04X", cpustate->ram[0xc]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAMD: sprintf(info->s, "RAM[D]: %04X", cpustate->ram[0xd]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAME: sprintf(info->s, "RAM[E]: %04X", cpustate->ram[0xe]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_RAMF: sprintf(info->s, "RAM[F]: %04X", cpustate->ram[0xf]); break; case CPUINFO_STR_REGISTER + CQUESTLIN_FADLATCH: sprintf(info->s, "FADDR: %04X", cpustate->fadlatch); break; case CPUINFO_STR_REGISTER + CQUESTLIN_BADLATCH: sprintf(info->s, "BADDR: %04X", cpustate->badlatch); break; case CPUINFO_STR_REGISTER + CQUESTLIN_SREG: sprintf(info->s, "SREG: %04X", cpustate->sreg); break; case CPUINFO_STR_REGISTER + CQUESTLIN_XCNT: sprintf(info->s, "XCNT: %03X", cpustate->xcnt); break; case CPUINFO_STR_REGISTER + CQUESTLIN_YCNT: sprintf(info->s, "YCNT: %03X", cpustate->ycnt); break; case CPUINFO_STR_REGISTER + CQUESTLIN_CLATCH: sprintf(info->s, "CLATCH: %04X", cpustate->clatch); break; case CPUINFO_STR_REGISTER + CQUESTLIN_ZLATCH: sprintf(info->s, "ZLATCH: %04X", cpustate->zlatch); break; } }