mirror of
https://github.com/holub/mame
synced 2025-05-20 12:48:53 +03:00
Virtual Combat driver improvements. [Jason Eckhardt, Andrew Gardner]
* Graphics decoded, video improved, inputs mapped. Intel i860 CPU core added. [Jason Eckhardt] (The CPU core doesn't have accurate cycle counts for each opcode yet, but it'll have them soon. I believe that is the main culprit behind the sync of the two i860s and the 68k being outta' whack. You can still see the i860s do their thing and rasterize a voxel? groundplane and some simple polygon bad guys).
This commit is contained in:
parent
f4392d4c6f
commit
6ea9ca0589
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -162,6 +162,8 @@ src/emu/cpu/i86/table86.h svneol=native#text/plain
|
||||
src/emu/cpu/i860/i860.c svneol=native#text/plain
|
||||
src/emu/cpu/i860/i860.h svneol=native#text/plain
|
||||
src/emu/cpu/i860/i860dasm.c svneol=native#text/plain
|
||||
src/emu/cpu/i860/i860dec.c svneol=native#text/plain
|
||||
src/emu/cpu/i860/i860dis.c svneol=native#text/plain
|
||||
src/emu/cpu/i960/i960.c svneol=native#text/plain
|
||||
src/emu/cpu/i960/i960.h svneol=native#text/plain
|
||||
src/emu/cpu/i960/i960dis.c svneol=native#text/plain
|
||||
|
@ -744,12 +744,12 @@ CPUDEFS += -DHAS_I860=$(if $(filter I860,$(CPUS)),1,0)
|
||||
ifneq ($(filter I860,$(CPUS)),)
|
||||
OBJDIRS += $(CPUOBJ)/i860
|
||||
CPUOBJS += $(CPUOBJ)/i860/i860.o
|
||||
DBGOBJS += $(CPUOBJ)/i860/i860dasm.o
|
||||
DBGOBJS += $(CPUOBJ)/i860/i860dis.o
|
||||
endif
|
||||
|
||||
$(CPUOBJ)/i860/i860.o: $(CPUSRC)/i860/i860.c \
|
||||
$(CPUSRC)/i860/i860.h
|
||||
|
||||
$(CPUOBJ)/i860/i860.o: $(CPUSRC)/i860/i860.c \
|
||||
$(CPUSRC)/i860/i860.h \
|
||||
$(CPUSRC)/i860/i860dec.c
|
||||
|
||||
#-------------------------------------------------
|
||||
# Intel i960
|
||||
|
@ -1,91 +1,285 @@
|
||||
/***************************************************************************
|
||||
|
||||
i860.c
|
||||
|
||||
Interface file for the Intel i860 emulator.
|
||||
|
||||
Copyright (C) 1995-present Jason Eckhardt (jle@rice.edu)
|
||||
Released for general non-commercial use under the MAME license
|
||||
with the additional requirement that you are free to use and
|
||||
redistribute this code in modified or unmodified form, provided
|
||||
you list me in the credits.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/*
|
||||
TODO: Separate out i860XR and i860XP (make different types, etc).
|
||||
Hook IRQ lines into MAME core (they're custom functions atm).
|
||||
*/
|
||||
|
||||
#include "debugger.h"
|
||||
#include "i860.h"
|
||||
|
||||
/**************************************************************************
|
||||
* The core struct
|
||||
**************************************************************************/
|
||||
typedef struct _i860_state_t i860_state_t;
|
||||
struct _i860_state_t
|
||||
{
|
||||
const device_config *device;
|
||||
const address_space *program;
|
||||
|
||||
UINT32 pc;
|
||||
UINT32 ppc;
|
||||
|
||||
int icount;
|
||||
};
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* Functions specified by GET_INFO
|
||||
**************************************************************************/
|
||||
|
||||
static CPU_INIT( i860 )
|
||||
{
|
||||
i860_state_t *i860 = device->token;
|
||||
i860->device = device;
|
||||
i860->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM);
|
||||
i860_state_t *cpustate = device->token;
|
||||
cpustate->device = device;
|
||||
cpustate->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM);
|
||||
reset_i860(cpustate);
|
||||
i860_set_pin(cpustate, DEC_PIN_BUS_HOLD, 0);
|
||||
i860_set_pin(cpustate, DEC_PIN_RESET, 0);
|
||||
cpustate->single_stepping = 0;
|
||||
|
||||
state_save_register_device_item_array(device, 0, cpustate->iregs);
|
||||
state_save_register_device_item_array(device, 0, cpustate->cregs);
|
||||
state_save_register_device_item_array(device, 0, cpustate->frg);
|
||||
state_save_register_device_item(device, 0, cpustate->pc);
|
||||
}
|
||||
|
||||
static CPU_RESET( i860 )
|
||||
{
|
||||
logerror("i860 reset\n");
|
||||
i860_state_t *cpustate = device->token;
|
||||
reset_i860(cpustate);
|
||||
}
|
||||
|
||||
static CPU_EXECUTE( i860 )
|
||||
|
||||
/***************************************************************************
|
||||
* Disassembler hook
|
||||
***************************************************************************/
|
||||
|
||||
static CPU_DISASSEMBLE( i860 )
|
||||
{
|
||||
/* Just a disassembler ATM */
|
||||
return cycles;
|
||||
extern unsigned disasm_i860(char*, unsigned, UINT32);
|
||||
|
||||
/* Hard-coded little endian for now. */
|
||||
return disasm_i860(buffer, pc, (oprom[0] << 0) |
|
||||
(oprom[1] << 8) |
|
||||
(oprom[2] << 16) |
|
||||
(oprom[3] << 24));
|
||||
}
|
||||
|
||||
extern CPU_DISASSEMBLE( i860 );
|
||||
|
||||
/**************************************************************************
|
||||
* The actual decode and execute code.
|
||||
**************************************************************************/
|
||||
#include "i860dec.c"
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* Generic set_info/get_info
|
||||
**************************************************************************/
|
||||
|
||||
#define CPU_SET_INFO_F(fnum) cpustate->frg[0+(4*fnum)] = (info->i & 0x000000ff); \
|
||||
cpustate->frg[1+(4*fnum)] = (info->i & 0x0000ff00) >> 8; \
|
||||
cpustate->frg[2+(4*fnum)] = (info->i & 0x00ff0000) >> 16; \
|
||||
cpustate->frg[3+(4*fnum)] = (info->i & 0xff000000) >> 24;
|
||||
|
||||
static CPU_SET_INFO( i860 )
|
||||
{
|
||||
i860_state_t *i860 = device->token;
|
||||
i860_state_t *cpustate = device->token;
|
||||
|
||||
switch(state)
|
||||
{
|
||||
/* Interfacing */
|
||||
case CPUINFO_INT_PC:
|
||||
case CPUINFO_INT_REGISTER + I860_PC: i860->pc = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_PC: cpustate->pc = info->i & 0xffffffff; break;
|
||||
|
||||
case CPUINFO_INT_REGISTER + I860_FIR: cpustate->cregs[CR_FIR] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_PSR: cpustate->cregs[CR_PSR] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_DIRBASE: cpustate->cregs[CR_DIRBASE] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_DB: cpustate->cregs[CR_DB] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_FSR: cpustate->cregs[CR_FSR] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_EPSR: cpustate->cregs[CR_EPSR] = info->i & 0xffffffff; break;
|
||||
|
||||
case CPUINFO_INT_REGISTER + I860_R0: cpustate->iregs[0] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R1: cpustate->iregs[1] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R2: cpustate->iregs[2] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R3: cpustate->iregs[3] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R4: cpustate->iregs[4] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R5: cpustate->iregs[5] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R6: cpustate->iregs[6] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R7: cpustate->iregs[7] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R8: cpustate->iregs[8] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R9: cpustate->iregs[9] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R10: cpustate->iregs[10] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R11: cpustate->iregs[11] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R12: cpustate->iregs[12] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R13: cpustate->iregs[13] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R14: cpustate->iregs[14] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R15: cpustate->iregs[15] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R16: cpustate->iregs[16] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R17: cpustate->iregs[17] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R18: cpustate->iregs[18] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R19: cpustate->iregs[19] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R20: cpustate->iregs[20] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R21: cpustate->iregs[21] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R22: cpustate->iregs[22] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R23: cpustate->iregs[23] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R24: cpustate->iregs[24] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R25: cpustate->iregs[25] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R26: cpustate->iregs[26] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R27: cpustate->iregs[27] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R28: cpustate->iregs[28] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R29: cpustate->iregs[29] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R30: cpustate->iregs[30] = info->i & 0xffffffff; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R31: cpustate->iregs[31] = info->i & 0xffffffff; break;
|
||||
|
||||
case CPUINFO_INT_REGISTER + I860_F0: CPU_SET_INFO_F(0); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F1: CPU_SET_INFO_F(1); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F2: CPU_SET_INFO_F(2); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F3: CPU_SET_INFO_F(3); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F4: CPU_SET_INFO_F(4); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F5: CPU_SET_INFO_F(5); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F6: CPU_SET_INFO_F(6); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F7: CPU_SET_INFO_F(7); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F8: CPU_SET_INFO_F(8); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F9: CPU_SET_INFO_F(9); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F10: CPU_SET_INFO_F(10); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F11: CPU_SET_INFO_F(11); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F12: CPU_SET_INFO_F(12); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F13: CPU_SET_INFO_F(13); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F14: CPU_SET_INFO_F(14); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F15: CPU_SET_INFO_F(15); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F16: CPU_SET_INFO_F(16); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F17: CPU_SET_INFO_F(17); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F18: CPU_SET_INFO_F(18); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F19: CPU_SET_INFO_F(19); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F20: CPU_SET_INFO_F(20); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F21: CPU_SET_INFO_F(21); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F22: CPU_SET_INFO_F(22); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F23: CPU_SET_INFO_F(23); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F24: CPU_SET_INFO_F(24); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F25: CPU_SET_INFO_F(25); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F26: CPU_SET_INFO_F(26); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F27: CPU_SET_INFO_F(27); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F28: CPU_SET_INFO_F(28); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F29: CPU_SET_INFO_F(29); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F30: CPU_SET_INFO_F(30); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F31: CPU_SET_INFO_F(31); break;
|
||||
}
|
||||
}
|
||||
|
||||
#define CPU_GET_INFO_INT_F(fnum) (info->i = cpustate->frg[0+(4*fnum)] | \
|
||||
cpustate->frg[1+(4*fnum)] << 8 | \
|
||||
cpustate->frg[2+(4*fnum)] << 16 | \
|
||||
cpustate->frg[3+(4*fnum)] << 24)
|
||||
|
||||
#define CPU_GET_INFO_STR_F(fnum) (sprintf(info->s, "F%d : %08x", fnum, cpustate->frg[0+(4*fnum)] | \
|
||||
cpustate->frg[1+(4*fnum)] << 8 | \
|
||||
cpustate->frg[2+(4*fnum)] << 16 | \
|
||||
cpustate->frg[3+(4*fnum)] << 24))
|
||||
|
||||
CPU_GET_INFO( i860 )
|
||||
{
|
||||
i860_state_t *i860 = (device != NULL) ? device->token : NULL;
|
||||
i860_state_t *cpustate = (device != NULL) ? device->token : NULL;
|
||||
|
||||
switch (state)
|
||||
{
|
||||
// --- the following bits of info are returned as 64-bit signed integers ---
|
||||
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(i860_state_t); break;
|
||||
case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
|
||||
case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0x00000000; break;
|
||||
case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; 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 = 4; break;
|
||||
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
|
||||
case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
|
||||
case CPUINFO_INT_MAX_CYCLES: info->i = 8; break;
|
||||
/* --- the following bits of info are returned as 64-bit signed integers --- */
|
||||
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(i860_state_t); break;
|
||||
case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
|
||||
case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0x00000000; break;
|
||||
case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; 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 = 4; break;
|
||||
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
|
||||
case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
|
||||
case CPUINFO_INT_MAX_CYCLES: info->i = 8; break;
|
||||
|
||||
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; 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_DATABUS_WIDTH_PROGRAM: info->i = 64; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH_PROGRAM: info->i = 32; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT_PROGRAM: info->i = 0; break;
|
||||
case CPUINFO_INT_DATABUS_WIDTH_DATA: info->i = 0; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH_DATA: info->i = 0; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT_DATA: info->i = 0; break;
|
||||
case CPUINFO_INT_DATABUS_WIDTH_IO: info->i = 0; break;
|
||||
case CPUINFO_INT_ADDRBUS_WIDTH_IO: info->i = 0; break;
|
||||
case CPUINFO_INT_ADDRBUS_SHIFT_IO: info->i = 0; break;
|
||||
|
||||
// --- the following bits of info are returned as pointers to data or functions ---
|
||||
case CPUINFO_INT_PC:
|
||||
case CPUINFO_INT_REGISTER + I860_PC: info->i = cpustate->pc; break;
|
||||
case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->ppc; break;
|
||||
|
||||
case CPUINFO_INT_REGISTER + I860_FIR: info->i = cpustate->cregs[CR_FIR]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_PSR: info->i = cpustate->cregs[CR_PSR]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_DIRBASE: info->i = cpustate->cregs[CR_DIRBASE]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_DB: info->i = cpustate->cregs[CR_DB]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_FSR: info->i = cpustate->cregs[CR_FSR]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_EPSR: info->i = cpustate->cregs[CR_EPSR]; break;
|
||||
|
||||
case CPUINFO_INT_REGISTER + I860_R0: info->i = cpustate->iregs[0]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R1: info->i = cpustate->iregs[1]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R2: info->i = cpustate->iregs[2]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R3: info->i = cpustate->iregs[3]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R4: info->i = cpustate->iregs[4]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R5: info->i = cpustate->iregs[5]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R6: info->i = cpustate->iregs[6]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R7: info->i = cpustate->iregs[7]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R8: info->i = cpustate->iregs[8]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R9: info->i = cpustate->iregs[9]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R10: info->i = cpustate->iregs[10]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R11: info->i = cpustate->iregs[11]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R12: info->i = cpustate->iregs[12]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R13: info->i = cpustate->iregs[13]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R14: info->i = cpustate->iregs[14]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R15: info->i = cpustate->iregs[15]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R16: info->i = cpustate->iregs[16]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R17: info->i = cpustate->iregs[17]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R18: info->i = cpustate->iregs[18]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R19: info->i = cpustate->iregs[19]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R20: info->i = cpustate->iregs[20]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R21: info->i = cpustate->iregs[21]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R22: info->i = cpustate->iregs[22]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R23: info->i = cpustate->iregs[23]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R24: info->i = cpustate->iregs[24]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R25: info->i = cpustate->iregs[25]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R26: info->i = cpustate->iregs[26]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R27: info->i = cpustate->iregs[27]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R28: info->i = cpustate->iregs[28]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R29: info->i = cpustate->iregs[29]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R30: info->i = cpustate->iregs[30]; break;
|
||||
case CPUINFO_INT_REGISTER + I860_R31: info->i = cpustate->iregs[31]; break;
|
||||
|
||||
case CPUINFO_INT_REGISTER + I860_F0: CPU_GET_INFO_INT_F(0); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F1: CPU_GET_INFO_INT_F(1); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F2: CPU_GET_INFO_INT_F(2); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F3: CPU_GET_INFO_INT_F(3); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F4: CPU_GET_INFO_INT_F(4); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F5: CPU_GET_INFO_INT_F(5); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F6: CPU_GET_INFO_INT_F(6); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F7: CPU_GET_INFO_INT_F(7); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F8: CPU_GET_INFO_INT_F(8); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F9: CPU_GET_INFO_INT_F(9); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F10: CPU_GET_INFO_INT_F(10); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F11: CPU_GET_INFO_INT_F(11); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F12: CPU_GET_INFO_INT_F(12); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F13: CPU_GET_INFO_INT_F(13); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F14: CPU_GET_INFO_INT_F(14); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F15: CPU_GET_INFO_INT_F(15); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F16: CPU_GET_INFO_INT_F(16); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F17: CPU_GET_INFO_INT_F(17); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F18: CPU_GET_INFO_INT_F(18); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F19: CPU_GET_INFO_INT_F(19); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F20: CPU_GET_INFO_INT_F(20); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F21: CPU_GET_INFO_INT_F(21); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F22: CPU_GET_INFO_INT_F(22); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F23: CPU_GET_INFO_INT_F(23); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F24: CPU_GET_INFO_INT_F(24); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F25: CPU_GET_INFO_INT_F(25); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F26: CPU_GET_INFO_INT_F(26); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F27: CPU_GET_INFO_INT_F(27); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F28: CPU_GET_INFO_INT_F(28); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F29: CPU_GET_INFO_INT_F(29); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F30: CPU_GET_INFO_INT_F(30); break;
|
||||
case CPUINFO_INT_REGISTER + I860_F31: CPU_GET_INFO_INT_F(31); 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(i860); break;
|
||||
case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i860); break;
|
||||
case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(i860); break;
|
||||
@ -98,16 +292,90 @@ CPU_GET_INFO( i860 )
|
||||
case CPUINFO_FCT_READ: info->read = NULL; break;
|
||||
case CPUINFO_FCT_WRITE: info->write = NULL; break;
|
||||
case CPUINFO_FCT_READOP: info->readop = NULL; break;
|
||||
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &i860->icount; 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, "i860"); break;
|
||||
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Intel"); break;
|
||||
/* --- the following bits of info are returned as NULL-terminated strings --- */
|
||||
case CPUINFO_STR_NAME: strcpy(info->s, "i860XR"); break;
|
||||
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Intel i860"); break;
|
||||
case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "0.1"); break;
|
||||
case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
|
||||
case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Jason Eckhardt and Andrew Gardner"); break;
|
||||
case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Jason Eckhardt"); break;
|
||||
|
||||
case CPUINFO_INT_PC: info->i = i860->pc; break;
|
||||
case CPUINFO_INT_PREVIOUSPC: info->i = i860->ppc; break;
|
||||
case CPUINFO_STR_FLAGS:
|
||||
strcpy(info->s, ""); break;
|
||||
|
||||
case CPUINFO_STR_REGISTER + I860_PC: sprintf(info->s, "PC : %08x", cpustate->pc); break;
|
||||
case CPUINFO_STR_REGISTER + I860_FIR: sprintf(info->s, "FIR : %08x", cpustate->cregs[CR_FIR]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_PSR: sprintf(info->s, "PSR : %08x", cpustate->cregs[CR_PSR]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_DIRBASE: sprintf(info->s, "DIRBASE : %08x", cpustate->cregs[CR_DIRBASE]);break;
|
||||
case CPUINFO_STR_REGISTER + I860_DB: sprintf(info->s, "DB : %08x", cpustate->cregs[CR_DB]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_FSR: sprintf(info->s, "FSR : %08x", cpustate->cregs[CR_FSR]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_EPSR: sprintf(info->s, "EPSR : %08x", cpustate->cregs[CR_EPSR]); break;
|
||||
|
||||
case CPUINFO_STR_REGISTER + I860_R0: sprintf(info->s, "R0 : %08x", cpustate->iregs[0]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R1: sprintf(info->s, "R1 : %08x", cpustate->iregs[1]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R2: sprintf(info->s, "R2 : %08x", cpustate->iregs[2]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R3: sprintf(info->s, "R3 : %08x", cpustate->iregs[3]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R4: sprintf(info->s, "R4 : %08x", cpustate->iregs[4]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R5: sprintf(info->s, "R5 : %08x", cpustate->iregs[5]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R6: sprintf(info->s, "R6 : %08x", cpustate->iregs[6]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R7: sprintf(info->s, "R7 : %08x", cpustate->iregs[7]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R8: sprintf(info->s, "R8 : %08x", cpustate->iregs[8]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R9: sprintf(info->s, "R9 : %08x", cpustate->iregs[9]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R10: sprintf(info->s, "R10 : %08x", cpustate->iregs[10]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R11: sprintf(info->s, "R11 : %08x", cpustate->iregs[11]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R12: sprintf(info->s, "R12 : %08x", cpustate->iregs[12]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R13: sprintf(info->s, "R13 : %08x", cpustate->iregs[13]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R14: sprintf(info->s, "R14 : %08x", cpustate->iregs[14]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R15: sprintf(info->s, "R15 : %08x", cpustate->iregs[15]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R16: sprintf(info->s, "R16 : %08x", cpustate->iregs[16]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R17: sprintf(info->s, "R17 : %08x", cpustate->iregs[17]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R18: sprintf(info->s, "R18 : %08x", cpustate->iregs[18]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R19: sprintf(info->s, "R19 : %08x", cpustate->iregs[19]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R20: sprintf(info->s, "R20 : %08x", cpustate->iregs[20]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R21: sprintf(info->s, "R21 : %08x", cpustate->iregs[21]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R22: sprintf(info->s, "R22 : %08x", cpustate->iregs[22]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R23: sprintf(info->s, "R23 : %08x", cpustate->iregs[23]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R24: sprintf(info->s, "R24 : %08x", cpustate->iregs[24]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R25: sprintf(info->s, "R25 : %08x", cpustate->iregs[25]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R26: sprintf(info->s, "R26 : %08x", cpustate->iregs[26]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R27: sprintf(info->s, "R27 : %08x", cpustate->iregs[27]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R28: sprintf(info->s, "R28 : %08x", cpustate->iregs[28]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R29: sprintf(info->s, "R29 : %08x", cpustate->iregs[29]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R30: sprintf(info->s, "R30 : %08x", cpustate->iregs[30]); break;
|
||||
case CPUINFO_STR_REGISTER + I860_R31: sprintf(info->s, "R31 : %08x", cpustate->iregs[31]); break;
|
||||
|
||||
case CPUINFO_STR_REGISTER + I860_F0: CPU_GET_INFO_STR_F(0); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F1: CPU_GET_INFO_STR_F(1); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F2: CPU_GET_INFO_STR_F(2); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F3: CPU_GET_INFO_STR_F(3); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F4: CPU_GET_INFO_STR_F(4); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F5: CPU_GET_INFO_STR_F(5); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F6: CPU_GET_INFO_STR_F(6); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F7: CPU_GET_INFO_STR_F(7); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F8: CPU_GET_INFO_STR_F(8); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F9: CPU_GET_INFO_STR_F(9); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F10: CPU_GET_INFO_STR_F(10); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F11: CPU_GET_INFO_STR_F(11); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F12: CPU_GET_INFO_STR_F(12); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F13: CPU_GET_INFO_STR_F(13); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F14: CPU_GET_INFO_STR_F(14); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F15: CPU_GET_INFO_STR_F(15); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F16: CPU_GET_INFO_STR_F(16); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F17: CPU_GET_INFO_STR_F(17); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F18: CPU_GET_INFO_STR_F(18); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F19: CPU_GET_INFO_STR_F(19); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F20: CPU_GET_INFO_STR_F(20); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F21: CPU_GET_INFO_STR_F(21); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F22: CPU_GET_INFO_STR_F(22); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F23: CPU_GET_INFO_STR_F(23); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F24: CPU_GET_INFO_STR_F(24); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F25: CPU_GET_INFO_STR_F(25); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F26: CPU_GET_INFO_STR_F(26); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F27: CPU_GET_INFO_STR_F(27); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F28: CPU_GET_INFO_STR_F(28); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F29: CPU_GET_INFO_STR_F(29); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F30: CPU_GET_INFO_STR_F(30); break;
|
||||
case CPUINFO_STR_REGISTER + I860_F31: CPU_GET_INFO_STR_F(31); break;
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,18 @@
|
||||
/***************************************************************************
|
||||
|
||||
i860.h
|
||||
|
||||
Interface file for the Intel i860 emulator.
|
||||
|
||||
Copyright (C) 1995-present Jason Eckhardt (jle@rice.edu)
|
||||
Released for general non-commercial use under the MAME license
|
||||
with the additional requirement that you are free to use and
|
||||
redistribute this code in modified or unmodified form, provided
|
||||
you list me in the credits.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef __I860_H__
|
||||
@ -5,13 +20,199 @@
|
||||
|
||||
#include "cpuintrf.h"
|
||||
|
||||
/***************************************************************************
|
||||
REGISTER ENUMERATION
|
||||
***************************************************************************/
|
||||
|
||||
enum
|
||||
{
|
||||
I860_PC = 0
|
||||
I860_PC = 1,
|
||||
|
||||
I860_FIR,
|
||||
I860_PSR,
|
||||
I860_DIRBASE,
|
||||
I860_DB,
|
||||
I860_FSR,
|
||||
I860_EPSR,
|
||||
|
||||
I860_R0, I860_R1, I860_R2, I860_R3, I860_R4, I860_R5, I860_R6, I860_R7, I860_R8, I860_R9,
|
||||
I860_R10, I860_R11, I860_R12, I860_R13, I860_R14, I860_R15, I860_R16, I860_R17, I860_R18, I860_R19,
|
||||
I860_R20, I860_R21, I860_R22, I860_R23, I860_R24, I860_R25, I860_R26, I860_R27, I860_R28, I860_R29,
|
||||
I860_R30, I860_R31,
|
||||
|
||||
I860_F0, I860_F1, I860_F2, I860_F3, I860_F4, I860_F5, I860_F6, I860_F7, I860_F8, I860_F9,
|
||||
I860_F10, I860_F11, I860_F12, I860_F13, I860_F14, I860_F15, I860_F16, I860_F17, I860_F18, I860_F19,
|
||||
I860_F20, I860_F21, I860_F22, I860_F23, I860_F24, I860_F25, I860_F26, I860_F27, I860_F28, I860_F29,
|
||||
I860_F30, I860_F31,
|
||||
|
||||
};
|
||||
|
||||
/* Needed for MAME */
|
||||
CPU_GET_INFO( i860 );
|
||||
#define CPU_I860 CPU_GET_INFO_NAME( i860 )
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
STRUCTURES & TYPEDEFS
|
||||
***************************************************************************/
|
||||
|
||||
/* i860 state. */
|
||||
typedef struct {
|
||||
/* Integer registers (32 x 32-bits). */
|
||||
UINT32 iregs[32];
|
||||
|
||||
/* Floating point registers (32 x 32-bits, 16 x 64 bits, or 8 x 128 bits).
|
||||
When referenced as pairs or quads, the higher numbered registers
|
||||
are the upper bits. E.g., double precision f0 is f1:f0. */
|
||||
UINT8 frg[32 * 4];
|
||||
|
||||
/* Control registers (6 x 32-bits). */
|
||||
UINT32 cregs[6];
|
||||
|
||||
/* Program counter (1 x 32-bits). Reset starts at pc=0xffffff00. */
|
||||
UINT32 pc;
|
||||
|
||||
/* Special registers (4 x 64-bits). */
|
||||
union
|
||||
{
|
||||
float s;
|
||||
double d;
|
||||
} KR, KI, T;
|
||||
UINT64 merge;
|
||||
|
||||
/* The adder pipeline, always 3 stages. */
|
||||
struct
|
||||
{
|
||||
/* The stage contents. */
|
||||
union {
|
||||
float s;
|
||||
double d;
|
||||
} val;
|
||||
|
||||
/* The stage status bits. */
|
||||
struct {
|
||||
/* Adder result precision (1 = dbl, 0 = sgl). */
|
||||
char arp;
|
||||
} stat;
|
||||
} A[3];
|
||||
|
||||
/* The multiplier pipeline. 3 stages for single precision, 2 stages
|
||||
for double precision, and confusing for mixed precision. */
|
||||
struct {
|
||||
/* The stage contents. */
|
||||
union {
|
||||
float s;
|
||||
double d;
|
||||
} val;
|
||||
|
||||
/* The stage status bits. */
|
||||
struct {
|
||||
/* Multiplier result precision (1 = dbl, 0 = sgl). */
|
||||
char mrp;
|
||||
} stat;
|
||||
} M[3];
|
||||
|
||||
/* The load pipeline, always 3 stages. */
|
||||
struct {
|
||||
/* The stage contents. */
|
||||
union {
|
||||
float s;
|
||||
double d;
|
||||
} val;
|
||||
|
||||
/* The stage status bits. */
|
||||
struct {
|
||||
/* Load result precision (1 = dbl, 0 = sgl). */
|
||||
char lrp;
|
||||
} stat;
|
||||
} L[3];
|
||||
|
||||
/* The graphics/integer pipeline, always 1 stage. */
|
||||
struct {
|
||||
/* The stage contents. */
|
||||
union {
|
||||
float s;
|
||||
double d;
|
||||
} val;
|
||||
|
||||
/* The stage status bits. */
|
||||
struct {
|
||||
/* Integer/graphics result precision (1 = dbl, 0 = sgl). */
|
||||
char irp;
|
||||
} stat;
|
||||
} G;
|
||||
|
||||
/* Pins. */
|
||||
int pin_bus_hold;
|
||||
int pin_reset;
|
||||
|
||||
/*
|
||||
* Other emulator state.
|
||||
*/
|
||||
int exiting_readmem;
|
||||
int exiting_ifetch;
|
||||
|
||||
/* Indicate a control-flow instruction, so we know the PC is updated. */
|
||||
int pc_updated;
|
||||
|
||||
/* Indicate an instruction just generated a trap, so we know the PC
|
||||
needs to go to the trap address. */
|
||||
int pending_trap;
|
||||
|
||||
/* This is 1 if the next fir load gets the trap address, otherwise
|
||||
it is 0 to get the ld.c address. This is set to 1 only when a
|
||||
non-reset trap occurs. */
|
||||
int fir_gets_trap_addr;
|
||||
|
||||
/* Single stepping flag for internal use. */
|
||||
int single_stepping;
|
||||
|
||||
/*
|
||||
* MAME-specific stuff.
|
||||
*/
|
||||
const device_config *device;
|
||||
const address_space *program;
|
||||
UINT32 ppc;
|
||||
int icount;
|
||||
|
||||
} i860_state_t;
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
PUBLIC FUNCTIONS
|
||||
***************************************************************************/
|
||||
|
||||
/* This is the external interface for asserting an external interrupt
|
||||
to the i860. */
|
||||
extern void i860_gen_interrupt(i860_state_t*);
|
||||
|
||||
/* This is the external interface for asserting/deasserting a pin on
|
||||
the i860. */
|
||||
extern void i860_set_pin(i860_state_t*, int, int);
|
||||
|
||||
/* Hard or soft reset. */
|
||||
extern void reset_i860(i860_state_t*);
|
||||
|
||||
/* i860 pins. */
|
||||
enum {
|
||||
DEC_PIN_BUS_HOLD, /* Bus HOLD pin. */
|
||||
DEC_PIN_RESET /* System reset pin. */
|
||||
};
|
||||
|
||||
|
||||
/* TODO: THESE WILL BE REPLACED BY MAME FUNCTIONS
|
||||
#define BYTE_REV32(t) \
|
||||
do { \
|
||||
(t) = ((UINT32)(t) >> 16) | ((UINT32)(t) << 16); \
|
||||
(t) = (((UINT32)(t) >> 8) & 0x00ff00ff) | (((UINT32)(t) << 8) & 0xff00ff00); \
|
||||
} while (0);
|
||||
|
||||
#define BYTE_REV16(t) \
|
||||
do { \
|
||||
(t) = (((UINT16)(t) >> 8) & 0x00ff) | (((UINT16)(t) << 8) & 0xff00); \
|
||||
} while (0);
|
||||
#endif
|
||||
*/
|
||||
|
||||
#endif /* __I860_H__ */
|
||||
|
||||
|
4722
src/emu/cpu/i860/i860dec.c
Normal file
4722
src/emu/cpu/i860/i860dec.c
Normal file
File diff suppressed because it is too large
Load Diff
694
src/emu/cpu/i860/i860dis.c
Normal file
694
src/emu/cpu/i860/i860dis.c
Normal file
@ -0,0 +1,694 @@
|
||||
/***************************************************************************
|
||||
|
||||
i860dis.c
|
||||
|
||||
Disassembler for the Intel i860 emulator.
|
||||
|
||||
Copyright (C) 1995-present Jason Eckhardt (jle@rice.edu)
|
||||
Released for general non-commercial use under the MAME license
|
||||
with the additional requirement that you are free to use and
|
||||
redistribute this code in modified or unmodified form, provided
|
||||
you list me in the credits.
|
||||
Visit http://mamedev.org for licensing and usage restrictions.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "i860.h"
|
||||
#include <string.h>
|
||||
|
||||
/* Macros for accessing register fields in instruction word. */
|
||||
#define get_isrc1(bits) (((bits) >> 11) & 0x1f)
|
||||
#define get_isrc2(bits) (((bits) >> 21) & 0x1f)
|
||||
#define get_idest(bits) (((bits) >> 16) & 0x1f)
|
||||
#define get_fsrc1(bits) (((bits) >> 11) & 0x1f)
|
||||
#define get_fsrc2(bits) (((bits) >> 21) & 0x1f)
|
||||
#define get_fdest(bits) (((bits) >> 16) & 0x1f)
|
||||
#define get_creg(bits) (((bits) >> 21) & 0x7)
|
||||
|
||||
/* Macros for accessing immediate fields. */
|
||||
/* 16-bit immediate. */
|
||||
#define get_imm16(insn) ((insn) & 0xffff)
|
||||
|
||||
|
||||
/* Control register names. */
|
||||
static const char *const cr2str[] =
|
||||
{"fir", "psr", "dirbase", "db", "fsr", "epsr", "!", "!"};
|
||||
|
||||
|
||||
/* Sign extend N-bit number. */
|
||||
static INT32 sign_ext(UINT32 x, int n)
|
||||
{
|
||||
INT32 t;
|
||||
t = x >> (n - 1);
|
||||
t = ((-t) << n) | x;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
/* Basic integer 3-address register format:
|
||||
* mnemonic %rs1,%rs2,%rd */
|
||||
static void int_12d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
/* Possibly prefix shrd with 'd.' */
|
||||
if (((insn & 0xfc000000) == 0xb0000000) && (insn & 0x200))
|
||||
sprintf(buf, "d.%s\t%%r%d,%%r%d,%%r%d", mnemonic,
|
||||
get_isrc1 (insn), get_isrc2 (insn), get_idest (insn));
|
||||
else
|
||||
sprintf(buf, "%s\t%%r%d,%%r%d,%%r%d", mnemonic,
|
||||
get_isrc1 (insn), get_isrc2 (insn), get_idest (insn));
|
||||
}
|
||||
|
||||
|
||||
/* Basic integer 3-address imm16 format:
|
||||
* mnemonic #imm16,%rs2,%rd */
|
||||
static void int_i2d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
/* Sign extend the 16-bit immediate.
|
||||
Print as hex for the bitwise operations. */
|
||||
int upper_6bits = (insn >> 26) & 0x3f;
|
||||
if (upper_6bits >= 0x30 && upper_6bits <= 0x3f)
|
||||
sprintf(buf, "%s\t0x%04x,%%r%d,%%r%d", mnemonic,
|
||||
(UINT32)(get_imm16 (insn)), get_isrc2 (insn), get_idest (insn));
|
||||
else
|
||||
sprintf(buf, "%s\t%d,%%r%d,%%r%d", mnemonic,
|
||||
sign_ext(get_imm16 (insn), 16), get_isrc2 (insn), get_idest (insn));
|
||||
}
|
||||
|
||||
|
||||
/* Integer (mixed) 2-address isrc1ni,fdest. */
|
||||
static void int_1d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
sprintf(buf, "%s\t%%r%d,%%f%d", mnemonic, get_isrc1 (insn), get_fdest (insn));
|
||||
}
|
||||
|
||||
|
||||
/* Integer (mixed) 2-address csrc2,idest. */
|
||||
static void int_cd(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
sprintf(buf, "%s\t%%%s,%%r%d", mnemonic, cr2str[get_creg (insn)], get_idest (insn));
|
||||
}
|
||||
|
||||
|
||||
/* Integer (mixed) 2-address isrc1,csrc2. */
|
||||
static void int_1c(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
sprintf(buf, "%s\t%%r%d,%%%s", mnemonic, get_isrc1(insn), cr2str[get_creg (insn)]);
|
||||
}
|
||||
|
||||
|
||||
/* Integer 1-address register format:
|
||||
* mnemonic %rs1 */
|
||||
static void int_1(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
sprintf(buf, "%s\t%%r%d", mnemonic, get_isrc1 (insn));
|
||||
}
|
||||
|
||||
|
||||
/* Integer no-address register format:
|
||||
* mnemonic */
|
||||
static void int_0(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
sprintf(buf, "%s", mnemonic);
|
||||
}
|
||||
|
||||
|
||||
/* Basic floating-point 3-address register format:
|
||||
* mnemonic %fs1,%fs2,%fd */
|
||||
static void flop_12d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
const char *suffix[4] = { "ss", "sd", "ds", "dd" };
|
||||
const char *prefix_d, *prefix_p;
|
||||
int s = (insn & 0x180) >> 7;
|
||||
prefix_p = (insn & 0x400) ? "p" : "";
|
||||
prefix_d = (insn & 0x200) ? "d." : "";
|
||||
|
||||
/* Special case: pf[m]am and pf[m]sm families are always pipelined, so they
|
||||
do not have a prefix. Also, for the pfmam and pfmsm families, replace
|
||||
any 'a' in the mnemonic with 'm' and prepend an 'm'. */
|
||||
if ((insn & 0x7f) < 0x20)
|
||||
{
|
||||
int is_pfam = insn & 0x400;
|
||||
if (!is_pfam)
|
||||
{
|
||||
char newname[256];
|
||||
char *op = mnemonic;
|
||||
char *np = newname + 1;
|
||||
newname[0] = 'm';
|
||||
while (*op)
|
||||
{
|
||||
if (*op == 'a')
|
||||
*np = 'm';
|
||||
else
|
||||
*np = *op;
|
||||
np++;
|
||||
op++;
|
||||
}
|
||||
*np = 0;
|
||||
mnemonic = newname;
|
||||
}
|
||||
prefix_p = "";
|
||||
}
|
||||
|
||||
/* Special case: pfgt/pfle-- R-bit distinguishes the two. */
|
||||
if ((insn & 0x7f) == 0x34)
|
||||
{
|
||||
const char *mn[2] = { "fgt.", "fle." };
|
||||
int r = (insn & 0x080) >> 7;
|
||||
int s = (insn & 0x100) ? 3 : 0;
|
||||
sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d,%%f%d", prefix_d, prefix_p, mn[r],
|
||||
suffix[s], get_fsrc1 (insn), get_fsrc2 (insn), get_fdest (insn));
|
||||
}
|
||||
else
|
||||
sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d,%%f%d", prefix_d, prefix_p, mnemonic,
|
||||
suffix[s], get_fsrc1 (insn), get_fsrc2 (insn), get_fdest (insn));
|
||||
}
|
||||
|
||||
|
||||
/* Floating-point 2-address register format:
|
||||
* mnemonic %fs1,%fd */
|
||||
static void flop_1d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
const char *suffix[4] = { "ss", "sd", "ds", "dd" };
|
||||
const char *prefix_d, *prefix_p;
|
||||
int s = (insn & 0x180) >> 7;
|
||||
prefix_p = (insn & 0x400) ? "p" : "";
|
||||
prefix_d = (insn & 0x200) ? "d." : "";
|
||||
sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d", prefix_d, prefix_p, mnemonic,
|
||||
suffix[s], get_fsrc1 (insn), get_fdest (insn));
|
||||
}
|
||||
|
||||
|
||||
/* Floating-point 2-address register format:
|
||||
* mnemonic %fs2,%fd */
|
||||
static void flop_2d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
const char *suffix[4] = { "ss", "sd", "ds", "dd" };
|
||||
const char *prefix_d;
|
||||
int s = (insn & 0x180) >> 7;
|
||||
prefix_d = (insn & 0x200) ? "d." : "";
|
||||
sprintf(buf, "%s%s%s\t%%f%d,%%f%d", prefix_d, mnemonic, suffix[s],
|
||||
get_fsrc2 (insn), get_fdest (insn));
|
||||
}
|
||||
|
||||
|
||||
/* Floating-point (mixed) 2-address register format:
|
||||
* fxfr fsrc1,idest. */
|
||||
static void flop_fxfr(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
const char *prefix_d = (insn & 0x200) ? "d." : "";
|
||||
sprintf(buf, "%s%s\t%%f%d,%%r%d", prefix_d, mnemonic, get_fsrc1 (insn),
|
||||
get_idest (insn));
|
||||
}
|
||||
|
||||
|
||||
/* Branch with reg,reg,sbroff format:
|
||||
* mnemonic %rs1,%rs2,sbroff */
|
||||
static void int_12S(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
INT32 sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
|
||||
INT32 rel = (INT32)pc + (sbroff << 2) + 4;
|
||||
|
||||
sprintf(buf, "%s\t%%r%d,%%r%d,0x%08x", mnemonic, get_isrc1 (insn),
|
||||
get_isrc2 (insn), (UINT32)rel);
|
||||
}
|
||||
|
||||
|
||||
/* Branch with #const5,reg,sbroff format:
|
||||
* mnemonic #const5,%rs2,sbroff */
|
||||
static void int_i2S(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
INT32 sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
|
||||
INT32 rel = (INT32)pc + (sbroff << 2) + 4;
|
||||
|
||||
sprintf(buf, "%s\t%d,%%r%d,0x%08x", mnemonic, ((insn >> 11) & 0x1f),
|
||||
get_isrc2 (insn), (UINT32)rel);
|
||||
}
|
||||
|
||||
|
||||
/* Branch with lbroff format:
|
||||
* mnemonic lbroff */
|
||||
static void int_L(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
INT32 lbroff = sign_ext ((insn & 0x03ffffff), 26);
|
||||
INT32 rel = (INT32)pc + (lbroff << 2) + 4;
|
||||
|
||||
sprintf(buf, "%s\t0x%08x", mnemonic, (UINT32)rel);
|
||||
}
|
||||
|
||||
|
||||
/* Integer load.
|
||||
* ld.{b,s,l} isrc1(isrc2),idest
|
||||
* ld.{b,s,l} #const(isrc2),idest */
|
||||
static void int_ldx(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
/* Operand size, in bytes. */
|
||||
int sizes[4] = { 1, 1, 2, 4 };
|
||||
const char *suffix[4] = { "b", "b", "s", "l" };
|
||||
UINT32 idx = 0;
|
||||
|
||||
/* Bits 28 and 0 determine the operand size. */
|
||||
idx = ((insn >> 27) & 2) | (insn & 1);
|
||||
|
||||
/* Bit 26 determines the addressing mode (reg+reg or disp+reg). */
|
||||
if (insn & 0x04000000)
|
||||
{
|
||||
/* Chop off lower bits of displacement. */
|
||||
INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
|
||||
int size = sizes[idx];
|
||||
immsrc1 &= ~(size - 1);
|
||||
sprintf(buf, "%s%s\t%d(%%r%d),%%r%d", mnemonic, suffix[idx],
|
||||
immsrc1, get_isrc2 (insn), get_idest (insn));
|
||||
}
|
||||
else
|
||||
sprintf(buf, "%s%s\t%%r%d(%%r%d),%%r%d", mnemonic, suffix[idx],
|
||||
get_isrc1 (insn), get_isrc2 (insn), get_idest (insn));
|
||||
}
|
||||
|
||||
|
||||
/* Integer store: st.b isrc1ni,#const(isrc2) */
|
||||
static void int_stx(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
/* Operand size, in bytes. */
|
||||
int sizes[4] = { 1, 1, 2, 4 };
|
||||
const char *suffix[4] = { "b", "b", "s", "l" };
|
||||
int idx = 0;
|
||||
int size;
|
||||
INT32 immsrc = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
|
||||
|
||||
/* Bits 28 and 0 determine the operand size. */
|
||||
idx = ((insn >> 27) & 2) | (insn & 1);
|
||||
|
||||
/* Chop off lower bits of displacement. */
|
||||
size = sizes[idx];
|
||||
immsrc &= ~(size - 1);
|
||||
sprintf(buf, "%s%s\t%%r%d,%d(%%r%d)", mnemonic, suffix[idx],
|
||||
get_isrc1 (insn), immsrc, get_isrc2 (insn));
|
||||
}
|
||||
|
||||
|
||||
/* Disassemble:
|
||||
* "[p]fld.y isrc1(isrc2),fdest", "[p]fld.y isrc1(isrc2)++,idest",
|
||||
* "[p]fld.y #const(isrc2),fdest" or "[p]fld.y #const(isrc2)++,idest".
|
||||
* "fst.y fdest,isrc1(isrc2)", "fst.y fdest,isrc1(isrc2)++",
|
||||
* "fst.y fdest,#const(isrc2)" or "fst.y fdest,#const(isrc2)++"
|
||||
* Where y = {l,d,q}. Note, there is no pfld.q, though. */
|
||||
static void int_fldst(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
|
||||
/* Operand size, in bytes. */
|
||||
int sizes[4] = { 8, 4, 16, 4 };
|
||||
const char *suffix[4] = { "d", "l", "q", "l" };
|
||||
int idx = 0;
|
||||
int size = 0;
|
||||
int auto_inc = (insn & 1);
|
||||
const char *auto_suff[2] = { "", "++" };
|
||||
int piped = (insn & 0x40000000) >> 29;
|
||||
const char *piped_suff[2] = { "", "p" };
|
||||
int upper_6bits = (insn >> 26) & 0x3f;
|
||||
int is_load = (upper_6bits == 8 || upper_6bits == 9 || upper_6bits == 24
|
||||
|| upper_6bits == 25);
|
||||
|
||||
/* Bits 2 and 1 determine the operand size. */
|
||||
idx = ((insn >> 1) & 3);
|
||||
size = sizes[idx];
|
||||
|
||||
/* There is no pipelined load quad on XR. */
|
||||
if (piped && size == 16)
|
||||
{
|
||||
sprintf (buf, ".long\t%#08x; *", insn);
|
||||
return;
|
||||
}
|
||||
|
||||
/* There is only a 64-bit pixel store. */
|
||||
if ((upper_6bits == 15) && size != 8)
|
||||
{
|
||||
sprintf (buf, ".long\t%#08x", insn);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Bit 26 determines the addressing mode (reg+reg or disp+reg). */
|
||||
if (insn & 0x04000000)
|
||||
{
|
||||
/* Chop off lower bits of displacement. */
|
||||
immsrc1 &= ~(size - 1);
|
||||
if (is_load)
|
||||
sprintf(buf, "%s%s%s\t%d(%%r%d)%s,%%f%d", piped_suff[piped], mnemonic,
|
||||
suffix[idx], immsrc1, get_isrc2 (insn), auto_suff[auto_inc],
|
||||
get_fdest (insn));
|
||||
else
|
||||
sprintf(buf, "%s%s\t%%f%d,%d(%%r%d)%s", mnemonic, suffix[idx],
|
||||
get_fdest (insn), immsrc1, get_isrc2 (insn), auto_suff[auto_inc]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_load)
|
||||
sprintf(buf, "%s%s%s\t%%r%d(%%r%d)%s,%%f%d", piped_suff[piped],
|
||||
mnemonic, suffix[idx], get_isrc1 (insn), get_isrc2 (insn),
|
||||
auto_suff[auto_inc], get_fdest (insn));
|
||||
else
|
||||
sprintf(buf, "%s%s\t%%f%d,%%r%d(%%r%d)%s", mnemonic, suffix[idx],
|
||||
get_fdest (insn), get_isrc1 (insn), get_isrc2 (insn),
|
||||
auto_suff[auto_inc]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* flush #const(isrc2)[++]. */
|
||||
static void int_flush(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
|
||||
{
|
||||
const char *auto_suff[2] = { "", "++" };
|
||||
INT32 immsrc = sign_ext (get_imm16 (insn), 16);
|
||||
immsrc &= ~(16-1);
|
||||
sprintf(buf, "%s\t%d(%%r%d)%s", mnemonic, immsrc, get_isrc2 (insn),
|
||||
auto_suff[(insn & 1)]);
|
||||
}
|
||||
|
||||
|
||||
/* Flags for the decode table. */
|
||||
enum
|
||||
{
|
||||
DEC_MORE = 1, /* More decoding necessary. */
|
||||
DEC_DECODED = 2 /* Fully decoded, go. */
|
||||
};
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* Disassembly function for this opcode.
|
||||
Call with buffer, mnemonic, pc, insn. */
|
||||
void (*insn_dis)(char *, char *, UINT32, UINT32);
|
||||
|
||||
/* Flags for this opcode. */
|
||||
char flags;
|
||||
|
||||
/* Mnemonic of this opcode (sometimes partial when more decode is
|
||||
done in disassembly routines-- e.g., loads and stores). */
|
||||
const char *mnemonic;
|
||||
} decode_tbl_t;
|
||||
|
||||
|
||||
/* First-level decode table (i.e., for the 6 primary opcode bits). */
|
||||
static decode_tbl_t decode_tbl[64] =
|
||||
{
|
||||
/* A slight bit of decoding for loads and stores is done in the
|
||||
execution routines (operand size and addressing mode), which
|
||||
is why their respective entries are identical. */
|
||||
{ int_ldx, DEC_DECODED, "ld." }, /* ld.b isrc1(isrc2),idest. */
|
||||
{ int_ldx, DEC_DECODED, "ld." }, /* ld.b #const(isrc2),idest. */
|
||||
{ int_1d, DEC_DECODED, "ixfr" }, /* ixfr isrc1ni,fdest. */
|
||||
{ int_stx, DEC_DECODED, "st." }, /* st.b isrc1ni,#const(isrc2). */
|
||||
{ int_ldx, DEC_DECODED, "ld." }, /* ld.{s,l} isrc1(isrc2),idest. */
|
||||
{ int_ldx, DEC_DECODED, "ld." }, /* ld.{s,l} #const(isrc2),idest. */
|
||||
{ 0, 0 , 0 },
|
||||
{ int_stx, DEC_DECODED, "st." }, /* st.{s,l} isrc1ni,#const(isrc2),idest.*/
|
||||
{ int_fldst, DEC_DECODED, "fld." }, /* fld.{l,d,q} isrc1(isrc2)[++],fdest. */
|
||||
{ int_fldst, DEC_DECODED, "fld." }, /* fld.{l,d,q} #const(isrc2)[++],fdest. */
|
||||
{ int_fldst, DEC_DECODED, "fst." }, /* fst.{l,d,q} fdest,isrc1(isrc2)[++] */
|
||||
{ int_fldst, DEC_DECODED, "fst." }, /* fst.{l,d,q} fdest,#const(isrc2)[++] */
|
||||
{ int_cd, DEC_DECODED, "ld.c" }, /* ld.c csrc2,idest. */
|
||||
{ int_flush, DEC_DECODED, "flush" }, /* flush #const(isrc2) (or autoinc). */
|
||||
{ int_1c, DEC_DECODED, "st.c" }, /* st.c isrc1,csrc2. */
|
||||
{ int_fldst, DEC_DECODED, "pstd." }, /* pst.d fdest,#const(isrc2)[++]. */
|
||||
{ int_1, DEC_DECODED, "bri" }, /* bri isrc1ni. */
|
||||
{ int_12d, DEC_DECODED, "trap" }, /* trap isrc1ni,isrc2,idest. */
|
||||
{ 0, DEC_MORE, 0 }, /* FP ESCAPE FORMAT, more decode. */
|
||||
{ 0, DEC_MORE, 0 }, /* CORE ESCAPE FORMAT, more decode. */
|
||||
{ int_12S, DEC_DECODED, "btne" }, /* btne isrc1,isrc2,sbroff. */
|
||||
{ int_i2S, DEC_DECODED, "btne" }, /* btne #const,isrc2,sbroff. */
|
||||
{ int_12S, DEC_DECODED, "bte" }, /* bte isrc1,isrc2,sbroff. */
|
||||
{ int_i2S, DEC_DECODED, "bte" }, /* bte #const5,isrc2,idest. */
|
||||
{ int_fldst, DEC_DECODED, "pfld." }, /* pfld.{l,d,q} isrc1(isrc2)[++],fdest. */
|
||||
{ int_fldst, DEC_DECODED, "pfld." }, /* pfld.{l,d,q} #const(isrc2)[++],fdest.*/
|
||||
{ int_L, DEC_DECODED, "br" }, /* br lbroff. */
|
||||
{ int_L, DEC_DECODED, "call" }, /* call lbroff . */
|
||||
{ int_L, DEC_DECODED, "bc" }, /* bc lbroff. */
|
||||
{ int_L, DEC_DECODED, "bc.t" }, /* bc.t lbroff. */
|
||||
{ int_L, DEC_DECODED, "bnc" }, /* bnc lbroff. */
|
||||
{ int_L, DEC_DECODED, "bnc.t" }, /* bnc.t lbroff. */
|
||||
{ int_12d, DEC_DECODED, "addu" }, /* addu isrc1,isrc2,idest. */
|
||||
{ int_i2d, DEC_DECODED, "addu" }, /* addu #const,isrc2,idest. */
|
||||
{ int_12d, DEC_DECODED, "subu" }, /* subu isrc1,isrc2,idest. */
|
||||
{ int_i2d, DEC_DECODED, "subu" }, /* subu #const,isrc2,idest. */
|
||||
{ int_12d, DEC_DECODED, "adds" }, /* adds isrc1,isrc2,idest. */
|
||||
{ int_i2d, DEC_DECODED, "adds" }, /* adds #const,isrc2,idest. */
|
||||
{ int_12d, DEC_DECODED, "subs" }, /* subs isrc1,isrc2,idest. */
|
||||
{ int_i2d, DEC_DECODED, "subs" }, /* subs #const,isrc2,idest. */
|
||||
{ int_12d, DEC_DECODED, "shl" }, /* shl isrc1,isrc2,idest. */
|
||||
{ int_i2d, DEC_DECODED, "shl" }, /* shl #const,isrc2,idest. */
|
||||
{ int_12d, DEC_DECODED, "shr" }, /* shr isrc1,isrc2,idest. */
|
||||
{ int_i2d, DEC_DECODED, "shr" }, /* shr #const,isrc2,idest. */
|
||||
{ int_12d, DEC_DECODED, "shrd" }, /* shrd isrc1ni,isrc2,idest. */
|
||||
{ int_12S, DEC_DECODED, "bla" }, /* bla isrc1ni,isrc2,sbroff. */
|
||||
{ int_12d, DEC_DECODED, "shra" }, /* shra isrc1,isrc2,idest. */
|
||||
{ int_i2d, DEC_DECODED, "shra" }, /* shra #const,isrc2,idest. */
|
||||
{ int_12d, DEC_DECODED, "and" }, /* and isrc1,isrc2,idest. */
|
||||
{ int_i2d, DEC_DECODED, "and" }, /* and #const,isrc2,idest. */
|
||||
{ 0, 0 , 0 },
|
||||
{ int_i2d, DEC_DECODED, "andh" }, /* andh #const,isrc2,idest. */
|
||||
{ int_12d, DEC_DECODED, "andnot" }, /* andnot isrc1,isrc2,idest. */
|
||||
{ int_i2d, DEC_DECODED, "andnot" }, /* andnot #const,isrc2,idest. */
|
||||
{ 0, 0 , 0 },
|
||||
{ int_i2d, DEC_DECODED, "andnoth" }, /* andnoth #const,isrc2,idest.*/
|
||||
{ int_12d, DEC_DECODED, "or" }, /* or isrc1,isrc2,idest. */
|
||||
{ int_i2d, DEC_DECODED, "or" }, /* or #const,isrc2,idest. */
|
||||
{ 0, 0 , 0 },
|
||||
{ int_i2d, DEC_DECODED, "orh" }, /* orh #const,isrc2,idest. */
|
||||
{ int_12d, DEC_DECODED, "xor" }, /* xor isrc1,isrc2,idest. */
|
||||
{ int_i2d, DEC_DECODED, "xor" }, /* xor #const,isrc2,idest. */
|
||||
{ 0, 0 , 0 },
|
||||
{ int_i2d, DEC_DECODED, "xorh" }, /* xorh #const,isrc2,idest. */
|
||||
};
|
||||
|
||||
|
||||
/* Second-level decode table (i.e., for the 3 core escape opcode bits). */
|
||||
static decode_tbl_t core_esc_decode_tbl[8] =
|
||||
{
|
||||
{ 0, 0 , 0 },
|
||||
{ int_0, DEC_DECODED, "lock" }, /* lock. */
|
||||
{ int_1, DEC_DECODED, "calli" }, /* calli isrc1ni. */
|
||||
{ 0, 0 , 0 },
|
||||
{ int_0, DEC_DECODED, "intovr" }, /* intovr. */
|
||||
{ 0, 0 , 0 },
|
||||
{ 0, 0 , 0 },
|
||||
{ int_0, DEC_DECODED, "unlock" }, /* unlock. */
|
||||
};
|
||||
|
||||
|
||||
/* Second-level decode table (i.e., for the 7 FP extended opcode bits). */
|
||||
static decode_tbl_t fp_decode_tbl[128] =
|
||||
{
|
||||
/* Floating point instructions. The least significant 7 bits are
|
||||
the (extended) opcode and bits 10:7 are P,D,S,R respectively
|
||||
([p]ipelined, [d]ual, [s]ource prec., [r]esult prec.).
|
||||
For some operations, I defer decoding the P,S,R bits to the
|
||||
emulation routine for them. */
|
||||
{ flop_12d, DEC_DECODED, "r2p1." }, /* 0x00 pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "r2pt." }, /* 0x01 pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "r2ap1." }, /* 0x02 pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "r2apt." }, /* 0x03 pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "i2p1." }, /* 0x04 pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "i2pt." }, /* 0x05 pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "i2ap1." }, /* 0x06 pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "i2apt." }, /* 0x07 pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "rat1p2." }, /* 0x08 pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "m12apm." }, /* 0x09 pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "ra1p2." }, /* 0x0A pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "m12ttpa." }, /* 0x0B pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "iat1p2." }, /* 0x0C pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "m12tpm." }, /* 0x0D pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "ia1p2." }, /* 0x0E pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "m12tpa." }, /* 0x0F pf[m]am */
|
||||
{ flop_12d, DEC_DECODED, "r2s1." }, /* 0x10 pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "r2st." }, /* 0x11 pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "r2as1." }, /* 0x12 pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "r2ast." }, /* 0x13 pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "i2s1." }, /* 0x14 pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "i2st." }, /* 0x15 pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "i2as1." }, /* 0x16 pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "i2ast." }, /* 0x17 pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "rat1s2." }, /* 0x18 pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "m12asm." }, /* 0x19 pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "ra1s2." }, /* 0x1A pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "m12ttsa." }, /* 0x1B pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "iat1s2." }, /* 0x1C pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "m12tsm." }, /* 0x1D pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "ia1s2." }, /* 0x1E pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "m12tsa." }, /* 0x1F pf[m]sm */
|
||||
{ flop_12d, DEC_DECODED, "fmul." }, /* 0x20 [p]fmul */
|
||||
{ flop_12d, DEC_DECODED, "fmlow." }, /* 0x21 fmlow.dd */
|
||||
{ flop_2d, DEC_DECODED, "frcp." }, /* 0x22 frcp.{ss,sd,dd} */
|
||||
{ flop_2d, DEC_DECODED, "frsqr." }, /* 0x23 frsqr.{ss,sd,dd} */
|
||||
{ flop_12d, DEC_DECODED, "pfmul3.dd" }, /* 0x24 pfmul3.dd */
|
||||
{ 0, 0 , 0 }, /* 0x25 */
|
||||
{ 0, 0 , 0 }, /* 0x26 */
|
||||
{ 0, 0 , 0 }, /* 0x27 */
|
||||
{ 0, 0 , 0 }, /* 0x28 */
|
||||
{ 0, 0 , 0 }, /* 0x29 */
|
||||
{ 0, 0 , 0 }, /* 0x2A */
|
||||
{ 0, 0 , 0 }, /* 0x2B */
|
||||
{ 0, 0 , 0 }, /* 0x2C */
|
||||
{ 0, 0 , 0 }, /* 0x2D */
|
||||
{ 0, 0 , 0 }, /* 0x2E */
|
||||
{ 0, 0 , 0 }, /* 0x2F */
|
||||
{ flop_12d, DEC_DECODED, "fadd." }, /* 0x30, [p]fadd.{ss,sd,dd} */
|
||||
{ flop_12d, DEC_DECODED, "fsub." }, /* 0x31, [p]fsub.{ss,sd,dd} */
|
||||
{ flop_1d, DEC_DECODED, "fix." }, /* 0x32, [p]fix.{ss,sd,dd} */
|
||||
{ flop_1d, DEC_DECODED, "famov." }, /* 0x33, [p]famov.{ss,sd,ds,dd} */
|
||||
{ flop_12d, DEC_DECODED, "f{gt,le}" }, /* 0x34, pf{gt,le}.{ss,dd} */
|
||||
{ flop_12d, DEC_DECODED, "feq." }, /* 0x35, pfeq.{ss,dd} */
|
||||
{ 0, 0 , 0 }, /* 0x36 */
|
||||
{ 0, 0 , 0 }, /* 0x37 */
|
||||
{ 0, 0 , 0 }, /* 0x38 */
|
||||
{ 0, 0 , 0 }, /* 0x39 */
|
||||
{ flop_1d, DEC_DECODED, "ftrunc." }, /* 0x3A, [p]ftrunc.{ss,sd,dd} */
|
||||
{ 0, 0 , 0 }, /* 0x3B */
|
||||
{ 0, 0 , 0 }, /* 0x3C */
|
||||
{ 0, 0 , 0 }, /* 0x3D */
|
||||
{ 0, 0 , 0 }, /* 0x3E */
|
||||
{ 0, 0 , 0 }, /* 0x3F */
|
||||
{ flop_fxfr, DEC_DECODED, "fxfr" }, /* 0x40, fxfr fsrc1,idest. */
|
||||
{ 0, 0 , 0 }, /* 0x41 */
|
||||
{ 0, 0 , 0 }, /* 0x42 */
|
||||
{ 0, 0 , 0 }, /* 0x43 */
|
||||
{ 0, 0 , 0 }, /* 0x44 */
|
||||
{ 0, 0 , 0 }, /* 0x45 */
|
||||
{ 0, 0 , 0 }, /* 0x46 */
|
||||
{ 0, 0 , 0 }, /* 0x47 */
|
||||
{ 0, 0 , 0 }, /* 0x48 */
|
||||
{ flop_12d, DEC_DECODED, "fiadd." }, /* 0x49, [p]fiadd.{ss,dd} */
|
||||
{ 0, 0 , 0 }, /* 0x4A */
|
||||
{ 0, 0 , 0 }, /* 0x4B */
|
||||
{ 0, 0 , 0 }, /* 0x4C */
|
||||
{ flop_12d, DEC_DECODED, "fisub." }, /* 0x4D, [p]fisub.{ss,dd} */
|
||||
{ 0, 0 , 0 }, /* 0x4E */
|
||||
{ 0, 0 , 0 }, /* 0x4F */
|
||||
{ flop_12d, DEC_DECODED, "faddp" }, /* 0x50, [p]faddp */
|
||||
{ flop_12d, DEC_DECODED, "faddz" }, /* 0x51, [p]faddz */
|
||||
{ 0, 0 , 0 }, /* 0x52 */
|
||||
{ 0, 0 , 0 }, /* 0x53 */
|
||||
{ 0, 0 , 0 }, /* 0x54 */
|
||||
{ 0, 0 , 0 }, /* 0x55 */
|
||||
{ 0, 0 , 0 }, /* 0x56 */
|
||||
{ flop_12d, DEC_DECODED, "fzchkl" }, /* 0x57, [p]fzchkl */
|
||||
{ 0, 0 , 0 }, /* 0x58 */
|
||||
{ 0, 0 , 0 }, /* 0x59 */
|
||||
{ flop_1d, DEC_DECODED, "form" }, /* 0x5A, [p]form.dd */
|
||||
{ 0, 0 , 0 }, /* 0x5B */
|
||||
{ 0, 0 , 0 }, /* 0x5C */
|
||||
{ 0, 0 , 0 }, /* 0x5D */
|
||||
{ 0, 0 , 0 }, /* 0x5E */
|
||||
{ flop_12d, DEC_DECODED, "fzchks" }, /* 0x5F, [p]fzchks */
|
||||
{ 0, 0 , 0 }, /* 0x60 */
|
||||
{ 0, 0 , 0 }, /* 0x61 */
|
||||
{ 0, 0 , 0 }, /* 0x62 */
|
||||
{ 0, 0 , 0 }, /* 0x63 */
|
||||
{ 0, 0 , 0 }, /* 0x64 */
|
||||
{ 0, 0 , 0 }, /* 0x65 */
|
||||
{ 0, 0 , 0 }, /* 0x66 */
|
||||
{ 0, 0 , 0 }, /* 0x67 */
|
||||
{ 0, 0 , 0 }, /* 0x68 */
|
||||
{ 0, 0 , 0 }, /* 0x69 */
|
||||
{ 0, 0 , 0 }, /* 0x6A */
|
||||
{ 0, 0 , 0 }, /* 0x6B */
|
||||
{ 0, 0 , 0 }, /* 0x6C */
|
||||
{ 0, 0 , 0 }, /* 0x6D */
|
||||
{ 0, 0 , 0 }, /* 0x6E */
|
||||
{ 0, 0 , 0 }, /* 0x6F */
|
||||
{ 0, 0 , 0 }, /* 0x70 */
|
||||
{ 0, 0 , 0 }, /* 0x71 */
|
||||
{ 0, 0 , 0 }, /* 0x72 */
|
||||
{ 0, 0 , 0 }, /* 0x73 */
|
||||
{ 0, 0 , 0 }, /* 0x74 */
|
||||
{ 0, 0 , 0 }, /* 0x75 */
|
||||
{ 0, 0 , 0 }, /* 0x76 */
|
||||
{ 0, 0 , 0 }, /* 0x77 */
|
||||
{ 0, 0 , 0 }, /* 0x78 */
|
||||
{ 0, 0 , 0 }, /* 0x79 */
|
||||
{ 0, 0 , 0 }, /* 0x7A */
|
||||
{ 0, 0 , 0 }, /* 0x7B */
|
||||
{ 0, 0 , 0 }, /* 0x7C */
|
||||
{ 0, 0 , 0 }, /* 0x7D */
|
||||
{ 0, 0 , 0 }, /* 0x7E */
|
||||
{ 0, 0 , 0 }, /* 0x7F */
|
||||
};
|
||||
|
||||
|
||||
/* Replaces tabs with spaces. */
|
||||
static void i860_dasm_tab_replacer(char* buf, int tab_size)
|
||||
{
|
||||
int i = 0;
|
||||
int tab_count = 0;
|
||||
char tab_buf[1024];
|
||||
memset(tab_buf, 0, 1024);
|
||||
|
||||
while (i != strlen(buf))
|
||||
{
|
||||
if (buf[i] != '\t')
|
||||
{
|
||||
tab_buf[tab_count] = buf[i];
|
||||
tab_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
while (tab_count % tab_size != 0)
|
||||
{
|
||||
strcat(tab_buf, " ");
|
||||
tab_count++;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
tab_buf[tab_count] = 0x00;
|
||||
strcpy(buf, tab_buf);
|
||||
}
|
||||
|
||||
|
||||
/* Entry point for disassembler. */
|
||||
unsigned disasm_i860(char *buf, unsigned pc, UINT32 insn)
|
||||
{
|
||||
int unrecognized_op = 1;
|
||||
int upper_6bits = (insn >> 26) & 0x3f;
|
||||
char flags = decode_tbl[upper_6bits].flags;
|
||||
if (flags & DEC_DECODED)
|
||||
{
|
||||
const char *s = decode_tbl[upper_6bits].mnemonic;
|
||||
decode_tbl[upper_6bits].insn_dis (buf, (char *)s, pc, insn);
|
||||
unrecognized_op = 0;
|
||||
}
|
||||
else if (flags & DEC_MORE)
|
||||
{
|
||||
if (upper_6bits == 0x12)
|
||||
{
|
||||
/* FP instruction format handled here. */
|
||||
char fp_flags = fp_decode_tbl[insn & 0x7f].flags;
|
||||
const char *s = fp_decode_tbl[insn & 0x7f].mnemonic;
|
||||
if (fp_flags & DEC_DECODED)
|
||||
{
|
||||
fp_decode_tbl[insn & 0x7f].insn_dis (buf, (char *)s, pc, insn);
|
||||
unrecognized_op = 0;
|
||||
}
|
||||
}
|
||||
else if (upper_6bits == 0x13)
|
||||
{
|
||||
/* Core escape instruction format handled here. */
|
||||
char esc_flags = core_esc_decode_tbl[insn & 0x3].flags;
|
||||
const char *s = core_esc_decode_tbl[insn & 0x3].mnemonic;
|
||||
if (esc_flags & DEC_DECODED)
|
||||
{
|
||||
core_esc_decode_tbl[insn & 0x3].insn_dis (buf, (char *)s, pc, insn);
|
||||
unrecognized_op = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unrecognized_op)
|
||||
sprintf (buf, ".long\t%#08x", insn);
|
||||
|
||||
/* Replace tabs with spaces */
|
||||
i860_dasm_tab_replacer(buf, 10);
|
||||
|
||||
/* Return number of bytes disassembled. */
|
||||
/* MAME dasm flags haven't been added yet */
|
||||
return (4);
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
/*
|
||||
Virtual Combat hardware games.
|
||||
|
||||
Driver by Jason Eckhardt and Andrew Gardner.
|
||||
|
||||
|
||||
Driver by Jason Eckhardt and Andrew Gardner.
|
||||
|
||||
----
|
||||
|
||||
There are two known games on this hardware. Both are developed by
|
||||
@ -17,10 +17,10 @@ Shadow Fighters (German) (c) Sega? 1989?
|
||||
|
||||
There are two boards to this hardware. The upper, which contains the
|
||||
graphics ROMs and the i860, and the lower which contains the main
|
||||
and sound CPUs. Virtual Combat sports two upper boards which presumably
|
||||
and sound CPUs. Virtual Combat sports two upper boards which
|
||||
output a different rasterization of the scene for each stereo eye.
|
||||
|
||||
UPPER:
|
||||
UPPER: (Virtual Combat has an identical MIDDLE board also).
|
||||
Intel I860 XR processor
|
||||
MB8298-25P-SK RAMS x12 (silkscreen said 62256)
|
||||
Analog device ADV476KN50E (silkscreen said BT476)
|
||||
@ -28,7 +28,7 @@ UPPER:
|
||||
8-way DIP switch
|
||||
574200D x4
|
||||
PAL palce24v10 x2 (next to the i860)
|
||||
Bt476 RAMDAC
|
||||
Bt476 RAMDAC
|
||||
|
||||
LOWER:
|
||||
Motorola MC68000P12 x2
|
||||
@ -54,20 +54,50 @@ NOTES : Shadow Fighters appears to have been dumped from an earlier
|
||||
The data stored in "samples" is simply a series of
|
||||
Creative Media VOC files concatenated to eachother.
|
||||
The sound program ("sound") is about 640 bytes long.
|
||||
The graphics ROMs have had images successfully extracted from
|
||||
them. Pictures for Shadow Fighters can be found online.
|
||||
The hardware is said to run at medium resolution.
|
||||
The SRAM module dump can likely be thrown away for both games.
|
||||
The PAL that's dumped for Shadow Fighters looks pretty bad.
|
||||
Websites seem to say Shadow Fighters is a SEGA game, but I
|
||||
couldn't find a SEGA string anywhere in the ROMs. I also,
|
||||
however, could not find a VR8 string in the Virtual Combat
|
||||
ROMs, so who knows... Kyle's name is easily found in both
|
||||
though :).
|
||||
|
||||
TODO : This is a skeleton driver. Nearly everything.
|
||||
i860XR-25 CPU core!
|
||||
TODO : This is a partially working driver. Most of the memory maps for
|
||||
all four CPUs are complete. An Intel i860XR CPU core has now
|
||||
been incorporated into MAME.
|
||||
|
||||
-------- Notes/questions ----------
|
||||
- Most of the memory maps and input ports are complete now.
|
||||
For "main", the only I/O locations that seem to be left
|
||||
mysterious are:
|
||||
0x600010,
|
||||
0x60000C: Only written; maybe mc6845? Often accessed
|
||||
together, and 16 consecutive words of data are
|
||||
written to 0x60000C, making me think it might be
|
||||
6845-related. May or may not be important for
|
||||
reasonable emulation.
|
||||
0x60001C: Only read; might be a latch of some sort. It is
|
||||
read each time M0's interrupt service routine syncs
|
||||
with the i860's to have them update the frame buffer.
|
||||
Might this be a HW blank bit so things look clean when
|
||||
the i860's do their updates?
|
||||
The two other times I see it read are just before
|
||||
and after one of the pallette setups is done.
|
||||
0x600018: ? No info yet.
|
||||
0x704000: (VC only) Likely analog axis for VR headset
|
||||
0x703000: (VC only) Likely analog axis for VR headset
|
||||
0x702000: (Shadow only). I think this is another IN port. It
|
||||
is always read at the same time as the other two
|
||||
ports.
|
||||
|
||||
- Assuming a single framebuffer, as I think we are at the moment,
|
||||
how are all the CPUs writes to the framebuffer prioritized,
|
||||
if at all? The zero values written by the 68k side erase
|
||||
the i860-generated FB data (i.e., zero maps to black in the
|
||||
pallette). On the other hand, treating the zero values as
|
||||
transparent doesn't quite look right either. Could just the
|
||||
i860s each have their own framebuffers? After
|
||||
all, since each eye of the binocular sees a slightly different
|
||||
picture, the i860's might just maintain their own. Then maybe
|
||||
the 68k shares with each of the two, since I think it just
|
||||
generates a single picture (not sure about that either).
|
||||
----------------------------------------------
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
@ -77,61 +107,266 @@ TODO : This is a skeleton driver. Nearly everything.
|
||||
#include "video/generic.h"
|
||||
#include "video/tlc34076.h"
|
||||
|
||||
static UINT16* framebuffer;
|
||||
static UINT16* framebuffer_main;
|
||||
static UINT16* framebuffer_secondary;
|
||||
static UINT16* vid_0_shared_RAM;
|
||||
static UINT16* vid_1_shared_RAM;
|
||||
|
||||
|
||||
static VIDEO_UPDATE( vcombat )
|
||||
{
|
||||
int x, y;
|
||||
int count = 0;
|
||||
const rgb_t *pens = tlc34076_get_pens();
|
||||
|
||||
/* TODO: It looks like the leftmost chunk of the ground should really be on the right side? */
|
||||
/* But the i860 draws the background correctly, so it may be an original game issue. */
|
||||
/* There's also some garbage in the upper-left corner. Might be related to this 'wraparound'. */
|
||||
/* Or maybe it's related to the 68k's alpha? It might come from the 68k side of the house. */
|
||||
|
||||
/* Main eye */
|
||||
for(y = 0; y < 256; y++)
|
||||
{
|
||||
for(x = 384; x < 640; x++)
|
||||
{
|
||||
UINT32 color;
|
||||
if (x % 2) color = (framebuffer_main[count] & 0xff00) >> 8;
|
||||
else color = framebuffer_main[count] & 0x00ff;
|
||||
|
||||
/* Vcombat's screen renders 'flopped' - very likely because VR headset displays may reflect off mirrors.
|
||||
Shadfgtr isn't flopped, so it's not a constant feature of the hardware. */
|
||||
if(x < video_screen_get_visible_area(screen)->max_x && y < video_screen_get_visible_area(screen)->max_y)
|
||||
*BITMAP_ADDR32(bitmap, y, x) = pens[color];
|
||||
|
||||
if (x % 2) count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Early out for shadow fighters */
|
||||
if (!framebuffer_secondary)
|
||||
return 0;
|
||||
|
||||
/* Secondary eye */
|
||||
count = 0;
|
||||
for(y = 0; y < 256; y++)
|
||||
{
|
||||
for(x = 0; x < 256; x++)
|
||||
{
|
||||
UINT32 color;
|
||||
if (x % 2) color = (framebuffer_secondary[count] & 0xff00) >> 8;
|
||||
else color = framebuffer_secondary[count] & 0x00ff;
|
||||
|
||||
/* Vcombat's screen renders 'flopped' - very likely because VR headset displays may reflect off mirrors.
|
||||
Shadfgtr isn't flopped, so it's not a constant feature of the hardware. */
|
||||
if(x < video_screen_get_visible_area(screen)->max_x && y < video_screen_get_visible_area(screen)->max_y)
|
||||
*BITMAP_ADDR32(bitmap, y, x) = pens[color];
|
||||
|
||||
if (x % 2) count++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Maybe there's a blend chip between the 68k and the framebuffer? */
|
||||
static WRITE16_HANDLER( main_video_write )
|
||||
{
|
||||
/* Doesn't seem to make sense for shadow fighters. Maybe some of that factory rework disables this? */
|
||||
/* Doesn't always seem to work for vcombat either. More testing needed. */
|
||||
if (data != 0x00000000) {
|
||||
framebuffer_main[offset] = data;
|
||||
}
|
||||
}
|
||||
|
||||
static READ16_HANDLER( control_1_r )
|
||||
{
|
||||
return (input_port_read(space->machine, "IN0") << 8);
|
||||
}
|
||||
|
||||
static READ16_HANDLER( control_2_r )
|
||||
{
|
||||
return (input_port_read(space->machine, "IN1") << 8);
|
||||
}
|
||||
|
||||
static void wiggle_i860_common(int n, UINT16 data, const device_config *device)
|
||||
{
|
||||
int bus_hold = (data & 0x03) == 0x03;
|
||||
int reset = data & 0x10;
|
||||
assert(n >= 0 && n < 2);
|
||||
if (!device)
|
||||
return;
|
||||
if (bus_hold)
|
||||
{
|
||||
fprintf(stderr, "M0 asserting bus HOLD to i860 %s\n", device->tag);
|
||||
i860_set_pin(device->token, DEC_PIN_BUS_HOLD, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "M0 clearing bus HOLD to i860 %s\n", device->tag);
|
||||
i860_set_pin(device->token, DEC_PIN_BUS_HOLD, 0);
|
||||
}
|
||||
|
||||
if (reset)
|
||||
{
|
||||
fprintf(stderr, "M0 asserting RESET to i860 %s\n", device->tag);
|
||||
i860_set_pin(device->token, DEC_PIN_RESET, 1);
|
||||
}
|
||||
else
|
||||
i860_set_pin(device->token, DEC_PIN_RESET, 0);
|
||||
}
|
||||
|
||||
static WRITE16_HANDLER( wiggle_i860p0_pins_w )
|
||||
{
|
||||
wiggle_i860_common(0, data, cputag_get_cpu(space->machine, "vid_0"));
|
||||
}
|
||||
|
||||
static WRITE16_HANDLER( wiggle_i860p1_pins_w )
|
||||
{
|
||||
wiggle_i860_common(1, data, cputag_get_cpu(space->machine, "vid_1"));
|
||||
}
|
||||
|
||||
static READ16_HANDLER( main_irqiack_r )
|
||||
{
|
||||
//fprintf(stderr, "M0: irq iack\n");
|
||||
cpu_set_input_line(cputag_get_cpu(space->machine, "main"), M68K_IRQ_1, CLEAR_LINE);
|
||||
//cpu_set_input_line(cputag_get_cpu(space->machine, "main"), INPUT_LINE_RESET, CLEAR_LINE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static READ16_HANDLER( sound_resetmain_r )
|
||||
{
|
||||
//fprintf(stderr, "M1: reset line to M0\n");
|
||||
//cpu_set_input_line(cputag_get_cpu(space->machine, "main"), INPUT_LINE_RESET, PULSE_LINE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static WRITE64_HANDLER( v0_fb_w )
|
||||
{
|
||||
/* The frame buffer seems to sit on a 32-bit data bus, while the
|
||||
i860 uses a 64-bit data bus. Adjust accordingly. */
|
||||
char *p = (char *)framebuffer_main;
|
||||
int m = mem_mask;
|
||||
int o = (offset << 2);
|
||||
if (m & 0xff000000) {
|
||||
p[o+3] = (data >> 24) & 0xff;
|
||||
}
|
||||
if (m & 0x00ff0000) {
|
||||
p[o+2] = (data >> 16) & 0xff;
|
||||
}
|
||||
if (m & 0x0000ff00) {
|
||||
p[o+1] = (data >> 8) & 0xff;
|
||||
}
|
||||
if (m & 0x000000ff) {
|
||||
p[o+0] = (data >> 0) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is just temporary so we can see what each i860 is doing to the
|
||||
framebuffer. */
|
||||
static WRITE64_HANDLER( v1_fb_w )
|
||||
{
|
||||
/* The frame buffer seems to sit on a 32-bit data bus, while the
|
||||
i860 uses a 64-bit data bus. Adjust accordingly. */
|
||||
char *p = (char *)framebuffer_secondary;
|
||||
int m = mem_mask;
|
||||
int o = (offset << 2);
|
||||
if (m & 0xff000000) {
|
||||
p[o+3] = (data >> 24) & 0xff;
|
||||
}
|
||||
if (m & 0x00ff0000) {
|
||||
p[o+2] = (data >> 16) & 0xff;
|
||||
}
|
||||
if (m & 0x0000ff00) {
|
||||
p[o+1] = (data >> 8) & 0xff;
|
||||
}
|
||||
if (m & 0x000000ff) {
|
||||
p[o+0] = (data >> 0) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 16 )
|
||||
AM_RANGE(0x000000, 0x0fffff) AM_ROM
|
||||
AM_RANGE(0x200000, 0x2fffff) AM_RAM
|
||||
AM_RANGE(0x300000, 0x3fffff) AM_RAM AM_BASE(&framebuffer) AM_SHARE(1)
|
||||
|
||||
AM_RANGE(0x300000, 0x30ffff) AM_RAM_WRITE(main_video_write)
|
||||
|
||||
AM_RANGE(0x400000, 0x43ffff) AM_RAM AM_BASE(&vid_0_shared_RAM) AM_SHARE(2) /* First i860 shared RAM */
|
||||
// AM_RANGE(0x440000, 0x440003) i860 #1 com 1
|
||||
// AM_RANGE(0x480000, 0x480003) i860 #1 com 2
|
||||
// AM_RANGE(0x4c0000, 0x4c0003) i860 #1 stop/start/reset
|
||||
AM_RANGE(0x440000, 0x440003) AM_RAM AM_SHARE(6) /* M0->P0 i860 #1 com 1 */
|
||||
AM_RANGE(0x480000, 0x480003) AM_RAM AM_SHARE(7) /* M0<-P0 i860 #1 com 2 */
|
||||
AM_RANGE(0x4c0000, 0x4c0003) AM_WRITE(wiggle_i860p0_pins_w) /* i860 #1 stop/start/reset */
|
||||
|
||||
AM_RANGE(0x500000, 0x53ffff) AM_RAM AM_BASE(&vid_1_shared_RAM) AM_SHARE(3) /* Second i860 shared RAM */
|
||||
// AM_RANGE(0x540000, 0x540003) i860 #2 com 1
|
||||
// AM_RANGE(0x580000, 0x580003) i860 #2 com 2
|
||||
// AM_RANGE(0x5c0000, 0x5c0003) i860 #2 stop/start/reset
|
||||
AM_RANGE(0x540000, 0x540003) AM_RAM AM_SHARE(8) /* M0->P1 i860 #2 com 1 */
|
||||
AM_RANGE(0x580000, 0x580003) AM_RAM AM_SHARE(9) /* M0<-P1 i860 #2 com 2 */
|
||||
AM_RANGE(0x5c0000, 0x5c0003) AM_WRITE(wiggle_i860p1_pins_w) /* i860 #2 stop/start/reset */
|
||||
|
||||
AM_RANGE(0x600000, 0x600001) AM_READ(control_1_r) /* IN0 port */
|
||||
AM_RANGE(0x600004, 0x600005) AM_RAM AM_SHARE(5) /* M0<-M1 */
|
||||
AM_RANGE(0x600008, 0x600009) AM_READ(control_2_r) /* IN1 port */
|
||||
/* AM_RANGE(0x60000c, 0x60000d) See notes at top of driver. */
|
||||
/* AM_RANGE(0x600010, 0x600011) See notes at top of driver. */
|
||||
AM_RANGE(0x700000, 0x7007ff) AM_RAM /* TODO: Non-volatile RAM */
|
||||
AM_RANGE(0x701000, 0x701001) AM_READ(main_irqiack_r)
|
||||
AM_RANGE(0x705000, 0x705001) AM_RAM AM_SHARE(4) /* M1->M0 */
|
||||
|
||||
//AM_RANGE(0x703000, 0x703001) /* Headset rotation axis? */
|
||||
//AM_RANGE(0x704000, 0x704001) /* Headset rotation axis? */
|
||||
|
||||
AM_RANGE(0x706000, 0x70601f) AM_READWRITE(tlc34076_lsb_r, tlc34076_lsb_w)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
/* The first i860 - middle board */
|
||||
static ADDRESS_MAP_START( vid_0_map, ADDRESS_SPACE_PROGRAM, 32 )
|
||||
AM_RANGE(0x00000000, 0x000fffff) AM_RAM AM_SHARE(1) /* Shared framebuffer */
|
||||
// AM_RANGE(0x20000000, 0x20000003) com 1 (0x440000 in 68k-land)
|
||||
// AM_RANGE(0x40000000, 0x401fffff) AM_ROM /* 3d data ROMs */
|
||||
// AM_RANGE(0x80000000, 0x80000003) com 2 (0x480000 in 68k-land)
|
||||
AM_RANGE(0xfffc0000, 0xffffffff) AM_RAM AM_SHARE(2) /* Shared RAM with main */
|
||||
static ADDRESS_MAP_START( vid_0_map, ADDRESS_SPACE_PROGRAM, 64 )
|
||||
AM_RANGE(0x00000000, 0x0001ffff) AM_RAM_WRITE(v0_fb_w) /* Shared framebuffer - half of the bits lost to 32-bit bus */
|
||||
AM_RANGE(0x20000000, 0x20000007) AM_RAM AM_SHARE(6) /* M0<-P0 com 1 (0x440000 in 68k-land) */
|
||||
AM_RANGE(0x40000000, 0x401fffff) AM_ROM AM_REGION("gfx", 0)
|
||||
AM_RANGE(0x80000000, 0x80000007) AM_RAM AM_SHARE(7) /* M0->P0 com 2 (0x480000 in 68k-land) */
|
||||
AM_RANGE(0xc0000000, 0xc0000fff) AM_NOP /* Dummy D$ flush page. */
|
||||
AM_RANGE(0xfffc0000, 0xffffffff) AM_RAM AM_SHARE(2) /* Shared RAM with main */
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
/* The second i860 - top board */
|
||||
static ADDRESS_MAP_START( vid_1_map, ADDRESS_SPACE_PROGRAM, 32 )
|
||||
AM_RANGE(0x00000000, 0x000fffff) AM_RAM AM_SHARE(1) /* Shared framebuffer */
|
||||
// AM_RANGE(0x20000000, 0x20000003) com 1 (0x540000 in 68k-land)
|
||||
// AM_RANGE(0x40000000, 0x401fffff) AM_ROM /* 3d data ROMs */
|
||||
// AM_RANGE(0x80000000, 0x80000003) com 2 (0x580000 in 68k-land)
|
||||
AM_RANGE(0xfffc0000, 0xffffffff) AM_RAM AM_SHARE(3) /* Shared RAM with main */
|
||||
static ADDRESS_MAP_START( vid_1_map, ADDRESS_SPACE_PROGRAM, 64 )
|
||||
AM_RANGE(0x00000000, 0x0001ffff) AM_RAM_WRITE(v1_fb_w) /* Half of the bits lost to 32-bit bus */
|
||||
AM_RANGE(0x20000000, 0x20000007) AM_RAM AM_SHARE(8) /* M0->P1 com 1 (0x540000 in 68k-land) */
|
||||
AM_RANGE(0x40000000, 0x401fffff) AM_ROM AM_REGION("gfx", 0)
|
||||
AM_RANGE(0x80000000, 0x80000007) AM_RAM AM_SHARE(9) /* M0<-P1 com 2 (0x580000 in 68k-land) */
|
||||
AM_RANGE(0xc0000000, 0xc0000fff) AM_NOP /* Dummy D$ flush page. */
|
||||
AM_RANGE(0xfffc0000, 0xffffffff) AM_RAM AM_SHARE(3) /* Shared RAM with main */
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
/* Sound CPU - temprarily disabled */
|
||||
//static ADDRESS_MAP_START( sound_map, ADDRESS_SPACE_PROGRAM, 16 )
|
||||
// AM_RANGE(0x000000, 0x03ffff) AM_ROM
|
||||
//ADDRESS_MAP_END
|
||||
/* Sound CPU */
|
||||
static ADDRESS_MAP_START( sound_map, ADDRESS_SPACE_PROGRAM, 16 )
|
||||
AM_RANGE(0x000000, 0x03ffff) AM_ROM
|
||||
AM_RANGE(0x081000, 0x081fff) AM_RAM
|
||||
AM_RANGE(0x140000, 0x140001) AM_READ(sound_resetmain_r) /* Ping M0's reset line */
|
||||
AM_RANGE(0x180000, 0x180001) AM_RAM AM_SHARE(4) /* M1<-M0 */
|
||||
AM_RANGE(0x1C0000, 0x1C0001) AM_RAM AM_SHARE(5) /* M1->M0 */
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
static MACHINE_RESET( vcombat )
|
||||
{
|
||||
/* Setup the Bt476 VGA RAMDAC palette chip */
|
||||
tlc34076_reset(6);
|
||||
|
||||
i860_set_pin(cputag_get_cpu(machine, "vid_0")->token, DEC_PIN_BUS_HOLD, 1);
|
||||
i860_set_pin(cputag_get_cpu(machine, "vid_1")->token, DEC_PIN_BUS_HOLD, 1);
|
||||
}
|
||||
|
||||
static MACHINE_RESET( shadfgtr )
|
||||
{
|
||||
/* Setup the Bt476 VGA RAMDAC palette chip */
|
||||
tlc34076_reset(6);
|
||||
|
||||
i860_set_pin(cputag_get_cpu(machine, "vid_0")->token, DEC_PIN_BUS_HOLD, 1);
|
||||
}
|
||||
|
||||
|
||||
static DIRECT_UPDATE_HANDLER( vid_0_direct_handler )
|
||||
{
|
||||
if (address >= 0xfffc0000 && address <= 0xffffffff)
|
||||
@ -152,6 +387,7 @@ static DIRECT_UPDATE_HANDLER( vid_1_direct_handler )
|
||||
return address;
|
||||
}
|
||||
|
||||
|
||||
static DRIVER_INIT( vcombat )
|
||||
{
|
||||
UINT8 *ROM = memory_region(machine, "main");
|
||||
@ -160,72 +396,87 @@ static DRIVER_INIT( vcombat )
|
||||
memory_set_direct_update_handler(cputag_get_address_space(machine, "vid_0", ADDRESS_SPACE_PROGRAM), vid_0_direct_handler);
|
||||
memory_set_direct_update_handler(cputag_get_address_space(machine, "vid_1", ADDRESS_SPACE_PROGRAM), vid_1_direct_handler);
|
||||
|
||||
// Hacks
|
||||
// pc==4016 : jump 4038 ... There's something strange about how it waits at 402e (interrupts all masked out)
|
||||
/* Allocate the two framebuffers */
|
||||
framebuffer_main = auto_malloc(0x10000 * sizeof(UINT16));
|
||||
framebuffer_secondary = auto_malloc(0x10000 * sizeof(UINT16));
|
||||
|
||||
/* pc==4016 : jump 4038 ... There's something strange about how it waits at 402e (interrupts all masked out)
|
||||
I think what is happening here is that M0 snags the first time
|
||||
it hits this point based on a counter test just above this
|
||||
instruction. That counter gets updated just past this instruction.
|
||||
However, the only way this can be passed is if the M0 CPU is
|
||||
reset (the IPL=7, but irq 7 is a nop). I am almost sure that M1
|
||||
reads a latch, which resets M0 (probably to ensure M0 and M1 are
|
||||
both alive) and gets passed this snag. I tried to hook up a reset
|
||||
which should work, but asserting the reset line on the m68k doesn't
|
||||
seem to do anything. Maybe the 68k emulator doesn't respond to
|
||||
that, or I didn't do it correctly. But I think that is what needs
|
||||
to be done. But it isn't crucial for emulation. Shadow does not
|
||||
have this snag. */
|
||||
ROM[0x4017] = 0x66;
|
||||
}
|
||||
|
||||
// Sound CPU comm bits
|
||||
// pc==40fa : jump 40fc ... 600004 should be -16
|
||||
ROM[0x40fb] = 0x67;
|
||||
// pc==410e : jump 4110 ... 600004 should be 31
|
||||
ROM[0x410f] = 0x67;
|
||||
static DRIVER_INIT( shadfgtr )
|
||||
{
|
||||
/* Allocate just one framebuffer */
|
||||
framebuffer_main = auto_malloc(0x10000 * sizeof(UINT16));
|
||||
framebuffer_secondary = NULL;
|
||||
|
||||
// pc==e220 : jump e222 ... 20119a should not be 0. (no interrupts masked)
|
||||
// TODO: I wonder if this is an input bit that's ticked on vblank or something. The menu selection continually crawls up.
|
||||
/* The i860 executes out of RAM */
|
||||
memory_set_direct_update_handler(cputag_get_address_space(machine, "vid_0", ADDRESS_SPACE_PROGRAM), vid_0_direct_handler);
|
||||
}
|
||||
|
||||
|
||||
static INPUT_PORTS_START( vcombat )
|
||||
PORT_START("IN0")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) /* Left button */
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) /* Right button */
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_4WAY
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
|
||||
PORT_START("IN1")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
static VIDEO_UPDATE( vcombat )
|
||||
{
|
||||
int x, y;
|
||||
int count = 0;
|
||||
const rgb_t *pens = tlc34076_get_pens();
|
||||
static INPUT_PORTS_START( shadfgtr )
|
||||
PORT_START("IN0")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 )
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 )
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_4WAY /* ? */
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_4WAY /* ? */
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_4WAY
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
|
||||
for(y = 0; y < 480; y++)
|
||||
{
|
||||
for(x = 0; x < 256; x++)
|
||||
{
|
||||
UINT32 color;
|
||||
|
||||
if (x % 2) color = (framebuffer[count] & 0xff00) >> 8;
|
||||
else color = framebuffer[count] & 0x00ff;
|
||||
|
||||
if(x < video_screen_get_visible_area(screen)->max_x && y < video_screen_get_visible_area(screen)->max_y)
|
||||
*BITMAP_ADDR32(bitmap, y, x) = pens[color];
|
||||
|
||||
if (x % 2) count++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// This is just here to show that there is text in the main program ROM. It probably won't really be a useful decode.
|
||||
static const gfx_layout vcombat_charlayout =
|
||||
{
|
||||
8, 8,
|
||||
0x100000 / 0x80,
|
||||
8,
|
||||
{ 0,1,2,3,4,5,6,7 },
|
||||
{ 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16 },
|
||||
{ 0*16*8, 1*16*8, 2*16*8, 3*16*8, 4*16*8, 5*16*8, 6*16*8, 7*16*8 },
|
||||
8 * 0x80
|
||||
};
|
||||
|
||||
|
||||
static GFXDECODE_START( vcombat )
|
||||
GFXDECODE_ENTRY( "main", 0, vcombat_charlayout, 0, 256 )
|
||||
GFXDECODE_END
|
||||
PORT_START("IN1")
|
||||
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
|
||||
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
|
||||
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 )
|
||||
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START2 )
|
||||
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE )
|
||||
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
static MACHINE_DRIVER_START( vcombat )
|
||||
MDRV_CPU_ADD("main", M68000, XTAL_12MHz)
|
||||
MDRV_CPU_PROGRAM_MAP(main_map,0)
|
||||
//MDRV_CPU_VBLANK_INT("main", irq7_line_hold)
|
||||
MDRV_CPU_VBLANK_INT("main", irq1_line_assert)
|
||||
|
||||
/* The middle board i860 */
|
||||
MDRV_CPU_ADD("vid_0", I860, XTAL_20MHz)
|
||||
@ -235,14 +486,43 @@ static MACHINE_DRIVER_START( vcombat )
|
||||
MDRV_CPU_ADD("vid_1", I860, XTAL_20MHz)
|
||||
MDRV_CPU_PROGRAM_MAP(vid_1_map,0)
|
||||
|
||||
/* Sound CPU Disabled for now */
|
||||
//MDRV_CPU_ADD("sound", M68000, XTAL_12MHz)
|
||||
//MDRV_CPU_PROGRAM_MAP(sound_map,0)
|
||||
/* Sound CPU */
|
||||
MDRV_CPU_ADD("sound", M68000, XTAL_12MHz)
|
||||
MDRV_CPU_PROGRAM_MAP(sound_map,0)
|
||||
|
||||
MDRV_MACHINE_RESET(vcombat)
|
||||
|
||||
// Likely will go away
|
||||
MDRV_GFXDECODE(vcombat)
|
||||
/* Temporary hack for experimenting with timing. */
|
||||
#if 0
|
||||
//MDRV_QUANTUM_TIME(HZ(1200))
|
||||
MDRV_QUANTUM_PERFECT_CPU("main")
|
||||
#endif
|
||||
|
||||
MDRV_SCREEN_ADD("main", RASTER)
|
||||
MDRV_SCREEN_REFRESH_RATE(50)
|
||||
MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
|
||||
MDRV_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
|
||||
MDRV_SCREEN_SIZE(640, 480)
|
||||
MDRV_SCREEN_VISIBLE_AREA(0, 640-1, 0, 480-1)
|
||||
|
||||
MDRV_VIDEO_UPDATE(vcombat)
|
||||
MACHINE_DRIVER_END
|
||||
|
||||
|
||||
static MACHINE_DRIVER_START( shadfgtr )
|
||||
MDRV_CPU_ADD("main", M68000, XTAL_12MHz)
|
||||
MDRV_CPU_PROGRAM_MAP(main_map,0)
|
||||
MDRV_CPU_VBLANK_INT("main", irq1_line_assert)
|
||||
|
||||
/* The middle board i860 */
|
||||
MDRV_CPU_ADD("vid_0", I860, XTAL_20MHz)
|
||||
MDRV_CPU_PROGRAM_MAP(vid_0_map,0)
|
||||
|
||||
/* Sound CPU */
|
||||
MDRV_CPU_ADD("sound", M68000, XTAL_12MHz)
|
||||
MDRV_CPU_PROGRAM_MAP(sound_map,0)
|
||||
|
||||
MDRV_MACHINE_RESET(shadfgtr)
|
||||
|
||||
MDRV_SCREEN_ADD("main", RASTER)
|
||||
MDRV_SCREEN_REFRESH_RATE(60)
|
||||
@ -255,6 +535,9 @@ static MACHINE_DRIVER_START( vcombat )
|
||||
MACHINE_DRIVER_END
|
||||
|
||||
|
||||
/* Perhaps add this to the core romload.h file? */
|
||||
#define ROM_LOAD64_WORD(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_SKIP(6))
|
||||
|
||||
ROM_START( vcombat )
|
||||
ROM_REGION( 0x100000, "main", 0 )
|
||||
ROM_LOAD16_BYTE( "ep8v2.b49", 0x00000, 0x80000, CRC(98d5a45d) SHA1(099e314f11c93ad6e642ceaa311e2a5b6fd7193c) )
|
||||
@ -270,15 +553,15 @@ ROM_START( vcombat )
|
||||
ROM_LOAD16_BYTE( "ep3v2.b40", 0x100000, 0x40000, CRC(8c491526) SHA1(95c6bcbe0adcfffb12fd2b86c9f4ca26aa188bbf) )
|
||||
ROM_LOAD16_BYTE( "ep5v2.b36", 0x100001, 0x40000, CRC(7592b2eb) SHA1(92a540726306d7adbf207fe86a4c4fa66958f90b) )
|
||||
|
||||
ROM_REGION( 0x800, "user1", 0 ) /* The SRAM module */
|
||||
ROM_REGION( 0x800, "user1", 0 ) /* The SRAM module */
|
||||
ROM_LOAD( "ds1220y.b53", 0x000, 0x800, CRC(b21cfe5f) SHA1(898ace3cd0913ea4b0dc84320219777773ef856f) )
|
||||
|
||||
/* These roms are identical on both of the upper boards */
|
||||
ROM_REGION( 0x200000, "3d", 0 )
|
||||
ROM_LOAD16_BYTE( "11.u56", 0x000000, 0x80000, CRC(a83094ce) SHA1(c3512375fecdb5e7eb02a4aa140ae4efe0233cb8) )
|
||||
ROM_LOAD16_BYTE( "9.u54", 0x000001, 0x80000, CRC(a276e18b) SHA1(6d60e519196a4858b82241504592413df498e12f) )
|
||||
ROM_LOAD16_BYTE( "12.u57", 0x100000, 0x80000, CRC(0cdffd4f) SHA1(65ace78711b3ef6e0ff9a7ad7343b5558e652f6c) )
|
||||
ROM_LOAD16_BYTE( "10.u55", 0x100001, 0x80000, CRC(8921f20e) SHA1(6e9ca2eaad3e1108ba0e1d7792fd5d0305bec201) )
|
||||
ROM_REGION( 0x200000, "gfx", 0 )
|
||||
ROM_LOAD64_WORD( "9.u55", 0x000000, 0x80000, CRC(a276e18b) SHA1(6d60e519196a4858b82241504592413df498e12f) )
|
||||
ROM_LOAD64_WORD( "10.u57", 0x000002, 0x80000, CRC(8921f20e) SHA1(6e9ca2eaad3e1108ba0e1d7792fd5d0305bec201) )
|
||||
ROM_LOAD64_WORD( "11.u54", 0x000004, 0x80000, CRC(a83094ce) SHA1(c3512375fecdb5e7eb02a4aa140ae4efe0233cb8) )
|
||||
ROM_LOAD64_WORD( "12.u56", 0x000006, 0x80000, CRC(0cdffd4f) SHA1(65ace78711b3ef6e0ff9a7ad7343b5558e652f6c) )
|
||||
|
||||
ROM_REGION( 0x400, "plds", 0 )
|
||||
ROM_LOAD( "pal1_w2.u51", 0x000, 0x1f1, CRC(af497420) SHA1(03aa82189d91ae194dd5a6e7b9dbdb7cd473ddb6) )
|
||||
@ -301,18 +584,17 @@ ROM_START( shadfgtr )
|
||||
ROM_REGION( 0x800, "user1", 0 ) /* The SRAM module */
|
||||
ROM_LOAD( "shadfgtr.b53", 0x000, 0x800, CRC(e766a3ab) SHA1(e7696ec08d5c86f64d768480f43edbd19ded162d) )
|
||||
|
||||
/* These roms are identical on both of the upper boards */
|
||||
ROM_REGION( 0x200000, "3d", 0 )
|
||||
ROM_LOAD16_BYTE( "shadfgtr.u56", 0x000000, 0x80000, CRC(fb76db5a) SHA1(fa546f465df113c13037abed1162bfa6f9b1dc9b) )
|
||||
ROM_LOAD16_BYTE( "shadfgtr.u54", 0x000001, 0x80000, CRC(c45d68d6) SHA1(a133e4f13d3af18bccf0d060a659d64ac699b159) )
|
||||
ROM_LOAD16_BYTE( "shadfgtr.u57", 0x100000, 0x80000, CRC(60d701d7) SHA1(936473b5e3b2e9e9e3b50cf977fc5a670a097850) )
|
||||
ROM_LOAD16_BYTE( "shadfgtr.u55", 0x100001, 0x80000, CRC(e807631d) SHA1(9027ff7dc60b808434dac292c08f0630d3d52186) )
|
||||
ROM_REGION( 0x200000, "gfx", 0 )
|
||||
ROM_LOAD64_WORD( "shadfgtr.u55", 0x000000, 0x80000, CRC(e807631d) SHA1(9027ff7dc60b808434dac292c08f0630d3d52186) )
|
||||
ROM_LOAD64_WORD( "shadfgtr.u57", 0x000002, 0x80000, CRC(60d701d7) SHA1(936473b5e3b2e9e9e3b50cf977fc5a670a097850) )
|
||||
ROM_LOAD64_WORD( "shadfgtr.u54", 0x000004, 0x80000, CRC(c45d68d6) SHA1(a133e4f13d3af18bccf0d060a659d64ac699b159) )
|
||||
ROM_LOAD64_WORD( "shadfgtr.u56", 0x000006, 0x80000, CRC(fb76db5a) SHA1(fa546f465df113c13037abed1162bfa6f9b1dc9b) )
|
||||
|
||||
ROM_REGION( 0x200, "plds", 0 )
|
||||
ROM_LOAD( "shadfgtr.u51", 0x000, 0x1f1, CRC(bab58337) SHA1(c4a79c8e53aeadb7f64d49d214b607b5b36f144e) )
|
||||
/* The second upper-board PAL couldn't be read */
|
||||
ROM_END
|
||||
|
||||
/* YEAR NAME PARENT MACHINE INPUT INIT MONITOR COMPANY FULLNAME FLAGS */
|
||||
GAME( 1993, vcombat, 0, vcombat, vcombat, vcombat, ROT0, "VR8 Inc.", "Virtual Combat", GAME_NOT_WORKING | GAME_NO_SOUND )
|
||||
GAME( 1989, shadfgtr, 0, vcombat, vcombat, 0, ROT0, "Sega?", "Shadow Fighters", GAME_NOT_WORKING | GAME_NO_SOUND )
|
||||
/* YEAR NAME PARENT MACHINE INPUT INIT MONITOR COMPANY FULLNAME FLAGS */
|
||||
GAME( 1993, vcombat, 0, vcombat, vcombat, vcombat, ORIENTATION_FLIP_X, "VR8 Inc.", "Virtual Combat", GAME_NOT_WORKING | GAME_NO_SOUND )
|
||||
GAME( 1989, shadfgtr, 0, shadfgtr, shadfgtr, shadfgtr, ROT0, "DUTECH Inc.", "Shadow Fighters", GAME_NOT_WORKING | GAME_NO_SOUND )
|
||||
|
@ -8433,7 +8433,7 @@ Other Sun games
|
||||
DRIVER( blazlaz ) /* (c) 1989 Hudson Soft */
|
||||
DRIVER( paranoia ) /* (c) 1990 Naxat Soft */
|
||||
DRIVER( vcombat ) /* (c) 1993 VR8 Inc. */
|
||||
DRIVER( shadfgtr ) /* (c) 1989 Sega? */
|
||||
DRIVER( shadfgtr ) /* (c) 1989 DUTECH Inc. */
|
||||
DRIVER( blackt96 ) /* (c) 1996 D.G.R.M. of Korea */
|
||||
DRIVER( magictg ) /* (c) 199? Acclaim */
|
||||
DRIVER( magictga ) /* (c) 199? Acclaim */
|
||||
|
Loading…
Reference in New Issue
Block a user