summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/cubeqcpu/cubeqcpu.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/cubeqcpu/cubeqcpu.c')
-rw-r--r--trunk/src/emu/cpu/cubeqcpu/cubeqcpu.c1885
1 files changed, 1885 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/cubeqcpu/cubeqcpu.c b/trunk/src/emu/cpu/cubeqcpu/cubeqcpu.c
new file mode 100644
index 00000000000..e64e917e5cd
--- /dev/null
+++ b/trunk/src/emu/cpu/cubeqcpu/cubeqcpu.c
@@ -0,0 +1,1885 @@
+/***************************************************************************
+
+ cubeqcpu.c
+
+ Implementation of the Cube Quest AM2901-based CPUs
+
+ TODO:
+
+ * Tidy up diassembly (split into different files?)
+
+***************************************************************************/
+
+#include "emu.h"
+#include "debugger.h"
+#include "cubeqcpu.h"
+
+
+CPU_DISASSEMBLE( cquestsnd );
+CPU_DISASSEMBLE( cquestrot );
+CPU_DISASSEMBLE( cquestlin );
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* Am2901 Instruction Fields */
+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;
+
+ legacy_cpu_device *device;
+ address_space *program;
+ direct_read_data *direct;
+ 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;
+
+ legacy_cpu_device *device;
+ legacy_cpu_device *lindevice;
+ address_space *program;
+ direct_read_data *direct;
+ 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;
+
+ legacy_cpu_device *device;
+ legacy_cpu_device *rotdevice;
+ address_space *program;
+ direct_read_data *direct;
+ int icount;
+} cquestlin_state;
+
+/***************************************************************************
+ STATE ACCESSORS
+***************************************************************************/
+
+INLINE cquestsnd_state *get_safe_token_snd(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == CQUESTSND);
+ return (cquestsnd_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE cquestrot_state *get_safe_token_rot(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == CQUESTROT);
+ return (cquestrot_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+INLINE cquestlin_state *get_safe_token_lin(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == CQUESTLIN);
+ return (cquestlin_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+/***************************************************************************
+ MEMORY ACCESSORS FOR 68000
+***************************************************************************/
+
+WRITE16_DEVICE_HANDLER( cubeqcpu_sndram_w )
+{
+ cquestsnd_state *cpustate = get_safe_token_snd(device);
+ COMBINE_DATA(&cpustate->sram[offset]);
+}
+
+READ16_DEVICE_HANDLER( cubeqcpu_sndram_r )
+{
+ cquestsnd_state *cpustate = get_safe_token_snd(device);
+ return cpustate->sram[offset];
+}
+
+
+WRITE16_DEVICE_HANDLER( cubeqcpu_rotram_w )
+{
+ cquestrot_state *cpustate = get_safe_token_rot(device);
+ COMBINE_DATA(&cpustate->dram[offset]);
+}
+
+READ16_DEVICE_HANDLER( cubeqcpu_rotram_r )
+{
+ cquestrot_state *cpustate = get_safe_token_rot(device);
+ return cpustate->dram[offset];
+}
+
+/***************************************************************************
+ SOUND INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+
+static void cquestsnd_state_register(device_t *device)
+{
+ cquestsnd_state *cpustate = get_safe_token_snd(device);
+ device->save_item(NAME(cpustate->ram));
+ device->save_item(NAME(cpustate->q));
+ device->save_item(NAME(cpustate->f));
+ device->save_item(NAME(cpustate->y));
+ device->save_item(NAME(cpustate->cflag));
+ device->save_item(NAME(cpustate->vflag));
+
+ device->save_item(NAME(cpustate->pc));
+ device->save_item(NAME(cpustate->platch));
+ device->save_item(NAME(cpustate->rtnlatch));
+ device->save_item(NAME(cpustate->adrcntr));
+ device->save_item(NAME(cpustate->adrlatch));
+ device->save_item(NAME(cpustate->dinlatch));
+ device->save_item(NAME(cpustate->ramwlatch));
+ device->save_item(NAME(cpustate->prev_ipram));
+ device->save_item(NAME(cpustate->prev_ipwrt));
+}
+
+static CPU_INIT( cquestsnd )
+{
+ cquestsnd_state *cpustate = get_safe_token_snd(device);
+ 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*)device->machine().region(_config->sound_data_region)->base();
+
+ cpustate->device = device;
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ /* Allocate RAM shared with 68000 */
+ cpustate->sram = auto_alloc_array(device->machine(), UINT16, 4096/2);
+
+ cquestsnd_state_register(device);
+}
+
+
+static CPU_RESET( cquestsnd )
+{
+ cquestsnd_state *cpustate = get_safe_token_snd(device);
+ cpustate->pc = 0;
+}
+
+
+static CPU_EXIT( cquestsnd )
+{
+}
+
+
+/***************************************************************************
+ ROTATE INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+
+static void cquestrot_state_register(device_t *device)
+{
+ cquestrot_state *cpustate = get_safe_token_rot(device);
+ device->save_item(NAME(cpustate->ram));
+ device->save_item(NAME(cpustate->q));
+ device->save_item(NAME(cpustate->f));
+ device->save_item(NAME(cpustate->y));
+ device->save_item(NAME(cpustate->cflag));
+ device->save_item(NAME(cpustate->vflag));
+
+ device->save_item(NAME(cpustate->pc));
+ device->save_item(NAME(cpustate->seqcnt));
+ device->save_item(NAME(cpustate->dsrclatch));
+ device->save_item(NAME(cpustate->rsrclatch));
+ device->save_item(NAME(cpustate->dynaddr));
+ device->save_item(NAME(cpustate->dyndata));
+ device->save_item(NAME(cpustate->yrlatch));
+ device->save_item(NAME(cpustate->ydlatch));
+ device->save_item(NAME(cpustate->dinlatch));
+ device->save_item(NAME(cpustate->divreg));
+ device->save_item(NAME(cpustate->linedata));
+ device->save_item(NAME(cpustate->lineaddr));
+ device->save_item(NAME(cpustate->prev_dred));
+ device->save_item(NAME(cpustate->prev_dwrt));
+ device->save_item(NAME(cpustate->wc));
+
+ device->save_pointer(NAME(cpustate->dram), 16384);
+ device->save_pointer(NAME(cpustate->sram), 2048);
+}
+
+static CPU_INIT( cquestrot )
+{
+ const cubeqst_rot_config *rotconfig = (const cubeqst_rot_config *)device->static_config();
+ cquestrot_state *cpustate = get_safe_token_rot(device);
+ memset(cpustate, 0, sizeof(*cpustate));
+
+ /* Allocate RAM */
+ cpustate->dram = auto_alloc_array(device->machine(), UINT16, 16384); /* Shared with 68000 */
+ cpustate->sram = auto_alloc_array(device->machine(), UINT16, 2048); /* Private */
+
+ cpustate->device = device;
+ cpustate->lindevice = device->machine().device<legacy_cpu_device>(rotconfig->lin_cpu_tag);
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ cquestrot_state_register(device);
+}
+
+
+static CPU_RESET( cquestrot )
+{
+ cquestrot_state *cpustate = get_safe_token_rot(device);
+ 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 void cquestlin_state_register(device_t *device)
+{
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+
+ device->save_item(NAME(cpustate->ram));
+ device->save_item(NAME(cpustate->q));
+ device->save_item(NAME(cpustate->f));
+ device->save_item(NAME(cpustate->y));
+ device->save_item(NAME(cpustate->cflag));
+ device->save_item(NAME(cpustate->vflag));
+
+ device->save_item(NAME(cpustate->pc[0]));
+ device->save_item(NAME(cpustate->pc[1]));
+ device->save_item(NAME(cpustate->seqcnt));
+ device->save_item(NAME(cpustate->clatch));
+ device->save_item(NAME(cpustate->zlatch));
+ device->save_item(NAME(cpustate->xcnt));
+ device->save_item(NAME(cpustate->ycnt));
+ device->save_item(NAME(cpustate->sreg));
+ device->save_item(NAME(cpustate->fadlatch));
+ device->save_item(NAME(cpustate->badlatch));
+ device->save_item(NAME(cpustate->sramdlatch));
+ device->save_item(NAME(cpustate->fglatch));
+ device->save_item(NAME(cpustate->bglatch));
+ device->save_item(NAME(cpustate->gt0reg));
+ device->save_item(NAME(cpustate->fdxreg));
+ device->save_item(NAME(cpustate->field));
+ device->save_item(NAME(cpustate->clkcnt));
+
+ device->save_pointer(NAME(cpustate->sram), 4096);
+ device->save_pointer(NAME(cpustate->ptr_ram), 1024);
+ device->save_pointer(NAME(cpustate->e_stack), 32768);
+ device->save_pointer(NAME(cpustate->o_stack), 32768);
+}
+
+static CPU_INIT( cquestlin )
+{
+ const cubeqst_lin_config *linconfig = (const cubeqst_lin_config *)device->static_config();
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+ memset(cpustate, 0, sizeof(*cpustate));
+
+ /* Allocate RAM */
+ cpustate->sram = auto_alloc_array(device->machine(), UINT16, 4096); /* Shared with rotate CPU */
+ cpustate->ptr_ram = auto_alloc_array(device->machine(), UINT8, 1024); /* Pointer RAM */
+ cpustate->e_stack = auto_alloc_array(device->machine(), UINT32, 32768); /* Stack DRAM: 32kx20 */
+ cpustate->o_stack = auto_alloc_array(device->machine(), UINT32, 32768); /* Stack DRAM: 32kx20 */
+
+ cpustate->device = device;
+ cpustate->rotdevice = device->machine().device<legacy_cpu_device>(linconfig->rot_cpu_tag);
+ cpustate->program = device->space(AS_PROGRAM);
+ cpustate->direct = &cpustate->program->direct();
+
+ cquestlin_state_register(device);
+}
+
+
+static CPU_RESET( cquestlin )
+{
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+ 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 = get_safe_token_snd(device);
+ int calldebugger = ((device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);
+
+ /* Core execution loop */
+ do
+ {
+ /* Decode the instruction */
+ UINT64 inst = cpustate->direct->read_decrypted_qword(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);
+}
+
+
+/***************************************************************************
+ 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 = get_safe_token_rot(device);
+ cquestlin_state *lincpustate = get_safe_token_lin(cpustate->lindevice);
+ int calldebugger = ((device->machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);
+
+ /* Core execution loop */
+ do
+ {
+ /* Decode the instruction */
+ UINT64 inst = cpustate->direct->read_decrypted_qword(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);
+}
+
+
+/***************************************************************************
+ LINE DRAWER CORE EXECUTION LOOP
+***************************************************************************/
+
+#define VISIBLE_FIELD !cpustate->field
+
+enum line_spf
+{
+ LSPF_UNUSED = 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(device_t *device)
+{
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+ cpustate->field = cpustate->field ^ 1;
+}
+
+
+void cubeqcpu_clear_stack(device_t *device)
+{
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+ memset(&cpustate->ptr_ram[cpustate->field * 256], 0, 256);
+}
+
+UINT8 cubeqcpu_get_ptr_ram_val(device_t *device, int i)
+{
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+ return cpustate->ptr_ram[(VISIBLE_FIELD * 256) + i];
+}
+
+UINT32* cubeqcpu_get_stack_ram(device_t *device)
+{
+ cquestlin_state *cpustate = get_safe_token_lin(device);
+ 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 = get_safe_token_lin(device);
+ cquestrot_state *rotcpustate = get_safe_token_rot(cpustate->rotdevice);
+ 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];
+ }
+
+ /* Core execution loop */
+ do
+ {
+ /* Are we executing the foreground or backgroud program? */
+ int prog = (cpustate->clkcnt & 3) ? BACKGROUND : FOREGROUND;
+
+ UINT64 inst = cpustate->direct->read_decrypted_qword(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);
+}
+
+
+/**************************************************************************
+ * Sound set_info
+ **************************************************************************/
+
+static CPU_SET_INFO( cquestsnd )
+{
+ cquestsnd_state *cpustate = get_safe_token_snd(device);
+ 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) ? get_safe_token_snd(device) : 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 DEVINFO_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 DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -3; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_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_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(cquestsnd); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cquestsnd); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(cquestsnd); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(cquestsnd); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(cquestsnd); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_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 DEVINFO_STR_NAME: strcpy(info->s, "Sound CPU");break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Cube Quest"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_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 = get_safe_token_rot(device);
+ 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) ? get_safe_token_rot(device) : 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 DEVINFO_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 DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 9; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -3; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_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_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(cquestrot); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cquestrot); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(cquestrot); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(cquestrot); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(cquestrot); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_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 DEVINFO_STR_NAME: strcpy(info->s, "Rotate CPU");break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Cube Quest"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_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 = get_safe_token_lin(device);
+ 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) ? get_safe_token_lin(device) : 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 DEVINFO_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 DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 64; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -3; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_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_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(cquestlin); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(cquestlin); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(cquestlin); break;
+ case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(cquestlin); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(cquestlin); break;
+ case CPUINFO_FCT_BURN: info->burn = NULL; break;
+ case CPUINFO_FCT_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 DEVINFO_STR_NAME: strcpy(info->s, "Line CPU"); break;
+ case DEVINFO_STR_FAMILY: strcpy(info->s, "Cube Quest"); break;
+ case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
+ case DEVINFO_STR_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;
+ }
+}
+
+DEFINE_LEGACY_CPU_DEVICE(CQUESTSND, cquestsnd);
+DEFINE_LEGACY_CPU_DEVICE(CQUESTROT, cquestrot);
+DEFINE_LEGACY_CPU_DEVICE(CQUESTLIN, cquestlin);