mirror of
https://github.com/holub/mame
synced 2025-05-17 19:24:59 +03:00

machine configuration just as any other device, and the standard CPU configuration is performed via the inline configuration macros. Change cpu_type from an enumeration into a pointer to the CPU's get_info function, very similar to device behavior. For now all CPUs are declared in cpuintrf.h, but eventually they should be declared in the CPU's header file, and the driver should #include that header. Added function cpu_get_type() to return the CPU type. Changed several cpu_* functions into macros that call through to the equivalent device_* function. The device system now maintains a parallel list of devices based on type, for faster iteration through all devices of a given type. Cleaned up code that looped over CPUs via the machine->cpu array to now loop using the type-based device list. Removed start/stop/reset/nvram functions from the device_config in favor of grabbing them as needed. Cleaned up the generic interrupt_enable code to work with CPU devices instead of numbers. Mapped the devtag_* functions to device_* functions via macros instead of parallel implementations.
2166 lines
67 KiB
C
2166 lines
67 KiB
C
/***************************************************************************
|
|
|
|
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;
|
|
}
|
|
}
|