diff --git a/.gitattributes b/.gitattributes index 0d1977b9391..4c85b281b92 100644 --- a/.gitattributes +++ b/.gitattributes @@ -92,6 +92,8 @@ src/emu/cpu/e132xs/32xsdasm.c svneol=native#text/plain src/emu/cpu/e132xs/e132xs.c svneol=native#text/plain src/emu/cpu/e132xs/e132xs.h svneol=native#text/plain src/emu/cpu/e132xs/e132xsop.c svneol=native#text/plain +src/emu/cpu/esrip/esrip.c svneol=native#text/plain +src/emu/cpu/esrip/esrip.h svneol=native#text/plain src/emu/cpu/f8/f3853.c svneol=native#text/plain src/emu/cpu/f8/f3853.h svneol=native#text/plain src/emu/cpu/f8/f8.c svneol=native#text/plain @@ -1444,6 +1446,7 @@ src/mame/drivers/ertictac.c svneol=native#text/plain src/mame/drivers/esd16.c svneol=native#text/plain src/mame/drivers/esh.c svneol=native#text/plain src/mame/drivers/espial.c svneol=native#text/plain +src/mame/drivers/esripsys.c svneol=native#text/plain src/mame/drivers/ettrivia.c svneol=native#text/plain src/mame/drivers/exedexes.c svneol=native#text/plain src/mame/drivers/exerion.c svneol=native#text/plain @@ -2099,7 +2102,6 @@ src/mame/drivers/tumbleb.c svneol=native#text/plain src/mame/drivers/tumblep.c svneol=native#text/plain src/mame/drivers/tunhunt.c svneol=native#text/plain src/mame/drivers/turbo.c svneol=native#text/plain -src/mame/drivers/turbosub.c svneol=native#text/plain src/mame/drivers/tutankhm.c svneol=native#text/plain src/mame/drivers/twin16.c svneol=native#text/plain src/mame/drivers/twincobr.c svneol=native#text/plain @@ -2265,6 +2267,7 @@ src/mame/includes/epos.h svneol=native#text/plain src/mame/includes/eprom.h svneol=native#text/plain src/mame/includes/equites.h svneol=native#text/plain src/mame/includes/espial.h svneol=native#text/plain +src/mame/includes/esripsys.h svneol=native#text/plain src/mame/includes/exerion.h svneol=native#text/plain src/mame/includes/exidy.h svneol=native#text/plain src/mame/includes/exidy440.h svneol=native#text/plain @@ -2935,6 +2938,7 @@ src/mame/video/eprom.c svneol=native#text/plain src/mame/video/equites.c svneol=native#text/plain src/mame/video/esd16.c svneol=native#text/plain src/mame/video/espial.c svneol=native#text/plain +src/mame/video/esripsys.c svneol=native#text/plain src/mame/video/exedexes.c svneol=native#text/plain src/mame/video/exerion.c svneol=native#text/plain src/mame/video/exidy.c svneol=native#text/plain diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak index 38ee77b7c4f..ca31ea131c4 100644 --- a/src/emu/cpu/cpu.mak +++ b/src/emu/cpu/cpu.mak @@ -265,6 +265,23 @@ $(CPUOBJ)/cubeqcpu/cubeqcpu.o: $(CPUSRC)/cubeqcpu/cubeqcpu.c \ +#------------------------------------------------- +# Entertainment Sciences AM29116-based RIP +#------------------------------------------------- + +CPUDEFS += -DHAS_ESRIP=$(if $(filter ESRIP,$(CPUS)),1,0) + +ifneq ($(filter ESRIP,$(CPUS)),) +OBJDIRS += $(CPUOBJ)/esrip +CPUOBJS += $(CPUOBJ)/esrip/esrip.o +#DBGOBJS += $(CPUOBJ)/esrip/esrip.o +endif + +$(CPUOBJ)/esrip/esrip.o: $(CPUSRC)/esrip/esrip.c \ + $(CPUSRC)/esrip/esrip.h + + + #------------------------------------------------- # RCA CDP1802 #------------------------------------------------- diff --git a/src/emu/cpu/esrip/esrip.c b/src/emu/cpu/esrip/esrip.c new file mode 100644 index 00000000000..6cc28ab7d00 --- /dev/null +++ b/src/emu/cpu/esrip/esrip.c @@ -0,0 +1,2030 @@ +/*************************************************************************** + + escpustate->c + + Implementation of the Entertainment Sciences + AM29116-based Real Time Image Processor + +***************************************************************************/ + +#include "debugger.h" +#include "deprecat.h" +#include "esrip.h" + + +/*************************************************************************** + CONSTANTS +***************************************************************************/ + +#define IPT_RAM_SIZE (8192 * sizeof(UINT16)) + + +/*************************************************************************** + MACROS +***************************************************************************/ + +#define ASSERT(x) +//(assert(x)) +#define RIP_PC (cpustate->pc | ((cpustate->status_out & 1) << 8)) +#define _BIT(x, n) ((x) & (1 << (n))) +#define RISING_EDGE(old_val, new_val, bit) (!(old_val & (1 << bit)) && (new_val & (1 << bit))) + +#define UNHANDLED do {printf("%s:UNHANDLED (%x)\n", __FUNCTION__, inst); ASSERT(0);}while(0) +#define INVALID do {printf("%s:INVALID (%x)\n", __FUNCTION__, inst); ASSERT(0);}while(0) + +#define RAM_ADDR (inst & 0x1f) +#define MODE (inst & 0x8000) +#define WORD_MODE (inst & 0x8000) +#define BYTE_MODE (!WORD_MODE) +#define N ((inst >> 9) & 0xf) +#define OPCODE ((inst >> 5) & 0xf) +#define SRC ((inst >> 9) & 0xf) +#define DST (inst & 0x1f) // TEST + +#define BW_WORD (1 << 15) +#define BW_BYTE (0 << 15) + +#define FLAG_3 (1 << 7) +#define FLAG_2 (1 << 6) +#define FLAG_1 (1 << 5) +#define L_FLAG (1 << 4) +#define V_FLAG (1 << 3) +#define N_FLAG (1 << 2) +#define C_FLAG (1 << 1) +#define Z_FLAG (1 << 0) + +#define CLEAR_FLAGS(a) (cpustate->new_status &= ~(a)) +#define SET_FLAGS(a) (cpustate->new_status |= (a)) + + +/*************************************************************************** + STRUCTURES & TYPEDEFS +***************************************************************************/ + +typedef struct +{ + UINT16 ram[32]; + UINT16 acc; + UINT16 d_latch; + UINT16 i_latch; + UINT16 result; + UINT8 new_status; + UINT8 status; + UINT16 inst; + UINT8 immflag; + UINT8 ct; + UINT8 t; + + /* Instruction latches - current and previous values */ + UINT8 l1, pl1; + UINT8 l2, pl2; + UINT8 l3, pl3; + UINT8 l4, pl4; + UINT8 l5, pl5; + UINT8 l6, pl6; + UINT8 l7, pl7; + + UINT8 pc; + UINT8 status_out; + + UINT8 x_scale; + UINT8 y_scale; + UINT8 line_latch; + UINT16 fig_latch; + UINT16 attr_latch; + UINT16 adl_latch; + UINT16 adr_latch; + UINT8 c_latch; + UINT16 iaddr; + + UINT16 fdt_cnt; + UINT16 ipt_cnt; + + UINT16 *ipt_ram; + UINT8 *lbrm; + + UINT8 *optable; + + UINT8 fig; + UINT16 fig_cycles; + + const device_config *device; + const address_space *program; + int icount; + + read16_device_func fdt_r; + write16_device_func fdt_w; + UINT8 (*status_in)(running_machine *machine); + int (*draw)(running_machine *machine, int l, int r, int fig, int attr, int addr, int col, int x_scale, int line_latch); +} esrip_state; + + +/*************************************************************************** + INITIALIZATION AND SHUTDOWN +***************************************************************************/ + +UINT8 get_rip_status(const device_config *cpu) +{ + esrip_state *cpustate = cpu->token; + + return cpustate->status_out; +} + +/* +static STATE_POSTLOAD( esrip_postload ) +{ + +} +*/ + +//static void esrip_state_register(int index, const char *type) +//{ +// state_save_register_item_pointer(type, index, cpustate->ipt_ram, IPT_RAM_SIZE / 2); +//} + + +enum +{ + ROTR1, TOR1, ROTR2, ROTC, ROTM, BOR2, CRCF, CRCR, + SVSTR, PRT, SOR, TOR2, SHFTR, TEST, NOP, SETST, RSTST, + ROTNR, BONR, BOR1, SONR, SHFTNR, PRTNR, TONR +} ops; + + +void make_ops(esrip_state *cpustate) +{ + int inst; + + for (inst = 0; inst < 65536; ++inst) + { + int quad = (inst >> 13) & 3; + + if (quad == 0) + { + if (((inst >> 5) & 0xc) == 0xc) + cpustate->optable[inst] = ROTR1; + else + cpustate->optable[inst] = TOR1; + } + else if (quad == 1) + { + if (OPCODE < 2) + cpustate->optable[inst] = ROTR2; + else if (OPCODE < 6) + cpustate->optable[inst] = ROTC; + else + cpustate->optable[inst] = ROTM; + } + else if (quad == 2) + { + if (OPCODE > 11) + cpustate->optable[inst] = BOR2; + else + { + int tmp = (inst >> 5) & 0xff; + + if (tmp == 0x63) + cpustate->optable[inst] = CRCF; + else if (tmp == 0x69) + cpustate->optable[inst] = CRCR; + else if (tmp == 0x7a) + cpustate->optable[inst] = SVSTR; + else + { + if ((SRC > 7) && (SRC < 12)) + cpustate->optable[inst] = PRT; + else if (SRC > 11) + cpustate->optable[inst] = SOR; + else if (SRC < 6) + cpustate->optable[inst] = TOR2; + else + cpustate->optable[inst] = SHFTR; + } + } + } + else + { + if (inst == 0x7140) + cpustate->optable[inst] = NOP; + else + { + int x = (inst & 0xffe0); + if (x == 0x7340) + cpustate->optable[inst] = TEST; + else if (x == 0x7740) + cpustate->optable[inst] = SETST; + else if (x == 0x7540) + cpustate->optable[inst] = RSTST; + else + { + int op = OPCODE; + if (op == 0xc) + { + if ((inst & 0x18) == 0x18) + cpustate->optable[inst] = ROTNR; + else + cpustate->optable[inst] = BONR; + } + else if ((op & 0xc) == 0xc) + cpustate->optable[inst] = BOR1; + else + { + int src = SRC; + + if ((src & 0xc) == 0xc) + cpustate->optable[inst] = SONR; + else if ((src & 0x6) == 0x6) + cpustate->optable[inst] = SHFTNR; + else if (src & 0x8) + cpustate->optable[inst] = PRTNR; + else + cpustate->optable[inst] = TONR; + } + } + } + } + } +} + +static CPU_INIT( esrip ) +{ + esrip_state *cpustate = device->token; + esrip_config* _config = (esrip_config*)device->static_config; + + memset(cpustate, 0, sizeof(cpustate)); + + /* Register configuration structure callbacks */ + cpustate->fdt_r = _config->fdt_r; + cpustate->fdt_w = _config->fdt_w; + cpustate->lbrm = (UINT8*)memory_region(device->machine, _config->lbrm_prom); + cpustate->status_in = _config->status_in; + cpustate->draw = _config->draw; + + cpustate->ipt_ram = auto_malloc(IPT_RAM_SIZE); +//state_save_register_global_pointer(cpustate->ipt_ram, IPT_RAM_SIZE / 2); // TODO + +// esrip_state_register(index, "esrip"); + cpustate->device = device; + cpustate->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM); + + /* Create the instruction decode lookup table */ + cpustate->optable = auto_malloc(65536); + make_ops(cpustate); +} + + +static CPU_RESET( esrip ) +{ + esrip_state *cpustate = device->token; + + cpustate->pc = 0; + + cpustate->pl1 = 0xff; + cpustate->pl2 = 0xff; + cpustate->pl3 = 0xff; + cpustate->pl4 = 0xff; + cpustate->pl5 = 0xff; + cpustate->pl6 = 0xff; + cpustate->pl7 = 0xff; + + cpustate->l1 = 0xff; + cpustate->l2 = 0xff; + cpustate->l3 = 0xff; + cpustate->l4 = 0xff; + cpustate->l5 = 0xff; + cpustate->l6 = 0xff; + cpustate->l7 = 0xff; + + cpustate->status_out = 0; + cpustate->immflag = 0; +} + + +static CPU_EXIT( esrip ) +{ + +} + + + +static int get_hblank(running_machine *machine) +{ + return video_screen_get_hblank(machine->primary_screen); +} + +/* Return the state of the LBRM line (Y-scaling related) */ +static int get_lbrm(esrip_state *cpustate) +{ + int addr = ((cpustate->y_scale & 0x3f) << 3) | ((cpustate->line_latch >> 3) & 7); + int sel = (cpustate->line_latch & 7); + + UINT8 val = cpustate->lbrm[addr]; + + return (val >> sel) & 1; +} + +INLINE int check_jmp(esrip_state *cpustate, running_machine *machine, UINT8 jmp_ctrl) +{ + int ret = 0; + + if (~jmp_ctrl & 0x10) + { + switch (jmp_ctrl & 7) + { + /* CT */ case 0: ret = cpustate->ct; break; + /* T1 */ case 4: ret = BIT(cpustate->t, 0); break; + /* T2 */ case 2: ret = BIT(cpustate->t, 1); break; + /* T3 */ case 6: ret = BIT(cpustate->t, 2); break; + /* T4 */ case 1: ret = BIT(cpustate->t, 3); break; + /* /LBRM */ case 5: ret = !get_lbrm(cpustate); break; + /* /HBLANK */ case 3: ret = !get_hblank(machine); break; + /* JMP */ case 7: ret = 0; break; + } + + ret ^= 1; + } + else if (~jmp_ctrl & 0x08) + { + switch (jmp_ctrl & 7) + { + /* CT */ case 0: ret = cpustate->ct; break; + /* T1 */ case 4: ret = BIT(cpustate->t, 0); break; + /* T2 */ case 2: ret = BIT(cpustate->t, 1); break; + /* T3 */ case 6: ret = BIT(cpustate->t, 2); break; + /* T4 */ case 1: ret = BIT(cpustate->t, 3); break; + /* /LBRM */ case 5: ret = !get_lbrm(cpustate); break; + /* /FIG */ case 3: ret = !cpustate->fig; break; + /* JMP */ case 7: ret = 1; break; + } + } + else + ASSERT(!"RIP: Invalid jump control"); + + return ret; +} + + +INLINE void calc_z_flag(esrip_state *cpustate, UINT16 res) +{ + cpustate->new_status &= ~Z_FLAG; + cpustate->new_status |= (res == 0); +} + +INLINE void calc_c_flag_add(esrip_state *cpustate, UINT16 a, UINT16 b) +{ + cpustate->new_status &= ~C_FLAG; + cpustate->new_status |= ((UINT16)(b) > (UINT16)(~(a))) ? 2 : 0; +} + +INLINE void calc_c_flag_sub(esrip_state *cpustate, UINT16 a, UINT16 b) +{ + cpustate->new_status &= ~C_FLAG; + cpustate->new_status |= ((UINT16)(b) <= (UINT16)(a)) ? 2 : 0; +} + +INLINE void calc_n_flag(esrip_state *cpustate, UINT16 res) +{ + cpustate->new_status &= ~N_FLAG; + cpustate->new_status |= (res & 0x8000) ? 4 : 0; +} + +INLINE void calc_v_flag_add(esrip_state *cpustate, UINT16 a, UINT16 b, UINT32 r) +{ + cpustate->new_status &= ~V_FLAG; + cpustate->new_status |= ((a ^ r) & (b ^ r) & 0x8000) ? 8 : 0; +} + +INLINE void calc_v_flag_sub(esrip_state *cpustate, UINT16 a, UINT16 b, UINT32 r) +{ + cpustate->new_status &= ~V_FLAG; + cpustate->new_status |= ((a ^ b) & (r ^ b) & 0x8000) ? 8 : 0; +} + + +enum +{ + ACC, + Y_BUS, + STATUS, + RAM, +}; + +/************************************* + * + * Single operand + * + *************************************/ +enum +{ + MOVE = 0xc, + COMP = 0xd, + INC = 0xe, + NEG = 0xf +}; + +enum +{ + SORA = 0x0, + SORY = 0x2, + SORS = 0x3, + SOAR = 0x4, + SODR = 0x6, + SOIR = 0x7, + SOZR = 0x8, + SOZER = 0x9, + SOSER = 0xa, + SORR = 0xb +}; + +static UINT16 sor_op(esrip_state *cpustate, UINT16 r, UINT16 opcode) +{ + UINT32 res = 0; + + switch (opcode) + { + case MOVE: + { + res = r; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + break; + } + case COMP: + { + res = r ^ 0xffff; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + break; + } + case INC: + { + res = r + 1; + calc_v_flag_add(cpustate, r, 1, res); + calc_n_flag(cpustate, res); + calc_c_flag_add(cpustate, r, 1); + calc_z_flag(cpustate, res); + break; + } + case NEG: + { + res = (r ^ 0xffff) + 1; + calc_v_flag_sub(cpustate, 0, r, res); + calc_n_flag(cpustate, res); + calc_c_flag_sub(cpustate, 0, r); + calc_z_flag(cpustate, res); + break; + } + default: assert(0); + } + + return res & 0xffff; +} + +static void sor(esrip_state *cpustate, UINT16 inst) +{ + UINT16 r = 0; + UINT16 dst = 0; + UINT16 res = 0; + + if (BYTE_MODE) + { + printf("Byte Mode! %.4x\n", inst); + UNHANDLED; + } + + switch ((inst >> 5) & 0xf) + { + case SORA: r = cpustate->ram[RAM_ADDR]; dst = ACC; break; + case SORY: r = cpustate->ram[RAM_ADDR]; dst = Y_BUS; break; + case SORS: r = cpustate->ram[RAM_ADDR]; dst = STATUS; break; + case SOAR: r = cpustate->acc; dst = RAM; break; + case SODR: r = cpustate->d_latch; dst = RAM; break; + case SOIR: + { + if (cpustate->immflag == 0) // Macrofiy this? + { + cpustate->i_latch = inst; + cpustate->immflag = 1; + return; + } + else + { + r = cpustate->inst; + dst = RAM; + cpustate->immflag = 0; + } + break; + } + case SOZR: r = 0; dst = RAM; break; + case SORR: r = cpustate->ram[RAM_ADDR]; dst = RAM; break; + default: UNHANDLED; + } + + /* Operation */ + res = sor_op(cpustate, r, (inst >> 9) & 0xf); + + switch (dst) + { + case Y_BUS: break; + case ACC: cpustate->acc = res; break; + case RAM: cpustate->ram[RAM_ADDR] = res; break; + default: UNHANDLED; + } + + cpustate->result = res; +} + +enum +{ + SOA = 0x4, + SOD = 0x6, + SOI = 0x7, + SOZ = 0x8, + SOZE = 0x9, + SOSE = 0xa, +}; + +enum +{ + NRY = 0, + NRA = 1, + NRS = 4, + NRAS = 5, +}; + +static void sonr(esrip_state *cpustate, UINT16 inst) +{ + UINT16 r = 0; + UINT16 res = 0; + + switch ((inst >> 5) & 0xf) + { + case SOA: r = cpustate->acc; break; + case SOD: r = cpustate->d_latch; break; + case SOI: + { + if (cpustate->immflag == 0) + { + cpustate->i_latch = inst; + cpustate->immflag = 1; + return; + } + else + { + r = cpustate->inst; + cpustate->immflag = 0; + } + break; + } + case SOZ: r = 0; break; + default: INVALID; + } + + /* Operation */ + res = sor_op(cpustate, r, (inst >> 9) & 0xf); + + /* Destination */ + switch (inst & 0x1f) + { + case NRY: break; + case NRA: cpustate->acc = res; break; + default: UNHANDLED; + } + + cpustate->result = res; +} + +/************************************* + * + * Two operand + * + *************************************/ + +enum +{ + SUBR = 0x0, + SUBRC = 0x1, + SUBS = 0x2, + SUBSC = 0x3, + ADD = 0x4, + ADDC = 0x5, + AND = 0x6, + NAND = 0x7, + EXOR = 0x8, + NOR = 0x9, + OR = 0xa, + EXNOR = 0xb +}; + +static UINT16 tor_op(esrip_state *cpustate, UINT16 r, UINT16 s, int opcode) +{ + UINT32 res = 0; + + switch (opcode) + { + case SUBR: + { + res = s - r; + calc_v_flag_sub(cpustate, s, r, res); + calc_n_flag(cpustate, res); + calc_c_flag_sub(cpustate, s, r); + calc_z_flag(cpustate, res); + break; + } + case SUBRC: assert(0); break; + case SUBS: + { + res = r - s; + calc_v_flag_sub(cpustate, r, s, res); + calc_n_flag(cpustate, res); + calc_c_flag_sub(cpustate, r, s); + calc_z_flag(cpustate, res); + break; + } + case SUBSC: assert(0); break; + case ADD: + { + res = r + s; + calc_v_flag_add(cpustate, r, s, res); + calc_n_flag(cpustate, res); + calc_c_flag_add(cpustate, r, s); + calc_z_flag(cpustate, res); + break; + } + case ADDC: + { + // TODO TODO CHECK ME ETC + res = r + s + ((cpustate->status >> 1) & 1); + calc_v_flag_add(cpustate, r, s, res); + calc_n_flag(cpustate, res); + calc_c_flag_add(cpustate, r, s); + calc_z_flag(cpustate, res); + break; + } + case AND: + { + res = r & s; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + break; + } + case NAND: + { + res = (r & s) ^ 0xffff; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + break; + } + case EXOR: + { + res = r ^ s; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + break; + } + case NOR: + { + res = (r | s) ^ 0xffff; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + break; + } + case OR: + { + res = r | s; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + break; + } + case EXNOR: + { + res = (r ^ s) ^ 0xffff; + CLEAR_FLAGS(V_FLAG | N_FLAG | C_FLAG); + calc_z_flag(cpustate, res); + break; + } + default: assert(0); + } + + return res & 0xffff; +} + +static void tor1(esrip_state *cpustate, UINT16 inst) +{ + UINT16 r = 0; + UINT16 s = 0; + UINT16 dst = 0; + UINT16 res = 0; + + enum + { + TORAA = 0x0, + TORIA = 0x2, + TODRA = 0x3, + TORAY = 0x8, + TORIY = 0xa, + TODRY = 0xb, + TORAR = 0xc, + TORIR = 0xe, + TODRR = 0xf, + }; + + switch (SRC) + { + case TORAA: r = cpustate->ram[RAM_ADDR]; s = cpustate->acc; dst = ACC; break; + case TORIA: + { + if (cpustate->immflag == 0) + { + cpustate->i_latch = inst; + cpustate->immflag = 1; + return; + } + else + { + r = cpustate->ram[RAM_ADDR]; + s = cpustate->inst; + dst = ACC; + cpustate->immflag = 0; + } + break; + } + case TODRA: r = cpustate->d_latch; s = cpustate->ram[RAM_ADDR]; dst = ACC; break; + case TORAY: r = cpustate->ram[RAM_ADDR]; s = cpustate->acc; dst = Y_BUS;break; + case TORIY: + { + if (cpustate->immflag == 0) + { + cpustate->i_latch = inst; + cpustate->immflag = 1; + return; + } + else + { + r = cpustate->ram[RAM_ADDR]; + s = cpustate->inst; + dst = Y_BUS; + cpustate->immflag = 0; + } + break; + } + case TODRY: r = cpustate->d_latch; s = cpustate->ram[RAM_ADDR]; dst = Y_BUS;break; + case TORAR: r = cpustate->ram[RAM_ADDR]; s = cpustate->acc; dst = RAM; break; + case TORIR: + { + if (cpustate->immflag == 0) + { + cpustate->i_latch = inst; + cpustate->immflag = 1; + return; + } + else + { + r = cpustate->ram[RAM_ADDR]; + s = cpustate->inst; + dst = RAM; + cpustate->immflag = 0; + } + break; + } + case TODRR: r = cpustate->d_latch; s = cpustate->ram[RAM_ADDR]; dst = RAM; break; + default: INVALID; + } + + /* Operation */ + res = tor_op(cpustate, r, s, (inst >> 5) & 0xf); + + /* Destination */ + switch (dst) + { + case ACC: cpustate->acc = res; break; + case Y_BUS: break; + case RAM: cpustate->ram[RAM_ADDR] = res; break; + default: INVALID; + } + + cpustate->result = res; +} + +static void tor2(esrip_state *cpustate, UINT16 inst) +{ + UINT16 r = 0; + UINT16 s = 0; + UINT32 res = 0; + + enum + { + TODAR = 0x1, + TOAIR = 0x2, + TODIR = 0x5, + }; + + switch (SRC) + { + case TODAR: r = cpustate->d_latch; s = cpustate->acc; break; + case TOAIR: + { + if (cpustate->immflag == 0) + { + cpustate->i_latch = inst; + cpustate->immflag = 1; + return; + } + else + { + r = cpustate->acc; + s = cpustate->inst; + cpustate->immflag = 0; + } + break; + } + case TODIR: + { + if (cpustate->immflag == 0) + { + cpustate->i_latch = inst; + cpustate->immflag = 1; + return; + } + else + { + r = cpustate->d_latch; + s = cpustate->inst; + cpustate->immflag = 0; + } + break; + } + default: INVALID; + } + + /* Operation */ + res = tor_op(cpustate, r, s, (inst >> 5) & 0xf); + + /* Destination is always RAM */ + cpustate->ram[RAM_ADDR] = res; + + cpustate->result = res; +} + +static void tonr(esrip_state *cpustate, UINT16 inst) +{ + enum + { + TODA = 0x1, + TOAI = 0x2, + TODI = 0x5 + }; + + enum + { + NRY = 0, + NRA = 1, + NRS = 4, + NRAS = 5, + }; + + UINT16 r = 0; + UINT16 s = 0; + UINT16 res = 0; + + switch (SRC) + { + case TODA: + { + r = cpustate->d_latch; + s = cpustate->acc; + break; + } + case TOAI: + { + break; + } + case TODI: + { + if (cpustate->immflag == 0) + { + cpustate->i_latch = inst; + cpustate->immflag = 1; + return; + } + else + { + r = cpustate->d_latch; + s = cpustate->inst; + cpustate->immflag = 0; + } + break; + } + default: INVALID; + } + + /* Operation */ + res = tor_op(cpustate, r, s, (inst >> 5) & 0xf); + + /* Destination */ + switch (DST) + { + case NRY: + break; + case NRA: + cpustate->acc = res; + break; + case NRS: + UNHANDLED; + break; + case NRAS: + UNHANDLED; + break; + default: + INVALID; + } + cpustate->result = res; +} + +/************************************* + * + * Bit operation + * + *************************************/ + +static void bonr(esrip_state *cpustate, UINT16 inst) +{ + enum + { + TSTNA = 0x00, + RSTNA = 0x01, + SETNA = 0x02, + A2NA = 0x04, + S2NA = 0x05, + LD2NA = 0x06, + LDC2NA = 0x07, + TSTND = 0x10, + RSTND = 0x11, + SETND = 0x12, + A2NDY = 0x14, + S2NDY = 0x15, + LD2NY = 0x16, + LDC2NY = 0x17, + }; + + UINT16 res = 0; + + switch (inst & 0x1f) + { + case TSTNA: + { + res = cpustate->acc & (1 << N); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + break; + } + case RSTNA: + { + res = cpustate->acc & ~(1 << N); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + cpustate->acc = res; + break; + } + case SETNA: + { + res = cpustate->acc | (1 << N); + CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG); + calc_n_flag(cpustate, res); + cpustate->acc = res; + break; + } + case A2NA: + { + UINT16 r = cpustate->acc; + UINT16 s = 1 << N; + res = r + s; + calc_z_flag(cpustate, res); + calc_n_flag(cpustate, res); + calc_c_flag_add(cpustate, r, s); + calc_v_flag_add(cpustate, r, s, res); + cpustate->acc = res; + break; + } + case S2NA: + { + UINT16 r = cpustate->acc; + UINT16 s = 1 << N; + res = r - s; + calc_z_flag(cpustate, res); + calc_n_flag(cpustate, res); + calc_c_flag_sub(cpustate, r, s); + calc_v_flag_sub(cpustate, r, s, res); + cpustate->acc = res; + break; + } + + case TSTND: + { + res = cpustate->d_latch & (1 << N); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + break; + } + + case SETND: + { + UINT16 r = cpustate->d_latch; + res = r | (1 << N); + cpustate->d_latch = res; + + CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG); + calc_n_flag(cpustate, res); + break; + } + case LD2NY: + { + res = (1 << N); + CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG); + calc_n_flag(cpustate, res); + break; + } + case LDC2NY: + { + res = (1 << N) ^ 0xffff; + CLEAR_FLAGS(Z_FLAG | C_FLAG | V_FLAG); + calc_n_flag(cpustate, res); + break; + } + + case A2NDY: + { + UINT16 r = cpustate->d_latch; + UINT16 s = 1 << N; + res = r + s; + + calc_z_flag(cpustate, res); + calc_n_flag(cpustate, res); + calc_c_flag_add(cpustate, r, s); + calc_v_flag_add(cpustate, r, s, res); + break; + } + + default: + UNHANDLED; + } + + cpustate->result = res; +} + +static void bor1(esrip_state *cpustate, UINT16 inst) +{ + enum + { + SETNR = 0xd, + RSTNR = 0xe, + TSTNR = 0xf, + }; + + UINT16 res = 0; + + switch ((inst >> 5) & 0xf) + { + case SETNR: + { + res = cpustate->ram[RAM_ADDR] | (1 << N); + cpustate->ram[RAM_ADDR] = res; + CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG); + calc_n_flag(cpustate, res); + break; + } + case RSTNR: + { + res = cpustate->ram[RAM_ADDR] & ~(1 << N); + cpustate->ram[RAM_ADDR] = res; + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + break; + } + case TSTNR: + { + res = cpustate->ram[RAM_ADDR] & (1 << N); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + break; + } + default: INVALID; + } + + cpustate->result = res; +} + + + +static void bor2(esrip_state *cpustate, UINT16 inst) +{ + enum + { + LD2NR = 0xc, + LDC2NR = 0xd, + A2NR = 0xe, + S2NR = 0xf, + }; + + UINT32 res = 0; + + switch ((inst >> 5) & 0xf) + { + case LD2NR: + { + res = 1 << N; + CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG); + calc_n_flag(cpustate, res); + break; + } + case LDC2NR: + { + res = (1 << N) ^ 0xffff; + CLEAR_FLAGS(V_FLAG | C_FLAG | Z_FLAG); + calc_n_flag(cpustate, res); + break; + } + case A2NR: + { + UINT16 r = cpustate->ram[RAM_ADDR]; + UINT16 s = 1 << N; + + res = r + s; + calc_v_flag_add(cpustate, r, s, res); + calc_n_flag(cpustate, res); + calc_c_flag_add(cpustate, r, s); + calc_z_flag(cpustate, res); + break; + } + case S2NR: + { + UINT16 r = cpustate->ram[RAM_ADDR]; + UINT16 s = 1 << N; + + res = r - s; + calc_v_flag_sub(cpustate, r, s, res); + calc_n_flag(cpustate, res); + calc_c_flag_sub(cpustate, r, s); + calc_z_flag(cpustate, res); + break; + } + default: INVALID; + } + + /* Destination is RAM */ + cpustate->ram[RAM_ADDR] = res; + cpustate->result = res; +} + +/************************************* + * + * Rotate + * + *************************************/ + +/* TODO Combine these */ +static void rotr1(esrip_state *cpustate, UINT16 inst) +{ + enum + { + RTRA = 0xc, + RTRY = 0xd, + RTRR = 0xf, + }; + + UINT16 u = 0; + UINT16 dst = 0; + UINT16 res = 0; + int n = N; + + switch ((inst >> 5) & 0xf) + { + case RTRA: u = cpustate->ram[RAM_ADDR]; dst = ACC; break; + case RTRY: u = cpustate->ram[RAM_ADDR]; dst = Y_BUS; break; + case RTRR: u = cpustate->ram[RAM_ADDR]; dst = RAM; break; + default: INVALID; + } + + res = (u << n) | (u >> (16 - n)); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + + switch (dst) + { + case ACC: cpustate->acc = res; break; + case RAM: cpustate->ram[RAM_ADDR] = res; break; + } + + cpustate->result = res; +} + +static void rotr2(esrip_state *cpustate, UINT16 inst) +{ + enum + { + RTAR = 0, + RTDR = 1, + }; + + UINT16 u = 0; + UINT16 res = 0; + + switch ((inst >> 5) & 0xf) + { + case RTAR: u = cpustate->acc; break; + case RTDR: u = cpustate->d_latch; break; + default: INVALID; + } + + res = (u << N) | (u >> (16 - N)); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + cpustate->ram[RAM_ADDR] = res; + + cpustate->result = res; +} + +static void rotnr(esrip_state *cpustate, UINT16 inst) +{ + enum + { + RTDY = 0x18, + RTDA = 0x19, + RTAY = 0x1c, + RTAA = 0x1d, + }; + + UINT16 u = 0; + UINT16 res = 0; + UINT16 dst = 0; + + switch (inst & 0x1f) + { + case RTDY: u = cpustate->d_latch; dst = Y_BUS; break; + case RTDA: u = cpustate->d_latch; dst = ACC; break; + case RTAY: u = cpustate->acc; dst = Y_BUS; break; + case RTAA: u = cpustate->acc; dst = ACC; break; + default: INVALID; + } + + res = (u << N) | (u >> (16 - N)); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + + switch (dst) + { + case Y_BUS: break; + case ACC: cpustate->acc = res; break; + case RAM: cpustate->ram[RAM_ADDR] = res; break; + default: UNHANDLED; + } + + cpustate->result = res; +} + +/************************************* + * + * Rotate and compare + * + *************************************/ + +static void rotc(esrip_state *cpustate, UINT16 inst) +{ + UNHANDLED; +} + +/************************************* + * + * Rotate and merge + * + *************************************/ + +static void rotm(esrip_state *cpustate, UINT16 inst) +{ + UNHANDLED; +} + +/************************************* + * + * Prioritize + * + *************************************/ + +static void prt(esrip_state *cpustate, UINT16 inst) +{ + UNHANDLED; +} + +static void prtnr(esrip_state *cpustate, UINT16 inst) +{ + UNHANDLED; +} + + +/************************************* + * + * CRC + * + *************************************/ + +static void crcf(esrip_state *cpustate, UINT16 inst) +{ + UNHANDLED; +} + +static void crcr(esrip_state *cpustate, UINT16 inst) +{ + UNHANDLED; +} + +/************************************* + * + * Single bit shift + * + *************************************/ + +enum +{ + SHUPZ = 0, + SHUP1 = 1, + SHUPL = 2, + SHDNZ = 4, + SHDN1 = 5, + SHDNL = 6, + SHDNC = 7, + SHDNOV = 8, +}; + +#define SET_LINK_flag(cpustate, x) (cpustate->new_status &= ~L_FLAG); \ + (cpustate->new_status |= x ? L_FLAG : 0) + +static UINT16 shift_op(esrip_state *cpustate, UINT16 u, int opcode) +{ + UINT32 res = 0; + + switch (opcode) + { + case SHUPZ: + { + res = (u << 1); + SET_LINK_flag(cpustate, u & 0x8000); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + break; + } + case SHUP1: + { + res = (u << 1) | 1; + SET_LINK_flag(cpustate, u & 0x8000); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + break; + } + case SHUPL: + { + res = (u << 1) | ((cpustate->status & L_FLAG) ? 1 : 0); + SET_LINK_flag(cpustate, u & 0x8000); + CLEAR_FLAGS(V_FLAG | C_FLAG); + calc_n_flag(cpustate, res); + calc_z_flag(cpustate, res); + break; + } + + case SHDNZ: + case SHDN1: + case SHDNL: + case SHDNC: + case SHDNOV: + default: assert(0); + } + + return res; +} + +static void shftr(esrip_state *cpustate, UINT16 inst) +{ + enum + { + SHRR = 6, + SHDR = 7, + }; + + UINT16 u = 0; + UINT16 res = 0; + + switch ((inst >> 9) & 0xf) + { + case SHRR: u = cpustate->ram[RAM_ADDR]; break; + case SHDR: u = cpustate->d_latch; break; + default: INVALID; + } + + res = shift_op(cpustate, u, (inst >> 5) & 0xf); + + /* Destination is always RAM */ + cpustate->ram[RAM_ADDR] = res; + cpustate->result = res; +} + +static void shftnr(esrip_state *cpustate, UINT16 inst) +{ + enum + { + SHA = 6, + SHD = 7, + }; + + UINT16 u = 0; + UINT16 res = 0; + + switch ((inst >> 9) & 0xf) + { + case SHA: u = cpustate->acc; break; + case SHD: u = cpustate->d_latch; break; + default: INVALID; + } + + res = shift_op(cpustate, u, (inst >> 5) & 0xf); + + switch (DST) + { + case NRY: break; + case NRA: cpustate->acc = res; break; + default: INVALID; + } + cpustate->result = res; +} + + +/************************************* + * + * Status + * + *************************************/ + +static void svstr(esrip_state *cpustate, UINT16 inst) +{ + UNHANDLED; +} + +static void rstst(esrip_state *cpustate, UINT16 inst) +{ + enum + { + RONCZ = 0x3, + RL = 0x5, + RF1 = 0x6, + RF2 = 0x9, + RF3 = 0xa, + }; + + switch (inst & 0x1f) + { + case RONCZ: CLEAR_FLAGS(V_FLAG | N_FLAG | C_FLAG | Z_FLAG); break; + case RL: CLEAR_FLAGS(L_FLAG); break; + case RF1: CLEAR_FLAGS(FLAG_1); break; + case RF2: CLEAR_FLAGS(FLAG_2); break; + case RF3: CLEAR_FLAGS(FLAG_3); break; + } + + cpustate->result = 0; +} + +static void setst(esrip_state *cpustate, UINT16 inst) +{ + enum + { + SONCZ = 0x3, + SL = 0x5, + SF1 = 0x6, + SF2 = 0x9, + SF3 = 0xa, + }; + + switch (inst & 0x1f) + { + case SONCZ: SET_FLAGS(V_FLAG | N_FLAG | C_FLAG | Z_FLAG); break; + case SL: SET_FLAGS(L_FLAG); break; + case SF1: SET_FLAGS(FLAG_1); break; + case SF2: SET_FLAGS(FLAG_2); break; + case SF3: SET_FLAGS(FLAG_3); break; + } + + cpustate->result = 0xffff; +} + +static void test(esrip_state *cpustate, UINT16 inst) +{ + enum + { + TNOZ = 0x00, + TNO = 0x02, + TZ = 0x04, + TOVR = 0x06, + TLOW = 0x08, + TC = 0x0a, + TZC = 0x0c, + TN = 0x0e, + TL = 0x10, + TF1 = 0x12, + TF2 = 0x14, + TF3 = 0x16 + }; + + UINT32 res = 0; + + switch (inst & 0x1f) + { + case TNOZ: UNHANDLED; break; + case TNO: UNHANDLED; break; + case TZ: res = cpustate->status & (Z_FLAG); break; + case TOVR: res = cpustate->status & (V_FLAG); break; + case TLOW: UNHANDLED; break; + case TC: res = cpustate->status & (C_FLAG); break; + case TZC: UNHANDLED; break; + case TN: res = cpustate->status & (N_FLAG); break; + case TL: res = cpustate->status & (L_FLAG); break; + case TF1: res = cpustate->status & (FLAG_1); break; + case TF2: res = cpustate->status & (FLAG_2); break; + case TF3: res = cpustate->status & (FLAG_3); break; + default: INVALID; + } + + cpustate->ct = res && 1; +} + + +/************************************* + * + * No operation + * + *************************************/ + +static void nop(esrip_state *cpustate, UINT16 inst) +{ + cpustate->result = 0xff; // Undefined +} + +static void (*const operations[24])(esrip_state *cpustate, UINT16 inst) = +{ + rotr1, tor1, rotr2, rotc, rotm, bor2, crcf, crcr, + svstr, prt, sor, tor2, shftr, test, nop, setst, rstst, + rotnr, bonr, bor1, sonr, shftnr, prtnr, tonr +}; + +INLINE void am29116_execute(esrip_state *cpustate, UINT16 inst, int _sre) +{ + /* Status register shadow */ + cpustate->new_status = cpustate->status; + + /* Required for immediate source instructions */ + cpustate->inst = inst; + + if (cpustate->immflag == 1) + inst = cpustate->i_latch; + + (*operations[cpustate->optable[inst]])(cpustate, inst); + + if (!_sre) + { + cpustate->status = cpustate->new_status; + cpustate->t = cpustate->status; + } +} + + +static CPU_EXECUTE( esrip ) +{ + esrip_state *cpustate = device->token; + int calldebugger = (device->machine->debug_flags & DEBUG_FLAG_ENABLED) != 0; + UINT16 status = cpustate->status_in(device->machine); + + cpustate->icount = cycles; + + /* Core execution loop */ + do + { + UINT64 inst; + UINT8 next_pc; + UINT16 x_bus = 0; + UINT16 ipt_bus = 0; + UINT16 y_bus = 0; + + int yoe = _BIT(cpustate->l5, 1); + int bl46 = BIT(cpustate->l4, 6); + int bl44 = BIT(cpustate->l4, 4); + + UINT32 in_h; + UINT32 in_l; + + if (cpustate->fig_cycles) + { + if(--cpustate->fig_cycles == 0) + cpustate->fig = 0; + } + + /* /OEY = 1 : Y-bus is high imped */ + if (yoe) + { + /* Status In */ + if (!_BIT(cpustate->l2, 0)) + y_bus = status | (!cpustate->fig << 3); + + /* FDT RAM: /Enable, Direction and /RAM OE */ + else if (!bl44 && !_BIT(cpustate->l2, 3) && bl46) + y_bus = cpustate->fdt_r(device, cpustate->fdt_cnt, 0); + + /* IPT RAM: /Enable and /READ */ + else if (!_BIT(cpustate->l2, 6) && !_BIT(cpustate->l4, 5)) + y_bus = cpustate->ipt_ram[cpustate->ipt_cnt]; + + /* DLE - latch the value on the Y-BUS into the data latch */ + if (_BIT(cpustate->l5, 0)) + cpustate->d_latch = y_bus; + + /* Now execute the AM29116 instruction */ + am29116_execute(cpustate, (cpustate->l7 << 8) | cpustate->l6, BIT(cpustate->l5, 2)); + } + else + { + am29116_execute(cpustate, (cpustate->l7 << 8) | cpustate->l6, BIT(cpustate->l5, 2)); + + y_bus = cpustate->result; + + if (BIT(cpustate->l5, 0)) + cpustate->d_latch = y_bus; + } + + /* Determine what value is on the X-Bus */ + + /* FDT RAM */ + if (!bl44) + x_bus = cpustate->fdt_r(device, cpustate->fdt_cnt, 0); + + /* Buffer is enabled - write direction */ + else if (!BIT(cpustate->l2, 3) && !bl46) + { + if (!yoe) + x_bus = y_bus; + else if ( !BIT(cpustate->l2, 6) && !BIT(cpustate->l4, 5) ) + x_bus = cpustate->ipt_ram[cpustate->ipt_cnt]; + } + + /* IPT BUS */ + if (!BIT(cpustate->l2, 6)) + ipt_bus = cpustate->ipt_ram[cpustate->ipt_cnt]; + else if (!BIT(cpustate->l4, 5)) + { + if (!BIT(cpustate->l5, 1)) + ipt_bus = y_bus; + else + ipt_bus = x_bus; + } + + + /* Write FDT RAM: /Enable, Direction and WRITE */ + if (!BIT(cpustate->l2, 3) && !bl46 && !BIT(cpustate->l4, 3)) + cpustate->fdt_w(device, cpustate->fdt_cnt, x_bus, 0); + + /* Write IPT RAM: /Enable and /WR */ + if (!BIT(cpustate->l2, 7) && !BIT(cpustate->l4, 5)) + cpustate->ipt_ram[cpustate->ipt_cnt] = ipt_bus; + + + if ((((cpustate->l5 >> 3) & 0x1f) & 0x18) != 0x18) + { + if ( check_jmp(cpustate, device->machine, (cpustate->l5 >> 3) & 0x1f) ) + next_pc = cpustate->l1; + else + next_pc = cpustate->pc + 1; + } + else + next_pc = cpustate->pc + 1; + + cpustate->pl1 = cpustate->l1; + cpustate->pl2 = cpustate->l2; + cpustate->pl3 = cpustate->l3; + cpustate->pl4 = cpustate->l4; + cpustate->pl5 = cpustate->l5; + cpustate->pl6 = cpustate->l6; + cpustate->pl7 = cpustate->l7; + + /* Latch instruction */ + inst = memory_decrypted_read_qword(cpustate->program, RIP_PC << 3); + + in_h = inst >> 32; + in_l = inst & 0xffffffff; + + cpustate->l1 = (in_l >> 8); + cpustate->l2 = (in_l >> 16); + cpustate->l3 = (in_l >> 24); + + cpustate->l4 = (in_h >> 0); + cpustate->l5 = (in_h >> 8); + cpustate->l6 = (in_h >> 16); + cpustate->l7 = (in_h >> 24); + +// if (RISING_EDGE(cpustate->pl7, cpustate->l2, 7)) + + /* Colour latch */ + if (RISING_EDGE(cpustate->pl3, cpustate->l3, 0)) + cpustate->c_latch = (x_bus >> 12) & 0xf; + + /* Right pixel line buffer address */ + if (RISING_EDGE(cpustate->pl3, cpustate->l3, 1)) + cpustate->adr_latch = x_bus & 0xfff; + + /* Left pixel line buffer address */ + if (RISING_EDGE(cpustate->pl3, cpustate->l3, 2)) + cpustate->adl_latch = x_bus & 0xfff; + + /* FIGLD: Start the DMA */ + if (RISING_EDGE(cpustate->pl3, cpustate->l3, 3)) + { + cpustate->attr_latch = x_bus; + + cpustate->fig = 1; + cpustate->fig_cycles = cpustate->draw(device->machine, cpustate->adl_latch, cpustate->adr_latch, cpustate->fig_latch, cpustate->attr_latch, cpustate->iaddr, cpustate->c_latch, cpustate->x_scale, cpustate->line_latch); + } + + /* X-scale */ + if (RISING_EDGE(cpustate->pl3, cpustate->l3, 4)) + cpustate->x_scale = x_bus >> 8; + + /* Y-scale. Something else uses this too? */ + if (RISING_EDGE(cpustate->pl4, cpustate->l4, 2)) + cpustate->y_scale = x_bus & 0xff; + + /* Unknown */ +// if (RISING_EDGE(cpustate->pl4, cpustate->l4, 7)) + + /* Image ROM address */ + if (RISING_EDGE(cpustate->pl3, cpustate->l3, 5)) + cpustate->iaddr = y_bus; + + /* IXLLD */ + if (RISING_EDGE(cpustate->pl3, cpustate->l3, 6)) + { + cpustate->line_latch = ipt_bus >> 10; + cpustate->fig_latch = ipt_bus & 0x3ff; + } + + /* Status write */ + if (RISING_EDGE(cpustate->pl3, cpustate->l3, 7)) + cpustate->status_out = y_bus & 0xff; + + /* FDT address counter */ + if (!BIT(cpustate->pl2, 1)) + cpustate->fdt_cnt = y_bus & 0xfff; + else if (BIT(cpustate->pl2, 2)) + cpustate->fdt_cnt = (cpustate->fdt_cnt + 1) & 0xfff; + + /* Now we can alter the IPT address counter */ + if (!BIT(cpustate->pl2, 4)) + cpustate->ipt_cnt = y_bus & 0x1fff; + else if (BIT(cpustate->pl2, 5)) + cpustate->ipt_cnt = (cpustate->ipt_cnt + 1) & 0x1fff; + + if (calldebugger) + debugger_instruction_hook(device, RIP_PC); + + cpustate->pc = next_pc; + + cpustate->icount--; + } while (cpustate->icount > 0); + + return cycles - cpustate->icount; +} + + +/*************************************************************************** + DISASSEMBLY HOOK +***************************************************************************/ + +static CPU_DISASSEMBLE( esrip ) +{ +#if 0 + static const char* const jmp_types[] = + { + "JCT", + "JT1", + "JT2", + "JT3", + "JT4", + "JLBRM", + "J#HBLANK", + "JMP", + }; + + static const char* const njmp_types[] = + { + "JNCT", + "JNT1", + "JNT2", + "JNT3", + "JNT4", + "JNLBRM", + "J#HBLANK", + " ", + }; +#endif + + UINT64 inst = BIG_ENDIANIZE_INT64(*(UINT64 *)oprom); + + UINT32 inst_hi = inst >> 32; + UINT32 inst_lo = inst & 0xffffffff; + + UINT16 ins = (inst_hi >> 16) & 0xffff; + UINT8 ctrl = (inst_hi >> 8) & 0xff; + UINT8 jmp_dest = (inst_lo >> 8) & 0xff; + + UINT8 jmp_ctrl = (ctrl >> 3) & 0x1f; + + UINT8 ctrl1 = (inst_lo >> 16) & 0xff; + UINT8 ctrl2 = (inst_lo >> 24) & 0xff; + UINT8 ctrl3 = (inst_hi) & 0xff; + + sprintf(buffer, "%.4x %c%c%c%c %.2x %s%s%s%s%s%s%s%s %c%s%s%s %c%c%c%c%c%c%c%c\n", + ins, + ctrl & 1 ? 'D' : ' ', + ctrl & 2 ? ' ' : 'Y', + ctrl & 4 ? 'S' : ' ', + (~jmp_ctrl & 0x18) ? 'J' : ' ', + jmp_dest, + ctrl1 & 0x01 ? " " : "I ", + ctrl1 & 0x02 ? " " : "FL", + ctrl1 & 0x04 ? "FE" : " ", + ctrl1 & 0x08 ? " " : "FR", + ctrl1 & 0x10 ? " " : "IL", + ctrl1 & 0x20 ? "IE" : " ", + ctrl1 & 0x40 ? " " : "IR", + ctrl1 & 0x80 ? " " : "IW", + + ctrl2 & 0x80 ? ' ' : 'O', + ctrl2 & 0x40 ? " " : "IXLLD", + ctrl2 & 0x20 ? " " : "IADLD", + ctrl2 & 0x10 ? " " : "SCALD", + + ctrl3 & 0x01 ? ' ' : '0', + ctrl3 & 0x02 ? ' ' : '1', + ctrl3 & 0x04 ? ' ' : '2', + ctrl3 & 0x08 ? ' ' : '3', + ctrl3 & 0x10 ? ' ' : '4', + ctrl3 & 0x20 ? ' ' : '5', + ctrl3 & 0x40 ? ' ' : '6', + ctrl3 & 0x80 ? ' ' : '7' + ); + + return 1 | DASMFLAG_SUPPORTED; +} + +/************************************************************************** + * set_info + **************************************************************************/ + +CPU_SET_INFO( esrip ) +{ + esrip_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 + ESRIP_PC: cpustate->pc = info->i & 0xff; + cpustate->status_out &= ~1; + cpustate->status_out |= ((info->i >> 8) & 1); + break; + } +} + +/************************************************************************** + * get_info + **************************************************************************/ + +CPU_GET_INFO( esrip ) +{ + esrip_state *cpustate = device->token; + + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(esrip_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_REGISTER: + case CPUINFO_INT_PC: info->i = RIP_PC; break; + case CPUINFO_INT_REGISTER + ESRIP_STATW: info->i = cpustate->status_out; break; + case CPUINFO_INT_REGISTER + ESRIP_FDTC: info->i = cpustate->fdt_cnt; break; + case CPUINFO_INT_REGISTER + ESRIP_IPTC: info->i = cpustate->ipt_cnt; 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(esrip); break; + case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(esrip); break; + case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(esrip); break; + case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(esrip); break; + case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(esrip); break; + case CPUINFO_FCT_BURN: info->burn = NULL; break; + case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(esrip); 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, "Real Time Image Processor"); break; + case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Entertainment Sciences"); 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%c%c%c%c%c%c", + cpustate->status & 0x80 ? '3' : '.', + cpustate->status & 0x40 ? '2' : '.', + cpustate->status & 0x20 ? '1' : '.', + cpustate->status & 0x10 ? 'L' : '.', + cpustate->status & 0x08 ? 'V' : '.', + cpustate->status & 0x04 ? 'N' : '.', + cpustate->status & 0x02 ? 'C' : '.', + cpustate->status & 0x01 ? 'Z' : '.', + get_hblank(device->machine) ? 'H' : '.'); break; + + case CPUINFO_STR_REGISTER + ESRIP_PC: sprintf(info->s, "PC: %04X", RIP_PC); break; + case CPUINFO_STR_REGISTER + ESRIP_ACC: sprintf(info->s, "ACC: %04X", cpustate->acc); break; + case CPUINFO_STR_REGISTER + ESRIP_DLATCH: sprintf(info->s, "DLATCH: %04X", cpustate->d_latch); break; + case CPUINFO_STR_REGISTER + ESRIP_ILATCH: sprintf(info->s, "ILATCH: %04X", cpustate->i_latch); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM00: sprintf(info->s, "RAM[00]: %04X", cpustate->ram[0x00]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM01: sprintf(info->s, "RAM[01]: %04X", cpustate->ram[0x01]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM02: sprintf(info->s, "RAM[02]: %04X", cpustate->ram[0x02]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM03: sprintf(info->s, "RAM[03]: %04X", cpustate->ram[0x03]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM04: sprintf(info->s, "RAM[04]: %04X", cpustate->ram[0x04]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM05: sprintf(info->s, "RAM[05]: %04X", cpustate->ram[0x05]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM06: sprintf(info->s, "RAM[06]: %04X", cpustate->ram[0x06]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM07: sprintf(info->s, "RAM[07]: %04X", cpustate->ram[0x07]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM08: sprintf(info->s, "RAM[08]: %04X", cpustate->ram[0x08]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM09: sprintf(info->s, "RAM[09]: %04X", cpustate->ram[0x09]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM0A: sprintf(info->s, "RAM[0A]: %04X", cpustate->ram[0x0a]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM0B: sprintf(info->s, "RAM[0B]: %04X", cpustate->ram[0x0b]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM0C: sprintf(info->s, "RAM[0C]: %04X", cpustate->ram[0x0c]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM0D: sprintf(info->s, "RAM[0D]: %04X", cpustate->ram[0x0d]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM0E: sprintf(info->s, "RAM[0E]: %04X", cpustate->ram[0x0e]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM0F: sprintf(info->s, "RAM[0F]: %04X", cpustate->ram[0x0f]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM10: sprintf(info->s, "RAM[10]: %04X", cpustate->ram[0x10]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM11: sprintf(info->s, "RAM[11]: %04X", cpustate->ram[0x11]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM12: sprintf(info->s, "RAM[12]: %04X", cpustate->ram[0x12]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM13: sprintf(info->s, "RAM[13]: %04X", cpustate->ram[0x13]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM14: sprintf(info->s, "RAM[14]: %04X", cpustate->ram[0x14]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM15: sprintf(info->s, "RAM[15]: %04X", cpustate->ram[0x15]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM16: sprintf(info->s, "RAM[16]: %04X", cpustate->ram[0x16]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM17: sprintf(info->s, "RAM[17]: %04X", cpustate->ram[0x17]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM18: sprintf(info->s, "RAM[18]: %04X", cpustate->ram[0x18]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM19: sprintf(info->s, "RAM[19]: %04X", cpustate->ram[0x19]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM1A: sprintf(info->s, "RAM[1A]: %04X", cpustate->ram[0x1a]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM1B: sprintf(info->s, "RAM[1B]: %04X", cpustate->ram[0x1b]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM1C: sprintf(info->s, "RAM[1C]: %04X", cpustate->ram[0x1c]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM1D: sprintf(info->s, "RAM[1D]: %04X", cpustate->ram[0x1d]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM1E: sprintf(info->s, "RAM[1E]: %04X", cpustate->ram[0x1e]); break; + case CPUINFO_STR_REGISTER + ESRIP_RAM1F: sprintf(info->s, "RAM[1F]: %04X", cpustate->ram[0x1f]); break; + case CPUINFO_STR_REGISTER + ESRIP_STATW: sprintf(info->s, "STAT: %04X", cpustate->status_out); break; + case CPUINFO_STR_REGISTER + ESRIP_FDTC: sprintf(info->s, "FDTC: %04X", cpustate->fdt_cnt); break; + case CPUINFO_STR_REGISTER + ESRIP_IPTC: sprintf(info->s, "IPTC: %04X", cpustate->ipt_cnt); break; + case CPUINFO_STR_REGISTER + ESRIP_XSCALE: sprintf(info->s, "XSCL: %04X", cpustate->x_scale); break; + case CPUINFO_STR_REGISTER + ESRIP_YSCALE: sprintf(info->s, "YSCL: %04X", cpustate->y_scale); break; + case CPUINFO_STR_REGISTER + ESRIP_LINE: sprintf(info->s, "LINE: %04X", cpustate->line_latch); break; + case CPUINFO_STR_REGISTER + ESRIP_FIG: sprintf(info->s, "FIG: %04X", cpustate->fig_latch); break; + case CPUINFO_STR_REGISTER + ESRIP_ATTR: sprintf(info->s, "ATTR: %04X", cpustate->attr_latch); break; + case CPUINFO_STR_REGISTER + ESRIP_ADRL: sprintf(info->s, "ADRL: %04X", cpustate->adl_latch); break; + case CPUINFO_STR_REGISTER + ESRIP_ADRR: sprintf(info->s, "ADRR: %04X", cpustate->adr_latch); break; + case CPUINFO_STR_REGISTER + ESRIP_COLR: sprintf(info->s, "COLR: %04X", cpustate->c_latch); break; + case CPUINFO_STR_REGISTER + ESRIP_IADDR: sprintf(info->s, "IADR: %04X", cpustate->iaddr); break; + } +} diff --git a/src/emu/cpu/esrip/esrip.h b/src/emu/cpu/esrip/esrip.h new file mode 100644 index 00000000000..c629f1d7f22 --- /dev/null +++ b/src/emu/cpu/esrip/esrip.h @@ -0,0 +1,104 @@ +/*************************************************************************** + + esrip.h + Interface file for the Entertainment Sciences RIP + Written by Phil Bennett + +***************************************************************************/ + +#ifndef _ESRIP_H +#define _ESRIP_H + +#include "cpuintrf.h" + + +/*************************************************************************** + COMPILE-TIME DEFINITIONS +***************************************************************************/ + + +/*************************************************************************** + GLOBAL CONSTANTS +***************************************************************************/ + + +/*************************************************************************** + REGISTER ENUMERATION +***************************************************************************/ + +enum +{ + ESRIP_PC = 1, + ESRIP_ACC, + ESRIP_DLATCH, + ESRIP_ILATCH, + ESRIP_RAM00, + ESRIP_RAM01, + ESRIP_RAM02, + ESRIP_RAM03, + ESRIP_RAM04, + ESRIP_RAM05, + ESRIP_RAM06, + ESRIP_RAM07, + ESRIP_RAM08, + ESRIP_RAM09, + ESRIP_RAM0A, + ESRIP_RAM0B, + ESRIP_RAM0C, + ESRIP_RAM0D, + ESRIP_RAM0E, + ESRIP_RAM0F, + ESRIP_RAM10, + ESRIP_RAM11, + ESRIP_RAM12, + ESRIP_RAM13, + ESRIP_RAM14, + ESRIP_RAM15, + ESRIP_RAM16, + ESRIP_RAM17, + ESRIP_RAM18, + ESRIP_RAM19, + ESRIP_RAM1A, + ESRIP_RAM1B, + ESRIP_RAM1C, + ESRIP_RAM1D, + ESRIP_RAM1E, + ESRIP_RAM1F, + ESRIP_STATW, + ESRIP_FDTC, + ESRIP_IPTC, + ESRIP_XSCALE, + ESRIP_YSCALE, + ESRIP_LINE, + ESRIP_FIG, + ESRIP_ATTR, + ESRIP_ADRL, + ESRIP_ADRR, + ESRIP_COLR, + ESRIP_IADDR, +}; + +/*************************************************************************** + CONFIGURATION STRUCTURE +***************************************************************************/ +typedef struct _esrip_config_ esrip_config; +struct _esrip_config_ +{ + read16_device_func fdt_r; + write16_device_func fdt_w; + UINT8 (*status_in)(running_machine *machine); + int (*draw)(running_machine *machine, int l, int r, int fig, int attr, int addr, int col, int x_scale, int line_latch); + const char* const lbrm_prom; +}; + +/*************************************************************************** + PUBLIC FUNCTIONS +***************************************************************************/ + +CPU_GET_INFO( esrip ); + +#define CPU_ESRIP CPU_GET_INFO_NAME( esrip ) + +extern UINT8 get_rip_status(const device_config *cpu); + +#endif /* _ESRIP_H */ diff --git a/src/mame/drivers/esripsys.c b/src/mame/drivers/esripsys.c new file mode 100644 index 00000000000..270e071be8e --- /dev/null +++ b/src/mame/drivers/esripsys.c @@ -0,0 +1,990 @@ +/*************************************************************************** + + Entertainment Sciences Real-Time Image Processor (RIP) hardware + + driver by Phil Bennett + + Games supported: + * Turbo Sub [2 sets] + + ROMs wanted: + * Bouncer + * Turbo Sub [later version] (uses 512kbit graphics ROMs) + + Notes: + * 'turbosub' executes a series of hardware tests on startup. + To skip, hold down keypad '*' on reset. + + Todo: + * TMS5220 speech? The game sends speech play commands to the sound + CPU but they're ignored. The speech data seems to be stored in + the upper half of the (banked) sound data ROMs but this is never + accessed. Maybe the speech data was unfinished and only the later + version of Turbo Sub has speech? + + * Determine if line drop outs occur on real hardware. Overclocking + the RIP CPU eliminates them. + + * Implement collision detection hardware (not used by Turbo Sub). + +****************************************************************************/ + +#include "driver.h" +#include "cpu/m6809/m6809.h" +#include "cpu/esrip/esrip.h" +#include "machine/6840ptm.h" +#include "sound/dac.h" +#include "sound/5220intf.h" +#include "esripsys.h" + + +/************************************* + * + * Statics + * + *************************************/ + +/* I/O */ +static UINT8 g_iodata; +static UINT8 g_ioaddr; +static UINT8 coin_latch; +static UINT8 keypad_status; +static UINT8 g_status; +static UINT8 f_status; +static int io_firq_status; +static UINT8 cmos_ram_a2_0; +static UINT8 cmos_ram_a10_3; +static UINT8 *cmos_ram; + +/* Sound */ +static UINT8 u56a; +static UINT8 u56b; +static UINT8 g_to_s_latch1; +static UINT8 g_to_s_latch2; +static UINT8 s_to_g_latch1; +static UINT8 s_to_g_latch2; +static UINT8 dac_msb; +static UINT8 dac_vol; +static UINT8 tms_data; + +/* Video */ +static UINT8 *fdt_a; +static UINT8 *fdt_b; +static int _fasel = 0; +static int _fbsel = 1; +//static int fig = 0; + +/************************************* + * + * 6840 PTM + * + *************************************/ + +static void ptm_irq(running_machine *machine, int state) +{ + cpu_set_input_line(machine->cpu[ESRIPSYS_SOUND_CPU], M6809_FIRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE); +} + +static const ptm6840_interface ptm_intf = +{ + 2000000, + { 0, 0, 0 }, + { NULL, NULL, NULL }, + ptm_irq +}; + + +/************************************* + * + * i8251A UART + * + *************************************/ + +/* Note: Game CPU /FIRQ is connected to RXRDY */ +static WRITE8_HANDLER( uart_w ) +{ + if ((offset & 1) == 0) + mame_printf_debug("%c",data); +} + +static READ8_HANDLER( uart_r ) +{ + return 0; +} + + +/************************************* + * + * Game CPU Status Ports + * + *************************************/ + +/* + Write Read + ===== ==== + 0: ROM bank bit 0 0: Frame CPU status D0 + 1: ROM bank bit 1 1: Frame CPU status D1 + 2: - 2: Frame CPU status D2 + 3: Bank sel enable? 3: Frame CPU status D3 + 4: Frame CPU /FIRQ 4: - + 5: /INTACK 5: Frame CPU status D5 + 6: - 6: RIP BANK 4 + 7: Frame CPU /NMI 7: /VBLANK +*/ + +static READ8_HANDLER( g_status_r ) +{ + int bank4 = BIT(get_rip_status(space->machine->cpu[ESRIPSYS_VIDEO_CPU]), 2); + int vblank = video_screen_get_vblank(space->machine->primary_screen); + + return (!vblank << 7) | (bank4 << 6) | (f_status & 0x2f); +} + +static WRITE8_HANDLER( g_status_w ) +{ + int bankaddress; + UINT8* const ROM = memory_region(space->machine, "game_cpu"); + + g_status = data; + + bankaddress = 0x10000 + (data & 0x03) * 0x10000; + memory_set_bankptr(space->machine, 1, &ROM[bankaddress]); + + cpu_set_input_line(space->machine->cpu[ESRIPSYS_FRAME_CPU], M6809_FIRQ_LINE, data & 0x10 ? CLEAR_LINE : ASSERT_LINE); + cpu_set_input_line(space->machine->cpu[ESRIPSYS_FRAME_CPU], INPUT_LINE_NMI, data & 0x80 ? CLEAR_LINE : ASSERT_LINE); + + cpu_set_input_line(space->machine->cpu[ESRIPSYS_VIDEO_CPU], INPUT_LINE_RESET, data & 0x40 ? CLEAR_LINE : ASSERT_LINE); + + /* /VBLANK IRQ acknowledge */ + if (!(data & 0x20)) + cpu_set_input_line(space->machine->cpu[ESRIPSYS_GAME_CPU], M6809_IRQ_LINE, CLEAR_LINE); +} + + +/************************************* + * + * Frame CPU Status Ports + * + *************************************/ + +/* + Write Read + ===== ==== + 0: Game CPU status in D0 0: /ERROR (AM29116) + 1: Game CPU status in D1 1: /IPT UPLOAD (AM29116) + 2: Game CPU status in D2 2: - + 3: Game CPU status in D3 3: RER0 (AM29116) + 4: - 4: RER1 (AM29116) + 5: Game CPU status in D5 5: VBLANK flag (cleared on FRAME write) + 6: - 6: /FBSEL + 7: /FRDONE 7: /VBLANK +*/ + +static READ8_HANDLER( f_status_r ) +{ + int vblank = video_screen_get_vblank(space->machine->primary_screen); + UINT8 rip_status = get_rip_status(space->machine->cpu[ESRIPSYS_VIDEO_CPU]); + + rip_status = (rip_status & 0x18) | (BIT(rip_status, 6) << 1) | BIT(rip_status, 7); + + return (!vblank << 7) | (_fbsel << 6) | (esripsys_frame_vbl << 5) | rip_status; +} + +static WRITE8_HANDLER( f_status_w ) +{ + f_status = data; +} + + +/************************************* + * + * Frame CPU Functions + * + *************************************/ + +static TIMER_CALLBACK( delayed_bank_swap ) +{ + _fasel ^= 1; + _fbsel ^= 1; +} + +static WRITE8_HANDLER( frame_w ) +{ + timer_call_after_resynch(space->machine, NULL, 0, delayed_bank_swap); + esripsys_frame_vbl = 1; +} + +static READ8_HANDLER( fdt_r ) +{ + if (!_fasel) + return fdt_b[offset]; + else + return fdt_a[offset]; +} + +static WRITE8_HANDLER( fdt_w ) +{ + if (!_fasel) + fdt_b[offset] = data; + else + fdt_a[offset] = data; +} + + +/************************************* + * + * Video CPU Functions + * + *************************************/ + +READ16_DEVICE_HANDLER( fdt_rip_r ) +{ + offset = (offset & 0x7ff) << 1; + + if (!_fasel) + return (fdt_a[offset] << 8) | fdt_a[offset + 1]; + else + return (fdt_b[offset] << 8) | fdt_b[offset + 1]; +} + +WRITE16_DEVICE_HANDLER( fdt_rip_w ) +{ + offset = (offset & 0x7ff) << 1; + + if (!_fasel) + { + fdt_a[offset + 0] = data >> 8; + fdt_a[offset + 1] = data & 0xff; + } + else + { + fdt_b[offset + 0] = data >> 8; + fdt_b[offset + 1] = data & 0xff; + } +} + +/* + D0 = /VBLANK + D1 = /HBLANK + D2 = 1/2SEL + D3 = /FIG + D4 = /FBSEL + D5 = VO + D6 = + D7 = /FDONE +*/ + +UINT8 rip_status_in(running_machine *machine) +{ + UINT8 _vblank = !video_screen_get_vblank(machine->primary_screen); + UINT8 _hblank = !video_screen_get_hblank(machine->primary_screen); + UINT8 v0 = video_screen_get_vpos(machine->primary_screen) & 1; + + return _vblank + | (_hblank << 1) + | (esripsys__12sel << 2) + | (_fbsel << 4) + | (v0 << 5) + | (f_status & 0x80); +} + +/************************************* + * + * I/O + * + *************************************/ + +static WRITE8_HANDLER( g_iobus_w ) +{ + g_iodata = data; +} + +static READ8_HANDLER( g_iobus_r ) +{ + switch (g_ioaddr & 0x7f) + { + case 0: + return s_to_g_latch2; + case 3: + return s_to_g_latch1; + case 5: + return cmos_ram[(cmos_ram_a10_3 << 3) | (cmos_ram_a2_0 & 3)]; + case 8: + { + int keypad = input_port_read(space->machine, "KEYPAD_B") | keypad_status; + keypad_status = 0; + io_firq_status = 0; + return keypad; + } + case 9: + { + return input_port_read(space->machine, "KEYPAD_A"); + } + case 0xa: + { + int coins = coin_latch | (input_port_read(space->machine, "COINS") & 0x30); + coin_latch = 0; + io_firq_status = 0; + return coins; + } + case 0x10: + return input_port_read(space->machine, "IO_1"); + case 0x11: + return input_port_read(space->machine, "JOYSTICK_X"); + case 0x12: + return input_port_read(space->machine, "JOYSTICK_Y"); + case 0x16: + return io_firq_status; + case 0x18: + return input_port_read(space->machine, "IO_2"); + /* Unused I/O */ + case 0x19: + case 0x1a: + return 0xff; + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5a: + case 0x5b: + case 0x5c: + case 0x5d: + case 0x5e: + /* MSM5832 real-time clock/calendar */ + return 0xff; + default: + { + logerror("Unknown I/O read (%x)\n", g_ioaddr & 0x7f); + return 0xff; + } + } +} + +static WRITE8_HANDLER( g_ioadd_w ) +{ + g_ioaddr = data; + + /* Bit 7 is connected to /OE of LS374 containing I/O data */ + if ((data & 0x80) == 0) + { + switch (g_ioaddr & 0x7f) + { + case 0x00: + { + g_to_s_latch1 = g_iodata; + break; + } + case 0x02: + { + cpu_set_input_line(space->machine->cpu[ESRIPSYS_SOUND_CPU], INPUT_LINE_NMI, g_iodata & 4 ? CLEAR_LINE : ASSERT_LINE); + + if (!(g_to_s_latch2 & 1) && (g_iodata & 1)) + { + /* Rising D0 will clock in 1 to FF1... */ + u56a = 1; + + /*...causing a sound CPU /IRQ */ + cpu_set_input_line(space->machine->cpu[ESRIPSYS_SOUND_CPU], M6809_IRQ_LINE, ASSERT_LINE); + } + + if (g_iodata & 2) + u56b = 0; + + g_to_s_latch2 = g_iodata; + + break; + } + case 0x04: + { + cmos_ram[(cmos_ram_a10_3 << 3) | (cmos_ram_a2_0 & 3)] = g_iodata; + break; + } + case 0x06: + { + cmos_ram_a10_3 = g_iodata; + break; + } + case 0x07: + { + cmos_ram_a2_0 = g_iodata; + break; + } + case 0x0b: + { + /* Possibly I/O acknowledge; see FIRQ */ + break; + } + case 0x14: + { + break; + } + case 0x15: + { + esripsys_video_firq_en = g_iodata & 1; + break; + } + default: + { + logerror("Unknown I/O write to %x with %x\n", g_ioaddr, g_iodata); + } + } + } +} + +static INPUT_CHANGED( keypad_interrupt ) +{ + if (newval == 0) + { + io_firq_status |= 2; + keypad_status |= 0x20; + cpu_set_input_line(field->port->machine->cpu[ESRIPSYS_GAME_CPU], M6809_FIRQ_LINE, HOLD_LINE); + } +} + +static INPUT_CHANGED( coin_interrupt ) +{ + if (newval == 1) + { + io_firq_status |= 2; + coin_latch = input_port_read(field->port->machine, "COINS") << 2; + cpu_set_input_line(field->port->machine->cpu[ESRIPSYS_GAME_CPU], M6809_FIRQ_LINE, HOLD_LINE); + } +} + +/************************************* + * + * Port definitions + * + *************************************/ + +INPUT_PORTS_START( turbosub ) + PORT_START("KEYPAD_A") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(3) PORT_CODE(KEYCODE_0_PAD) PORT_NAME("0") PORT_CHANGED(keypad_interrupt, 0) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(3) PORT_CODE(KEYCODE_1_PAD) PORT_NAME("1") PORT_CHANGED(keypad_interrupt, 0) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(3) PORT_CODE(KEYCODE_2_PAD) PORT_NAME("2") PORT_CHANGED(keypad_interrupt, 0) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(3) PORT_CODE(KEYCODE_3_PAD) PORT_NAME("3") PORT_CHANGED(keypad_interrupt, 0) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(3) PORT_CODE(KEYCODE_4_PAD) PORT_NAME("4") PORT_CHANGED(keypad_interrupt, 0) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(3) PORT_CODE(KEYCODE_5_PAD) PORT_NAME("5") PORT_CHANGED(keypad_interrupt, 0) + + PORT_START("KEYPAD_B") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON7 ) PORT_PLAYER(3) PORT_CODE(KEYCODE_6_PAD) PORT_NAME("6") PORT_CHANGED(keypad_interrupt, 0) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON8 ) PORT_PLAYER(3) PORT_CODE(KEYCODE_7_PAD) PORT_NAME("7") PORT_CHANGED(keypad_interrupt, 0) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON9 ) PORT_PLAYER(3) PORT_CODE(KEYCODE_8_PAD) PORT_NAME("8") PORT_CHANGED(keypad_interrupt, 0) + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON10 ) PORT_PLAYER(3) PORT_CODE(KEYCODE_9_PAD) PORT_NAME("9") PORT_CHANGED(keypad_interrupt, 0) + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON11 ) PORT_PLAYER(3) PORT_CODE(KEYCODE_ASTERISK) PORT_NAME("*") PORT_CHANGED(keypad_interrupt, 0) + + PORT_START("COINS") + PORT_BIT( 0x0f, IP_ACTIVE_HIGH, IPT_UNUSED ) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_CHANGED(coin_interrupt, 0) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_CHANGED(coin_interrupt, 0) + PORT_BIT( 0xc0, IP_ACTIVE_HIGH, IPT_UNUSED ) + + PORT_START("IO_1") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_NAME("Neutralizer") + PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Fire") + PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) + + /* Mirror of IO_1 (unused) */ + PORT_START("IO_2") + PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED ) + + PORT_START("JOYSTICK_X") + PORT_BIT( 0xff, 0x00, IPT_AD_STICK_X ) PORT_MINMAX(0xff, 0x00) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) + + PORT_START("JOYSTICK_Y") + PORT_BIT( 0xff, 0x00, IPT_AD_STICK_Y ) PORT_MINMAX(0xff, 0x00) PORT_SENSITIVITY(25) PORT_KEYDELTA(200) +INPUT_PORTS_END + + +/************************************* + * + * Sound + * + *************************************/ + +/* Game/Sound CPU communications */ +static READ8_HANDLER( s_200e_r ) +{ + return g_to_s_latch1; +} + +static WRITE8_HANDLER( s_200e_w ) +{ + s_to_g_latch1 = data; +} + +static WRITE8_HANDLER( s_200f_w ) +{ + /* Bit 6 -> Reset latch U56A */ + /* Bit 7 -> Clock latch U56B */ + + if (s_to_g_latch2 & 0x40) + { + u56a = 0; + cpu_set_input_line(space->machine->cpu[ESRIPSYS_SOUND_CPU], M6809_IRQ_LINE, CLEAR_LINE); + } + + if (!(s_to_g_latch2 & 0x40) && (data & 0x40)) + u56b = 1; + + s_to_g_latch2 = data; +} + +static READ8_HANDLER( s_200f_r ) +{ + return (g_to_s_latch2 & 0xfc) | (u56b << 1) | u56a; +} + +static READ8_HANDLER( tms5220_r ) +{ + if (offset == 0) + { + /* TMS5220 core returns status bits in D7-D6 */ + UINT8 status = tms5220_status_r(space, 0); + + status = (status & 0x80 >> 5) | (status & 0x40 >> 5) | (status & 0x20 >> 5); + return (!tms5220_ready_r() << 7) | (!tms5220_int_r() << 6) | status; + } + + return 0xff; +} + +static WRITE8_HANDLER( tms5220_w ) +{ + if (offset == 0) + { + if (tms5220_ready_r()) + tms5220_status_r(space, 0); + + tms_data = data; + } + if (offset == 1) + { + if (tms5220_ready_r()) + tms5220_data_w(0, 0, tms_data); + } +} + +/* Not used in later revisions */ +static WRITE8_HANDLER( control_w ) +{ + logerror("Sound control write: %.2x (PC:0x%.4x)\n", data, cpu_get_previouspc(space->cpu)); +} + + +/* 10-bit MC3410CL DAC */ +static WRITE8_HANDLER( dac_w ) +{ + if (offset == 0) + { + dac_msb = data & 3; + } + else + { + UINT16 dac_data = (dac_msb << 8) | data; + + /* + The 8-bit DAC modulates the 10-bit DAC. + Shift down to prevent clipping. + */ + dac_signed_data_16_w(0, (dac_vol * dac_data) >> 1); + } +} + +/* 8-bit MC3408 DAC */ +static WRITE8_HANDLER( volume_dac_w ) +{ + dac_vol = data; +} + + +/************************************* + * + * Memory Maps + * + *************************************/ + +static ADDRESS_MAP_START( game_cpu_map, ADDRESS_SPACE_PROGRAM, 8 ) + AM_RANGE(0x0000, 0x3fff) AM_RAM AM_SHARE(1) + AM_RANGE(0x4000, 0x42ff) AM_RAM AM_BASE(&esripsys_pal_ram) + AM_RANGE(0x4300, 0x4300) AM_WRITE(esripsys_bg_intensity_w) + AM_RANGE(0x4400, 0x47ff) AM_NOP /* Collision detection RAM */ + AM_RANGE(0x4800, 0x4bff) AM_READWRITE(g_status_r, g_status_w) + AM_RANGE(0x4c00, 0x4fff) AM_READWRITE(g_iobus_r, g_iobus_w) + AM_RANGE(0x5000, 0x53ff) AM_WRITE(g_ioadd_w) + AM_RANGE(0x5400, 0x57ff) AM_NOP + AM_RANGE(0x5c00, 0x5fff) AM_READWRITE(uart_r, uart_w) + AM_RANGE(0x6000, 0xdfff) AM_ROMBANK(1) + AM_RANGE(0xe000, 0xffff) AM_ROM +ADDRESS_MAP_END + + +static ADDRESS_MAP_START( frame_cpu_map, ADDRESS_SPACE_PROGRAM, 8 ) + AM_RANGE(0x0000, 0x3fff) AM_RAM AM_SHARE(1) + AM_RANGE(0x4000, 0x4fff) AM_READWRITE(fdt_r, fdt_w) + AM_RANGE(0x6000, 0x6000) AM_READWRITE(f_status_r, f_status_w) + AM_RANGE(0x8000, 0x8000) AM_WRITE(frame_w) + AM_RANGE(0xc000, 0xffff) AM_ROM +ADDRESS_MAP_END + + +static ADDRESS_MAP_START( sound_cpu_map, ADDRESS_SPACE_PROGRAM, 8 ) + AM_RANGE(0x0000, 0x07ff) AM_RAM + AM_RANGE(0x0800, 0x0fff) AM_RAM /* Not installed on later PCBs */ + AM_RANGE(0x2008, 0x2009) AM_READWRITE(tms5220_r, tms5220_w) + AM_RANGE(0x200a, 0x200b) AM_WRITE(dac_w) + AM_RANGE(0x200c, 0x200c) AM_WRITE(volume_dac_w) + AM_RANGE(0x200d, 0x200d) AM_WRITE(control_w) + AM_RANGE(0x200e, 0x200e) AM_READWRITE(s_200e_r, s_200e_w) + AM_RANGE(0x200f, 0x200f) AM_READWRITE(s_200f_r, s_200f_w) + AM_RANGE(0x2020, 0x2027) AM_READWRITE(ptm6840_0_r, ptm6840_0_w) + AM_RANGE(0x8000, 0x9fff) AM_ROMBANK(2) + AM_RANGE(0xa000, 0xbfff) AM_ROMBANK(3) + AM_RANGE(0xc000, 0xdfff) AM_ROMBANK(4) + AM_RANGE(0xe000, 0xffff) AM_ROM +ADDRESS_MAP_END + + +static ADDRESS_MAP_START( video_cpu_map, ADDRESS_SPACE_PROGRAM, 64 ) + AM_RANGE(0x000, 0x1ff) AM_ROM +ADDRESS_MAP_END + + +/************************************* + * + * Machine drivers + * + *************************************/ + +static DRIVER_INIT( esripsys ) +{ + UINT8* const ROM = memory_region(machine, "sound_data"); + + fdt_a = auto_malloc(FDT_RAM_SIZE); + fdt_b = auto_malloc(FDT_RAM_SIZE); + cmos_ram = auto_malloc(CMOS_RAM_SIZE); + + ptm6840_config(machine, 0, &ptm_intf); + + memory_set_bankptr(machine, 2, &ROM[0x0000+0x0000]); + memory_set_bankptr(machine, 3, &ROM[0x0000+0x4000]); + memory_set_bankptr(machine, 4, &ROM[0x0000+0x8000]); + + /* TODO: Finish me! */ +// state_save_register_global_pointer(fdt_a, FDT_RAM_SIZE); +// state_save_register_global_pointer(fdt_b, FDT_RAM_SIZE); +} + +static NVRAM_HANDLER( esripsys ) +{ + if (read_or_write) + mame_fwrite(file, cmos_ram, CMOS_RAM_SIZE); + else if (file) + mame_fread(file, cmos_ram, CMOS_RAM_SIZE); + else + memset(cmos_ram, 0x00, CMOS_RAM_SIZE); +} + +static esrip_config rip_config = +{ + fdt_rip_r, + fdt_rip_w, + rip_status_in, + esripsys_draw, + "proms" +}; + +static MACHINE_DRIVER_START( esripsys ) + MDRV_CPU_ADD("game_cpu", M6809E, XTAL_8MHz) + MDRV_CPU_PROGRAM_MAP(game_cpu_map, 0) + MDRV_CPU_VBLANK_INT("main", esripsys_vblank_irq) + + MDRV_CPU_ADD("frame_cpu", M6809E, XTAL_8MHz) + MDRV_CPU_PROGRAM_MAP(frame_cpu_map, 0) + + MDRV_CPU_ADD("video_cpu", ESRIP, XTAL_40MHz/4) + MDRV_CPU_PROGRAM_MAP(video_cpu_map, 0) + MDRV_CPU_CONFIG(rip_config) + + MDRV_CPU_ADD("sound_cpu", M6809E, XTAL_8MHz) + MDRV_CPU_PROGRAM_MAP(sound_cpu_map, 0) + + MDRV_NVRAM_HANDLER(esripsys) + + /* Video hardware */ + MDRV_SCREEN_ADD("main", RASTER) + MDRV_SCREEN_FORMAT(BITMAP_FORMAT_RGB32) + MDRV_SCREEN_RAW_PARAMS(ESRIPSYS_PIXEL_CLOCK, ESRIPSYS_HTOTAL, ESRIPSYS_HBLANK_END, ESRIPSYS_HBLANK_START, ESRIPSYS_VTOTAL, ESRIPSYS_VBLANK_END, ESRIPSYS_VBLANK_START) + + MDRV_VIDEO_START(esripsys) + MDRV_VIDEO_UPDATE(esripsys) + + /* Sound hardware */ + MDRV_SPEAKER_STANDARD_MONO("mono") + + MDRV_SOUND_ADD("tms5220nl", TMS5220, 640000) + MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50) + + MDRV_SOUND_ADD("dac", DAC, 0) + MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80) +MACHINE_DRIVER_END + + +/************************************* + * + * ROM definitions + * + *************************************/ + +ROM_START( turbosub ) + ROM_REGION( 0xc0000, "main_code", 0) /* Non-bankswitched, 6809 #0 code */ + ROM_LOAD( "turbosub.u85", 0x18000, 0x4000, CRC(eabb9509) SHA1(cbfb6c5becb3fe1b4ed729e92a0f4029a5df7d67) ) + + ROM_REGION( 0x48000, "game_cpu", 0 ) /* Bankswitched 6809 code */ + ROM_LOAD( "turbosub.u82", 0x10000, 0x2000, CRC(de32eb6f) SHA1(90bf31a5adf261d47b4f52e93b5e97f343b7ebf0) ) + ROM_CONTINUE( 0x20000, 0x2000 ) + ROM_LOAD( "turbosub.u81", 0x12000, 0x2000, CRC(9ae09613) SHA1(9b5ada4a21473b30be98bcc461129b6ed4e0bb11) ) + ROM_CONTINUE( 0x22000, 0x2000 ) + ROM_LOAD( "turbosub.u87", 0x14000, 0x2000, CRC(ad2284f7) SHA1(8e11b8ad0a98dd1fe6ec8f7ea9e6e4f4a45d8a1b) ) + ROM_CONTINUE( 0x24000, 0x2000 ) + ROM_LOAD( "turbosub.u86", 0x16000, 0x2000, CRC(4f51e6fd) SHA1(8f51ac6412aace29279ce7b02cad45ed681c2065) ) + ROM_CONTINUE( 0x26000, 0x2000 ) + + ROM_LOAD( "turbosub.u80", 0x30000, 0x2000, CRC(ff2e2870) SHA1(45f91d63ad91585482c9dd05290b204b007e3f44) ) + ROM_CONTINUE( 0x40000, 0x2000 ) + ROM_LOAD( "turbosub.u79", 0x32000, 0x2000, CRC(13680923) SHA1(14e3daa2178853cef1fd96a68305420c11fceb96) ) + ROM_CONTINUE( 0x42000, 0x2000 ) + ROM_LOAD( "turbosub.u84", 0x34000, 0x2000, CRC(7059842d) SHA1(c20a8accd3fc23bc4476e1d08798d7a80915d37c) ) + ROM_CONTINUE( 0x44000, 0x2000 ) + ROM_LOAD( "turbosub.u83", 0x36000, 0x2000, CRC(31b86fc6) SHA1(8e56e8a75f653c3c4da2c9f31f739894beb194db) ) + ROM_CONTINUE( 0x46000, 0x2000 ) + + /* e000 - ffff = Upper half of U85 (lower half is blank) */ + ROM_COPY( "main_code", 0x18000 + 0x2000, 0xe000, 0x2000 ) + + ROM_REGION( 0x10000, "frame_cpu", 0 ) + ROM_LOAD( "turbosub.u63", 0xc000, 0x4000, CRC(35701532) SHA1(77d957682aab10ee902c1e47c468b9ab8fe6a512) ) + + ROM_REGION( 0x1000, "video_cpu", 0 ) + ROMX_LOAD( "27s29.u29", 0x0, 0x200, CRC(d580672b) SHA1(b56295a5b780ab5e8ff6817ebb084a8dfad8c281), ROM_SKIP(7)) + ROMX_LOAD( "27s29.u28", 0x1, 0x200, CRC(f7976b87) SHA1(c19a1d375c497f1671170c7833952979819c3812), ROM_SKIP(7)) + ROMX_LOAD( "27s29.u27", 0x2, 0x200, CRC(03ebd3ea) SHA1(109f5369bd36bcf0da5928b96566655c6895c737), ROM_SKIP(7)) + ROMX_LOAD( "27s29.u21", 0x3, 0x200, CRC(e232384b) SHA1(cfc3acc86add06b4cb6addb3455d71123fb359ce), ROM_SKIP(7)) + ROMX_LOAD( "27s29.u20", 0x4, 0x200, CRC(0a8e44d8) SHA1(2df46316510b2dbfd4c9913a1460c00d5572d586), ROM_SKIP(7)) + ROMX_LOAD( "27s29.u19", 0x5, 0x200, CRC(de17e5f0) SHA1(3e14768374e1bda25183aee86a82d220b7f58ff9), ROM_SKIP(7)) + ROMX_LOAD( "27s29.u18", 0x6, 0x200, CRC(e33ed0a4) SHA1(41edbdc7c022971ce14bd2f419c92714b796fad7), ROM_SKIP(7)) + + ROM_REGION( 0x10000, "sound_cpu", 0 ) + ROM_LOAD( "turbosub.u66a", 0xe000, 0x2000, CRC(8db3bcdb) SHA1(e6ae324ba9dad4884e1cb3d67ce099a6f4739456) ) + + ROM_REGION( 0xc000, "sound_data", 0) + ROM_LOAD( "turbosub.u69", 0x0000, 0x4000, CRC(ad04193b) SHA1(2f660302e60a7e68e079a8dd13266a77c077f939) ) + ROM_LOAD( "turbosub.u68", 0x4000, 0x4000, CRC(72e3d09b) SHA1(eefdfcd0c4c32e465f18d40f46cb5bc022c22bfd) ) + ROM_LOAD( "turbosub.u67", 0x8000, 0x4000, CRC(f8ae82e9) SHA1(fd27b9fe7872c3c680a1f71a4a5d5eeaa12e4a19) ) + + ROM_REGION( 0x40000, "4bpp", 0) + ROM_LOAD( "turbosub.u44", 0x00000, 0x4000, CRC(eaa05860) SHA1(f649891dae9354b7f2e46e6a380b52a569229d64) ) + ROM_LOAD( "turbosub.u49", 0x10000, 0x4000, CRC(b4170ac2) SHA1(bdbfc43c891c8d525dcc46fb9d05602263ab69cd) ) + ROM_LOAD( "turbosub.u54", 0x20000, 0x4000, CRC(bebf98d8) SHA1(170502bb44fc6d6bf14d8dac4778b37888c14a7b) ) + ROM_LOAD( "turbosub.u59", 0x30000, 0x4000, CRC(9c1f4397) SHA1(94335f2db2650f8b7e24fc3f92a04b73325ab164) ) + + ROM_LOAD( "turbosub.u43", 0x04000, 0x4000, CRC(5d76237c) SHA1(3d50347856039e43290497348447b1c4581f3a33) ) + ROM_LOAD( "turbosub.u48", 0x14000, 0x4000, CRC(cea4e036) SHA1(4afce4f2a09adf9c83ab7188c05cd7236dea16a3) ) + ROM_LOAD( "turbosub.u53", 0x24000, 0x4000, CRC(1352d58a) SHA1(76ae86c365dd4c9e1a6c5af91c01d31e7ee35f0f) ) + ROM_LOAD( "turbosub.u58", 0x34000, 0x4000, CRC(5024d83f) SHA1(a293d92a0ae01901b5618b0250d48e3ba631dfcb) ) + + ROM_LOAD( "turbosub.u42", 0x08000, 0x4000, CRC(057a1c72) SHA1(5af89b128b7818550572d02e5ff724c415fa8b8b) ) + ROM_LOAD( "turbosub.u47", 0x18000, 0x4000, CRC(10def494) SHA1(a3ba691eb2b0d782162ffc6c081761965844a3a9) ) + ROM_LOAD( "turbosub.u52", 0x28000, 0x4000, CRC(070d07d6) SHA1(4c81310cd646641a380817fedffab66e76529c97) ) + ROM_LOAD( "turbosub.u57", 0x38000, 0x4000, CRC(5ddb0458) SHA1(d1169882397f364ca38fbd563250b33d13b1a7c6) ) + + ROM_LOAD( "turbosub.u41", 0x0c000, 0x4000, CRC(014bb06b) SHA1(97276ba26b60c2907e59b92cc9de5251298579cf) ) + ROM_LOAD( "turbosub.u46", 0x1c000, 0x4000, CRC(3b866e2c) SHA1(c0dd4827a18eb9f4b1055d92544beed10f01fd86) ) + ROM_LOAD( "turbosub.u51", 0x2c000, 0x4000, CRC(43cdcb5c) SHA1(3dd966daa904d3be7be63c584ba033c0e7904d5c) ) + ROM_LOAD( "turbosub.u56", 0x3c000, 0x4000, CRC(6d116adf) SHA1(f808e28cef41dc86e43d8c12966037213da87c87) ) + + ROM_REGION( 0x40000, "8bpp_l", 0) + ROM_LOAD( "turbosub.u4", 0x00000, 0x4000, CRC(08303604) SHA1(f075b645d89a2d91bd9b621748906a9f9890ee60) ) + ROM_LOAD( "turbosub.u14", 0x10000, 0x4000, CRC(83b26c8d) SHA1(2dfa3b45c44652d255c402511bb3810fffb0731d) ) + ROM_LOAD( "turbosub.u24", 0x20000, 0x4000, CRC(6bbb6cb3) SHA1(d513e547a05b34076bb8261abd51301ac5f3f5d4) ) + ROM_LOAD( "turbosub.u34", 0x30000, 0x4000, CRC(7b844f4a) SHA1(82467eb7e116f9f225711a1698c151945e1de6e4) ) + + ROM_LOAD( "turbosub.u3", 0x04000, 0x4000, CRC(825ef29c) SHA1(affadd0976f793b8bdbcbc4768b7de27121e7b11) ) + ROM_LOAD( "turbosub.u13", 0x14000, 0x4000, CRC(350cc17a) SHA1(b98d16be997fc0576d3206f51f29ce3e257492d3) ) + ROM_LOAD( "turbosub.u23", 0x24000, 0x4000, CRC(b1531916) SHA1(805a23f40aa875f431e835fdaceba87261c14155) ) + ROM_LOAD( "turbosub.u33", 0x34000, 0x4000, CRC(0d5130cb) SHA1(7e4e4e5ea50c581a60d15964571464029515c720) ) + + ROM_LOAD( "turbosub.u2", 0x08000, 0x4000, CRC(a8b8c032) SHA1(20512a3a1f8b9c0361e6f5a7e9a50605be3ae650) ) + ROM_LOAD( "turbosub.u12", 0x18000, 0x4000, CRC(a2c4badf) SHA1(267af1be6261833211270af25045e306efffee80) ) + ROM_LOAD( "turbosub.u22", 0x28000, 0x4000, CRC(97b7cf0e) SHA1(888fb2f384a5cba8a6f7569886eb6dc27e2b024f) ) + ROM_LOAD( "turbosub.u32", 0x38000, 0x4000, CRC(b286710e) SHA1(5082db13630ba0967006619027c39ee3607b838d) ) + + ROM_LOAD( "turbosub.u1", 0x0c000, 0x4000, CRC(88b0a7a9) SHA1(9012c8059cf60131efa6a0432accd87813187206) ) + ROM_LOAD( "turbosub.u11", 0x1c000, 0x4000, CRC(9f0ff723) SHA1(54b52b4ebc32f10aa32c799ac819928290e70455) ) + ROM_LOAD( "turbosub.u21", 0x2c000, 0x4000, CRC(b4122fe2) SHA1(50e8b488a7b7f739336b60a3fd8a5b14f5010b75) ) + ROM_LOAD( "turbosub.u31", 0x3c000, 0x4000, CRC(3fa15c78) SHA1(bf5cb85fc26b5045ad5acc944c917b068ace2c49) ) + + ROM_REGION( 0x40000, "8bpp_r", 0) + ROM_LOAD( "turbosub.u9", 0x00000, 0x4000, CRC(9a03eadf) SHA1(25ee1ebe52f030b2fa09d76161e46540c91cbc4c) ) + ROM_LOAD( "turbosub.u19", 0x10000, 0x4000, CRC(498253b8) SHA1(dd74d4f9f19d8a746415baea604116faedb4fb31) ) + ROM_LOAD( "turbosub.u29", 0x20000, 0x4000, CRC(809c374f) SHA1(d3849eed8441e4641ffcbca7c83ee3bb16681a0b) ) + ROM_LOAD( "turbosub.u39", 0x30000, 0x4000, CRC(3e4e0681) SHA1(ac834f6823ffe835d6f149e79c1d31ae2b89e85d) ) + + ROM_LOAD( "turbosub.u8", 0x04000, 0x4000, CRC(01118737) SHA1(3a8e998b80dffe82296170273dcbbe9870c5b695) ) + ROM_LOAD( "turbosub.u18", 0x14000, 0x4000, CRC(39fd8e57) SHA1(392f8a8cf58fc4813de840775d9c53561488152d) ) + ROM_LOAD( "turbosub.u28", 0x24000, 0x4000, CRC(0628586d) SHA1(e37508c2812e1c98659aaba9c495e7396842614e) ) + ROM_LOAD( "turbosub.u38", 0x34000, 0x4000, CRC(7d597a7e) SHA1(2f48faf75406ab3ff0b954040b74e68b7ca6f7a5) ) + + ROM_LOAD( "turbosub.u7", 0x08000, 0x4000, CRC(50eea315) SHA1(567dbb3cb3a75a7507f4cb4748c7dd878e69d6b7) ) + ROM_LOAD( "turbosub.u17", 0x18000, 0x4000, CRC(8a9e19e6) SHA1(19067e153c0002edfd4a756f92ad75d9a0cbc3dd) ) + ROM_LOAD( "turbosub.u27", 0x28000, 0x4000, CRC(1c81a8d9) SHA1(3d13d1ccd7ec3dddf2a27600eb64b5be386e868c) ) + ROM_LOAD( "turbosub.u37", 0x38000, 0x4000, CRC(59f978cb) SHA1(e99d6378de941cad92e9702fcb18aea87acd371f) ) + + ROM_LOAD( "turbosub.u6", 0x0c000, 0x4000, CRC(841e00bd) SHA1(f777cc8dd8dd7c8baa2007355a76db782a218efc) ) + ROM_LOAD( "turbosub.u16", 0x1c000, 0x4000, CRC(d3b63d81) SHA1(e86dd64825f6d9e7bebc26413f524a8962f68f2d) ) + ROM_LOAD( "turbosub.u26", 0x2c000, 0x4000, CRC(867cfe32) SHA1(549e4e557d63dfab8e8c463916512a1b422ce425) ) + ROM_LOAD( "turbosub.u36", 0x3c000, 0x4000, CRC(0d8ebc21) SHA1(7ae65edae05869376caa975ff2c778a08e8ad8a2) ) + + ROM_REGION( 0x260, "proms", 0) + ROM_LOAD( "27s29.u123", 0x0000, 0x0200, CRC(b2e8770e) SHA1(849292a6b30bb0e6547ce3232438136897a651b0) ) + ROM_LOAD( "6331_snd.u2", 0x0200, 0x0020, CRC(f1328a5e) SHA1(44d4e802988415d24a0b9eaa38300f5add3a2727) ) + ROM_LOAD( "6331_rom.u74", 0x0220, 0x0020, CRC(7b72b34e) SHA1(bc4d67a6993beb36a161368428e648d0492ac436) ) + ROM_LOAD( "6331_vid.u155", 0x0240, 0x0020, CRC(63371737) SHA1(f08c03c81322c0de9ee64b4a9f11a1422c5bd463) ) +ROM_END + +ROM_START( turbosba ) + ROM_REGION( 0xc0000, "main_code", 0) /* Non-bankswitched, 6809 #0 code */ + ROM_LOAD( "u85", 0x18000, 0x4000, CRC(d37ccb06) SHA1(445df1caa4dd4901e474bb0903bf28e536edf493) ) + + ROM_REGION( 0x48000, "game_cpu", 0 ) /* Bankswitched 6809 code */ + ROM_LOAD( "u82", 0x10000, 0x2000, CRC(1596a100) SHA1(0a53d4b79245f2a51de87ec4de6db525aa342f2c) ) + ROM_CONTINUE( 0x20000, 0x2000 ) + ROM_LOAD( "u81", 0x12000, 0x2000, CRC(1c8e053d) SHA1(397f04fdf7c5dfaa33a396b1b41c015a86537ef6) ) + ROM_CONTINUE( 0x22000, 0x2000 ) + ROM_LOAD( "u87", 0x14000, 0x2000, CRC(c80d0512) SHA1(aedd829edd2cb214fa30ae2fe25ad7590c86971b) ) + ROM_CONTINUE( 0x24000, 0x2000 ) + ROM_LOAD( "u86", 0x16000, 0x2000, CRC(8af137d3) SHA1(12768d14b18401d07a793de3412da059b5a33699) ) + ROM_CONTINUE( 0x26000, 0x2000 ) + + ROM_LOAD( "u80", 0x30000, 0x2000, CRC(6f53b658) SHA1(39841e4b0a6809ad061a07adcdb8d92fd7652959) ) + ROM_CONTINUE( 0x40000, 0x2000 ) + ROM_LOAD( "u79", 0x32000, 0x2000, CRC(aa6f1db6) SHA1(70cacedb57f3c5646181e26c355f87f1cea1d651) ) + ROM_CONTINUE( 0x42000, 0x2000 ) + ROM_LOAD( "u84", 0x34000, 0x2000, CRC(e856323f) SHA1(d973f8efa3a1f5907b8c09b58043d7b41ff3f0c1) ) + ROM_CONTINUE( 0x44000, 0x2000 ) + ROM_LOAD( "u83", 0x36000, 0x2000, CRC(056fc173) SHA1(426bcea3c2420b8df036122ebb6fc80af89e63d2) ) + ROM_CONTINUE( 0x46000, 0x2000 ) + + /* e000 - ffff = Upper half of U85 (lower half is blank) */ + ROM_COPY( "main_code", 0x18000 + 0x2000, 0xe000, 0x2000 ) + + ROM_REGION( 0x10000, "frame_cpu", 0 ) + ROM_LOAD( "u63", 0xe000, 0x2000, CRC(e85216d4) SHA1(7f61a93c52a31782116e9825d0aefa58ca3720b9) ) + + ROM_REGION( 0x1000, "video_cpu", 0 ) + ROMX_LOAD( "27s29.u29", 0x0, 0x200, CRC(d580672b) SHA1(b56295a5b780ab5e8ff6817ebb084a8dfad8c281), ROM_SKIP(7)) + ROMX_LOAD( "27s29.u28", 0x1, 0x200, CRC(f7976b87) SHA1(c19a1d375c497f1671170c7833952979819c3812), ROM_SKIP(7)) + ROMX_LOAD( "27s29.u27", 0x2, 0x200, CRC(03ebd3ea) SHA1(109f5369bd36bcf0da5928b96566655c6895c737), ROM_SKIP(7)) + ROMX_LOAD( "27s29.u21", 0x3, 0x200, CRC(e232384b) SHA1(cfc3acc86add06b4cb6addb3455d71123fb359ce), ROM_SKIP(7)) + ROMX_LOAD( "27s29.u20", 0x4, 0x200, CRC(0a8e44d8) SHA1(2df46316510b2dbfd4c9913a1460c00d5572d586), ROM_SKIP(7)) + ROMX_LOAD( "27s29.u19", 0x5, 0x200, CRC(de17e5f0) SHA1(3e14768374e1bda25183aee86a82d220b7f58ff9), ROM_SKIP(7)) + ROMX_LOAD( "27s29.u18", 0x6, 0x200, CRC(e33ed0a4) SHA1(41edbdc7c022971ce14bd2f419c92714b796fad7), ROM_SKIP(7)) + + ROM_REGION( 0x10000, "sound_cpu", 0 ) + ROM_LOAD( "turbosub.u66", 0xe000, 0x2000, CRC(8db3bcdb) SHA1(e6ae324ba9dad4884e1cb3d67ce099a6f4739456) ) + + ROM_REGION( 0xc000, "sound_data", 0) + ROM_LOAD( "turbosub.u69", 0x0000, 0x4000, CRC(ad04193b) SHA1(2f660302e60a7e68e079a8dd13266a77c077f939) ) + ROM_LOAD( "turbosub.u68", 0x4000, 0x4000, CRC(72e3d09b) SHA1(eefdfcd0c4c32e465f18d40f46cb5bc022c22bfd) ) + ROM_LOAD( "turbosub.u67", 0x8000, 0x4000, CRC(f8ae82e9) SHA1(fd27b9fe7872c3c680a1f71a4a5d5eeaa12e4a19) ) + + ROM_REGION( 0x40000, "4bpp", 0) + ROM_LOAD( "turbosub.u44", 0x00000, 0x4000, CRC(eaa05860) SHA1(f649891dae9354b7f2e46e6a380b52a569229d64) ) + ROM_LOAD( "turbosub.u49", 0x10000, 0x4000, CRC(b4170ac2) SHA1(bdbfc43c891c8d525dcc46fb9d05602263ab69cd) ) + ROM_LOAD( "turbosub.u54", 0x20000, 0x4000, CRC(bebf98d8) SHA1(170502bb44fc6d6bf14d8dac4778b37888c14a7b) ) + ROM_LOAD( "turbosub.u59", 0x30000, 0x4000, CRC(9c1f4397) SHA1(94335f2db2650f8b7e24fc3f92a04b73325ab164) ) + + ROM_LOAD( "turbosub.u43", 0x04000, 0x4000, CRC(5d76237c) SHA1(3d50347856039e43290497348447b1c4581f3a33) ) + ROM_LOAD( "turbosub.u48", 0x14000, 0x4000, CRC(cea4e036) SHA1(4afce4f2a09adf9c83ab7188c05cd7236dea16a3) ) + ROM_LOAD( "turbosub.u53", 0x24000, 0x4000, CRC(1352d58a) SHA1(76ae86c365dd4c9e1a6c5af91c01d31e7ee35f0f) ) + ROM_LOAD( "turbosub.u58", 0x34000, 0x4000, CRC(5024d83f) SHA1(a293d92a0ae01901b5618b0250d48e3ba631dfcb) ) + + ROM_LOAD( "turbosub.u42", 0x08000, 0x4000, CRC(057a1c72) SHA1(5af89b128b7818550572d02e5ff724c415fa8b8b) ) + ROM_LOAD( "turbosub.u47", 0x18000, 0x4000, CRC(10def494) SHA1(a3ba691eb2b0d782162ffc6c081761965844a3a9) ) + ROM_LOAD( "turbosub.u52", 0x28000, 0x4000, CRC(070d07d6) SHA1(4c81310cd646641a380817fedffab66e76529c97) ) + ROM_LOAD( "turbosub.u57", 0x38000, 0x4000, CRC(5ddb0458) SHA1(d1169882397f364ca38fbd563250b33d13b1a7c6) ) + + ROM_LOAD( "turbosub.u41", 0x0c000, 0x4000, CRC(014bb06b) SHA1(97276ba26b60c2907e59b92cc9de5251298579cf) ) + ROM_LOAD( "turbosub.u46", 0x1c000, 0x4000, CRC(3b866e2c) SHA1(c0dd4827a18eb9f4b1055d92544beed10f01fd86) ) + ROM_LOAD( "turbosub.u51", 0x2c000, 0x4000, CRC(43cdcb5c) SHA1(3dd966daa904d3be7be63c584ba033c0e7904d5c) ) + ROM_LOAD( "turbosub.u56", 0x3c000, 0x4000, CRC(6d116adf) SHA1(f808e28cef41dc86e43d8c12966037213da87c87) ) + + ROM_REGION( 0x40000, "8bpp_l", 0) + ROM_LOAD( "turbosub.u4", 0x00000, 0x4000, CRC(08303604) SHA1(f075b645d89a2d91bd9b621748906a9f9890ee60) ) + ROM_LOAD( "turbosub.u14", 0x10000, 0x4000, CRC(83b26c8d) SHA1(2dfa3b45c44652d255c402511bb3810fffb0731d) ) + ROM_LOAD( "turbosub.u24", 0x20000, 0x4000, CRC(6bbb6cb3) SHA1(d513e547a05b34076bb8261abd51301ac5f3f5d4) ) + ROM_LOAD( "turbosub.u34", 0x30000, 0x4000, CRC(7b844f4a) SHA1(82467eb7e116f9f225711a1698c151945e1de6e4) ) + + ROM_LOAD( "turbosub.u3", 0x04000, 0x4000, CRC(825ef29c) SHA1(affadd0976f793b8bdbcbc4768b7de27121e7b11) ) + ROM_LOAD( "turbosub.u13", 0x14000, 0x4000, CRC(350cc17a) SHA1(b98d16be997fc0576d3206f51f29ce3e257492d3) ) + ROM_LOAD( "turbosub.u23", 0x24000, 0x4000, CRC(b1531916) SHA1(805a23f40aa875f431e835fdaceba87261c14155) ) + ROM_LOAD( "turbosub.u33", 0x34000, 0x4000, CRC(0d5130cb) SHA1(7e4e4e5ea50c581a60d15964571464029515c720) ) + + ROM_LOAD( "turbosub.u2", 0x08000, 0x4000, CRC(a8b8c032) SHA1(20512a3a1f8b9c0361e6f5a7e9a50605be3ae650) ) + ROM_LOAD( "turbosub.u12", 0x18000, 0x4000, CRC(a2c4badf) SHA1(267af1be6261833211270af25045e306efffee80) ) + ROM_LOAD( "turbosub.u22", 0x28000, 0x4000, CRC(97b7cf0e) SHA1(888fb2f384a5cba8a6f7569886eb6dc27e2b024f) ) + ROM_LOAD( "turbosub.u32", 0x38000, 0x4000, CRC(b286710e) SHA1(5082db13630ba0967006619027c39ee3607b838d) ) + + ROM_LOAD( "turbosub.u1", 0x0c000, 0x4000, CRC(88b0a7a9) SHA1(9012c8059cf60131efa6a0432accd87813187206) ) + ROM_LOAD( "turbosub.u11", 0x1c000, 0x4000, CRC(9f0ff723) SHA1(54b52b4ebc32f10aa32c799ac819928290e70455) ) + ROM_LOAD( "turbosub.u21", 0x2c000, 0x4000, CRC(b4122fe2) SHA1(50e8b488a7b7f739336b60a3fd8a5b14f5010b75) ) + ROM_LOAD( "turbosub.u31", 0x3c000, 0x4000, CRC(3fa15c78) SHA1(bf5cb85fc26b5045ad5acc944c917b068ace2c49) ) + + ROM_REGION( 0x40000, "8bpp_r", 0) + ROM_LOAD( "turbosub.u9", 0x00000, 0x4000, CRC(9a03eadf) SHA1(25ee1ebe52f030b2fa09d76161e46540c91cbc4c) ) + ROM_LOAD( "turbosub.u19", 0x10000, 0x4000, CRC(498253b8) SHA1(dd74d4f9f19d8a746415baea604116faedb4fb31) ) + ROM_LOAD( "turbosub.u29", 0x20000, 0x4000, CRC(809c374f) SHA1(d3849eed8441e4641ffcbca7c83ee3bb16681a0b) ) + ROM_LOAD( "turbosub.u39", 0x30000, 0x4000, CRC(3e4e0681) SHA1(ac834f6823ffe835d6f149e79c1d31ae2b89e85d) ) + + ROM_LOAD( "turbosub.u8", 0x04000, 0x4000, CRC(01118737) SHA1(3a8e998b80dffe82296170273dcbbe9870c5b695) ) + ROM_LOAD( "turbosub.u18", 0x14000, 0x4000, CRC(39fd8e57) SHA1(392f8a8cf58fc4813de840775d9c53561488152d) ) + ROM_LOAD( "turbosub.u28", 0x24000, 0x4000, CRC(0628586d) SHA1(e37508c2812e1c98659aaba9c495e7396842614e) ) + ROM_LOAD( "turbosub.u38", 0x34000, 0x4000, CRC(7d597a7e) SHA1(2f48faf75406ab3ff0b954040b74e68b7ca6f7a5) ) + + ROM_LOAD( "turbosub.u7", 0x08000, 0x4000, CRC(50eea315) SHA1(567dbb3cb3a75a7507f4cb4748c7dd878e69d6b7) ) + ROM_LOAD( "turbosub.u17", 0x18000, 0x4000, CRC(8a9e19e6) SHA1(19067e153c0002edfd4a756f92ad75d9a0cbc3dd) ) + ROM_LOAD( "turbosub.u27", 0x28000, 0x4000, CRC(1c81a8d9) SHA1(3d13d1ccd7ec3dddf2a27600eb64b5be386e868c) ) + ROM_LOAD( "turbosub.u37", 0x38000, 0x4000, CRC(59f978cb) SHA1(e99d6378de941cad92e9702fcb18aea87acd371f) ) + + ROM_LOAD( "turbosub.u6", 0x0c000, 0x4000, CRC(841e00bd) SHA1(f777cc8dd8dd7c8baa2007355a76db782a218efc) ) + ROM_LOAD( "turbosub.u16", 0x1c000, 0x4000, CRC(d3b63d81) SHA1(e86dd64825f6d9e7bebc26413f524a8962f68f2d) ) + ROM_LOAD( "turbosub.u26", 0x2c000, 0x4000, CRC(867cfe32) SHA1(549e4e557d63dfab8e8c463916512a1b422ce425) ) + ROM_LOAD( "turbosub.u36", 0x3c000, 0x4000, CRC(0d8ebc21) SHA1(7ae65edae05869376caa975ff2c778a08e8ad8a2) ) + + ROM_REGION( 0x260, "proms", 0) + ROM_LOAD( "27s29.u123", 0x0000, 0x0200, CRC(b2e8770e) SHA1(849292a6b30bb0e6547ce3232438136897a651b0) ) + ROM_LOAD( "6331_snd.u2", 0x0200, 0x0020, CRC(f1328a5e) SHA1(44d4e802988415d24a0b9eaa38300f5add3a2727) ) + ROM_LOAD( "6331_rom.u74", 0x0220, 0x0020, CRC(7b72b34e) SHA1(bc4d67a6993beb36a161368428e648d0492ac436) ) + ROM_LOAD( "6331_vid.u155", 0x0240, 0x0020, CRC(63371737) SHA1(f08c03c81322c0de9ee64b4a9f11a1422c5bd463) ) +ROM_END + + +/************************************* + * + * Game drivers + * + *************************************/ + +GAME( 1985, turbosub, 0, esripsys, turbosub, esripsys, ROT0, "Entertainment Sciences", "Turbo Sub (prototype rev. TSCA)", 0 ) +GAME( 1985, turbosba, turbosub, esripsys, turbosub, esripsys, ROT0, "Entertainment Sciences", "Turbo Sub (prototype rev. TSC6)", 0 ) diff --git a/src/mame/drivers/turbosub.c b/src/mame/drivers/turbosub.c deleted file mode 100644 index 8c3ba4fdd1e..00000000000 --- a/src/mame/drivers/turbosub.c +++ /dev/null @@ -1,464 +0,0 @@ -/*********************************************************************** - - Entertainment Sciences Real-Time Image Processor System - -Turbo Sub 1986 -Bouncer 1983 (No ROMs available) - -Hardware -======== -* 6809 (Game Processor) - - i8251A (USART) -* 6809 (Frame Processor) -* 6809 (Sound Processor) - - TMS5220NL - - DAC -* AM29116DC (Video Processor) - -Useful References -================= -http://www.turbosub.com/schematics.htm -http://www.turbosub.com/ripdoc1.jpg (1 to 4) -http://www.ionpool.net/arcade/es/turbo_sub.html -http://www.bitsavers.org/pdf/amd/_dataSheets/29116_dataSheet_Mar86.pdf - -Note: The schematics do not represent exactly the final hardware. - -Information -=========== - -The game processor is responsible for gameplay and reading inputs -(keypad, ADC and digital). It shares 16kB of RAM with the frame processor. -According to the schematics, it also has access to collision detection RAM -and palette RAM used by the video system. - -The frame processor organises data supplied by the game processor into a -suitable format for the video processor and video hardware. It shares 8kB of -banked RAM (Frame Drive Table) with the video processor. - -The video processor instructions are stored in 6 PROMS (which are ARE -NOT DUMPED). - -Each CPU has a R/W status port used to communicate with the other CPUs -and hardware. - -***********************************************************************/ - -#include "driver.h" -#include "cpu/m6809/m6809.h" - -/* Set to 1 to display test results and skip on errors */ -#define ROM_PATCHES 1 - -/* Frame Drive Table bank indicators */ -static int _FASEL = 0; -static int _FBSEL = 1; - -static UINT8 *FDT_A; -static UINT8 *FDT_B; -static UINT8 INTER_CPU_REG; - -static VIDEO_START( turbosub ) -{ -} - -static VIDEO_UPDATE( turbosub ) -{ - return 0; -} - - -static MACHINE_RESET( turbosub ) -{ -#if ROM_PATCHES - UINT8 *rom = (UINT8 *)memory_region(machine, "main"); - - rom[0xf564]=0; /* Display test status */ - rom[0xf60a]=0x20; /* Skip on error */ -#endif -} - -static DRIVER_INIT( turbosub ) -{ - FDT_A = auto_malloc(0x1000); - FDT_B = auto_malloc(0x1000); -} - -/* i8251A UART */ -static WRITE8_HANDLER( UART_W ) -{ - if (offset==0) - mame_printf_debug("%c",data); -} - -static READ8_HANDLER( UART_R ) -{ - return 0; -} - -/* - Game Processor - ============== - -Status Write Status Read -============ =========== -0: 6809 #0 ROM bank bit 0 0: Frame CPU status out D0 -1: 6809 #0 ROM bank bit 1 1: Frame CPU status out D0 -2: 2: Frame CPU status out D0 -3: 3: Frame CPU status out D0 -4: ? (usually 1) 4: -5: ? (usually 1) 5: -6: V0? (AM29116)(active high?) 6: -7: Game/Frame CPU NMI 7: /RIPERR ? - -*/ - -static READ8_HANDLER( G_STATUS_R ) -{ - return 0x80 | INTER_CPU_REG; -} - -static WRITE8_HANDLER( G_STATUS_W ) -{ - int bankaddress; - UINT8 *ROM = memory_region(space->machine, "main"); - bankaddress = 0x10000 + (data & 0x03) * 0x10000; - memory_set_bankptr(space->machine, 1,&ROM[bankaddress]); - - cpu_set_input_line(space->machine->cpu[0], INPUT_LINE_NMI, (data&0x80) ? ASSERT_LINE : CLEAR_LINE); - cpu_set_input_line(space->machine->cpu[1], INPUT_LINE_NMI, (data&0x80) ? ASSERT_LINE : CLEAR_LINE); -} - -/* - Frame Processor - =============== - -Status Write Status Read -============ =========== -0: Game CPU status in D0 0: /VBLANK ? -1: Game CPU status in D1 1: -2: Game CPU status in D2 2: -3: Game CPU status in D3 3: -4: 4: -5: 5: -6: 6: /FBSEL -7: 7: - -*/ - -static READ8_HANDLER( F_STATUS_R ) -{ - return (_FBSEL << 6); -} - -static WRITE8_HANDLER( F_STATUS_W ) -{ - INTER_CPU_REG = data; -} - -static WRITE8_HANDLER( FRAME ) -{ - _FASEL = !_FASEL; - _FBSEL = !_FBSEL; -} - -static READ8_HANDLER( FDT_R ) -{ - if(!_FASEL) - return FDT_A[offset]; - else - return FDT_B[offset]; -} - -static WRITE8_HANDLER( FDT_W ) -{ - if(!_FASEL) - FDT_A[offset] = data; - else - FDT_B[offset] = data; -} - -static INPUT_PORTS_START( turbosub ) -PORT_START("IN0") -INPUT_PORTS_END - -/* -TURBOSUB.U85 -============ - -Vectors -======= - -Reset = E002 -/NMI = E3D0 (Not used = RTI) -SWI = E8D0 -IRQ = E133 -FIRQ = E319 -Others = E3D0 (Not used = RTI) - - -Self-tests (initiated by CPU 0) -=============================== - - f561: LDY, #$0001 Change to 0 to print out test results. - f737: JMP [A,X] A = test number/2 - - Test Loc. Desc. Status - ==== ==== ===== ====== - 0-16 CPU 0 ROM checksums OK - 17 CPU 0 RAM 0000-07ff OK - 18 CPU 0 RAM 0800-0fff OK - 19 CPU 0 RAM 1000-17ff OK - 20 CPU 0 RAM 1800-1fff OK - 21 CPU 0 RAM 2000-27ff OK - 22 CPU 0 RAM 2800-2fff OK - 23 CPU 0 RAM 3000-37ff OK - 24 0xf90d ? FAIL - [4800]<-b10010000 - [4800]<-b11010000 - Expect bit 7 of [4800] == 1 on SECOND access or thereafter. - - 25 0xf966 CPU 0<->1 communication test OK - 26 0xf98b CPU 1 ROM e000-ffff checksum OK - 27 0xf990 CPU 1 RAM 3000-37ff OK - 28 0xf995 CPU 1 RAM 0000-0fff OK - 29 0xf99a CPU 1 RAM 1000-17ff OK - 30 0xf99f CPU 1 RAM 1800-1fff OK - 31 0xf9a4 CPU 1 RAM 2000-27ff OK - 32 0xf9a9 CPU 1 RAM 2800-2fff OK - 33 0xf9ae CPU 1 RAM 3000-37ff OK - 34 0xf9b3 CPU 1 RAM 3800-3fff OK - - 35 0xf9dd/0xf115 FAIL - - 36 0xf9e3/f151 TEST banked FDT? OK - 37 0xf9e3 TEST banked FDT? OK - 38 0xf9e3 CPU 1 FDT (even bytes) OK - 39 0xf9e3 CPU 1 FDT (odd bytes) OK - - 40 0xfa06 FAIL - 41 0xfafd OK - 42 0xfb0e FAIL - 43 0xfb2a FAIL - 44 0xfbc9 FAIL - 45 0xfd61 FAIL - 46 0xfd70 FAIL - 47 0xfd97 FAIL - 48 0xfdc9 FAIL - 49 0xfdee FAIL - 50 0xfe05 FAIL - 51 0xfe3d FAIL - 52 0xfe54 FAIL - 53 0xfe6b FAIL - 54 0xfe82 FAIL - 55 0xfe99 FAIL -*/ - -static ADDRESS_MAP_START( game_cpu_map, ADDRESS_SPACE_PROGRAM, 8 ) - AM_RANGE(0x0000, 0x3fff) AM_RAM AM_SHARE(1) - AM_RANGE(0x40ff, 0x40ff) AM_RAM /* W */ - AM_RANGE(0x41ff, 0x41ff) AM_RAM /* W */ - AM_RANGE(0x42ff, 0x4300) AM_RAM /* W */ - AM_RANGE(0x4800, 0x4800) AM_READWRITE(G_STATUS_R, G_STATUS_W) /* Status port */ - AM_RANGE(0x4C00, 0x4C00) AM_RAM /* R/W - An input device? (doesn't enter auto mode depending on read) */ - AM_RANGE(0x5000, 0x5000) AM_RAM /* Write - related to 4C00. Bit 8 = ? bits0..3 =???? */ - AM_RANGE(0x5400, 0x54ff) AM_RAM /* UART buffer? */ - AM_RANGE(0x5c00, 0x5c01) AM_READWRITE(UART_R, UART_W) /* i8251A USART */ - AM_RANGE(0x6000, 0xdfff) AM_READWRITE(SMH_BANK1, SMH_ROM) /* Bank switched ROMs */ - AM_RANGE(0xe000, 0xffff) AM_ROM -ADDRESS_MAP_END - -/* -TURBOSUB.U63 -============ - -Vectors -======= - -Reset: EF2A -/NMI: EF30 -Others: E064 - -*/ - -static ADDRESS_MAP_START( frame_cpu_map, ADDRESS_SPACE_PROGRAM, 8 ) - AM_RANGE(0x0000, 0x3fff) AM_RAM AM_SHARE(1) /* 16kB RAM: Shared with game CPU */ - AM_RANGE(0x4000, 0x4fff) AM_READWRITE(FDT_R, FDT_W) /* 8kB RAM: Frame Drive Table (banked) */ - AM_RANGE(0x6000, 0x6000) AM_READWRITE(F_STATUS_R, F_STATUS_W) /* Status port */ - AM_RANGE(0x8000, 0x8000) AM_WRITE(FRAME) - AM_RANGE(0xc000, 0xffff) AM_ROM -ADDRESS_MAP_END - -/* -TURBOSUB.U66 -============ - -Vectors -======= - -Reset: ecb5 ` -/NMI: ecb5 -FIRQ: e114 -IRQ: e0d3 - -SWI: e13d -SWI2: e13d -SWI3: e13d - -*/ - - -/* Sound CPU */ - -static ADDRESS_MAP_START( sound_cpu_map, ADDRESS_SPACE_PROGRAM, 8 ) - AM_RANGE(0x0000, 0x07ff) AM_RAM - AM_RANGE(0x2008, 0x2008) AM_RAM /* R=status line? D7 0=Ready? 1=Not ready? */ - AM_RANGE(0x2009, 0x2009) AM_RAM /* W (only written once - with value read from 2008) */ - AM_RANGE(0x200a, 0x200b) AM_RAM /* W 16-bit value during FIRQ */ - AM_RANGE(0x200c, 0x200c) AM_RAM /* W */ - AM_RANGE(0x200d, 0x200d) AM_RAM /* W - 03 */ - AM_RANGE(0x200e, 0x200e) AM_RAM /* R/W - communication with game processor */ - AM_RANGE(0x200f, 0x200f) AM_RAM /* R/W - communication with game processor */ - AM_RANGE(0x2020, 0x2020) AM_RAM /* W - 42 */ - AM_RANGE(0x2021, 0x2021) AM_RAM /* W - 42,1 and R during FIRQ? */ - AM_RANGE(0x2022, 0x2023) AM_RAM /* R/W rarely */ - AM_RANGE(0x2024, 0x2025) AM_RAM /* R/W rarely */ - AM_RANGE(0x8000, 0x8006) AM_RAM /* R */ - AM_RANGE(0xc000, 0xffff) AM_ROM -ADDRESS_MAP_END - - -static MACHINE_DRIVER_START( turbosub ) - - MDRV_CPU_ADD("main", M6809E,4000000) - MDRV_CPU_PROGRAM_MAP(game_cpu_map,0) - MDRV_CPU_VBLANK_INT("main", irq0_line_assert) /* Unverified */ - - MDRV_CPU_ADD("frame", M6809E,4000000) - MDRV_CPU_PROGRAM_MAP(frame_cpu_map,0) - - MDRV_CPU_ADD("audio", M6809E,4000000) - MDRV_CPU_PROGRAM_MAP(sound_cpu_map,0) - - /* video hardware */ - MDRV_SCREEN_ADD("main", RASTER) - MDRV_SCREEN_REFRESH_RATE(60) - MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) - MDRV_SCREEN_FORMAT(BITMAP_FORMAT_INDEXED16) - MDRV_SCREEN_SIZE(34*8, 34*8) - MDRV_SCREEN_VISIBLE_AREA(0*8, 34*8-1, 0, 34*8-1) - - MDRV_PALETTE_LENGTH(512) - MDRV_MACHINE_RESET( turbosub ) - MDRV_QUANTUM_TIME(HZ(6000)) - - MDRV_VIDEO_START(turbosub) - MDRV_VIDEO_UPDATE(turbosub) -MACHINE_DRIVER_END - -ROM_START( turbosub ) - ROM_REGION( 0xc0000, "user1", 0) /* Non-bankswitched, 6809 #0 code */ - ROM_LOAD( "turbosub.u85", 0x18000, 0x4000, CRC(eabb9509) SHA1(cbfb6c5becb3fe1b4ed729e92a0f4029a5df7d67) ) - - ROM_REGION( 0x48000, "main", 0 ) /* Bankswitched 6809 code */ - ROM_LOAD( "turbosub.u82", 0x10000, 0x2000, CRC(de32eb6f) SHA1(90bf31a5adf261d47b4f52e93b5e97f343b7ebf0) ) - ROM_CONTINUE( 0x20000, 0x2000 ) - ROM_LOAD( "turbosub.u81", 0x12000, 0x2000, CRC(9ae09613) SHA1(9b5ada4a21473b30be98bcc461129b6ed4e0bb11) ) - ROM_CONTINUE( 0x22000, 0x2000 ) - ROM_LOAD( "turbosub.u87", 0x14000, 0x2000, CRC(ad2284f7) SHA1(8e11b8ad0a98dd1fe6ec8f7ea9e6e4f4a45d8a1b) ) - ROM_CONTINUE( 0x24000, 0x2000 ) - ROM_LOAD( "turbosub.u86", 0x16000, 0x2000, CRC(4f51e6fd) SHA1(8f51ac6412aace29279ce7b02cad45ed681c2065) ) - ROM_CONTINUE( 0x26000, 0x2000 ) - - ROM_LOAD( "turbosub.u80", 0x30000, 0x2000, CRC(ff2e2870) SHA1(45f91d63ad91585482c9dd05290b204b007e3f44) ) - ROM_CONTINUE( 0x40000, 0x2000 ) - ROM_LOAD( "turbosub.u79", 0x32000, 0x2000, CRC(13680923) SHA1(14e3daa2178853cef1fd96a68305420c11fceb96) ) - ROM_CONTINUE( 0x42000, 0x2000 ) - ROM_LOAD( "turbosub.u84", 0x34000, 0x2000, CRC(7059842d) SHA1(c20a8accd3fc23bc4476e1d08798d7a80915d37c) ) - ROM_CONTINUE( 0x44000, 0x2000 ) - ROM_LOAD( "turbosub.u83", 0x36000, 0x2000, CRC(31b86fc6) SHA1(8e56e8a75f653c3c4da2c9f31f739894beb194db) ) - ROM_CONTINUE( 0x46000, 0x2000 ) - - /* e000 - ffff = Upper half of U85 (lower half is blank) */ - ROM_COPY( "user1", 0x18000+0x2000, 0xe000, 0x2000 ) - - ROM_REGION( 0x10000, "frame", 0 ) - ROM_LOAD( "turbosub.u63", 0xc000, 0x4000, CRC(35701532) SHA1(77d957682aab10ee902c1e47c468b9ab8fe6a512) ) - - ROM_REGION( 0x10000, "audio", 0 ) - ROM_LOAD( "turbosub.u66", 0xc000, 0x4000, CRC(5091bf3d) SHA1(7ab872cef1562a45f7533c16bbbae8772673465b) ) - - ROM_REGION( 0xc0000, "user2", 0) /* Unknown */ - ROM_LOAD( "turbosub.u67", 0x00000, 0x4000, CRC(f8ae82e9) SHA1(fd27b9fe7872c3c680a1f71a4a5d5eeaa12e4a19) ) - ROM_LOAD( "turbosub.u68", 0x04000, 0x4000, CRC(72e3d09b) SHA1(eefdfcd0c4c32e465f18d40f46cb5bc022c22bfd) ) - ROM_LOAD( "turbosub.u69", 0x00000, 0x4000, CRC(ad04193b) SHA1(2f660302e60a7e68e079a8dd13266a77c077f939) ) - - ROM_REGION( 0x80000, "gfx1", 0 ) /* Incorrect */ - ROMX_LOAD( "turbosub.u4", 0x00000, 0x4000, CRC(08303604) SHA1(f075b645d89a2d91bd9b621748906a9f9890ee60), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u14", 0x00001, 0x4000, CRC(83b26c8d) SHA1(2dfa3b45c44652d255c402511bb3810fffb0731d), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u24", 0x00002, 0x4000, CRC(6bbb6cb3) SHA1(d513e547a05b34076bb8261abd51301ac5f3f5d4), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u34", 0x00003, 0x4000, CRC(7b844f4a) SHA1(82467eb7e116f9f225711a1698c151945e1de6e4), ROM_SKIP(3) ) - - ROMX_LOAD( "turbosub.u9", 0x10000, 0x4000, CRC(9a03eadf) SHA1(25ee1ebe52f030b2fa09d76161e46540c91cbc4c), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u19", 0x10001, 0x4000, CRC(498253b8) SHA1(dd74d4f9f19d8a746415baea604116faedb4fb31), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u29", 0x10002, 0x4000, CRC(809c374f) SHA1(d3849eed8441e4641ffcbca7c83ee3bb16681a0b), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u39", 0x10003, 0x4000, CRC(3e4e0681) SHA1(ac834f6823ffe835d6f149e79c1d31ae2b89e85d), ROM_SKIP(3) ) - - ROMX_LOAD( "turbosub.u3", 0x20000, 0x4000, CRC(825ef29c) SHA1(affadd0976f793b8bdbcbc4768b7de27121e7b11), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u13", 0x20001, 0x4000, CRC(350cc17a) SHA1(b98d16be997fc0576d3206f51f29ce3e257492d3), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u23", 0x20002, 0x4000, CRC(b1531916) SHA1(805a23f40aa875f431e835fdaceba87261c14155), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u33", 0x20003, 0x4000, CRC(0d5130cb) SHA1(7e4e4e5ea50c581a60d15964571464029515c720), ROM_SKIP(3) ) - - ROMX_LOAD( "turbosub.u8", 0x30000, 0x4000, CRC(01118737) SHA1(3a8e998b80dffe82296170273dcbbe9870c5b695), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u18", 0x30001, 0x4000, CRC(39fd8e57) SHA1(392f8a8cf58fc4813de840775d9c53561488152d), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u28", 0x30002, 0x4000, CRC(0628586d) SHA1(e37508c2812e1c98659aaba9c495e7396842614e), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u38", 0x30003, 0x4000, CRC(7d597a7e) SHA1(2f48faf75406ab3ff0b954040b74e68b7ca6f7a5), ROM_SKIP(3) ) - - ROMX_LOAD( "turbosub.u2", 0x40000, 0x4000, CRC(a8b8c032) SHA1(20512a3a1f8b9c0361e6f5a7e9a50605be3ae650), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u12", 0x40001, 0x4000, CRC(a2c4badf) SHA1(267af1be6261833211270af25045e306efffee80), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u22", 0x40002, 0x4000, CRC(97b7cf0e) SHA1(888fb2f384a5cba8a6f7569886eb6dc27e2b024f), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u32", 0x40003, 0x4000, CRC(b286710e) SHA1(5082db13630ba0967006619027c39ee3607b838d), ROM_SKIP(3) ) - - ROMX_LOAD( "turbosub.u7", 0x50000, 0x4000, CRC(50eea315) SHA1(567dbb3cb3a75a7507f4cb4748c7dd878e69d6b7), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u17", 0x50001, 0x4000, CRC(8a9e19e6) SHA1(19067e153c0002edfd4a756f92ad75d9a0cbc3dd), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u27", 0x50002, 0x4000, CRC(1c81a8d9) SHA1(3d13d1ccd7ec3dddf2a27600eb64b5be386e868c), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u37", 0x50003, 0x4000, CRC(59f978cb) SHA1(e99d6378de941cad92e9702fcb18aea87acd371f), ROM_SKIP(3) ) - - ROMX_LOAD( "turbosub.u1", 0x60000, 0x4000, CRC(88b0a7a9) SHA1(9012c8059cf60131efa6a0432accd87813187206), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u11", 0x60001, 0x4000, CRC(9f0ff723) SHA1(54b52b4ebc32f10aa32c799ac819928290e70455), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u21", 0x60002, 0x4000, CRC(b4122fe2) SHA1(50e8b488a7b7f739336b60a3fd8a5b14f5010b75), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u31", 0x60003, 0x4000, CRC(3fa15c78) SHA1(bf5cb85fc26b5045ad5acc944c917b068ace2c49), ROM_SKIP(3) ) - - ROMX_LOAD( "turbosub.u6", 0x70000, 0x4000, CRC(841e00bd) SHA1(f777cc8dd8dd7c8baa2007355a76db782a218efc), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u16", 0x70001, 0x4000, CRC(d3b63d81) SHA1(e86dd64825f6d9e7bebc26413f524a8962f68f2d), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u26", 0x70002, 0x4000, CRC(867cfe32) SHA1(549e4e557d63dfab8e8c463916512a1b422ce425), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u36", 0x70003, 0x4000, CRC(0d8ebc21) SHA1(7ae65edae05869376caa975ff2c778a08e8ad8a2), ROM_SKIP(3) ) - - ROM_REGION( 0x40000, "gfx2", 0) /* Incorrect */ - ROMX_LOAD( "turbosub.u44", 0x00000, 0x4000, CRC(eaa05860) SHA1(f649891dae9354b7f2e46e6a380b52a569229d64), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u54", 0x00001, 0x4000, CRC(bebf98d8) SHA1(170502bb44fc6d6bf14d8dac4778b37888c14a7b), ROM_SKIP(3) ) - - ROMX_LOAD( "turbosub.u49", 0x00002, 0x4000, CRC(b4170ac2) SHA1(bdbfc43c891c8d525dcc46fb9d05602263ab69cd), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u59", 0x00003, 0x4000, CRC(9c1f4397) SHA1(94335f2db2650f8b7e24fc3f92a04b73325ab164), ROM_SKIP(3) ) - - ROMX_LOAD( "turbosub.u43", 0x10000, 0x4000, CRC(5d76237c) SHA1(3d50347856039e43290497348447b1c4581f3a33), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u53", 0x10001, 0x4000, CRC(1352d58a) SHA1(76ae86c365dd4c9e1a6c5af91c01d31e7ee35f0f), ROM_SKIP(3) ) - - ROMX_LOAD( "turbosub.u48", 0x10002, 0x4000, CRC(cea4e036) SHA1(4afce4f2a09adf9c83ab7188c05cd7236dea16a3), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u58", 0x10003, 0x4000, CRC(5024d83f) SHA1(a293d92a0ae01901b5618b0250d48e3ba631dfcb), ROM_SKIP(3) ) - - ROMX_LOAD( "turbosub.u42", 0x20000, 0x4000, CRC(057a1c72) SHA1(5af89b128b7818550572d02e5ff724c415fa8b8b), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u52", 0x20001, 0x4000, CRC(070d07d6) SHA1(4c81310cd646641a380817fedffab66e76529c97), ROM_SKIP(3) ) - - ROMX_LOAD( "turbosub.u47", 0x20002, 0x4000, CRC(10def494) SHA1(a3ba691eb2b0d782162ffc6c081761965844a3a9), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u57", 0x20003, 0x4000, CRC(5ddb0458) SHA1(d1169882397f364ca38fbd563250b33d13b1a7c6), ROM_SKIP(3) ) - - ROMX_LOAD( "turbosub.u41", 0x30000, 0x4000, CRC(014bb06b) SHA1(97276ba26b60c2907e59b92cc9de5251298579cf), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u51", 0x30001, 0x4000, CRC(43cdcb5c) SHA1(3dd966daa904d3be7be63c584ba033c0e7904d5c), ROM_SKIP(3) ) - - ROMX_LOAD( "turbosub.u46", 0x30002, 0x4000, CRC(3b866e2c) SHA1(c0dd4827a18eb9f4b1055d92544beed10f01fd86), ROM_SKIP(3) ) - ROMX_LOAD( "turbosub.u56", 0x30003, 0x4000, CRC(6d116adf) SHA1(f808e28cef41dc86e43d8c12966037213da87c87), ROM_SKIP(3) ) -ROM_END - -GAME( 1986, turbosub, 0, turbosub, turbosub, turbosub, ROT0, "Entertainment Sciences", "Turbo Sub",GAME_NO_SOUND|GAME_IMPERFECT_GRAPHICS|GAME_NOT_WORKING ) -/* One day, perhaps Bouncer will be added here... */ diff --git a/src/mame/includes/esripsys.h b/src/mame/includes/esripsys.h new file mode 100644 index 00000000000..e7a3f66bf7a --- /dev/null +++ b/src/mame/includes/esripsys.h @@ -0,0 +1,40 @@ +/************************************************************************* + + Entertainment Sciences RIP System hardware + +*************************************************************************/ + +/* TODO */ +#define ESRIPSYS_PIXEL_CLOCK (XTAL_25MHz / 2) +#define ESRIPSYS_HTOTAL (512 + 141) +#define ESRIPSYS_HBLANK_START (512) +#define ESRIPSYS_HBLANK_END (0) +#define ESRIPSYS_VTOTAL (384 + 20) +#define ESRIPSYS_VBLANK_START (384) +#define ESRIPSYS_VBLANK_END (0) + +#define CMOS_RAM_SIZE (2048) +#define FDT_RAM_SIZE (2048 * sizeof(UINT16)) + +enum +{ + ESRIPSYS_GAME_CPU = 0, + ESRIPSYS_FRAME_CPU = 1, + ESRIPSYS_VIDEO_CPU = 2, + ESRIPSYS_SOUND_CPU = 3, +}; + +/*----------- defined in video/esripsys.c -----------*/ + +extern UINT8 *esripsys_pal_ram; +extern int esripsys_frame_vbl; +extern int esripsys__12sel; +extern int esripsys_video_firq_en; + +VIDEO_START( esripsys ); +VIDEO_UPDATE( esripsys ); + +WRITE8_HANDLER( esripsys_bg_intensity_w ); +INTERRUPT_GEN( esripsys_vblank_irq ); + +int esripsys_draw(running_machine *machine, int l, int r, int fig, int attr, int addr, int col, int x_scale, int line_latch); diff --git a/src/mame/mame.mak b/src/mame/mame.mak index 4d99dc8b4ec..54559eb9d11 100644 --- a/src/mame/mame.mak +++ b/src/mame/mame.mak @@ -143,6 +143,7 @@ CPUS += ARM CPUS += ARM7 CPUS += JAGUAR CPUS += CUBEQCPU +CPUS += ESRIP CPUS += R3000 CPUS += R3041 CPUS += R4600 @@ -1575,6 +1576,7 @@ $(MAMEOBJ)/misc.a: \ $(DRIVERS)/ertictac.o \ $(DRIVERS)/esd16.o $(VIDEO)/esd16.o \ $(DRIVERS)/esh.o \ + $(DRIVERS)/esripsys.o $(VIDEO)/esripsys.o \ $(DRIVERS)/ettrivia.o \ $(DRIVERS)/filetto.o \ $(DRIVERS)/flower.o $(AUDIO)/flower.o $(VIDEO)/flower.o \ @@ -1677,7 +1679,6 @@ $(MAMEOBJ)/misc.a: \ $(DRIVERS)/trvquest.o \ $(DRIVERS)/ttchamp.o \ $(DRIVERS)/tugboat.o \ - $(DRIVERS)/turbosub.o \ $(DRIVERS)/usgames.o $(VIDEO)/usgames.o \ $(DRIVERS)/vamphalf.o \ $(DRIVERS)/vcombat.o \ diff --git a/src/mame/mamedriv.c b/src/mame/mamedriv.c index 2b795b19e2a..7ea1e0cec0c 100644 --- a/src/mame/mamedriv.c +++ b/src/mame/mamedriv.c @@ -8082,7 +8082,8 @@ Other Sun games DRIVER( laserbas ) /* (c) 1981 Amstar/HOEI */ DRIVER( laserbsa ) /* (c) 1981 Amstar/HOEI */ DRIVER( futflash ) /* (c) 19?? HOEI */ - DRIVER( turbosub ) /* (c) 1986 Entertainment Sciences */ + DRIVER( turbosub ) /* (c) 1985 Entertainment Sciences */ + DRIVER( turbosba ) /* (c) 1985 Entertainment Sciences */ DRIVER( pipeline ) /* (c) 1990 Daehyun Electronics */ DRIVER( ttchamp ) DRIVER( ttchampa ) diff --git a/src/mame/video/esripsys.c b/src/mame/video/esripsys.c new file mode 100644 index 00000000000..0b85eb3efce --- /dev/null +++ b/src/mame/video/esripsys.c @@ -0,0 +1,362 @@ +/*************************************************************************** + + Entertainment Sciences Real-Time Image Processor (RIP) video hardware + +****************************************************************************/ + +#include "driver.h" +#include "cpu/m6809/m6809.h" +#include "esripsys.h" + +typedef struct _pixel_ +{ + UINT8 colour; + UINT8 intensity; + UINT8 priority; +} pixel; + +static emu_timer *hblank_end_timer; +static emu_timer *hblank_start_timer; + +static UINT8 *fig_scale_table; +static UINT8 *scale_table; +static pixel *line_buffer_1; +static pixel *line_buffer_2; + +static int vcount; +static int video_firq; +static UINT8 bg_intensity; + +int esripsys_video_firq_en; +int esripsys_frame_vbl; +int esripsys__12sel; +UINT8 *esripsys_pal_ram; + + +INTERRUPT_GEN( esripsys_vblank_irq ) +{ + cpu_set_input_line(device->machine->cpu[ESRIPSYS_GAME_CPU], M6809_IRQ_LINE, ASSERT_LINE); + esripsys_frame_vbl = 0; +} + +static TIMER_CALLBACK( hblank_start_callback ) +{ + int v = vcount; + + if (video_firq) + { + video_firq = 0; + cpu_set_input_line(machine->cpu[ESRIPSYS_GAME_CPU], M6809_FIRQ_LINE, CLEAR_LINE); + } + + if (!(vcount % 6) && vcount && esripsys_video_firq_en && vcount < ESRIPSYS_VBLANK_START) + { + video_firq = 1; + cpu_set_input_line(machine->cpu[ESRIPSYS_GAME_CPU], M6809_FIRQ_LINE, ASSERT_LINE); + } + + /* Adjust for next scanline */ + if (++vcount >= ESRIPSYS_VTOTAL) + vcount = 0; + + /* Set end of HBLANK timer */ + timer_adjust_oneshot(hblank_end_timer, video_screen_get_time_until_pos(machine->primary_screen, v, ESRIPSYS_HTOTAL-1), v); +} + +static TIMER_CALLBACK( hblank_end_callback ) +{ + video_screen_update_partial(machine->primary_screen, param); + + esripsys__12sel ^= 1; + timer_adjust_oneshot(hblank_start_timer, video_screen_get_time_until_pos(machine->primary_screen, vcount, ESRIPSYS_HBLANK_START), 0); +} + +VIDEO_START( esripsys ) +{ + int i; + + /* Allocate memory for the two 512-pixel line buffers */ + line_buffer_1 = auto_malloc(512 * sizeof(pixel)); + line_buffer_2 = auto_malloc(512 * sizeof(pixel)); + + /* Create and initialise the HBLANK timers */ + hblank_start_timer = timer_alloc(machine, hblank_start_callback, NULL); + hblank_end_timer = timer_alloc(machine, hblank_end_callback, NULL); + timer_adjust_oneshot(hblank_start_timer, video_screen_get_time_until_pos(machine->primary_screen, 0, ESRIPSYS_HBLANK_START), 0); + + /* Create the sprite scaling table */ + scale_table = auto_malloc(64 * 64); + + for (i = 0; i < 64; ++i) + { + int j; + + for (j = 1; j < 65; ++j) + { + int p0 = 0; + int p1 = 0; + int p2 = 0; + int p3 = 0; + int p4 = 0; + int p5 = 0; + + if (i & 0x1) + p0 = BIT(j, 5) && !BIT(j, 4) && !BIT(j,3) && !BIT(j, 2) && !BIT(j, 1) && !BIT(j, 0); + if (i & 0x2) + p1 = BIT(j, 4) && !BIT(j, 3) && !BIT(j, 2) && !BIT(j, 1) && !BIT(j, 0); + if (i & 0x4) + p2 = BIT(j,3) && !BIT(j, 2) && !BIT(j, 1) && !BIT(j, 0); + if (i & 0x8) + p3 = BIT(j, 2) && !BIT(j,1) && !BIT(j,0); + if (i & 0x10) + p4 = BIT(j, 1) && !BIT(j, 0); + if (i & 0x20) + p5 = BIT(j, 0); + + scale_table[i * 64 + j - 1] = p0 | p1 | p2 | p3 | p4 | p5; + } + } + + /* Now create a lookup table for scaling the sprite 'fig' value */ + fig_scale_table = auto_malloc(1024 * 64); + + for (i = 0; i < 1024; ++i) + { + int scale; + + for (scale = 0; scale < 64; ++scale) + { + int input_pixels = i + 1; + int scaled_pixels = 0; + + while (input_pixels) + { + if (scale_table[scale * 64 + (scaled_pixels & 0x3f)] == 0) + input_pixels--; + + scaled_pixels++; + } + + fig_scale_table[i * 64 + scale] = scaled_pixels - 1; + } + } +} + +VIDEO_UPDATE( esripsys ) +{ + int x; + int y; + pixel *src; + + /* Select line buffer to scan out */ + if (esripsys__12sel) + src = line_buffer_2; + else + src = line_buffer_1; + + for (y = cliprect->min_y; y <= cliprect->max_y; ++y) + { + UINT32 *dest = BITMAP_ADDR32(bitmap, y, 0); + + for (x = cliprect->min_x; x <= cliprect->max_x; ++x) + { + int idx = src[x].colour; + int r = (esripsys_pal_ram[idx] & 0xf); + int g = (esripsys_pal_ram[256 + idx] & 0xf); + int b = (esripsys_pal_ram[512 + idx] & 0xf); + int i = src[x].intensity; + + *dest++ = MAKE_RGB(r*i, g*i, b*i); + + /* Clear the line buffer as we scan out */ + src[x].colour = 0xff; + src[x].intensity = bg_intensity; + src[x].priority = 0; + } + } + + return 0; +} + +WRITE8_HANDLER( esripsys_bg_intensity_w ) +{ + bg_intensity = data & 0xf; +} + +/* Draw graphics to a line buffer */ +int esripsys_draw(running_machine *machine, int l, int r, int fig, int attr, int addr, int col, int x_scale, int line_latch) +{ + pixel *dst; + UINT8 pri = attr & 0xff; + UINT8 iny = (attr >> 8) & 0xf; + UINT8 pal = col << 4; + int x_flip = x_scale & 0x80; + int xs_typ = x_scale & 0x40; + int xs_val = x_scale & 0x3f; + + /* Fig is the number of pixels to draw / 2 - 1 */ + if (xs_typ) + fig = fig_scale_table[fig * 64 + xs_val]; + + if (esripsys__12sel) + dst = line_buffer_1; + else + dst = line_buffer_2; + + /* 8bpp case */ + if (attr & 0x8000) + { + int ptr = 0; + int cnt; + UINT8 *rom_l; + UINT8 *rom_r; + UINT32 lpos = l; + UINT32 rpos = r; + + if (x_flip) + { + rom_l = memory_region(machine, "8bpp_r"); + rom_r = memory_region(machine, "8bpp_l"); + } + else + { + rom_l = memory_region(machine, "8bpp_l"); + rom_r = memory_region(machine, "8bpp_r"); + } + + for (cnt = 0; cnt <= fig; cnt++) + { + UINT32 rom_addr = (ptr * 0x10000) + addr; + UINT8 pix1 = rom_l[rom_addr]; + UINT8 pix2 = rom_r[rom_addr]; + + if ((UINT32)lpos < 512) + { + if ((pri > dst[lpos].priority) && pix1 != 0xff) + { + dst[lpos].colour = pix1; + dst[lpos].priority = pri; + dst[lpos].intensity = iny; + } + } + + if ((UINT32)rpos < 512) + { + if ((pri > dst[rpos].priority) && pix2 != 0xff) + { + dst[rpos].colour = pix2; + dst[rpos].priority = pri; + dst[rpos].intensity = iny; + } + } + + /* Shrink */ + if (!xs_typ) + { + if (scale_table[xs_val * 64 + (cnt & 0x3f)]) + { + --lpos; + ++rpos; + } + + if (++ptr == 4) + { + ++addr; + ptr = 0; + } + } + else + { + if (!scale_table[xs_val * 64 + (cnt & 0x3f)]) + { + if (++ptr == 4) + { + ++addr; + ptr = 0; + } + } + + lpos--; + rpos++; + } + } + } + /* 4bpp case */ + else + { + const UINT8* const rom = memory_region(machine, "4bpp"); + int ptr = 0; + int cnt; + UINT32 lpos = l; + UINT32 rpos = r; + + for (cnt = 0; cnt <= fig; cnt++) + { + UINT8 px8 = rom[(ptr * 0x10000) + addr]; + UINT8 px1; + UINT8 px2; + + if (x_flip) + { + px1 = px8 & 0xf; + px2 = (px8 >> 4) & 0xf; + } + else + { + px2 = px8 & 0xf; + px1 = (px8 >> 4) & 0xf; + } + + if ((UINT32)lpos < 512) + { + if ((pri > dst[lpos].priority) && px1 != 0xf) + { + dst[lpos].colour = pal | px1; + dst[lpos].priority = pri; + dst[lpos].intensity = iny; + } + } + + if ((UINT32)rpos < 512) + { + if (pri > dst[rpos].priority && px2 != 0xf) + { + dst[rpos].colour = pal | px2; + dst[rpos].priority = pri; + dst[rpos].intensity = iny; + } + } + + /* Shrink */ + if (!xs_typ) + { + if (scale_table[xs_val * 64 + (cnt & 0x3f)]) + { + lpos--; + rpos++; + } + + if (++ptr == 4) + { + addr++; + ptr = 0; + } + } + else + { + if (!scale_table[xs_val * 64 + (cnt & 0x3f)]) + { + if (++ptr == 4) + { + addr++; + ptr = 0; + } + } + lpos--; + rpos++; + } + } + } + + return fig + 1; +}