diff options
Diffstat (limited to 'src/mame/drivers/bfcobra.c')
-rw-r--r-- | src/mame/drivers/bfcobra.c | 1622 |
1 files changed, 1622 insertions, 0 deletions
diff --git a/src/mame/drivers/bfcobra.c b/src/mame/drivers/bfcobra.c new file mode 100644 index 00000000000..6204f99740d --- /dev/null +++ b/src/mame/drivers/bfcobra.c @@ -0,0 +1,1622 @@ +/****************************************************************************** + + Bell-Fruit Cobra I/II and Viper Hardware + + driver by Phil Bennett + + Games supported: + * A Question of Sport (two sets) + * Every Second Counts + * Inquizitor (Viper hardware) + * Quizvaders + * Treble Top + + Other games on this hardware: + * Brain Box + * Quintoon alt. version (Cobra II/Cyclone hardware) + + Notes: + + The hardware is based on a chipset known as 'Flare One', developed + by Flare Technology. It consists of a 16-bit DSP (intended for sound + synthesis and 3D maths), an 8bpp blitter and a video controller, driven + by a Z80. + + Flare One would evolve to become 'Slipstream', used by the unreleased + Konix Multisystem console. + + The Flare One chipset is implemented as four Texas Instruments ASICs, + each an 84 pin PLCC package: + + CF30204, CF30205, CF30206 (DSP) and CF30207. + + The hardware using this chipset is as follows: + + Viper + ===== + + A video expansion PCB for Scorpion I? + On some PCB revisions there is audio output circuitry connected to the DSP. + Viper uses a WD1772 type floppy disk controller. + + Cobra I + ======= + + A combination of Viper and Scorpion I hardware on a single PCB. + Cobra uses an NEC '765 type FDC. Later revisions have no DSP. + + Cobra II (Cyclone) + ================== + + A compact video expansion board for Scorpion II. + The Z80 is replaced by a Z180 and there is no Flare DSP or FDC + + + To do: + + * Verify blitter modes on real hardware and rewrite code + * Deduce unknown chipset accesses + * Cobra II support + * Implement Flare One DSP (although nothing seems to use it) + * Hook up additional inputs, EM meters, lamps etc + * Remove a 'TODO' comment or thirty + + Known issues: + + * trebltop: During the intro, DLT's signature is drawn incorrectly. + * escounts: Colours are completely wrong. Is there a palette register + somewhere that affects blitter/video output? + * qos: Game clock and score dividers aren't drawn (needs line draw mode) + +******************************************************************************/ +#include "driver.h" +#include "debugger.h" +#include "machine/6850acia.h" +#include "cpu/z80/z80.h" +#include "cpu/m6809/m6809.h" +#include "sound/upd7759.h" +#include "sound/ay8910.h" + +/* + Defines +*/ +#define Z80_XTAL 4000000 +#define M6809_XTAL 1000000 + + +/* + Globals +*/ +static UINT8 bank[4]; +static UINT8 *work_ram; +static UINT8 *video_ram; +static UINT8 h_scroll; +static UINT8 v_scroll; +static UINT8 flip_8; +static UINT8 flip_22; + +/* UART source/sinks */ +static UINT8 z80_m6809_line; +static UINT8 m6809_z80_line; +static UINT8 data_r; +static UINT8 data_t; + +static int irq_state; +static int acia_irq; +static int vblank_irq; +static int blitter_irq; + +static UINT8 z80_int; +static UINT8 z80_inten; + +/* EM and lamps stuff */ +static UINT32 meter_latch; +static UINT32 mux_input; +static UINT32 mux_outputlatch; + +/* + Function prototypes +*/ +INLINE void z80_bank(int num, int data); + + +static void update_irqs(void) +{ + int newstate = blitter_irq || vblank_irq || acia_irq; + + if (newstate != irq_state) + { + irq_state = newstate; + cpunum_set_input_line(0, 0, irq_state ? ASSERT_LINE : CLEAR_LINE); + } +} + +/*************************************************************************** + + Split into video\cobra.c ! + +***************************************************************************/ + +#ifdef MAME_DEBUG +int DEBUG_BLITTER = 0; +#endif + +/* Typedefs */ +typedef union +{ +#ifdef LSB_FIRST + struct { UINT8 addr0, addr1, addr2; }; +#else + struct { UINT8 addr2, addr1, addr0; }; +#endif + UINT32 addr; +} ADDR_REG; + +/* Blitter register flag bits */ +#define CMD_RUN 0x01 +#define CMD_COLST 0x02 +#define CMD_PARRD 0x04 /* Never used? */ +#define CMD_SRCUP 0x08 +#define CMD_DSTUP 0x10 +#define CMD_SRCEN 0x20 +#define CMD_DSTEN 0x40 +#define CMD_LINEDRAW 0x80 + +/* All unconfirmed */ +//#define SRCDST_CMP 0x10 +//#define SRCDST_WRAP 0x20 +//#define SRCDST_SIGN 0x40 +#define SRCDST_A_1 0x80 /* This might be correct for line drawing? */ + +/* These appear to be correct */ +#define MODE_SSIGN 0x80 +#define MODE_DSIGN 0x40 +#define MODE_YFRAC 0x20 +#define MODE_BITTOBYTE 0x04 +#define MODE_PALREMAP 0x10 + +/* All unconfirmed */ +//#define CMPFUNC_EQ 0x01 +//#define CMPFUNC_NE 0x02 +//#define CMPFUNC_GT 0x04 +//#define CMPFUNC_PLANE 0x08 + +#define CMPFUNC_EQ 0x08 +#define CMPFUNC_LOG0 0x10 +#define CMPFUNC_LOG1 0x20 +#define CMPFUNC_LOG2 0x40 +#define CMPFUNC_LOG3 0x80 + +/* + Blitter state +*/ +static struct +{ + ADDR_REG program; + + UINT8 control; + UINT8 status; + + UINT8 command; + ADDR_REG source; + ADDR_REG dest; + UINT8 modectl; + UINT8 compfunc; + UINT8 outercnt; + + UINT8 innercnt; + UINT8 step; + UINT8 pattern; +} blitter; + +/* + MUSIC Semiconductor TR9C1710 RAMDAC or equivalent +*/ +static struct +{ + UINT8 addr_w; + UINT8 addr_r; + UINT8 mask; + + /* 18-bit colors */ + UINT8 color_r[3]; + UINT8 color_w[3]; + UINT32 table[256]; + + /* Access counts */ + UINT8 count_r; + UINT8 count_w; +} ramdac; + +static VIDEO_UPDATE( bfcobra ) +{ + int x, y; + UINT8 *src; + UINT32 *dest; + UINT32 offset; + + /* A bit dodgy */ + if (flip_8 & 0x40 && flip_22 & 0x40) + offset = 0x10000; + else + offset = 0; + + for (y = cliprect->min_y; y <= cliprect->max_y; ++y) + { + UINT16 y_offset = (y + v_scroll) * 256; + src = &video_ram[offset + y_offset]; + dest = BITMAP_ADDR32(bitmap, y, 0); + + for (x = cliprect->min_x; x <= cliprect->max_x; ++x) + { + UINT8 x_offset = x + h_scroll; + UINT8 pen = *(src + x_offset); + + //*dest++ = Machine->pens[pen & ramdac.mask]; + *dest++ = Machine->pens[pen]; + } + } + + return 0; +} + +INLINE UINT8* blitter_get_addr(UINT32 addr) +{ + if (addr < 0x10000) + { + /* Is this region fixed? */ + return (UINT8*)(memory_region(REGION_USER1) + addr); + } + else if(addr < 0x20000) + { + addr &= 0xffff; + addr += (bank[0] & 1) ? 0x10000 : 0; + + return (UINT8*)(memory_region(REGION_USER1) + addr + ((bank[0] >> 1) * 0x20000)); + } + else if (addr >= 0x20000 && addr < 0x40000) + { + return (UINT8*)&video_ram[addr - 0x20000]; + } + else + { + return (UINT8*)&work_ram[addr - 0x40000]; + } +} + + +/* + This is based this on the Slipstream technical reference manual. + The Flare One blitter is a simpler design with slightly different parameters + and will require hardware tests to figure everything out correctly. +*/ +static void RunBlit(void) +{ +#define BLITPRG_READ(x) blitter.x = *(blitter_get_addr(blitter.program.addr++)) + + do + { + UINT8 srcdata = 0; + UINT8 dstdata = 0; + + /* Read the blitter command */ + BLITPRG_READ(source.addr0); + BLITPRG_READ(source.addr1); + BLITPRG_READ(source.addr2); + BLITPRG_READ(dest.addr0); + BLITPRG_READ(dest.addr1); + BLITPRG_READ(dest.addr2); + BLITPRG_READ(modectl); + BLITPRG_READ(compfunc); + BLITPRG_READ(outercnt); + BLITPRG_READ(innercnt); + BLITPRG_READ(step); + BLITPRG_READ(pattern); + +#ifdef MAME_DEBUG + if (DEBUG_BLITTER) + { + mame_printf_debug("\nBlitter (%x): Running command from 0x%.5x\n\n", activecpu_get_previouspc(), blitter.program.addr - 12); + mame_printf_debug("Command Reg %.2x", blitter.command); + mame_printf_debug(" %s %s %s %s %s %s %s\n", + blitter.command & CMD_RUN ? "RUN" : " ", + blitter.command & CMD_COLST ? "COLST" : " ", + blitter.command & CMD_PARRD ? "PARRD" : " ", + blitter.command & CMD_SRCUP ? "SRCUP" : " ", + blitter.command & CMD_DSTUP ? "DSTUP" : " ", + blitter.command & CMD_SRCEN ? "SRCEN" : " ", + blitter.command & CMD_DSTEN ? "DSTEN" : " "); + + mame_printf_debug("Src Address Byte 0 %.2x\n", blitter.source.addr0); + mame_printf_debug("Src Address Byte 1 %.2x\n", blitter.source.addr1); + mame_printf_debug("Src Control %.2x\n", blitter.source.addr2); + mame_printf_debug(" Src Address %.5x\n", blitter.source.addr & 0xfffff); + mame_printf_debug("Dest Address Byte 0 %.2x\n", blitter.dest.addr0); + mame_printf_debug("Dest Address Byte 1 %.2x\n", blitter.dest.addr1); + mame_printf_debug("Dest Control %.2x\n", blitter.dest.addr2); + mame_printf_debug(" Dst. Address %.5x\n", blitter.dest.addr & 0xfffff); + mame_printf_debug("Mode Control %.2x", blitter.modectl); + mame_printf_debug(" %s\n", blitter.modectl & MODE_BITTOBYTE ? "BIT_TO_BYTE" : ""); + + mame_printf_debug("Comp. and LFU %.2x\n", blitter.compfunc); + mame_printf_debug("Outer Loop Count %.2x (%d)\n", blitter.outercnt, blitter.outercnt); + mame_printf_debug("Inner Loop Count %.2x (%d)\n", blitter.innercnt, blitter.innercnt); + mame_printf_debug("Step Value %.2x\n", blitter.step); + mame_printf_debug("Pattern Byte %.2x\n", blitter.pattern); + } +#endif + + /* Ignore these writes */ + if (blitter.dest.addr == 0) + { + return; + } + + /* Dirty hacks for Quizvaders */ + if ( (blitter.command == 0x01) || (blitter.command == 0x19) ) + { + blitter.command |= CMD_SRCEN; + } + + /* Begin outer loop */ + for (;;) + { + UINT8 innercnt = blitter.innercnt; + + if (blitter.command & CMD_LINEDRAW) + { + /* + Line Drawing Mode + + x1 - x0 + y1 - y0 + + d1 = bigger + d2 = smaller + + * SRC0 = d1/2 + * SRC1 = d1 + * Inner Count = d1 + * DST0 = X0 + * DST1 = Y0 + * Source control = LSB of d1 + * Step reg = d2 + */ + } + else do + { + // UINT32 srcaddr = 0; + UINT8 inhibit = 0; + + /* TODO: Set this correctly */ + UINT8 result = blitter.pattern; + + /* Source value is read only once in character mode */ + if (blitter.modectl & MODE_BITTOBYTE && innercnt == blitter.innercnt) + { + if (blitter.command & CMD_SRCEN) + { + srcdata = *(blitter_get_addr(blitter.source.addr & 0xfffff)); + } + } + + /* Enable source address read and increment? */ + if ( !(blitter.modectl & (MODE_BITTOBYTE | MODE_PALREMAP)) ) + { + if (blitter.command & CMD_SRCEN) + { + srcdata = *(blitter_get_addr(blitter.source.addr & 0xfffff)); + + /* TODO */ + if (blitter.modectl & MODE_SSIGN) + blitter.source.addr = (blitter.source.addr - 1) & 0xfffff; + else + blitter.source.addr = (blitter.source.addr + 1) & 0xfffff; + + result = srcdata; + } + } + + /* Read destination pixel? */ + if (blitter.command & CMD_DSTEN) + { + dstdata = *blitter_get_addr(blitter.dest.addr & 0xfffff); + } + + /* Inhibit depending on the bit selected by the inner count */ + + /* Switch on comparator type? */ + if (blitter.modectl & MODE_BITTOBYTE) + { + inhibit = !(srcdata & (1 << (8 - innercnt))); + + if (innercnt == 1) + { + blitter.source.addr = (blitter.source.addr + 1) & 0xfffff; + } + } + + if (blitter.compfunc & 0x08) + { + if (srcdata == blitter.pattern) + { + inhibit = 1; + + /* TODO: Resume from inhibit? */ + if (blitter.command & CMD_COLST) + return; + } + } + + /* Write the data if not inhibited */ + if (!inhibit) + { + if (blitter.modectl == MODE_PALREMAP) + { + /* + In this mode, the source points to a 256 entry lookup table. + The existing destination pixel is used as a lookup + into the table and the colours is replaced. + */ + UINT8 dest = *blitter_get_addr(blitter.dest.addr); + UINT8 newcol = *(blitter_get_addr((blitter.source.addr + dest) & 0xfffff)); + + *blitter_get_addr(blitter.dest.addr) = newcol; + } + else + { + *blitter_get_addr(blitter.dest.addr) = result; + } + } + + /* Update destination address */ + blitter.dest.addr = (blitter.dest.addr + 1) & 0xfffff; + } while (--innercnt); + + if (!--blitter.outercnt) + { + break; + } + else + { + if (blitter.command & CMD_DSTUP) + { + blitter.dest.addr = (blitter.dest.addr + blitter.step) & 0xfffff; + } + + if (blitter.command & CMD_SRCUP) + { + blitter.source.addr = (blitter.source.addr + blitter.step) & 0xfffff; + } + + if (blitter.command & CMD_PARRD) + { + BLITPRG_READ(innercnt); + BLITPRG_READ(step); + BLITPRG_READ(pattern); + } + } + } + + /* Read next command header */ + BLITPRG_READ(command); + + } while (blitter.command & CMD_RUN); +} + + +static READ8_HANDLER( ramdac_r ) +{ + UINT8 val = 0xff; + + switch (offset & 3) + { + case 1: + { + UINT8 *count = &ramdac.count_r; + + if (*count == 0) + { + rgb_t color; + color = palette_get_color(Machine, ramdac.addr_r); + + ramdac.color_r[0] = RGB_RED(color); + ramdac.color_r[1] = RGB_GREEN(color); + ramdac.color_r[2] = RGB_BLUE(color); + } + + val = ramdac.color_r[*count]; + + /* 8bpp -> 6bpp */ + val = ((val & 0xc0) >> 2) | ((val >>2) & 0xf); + + if (++*count == 3) + { + *count = 0; + ramdac.addr_r++; + } + break; + } + default: + { + mame_printf_debug("Unhandled RAMDAC read (PC:%.4x)\n", activecpu_get_previouspc()); + } + } + + return val; +} + +static WRITE8_HANDLER( ramdac_w ) +{ + switch (offset & 3) + { + case 0: + { + ramdac.addr_w = data; + break; + } + case 1: + { + data &= 0x3f; + ramdac.color_w[ramdac.count_w] = pal6bit(data); + if (++ramdac.count_w == 3) + { + palette_set_color_rgb(Machine, ramdac.addr_w, ramdac.color_w[0], ramdac.color_w[1], ramdac.color_w[2]); + ramdac.count_w = 0; + ramdac.addr_w++; + } + break; + } + case 2: + { + ramdac.mask = data; + break; + } + case 3: + { + ramdac.addr_r = data; + break; + } + } +} + +/*************************************************************************** + + Flare One Register Map + + 01 Bank control for Z80 region 0x4000-0x7fff (16kB) WR + 02 Bank control for Z80 region 0x8000-0xbfff (16kB) WR + 03 Bank control for Z80 region 0xc000-0xffff (16kB) WR + + 06 Interrupt status....................................WR + 07 Interrupt ack.......................................WR + ???? Written with 0x21 + 08 + 09 ???? Linked with c001...............................W + 0A ???? Written with 0 and 1...........................W + + 0B Horizontal frame buffer scroll .....................W + 0C Vertical frame buffer scroll .......................W + + 0D ???? Written with $FF...............................W + 0E ???? Written with $A2 (162).........................W + 0F ???? Written with $B4 (180).........................W + 14 ....................................................W + + 18 Blitter program low byte............................WR + 19 Blitter program middle byte.........................W + 1A Blitter program high byte...........................W + 1B Blitter command?....................................W + 1C Blitter status?......................................R + 20 Blitter control register............................W + + 22 ???? Linked with C002...............................W + Mask of 20 + + Joystick: xxx1 11xx R + ? (polled on tight loop): x1xx xxxx R + + 40: ROM bank select.....................................W + +***************************************************************************/ + +static READ8_HANDLER( chipset_r ) +{ + UINT8 val = 0xff; + + switch(offset) + { + case 1: + case 2: + case 3: + { + val = bank[offset]; + break; + } + case 6: + { + /* TODO */ + val = vblank_irq << 4; + break; + } + case 7: + { + vblank_irq = 0; + val = 0x1; + + /* TODO */ + update_irqs(); + break; + } + case 0x1C: + { + /* Blitter status ? */ + val = 0; + break; + } + case 0x20: + { + /* Seems correct - used during RLE pic decoding */ + val = blitter.dest.addr0; + break; + } + case 0x22: + { + val = 0x40 | readinputportbytag("JOYSTICK"); + break; + } + default: + { + mame_printf_debug("Flare One unknown read: 0x%.2x (PC:0x%.4x)\n", offset, activecpu_get_previouspc()); + } + } + + return val; +} + +static WRITE8_HANDLER( chipset_w ) +{ + switch (offset) + { + case 0x01: + case 0x02: + case 0x03: + { + if (data > 0x3f) + { + popmessage("%x: Unusual bank access (%x)\n", activecpu_get_previouspc(), data); + } + data &= 0x3f; + bank[offset] = data; + z80_bank(offset, data); + break; + } + case 0x08: + { + flip_8 = data; + break; + } + case 0x0B: + { + h_scroll = data; + break; + } + case 0x0C: + { + v_scroll = data; + break; + } + case 0x18: + { + blitter.program.addr0 = data; + break; + } + case 0x19: + { + blitter.program.addr1 = data; + break; + } + case 0x1A: + { + blitter.program.addr2 = data; + break; + } + case 0x20: + { + blitter.command = data; + + if (data & CMD_RUN) + RunBlit(); + else + mame_printf_debug ("Blitter stopped by IO.\n"); + + break; + } + case 0x22: + { + flip_22 = data; + break; + } + default: + { + mame_printf_debug("Flare One unknown write: 0x%.2x with 0x%.2x (PC:0x%.4x)\n", offset, data, activecpu_get_previouspc()); + } + } +} + +INLINE void z80_bank(int num, int data) +{ + if (data < 0x08) + { + /* TODO: Don't need this table! */ + static UINT32 offs_table[2][8] = + { + { 0x10000, 0x14000, 0x18000, 0x1c000, 0x00000, 0x04000, 0x08000, 0x0c000 }, + { 0x00000, 0x04000, 0x08000, 0x0c000, 0x10000, 0x14000, 0x18000, 0x1c000 } + }; + + UINT32 offset = ((bank[0] >> 1) * 0x20000) + offs_table[bank[0] & 0x1][data]; + + memory_set_bankptr(num, memory_region(REGION_USER1) + offset); + } + else if (data < 0x10) + { + memory_set_bankptr(num, &video_ram[(data - 0x08) * 0x4000]); + } + else + { + memory_set_bankptr(num, &work_ram[(data - 0x10) * 0x4000]); + } +} + +static WRITE8_HANDLER( rombank_w ) +{ + bank[0] = data; + z80_bank(1, bank[1]); + z80_bank(2, bank[2]); + z80_bank(3, bank[3]); +} + + + +/*************************************************************************** + + Split into machine\cobra.c ! + + Alternatively chuck it all away and borrow the MESS implementation + because it's a million times better. + +***************************************************************************/ + +static void command_phase(UINT8 data); +static void exec_w_phase(UINT8 data); +//UINT8 exec_r_phase(void); + +/* + WD37C656C-PL (or equivalent) Floppy Disk Controller +*/ + +enum fdc_phase +{ + COMMAND, + EXECUTION_R, + EXECUTION_W, + RESULTS, +}; + +enum command +{ + SENSE_DRIVE_STATUS = 0, + READ_A_TRACK = 2, + SPECIFY = 3, + WRITE_DATA = 5, + READ_DATA = 6, + RECALIBRATE = 7, + SENSE_INTERRUPT_STATUS = 8, + WRITE_DELETED_DATA = 9, + READ_ID = 10, + FORMAT_TRACK = 13, + READ_DELETED_DATA = 14, + SEEK = 15, + SCAN_EQUAL = 17, + SCAN_LOW_OR_EQUAL = 25, + SCAN_HIGH_OR_EQUAL = 29 +}; + +static struct +{ + UINT8 MSR; + + int side; + int track; + int sector; + int number; + int stop_track; + int setup_read; + + int byte_pos; + int offset; + + int phase; + int next_phase; + int cmd_len; + int cmd_cnt; + int res_len; + int res_cnt; + UINT8 cmd[10]; + UINT8 results[8]; +} fdc; + + +static void reset_fdc(void) +{ + memset(&fdc, 0, sizeof(fdc)); + + fdc.MSR = 0x80; + fdc.phase = COMMAND; +} + +static READ8_HANDLER( fdctrl_r ) +{ + UINT8 val = 0; + + val = fdc.MSR; + + return val; +} + +static READ8_HANDLER( fddata_r ) +{ + #define BPS 1024 + #define SPT 10 + #define BPT 1024*10 + + UINT8 val = 0; + + if (fdc.phase == EXECUTION_R) + { + switch (fdc.cmd[0] & 0x1f) + { + /* Specify */ + case READ_DATA: + { + if (fdc.setup_read) + { + fdc.track = fdc.cmd[2]; + fdc.side = fdc.cmd[3]; + fdc.sector = fdc.cmd[4]; + fdc.number = fdc.cmd[5]; + fdc.stop_track = fdc.cmd[6]; + //int GPL = fdc.cmd[7]; + //int DTL = fdc.cmd[8]; + + fdc.setup_read = 0; + fdc.byte_pos = 0; + } + + fdc.offset = (BPT * fdc.track*2) + (fdc.side ? BPT : 0) + (BPS * (fdc.sector-1)) + fdc.byte_pos++; + val = *(memory_region(REGION_USER2) + fdc.offset); + + /* Move on to next sector? */ + if (fdc.byte_pos == 1024) + { + fdc.byte_pos = 0; + + if(fdc.sector == fdc.stop_track || ++fdc.sector == 11) + { + /* End of read operation */ + fdc.MSR = 0xd0; + fdc.phase = RESULTS; + + fdc.results[0] = 0; + fdc.results[1] = 0; + fdc.results[2] = 0; + + fdc.results[3] = 0; + fdc.results[4] = 0; + fdc.results[5] = 0; + fdc.results[6] = 0; + } + } + break; + } + } + } + else if (fdc.phase == RESULTS) + { + val = fdc.results[fdc.res_cnt++]; + + if (fdc.res_cnt == fdc.res_len) + { + fdc.phase = COMMAND; + fdc.res_cnt = 0; + fdc.MSR &= ~0x40; + } + } + + return val; +} + +static WRITE8_HANDLER( fdctrl_w ) +{ + switch (fdc.phase) + { + case COMMAND: + { + command_phase(data); + break; + } + case EXECUTION_W: + { + exec_w_phase(data); + break; + } + default: + { + mame_printf_debug("Unknown FDC phase?!"); + } + } +} + +static void command_phase(UINT8 data) +{ + if (fdc.cmd_cnt == 0) + { + fdc.cmd[0] = data; + + fdc.cmd_cnt = 1; + + switch (data & 0x1f) + { + /* Specify */ + case READ_DATA: + { +// mame_printf_debug("Read data\n"); + fdc.cmd_len = 9; + fdc.res_len = 7; + fdc.next_phase = EXECUTION_R; + fdc.setup_read = 1; + break; + } + case SPECIFY: + { +// mame_printf_debug("Specify\n"); + fdc.cmd_len = 3; + fdc.res_len = 0; + fdc.next_phase = COMMAND; + break; + } + case RECALIBRATE: + { +// mame_printf_debug("Recalibrate\n"); + fdc.cmd_len = 2; + fdc.res_len = 0; + fdc.next_phase = COMMAND; + //fdc.MSR |= 0x40; + break; + } + case SENSE_INTERRUPT_STATUS: + { +// mame_printf_debug("Sense interrupt status\n"); + fdc.cmd_len = 1; + fdc.res_len = 2; + fdc.phase = RESULTS; + + fdc.results[0] = 0; + fdc.results[1] = 0; + + fdc.cmd_cnt = 0; + fdc.MSR |= 0x40; + break; + } + case SEEK: + { +// mame_printf_debug("Seek\n"); + fdc.cmd_len = 3; + fdc.res_len = 0; + fdc.next_phase = COMMAND; + break; + } + default: + { +// mame_printf_debug("%x\n",data & 0x1f); + } + } + } + else + { + fdc.cmd[fdc.cmd_cnt++] = data; + //mame_printf_debug(" %x\n",data); + } + + if(fdc.cmd_cnt == fdc.cmd_len) + { + fdc.phase = fdc.next_phase; + fdc.cmd_cnt = 0; + + if ((fdc.cmd[0] & 0x1f) == READ_DATA) + fdc.MSR = 0xf0; + } +} + +#ifdef UNUSED_FUNCTION +UINT8 exec_r_phase(void) +{ + return 0; +} +#endif + +static void exec_w_phase(UINT8 data) +{ +} + +#ifdef UNUSED_FUNCTION +UINT8 results_phase(void) +{ + return 0; +} + +WRITE8_HANDLER( fd_op_w ) +{ +} + +WRITE8_HANDLER( fd_ctrl_w ) +{ +} +#endif + +static MACHINE_RESET( bfcobra ) +{ + bank[0] = 1; + memset(&ramdac, 0, sizeof(ramdac)); + reset_fdc(); + + irq_state = blitter_irq = vblank_irq = acia_irq = 0; +} + +/*************************************************************************** + + Cobra I/Viper Z80 Memory Map + +***************************************************************************/ + +static ADDRESS_MAP_START( z80_prog_map, ADDRESS_SPACE_PROGRAM, 8 ) + AM_RANGE(0x0000, 0x3fff) AM_READ(MRA8_BANK4) + AM_RANGE(0x4000, 0x7fff) AM_READWRITE(MRA8_BANK1, MWA8_BANK1) + AM_RANGE(0x8000, 0xbfff) AM_READWRITE(MRA8_BANK2, MWA8_BANK2) + AM_RANGE(0xc000, 0xffff) AM_READWRITE(MRA8_BANK3, MWA8_BANK3) +ADDRESS_MAP_END + +static ADDRESS_MAP_START( z80_io_map, ADDRESS_SPACE_IO, 8 ) +ADDRESS_MAP_FLAGS( AMEF_ABITS(8) ) + AM_RANGE(0x00, 0x23) AM_READWRITE(chipset_r, chipset_w) + AM_RANGE(0x24, 0x24) AM_WRITE(acia6850_0_ctrl_w) + AM_RANGE(0x25, 0x25) AM_WRITE(acia6850_0_data_w) + AM_RANGE(0x26, 0x26) AM_READ(acia6850_0_stat_r) + AM_RANGE(0x27, 0x27) AM_READ(acia6850_0_data_r) + AM_RANGE(0x30, 0x30) AM_READ(fdctrl_r) + AM_RANGE(0x31, 0x31) AM_READWRITE(fddata_r, fdctrl_w) + AM_RANGE(0x40, 0x40) AM_WRITE(rombank_w) + AM_RANGE(0x50, 0x53) AM_READWRITE(ramdac_r, ramdac_w) +ADDRESS_MAP_END + + +/*************************************************************************** + + Cobra I/Viper 6809 Memory Map + + Cobra I has these components: + + EF68B50P - For communication with Z80 + EF68B50P - For data retrieval + AY38912A + UPD7759C + BFM1090 (CF30056) - 'TEXAS' I/O chip, lamps and misc + BFM1095 (CF30057) - 'TEXAS' I/O chip, handles switches + BFM1071 - 6809 Address decoding and bus control + + /IRQ provided by EF68850P at IC38 + /FIRQ connected to meter current sensing circuitry + + TODO: Calculate watchdog timer period. + +***************************************************************************/ + +/* TODO */ +static READ8_HANDLER( int_latch_r ) +{ + return 2 | 1; +} + +/* TODO */ +static READ8_HANDLER( meter_r ) +{ + return meter_latch; +} + +/* TODO */ +static WRITE8_HANDLER( meter_w ) +{ + //int changed = meter_latch ^ data; + + meter_latch = data; + + /* + When a meter is triggered, the current drawn is sensed. If a meter + is connected, the /FIRQ line will be pulsed. + */ + if ( data ) + { + cpunum_set_input_line(1, M6809_FIRQ_LINE, PULSE_LINE ); + } +} + +/* TODO */ +static READ8_HANDLER( latch_r ) +{ + return mux_input; +} + +static WRITE8_HANDLER( latch_w ) +{ + /* TODO: This is borrowed from Scorpion 1 */ + switch(offset) + { + case 0: + { + int changed = mux_outputlatch ^ data; + + mux_outputlatch = data; + + /* Clock has changed */ + if (changed & 0x08) + { + int input_strobe = data & 0x7; + + /* Clock is low */ + if (!(data & 0x08)) + mux_input = readinputport(input_strobe); + } + break; + } + case 1: + { +// strobe_data_l = data; + break; + } + case 2: + { +// strobe_data_h = data; + break; + } + } +} + +static READ8_HANDLER( upd7759_r ) +{ + return 2 | upd7759_busy_r(0); +} + +static WRITE8_HANDLER( upd7759_w ) +{ + upd7759_reset_w(0, data & 0x80); + upd7759_port_w(0, data & 0x3f); + upd7759_start_w(0, data & 0x40 ? 0 : 1); +} + +static ADDRESS_MAP_START( m6809_prog_map, ADDRESS_SPACE_PROGRAM, 8 ) + AM_RANGE(0x0000, 0x1fff) AM_RAM AM_BASE(&generic_nvram) AM_SIZE(&generic_nvram_size) + AM_RANGE(0x2000, 0x2000) AM_RAM // W 'B', 6F + AM_RANGE(0x2200, 0x2200) AM_RAM // W 'F' + AM_RANGE(0x2600, 0x2600) AM_READWRITE(meter_r, meter_w) + AM_RANGE(0x2800, 0x2800) AM_RAM // W + AM_RANGE(0x2A00, 0x2A02) AM_READWRITE(latch_r, latch_w) + AM_RANGE(0x2E00, 0x2E00) AM_READ(int_latch_r) + AM_RANGE(0x3001, 0x3001) AM_WRITE(AY8910_write_port_0_w) + AM_RANGE(0x3201, 0x3201) AM_WRITE(AY8910_control_port_0_w) + AM_RANGE(0x3404, 0x3404) AM_READWRITE(acia6850_1_stat_r, acia6850_1_ctrl_w) + AM_RANGE(0x3405, 0x3405) AM_READWRITE(acia6850_1_data_r, acia6850_1_data_w) + AM_RANGE(0x3406, 0x3406) AM_READWRITE(acia6850_2_stat_r, acia6850_2_ctrl_w) + AM_RANGE(0x3407, 0x3407) AM_READWRITE(acia6850_2_data_r, acia6850_2_data_w) +// AM_RANGE(0x3408, 0x3408) AM_NOP +// AM_RANGE(0x340A, 0x340A) AM_NOP +// AM_RANGE(0x3600, 0x3600) AM_NOP + AM_RANGE(0x3801, 0x3801) AM_READWRITE(upd7759_r, upd7759_w) + AM_RANGE(0x8000, 0xffff) AM_READ(MRA8_ROM) + AM_RANGE(0xf000, 0xf000) AM_WRITE(MWA8_NOP) /* Watchdog */ +ADDRESS_MAP_END + +static INPUT_PORTS_START( bfcobra ) +PORT_START_TAG("STROBE0") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_COIN1 ) PORT_NAME("Coin: 10p") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_NAME("Coin: 20p") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_COIN3 ) PORT_NAME("Coin: 50p") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_COIN4 ) PORT_NAME("Coin: 1 pound") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_SERVICE ) PORT_NAME("Green Test?") PORT_CODE(KEYCODE_F1) + PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN ) + + PORT_START_TAG("STROBE1") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("PASS") PORT_CODE(KEYCODE_A) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("CONTINUE") PORT_CODE(KEYCODE_S) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("COLLECT") PORT_CODE(KEYCODE_D) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_START1 ) PORT_NAME("START") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_NAME("BONUS") PORT_CODE(KEYCODE_F) +// PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON1 ) +// PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_BUTTON2 ) +// PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_BUTTON3 ) + + PORT_START_TAG("STROBE2") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("<A") + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("<B") + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_NAME("<C") + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON8 ) PORT_NAME("A>") + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON9 ) PORT_NAME("B>") + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_BUTTON10 ) PORT_NAME("C>") + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + + PORT_START_TAG("STROBE3") + PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Cash box door") PORT_CODE(KEYCODE_Y) PORT_TOGGLE + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_SERVICE ) PORT_NAME("Unknown (resets)") PORT_CODE(KEYCODE_T) PORT_TOGGLE + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SERVICE ) PORT_NAME("Refill Key") PORT_CODE(KEYCODE_R) PORT_TOGGLE + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0x40, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + PORT_BIT( 0xF8, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + + PORT_START_TAG("STROBE4") + PORT_BIT( 0xFF, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + + PORT_START_TAG("STROBE5") + PORT_BIT( 0xFF, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + + PORT_START_TAG("STROBE6") + PORT_DIPNAME( 0x01, 0x00, "DIL09" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x00, "DIL10" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x02, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x00, "DIL11" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x04, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x00, "DIL12" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x08, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x00, "DIL13" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x10, DEF_STR( On ) ) + PORT_DIPNAME( 0x20, 0x00, "DIL14" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x20, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x00, "DIL15" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x40, DEF_STR( On ) ) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + + PORT_START_TAG("STROBE7") + PORT_DIPNAME( 0x01, 0x00, "DIL02" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x01, DEF_STR( On ) ) + PORT_DIPNAME( 0x02, 0x00, "DIL03" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x02, DEF_STR( On ) ) + PORT_DIPNAME( 0x04, 0x00, "DIL04" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x04, DEF_STR( On ) ) + PORT_DIPNAME( 0x08, 0x00, "DIL05" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x08, DEF_STR( On ) ) + PORT_DIPNAME( 0x10, 0x00, "DIL06" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x10, DEF_STR( On ) ) + PORT_DIPNAME( 0x20, 0x00, "DIL07" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x20, DEF_STR( On ) ) + PORT_DIPNAME( 0x40, 0x00, "DIL08" ) + PORT_DIPSETTING( 0x00, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x40, DEF_STR( On ) ) + PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_UNKNOWN ) + + PORT_START_TAG("JOYSTICK") + PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) + PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) + PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) + PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) + PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_BUTTON1 ) +INPUT_PORTS_END + +/* + Allocate work RAM and video RAM shared by the Z80 and chipset. +*/ +static void init_ram(void) +{ + /* 768kB work RAM */ + work_ram = auto_malloc(0xC0000); + + /* 128kB video RAM */ + video_ram = auto_malloc(0x20000); + + memset(work_ram, 0, 0xc0000); + memset(video_ram, 0, 0x20000); +} + +static void z80_acia_irq(int state) +{ + acia_irq = state ? CLEAR_LINE : ASSERT_LINE; + update_irqs(); +} + +static void m6809_data_irq(int state) +{ + cpunum_set_input_line(1, M6809_IRQ_LINE, state ? CLEAR_LINE : ASSERT_LINE); +} + +/* + What are the correct ACIA clocks ? +*/ +static struct acia6850_interface z80_acia_if = +{ + 500000, + 500000, + &m6809_z80_line, + &z80_m6809_line, + NULL, + NULL, + NULL, + z80_acia_irq +}; + +static struct acia6850_interface m6809_acia_if = +{ + 500000, + 500000, + &z80_m6809_line, + &m6809_z80_line, + NULL, + NULL, + NULL, + NULL +}; + +static struct acia6850_interface data_acia_if = +{ + 500000, + 500000, + &data_r, + &data_t, + NULL, + NULL, + NULL, + m6809_data_irq +}; + + +/* TODO: Driver vs Machine Init */ +static DRIVER_INIT( bfcobra ) +{ + /* + 6809 ROM address and data lines are scrambled. + This is the same scrambling as Scorpion 2. + */ + static const UINT8 datalookup[] = { 1, 3, 5, 6, 4, 2, 0, 7 }; + static const UINT8 addrlookup[] = { 11, 12, 0, 2, 3, 5, 7, 9, 8, 6, 1, 4, 10, 13, 14 }; + + UINT32 i; + UINT8 *rom; + UINT8 *tmp; + + tmp = malloc_or_die(0x8000); + rom = memory_region(REGION_CPU2) + 0x8000; + memcpy(tmp, rom, 0x8000); + + for (i = 0; i < 0x8000; i++) + { + UINT16 addr = 0; + UINT8 x; + UINT8 data = 0; + UINT8 val = tmp[i]; + + for (x = 0; x < 8; x ++) + data |= ((val >> x) & 1) << datalookup[x]; + + for (x = 0; x < 15; x ++) + addr |= ((i >> x) & 1) << addrlookup[x]; + + rom[addr] = data; + } + + free(tmp); + + init_ram(); + + bank[0] = 1; + bank[1] = 0; + bank[2] = 0; + bank[3] = 0; + + /* Fixed 16kB ROM region */ + memory_set_bankptr(4, memory_region(REGION_USER1)); + + /* Configure the ACIAs */ + acia6850_config(0, &z80_acia_if); + acia6850_config(1, &m6809_acia_if); + acia6850_config(2, &data_acia_if); + + /* TODO: Properly sort out the data ACIA */ + data_r = 1; + + /* Finish this */ + state_save_register_global(z80_m6809_line); + state_save_register_global(m6809_z80_line); + state_save_register_global(data_r); + state_save_register_global(data_t); + state_save_register_global(h_scroll); + state_save_register_global(v_scroll); + state_save_register_global(flip_8); + state_save_register_global(flip_22); + state_save_register_global(z80_int); + state_save_register_global(z80_inten); + state_save_register_global_array(bank); + state_save_register_global_pointer(work_ram, 0xc0000); + state_save_register_global_pointer(video_ram, 0x20000); +} + +static struct upd7759_interface upd7759_interface = +{ + REGION_SOUND1 +}; + +/* TODO */ +static INTERRUPT_GEN( timer_irq ) +{ + cpunum_set_input_line(1, M6809_IRQ_LINE, PULSE_LINE); +} + +/* TODO */ +static INTERRUPT_GEN( vblank_gen ) +{ + vblank_irq = 1; + update_irqs(); +} + +static MACHINE_DRIVER_START( bfcobra ) + MDRV_CPU_ADD(Z80, Z80_XTAL) + MDRV_CPU_PROGRAM_MAP(z80_prog_map, 0) + MDRV_CPU_IO_MAP(z80_io_map, 0) + MDRV_CPU_VBLANK_INT(vblank_gen, 1) + + MDRV_CPU_ADD(M6809, M6809_XTAL) + MDRV_CPU_PROGRAM_MAP(m6809_prog_map, 0) + MDRV_CPU_PERIODIC_INT(timer_irq, 1000) + + MDRV_NVRAM_HANDLER(generic_0fill) + + MDRV_MACHINE_RESET(bfcobra) + + /* TODO */ + MDRV_SCREEN_REFRESH_RATE(60) + MDRV_SCREEN_VBLANK_TIME(DEFAULT_REAL_60HZ_VBLANK_DURATION) + MDRV_SCREEN_FORMAT(BITMAP_FORMAT_RGB32) + MDRV_SCREEN_SIZE(256, 256) + MDRV_SCREEN_VISIBLE_AREA(0, 256-1, 0, 256-1) + MDRV_PALETTE_LENGTH(256) + + MDRV_SPEAKER_STANDARD_MONO("mono") + + MDRV_SOUND_ADD(AY8910, M6809_XTAL) + MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.20) + + MDRV_SOUND_ADD(UPD7759, UPD7759_STANDARD_CLOCK) + MDRV_SOUND_CONFIG(upd7759_interface) + MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40) + + MDRV_VIDEO_START(generic_bitmapped) + MDRV_VIDEO_UPDATE(bfcobra) +MACHINE_DRIVER_END + +/*************************************************************************** + + Game driver(s) + + Note: Two different versions of each 6809 ROM exist: standard and protocol + It appears sets can be a combination of disk images, 6809 and Z80 ROMs! + +***************************************************************************/ + +ROM_START( inquiztr ) + ROM_REGION( 0x20000, REGION_USER1, 0 ) + ROM_LOAD( "9576028.bin", 0x00000, 0x10000, CRC(2d85682c) SHA1(baec47bff4b8beef5afbb737dc57b22bf93ebcf8) ) + ROM_LOAD( "9576002.bin", 0x10000, 0x10000, CRC(5b8c8a04) SHA1(af5328fee79c370f45bff36f534aaf50964b6900) ) + + ROM_REGION( 0x10000, REGION_CPU2, 0 ) + ROM_LOAD( "inq6809", 0x08000, 0x08000, CRC(ae996600) SHA1(f360399e77b81399d910770fa8106c196f04363c) ) + + ROM_REGION( 0x1c2000, REGION_USER2, 0 ) + ROM_LOAD( "inqdisk.img", 0x000000, 0x1c2000, NO_DUMP ) +ROM_END + +ROM_START( escounts ) + ROM_REGION( 0x10000, REGION_USER1, 0 ) + ROM_LOAD( "esccobpa", 0x00000, 0x10000, CRC(d8eadeb7) SHA1(9b94f1454e6a17bf8321b0ef4ddd0ed1a56150f7) ) + + ROM_REGION( 0x10000, REGION_CPU2, 0 ) +// ROM_LOAD( "escint1b", 0x08000, 0x08000, CRC(96918aae) SHA1(849ce7b8eccc89c45aacc840a73935f95788a141) ) + ROM_LOAD( "esc12int", 0x08000, 0x08000, CRC(741a1fe6) SHA1(e741d0ae0d2f11036a358120381e4b0df4a560a1) ) + + /* 95-100-207 */ + ROM_REGION( 0x190000, REGION_USER2, 0 ) + ROM_LOAD( "escdisk4.img", 0x000000, 0x190000, CRC(24156e0f) SHA1(e163daa8effadd93ace2bc2ba1af0f4a190abd7f) ) +ROM_END + +ROM_START( trebltop ) + ROM_REGION( 0x20000, REGION_USER1, 0 ) + ROM_LOAD( "95760031.bin", 0x00000, 0x10000, CRC(8e75edb8) SHA1(0aaa3834d5ac20f92bdf1f2b8f1eb71854469cbe) ) + ROM_LOAD( "95760021.bin", 0x10000, 0x10000, CRC(f42016c0) SHA1(7067d018cb4bdcfba777267fb01cddf44e4216c3) ) + + ROM_REGION( 0x10000, REGION_CPU2, 0 ) + ROM_LOAD( "95740078.bin", 0x08000, 0x08000, CRC(aca1980b) SHA1(3d4ed1dc545cc80f56d7daa13028fb10a12a718b) ) + + ROM_REGION( 0x20000, REGION_SOUND1, 0 ) + ROM_LOAD( "95000172.bin", 0x00000, 0x10000, CRC(e85367a5) SHA1(695fd95ddeecdb16602f7b0f075cf5128a2fb808) ) + ROM_LOAD( "95000173.bin", 0x10000, 0x10000, CRC(8bda2c5e) SHA1(79aab5a2af7a5add5fe9132dc13bcc3705c6faf3) ) + + ROM_REGION( 0x1c2000, REGION_USER2, 0 ) + ROM_LOAD( "ttdisk1.img", 0x000000, 0x190000, CRC(b2003228) SHA1(5eb49f05137cdd404f22948d39aa79c1518c06eb) ) +ROM_END + +ROM_START( quizvadr ) + ROM_REGION( 0x200000, REGION_USER1, 0 ) + ROM_LOAD( "5947011r.0", 0x000000, 0x80000, CRC(cac43c97) SHA1(3af529cd0f8ec57dd3596f5bca7b9c74cff171e4) ) + ROM_LOAD( "5947011r.1", 0x080000, 0x80000, CRC(120018dc) SHA1(cd153d2b7ed535b04dbcaf189d2fc96fe3c5b466) ) + ROM_LOAD( "5947011r.2", 0x100000, 0x80000, CRC(689b3b5a) SHA1(ea32d18acfd380de822efff4f2c95ce9873a33a2) ) + ROM_LOAD( "5947011r.3", 0x180000, 0x80000, CRC(c38dafeb) SHA1(d693387a5c3cde34c9d581f81a08a5fbc6f753f2) ) + + ROM_REGION( 0x10000, REGION_CPU2, 0 ) + ROM_LOAD( "q6809.bin", 0x08000, 0x8000, CRC(a74dff10) SHA1(87578694a022dc3d7ade9cc76d387c1ae5fc74d9) ) + + ROM_REGION( 0x20000, REGION_SOUND1, 0 ) + ROM_LOAD( "185snd2.bin", 0x00000, 0x10000, CRC(e36eccc2) SHA1(cfd8ca4c71528ea4e229074016240681b6de37cd) ) + ROM_LOAD( "184snd1.bin", 0x10000, 0x10000, CRC(aac058e8) SHA1(39e59ad9524130fc3bd8d46e1aa78bc4daf04e39) ) +ROM_END + +ROM_START( qos ) + ROM_REGION( 0x200000, REGION_USER1, 0 ) + ROM_LOAD( "95000338.rm0", 0x000000, 0x80000, CRC(96918aae) SHA1(849ce7b8eccc89c45aacc840a73935f95788a141) ) + ROM_LOAD( "95000339.rm1", 0x080000, 0x80000, CRC(b4c6dcc0) SHA1(56d8761766dfbd5b0e71f8c3ca575e88f1bc9929) ) + ROM_LOAD( "95000340.rm2", 0x100000, 0x80000, CRC(66d121fd) SHA1(ac65cc0ac6b0a41e78a3159c21ee44f765bdb5c8) ) + ROM_LOAD( "95000341.rm3", 0x180000, 0x80000, CRC(ef13658d) SHA1(240bc589900214eac79c91a531f254a9ac2f4ef6) ) + + ROM_REGION( 0x10000, REGION_CPU2, 0 ) + ROM_LOAD( "qos_nondata_68f4.bin", 0x08000, 0x8000, CRC(5f40005a) SHA1(180017acf6b432bc135d1090099fdf99f1e3583a) ) + + ROM_REGION( 0x20000, REGION_SOUND1, 0 ) + ROM_LOAD( "snd1_218.ic7", 0x00000, 0x10000, CRC(061f496d) SHA1(653d16454d909c034191813b37d14010da7258c6) ) + ROM_LOAD( "snd2_219.ic8", 0x10000, 0x10000, CRC(d7874a47) SHA1(5bbd4040c7c0299e8cc135e6c6cd05370b260e9b) ) +ROM_END + +ROM_START( qosa ) + ROM_REGION( 0x200000, REGION_USER1, 0 ) + ROM_LOAD( "0306.bin", 0x000000, 0x80000, CRC(c26c8f83) SHA1(6949027e1fe241cbb2e1cbbce18e47bcb0d84550) ) + ROM_LOAD( "1307.bin", 0x080000, 0x80000, CRC(94611c03) SHA1(81f545ff96ff3d44285315400da94d870c89f896) ) + ROM_LOAD( "2308.bin", 0x100000, 0x80000, CRC(f5572726) SHA1(e109265c5571d21213a6f405a13459e7bc6699bc) ) + ROM_LOAD( "3309.bin", 0x180000, 0x80000, CRC(1b5edfa8) SHA1(348488debd4aa52f064e351ed0c082274da1db2b) ) + + ROM_REGION( 0x10000, REGION_CPU2, 0 ) + ROM_LOAD( "95740599.bin", 0x08000, 0x8000, CRC(bf1e321f) SHA1(51f18620f22ba2a1b110954284ddf00614d51a0e) ) + + ROM_REGION( 0x20000, REGION_SOUND1, 0 ) + ROM_LOAD( "snd1_218.ic7", 0x00000, 0x10000, CRC(061f496d) SHA1(653d16454d909c034191813b37d14010da7258c6) ) + ROM_LOAD( "snd2_219.ic8", 0x10000, 0x10000, CRC(d7874a47) SHA1(5bbd4040c7c0299e8cc135e6c6cd05370b260e9b) ) +ROM_END + +GAME( 1989, inquiztr, 0, bfcobra, bfcobra, bfcobra, ROT0, "BFM", "Inquizitor", GAME_NOT_WORKING ) +GAME( 1990, escounts, 0, bfcobra, bfcobra, bfcobra, ROT0, "BFM", "Every Second Counts (39-360-053)", GAME_IMPERFECT_GRAPHICS | GAME_IMPERFECT_COLORS ) +GAME( 1991, trebltop, 0, bfcobra, bfcobra, bfcobra, ROT0, "BFM", "Treble Top (39-360-070)", GAME_IMPERFECT_GRAPHICS ) +GAME( 1991, quizvadr, 0, bfcobra, bfcobra, bfcobra, ROT0, "BFM", "Quizvaders (39-360-078)", GAME_IMPERFECT_GRAPHICS ) +GAME( 1992, qos, 0, bfcobra, bfcobra, bfcobra, ROT0, "BFM", "A Question of Sport (39-960-099)", GAME_IMPERFECT_GRAPHICS ) +GAME( 1992, qosa, qos, bfcobra, bfcobra, bfcobra, ROT0, "BFM", "A Question of Sport (39-960-089)", GAME_IMPERFECT_GRAPHICS ) |