Big H8 update

H8:
- Added support for 8-bit H8 family MCUs, starting with the H8/3344
- Pointer-ified all H8 cores
- Some cleanup and renames toward additional future work

System 23:
- Added extremely preliminary support for I/O boards with the H8/3344
- Added new game: Motocross Go! (MG3 Ver. A) [credit Guru]
This commit is contained in:
R. Belmont 2008-11-19 03:29:10 +00:00
parent 13bd16a090
commit 6c1655976f
23 changed files with 5304 additions and 4471 deletions

6
.gitattributes vendored
View File

@ -113,9 +113,11 @@ src/emu/cpu/h6280/h6280.c svneol=native#text/plain
src/emu/cpu/h6280/h6280.h svneol=native#text/plain src/emu/cpu/h6280/h6280.h svneol=native#text/plain
src/emu/cpu/h6280/h6280ops.h svneol=native#text/plain src/emu/cpu/h6280/h6280ops.h svneol=native#text/plain
src/emu/cpu/h6280/tblh6280.c svneol=native#text/plain src/emu/cpu/h6280/tblh6280.c svneol=native#text/plain
src/emu/cpu/h83002/h83002.c svneol=native#text/plain src/emu/cpu/h83002/h8.h svneol=native#text/plain
src/emu/cpu/h83002/h83002.h svneol=native#text/plain src/emu/cpu/h83002/h8_16.c svneol=native#text/plain
src/emu/cpu/h83002/h8_8.c svneol=native#text/plain
src/emu/cpu/h83002/h8disasm.c svneol=native#text/plain src/emu/cpu/h83002/h8disasm.c svneol=native#text/plain
src/emu/cpu/h83002/h8ops.h svneol=native#text/plain
src/emu/cpu/h83002/h8periph.c svneol=native#text/plain src/emu/cpu/h83002/h8periph.c svneol=native#text/plain
src/emu/cpu/h83002/h8priv.h svneol=native#text/plain src/emu/cpu/h83002/h8priv.h svneol=native#text/plain
src/emu/cpu/hd6309/6309dasm.c svneol=native#text/plain src/emu/cpu/hd6309/6309dasm.c svneol=native#text/plain

View File

@ -470,21 +470,21 @@ $(CPUOBJ)/hd6309/hd6309.o: $(CPUSRC)/hd6309/hd6309.c \
$(CPUSRC)/hd6309/6309tbl.c $(CPUSRC)/hd6309/6309tbl.c
#------------------------------------------------- #-------------------------------------------------
# Hitachi H8/3002 # Hitachi H8/30xx (16/32-bit H8/3xx series)
#------------------------------------------------- #-------------------------------------------------
CPUDEFS += -DHAS_H83002=$(if $(filter H83002,$(CPUS)),1,0) CPUDEFS += -DHAS_H83002=$(if $(filter H83002,$(CPUS)),1,0)
ifneq ($(filter H83002,$(CPUS)),) ifneq ($(filter H83002,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/h83002 OBJDIRS += $(CPUOBJ)/h83002
CPUOBJS += $(CPUOBJ)/h83002/h83002.o $(CPUOBJ)/h83002/h8periph.o CPUOBJS += $(CPUOBJ)/h83002/h8_16.o $(CPUOBJ)/h83002/h8periph.o
DBGOBJS += $(CPUOBJ)/h83002/h8disasm.o DBGOBJS += $(CPUOBJ)/h83002/h8disasm.o
endif endif
$(CPUOBJ)/h83002/h83002.o: $(CPUSRC)/h83002/h83002.c \ $(CPUOBJ)/h83002/h8_16.o: $(CPUSRC)/h83002/h8_16.c \
$(CPUSRC)/h83002/h83002.h \ $(CPUSRC)/h83002/h8.h \
$(CPUSRC)/h83002/h8ops.h \
$(CPUSRC)/h83002/h8priv.h $(CPUSRC)/h83002/h8priv.h
$(CPUOBJ)/h83002/h8disasm.o: $(CPUSRC)/h83002/h8disasm.c $(CPUOBJ)/h83002/h8disasm.o: $(CPUSRC)/h83002/h8disasm.c
@ -493,6 +493,28 @@ $(CPUOBJ)/h83002/h8periph.o: $(CPUSRC)/h83002/h8periph.c \
$(CPUSRC)/h83002/h8priv.h $(CPUSRC)/h83002/h8priv.h
#-------------------------------------------------
# Hitachi H8/3344 (8/16-bit H8/3xx series)
#-------------------------------------------------
CPUDEFS += -DHAS_H83344=$(if $(filter H83344,$(CPUS)),1,0)
ifneq ($(filter H83344,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/h83002
CPUOBJS += $(CPUOBJ)/h83002/h8_8.o $(CPUOBJ)/h83002/h8periph.o
DBGOBJS += $(CPUOBJ)/h83002/h8disasm.o
endif
$(CPUOBJ)/h83002/h8_8.o: $(CPUSRC)/h83002/h8_8.c \
$(CPUSRC)/h83002/h8.h \
$(CPUSRC)/h83002/h8ops.h \
$(CPUSRC)/h83002/h8priv.h
$(CPUOBJ)/h83002/h8disasm.o: $(CPUSRC)/h83002/h8disasm.c
$(CPUOBJ)/h83002/h8periph.o: $(CPUSRC)/h83002/h8periph.c \
$(CPUSRC)/h83002/h8priv.h
#------------------------------------------------- #-------------------------------------------------
# Hitachi SH1/SH2 # Hitachi SH1/SH2
#------------------------------------------------- #-------------------------------------------------

View File

@ -35,7 +35,7 @@ enum
H8_CCR H8_CCR
}; };
// external interrupt lines // external input lines
enum enum
{ {
H8_IRQ0 = 0, H8_IRQ0 = 0,
@ -43,20 +43,33 @@ enum
H8_IRQ2, H8_IRQ2,
H8_IRQ3, H8_IRQ3,
H8_IRQ4, H8_IRQ4,
H8_IRQ5 H8_IRQ5,
H8_IRQ6, // IRQs 6+ only available on 8-bit H8/3xx
H8_IRQ7,
H8_NMI,
H8_METRO_TIMER_HACK, // as described. this needs to be fixed.
H8_SCI_0_RX, // incoming character on SCI 0
H8_SCI_1_RX, // incoming character on SCI 1
}; };
// I/O ports // I/O ports
enum enum
{ {
// digital I/O ports // digital I/O ports
H8_PORT4 = 0, // 0 // ports 4-B are valid on 16-bit H8/3xx, ports 1-9 on 8-bit H8/3xx
H8_PORT6, // 1 H8_PORT_1 = 0, // 0
H8_PORT7, // 2 H8_PORT_2, // 1
H8_PORT8, // 3 H8_PORT_3, // 2
H8_PORT9, // 4 H8_PORT_4, // 3
H8_PORTA, // 5 H8_PORT_5, // 4
H8_PORTB, // 6 H8_PORT_6, // 5
H8_PORT_7, // 6
H8_PORT_8, // 7
H8_PORT_9, // 8
H8_PORT_A, // 9
H8_PORT_B, // A
// analog inputs // analog inputs
H8_ADC_0_H = 0x10, H8_ADC_0_H = 0x10,
@ -69,12 +82,12 @@ enum
H8_ADC_3_L, H8_ADC_3_L,
// serial ports // serial ports
H8_SERIAL_A = 0x20, H8_SERIAL_0 = 0x20,
H8_SERIAL_B H8_SERIAL_1,
}; };
CPU_GET_INFO( h8_300 );
CPU_GET_INFO( h8_3002 ); CPU_GET_INFO( h8_3002 );
CPU_GET_INFO( h8_3344 );
void h8_3002_InterruptRequest(UINT8 source);
#endif /* __H83002_H__ */ #endif /* __H83002_H__ */

File diff suppressed because it is too large Load Diff

653
src/emu/cpu/h83002/h8_16.c Normal file
View File

@ -0,0 +1,653 @@
/***************************************************************************
h8_16.c: Hitachi H8/3xx series 16/32-bit microcontroller emulator
Original by The_Author & DynaChicken for the ZiNc emulator.
MAME changes by R. Belmont, Luca Elia, and Tomasz Slanina.
TS 20060412 Added exts.l, sub.l, divxs.w (buggy), jsr @reg, rotxl.l reg, mov.l @(adr, reg), reg
LE 20070903 Added divxu.b shal.l extu.w dec.l #Imm,Rd subx.b
LE 20080202 Separated 3002/3044/3007, Added or.l shal.l rotl.l not.l neg.l exts.w
sub/or/xor.l #Imm:32,ERd bset/bnot/bclr.b Rn,@ERd bst/bist.b #Imm:3,@ERd bnot.b #Imm:3,@ERd
****************************************************************************/
#include "debugger.h"
#include "h8.h"
#include "h8priv.h"
#define H8_SP (7)
#define h8_mem_read8(x) program_read_byte_16be(x)
#define h8_mem_read16(x) program_read_word_16be(x)
#define h8_mem_write8(x, y) program_write_byte_16be(x, y)
#define h8_mem_write16(x, y) program_write_word_16be(x, y)
#define h8_readop16(x) program_decrypted_read_word(x)
// timing macros
// note: we assume a system 12 - type setup where external access is 3+1 states
// timing will be off somewhat for other configurations.
#define H8_IFETCH_TIMING(x) h8->cyccnt -= (x) * 4;
#define H8_BRANCH_TIMING(x) h8->cyccnt -= (x) * 4;
#define H8_STACK_TIMING(x) h8->cyccnt -= (x) * 4;
#define H8_BYTE_TIMING(x, adr) if (address24 >= 0xffff10) h8->cyccnt -= (x) * 3; else h8->cyccnt -= (x) * 4;
#define H8_WORD_TIMING(x, adr) if (address24 >= 0xffff10) h8->cyccnt -= (x) * 3; else h8->cyccnt -= (x) * 4;
#define H8_IOP_TIMING(x) h8->cyccnt -= (x);
INLINE UINT32 h8_mem_read32(offs_t address)
{
UINT32 result = program_read_word_16be(address) << 16;
return result | program_read_word_16be(address + 2);
}
INLINE void h8_mem_write32(offs_t address, UINT32 data)
{
program_write_word_16be(address, data >> 16);
program_write_word_16be(address + 2, data);
}
static void *token;
static void h8_check_irqs(h83xx_state *h8);
/* implementation */
extern offs_t h8_disasm(char *output, offs_t address, const UINT8 *oprom, const UINT8 *opram, UINT32 addr_mask);
// disassembly hook for varients with 24-bit address bus (e.g. H8/3044)
static CPU_DISASSEMBLE(h8_24)
{
return h8_disasm(buffer, pc, oprom, opram, 0xffffff);
}
// disassembly hook for full 32-bit address bus
static CPU_DISASSEMBLE(h8_32)
{
return h8_disasm(buffer, pc, oprom, opram, 0xffffffff);
}
void h8_3002_InterruptRequest(h83xx_state *h8, UINT8 source)
{
if(source>31)
{
h8->h8_IRQrequestH |= (1<<(source-32));
}
else
{
h8->h8_IRQrequestL |= (1<<source);
}
}
static UINT8 h8_get_ccr(h83xx_state *h8)
{
h8->ccr = 0;
if(h8->h8nflag)h8->ccr |= NFLAG;
if(h8->h8zflag)h8->ccr |= ZFLAG;
if(h8->h8vflag)h8->ccr |= VFLAG;
if(h8->h8cflag)h8->ccr |= CFLAG;
if(h8->h8uflag)h8->ccr |= UFLAG;
if(h8->h8hflag)h8->ccr |= HFLAG;
if(h8->h8uiflag)h8->ccr |= UIFLAG;
if(h8->h8iflag)h8->ccr |= IFLAG;
return h8->ccr;
}
static char *h8_get_ccr_str(h83xx_state *h8)
{
static char res[8];
memset(res, 0, 8);
if(h8->h8iflag) strcat(res, "I"); else strcat(res, "i");
if(h8->h8uiflag)strcat(res, "U"); else strcat(res, "u");
if(h8->h8hflag) strcat(res, "H"); else strcat(res, "h");
if(h8->h8uflag) strcat(res, "U"); else strcat(res, "u");
if(h8->h8nflag) strcat(res, "N"); else strcat(res, "n");
if(h8->h8zflag) strcat(res, "Z"); else strcat(res, "z");
if(h8->h8vflag) strcat(res, "V"); else strcat(res, "v");
if(h8->h8cflag) strcat(res, "C"); else strcat(res, "c");
return res;
}
static void h8_set_ccr(h83xx_state *h8, UINT8 data)
{
h8->ccr = data;
h8->h8nflag = 0;
h8->h8zflag = 0;
h8->h8vflag = 0;
h8->h8cflag = 0;
h8->h8hflag = 0;
h8->h8iflag = 0;
h8->h8uflag = 0;
h8->h8uiflag = 0;
if(h8->ccr & NFLAG) h8->h8nflag = 1;
if(h8->ccr & ZFLAG) h8->h8zflag = 1;
if(h8->ccr & VFLAG) h8->h8vflag = 1;
if(h8->ccr & CFLAG) h8->h8cflag = 1;
if(h8->ccr & HFLAG) h8->h8hflag = 1;
if(h8->ccr & UFLAG) h8->h8uflag = 1;
if(h8->ccr & UIFLAG) h8->h8uiflag = 1;
if(h8->ccr & IFLAG) h8->h8iflag = 1;
h8_check_irqs(h8);
}
static INT16 h8_getreg16(h83xx_state *h8, UINT8 reg)
{
if(reg > 7)
{
return h8->regs[reg-8]>>16;
}
else
{
return h8->regs[reg];
}
}
static void h8_setreg16(h83xx_state *h8, UINT8 reg, UINT16 data)
{
if(reg > 7)
{
h8->regs[reg-8] &= 0xffff;
h8->regs[reg-8] |= data<<16;
}
else
{
h8->regs[reg] &= 0xffff0000;
h8->regs[reg] |= data;
}
}
static UINT8 h8_getreg8(h83xx_state *h8, UINT8 reg)
{
if(reg > 7)
{
return h8->regs[reg-8];
}
else
{
return h8->regs[reg]>>8;
}
}
static void h8_setreg8(h83xx_state *h8, UINT8 reg, UINT8 data)
{
if(reg > 7)
{
h8->regs[reg-8] &= 0xffffff00;
h8->regs[reg-8] |= data;
}
else
{
h8->regs[reg] &= 0xffff00ff;
h8->regs[reg] |= data<<8;
}
}
static UINT32 h8_getreg32(h83xx_state *h8, UINT8 reg)
{
return h8->regs[reg];
}
static void h8_setreg32(h83xx_state *h8, UINT8 reg, UINT32 data)
{
h8->regs[reg] = data;
}
static STATE_POSTLOAD( h8_onstateload )
{
h83xx_state *h8 = (h83xx_state *)param;
h8_set_ccr(h8, h8->ccr);
}
static CPU_INIT(h8)
{
h83xx_state *h8 = device->token;
token = device->token;
h8->h8iflag = 1;
h8->irq_cb = irqcallback;
h8->device = device;
h8->h8300_mode = 0;
state_save_register_item("H8/3002", device->tag, 0, h8->h8err);
state_save_register_item_array("H8/3002", device->tag, 0, h8->regs);
state_save_register_item("H8/3002", device->tag, 0, h8->pc);
state_save_register_item("H8/3002", device->tag, 0, h8->ppc);
state_save_register_item("H8/3002", device->tag, 0, h8->h8_IRQrequestH);
state_save_register_item("H8/3002", device->tag, 0, h8->h8_IRQrequestL);
state_save_register_item("H8/3002", device->tag, 0, h8->ccr);
state_save_register_item("H8/3002", device->tag, 0, h8->h8300_mode);
state_save_register_item_array("H8/3002", device->tag, 0, h8->per_regs);
state_save_register_item("H8/3002", device->tag, 0, h8->h8TSTR);
state_save_register_item_array("H8/3002", device->tag, 0, h8->h8TCNT);
state_save_register_postload(device->machine, h8_onstateload, h8);
h8_itu_init(h8);
}
static CPU_INIT(h8_3007)
{
h83xx_state *h8 = device->token;
token = device->token;
CPU_INIT_CALL(h8);
h8_3007_itu_init(h8);
}
static CPU_RESET(h8)
{
h83xx_state *h8 = device->token;
h8->h8err = 0;
h8->pc = h8_mem_read32(0) & 0xffffff;
change_pc(h8->pc);
// disable timers
h8->h8TSTR = 0;
h8_itu_reset(h8);
}
static void h8_GenException(h83xx_state *h8, UINT8 vectornr)
{
// push PC on stack
// extended mode stack push!
h8_setreg32(h8, H8_SP, h8_getreg32(h8, H8_SP)-4);
h8_mem_write32(h8_getreg32(h8, H8_SP), h8->pc);
// push ccr
h8_setreg32(h8, H8_SP, h8_getreg32(h8, H8_SP)-2);
h8_mem_write16(h8_getreg32(h8, H8_SP), h8_get_ccr(h8));
// generate address from vector
h8_set_ccr(h8, h8_get_ccr(h8) | 0x80);
if (h8->h8uiflag == 0)
h8_set_ccr(h8, h8_get_ccr(h8) | 0x40);
h8->pc = h8_mem_read32(vectornr * 4) & 0xffffff;
change_pc(h8->pc);
// I couldn't find timing info for exceptions, so this is a guess (based on JSR/BSR)
H8_IFETCH_TIMING(2);
H8_STACK_TIMING(2);
}
static int h8_get_priority(h83xx_state *h8, UINT8 bit)
{
int res = 0;
switch(bit)
{
case 12: // IRQ0
if (h8->per_regs[0xF8]&0x80) res = 1; break;
case 13: // IRQ1
if (h8->per_regs[0xF8]&0x40) res = 1; break;
case 14: // IRQ2
case 15: // IRQ3
if (h8->per_regs[0xF8]&0x20) res = 1; break;
case 16: // IRQ4
case 17: // IRQ5
if (h8->per_regs[0xF8]&0x10) res = 1; break;
}
return res;
}
static void h8_check_irqs(h83xx_state *h8)
{
int lv = -1;
if (h8->h8iflag == 0)
{
lv = 0;
}
else
{
if ((h8->per_regs[0xF2]&0x08)/*SYSCR*/ == 0)
{
if (h8->h8uiflag == 0)
lv = 1;
}
}
// any interrupts wanted and can accept ?
if(((h8->h8_IRQrequestH != 0) || (h8->h8_IRQrequestL != 0)) && (lv >= 0))
{
UINT8 bit, source;
// which one ?
for(bit = 0, source = 0xff; source == 0xff && bit < 32; bit++)
{
if( h8->h8_IRQrequestL & (1<<bit) )
{
if (h8_get_priority(h8, bit) >= lv)
{
// mask off
h8->h8_IRQrequestL &= ~(1<<bit);
source = bit;
}
}
}
// which one ?
for(bit = 0; source == 0xff && bit < 32; bit++)
{
if( h8->h8_IRQrequestH & (1<<bit) )
{
if (h8_get_priority(h8, bit + 32) >= lv)
{
// mask off
h8->h8_IRQrequestH &= ~(1<<bit);
source = bit + 32;
}
}
}
// call the MAME callback if it's one of the 6
// external IRQs
if (source >= 12 && source <= 17)
{
(*h8->irq_cb)(h8->device, source - 12 + H8_IRQ0);
}
if (source != 0xff)
h8_GenException(h8, source);
}
}
#define H8_ADDR_MASK 0xffffff
#include "h8ops.h"
// MAME interface stuff
static CPU_GET_CONTEXT( h8 )
{
}
static CPU_SET_CONTEXT( h8 )
{
if (src)
{
token = src;
}
}
static CPU_SET_INFO( h8 )
{
h83xx_state *h8 = device->token;
switch(state) {
case CPUINFO_INT_PC: h8->pc = info->i; change_pc(h8->pc); break;
case CPUINFO_INT_REGISTER + H8_PC: h8->pc = info->i; change_pc(h8->pc); break;
case CPUINFO_INT_REGISTER + H8_CCR: h8_set_ccr(h8, info->i); break;
case CPUINFO_INT_REGISTER + H8_E0: h8->regs[0] = info->i; break;
case CPUINFO_INT_REGISTER + H8_E1: h8->regs[1] = info->i; break;
case CPUINFO_INT_REGISTER + H8_E2: h8->regs[2] = info->i; break;
case CPUINFO_INT_REGISTER + H8_E3: h8->regs[3] = info->i; break;
case CPUINFO_INT_REGISTER + H8_E4: h8->regs[4] = info->i; break;
case CPUINFO_INT_REGISTER + H8_E5: h8->regs[5] = info->i; break;
case CPUINFO_INT_REGISTER + H8_E6: h8->regs[6] = info->i; break;
case CPUINFO_INT_REGISTER + H8_E7: h8->regs[7] = info->i; break;
case CPUINFO_INT_INPUT_STATE + H8_IRQ0: if (info->i) h8_3002_InterruptRequest(h8, 12); break;
case CPUINFO_INT_INPUT_STATE + H8_IRQ1: if (info->i) h8_3002_InterruptRequest(h8, 13); break;
case CPUINFO_INT_INPUT_STATE + H8_IRQ2: if (info->i) h8_3002_InterruptRequest(h8, 14); break;
case CPUINFO_INT_INPUT_STATE + H8_IRQ3: if (info->i) h8_3002_InterruptRequest(h8, 15); break;
case CPUINFO_INT_INPUT_STATE + H8_IRQ4: if (info->i) h8_3002_InterruptRequest(h8, 16); break;
case CPUINFO_INT_INPUT_STATE + H8_IRQ5: if (info->i) h8_3002_InterruptRequest(h8, 17); break;
case CPUINFO_INT_INPUT_STATE + H8_METRO_TIMER_HACK: if (info->i) h8_3002_InterruptRequest(h8, 24); break;
case CPUINFO_INT_INPUT_STATE + H8_SCI_0_RX: if (info->i) h8_3002_InterruptRequest(h8, 53); break;
case CPUINFO_INT_INPUT_STATE + H8_SCI_1_RX: if (info->i) h8_3002_InterruptRequest(h8, 57); break;
default:
fatalerror("h8_set_info unknown request %x", state);
break;
}
}
static READ16_HANDLER( h8_itu_r )
{
h83xx_state *h8 = (h83xx_state *)space->cpu->token;
if (mem_mask == 0xffff)
{
// 16-bit read
return h8_register_read8(h8, offset*2 + 0xffff10)<<8 | h8_register_read8(h8, (offset*2) + 1 + 0xffff10);
}
else if (mem_mask == 0xff00)
{
return h8_register_read8(h8, offset*2 + 0xffff10)<<8;
}
else if (mem_mask == 0x00ff)
{
return h8_register_read8(h8, (offset*2) + 1 + 0xffff10);
}
return 0;
}
static WRITE16_HANDLER( h8_itu_w )
{
h83xx_state *h8 = (h83xx_state *)space->cpu->token;
if (mem_mask == 0xffff)
{
// 16-bit write
h8_register_write8(h8, offset*2 + 0xffff10, data>>8);
h8_register_write8(h8, (offset*2) + 1 + 0xffff10, data&0xff);
}
else if (mem_mask == 0xff00)
{
h8_register_write8(h8, offset*2 + 0xffff10, data>>8);
}
else if (mem_mask == 0x00ff)
{
h8_register_write8(h8, (offset*2) + 1 + 0xffff10, data&0xff);
}
}
static READ16_HANDLER( h8_3007_itu_r )
{
h83xx_state *h8 = (h83xx_state *)space->cpu->token;
if (mem_mask == 0xffff)
{
// 16-bit read
return h8_3007_register_read8(h8, offset*2 + 0xffff20)<<8 | h8_3007_register_read8(h8, (offset*2) + 1 + 0xffff20);
}
else if (mem_mask == 0xff00)
{
return h8_3007_register_read8(h8, offset*2 + 0xffff20)<<8;
}
else if (mem_mask == 0x00ff)
{
return h8_3007_register_read8(h8, (offset*2) + 1 + 0xffff20);
}
return 0;
}
static WRITE16_HANDLER( h8_3007_itu_w )
{
h83xx_state *h8 = (h83xx_state *)space->cpu->token;
if (mem_mask == 0xffff)
{
// 16-bit write
h8_3007_register_write8(h8, offset*2 + 0xffff20, data>>8);
h8_3007_register_write8(h8, (offset*2) + 1 + 0xffff20, data&0xff);
}
else if (mem_mask == 0xff00)
{
h8_3007_register_write8(h8, offset*2 + 0xffff20, data>>8);
}
else if (mem_mask == 0x00ff)
{
h8_3007_register_write8(h8, (offset*2) + 1 + 0xffff20, data&0xff);
}
}
static READ16_HANDLER( h8_3007_itu1_r )
{
h83xx_state *h8 = (h83xx_state *)space->cpu->token;
if (mem_mask == 0xffff)
{
// 16-bit read
return h8_3007_register1_read8(h8, offset*2 + 0xfee000)<<8 | h8_3007_register1_read8(h8, (offset*2) + 1 + 0xfee000);
}
else if (mem_mask == 0xff00)
{
return h8_3007_register1_read8(h8, offset*2 + 0xfee000)<<8;
}
else if (mem_mask == 0x00ff)
{
return h8_3007_register1_read8(h8, (offset*2) + 1 + 0xfee000);
}
return 0;
}
static WRITE16_HANDLER( h8_3007_itu1_w )
{
h83xx_state *h8 = (h83xx_state *)space->cpu->token;
if (mem_mask == 0xffff)
{
// 16-bit write
h8_3007_register1_write8(h8, offset*2 + 0xfee000, data>>8);
h8_3007_register1_write8(h8, (offset*2) + 1 + 0xfee000, data&0xff);
}
else if (mem_mask == 0xff00)
{
h8_3007_register1_write8(h8, offset*2 + 0xfee000, data>>8);
}
else if (mem_mask == 0x00ff)
{
h8_3007_register1_write8(h8, (offset*2) + 1 + 0xfee000, data&0xff);
}
}
// On-board RAM and peripherals
static ADDRESS_MAP_START( h8_3002_internal_map, ADDRESS_SPACE_PROGRAM, 16 )
// 512B RAM
AM_RANGE(0xfffd10, 0xffff0f) AM_RAM
AM_RANGE(0xffff10, 0xffffff) AM_READWRITE( h8_itu_r, h8_itu_w )
ADDRESS_MAP_END
static ADDRESS_MAP_START( h8_3044_internal_map, ADDRESS_SPACE_PROGRAM, 16 )
// 32k ROM, 2k RAM
AM_RANGE(0xfff710, 0xffff0f) AM_RAM
AM_RANGE(0xffff1c, 0xffffff) AM_READWRITE( h8_itu_r, h8_itu_w )
ADDRESS_MAP_END
static ADDRESS_MAP_START( h8_3007_internal_map, ADDRESS_SPACE_PROGRAM, 16 )
// ROM-less, 4k RAM
AM_RANGE(0xfee000, 0xfee0ff) AM_READWRITE( h8_3007_itu1_r, h8_3007_itu1_w )
AM_RANGE(0xffef20, 0xffff1f) AM_RAM
AM_RANGE(0xffff20, 0xffffe9) AM_READWRITE( h8_3007_itu_r, h8_3007_itu_w )
ADDRESS_MAP_END
CPU_GET_INFO( h8_3002 )
{
h83xx_state *h8 = (device != NULL) ? device->token : NULL;
switch(state) {
// Interface functions and variables
case CPUINFO_PTR_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(h8); break;
case CPUINFO_PTR_GET_CONTEXT: info->getcontext = CPU_GET_CONTEXT_NAME(h8); break;
case CPUINFO_PTR_SET_CONTEXT: info->setcontext = CPU_SET_CONTEXT_NAME(h8); break;
case CPUINFO_PTR_INIT: info->init = CPU_INIT_NAME(h8); break;
case CPUINFO_PTR_RESET: info->reset = CPU_RESET_NAME(h8); break;
case CPUINFO_PTR_EXIT: info->exit = 0; break;
case CPUINFO_PTR_EXECUTE: info->execute = CPU_EXECUTE_NAME(h8); break;
case CPUINFO_PTR_BURN: info->burn = 0; break;
case CPUINFO_PTR_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(h8_32); break;
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &h8->cyccnt; break;
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(h83xx_state); break;
case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 10; break;
// Bus sizes
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 24; 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 = 8; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
// Internal maps
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(h8_3002_internal_map); break;
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA: info->internal_map16 = NULL; break;
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_IO: info->internal_map16 = NULL; break;
// CPU misc parameters
case CPUINFO_STR_NAME: strcpy(info->s, "H8/3002"); break;
case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
case CPUINFO_STR_FLAGS: strcpy(info->s, h8_get_ccr_str(h8)); break;
case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break;
case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
case CPUINFO_INT_INPUT_LINES: info->i = 16; break;
case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = -1; break;
// CPU main state
case CPUINFO_INT_PC: info->i = h8->pc; break;
case CPUINFO_INT_PREVIOUSPC: info->i = h8->ppc; break;
case CPUINFO_INT_REGISTER + H8_PC: info->i = h8->pc; break;
case CPUINFO_INT_REGISTER + H8_CCR: info->i = h8_get_ccr(h8); break;
case CPUINFO_INT_REGISTER + H8_E0: info->i = h8->regs[0]; break;
case CPUINFO_INT_REGISTER + H8_E1: info->i = h8->regs[1]; break;
case CPUINFO_INT_REGISTER + H8_E2: info->i = h8->regs[2]; break;
case CPUINFO_INT_REGISTER + H8_E3: info->i = h8->regs[3]; break;
case CPUINFO_INT_REGISTER + H8_E4: info->i = h8->regs[4]; break;
case CPUINFO_INT_REGISTER + H8_E5: info->i = h8->regs[5]; break;
case CPUINFO_INT_REGISTER + H8_E6: info->i = h8->regs[6]; break;
case CPUINFO_INT_REGISTER + H8_E7: info->i = h8->regs[7]; break;
// CPU debug stuff
case CPUINFO_STR_REGISTER + H8_PC: sprintf(info->s, "PC :%08x", h8->pc); break;
case CPUINFO_STR_REGISTER + H8_CCR: sprintf(info->s, "CCR :%08x", h8_get_ccr(h8)); break;
case CPUINFO_STR_REGISTER + H8_E0: sprintf(info->s, "ER0 :%08x", h8->regs[0]); break;
case CPUINFO_STR_REGISTER + H8_E1: sprintf(info->s, "ER1 :%08x", h8->regs[1]); break;
case CPUINFO_STR_REGISTER + H8_E2: sprintf(info->s, "ER2 :%08x", h8->regs[2]); break;
case CPUINFO_STR_REGISTER + H8_E3: sprintf(info->s, "ER3 :%08x", h8->regs[3]); break;
case CPUINFO_STR_REGISTER + H8_E4: sprintf(info->s, "ER4 :%08x", h8->regs[4]); break;
case CPUINFO_STR_REGISTER + H8_E5: sprintf(info->s, "ER5 :%08x", h8->regs[5]); break;
case CPUINFO_STR_REGISTER + H8_E6: sprintf(info->s, "ER6 :%08x", h8->regs[6]); break;
case CPUINFO_STR_REGISTER + H8_E7: sprintf(info->s, " SP :%08x", h8->regs[7]); break;
}
}
CPU_GET_INFO( h8_3044 )
{
switch (state)
{
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME(h8_3044_internal_map); break;
case CPUINFO_PTR_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(h8_24); break;
case CPUINFO_STR_NAME: strcpy(info->s, "H8/3044"); break;
default:
CPU_GET_INFO_CALL(h8_3002);
}
}
CPU_GET_INFO( h8_3007 )
{
switch (state)
{
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map16 = address_map_h8_3007_internal_map; break;
case CPUINFO_PTR_INIT: info->init = CPU_INIT_NAME(h8_3007); break;
case CPUINFO_STR_NAME: strcpy(info->s, "H8/3007"); break;
default:
CPU_GET_INFO_CALL(h8_3002);
}
}

603
src/emu/cpu/h83002/h8_8.c Normal file
View File

@ -0,0 +1,603 @@
/***************************************************************************
h8_8.c: Hitachi H8/3xx 8/16-bit microcontroller emulator
Based on H8/300 series 16/32-bit emulator h83002.c.
Reference: Renesas Technology H8/3337 Group Hardware Manual
By R. Belmont
****************************************************************************/
#include "debugger.h"
#include "deprecat.h"
#include "h8.h"
#include "h8priv.h"
#define H8_SP (7)
#define h8_mem_read8(x) program_read_byte_8be(x)
#define h8_mem_write8(x, y) program_write_byte_8be(x, y)
// timing macros
#define H8_IFETCH_TIMING(x) h8->cyccnt -= (x) * 4;
#define H8_BRANCH_TIMING(x) h8->cyccnt -= (x) * 4;
#define H8_STACK_TIMING(x) h8->cyccnt -= (x) * 4;
#define H8_BYTE_TIMING(x, adr) if (address24 >= 0xff90) h8->cyccnt -= (x) * 3; else h8->cyccnt -= (x) * 4;
#define H8_WORD_TIMING(x, adr) if (address24 >= 0xff90) h8->cyccnt -= (x) * 3; else h8->cyccnt -= (x) * 4;
#define H8_IOP_TIMING(x) h8->cyccnt -= (x);
INLINE UINT16 h8_mem_read16(offs_t address)
{
UINT16 result = program_read_byte_8be(address)<<8;
return result | program_read_byte_8be(address+1);
}
INLINE UINT16 h8_readop16(offs_t address)
{
UINT16 result = program_decrypted_read_byte(address)<<8;
return result | program_decrypted_read_byte(address+1);
}
INLINE void h8_mem_write16(offs_t address, UINT16 data)
{
program_write_byte_8be(address, data >> 8);
program_write_byte_8be(address+1, data);
}
INLINE UINT32 h8_mem_read32(offs_t address)
{
UINT32 result = program_read_byte_8be(address) << 24;
result |= program_read_byte_8be(address+1) << 16;
result |= program_read_byte_8be(address+2) << 8;
result |= program_read_byte_8be(address+3);
return result;
}
INLINE void h8_mem_write32(offs_t address, UINT32 data)
{
program_write_byte_8be(address, data >> 24);
program_write_byte_8be(address+1, data >> 16);
program_write_byte_8be(address+2, data >> 8);
program_write_byte_8be(address+3, data);
}
static void *token;
static void h8_check_irqs(h83xx_state *h8);
/* implementation */
extern offs_t h8_disasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 addrmask);
static CPU_DISASSEMBLE(h8)
{
return h8_disasm(buffer, pc, oprom, opram, 0xffff);
}
void h8_300_InterruptRequest(h83xx_state *h8, UINT8 source)
{
if(source>31)
{
h8->h8_IRQrequestH |= (1<<(source-32));
}
else
{
h8->h8_IRQrequestL |= (1<<source);
}
}
static UINT8 h8_get_ccr(h83xx_state *h8)
{
h8->ccr = 0;
if(h8->h8nflag)h8->ccr |= NFLAG;
if(h8->h8zflag)h8->ccr |= ZFLAG;
if(h8->h8vflag)h8->ccr |= VFLAG;
if(h8->h8cflag)h8->ccr |= CFLAG;
if(h8->h8uflag)h8->ccr |= UFLAG;
if(h8->h8hflag)h8->ccr |= HFLAG;
if(h8->h8uiflag)h8->ccr |= UIFLAG;
if(h8->h8iflag)h8->ccr |= IFLAG;
return h8->ccr;
}
static char *h8_get_ccr_str(h83xx_state *h8)
{
static char res[8];
memset(res, 0, 8);
if(h8->h8iflag) strcat(res, "I"); else strcat(res, "i");
if(h8->h8uiflag)strcat(res, "U"); else strcat(res, "u");
if(h8->h8hflag) strcat(res, "H"); else strcat(res, "h");
if(h8->h8uflag) strcat(res, "U"); else strcat(res, "u");
if(h8->h8nflag) strcat(res, "N"); else strcat(res, "n");
if(h8->h8zflag) strcat(res, "Z"); else strcat(res, "z");
if(h8->h8vflag) strcat(res, "V"); else strcat(res, "v");
if(h8->h8cflag) strcat(res, "C"); else strcat(res, "c");
return res;
}
static void h8_set_ccr(h83xx_state *h8, UINT8 data)
{
h8->ccr = data;
h8->h8nflag = 0;
h8->h8zflag = 0;
h8->h8vflag = 0;
h8->h8cflag = 0;
h8->h8hflag = 0;
h8->h8iflag = 0;
h8->h8uflag = 0;
h8->h8uiflag = 0;
if(h8->ccr & NFLAG) h8->h8nflag = 1;
if(h8->ccr & ZFLAG) h8->h8zflag = 1;
if(h8->ccr & VFLAG) h8->h8vflag = 1;
if(h8->ccr & CFLAG) h8->h8cflag = 1;
if(h8->ccr & HFLAG) h8->h8hflag = 1;
if(h8->ccr & UFLAG) h8->h8uflag = 1;
if(h8->ccr & UIFLAG) h8->h8uiflag = 1;
if(h8->ccr & IFLAG) h8->h8iflag = 1;
h8_check_irqs(h8);
}
static INT16 h8_getreg16(h83xx_state *h8, UINT8 reg)
{
if(reg > 7)
{
return h8->regs[reg-8]>>16;
}
else
{
return h8->regs[reg];
}
}
static void h8_setreg16(h83xx_state *h8, UINT8 reg, UINT16 data)
{
if(reg > 7)
{
h8->regs[reg-8] &= 0xffff;
h8->regs[reg-8] |= data<<16;
}
else
{
h8->regs[reg] &= 0xffff0000;
h8->regs[reg] |= data;
}
}
static UINT8 h8_getreg8(h83xx_state *h8, UINT8 reg)
{
if(reg > 7)
{
return h8->regs[reg-8];
}
else
{
return h8->regs[reg]>>8;
}
}
static void h8_setreg8(h83xx_state *h8, UINT8 reg, UINT8 data)
{
if(reg > 7)
{
h8->regs[reg-8] &= 0xffffff00;
h8->regs[reg-8] |= data;
}
else
{
h8->regs[reg] &= 0xffff00ff;
h8->regs[reg] |= data<<8;
}
}
static UINT32 h8_getreg32(h83xx_state *h8, UINT8 reg)
{
return h8->regs[reg];
}
static void h8_setreg32(h83xx_state *h8, UINT8 reg, UINT32 data)
{
h8->regs[reg] = data;
}
static STATE_POSTLOAD( h8_onstateload )
{
h83xx_state *h8 = (h83xx_state *)param;
h8_set_ccr(h8, h8->ccr);
}
static CPU_INIT(h8bit)
{
h83xx_state *h8 = device->token;
h8->h8iflag = 1;
h8->irq_cb = irqcallback;
h8->device = device;
h8->h8300_mode = 1;
state_save_register_item("H8/300", device->tag, 0, h8->h8err);
state_save_register_item_array("H8/300", device->tag, 0, h8->regs);
state_save_register_item("H8/300", device->tag, 0, h8->pc);
state_save_register_item("H8/300", device->tag, 0, h8->ppc);
state_save_register_item("H8/300", device->tag, 0, h8->h8_IRQrequestH);
state_save_register_item("H8/300", device->tag, 0, h8->h8_IRQrequestL);
state_save_register_item("H8/300", device->tag, 0, h8->ccr);
state_save_register_item("H8/300", device->tag, 0, h8->h8300_mode);
state_save_register_item_array("H8/300", device->tag, 0, h8->per_regs);
state_save_register_item("H8/300", device->tag, 0, h8->h8TSTR);
state_save_register_item_array("H8/300", device->tag, 0, h8->h8TCNT);
state_save_register_postload(Machine, h8_onstateload, h8);
}
static CPU_RESET(h8bit)
{
h83xx_state *h8 = device->token;
h8->h8err = 0;
h8->pc = h8_mem_read16(0);
change_pc(h8->pc);
// disable timers
h8->h8TSTR = 0;
}
static void h8_GenException(h83xx_state *h8, UINT8 vectornr)
{
// push PC on stack
h8_setreg16(h8, H8_SP, h8_getreg16(h8, H8_SP)-2);
h8_mem_write16(h8_getreg16(h8, H8_SP), h8->pc);
// push ccr
h8_setreg16(h8, H8_SP, h8_getreg16(h8, H8_SP)-2);
h8_mem_write16(h8_getreg16(h8, H8_SP), h8_get_ccr(h8));
// generate address from vector
h8_set_ccr(h8, h8_get_ccr(h8) | 0x80);
if (h8->h8uiflag == 0)
h8_set_ccr(h8, h8_get_ccr(h8) | 0x40);
h8->pc = h8_mem_read16(vectornr * 2) & 0xffff;
change_pc(h8->pc);
// I couldn't find timing info for exceptions, so this is a guess (based on JSR/BSR)
H8_IFETCH_TIMING(2);
H8_STACK_TIMING(2);
}
static int h8_get_priority(h83xx_state *h8, UINT8 bit)
{
int res = 0;
switch(bit)
{
case 12: // IRQ0
if (h8->per_regs[0xF8]&0x80) res = 1; break;
case 13: // IRQ1
if (h8->per_regs[0xF8]&0x40) res = 1; break;
case 14: // IRQ2
case 15: // IRQ3
if (h8->per_regs[0xF8]&0x20) res = 1; break;
case 16: // IRQ4
case 17: // IRQ5
if (h8->per_regs[0xF8]&0x10) res = 1; break;
}
return res;
}
static void h8_check_irqs(h83xx_state *h8)
{
int lv = -1;
if (h8->h8iflag == 0)
{
lv = 0;
}
// any interrupts wanted and can accept ?
if(((h8->h8_IRQrequestH != 0) || (h8->h8_IRQrequestL != 0)) && (lv >= 0))
{
UINT8 bit, source;
// which one ?
for(bit = 0, source = 0xff; source == 0xff && bit < 32; bit++)
{
if( h8->h8_IRQrequestL & (1<<bit) )
{
if (h8_get_priority(h8, bit) >= lv)
{
// mask off
h8->h8_IRQrequestL &= ~(1<<bit);
source = bit;
}
}
}
// which one ?
for(bit = 0; source == 0xff && bit < 32; bit++)
{
if( h8->h8_IRQrequestH & (1<<bit) )
{
if (h8_get_priority(h8, bit + 32) >= lv)
{
// mask off
h8->h8_IRQrequestH &= ~(1<<bit);
source = bit + 32;
}
}
}
// call the MAME callback if it's one of the external IRQs
if (source >= 3 && source <= 11)
{
(*h8->irq_cb)(h8->device, source - 3 + H8_NMI);
}
if (source != 0xff)
{
h8_GenException(h8, source);
}
}
}
#define H8_ADDR_MASK 0xffff
#include "h8ops.h"
// MAME interface stuff
static CPU_GET_CONTEXT( h8 )
{
}
static CPU_SET_CONTEXT( h8 )
{
if (src)
{
token = src;
}
}
static CPU_SET_INFO( h8 )
{
h83xx_state *h8 = device->token;
switch(state) {
case CPUINFO_INT_PC: h8->pc = info->i; change_pc(h8->pc); break;
case CPUINFO_INT_REGISTER + H8_PC: h8->pc = info->i; change_pc(h8->pc); break;
case CPUINFO_INT_REGISTER + H8_CCR: h8_set_ccr(h8, info->i); break;
case CPUINFO_INT_REGISTER + H8_E0: h8->regs[0] = info->i; break;
case CPUINFO_INT_REGISTER + H8_E1: h8->regs[1] = info->i; break;
case CPUINFO_INT_REGISTER + H8_E2: h8->regs[2] = info->i; break;
case CPUINFO_INT_REGISTER + H8_E3: h8->regs[3] = info->i; break;
case CPUINFO_INT_REGISTER + H8_E4: h8->regs[4] = info->i; break;
case CPUINFO_INT_REGISTER + H8_E5: h8->regs[5] = info->i; break;
case CPUINFO_INT_REGISTER + H8_E6: h8->regs[6] = info->i; break;
case CPUINFO_INT_REGISTER + H8_E7: h8->regs[7] = info->i; break;
case CPUINFO_INT_INPUT_STATE + H8_NMI: if (info->i) h8_300_InterruptRequest(h8, 3); break;
case CPUINFO_INT_INPUT_STATE + H8_IRQ0: if (info->i) h8_300_InterruptRequest(h8, 4); break;
case CPUINFO_INT_INPUT_STATE + H8_IRQ1: if (info->i) h8_300_InterruptRequest(h8, 5); break;
case CPUINFO_INT_INPUT_STATE + H8_IRQ2: if (info->i) h8_300_InterruptRequest(h8, 6); break;
case CPUINFO_INT_INPUT_STATE + H8_IRQ3: if (info->i) h8_300_InterruptRequest(h8, 7); break;
case CPUINFO_INT_INPUT_STATE + H8_IRQ4: if (info->i) h8_300_InterruptRequest(h8, 8); break;
case CPUINFO_INT_INPUT_STATE + H8_IRQ5: if (info->i) h8_300_InterruptRequest(h8, 9); break;
case CPUINFO_INT_INPUT_STATE + H8_IRQ6: if (info->i) h8_300_InterruptRequest(h8, 10); break;
case CPUINFO_INT_INPUT_STATE + H8_IRQ7: if (info->i) h8_300_InterruptRequest(h8, 11); break;
case CPUINFO_INT_INPUT_STATE + H8_SCI_0_RX: if (info->i) h8_300_InterruptRequest(h8, 28); break;
case CPUINFO_INT_INPUT_STATE + H8_SCI_1_RX: if (info->i) h8_300_InterruptRequest(h8, 32); break;
default:
fatalerror("h8_set_info unknown request %x", state);
break;
}
}
static READ8_HANDLER( h8330_itu_r )
{
UINT8 val;
UINT8 reg;
h83xx_state *h8 = (h83xx_state *)space->cpu->token;
reg = (offset + 0x88) & 0xff;
switch(reg)
{
case 0x8d: // serial Rx 1
val = io_read_byte(H8_SERIAL_1);
break;
case 0xb2: // port 1 data
val = io_read_byte(H8_PORT_1);
break;
case 0xb3: // port 2 data
val = io_read_byte(H8_PORT_2);
break;
case 0xb6: // port 3 data
val = io_read_byte(H8_PORT_3);
break;
case 0xb7: // port 4 data
val = io_read_byte(H8_PORT_4);
break;
case 0xba: // port 5 data
val = io_read_byte(H8_PORT_5);
break;
case 0xbb: // port 6 data
val = io_read_byte(H8_PORT_6);
break;
case 0xbe: // port 7 data
val = io_read_byte(H8_PORT_7);
break;
case 0xbf: // port 8 data
val = io_read_byte(H8_PORT_8);
break;
case 0xc1: // port 9 data
val = io_read_byte(H8_PORT_9);
break;
case 0xdc: // serial status
val = 0x87;
break;
case 0xdd: // serial Rx 0
val = io_read_byte(H8_SERIAL_0);
break;
default:
val = h8->per_regs[reg];
break;
}
return val;
}
static WRITE8_HANDLER( h8330_itu_w )
{
UINT8 reg;
h83xx_state *h8 = (h83xx_state *)space->cpu->token;
reg = (offset + 0x88) & 0xff;
switch (reg)
{
case 0x8b: // serial Tx 1
io_write_byte(H8_SERIAL_1, data);
break;
case 0xb2: // port 1 data
io_write_byte(H8_PORT_1, data);
break;
case 0xb3: // port 2 data
io_write_byte(H8_PORT_2, data);
break;
case 0xb6: // port 3 data
io_write_byte(H8_PORT_3, data);
break;
case 0xb7: // port 4 data
io_write_byte(H8_PORT_4, data);
break;
case 0xba: // port 5 data
io_write_byte(H8_PORT_5, data);
break;
case 0xbb: // port 6 data
io_write_byte(H8_PORT_6, data);
break;
case 0xbe: // port 7 data
io_write_byte(H8_PORT_7, data);
break;
case 0xbf: // port 8 data
io_write_byte(H8_PORT_8, data);
break;
case 0xc1: // port 9 data
io_write_byte(H8_PORT_9, data);
break;
case 0xdb: // serial Tx 0
io_write_byte(H8_SERIAL_0, data);
break;
case 0xd8:
case 0xda:
case 0xdc:
case 0xd9:
break;
case 0x88:
case 0x8a:
case 0x8c:
case 0x89:
break;
case 0xc3:
break;
case 0xc7:
break;
}
h8->per_regs[reg] = data;
}
static ADDRESS_MAP_START( h8_3344_internal_map, ADDRESS_SPACE_PROGRAM, 8 )
// 512B RAM
AM_RANGE(0xfb80, 0xff7f) AM_RAM
AM_RANGE(0xff88, 0xffff) AM_READWRITE( h8330_itu_r, h8330_itu_w )
ADDRESS_MAP_END
CPU_GET_INFO( h8_3344 )
{
h83xx_state *h8 = (device != NULL) ? device->token : NULL;
switch(state) {
// Interface functions and variables
case CPUINFO_PTR_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(h8); break;
case CPUINFO_PTR_GET_CONTEXT: info->getcontext = CPU_GET_CONTEXT_NAME(h8); break;
case CPUINFO_PTR_SET_CONTEXT: info->setcontext = CPU_SET_CONTEXT_NAME(h8); break;
case CPUINFO_PTR_INIT: info->init = CPU_INIT_NAME(h8bit); break;
case CPUINFO_PTR_RESET: info->reset = CPU_RESET_NAME(h8bit); break;
case CPUINFO_PTR_EXIT: info->exit = 0; break;
case CPUINFO_PTR_EXECUTE: info->execute = CPU_EXECUTE_NAME(h8); break;
case CPUINFO_PTR_BURN: info->burn = 0; break;
case CPUINFO_PTR_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(h8); break;
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &h8->cyccnt; break;
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(h83xx_state); break;
case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 10; break;
// Bus sizes
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 8; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; 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 = 8; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
// Internal maps
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map8 = address_map_h8_3344_internal_map; break;
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_DATA: info->internal_map8 = NULL; break;
case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_IO: info->internal_map16 = NULL; break;
// CPU misc parameters
case CPUINFO_STR_NAME: strcpy(info->s, "H8/3344"); break;
case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
case CPUINFO_STR_FLAGS: strcpy(info->s, h8_get_ccr_str(h8)); break;
case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break;
case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
case CPUINFO_INT_INPUT_LINES: info->i = 16; break;
case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = -1; break;
// CPU main state
case CPUINFO_INT_PC: info->i = h8->pc; break;
case CPUINFO_INT_PREVIOUSPC: info->i = h8->ppc; break;
case CPUINFO_INT_REGISTER + H8_PC: info->i = h8->pc; break;
case CPUINFO_INT_REGISTER + H8_CCR: info->i = h8_get_ccr(h8); break;
case CPUINFO_INT_REGISTER + H8_E0: info->i = h8->regs[0]; break;
case CPUINFO_INT_REGISTER + H8_E1: info->i = h8->regs[1]; break;
case CPUINFO_INT_REGISTER + H8_E2: info->i = h8->regs[2]; break;
case CPUINFO_INT_REGISTER + H8_E3: info->i = h8->regs[3]; break;
case CPUINFO_INT_REGISTER + H8_E4: info->i = h8->regs[4]; break;
case CPUINFO_INT_REGISTER + H8_E5: info->i = h8->regs[5]; break;
case CPUINFO_INT_REGISTER + H8_E6: info->i = h8->regs[6]; break;
case CPUINFO_INT_REGISTER + H8_E7: info->i = h8->regs[7]; break;
// CPU debug stuff
case CPUINFO_STR_REGISTER + H8_PC: sprintf(info->s, "PC :%08x", h8->pc); break;
case CPUINFO_STR_REGISTER + H8_CCR: sprintf(info->s, "CCR :%08x", h8_get_ccr(h8)); break;
case CPUINFO_STR_REGISTER + H8_E0: sprintf(info->s, " R0 :%08x", h8->regs[0]); break;
case CPUINFO_STR_REGISTER + H8_E1: sprintf(info->s, " R1 :%08x", h8->regs[1]); break;
case CPUINFO_STR_REGISTER + H8_E2: sprintf(info->s, " R2 :%08x", h8->regs[2]); break;
case CPUINFO_STR_REGISTER + H8_E3: sprintf(info->s, " R3 :%08x", h8->regs[3]); break;
case CPUINFO_STR_REGISTER + H8_E4: sprintf(info->s, " R4 :%08x", h8->regs[4]); break;
case CPUINFO_STR_REGISTER + H8_E5: sprintf(info->s, " R5 :%08x", h8->regs[5]); break;
case CPUINFO_STR_REGISTER + H8_E6: sprintf(info->s, " R6 :%08x", h8->regs[6]); break;
case CPUINFO_STR_REGISTER + H8_E7: sprintf(info->s, " SP :%08x", h8->regs[7]); break;
}
}

View File

@ -1,6 +1,6 @@
/*************************************************************************** /***************************************************************************
h8disasm.c: Hitachi H8/3000 series disassembler h8disasm.c: Hitachi H8/3xx series disassembler
Original by The_Author & DynaChicken for the ZiNc emulator. Original by The_Author & DynaChicken for the ZiNc emulator.
@ -9,7 +9,7 @@
****************************************************************************/ ****************************************************************************/
#include "debugger.h" #include "debugger.h"
#include "h83002.h" #include "h8.h"
static const char *const bit_instr[8] = {"bset", "bnot", "bclr", "btst", "bor", "bxor", "band", "bld"}; static const char *const bit_instr[8] = {"bset", "bnot", "bclr", "btst", "bor", "bxor", "band", "bld"};
static const char *const bit_instr2[8] = {"bset", "bnot", "bclr", "btst", "bior", "bixor", "biand", "bild"}; static const char *const bit_instr2[8] = {"bset", "bnot", "bclr", "btst", "bior", "bixor", "biand", "bild"};
@ -20,16 +20,16 @@ static const char *const reg_names32[8] = {"ER0", "ER1", "ER2", "ER3", "ER4", "
static const char *const reg_names16[16] = {"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7"}; static const char *const reg_names16[16] = {"R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7"};
static const char *const reg_names8[16] = {"R0H", "R1H", "R2H", "R3H", "R4H", "R5H", "R6H", "R7H","R0L", "R1L", "R2L", "R3L", "R4L", "R5L", "R6L", "R7L"}; static const char *const reg_names8[16] = {"R0H", "R1H", "R2H", "R3H", "R4H", "R5H", "R6H", "R7H","R0L", "R1L", "R2L", "R3L", "R4L", "R5L", "R6L", "R7L"};
static UINT32 h8disasm_0(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *oprom); static UINT32 h8disasm_0(UINT32 address, UINT32 opcode, char *output, const UINT8 *oprom);
static UINT32 h8disasm_1(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *oprom); static UINT32 h8disasm_1(UINT32 address, UINT32 opcode, char *output, const UINT8 *oprom);
static UINT32 h8disasm_5(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *oprom); static UINT32 h8disasm_5(UINT32 address, UINT32 opcode, char *output, const UINT8 *oprom);
static UINT32 h8disasm_6(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *oprom); static UINT32 h8disasm_6(UINT32 address, UINT32 opcode, char *output, const UINT8 *oprom, UINT32 addr_mask);
static UINT32 h8disasm_7(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *oprom); static UINT32 h8disasm_7(UINT32 address, UINT32 opcode, char *output, const UINT8 *oprom, UINT32 addr_mask);
#define h8_mem_read16(x) ((oprom[x] << 8) | oprom[(x) + 1]) #define h8_mem_read16(x) ((oprom[x] << 8) | oprom[(x) + 1])
#define h8_mem_read32(x) ((oprom[x] << 24) | (oprom[(x) + 1] << 16) | (oprom[(x) + 2] << 8) | oprom[(x) + 3]) #define h8_mem_read32(x) ((oprom[x] << 24) | (oprom[(x) + 1] << 16) | (oprom[(x) + 2] << 8) | oprom[(x) + 3])
CPU_DISASSEMBLE( h8 ) offs_t h8_disasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 addr_mask)
{ {
UINT32 size = 0; UINT32 size = 0;
UINT16 opcode; UINT16 opcode;
@ -46,18 +46,18 @@ CPU_DISASSEMBLE( h8 )
break; break;
// mov.b @xx:8, Rd (abs) // mov.b @xx:8, Rd (abs)
case 0x2: case 0x2:
sprintf(buffer, "%4.4x mov.b @%8.8x, %s", opcode, 0xffff00 | (opcode & 0xff), reg_names8[(opcode>>8) & 0xf]); sprintf(buffer, "%4.4x mov.b @%8.8x, %s", opcode, (0xffff00 | (opcode & 0xff))&addr_mask, reg_names8[(opcode>>8) & 0xf]);
size = 2; size = 2;
break; break;
// mov.b Rs, @xx:8 (abs) // mov.b Rs, @xx:8 (abs)
case 0x3: case 0x3:
sprintf(buffer, "%4.4x mov.b %s, @%8.8x", opcode, reg_names8[(opcode>>8) & 0xf], 0xfffff00 | (opcode & 0xff)); sprintf(buffer, "%4.4x mov.b %s, @%8.8x", opcode, reg_names8[(opcode>>8) & 0xf], (0xfffff00 | (opcode & 0xff))&addr_mask);
size = 2; size = 2;
break; break;
// bcc @xx:8 // bcc @xx:8
case 0x4: case 0x4:
pc += 2; pc += 2;
sprintf(buffer, "%4.4x %s %8.8x", opcode, branch_instr[(opcode >> 8) & 0xf], pc + (INT8)(opcode &0xff)); sprintf(buffer, "%4.4x %s %8.8x", opcode, branch_instr[(opcode >> 8) & 0xf], (pc + (INT8)(opcode &0xff))&addr_mask);
size = 2; size = 2;
break; break;
// group 5 // group 5
@ -65,10 +65,10 @@ CPU_DISASSEMBLE( h8 )
size = h8disasm_5(pc, opcode, buffer, oprom); size = h8disasm_5(pc, opcode, buffer, oprom);
break; break;
case 0x6: case 0x6:
size = h8disasm_6(pc, opcode, buffer, oprom); size = h8disasm_6(pc, opcode, buffer, oprom, addr_mask);
break; break;
case 0x7: case 0x7:
size = h8disasm_7(pc, opcode, buffer, oprom); size = h8disasm_7(pc, opcode, buffer, oprom, addr_mask);
break; break;
case 0x8: case 0x8:
// add.b #xx:8, Rd // add.b #xx:8, Rd
@ -930,7 +930,7 @@ static UINT32 h8disasm_5(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *op
return size; return size;
} }
static UINT32 h8disasm_6(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *oprom) static UINT32 h8disasm_6(UINT32 address, UINT32 opcode, char *buffer, const UINT8 *oprom, UINT32 addr_mask)
{ {
UINT32 size = 2; UINT32 size = 2;
UINT32 data32; UINT32 data32;
@ -1011,17 +1011,17 @@ static UINT32 h8disasm_6(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *op
break; break;
case 0x2: case 0x2:
data32=h8_mem_read32(2); data32=h8_mem_read32(2);
sprintf(buffer, "%4.4x mov.b @%8.8x, %s", opcode, data32, reg_names8[opcode & 0xf]); sprintf(buffer, "%4.4x mov.b @%8.8x, %s", opcode, data32&addr_mask, reg_names8[opcode & 0xf]);
size = 6; size = 6;
break; break;
case 0x8: case 0x8:
data16=h8_mem_read16(2); data16=h8_mem_read16(2);
sprintf(buffer, "%4.4x mov.b %s, @%8.8x", opcode, reg_names8[opcode & 0xf], data16); sprintf(buffer, "%4.4x mov.b %s, @%8.8x", opcode, reg_names8[opcode & 0xf], data16&addr_mask);
size = 4; size = 4;
break; break;
case 0xa: case 0xa:
data32=h8_mem_read32(2); data32=h8_mem_read32(2);
sprintf(buffer, "%4.4x mov.b %s, @%8.8x", opcode, reg_names8[opcode & 0xf], data32); sprintf(buffer, "%4.4x mov.b %s, @%8.8x", opcode, reg_names8[opcode & 0xf], data32&addr_mask);
size = 6; size = 6;
break; break;
default: default:
@ -1036,22 +1036,22 @@ static UINT32 h8disasm_6(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *op
{ {
case 0x0: case 0x0:
data16=h8_mem_read16(2); data16=h8_mem_read16(2);
sprintf(buffer, "%4.4x mov.w @%8.8x, %s", opcode, data16, reg_names16[opcode & 0xf]); sprintf(buffer, "%4.4x mov.w @%8.8x, %s", opcode, data16&addr_mask, reg_names16[opcode & 0xf]);
size = 4; size = 4;
break; break;
case 0x2: case 0x2:
data32=h8_mem_read32(2); data32=h8_mem_read32(2);
sprintf(buffer, "%4.4x mov.w @%8.8x, %s", opcode, data32, reg_names16[opcode & 0xf]); sprintf(buffer, "%4.4x mov.w @%8.8x, %s", opcode, data32&addr_mask, reg_names16[opcode & 0xf]);
size = 6; size = 6;
break; break;
case 0x8: case 0x8:
data16=h8_mem_read16(2); data16=h8_mem_read16(2);
sprintf(buffer, "%4.4x mov.w %s, @%8.8x", opcode, reg_names16[opcode & 0xf], data16); sprintf(buffer, "%4.4x mov.w %s, @%8.8x", opcode, reg_names16[opcode & 0xf], data16&addr_mask);
size = 4; size = 4;
break; break;
case 0xa: case 0xa:
data32=h8_mem_read32(2); data32=h8_mem_read32(2);
sprintf(buffer, "%4.4x mov.w %s, @%8.8x", opcode, reg_names16[opcode & 0xf], data32); sprintf(buffer, "%4.4x mov.w %s, @%8.8x", opcode, reg_names16[opcode & 0xf], data32&addr_mask);
size = 6; size = 6;
break; break;
default: default:
@ -1092,7 +1092,7 @@ static UINT32 h8disasm_6(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *op
sprintf(buffer, "%4.4x mov.b %s,@(%x, %s)", opcode, reg_names8[opcode &0xf], data16, reg_names32[(opcode>>4)&7]); sprintf(buffer, "%4.4x mov.b %s,@(%x, %s)", opcode, reg_names8[opcode &0xf], data16, reg_names32[(opcode>>4)&7]);
} }
else else
{ {
sprintf(buffer, "%4.4x mov.b @(%x, %s), %s", opcode, data16, reg_names32[(opcode>>4)&7], reg_names8[opcode &0xf]); sprintf(buffer, "%4.4x mov.b @(%x, %s), %s", opcode, data16, reg_names32[(opcode>>4)&7], reg_names8[opcode &0xf]);
} }
size = 4; size = 4;
@ -1117,7 +1117,7 @@ static UINT32 h8disasm_6(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *op
return size; return size;
} }
static UINT32 h8disasm_7(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *oprom) static UINT32 h8disasm_7(UINT32 address, UINT32 opcode, char *buffer, const UINT8 *oprom, UINT32 addr_mask)
{ {
UINT32 size = 2; UINT32 size = 2;
UINT32 data32; UINT32 data32;
@ -1255,11 +1255,11 @@ static UINT32 h8disasm_7(UINT32 pc, UINT32 opcode, char *buffer, const UINT8 *op
data16 = h8_mem_read16(2); data16 = h8_mem_read16(2);
if(((data16>>4)&0x8) == 0) if(((data16>>4)&0x8) == 0)
{ {
sprintf(buffer, "%4.4x %4.4x %s.b #%1.1x, @%x", opcode, data16, bit_instr[(data16>>8)&7], (data16>>4)&7, 0xffffff00 + (opcode & 0xff)); sprintf(buffer, "%4.4x %4.4x %s.b #%1.1x, @%x", opcode, data16, bit_instr[(data16>>8)&7], (data16>>4)&7, (0xffffff00 + (opcode & 0xff))&addr_mask);
} }
else else
{ {
sprintf(buffer, "%4.4x %4.4x %s.b #%1.1x, @%x", opcode, data16, bit_instr2[(data16>>8)&7], (data16>>4)&7, 0xffffff00 + (opcode & 0xff)); sprintf(buffer, "%4.4x %4.4x %s.b #%1.1x, @%x", opcode, data16, bit_instr2[(data16>>8)&7], (data16>>4)&7, (0xffffff00 + (opcode & 0xff))&addr_mask);
} }
size = 4; size = 4;
break; break;

3551
src/emu/cpu/h83002/h8ops.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -11,7 +11,7 @@
#include "debugger.h" #include "debugger.h"
#include "deprecat.h" #include "deprecat.h"
#include "cpuexec.h" #include "cpuexec.h"
#include "h83002.h" #include "h8.h"
#include "h8priv.h" #include "h8priv.h"
#define H8_REG_START (0x00ffff10) #define H8_REG_START (0x00ffff10)
@ -39,99 +39,135 @@ static const UINT8 tier[5] = { TIER0, TIER1, TIER2, TIER3, TIER4 };
static const UINT8 tcr[5] = { TCR0, TCR1, TCR2, TCR3, TCR4 }; static const UINT8 tcr[5] = { TCR0, TCR1, TCR2, TCR3, TCR4 };
static const int tscales[4] = { 1, 2, 4, 8 }; static const int tscales[4] = { 1, 2, 4, 8 };
static TIMER_CALLBACK( h8itu_timer_cb ) extern void h8_3002_InterruptRequest(h83xx_state *h8, UINT8 source);
{ extern void *h8_token;
int which = (int)(FPTR)ptr; static void h8itu_timer_expire(h83xx_state *h8, int which)
timer_adjust_oneshot(h8.timer[which], attotime_never, 0); {
h8.h8TCNT[which] = 0; timer_adjust_oneshot(h8->timer[which], attotime_never, 0);
h8.per_regs[tsr[which]] |= 4; h8->h8TCNT[which] = 0;
h8->per_regs[tsr[which]] |= 4;
// interrupt on overflow ? // interrupt on overflow ?
if(h8.per_regs[tier[which]] & 4) if(h8->per_regs[tier[which]] & 4)
{ {
h8_3002_InterruptRequest(26 + 4*which); h8_3002_InterruptRequest(h8, 26 + 4*which);
} }
} }
static void h8_itu_refresh_timer(int tnum) static TIMER_CALLBACK( h8itu_timer_0_cb )
{
h83xx_state *h8 = (h83xx_state *)ptr;
h8itu_timer_expire(h8, 0);
}
static TIMER_CALLBACK( h8itu_timer_1_cb )
{
h83xx_state *h8 = (h83xx_state *)ptr;
h8itu_timer_expire(h8, 1);
}
static TIMER_CALLBACK( h8itu_timer_2_cb )
{
h83xx_state *h8 = (h83xx_state *)ptr;
h8itu_timer_expire(h8, 2);
}
static TIMER_CALLBACK( h8itu_timer_3_cb )
{
h83xx_state *h8 = (h83xx_state *)ptr;
h8itu_timer_expire(h8, 3);
}
static TIMER_CALLBACK( h8itu_timer_4_cb )
{
h83xx_state *h8 = (h83xx_state *)ptr;
h8itu_timer_expire(h8, 4);
}
static void h8_itu_refresh_timer(h83xx_state *h8, int tnum)
{ {
int ourTCR = 0; int ourTCR = 0;
int ourTVAL = 0; int ourTVAL = 0;
attotime period; attotime period;
ourTCR = h8.per_regs[tcr[tnum]]; ourTCR = h8->per_regs[tcr[tnum]];
ourTVAL = h8.h8TCNT[tnum]; ourTVAL = h8->h8TCNT[tnum];
period = attotime_mul(ATTOTIME_IN_HZ(cpu_get_clock(Machine->cpu[h8.cpu_number])), tscales[ourTCR & 3] * (65536 - ourTVAL)); period = attotime_mul(ATTOTIME_IN_HZ(cpu_get_clock(Machine->cpu[h8->cpu_number])), tscales[ourTCR & 3] * (65536 - ourTVAL));
if (ourTCR & 4) if (ourTCR & 4)
{ {
logerror("H8/3002: Timer %d is using an external clock. Unsupported!\n", tnum); logerror("H8/3002: Timer %d is using an external clock. Unsupported!\n", tnum);
} }
timer_adjust_oneshot(h8.timer[tnum], period, 0); timer_adjust_oneshot(h8->timer[tnum], period, 0);
} }
static void h8_itu_sync_timers(int tnum) static void h8_itu_sync_timers(h83xx_state *h8, int tnum)
{ {
int ourTCR = 0; int ourTCR = 0;
attotime cycle_time, cur; attotime cycle_time, cur;
UINT16 ratio; UINT16 ratio;
ourTCR = h8.per_regs[tcr[tnum]]; ourTCR = h8->per_regs[tcr[tnum]];
// get the time per unit // get the time per unit
cycle_time = attotime_mul(ATTOTIME_IN_HZ(cpu_get_clock(Machine->cpu[h8.cpu_number])), tscales[ourTCR & 3]); cycle_time = attotime_mul(ATTOTIME_IN_HZ(cpu_get_clock(Machine->cpu[h8->cpu_number])), tscales[ourTCR & 3]);
cur = timer_timeelapsed(h8.timer[tnum]); cur = timer_timeelapsed(h8->timer[tnum]);
ratio = attotime_to_double(cur) / attotime_to_double(cycle_time); ratio = attotime_to_double(cur) / attotime_to_double(cycle_time);
h8.h8TCNT[tnum] = ratio; h8->h8TCNT[tnum] = ratio;
} }
UINT8 h8_itu_read8(UINT8 reg) UINT8 h8_itu_read8(h83xx_state *h8, UINT8 reg)
{ {
UINT8 val; UINT8 val;
switch(reg) switch(reg)
{ {
case 0x60: case 0x60:
val = h8.h8TSTR; val = h8->h8TSTR;
break; break;
case 0x68: case 0x68:
h8_itu_sync_timers(0); h8_itu_sync_timers(h8, 0);
val = h8.h8TCNT[0]>>8; val = h8->h8TCNT[0]>>8;
break; break;
case 0x69: case 0x69:
h8_itu_sync_timers(0); h8_itu_sync_timers(h8, 0);
val = h8.h8TCNT[0]&0xff; val = h8->h8TCNT[0]&0xff;
break; break;
case 0x72: case 0x72:
h8_itu_sync_timers(1); h8_itu_sync_timers(h8, 1);
val = h8.h8TCNT[1]>>8; val = h8->h8TCNT[1]>>8;
break; break;
case 0x73: case 0x73:
h8_itu_sync_timers(1); h8_itu_sync_timers(h8, 1);
val = h8.h8TCNT[1]&0xff; val = h8->h8TCNT[1]&0xff;
break; break;
case 0x7c: case 0x7c:
h8_itu_sync_timers(2); h8_itu_sync_timers(h8, 2);
val = h8.h8TCNT[2]>>8; val = h8->h8TCNT[2]>>8;
break; break;
case 0x7d: case 0x7d:
h8_itu_sync_timers(2); h8_itu_sync_timers(h8, 2);
val = h8.h8TCNT[2]&0xff; val = h8->h8TCNT[2]&0xff;
break; break;
case 0x86: case 0x86:
h8_itu_sync_timers(3); h8_itu_sync_timers(h8, 3);
val = h8.h8TCNT[3]>>8; val = h8->h8TCNT[3]>>8;
break; break;
case 0x87: case 0x87:
h8_itu_sync_timers(3); h8_itu_sync_timers(h8, 3);
val = h8.h8TCNT[3]&0xff; val = h8->h8TCNT[3]&0xff;
break; break;
default: default:
val = h8.per_regs[reg]; val = h8->per_regs[reg];
break; break;
} }
@ -139,102 +175,102 @@ UINT8 h8_itu_read8(UINT8 reg)
return val; return val;
} }
void h8_itu_write8(UINT8 reg, UINT8 val) void h8_itu_write8(h83xx_state *h8, UINT8 reg, UINT8 val)
{ {
h8.per_regs[reg] = val; h8->per_regs[reg] = val;
switch(reg) switch(reg)
{ {
case 0x60: case 0x60:
if ((val & 1) && !(h8.h8TSTR & 1)) if ((val & 1) && !(h8->h8TSTR & 1))
{ {
h8_itu_refresh_timer(0); h8_itu_refresh_timer(h8, 0);
} }
if ((val & 2) && !(h8.h8TSTR & 2)) if ((val & 2) && !(h8->h8TSTR & 2))
{ {
h8_itu_refresh_timer(1); h8_itu_refresh_timer(h8, 1);
} }
if ((val & 4) && !(h8.h8TSTR & 4)) if ((val & 4) && !(h8->h8TSTR & 4))
{ {
h8_itu_refresh_timer(2); h8_itu_refresh_timer(h8, 2);
} }
if ((val & 8) && !(h8.h8TSTR & 8)) if ((val & 8) && !(h8->h8TSTR & 8))
{ {
h8_itu_refresh_timer(3); h8_itu_refresh_timer(h8, 3);
} }
if ((val & 0x10) && !(h8.h8TSTR & 0x10)) if ((val & 0x10) && !(h8->h8TSTR & 0x10))
{ {
h8_itu_refresh_timer(4); h8_itu_refresh_timer(h8, 4);
} }
h8.h8TSTR = val; h8->h8TSTR = val;
break; break;
case 0x68: case 0x68:
h8.h8TCNT[0] = (val<<8) | (h8.h8TCNT[0] & 0xff); h8->h8TCNT[0] = (val<<8) | (h8->h8TCNT[0] & 0xff);
if (h8.h8TSTR & 1) if (h8->h8TSTR & 1)
{ {
h8_itu_refresh_timer(0); h8_itu_refresh_timer(h8, 0);
} }
break; break;
case 0x69: case 0x69:
h8.h8TCNT[0] = (val) | (h8.h8TCNT[0] & 0xff00); h8->h8TCNT[0] = (val) | (h8->h8TCNT[0] & 0xff00);
if (h8.h8TSTR & 1) if (h8->h8TSTR & 1)
{ {
h8_itu_refresh_timer(0); h8_itu_refresh_timer(h8, 0);
} }
break; break;
case 0x72: case 0x72:
h8.h8TCNT[1] = (val<<8) | (h8.h8TCNT[1] & 0xff); h8->h8TCNT[1] = (val<<8) | (h8->h8TCNT[1] & 0xff);
if (h8.h8TSTR & 2) if (h8->h8TSTR & 2)
{ {
h8_itu_refresh_timer(1); h8_itu_refresh_timer(h8, 1);
} }
break; break;
case 0x73: case 0x73:
h8.h8TCNT[1] = (val) | (h8.h8TCNT[1] & 0xff00); h8->h8TCNT[1] = (val) | (h8->h8TCNT[1] & 0xff00);
if (h8.h8TSTR & 2) if (h8->h8TSTR & 2)
{ {
h8_itu_refresh_timer(1); h8_itu_refresh_timer(h8, 1);
} }
break; break;
case 0x7c: case 0x7c:
h8.h8TCNT[2] = (val<<8) | (h8.h8TCNT[2] & 0xff); h8->h8TCNT[2] = (val<<8) | (h8->h8TCNT[2] & 0xff);
if (h8.h8TSTR & 4) if (h8->h8TSTR & 4)
{ {
h8_itu_refresh_timer(2); h8_itu_refresh_timer(h8, 2);
} }
break; break;
case 0x7d: case 0x7d:
h8.h8TCNT[2] = (val) | (h8.h8TCNT[2] & 0xff00); h8->h8TCNT[2] = (val) | (h8->h8TCNT[2] & 0xff00);
if (h8.h8TSTR & 4) if (h8->h8TSTR & 4)
{ {
h8_itu_refresh_timer(2); h8_itu_refresh_timer(h8, 2);
} }
break; break;
case 0x86: case 0x86:
h8.h8TCNT[3] = (val<<8) | (h8.h8TCNT[3] & 0xff); h8->h8TCNT[3] = (val<<8) | (h8->h8TCNT[3] & 0xff);
if (h8.h8TSTR & 8) if (h8->h8TSTR & 8)
{ {
h8_itu_refresh_timer(3); h8_itu_refresh_timer(h8, 3);
} }
break; break;
case 0x87: case 0x87:
h8.h8TCNT[3] = (val) | (h8.h8TCNT[3] & 0xff00); h8->h8TCNT[3] = (val) | (h8->h8TCNT[3] & 0xff00);
if (h8.h8TSTR & 8) if (h8->h8TSTR & 8)
{ {
h8_itu_refresh_timer(3); h8_itu_refresh_timer(h8, 3);
} }
break; break;
case 0x96: case 0x96:
h8.h8TCNT[4] = (val<<8) | (h8.h8TCNT[4] & 0xff); h8->h8TCNT[4] = (val<<8) | (h8->h8TCNT[4] & 0xff);
if (h8.h8TSTR & 0x10) if (h8->h8TSTR & 0x10)
{ {
h8_itu_refresh_timer(4); h8_itu_refresh_timer(h8, 4);
} }
break; break;
case 0x97: case 0x97:
h8.h8TCNT[4] = (val) | (h8.h8TCNT[4] & 0xff00); h8->h8TCNT[4] = (val) | (h8->h8TCNT[4] & 0xff00);
if (h8.h8TSTR & 0x10) if (h8->h8TSTR & 0x10)
{ {
h8_itu_refresh_timer(4); h8_itu_refresh_timer(h8, 4);
} }
break; break;
default: default:
@ -253,26 +289,26 @@ UINT8 h8_debugger_itu_read8(UINT8 reg)
#endif #endif
static UINT8 h8_ISR_r(void) static UINT8 h8_ISR_r(h83xx_state *h8)
{ {
UINT8 res = 0; UINT8 res = 0;
int i; int i;
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
if (h8.h8_IRQrequestL & (1 << (12+i))) res |= (1 << i); if (h8->h8_IRQrequestL & (1 << (12+i))) res |= (1 << i);
return res; return res;
} }
static void h8_ISR_w(UINT8 val) static void h8_ISR_w(h83xx_state *h8, UINT8 val)
{ {
int i; int i;
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
if ((~val) & (1 << i)) h8.h8_IRQrequestL &= ~(1 << (12+i)); if ((~val) & (1 << i)) h8->h8_IRQrequestL &= ~(1 << (12+i));
} }
UINT8 h8_register_read8(UINT32 address) UINT8 h8_register_read8(h83xx_state *h8, UINT32 address)
{ {
UINT8 val; UINT8 val;
UINT8 reg; UINT8 reg;
@ -283,25 +319,25 @@ UINT8 h8_register_read8(UINT32 address)
if(reg >= 0x60 && reg <= 0x9f) if(reg >= 0x60 && reg <= 0x9f)
{ {
return h8_itu_read8(reg); return h8_itu_read8(h8, reg);
} }
else else
{ {
switch(reg) switch(reg)
{ {
case 0xb4: // serial port A status case 0xb4: // serial port A status
val = h8.per_regs[reg]; val = h8->per_regs[reg];
val |= 0xc4; // transmit finished, receive ready, no errors val |= 0xc4; // transmit finished, receive ready, no errors
break; break;
case 0xb5: // serial port A receive case 0xb5: // serial port A receive
val = io_read_byte(H8_SERIAL_A); val = io_read_byte(H8_SERIAL_0);
break; break;
case 0xbc: // serial port B status case 0xbc: // serial port B status
val = h8.per_regs[reg]; val = h8->per_regs[reg];
val |= 0xc4; // transmit finished, receive ready, no errors val |= 0xc4; // transmit finished, receive ready, no errors
break; break;
case 0xbd: // serial port B receive case 0xbd: // serial port B receive
val = io_read_byte(H8_SERIAL_B); val = io_read_byte(H8_SERIAL_1);
break; break;
case 0xe0: case 0xe0:
val = io_read_byte(H8_ADC_0_H); val = io_read_byte(H8_ADC_0_H);
@ -331,32 +367,32 @@ UINT8 h8_register_read8(UINT32 address)
val = 0x80; val = 0x80;
break; break;
case 0xc7: // port 4 data case 0xc7: // port 4 data
val = io_read_byte(H8_PORT4); val = io_read_byte(H8_PORT_4);
break; break;
case 0xcb: // port 6 data case 0xcb: // port 6 data
val = io_read_byte(H8_PORT6); val = io_read_byte(H8_PORT_6);
break; break;
case 0xce: // port 7 data case 0xce: // port 7 data
val = io_read_byte(H8_PORT7); val = io_read_byte(H8_PORT_7);
break; break;
case 0xcf: // port 8 data case 0xcf: // port 8 data
val = io_read_byte(H8_PORT8); val = io_read_byte(H8_PORT_8);
break; break;
case 0xd2: // port 9 data case 0xd2: // port 9 data
val = io_read_byte(H8_PORT9); val = io_read_byte(H8_PORT_9);
break; break;
case 0xd3: // port a data case 0xd3: // port a data
val = io_read_byte(H8_PORTA); val = io_read_byte(H8_PORT_A);
break; break;
case 0xd6: // port b data case 0xd6: // port b data
val = io_read_byte(H8_PORTB); val = io_read_byte(H8_PORT_B);
break; break;
case 0xf6: case 0xf6:
val = h8_ISR_r(); val = h8_ISR_r(h8);
break; break;
default: default:
val = h8.per_regs[reg]; val = h8->per_regs[reg];
break; break;
} }
} }
@ -364,7 +400,7 @@ UINT8 h8_register_read8(UINT32 address)
return val; return val;
} }
void h8_register_write8(UINT32 address, UINT8 val) void h8_register_write8(h83xx_state *h8, UINT32 address, UINT8 val)
{ {
UINT8 reg; UINT8 reg;
@ -374,167 +410,189 @@ void h8_register_write8(UINT32 address, UINT8 val)
if(reg >= 0x60 && reg <= 0x9f) if(reg >= 0x60 && reg <= 0x9f)
{ {
h8_itu_write8(reg, val); h8_itu_write8(h8, reg, val);
} }
switch (reg) switch (reg)
{ {
case 0xb3: case 0xb3:
io_write_byte(H8_SERIAL_A, val); io_write_byte(H8_SERIAL_0, val);
break; break;
case 0xbb: case 0xbb:
io_write_byte(H8_SERIAL_B, val); io_write_byte(H8_SERIAL_1, val);
break; break;
case 0xc7: case 0xc7:
io_write_byte(H8_PORT4, val); io_write_byte(H8_PORT_4, val);
break; break;
case 0xcb: // port 6 data case 0xcb: // port 6 data
io_write_byte(H8_PORT6, val); io_write_byte(H8_PORT_6, val);
break; break;
case 0xce: // port 7 data case 0xce: // port 7 data
io_write_byte(H8_PORT7, val); io_write_byte(H8_PORT_7, val);
break; break;
case 0xcf: // port 8 data case 0xcf: // port 8 data
io_write_byte(H8_PORT8, val); io_write_byte(H8_PORT_8, val);
break; break;
case 0xd2: // port 9 data case 0xd2: // port 9 data
io_write_byte(H8_PORT9, val); io_write_byte(H8_PORT_9, val);
break; break;
case 0xd3: // port a data case 0xd3: // port a data
io_write_byte(H8_PORTA, val); io_write_byte(H8_PORT_A, val);
break; break;
case 0xd6: // port b data case 0xd6: // port b data
io_write_byte(H8_PORTB, val); io_write_byte(H8_PORT_B, val);
break; break;
case 0xf6: case 0xf6:
h8_ISR_w(val); h8_ISR_w(h8, val);
break; break;
} }
h8.per_regs[reg] = val; h8->per_regs[reg] = val;
} }
static void h8_3007_itu_refresh_timer(int tnum) static void h8_3007_itu_refresh_timer(h83xx_state *h8, int tnum)
{ {
attotime period; attotime period;
int ourTCR = h8.per_regs[0x68+(tnum*8)]; int ourTCR = h8->per_regs[0x68+(tnum*8)];
period = attotime_mul(ATTOTIME_IN_HZ(cpu_get_clock(Machine->cpu[h8.cpu_number])), tscales[ourTCR & 3]); period = attotime_mul(ATTOTIME_IN_HZ(cpu_get_clock(Machine->cpu[h8->cpu_number])), tscales[ourTCR & 3]);
if (ourTCR & 4) if (ourTCR & 4)
{ {
logerror("H8/3007: Timer %d is using an external clock. Unsupported!\n", tnum); logerror("H8/3007: Timer %d is using an external clock. Unsupported!\n", tnum);
} }
timer_adjust_oneshot(h8.timer[tnum], period, 0); timer_adjust_oneshot(h8->timer[tnum], period, 0);
} }
static TIMER_CALLBACK( h8itu_3007_timer_cb ) static void h8itu_3007_timer_expire(h83xx_state *h8, int tnum)
{ {
int tnum = (int)(FPTR)ptr;
int base = 0x68 + (tnum*8); int base = 0x68 + (tnum*8);
UINT16 count = (h8.per_regs[base + 0x2]<<8) | h8.per_regs[base + 0x3]; UINT16 count;
count = (h8->per_regs[base + 0x2]<<8) | h8->per_regs[base + 0x3];
count++; count++;
//logerror("h8/3007 timer %d count = %04x\n",tnum,count); //logerror("h8/3007 timer %d count = %04x\n",tnum,count);
// GRA match // GRA match
if ((h8.per_regs[base + 0x1] & 0x03) && (count == ((h8.per_regs[base + 0x4]<<8) | h8.per_regs[base + 0x5]))) if ((h8->per_regs[base + 0x1] & 0x03) && (count == ((h8->per_regs[base + 0x4]<<8) | h8->per_regs[base + 0x5])))
{ {
if ((h8.per_regs[base + 0x0] & 0x60) == 0x20) if ((h8->per_regs[base + 0x0] & 0x60) == 0x20)
{ {
//logerror("h8/3007 timer %d GRA match, restarting\n",tnum); //logerror("h8/3007 timer %d GRA match, restarting\n",tnum);
count = 0; count = 0;
h8_3007_itu_refresh_timer(tnum); h8_3007_itu_refresh_timer(h8, tnum);
} }
else else
{ {
//logerror("h8/3007 timer %d GRA match, stopping\n",tnum); //logerror("h8/3007 timer %d GRA match, stopping\n",tnum);
timer_adjust_oneshot(h8.timer[tnum], attotime_never, 0); timer_adjust_oneshot(h8->timer[tnum], attotime_never, 0);
} }
h8.per_regs[0x64] |= 1<<tnum; h8->per_regs[0x64] |= 1<<tnum;
if(h8.per_regs[0x64] & (4<<tnum)) // interrupt enable if(h8->per_regs[0x64] & (4<<tnum)) // interrupt enable
{ {
//logerror("h8/3007 timer %d GRA INTERRUPT\n",tnum); //logerror("h8/3007 timer %d GRA INTERRUPT\n",tnum);
h8_3002_InterruptRequest(24+tnum*4); h8_3002_InterruptRequest(h8, 24+tnum*4);
} }
} }
// GRB match // GRB match
if ((h8.per_regs[base + 0x1] & 0x30) && (count == ((h8.per_regs[base + 0x6]<<8) | h8.per_regs[base + 0x7]))) if ((h8->per_regs[base + 0x1] & 0x30) && (count == ((h8->per_regs[base + 0x6]<<8) | h8->per_regs[base + 0x7])))
{ {
if ((h8.per_regs[base + 0x0] & 0x60) == 0x40) if ((h8->per_regs[base + 0x0] & 0x60) == 0x40)
{ {
//logerror("h8/3007 timer %d GRB match, restarting\n",tnum); //logerror("h8/3007 timer %d GRB match, restarting\n",tnum);
count = 0; count = 0;
h8_3007_itu_refresh_timer(tnum); h8_3007_itu_refresh_timer(h8, tnum);
} }
else else
{ {
//logerror("h8/3007 timer %d GRB match, stopping\n",tnum); //logerror("h8/3007 timer %d GRB match, stopping\n",tnum);
timer_adjust_oneshot(h8.timer[tnum], attotime_never, 0); timer_adjust_oneshot(h8->timer[tnum], attotime_never, 0);
} }
h8.per_regs[0x65] |= 1<<tnum; h8->per_regs[0x65] |= 1<<tnum;
if(h8.per_regs[0x65] & (4<<tnum)) // interrupt enable if(h8->per_regs[0x65] & (4<<tnum)) // interrupt enable
{ {
//logerror("h8/3007 timer %d GRB INTERRUPT\n",tnum); //logerror("h8/3007 timer %d GRB INTERRUPT\n",tnum);
h8_3002_InterruptRequest(25+tnum*4); h8_3002_InterruptRequest(h8, 25+tnum*4);
} }
} }
// Overflow // Overflow
if (((h8.per_regs[base + 0x1] & 0x33) == 0) && (count == 0)) if (((h8->per_regs[base + 0x1] & 0x33) == 0) && (count == 0))
{ {
//logerror("h8/3007 timer %d OVF match, restarting\n",tnum); //logerror("h8/3007 timer %d OVF match, restarting\n",tnum);
h8.per_regs[0x66] |= 1<<tnum; h8->per_regs[0x66] |= 1<<tnum;
if(h8.per_regs[0x66] & (4<<tnum)) // interrupt enable if(h8->per_regs[0x66] & (4<<tnum)) // interrupt enable
{ {
//logerror("h8/3007 timer %d OVF INTERRUPT\n",tnum); //logerror("h8/3007 timer %d OVF INTERRUPT\n",tnum);
h8_3002_InterruptRequest(26+tnum*4); h8_3002_InterruptRequest(h8, 26+tnum*4);
} }
} }
h8.per_regs[base + 0x2] = count >> 8; h8->per_regs[base + 0x2] = count >> 8;
h8.per_regs[base + 0x3] = count & 0xff; h8->per_regs[base + 0x3] = count & 0xff;
} }
UINT8 h8_3007_itu_read8(UINT8 reg) static TIMER_CALLBACK( h8itu_3007_timer_0_cb )
{
h83xx_state *h8 = (h83xx_state *)ptr;
h8itu_3007_timer_expire(h8, 0);
}
static TIMER_CALLBACK( h8itu_3007_timer_1_cb )
{
h83xx_state *h8 = (h83xx_state *)ptr;
h8itu_3007_timer_expire(h8, 1);
}
static TIMER_CALLBACK( h8itu_3007_timer_2_cb )
{
h83xx_state *h8 = (h83xx_state *)ptr;
h8itu_3007_timer_expire(h8, 2);
}
UINT8 h8_3007_itu_read8(h83xx_state *h8, UINT8 reg)
{ {
UINT8 val; UINT8 val;
switch(reg) switch(reg)
{ {
case 0x60: case 0x60:
val = h8.h8TSTR | 0xf8; val = h8->h8TSTR | 0xf8;
break; break;
default: default:
val = h8.per_regs[reg]; val = h8->per_regs[reg];
break; break;
} }
return val; return val;
} }
void h8_3007_itu_write8(UINT8 reg, UINT8 val) void h8_3007_itu_write8(h83xx_state *h8, UINT8 reg, UINT8 val)
{ {
//logerror("%06x: h8/3007 reg %02x = %02x\n",cpu_get_pc(machine->activecpu),reg,val); //logerror("%06x: h8/3007 reg %02x = %02x\n",cpu_get_pc(machine->activecpu),reg,val);
h8.per_regs[reg] = val; h8->per_regs[reg] = val;
switch(reg) switch(reg)
{ {
case 0x60: case 0x60:
if ((val & 1) && !(h8.h8TSTR & 1)) if ((val & 1) && !(h8->h8TSTR & 1))
{ {
h8_3007_itu_refresh_timer(0); h8_3007_itu_refresh_timer(h8, 0);
} }
if ((val & 2) && !(h8.h8TSTR & 2)) if ((val & 2) && !(h8->h8TSTR & 2))
{ {
h8_3007_itu_refresh_timer(1); h8_3007_itu_refresh_timer(h8, 1);
} }
if ((val & 4) && !(h8.h8TSTR & 4)) if ((val & 4) && !(h8->h8TSTR & 4))
{ {
h8_3007_itu_refresh_timer(2); h8_3007_itu_refresh_timer(h8, 2);
} }
h8.h8TSTR = val; h8->h8TSTR = val;
break; break;
default: default:
val = 0; val = 0;
@ -542,7 +600,7 @@ void h8_3007_itu_write8(UINT8 reg, UINT8 val)
} }
} }
UINT8 h8_3007_register_read8(UINT32 address) UINT8 h8_3007_register_read8(h83xx_state *h8, UINT32 address)
{ {
UINT8 val; UINT8 val;
UINT8 reg; UINT8 reg;
@ -553,25 +611,25 @@ UINT8 h8_3007_register_read8(UINT32 address)
if(reg >= 0x60 && reg <= 0x7f) if(reg >= 0x60 && reg <= 0x7f)
{ {
return h8_3007_itu_read8(reg); return h8_3007_itu_read8(h8, reg);
} }
else else
{ {
switch(reg) switch(reg)
{ {
case 0xb4: // serial port A status case 0xb4: // serial port A status
val = h8.per_regs[reg]; val = h8->per_regs[reg];
val |= 0xc4; // transmit finished, receive ready, no errors val |= 0xc4; // transmit finished, receive ready, no errors
break; break;
case 0xb5: // serial port A receive case 0xb5: // serial port A receive
val = io_read_byte(H8_SERIAL_A); val = io_read_byte(H8_SERIAL_0);
break; break;
case 0xbc: // serial port B status case 0xbc: // serial port B status
val = h8.per_regs[reg]; val = h8->per_regs[reg];
val |= 0xc4; // transmit finished, receive ready, no errors val |= 0xc4; // transmit finished, receive ready, no errors
break; break;
case 0xbd: // serial port B receive case 0xbd: // serial port B receive
val = io_read_byte(H8_SERIAL_B); val = io_read_byte(H8_SERIAL_1);
break; break;
case 0xe0: case 0xe0:
val = io_read_byte(H8_ADC_0_H); val = io_read_byte(H8_ADC_0_H);
@ -602,28 +660,28 @@ UINT8 h8_3007_register_read8(UINT32 address)
break; break;
case 0xd3: // port 4 data case 0xd3: // port 4 data
val = io_read_byte(H8_PORT4); val = io_read_byte(H8_PORT_4);
break; break;
case 0xd5: // port 6 data case 0xd5: // port 6 data
val = io_read_byte(H8_PORT6); val = io_read_byte(H8_PORT_6);
break; break;
case 0xd6: // port 7 data case 0xd6: // port 7 data
val = io_read_byte(H8_PORT7); val = io_read_byte(H8_PORT_7);
break; break;
case 0xd7: // port 8 data case 0xd7: // port 8 data
val = io_read_byte(H8_PORT8); val = io_read_byte(H8_PORT_8);
break; break;
case 0xd8: // port 9 data case 0xd8: // port 9 data
val = io_read_byte(H8_PORT9); val = io_read_byte(H8_PORT_9);
break; break;
case 0xd9: // port a data case 0xd9: // port a data
val = io_read_byte(H8_PORTA); val = io_read_byte(H8_PORT_A);
break; break;
case 0xda: // port b data case 0xda: // port b data
val = io_read_byte(H8_PORTB); val = io_read_byte(H8_PORT_B);
break; break;
default: default:
val = h8.per_regs[reg]; val = h8->per_regs[reg];
break; break;
} }
} }
@ -631,7 +689,7 @@ UINT8 h8_3007_register_read8(UINT32 address)
return val; return val;
} }
void h8_3007_register_write8(UINT32 address, UINT8 val) void h8_3007_register_write8(h83xx_state *h8, UINT32 address, UINT8 val)
{ {
UINT8 reg; UINT8 reg;
@ -639,98 +697,98 @@ void h8_3007_register_write8(UINT32 address, UINT8 val)
reg = address & 0xff; reg = address & 0xff;
h8.per_regs[reg] = val; h8->per_regs[reg] = val;
if(reg >= 0x60 && reg <= 0x7f) if(reg >= 0x60 && reg <= 0x7f)
{ {
h8_3007_itu_write8(reg, val); h8_3007_itu_write8(h8, reg, val);
} }
else else
{ {
switch (reg) switch (reg)
{ {
case 0xb3: case 0xb3:
io_write_byte(H8_SERIAL_A, val); io_write_byte(H8_SERIAL_0, val);
break; break;
case 0xbb: case 0xbb:
io_write_byte(H8_SERIAL_B, val); io_write_byte(H8_SERIAL_1, val);
break; break;
case 0xd3: case 0xd3:
io_write_byte(H8_PORT4, val); io_write_byte(H8_PORT_4, val);
break; break;
case 0xd5: // port 6 data case 0xd5: // port 6 data
io_write_byte(H8_PORT6, val); io_write_byte(H8_PORT_6, val);
break; break;
case 0xd6: // port 7 data case 0xd6: // port 7 data
io_write_byte(H8_PORT7, val); io_write_byte(H8_PORT_7, val);
break; break;
case 0xd7: // port 8 data case 0xd7: // port 8 data
io_write_byte(H8_PORT8, val); io_write_byte(H8_PORT_8, val);
break; break;
case 0xd8: // port 9 data case 0xd8: // port 9 data
io_write_byte(H8_PORT9, val); io_write_byte(H8_PORT_9, val);
break; break;
case 0xd9: // port a data case 0xd9: // port a data
io_write_byte(H8_PORTA, val); io_write_byte(H8_PORT_A, val);
break; break;
case 0xda: // port b data case 0xda: // port b data
io_write_byte(H8_PORTB, val); io_write_byte(H8_PORT_B, val);
break; break;
} }
} }
} }
UINT8 h8_3007_register1_read8(UINT32 address) UINT8 h8_3007_register1_read8(h83xx_state *h8, UINT32 address)
{ {
switch (address) switch (address)
{ {
case 0xfee012: return h8.per_regs[0xF2]; // SYSCR case 0xfee012: return h8->per_regs[0xF2]; // SYSCR
case 0xfee016: return h8_ISR_r(); // ISR case 0xfee016: return h8_ISR_r(h8); // ISR
case 0xfee018: return h8.per_regs[0xF8]; // IPRA case 0xfee018: return h8->per_regs[0xF8]; // IPRA
} }
logerror("cpu #%d (PC=%08X): unmapped I/O(1) byte read from %08X\n",cpunum_get_active(),cpu_get_pc(Machine->activecpu),address); logerror("cpu #%d (PC=%08X): unmapped I/O(1) byte read from %08X\n",cpunum_get_active(),cpu_get_pc(Machine->activecpu),address);
return 0; return 0;
} }
void h8_3007_register1_write8(UINT32 address, UINT8 val) void h8_3007_register1_write8(h83xx_state *h8, UINT32 address, UINT8 val)
{ {
switch (address) switch (address)
{ {
case 0xfee012: h8.per_regs[0xF2] = val; return; // SYSCR case 0xfee012: h8->per_regs[0xF2] = val; return; // SYSCR
case 0xfee016: h8_ISR_w(val); return; // ISR case 0xfee016: h8_ISR_w(h8, val); return; // ISR
case 0xfee018: h8.per_regs[0xF8] = val; return; // IPRA case 0xfee018: h8->per_regs[0xF8] = val; return; // IPRA
} }
logerror("cpu #%d (PC=%08X): unmapped I/O(1) byte write to %08X = %02X\n",cpunum_get_active(),cpu_get_pc(Machine->activecpu),address,val); logerror("cpu #%d (PC=%08X): unmapped I/O(1) byte write to %08X = %02X\n",cpunum_get_active(),cpu_get_pc(Machine->activecpu),address,val);
} }
void h8_3007_itu_init(void) void h8_3007_itu_init(h83xx_state *h8)
{ {
int i; h8->timer[0] = timer_alloc(h8itu_3007_timer_0_cb, h8);
h8->timer[1] = timer_alloc(h8itu_3007_timer_1_cb, h8);
h8->timer[2] = timer_alloc(h8itu_3007_timer_2_cb, h8);
for (i=0; i<3; i++) h8_itu_reset(h8);
h8.timer[i] = timer_alloc(h8itu_3007_timer_cb, (void*)(FPTR)i);
h8_itu_reset();
} }
void h8_itu_init(void) void h8_itu_init(h83xx_state *h8)
{ {
int i; h8->timer[0] = timer_alloc(h8itu_timer_0_cb, h8);
h8->timer[1] = timer_alloc(h8itu_timer_1_cb, h8);
h8->timer[2] = timer_alloc(h8itu_timer_2_cb, h8);
h8->timer[3] = timer_alloc(h8itu_timer_3_cb, h8);
h8->timer[4] = timer_alloc(h8itu_timer_4_cb, h8);
for (i=0; i<5; i++) h8_itu_reset(h8);
h8.timer[i] = timer_alloc(h8itu_timer_cb, (void*)(FPTR)i);
h8_itu_reset(); h8->cpu_number = cpunum_get_active();
h8.cpu_number = cpunum_get_active();
} }
void h8_itu_reset(void) void h8_itu_reset(h83xx_state *h8)
{ {
int i; int i;
// stop all the timers // stop all the timers
for (i=0; i<5; i++) for (i=0; i<5; i++)
timer_adjust_oneshot(h8.timer[i], attotime_never, 0); timer_adjust_oneshot(h8->timer[i], attotime_never, 0);
} }

View File

@ -9,14 +9,16 @@
#ifndef __H8PRIV_H__ #ifndef __H8PRIV_H__
#define __H8PRIV_H__ #define __H8PRIV_H__
typedef struct _h83002_state h83002_state; typedef struct _h83xx_state h83xx_state;
struct _h83002_state struct _h83xx_state
{ {
// main CPU stuff // main CPU stuff
UINT32 h8err; UINT32 h8err;
UINT32 regs[8]; UINT32 regs[8];
UINT32 pc, ppc; UINT32 pc, ppc;
UINT32 h8_IRQrequestH, h8_IRQrequestL; UINT32 h8_IRQrequestH, h8_IRQrequestL;
INT32 cyccnt;
UINT8 ccr; UINT8 ccr;
UINT8 h8nflag, h8vflag, h8cflag, h8zflag, h8iflag, h8hflag; UINT8 h8nflag, h8vflag, h8cflag, h8zflag, h8iflag, h8hflag;
@ -35,24 +37,24 @@ struct _h83002_state
emu_timer *timer[5]; emu_timer *timer[5];
int cpu_number; int cpu_number;
int h8300_mode;
}; };
extern h83xx_state h8;
extern h83002_state h8;
UINT8 h8_register_read8(UINT32 address); UINT8 h8_register_read8(h83xx_state *h8, UINT32 address);
UINT8 h8_3007_register_read8(UINT32 address); UINT8 h8_3007_register_read8(h83xx_state *h8, UINT32 address);
UINT8 h8_3007_register1_read8(UINT32 address); UINT8 h8_3007_register1_read8(h83xx_state *h8, UINT32 address);
void h8_register_write8(UINT32 address, UINT8 val); void h8_register_write8(h83xx_state *h8, UINT32 address, UINT8 val);
void h8_3007_register_write8(UINT32 address, UINT8 val); void h8_3007_register_write8(h83xx_state *h8, UINT32 address, UINT8 val);
void h8_3007_register1_write8(UINT32 address, UINT8 val); void h8_3007_register1_write8(h83xx_state *h8, UINT32 address, UINT8 val);
void h8_itu_init(void); void h8_itu_init(h83xx_state *h8);
void h8_3007_itu_init(void); void h8_3007_itu_init(h83xx_state *h8);
void h8_itu_reset(void); void h8_itu_reset(h83xx_state *h8);
UINT8 h8_itu_read8(UINT8 reg); UINT8 h8_itu_read8(h83xx_state *h8, UINT8 reg);
UINT8 h8_3007_itu_read8(UINT8 reg); UINT8 h8_3007_itu_read8(h83xx_state *h8, UINT8 reg);
void h8_itu_write8(UINT8 reg, UINT8 val); void h8_itu_write8(h83xx_state *h8, UINT8 reg, UINT8 val);
void h8_3007_itu_write8(UINT8 reg, UINT8 val); void h8_3007_itu_write8(h83xx_state *h8, UINT8 reg, UINT8 val);
#endif /* __H8PRIV_H__ */ #endif /* __H8PRIV_H__ */

View File

@ -209,6 +209,7 @@ CPU_GET_INFO( i960 );
CPU_GET_INFO( h8_3002 ); CPU_GET_INFO( h8_3002 );
CPU_GET_INFO( h8_3007 ); CPU_GET_INFO( h8_3007 );
CPU_GET_INFO( h8_3044 ); CPU_GET_INFO( h8_3044 );
CPU_GET_INFO( h8_3344 );
CPU_GET_INFO( v810 ); CPU_GET_INFO( v810 );
CPU_GET_INFO( m37702 ); CPU_GET_INFO( m37702 );
CPU_GET_INFO( m37710 ); CPU_GET_INFO( m37710 );
@ -745,6 +746,9 @@ static const struct
#if (HAS_I960) #if (HAS_I960)
{ CPU_I960, CPU_GET_INFO_NAME(i960) }, { CPU_I960, CPU_GET_INFO_NAME(i960) },
#endif #endif
#if (HAS_H83344)
{ CPU_H83344, CPU_GET_INFO_NAME(h8_3344) },
#endif
#if (HAS_H83002) #if (HAS_H83002)
{ CPU_H83002, CPU_GET_INFO_NAME(h8_3002) }, { CPU_H83002, CPU_GET_INFO_NAME(h8_3002) },
{ CPU_H83007, CPU_GET_INFO_NAME(h8_3007) }, { CPU_H83007, CPU_GET_INFO_NAME(h8_3007) },

View File

@ -375,6 +375,7 @@ enum _cpu_type
CPU_H83002, CPU_H83002,
CPU_H83007, CPU_H83007,
CPU_H83044, CPU_H83044,
CPU_H83344,
CPU_V810, CPU_V810,
CPU_M37702, CPU_M37702,
CPU_M37710, CPU_M37710,

View File

@ -47,7 +47,7 @@ Notes:
#include "driver.h" #include "driver.h"
#include "deprecat.h" #include "deprecat.h"
#include "cpu/h83002/h83002.h" #include "cpu/h83002/h8.h"
#define BISHJAN_DEBUG 0 #define BISHJAN_DEBUG 0
@ -435,7 +435,7 @@ static INTERRUPT_GEN( bishjan_interrupt )
cpu_set_input_line(device, 0, PULSE_LINE); cpu_set_input_line(device, 0, PULSE_LINE);
break; break;
default: default:
h8_3002_InterruptRequest(24); cpu_set_input_line(device->machine->cpu[0], H8_METRO_TIMER_HACK, HOLD_LINE);
break; break;
} }
} }

View File

@ -52,7 +52,7 @@
#define SND_CLOCK XTAL_14_31818MHz #define SND_CLOCK XTAL_14_31818MHz
#include "driver.h" #include "driver.h"
#include "cpu/h83002/h83002.h" #include "cpu/h83002/h8.h"
#include "sound/upd7759.h" #include "sound/upd7759.h"

View File

@ -41,7 +41,7 @@
#define MAIN_CLOCK XTAL_16MHz #define MAIN_CLOCK XTAL_16MHz
#include "driver.h" #include "driver.h"
#include "cpu/h83002/h83002.h" #include "cpu/h83002/h8.h"
#include "sound/okim6295.h" #include "sound/okim6295.h"

View File

@ -54,7 +54,7 @@
#define EJOLLYX5_MAIN_CLOCK XTAL_16MHz #define EJOLLYX5_MAIN_CLOCK XTAL_16MHz
#include "driver.h" #include "driver.h"
#include "cpu/h83002/h83002.h" #include "cpu/h83002/h8.h"
#include "sound/okim6295.h" #include "sound/okim6295.h"

View File

@ -64,7 +64,7 @@ Notes:
#include "driver.h" #include "driver.h"
#include "deprecat.h" #include "deprecat.h"
#include "cpu/h83002/h83002.h" #include "cpu/h83002/h8.h"
/*************************************************************************** /***************************************************************************
Video Hardware Video Hardware
@ -455,7 +455,7 @@ static INTERRUPT_GEN( unknown_interrupt )
cpu_set_input_line(device, 0, PULSE_LINE); cpu_set_input_line(device, 0, PULSE_LINE);
break; break;
default: default:
h8_3002_InterruptRequest(24); cpu_set_input_line(device->machine->cpu[0], H8_METRO_TIMER_HACK, HOLD_LINE);
break; break;
} }
} }

View File

@ -82,7 +82,7 @@ driver modified by Eisuke Watanabe
#include "driver.h" #include "driver.h"
#include "deprecat.h" #include "deprecat.h"
#include "cpu/h83002/h83002.h" #include "cpu/h83002/h8.h"
#include "cpu/upd7810/upd7810.h" #include "cpu/upd7810/upd7810.h"
#include "machine/eeprom.h" #include "machine/eeprom.h"
#include "video/konamiic.h" #include "video/konamiic.h"
@ -2188,9 +2188,9 @@ static WRITE8_HANDLER( puzzlet_portb_w )
} }
static ADDRESS_MAP_START( puzzlet_io_map, ADDRESS_SPACE_IO, 8 ) static ADDRESS_MAP_START( puzzlet_io_map, ADDRESS_SPACE_IO, 8 )
AM_RANGE( H8_PORT7, H8_PORT7 ) AM_READ_PORT("IN2") AM_RANGE( H8_PORT_7, H8_PORT_7 ) AM_READ_PORT("IN2")
AM_RANGE( H8_SERIAL_B, H8_SERIAL_B ) AM_READ_PORT("IN0") // coin AM_RANGE( H8_SERIAL_1, H8_SERIAL_1 ) AM_READ_PORT("IN0") // coin
AM_RANGE( H8_PORTB, H8_PORTB ) AM_READ_PORT("DSW0") AM_WRITE( puzzlet_portb_w ) AM_RANGE( H8_PORT_B, H8_PORT_B ) AM_READ_PORT("DSW0") AM_WRITE( puzzlet_portb_w )
ADDRESS_MAP_END ADDRESS_MAP_END
@ -4693,7 +4693,7 @@ static INTERRUPT_GEN( puzzlet_interrupt )
default: default:
// timer // timer
h8_3002_InterruptRequest(24); cpu_set_input_line(device->machine->cpu[0], H8_METRO_TIMER_HACK, HOLD_LINE);
break; break;
} }
} }

View File

@ -67,7 +67,7 @@ Notes:
#include "driver.h" #include "driver.h"
#include "video/ygv608.h" #include "video/ygv608.h"
#include "cpu/h83002/h83002.h" #include "cpu/h83002/h8.h"
#include "namcond1.h" #include "namcond1.h"
#include "sound/c352.h" #include "sound/c352.h"
#include "machine/at28c16.h" #include "machine/at28c16.h"
@ -259,8 +259,8 @@ static ADDRESS_MAP_START( nd1h8rwmap, ADDRESS_SPACE_PROGRAM, 16 )
ADDRESS_MAP_END ADDRESS_MAP_END
static ADDRESS_MAP_START( nd1h8iomap, ADDRESS_SPACE_IO, 8 ) static ADDRESS_MAP_START( nd1h8iomap, ADDRESS_SPACE_IO, 8 )
AM_RANGE(H8_PORT7, H8_PORT7) AM_READ( mcu_p7_read ) AM_RANGE(H8_PORT_7, H8_PORT_7) AM_READ( mcu_p7_read )
AM_RANGE(H8_PORTA, H8_PORTA) AM_READWRITE( mcu_pa_read, mcu_pa_write ) AM_RANGE(H8_PORT_A, H8_PORT_A) AM_READWRITE( mcu_pa_read, mcu_pa_write )
AM_RANGE(H8_ADC_0_L, H8_ADC_3_H) AM_NOP // MCU reads these, but the games have no analog controls AM_RANGE(H8_ADC_0_L, H8_ADC_3_H) AM_NOP // MCU reads these, but the games have no analog controls
ADDRESS_MAP_END ADDRESS_MAP_END

View File

@ -924,7 +924,7 @@ Notes:
#include "driver.h" #include "driver.h"
#include "deprecat.h" #include "deprecat.h"
#include "cpu/mips/psx.h" #include "cpu/mips/psx.h"
#include "cpu/h83002/h83002.h" #include "cpu/h83002/h8.h"
#include "includes/psx.h" #include "includes/psx.h"
#include "machine/at28c16.h" #include "machine/at28c16.h"
#include "sound/c352.h" #include "sound/c352.h"
@ -1421,11 +1421,11 @@ static READ8_HANDLER( s12_mcu_gun_v_r )
} }
static ADDRESS_MAP_START( s12h8iomap, ADDRESS_SPACE_IO, 8 ) static ADDRESS_MAP_START( s12h8iomap, ADDRESS_SPACE_IO, 8 )
AM_RANGE(H8_PORT7, H8_PORT7) AM_READ_PORT("DSW") AM_RANGE(H8_PORT_7, H8_PORT_7) AM_READ_PORT("DSW")
AM_RANGE(H8_PORT8, H8_PORT8) AM_READ( s12_mcu_p8_r ) AM_WRITENOP AM_RANGE(H8_PORT_8, H8_PORT_8) AM_READ( s12_mcu_p8_r ) AM_WRITENOP
AM_RANGE(H8_PORTA, H8_PORTA) AM_READWRITE( s12_mcu_pa_r, s12_mcu_pa_w ) AM_RANGE(H8_PORT_A, H8_PORT_A) AM_READWRITE( s12_mcu_pa_r, s12_mcu_pa_w )
AM_RANGE(H8_PORTB, H8_PORTB) AM_READWRITE( s12_mcu_portB_r, s12_mcu_portB_w ) AM_RANGE(H8_PORT_B, H8_PORT_B) AM_READWRITE( s12_mcu_portB_r, s12_mcu_portB_w )
AM_RANGE(H8_SERIAL_B, H8_SERIAL_B) AM_READ( s12_mcu_rtc_r ) AM_WRITE( s12_mcu_settings_w ) AM_RANGE(H8_SERIAL_1, H8_SERIAL_1) AM_READ( s12_mcu_rtc_r ) AM_WRITE( s12_mcu_settings_w )
AM_RANGE(H8_ADC_0_H, H8_ADC_0_L) AM_NOP AM_RANGE(H8_ADC_0_H, H8_ADC_0_L) AM_NOP
AM_RANGE(H8_ADC_1_H, H8_ADC_1_L) AM_READ( s12_mcu_gun_h_r ) // golgo 13 gun X-axis AM_RANGE(H8_ADC_1_H, H8_ADC_1_L) AM_READ( s12_mcu_gun_h_r ) // golgo 13 gun X-axis
AM_RANGE(H8_ADC_2_H, H8_ADC_2_L) AM_READ( s12_mcu_gun_v_r ) // golgo 13 gun Y-axis AM_RANGE(H8_ADC_2_H, H8_ADC_2_L) AM_READ( s12_mcu_gun_v_r ) // golgo 13 gun Y-axis

View File

@ -2,27 +2,32 @@
Namco System 22.5 and (Super) System 23 Namco System 22.5 and (Super) System 23
Extremely preliminary driver by R. Belmont, thanks to Phil Stroffolino & Olivier Galibert Extremely preliminary driver by R. Belmont, thanks to Phil Stroffolino & Olivier Galibert
Hardware: R4650 (MIPS III with IDT special instructions) main CPU @ 166 MHz Hardware: * R4650 (MIPS III with IDT special instructions) main CPU.
H8/3002 MCU for sound/inputs 133 MHz for Gorgon, 166 MHz for System 23 and Super System 23, and
Custom polygon hardware 200 MHz for Super System 23 Evolution 2.
1 text tilemap * H8/3002 MCU for sound/inputs
Sprites? * Custom polygon hardware
* 1 text tilemap
Gorgon and System 23 use an I/O board based on the Namco C78, which is a Renesas H8/3334 MCU
(8-bit version of the H8/3002).
Super System 23 uses a PIC16Cxx-based I/O board. In both cases the I/O boards' MCUs apparently are connected
to the H8/3002's serial port, similar to System 22 where one 37702 reads the I/O and communicates serially
with the second 37702 which is the traditional "subcpu".
NOTES: NOTES:
- First 128k of main program ROM is the BIOS, and after that is a 64-bit MIPS ELF image. - First 128k of main program ROM is the BIOS, and after that is a 64-bit MIPS ELF image.
- Text layer is (almost?) identical to System 22 & Super System 22. - Text layer is (almost?) identical to System 22 & Super System 22.
TODO: TODO:
- Palette is not right. - Palette is not right.
- H8/3002 does not handshake. Protocol should be the same as System 12 where the MIPS - H8/3002 does not handshake. Looks like it needs to speak serially with the I/O board.
writes 0x3163 to offset 0x3002 in the shared RAM and the H8/3002 notices and sets it to 0x7106.
The H8 currently never reads that location (core bug?).
- Hook up actual inputs via the 2 serial latches at d00004 and d00006. - Hook up actual inputs (?) via the 2 serial latches at d00004 and d00006.
Works like this: write to d00004, then read d00004 12 times. Ditto at Works like this: write to d00004, then read d00004 12 times. Ditto at
d00006. This gives 24 bits of inputs from the I/O board (?). d00006. This gives 24 bits of inputs (?) from the I/O board (?).
- The entire 3D subsystem. Is there a DSP living down there? If not, why the 300k - The entire 3D subsystem. Is there a DSP living down there? If not, why the 300k
download on initial startup? download on initial startup?
@ -45,15 +50,15 @@ Note! This document is a Work-In-Progress and will be updated from time to time
This document covers all the known Namco System 23 / Super System 23 games, including.... This document covers all the known Namco System 23 / Super System 23 games, including....
*Angler King Namco, 1999 System 23 *Angler King Namco, 1999 System 23
*Final Furlong Namco, 1997 System 23 *Final Furlong Namco, 1997 System 23
*Gunmen Wars Namco, 1998 System 23 Gunmen Wars Namco, 1998 System 23 [not dumped, but have]
*Motocross Go! Namco, 1997 System 23 Motocross Go! Namco, 1997 System 23
*Panic Park Namco, 1998 System 23 *Panic Park Namco, 1998 System 23
Rapid River Namco, 1997 System 22.5/Gorgon Rapid River Namco, 1997 System 22.5/Gorgon
Time Crisis II Namco, 1997 System 23 Time Crisis II Namco, 1997 System 23
*Underground King Namco, 1998 System 23 *Underground King Namco, 1998 System 23
*Downhill Bikers Namco, 199? System 23 *Downhill Bikers Namco, 199? System 23
GP 500 Namco, 1999 Super System 23 500 GP Namco, 1999 Super System 23
Crisis Zone Namco, 2000 Super System 23 [not dumped, but have] Crisis Zone Namco, 2000 Super System 23 Evolution 2 [not dumped, but have]
Final Furlong 2 Namco, 1999 Super System 23 Final Furlong 2 Namco, 1999 Super System 23
*Guitar Jam Namco, 1999 Super System 23 *Guitar Jam Namco, 1999 Super System 23
*Race On! Namco, 1998 Super System 23 *Race On! Namco, 1998 Super System 23
@ -732,7 +737,7 @@ Notes:
#include "driver.h" #include "driver.h"
#include "cpu/mips/mips3.h" #include "cpu/mips/mips3.h"
#include "cpu/h83002/h83002.h" #include "cpu/h83002/h8.h"
#include "sound/c352.h" #include "sound/c352.h"
static int ss23_vstat = 0, hstat = 0, vstate = 0; static int ss23_vstat = 0, hstat = 0, vstate = 0;
@ -1055,7 +1060,7 @@ static ADDRESS_MAP_START( ss23_map, ADDRESS_SPACE_PROGRAM, 32 )
AM_RANGE(0x06a30000, 0x06a3ffff) AM_RAM AM_RANGE(0x06a30000, 0x06a3ffff) AM_RAM
AM_RANGE(0x06820008, 0x0682000f) AM_READ( ss23_vstat_r ) // vblank status? AM_RANGE(0x06820008, 0x0682000f) AM_READ( ss23_vstat_r ) // vblank status?
AM_RANGE(0x08000000, 0x08017fff) AM_RAM AM_RANGE(0x08000000, 0x08017fff) AM_RAM
AM_RANGE(0x0d000000, 0x0d000007) AM_READ(sysctl_stat_r) AM_RANGE(0x0d000000, 0x0d000007) AM_READ(sysctl_stat_r) AM_WRITENOP
AM_RANGE(0x0fc00000, 0x0fffffff) AM_WRITENOP AM_ROM AM_REGION("user1", 0) AM_RANGE(0x0fc00000, 0x0fffffff) AM_WRITENOP AM_ROM AM_REGION("user1", 0)
AM_RANGE(0x1fc00000, 0x1fffffff) AM_WRITENOP AM_ROM AM_REGION("user1", 0) AM_RANGE(0x1fc00000, 0x1fffffff) AM_WRITENOP AM_ROM AM_REGION("user1", 0)
ADDRESS_MAP_END ADDRESS_MAP_END
@ -1074,6 +1079,15 @@ static READ16_HANDLER( sharedram_sub_r )
return shared16[BYTE_XOR_BE(offset)]; return shared16[BYTE_XOR_BE(offset)];
} }
#if 1
static WRITE16_HANDLER(cause_sync_w)
{
UINT16 *shared16 = (UINT16 *)namcos23_shared_ram;
shared16[BYTE_XOR_BE(0x4052/2)] = 0;
}
#endif
/* H8/3002 MCU stuff */ /* H8/3002 MCU stuff */
static ADDRESS_MAP_START( s23h8rwmap, ADDRESS_SPACE_PROGRAM, 16 ) static ADDRESS_MAP_START( s23h8rwmap, ADDRESS_SPACE_PROGRAM, 16 )
AM_RANGE(0x000000, 0x07ffff) AM_READ(SMH_ROM) AM_RANGE(0x000000, 0x07ffff) AM_READ(SMH_ROM)
@ -1082,7 +1096,7 @@ static ADDRESS_MAP_START( s23h8rwmap, ADDRESS_SPACE_PROGRAM, 16 )
AM_RANGE(0x300000, 0x300001) AM_READNOP //AM_READ_PORT("IN1") AM_RANGE(0x300000, 0x300001) AM_READNOP //AM_READ_PORT("IN1")
AM_RANGE(0x300002, 0x300003) AM_READNOP //AM_READ_PORT("IN2") AM_RANGE(0x300002, 0x300003) AM_READNOP //AM_READ_PORT("IN2")
AM_RANGE(0x300010, 0x300011) AM_NOP AM_RANGE(0x300010, 0x300011) AM_NOP
AM_RANGE(0x300030, 0x300031) AM_NOP AM_RANGE(0x300030, 0x300031) AM_WRITE(cause_sync_w) // cheats comms with I/O board and makes SUBCPU TEST pass
ADDRESS_MAP_END ADDRESS_MAP_END
static READ8_HANDLER( s23_mcu_p8_r ) static READ8_HANDLER( s23_mcu_p8_r )
@ -1200,11 +1214,11 @@ static WRITE8_HANDLER( s23_mcu_settings_w )
} }
static ADDRESS_MAP_START( s23h8iomap, ADDRESS_SPACE_IO, 8 ) static ADDRESS_MAP_START( s23h8iomap, ADDRESS_SPACE_IO, 8 )
AM_RANGE(H8_PORT7, H8_PORT7) AM_READ( input_port_0_r ) AM_RANGE(H8_PORT_7, H8_PORT_7) AM_READ( input_port_0_r )
AM_RANGE(H8_PORT8, H8_PORT8) AM_READ( s23_mcu_p8_r ) AM_WRITENOP AM_RANGE(H8_PORT_8, H8_PORT_8) AM_READ( s23_mcu_p8_r ) AM_WRITENOP
AM_RANGE(H8_PORTA, H8_PORTA) AM_READWRITE( s23_mcu_pa_r, s23_mcu_pa_w ) AM_RANGE(H8_PORT_A, H8_PORT_A) AM_READWRITE( s23_mcu_pa_r, s23_mcu_pa_w )
AM_RANGE(H8_PORTB, H8_PORTB) AM_READWRITE( s23_mcu_portB_r, s23_mcu_portB_w ) AM_RANGE(H8_PORT_B, H8_PORT_B) AM_READWRITE( s23_mcu_portB_r, s23_mcu_portB_w )
AM_RANGE(H8_SERIAL_B, H8_SERIAL_B) AM_READ( s23_mcu_rtc_r ) AM_WRITE( s23_mcu_settings_w ) AM_RANGE(H8_SERIAL_1, H8_SERIAL_1) AM_READ( s23_mcu_rtc_r ) AM_WRITE( s23_mcu_settings_w )
AM_RANGE(H8_ADC_0_H, H8_ADC_0_L) AM_NOP AM_RANGE(H8_ADC_0_H, H8_ADC_0_L) AM_NOP
AM_RANGE(H8_ADC_1_H, H8_ADC_1_L) AM_NOP AM_RANGE(H8_ADC_1_H, H8_ADC_1_L) AM_NOP
AM_RANGE(H8_ADC_2_H, H8_ADC_2_L) AM_NOP AM_RANGE(H8_ADC_2_H, H8_ADC_2_L) AM_NOP
@ -1212,10 +1226,18 @@ static ADDRESS_MAP_START( s23h8iomap, ADDRESS_SPACE_IO, 8 )
ADDRESS_MAP_END ADDRESS_MAP_END
/* H8/3334 (Namco C78) I/O board MCU */
static ADDRESS_MAP_START( s23iobrdmap, ADDRESS_SPACE_PROGRAM, 8 )
AM_RANGE(0x0000, 0x0fff) AM_READ(SMH_ROM)
AM_RANGE(0xc000, 0xdfff) AM_RAM
ADDRESS_MAP_END
static ADDRESS_MAP_START( s23iobrdiomap, ADDRESS_SPACE_IO, 8 )
ADDRESS_MAP_END
static DRIVER_INIT(ss23) static DRIVER_INIT(ss23)
{ {
} }
static const gfx_layout namcos23_cg_layout = static const gfx_layout namcos23_cg_layout =
{ {
@ -1279,6 +1301,8 @@ static MACHINE_DRIVER_START( gorgon )
MDRV_CPU_IO_MAP( s23h8iomap, 0 ) MDRV_CPU_IO_MAP( s23h8iomap, 0 )
MDRV_CPU_VBLANK_INT("main", irq1_line_pulse) MDRV_CPU_VBLANK_INT("main", irq1_line_pulse)
MDRV_INTERLEAVE(1000)
MDRV_SCREEN_ADD("main", RASTER) MDRV_SCREEN_ADD("main", RASTER)
MDRV_SCREEN_REFRESH_RATE(60) MDRV_SCREEN_REFRESH_RATE(60)
MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
@ -1315,6 +1339,13 @@ static MACHINE_DRIVER_START( s23 )
MDRV_CPU_IO_MAP( s23h8iomap, 0 ) MDRV_CPU_IO_MAP( s23h8iomap, 0 )
MDRV_CPU_VBLANK_INT("main", irq1_line_pulse) MDRV_CPU_VBLANK_INT("main", irq1_line_pulse)
MDRV_CPU_ADD("ioboard", H83344, 14745600 )
MDRV_CPU_PROGRAM_MAP( s23iobrdmap, 0 )
MDRV_CPU_IO_MAP( s23iobrdiomap, 0 )
MDRV_CPU_VBLANK_INT("main", irq1_line_pulse)
MDRV_INTERLEAVE(1000)
MDRV_SCREEN_ADD("main", RASTER) MDRV_SCREEN_ADD("main", RASTER)
MDRV_SCREEN_REFRESH_RATE(60) MDRV_SCREEN_REFRESH_RATE(60)
@ -1353,6 +1384,8 @@ static MACHINE_DRIVER_START( ss23 )
MDRV_CPU_IO_MAP( s23h8iomap, 0 ) MDRV_CPU_IO_MAP( s23h8iomap, 0 )
MDRV_CPU_VBLANK_INT("main", irq1_line_pulse) MDRV_CPU_VBLANK_INT("main", irq1_line_pulse)
MDRV_INTERLEAVE(1000)
MDRV_SCREEN_ADD("main", RASTER) MDRV_SCREEN_ADD("main", RASTER)
MDRV_SCREEN_REFRESH_RATE(60) MDRV_SCREEN_REFRESH_RATE(60)
MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
@ -1436,6 +1469,53 @@ ROM_START( rapidrvr )
ROM_LOAD( "rd1waveh.3s", 0x800000, 0x800000, CRC(ef0136b5) SHA1(a6d923ededca168fe555e0b86a72f53bec5424cc) ) ROM_LOAD( "rd1waveh.3s", 0x800000, 0x800000, CRC(ef0136b5) SHA1(a6d923ededca168fe555e0b86a72f53bec5424cc) )
ROM_END ROM_END
ROM_START( motoxgo )
ROM_REGION32_BE( 0x400000, "user1", 0 ) /* 4 megs for main R4650 code */
ROM_LOAD16_BYTE( "mg3vera.ic2", 0x000000, 0x200000, CRC(1bf06f00) SHA1(e9d04e9f19bff7a58cb280dd1d5db12801b68ba0) )
ROM_LOAD16_BYTE( "mg3vera.ic1", 0x000001, 0x200000, CRC(f5e6e25b) SHA1(1de30e8e831be66987112645a9db3a3001b89fe6) )
ROM_REGION( 0x80000, "audio", 0 ) /* Hitachi H8/3002 MCU code */
ROM_LOAD16_WORD_SWAP( "mg3vera.ic3", 0x000000, 0x080000, CRC(9e3d46a8) SHA1(9ffa5b91ea51cc0fb97def25ce47efa3441f3c6f) )
ROM_REGION( 0x40000, "ioboard", 0 ) /* I/O board HD643334 H8/3344 MCU code */
ROM_LOAD( "asca-3a.ic14", 0x000000, 0x040000, CRC(8e9266e5) SHA1(ffa8782ca641d71d57df23ed1c5911db05d3df97) )
ROM_REGION( 0x20000, "exioboard", 0 ) /* "extra" I/O board (uses Fujitsu MB90611A MCU) */
ROM_LOAD( "mg1prog0a.3a", 0x000000, 0x020000, CRC(b2b5be8f) SHA1(803652b7b8fde2196b7fb742ba8b9843e4fcd2de) )
ROM_REGION( 0x2000000, "sprite", ROMREGION_ERASEFF ) /* sprite? tilemap? tiles */
ROM_LOAD16_BYTE( "mg1mtal.2h", 0x000000, 0x800000, CRC(fdad0f0a) SHA1(420d50f012af40f80b196d3aae320376e6c32367) )
ROM_LOAD16_BYTE( "mg1mtah.2j", 0x000001, 0x800000, CRC(845f4768) SHA1(9c03b1f6dcd9d1f43c2958d855221be7f9415c47) )
ROM_REGION( 0x2000000, "textile", ROMREGION_ERASEFF ) /* texture tiles */
ROM_LOAD( "mg1cgum.4j", 0x000000, 0x800000, CRC(46a77d73) SHA1(132ce2452ee68ba374e98b59032ac0a1a277078d) )
ROM_LOAD( "mg1cgll.4m", 0x000000, 0x800000, CRC(175dfe34) SHA1(66ae35b0084159aea1afeb1a6486fffa635992b5) )
ROM_LOAD( "mg1cglm.4k", 0x000000, 0x800000, CRC(b3e648e7) SHA1(98018ae2276f905a7f74e1dab540a44247524436) )
ROM_REGION( 0x2000000, "textile2", ROMREGION_ERASEFF ) /* second copy of texture tiles */
ROM_LOAD( "mg1cgum.5j", 0x000000, 0x800000, CRC(46a77d73) SHA1(132ce2452ee68ba374e98b59032ac0a1a277078d) )
ROM_LOAD( "mg1cgll.5m", 0x000000, 0x800000, CRC(175dfe34) SHA1(66ae35b0084159aea1afeb1a6486fffa635992b5) )
ROM_LOAD( "mg1cglm.5k", 0x000000, 0x800000, CRC(b3e648e7) SHA1(98018ae2276f905a7f74e1dab540a44247524436) )
ROM_REGION( 0x600000, "textilemap", ROMREGION_ERASEFF ) /* texture tilemap */
ROM_LOAD( "mg1ccrl.7f", 0x000000, 0x400000, CRC(5372e300) SHA1(63a49782289ed93a321ca7d193241fb83ca97e6b) )
ROM_LOAD( "mg1ccrh.7e", 0x400000, 0x200000, CRC(2e77597d) SHA1(58dd83c1b0c08115e728c5e7dea5e62135b821ba) )
ROM_REGION( 0x600000, "textilemap2", ROMREGION_ERASEFF) /* second copy of texture tilemap */
ROM_LOAD( "mg1ccrl.7m", 0x000000, 0x400000, CRC(5372e300) SHA1(63a49782289ed93a321ca7d193241fb83ca97e6b) )
ROM_LOAD( "mg1ccrh.7k", 0x400000, 0x200000, CRC(2e77597d) SHA1(58dd83c1b0c08115e728c5e7dea5e62135b821ba) )
ROM_REGION32_LE( 0x2000000, "pointrom", ROMREGION_ERASEFF ) /* 3D model data */
ROM_LOAD32_WORD( "mg1pt0l.7c", 0x000000, 0x400000, CRC(3b9e95d3) SHA1(d7823ed6c590669ccd4098ed439599a3eb814ed1) )
ROM_LOAD32_WORD( "mg1pt0h.7a", 0x000002, 0x400000, CRC(c9ba1b47) SHA1(42ec0638edb4c502ff0a340c4cf590bdd767cfe2) )
ROM_LOAD32_WORD( "mg1pt1h.5a", 0x800000, 0x400000, CRC(8d4f7097) SHA1(004e9ed0b5d6ce83ffadb9bd429fa7560abdb598) )
ROM_LOAD32_WORD( "mg1pt1l.5c", 0x800002, 0x400000, CRC(0dd2f358) SHA1(3537e6be3fec9fec8d5a8dd02d9cf67b3805f8f0) )
ROM_REGION( 0x1000000, "c352", ROMREGION_ERASEFF ) /* C352 PCM samples */
ROM_LOAD( "mg1wavel.2c", 0x000000, 0x800000, CRC(f78b1b4d) SHA1(47cd654ec0a69de0dc81b8d83692eebf5611228b) )
ROM_LOAD( "mg1waveh.2a", 0x800000, 0x800000, CRC(8cb73877) SHA1(2e2b170c7ff889770c13b4ab7ac316b386ada153) )
ROM_END
ROM_START( timecrs2 ) ROM_START( timecrs2 )
ROM_REGION32_BE( 0x400000, "user1", 0 ) /* 4 megs for main R4650 code */ ROM_REGION32_BE( 0x400000, "user1", 0 ) /* 4 megs for main R4650 code */
ROM_LOAD16_BYTE( "tss3verb.2", 0x000000, 0x200000, CRC(c7be691f) SHA1(5e2e7a0db3d8ce6dfeb6c0d99e9fe6a9f9cab467) ) ROM_LOAD16_BYTE( "tss3verb.2", 0x000000, 0x200000, CRC(c7be691f) SHA1(5e2e7a0db3d8ce6dfeb6c0d99e9fe6a9f9cab467) )
@ -1444,6 +1524,9 @@ ROM_START( timecrs2 )
ROM_REGION( 0x80000, "audio", 0 ) /* Hitachi H8/3002 MCU code */ ROM_REGION( 0x80000, "audio", 0 ) /* Hitachi H8/3002 MCU code */
ROM_LOAD16_WORD_SWAP( "tss3verb.3", 0x000000, 0x080000, CRC(41e41994) SHA1(eabc1a307c329070bfc6486cb68169c94ff8a162) ) ROM_LOAD16_WORD_SWAP( "tss3verb.3", 0x000000, 0x080000, CRC(41e41994) SHA1(eabc1a307c329070bfc6486cb68169c94ff8a162) )
ROM_REGION( 0x40000, "ioboard", 0 ) /* I/O board HD643334 H8/3344 MCU code */
ROM_LOAD( "tssioprog.ic3", 0x000000, 0x040000, CRC(edad4538) SHA1(1330189184a636328d956c0e435f8d9ad2e96a80) )
ROM_REGION( 0x2000000, "sprite", 0 ) /* sprite? tilemap? tiles */ ROM_REGION( 0x2000000, "sprite", 0 ) /* sprite? tilemap? tiles */
ROM_LOAD16_BYTE( "tss1mtal.2h", 0x0000000, 0x800000, CRC(bfc79190) SHA1(04bda00c4cc5660d27af4f3b0ee3550dea8d3805) ) ROM_LOAD16_BYTE( "tss1mtal.2h", 0x0000000, 0x800000, CRC(bfc79190) SHA1(04bda00c4cc5660d27af4f3b0ee3550dea8d3805) )
ROM_LOAD16_BYTE( "tss1mtah.2j", 0x0000001, 0x800000, CRC(697c26ed) SHA1(72f6f69e89496ba0c6183b35c3bde71f5a3c721f) ) ROM_LOAD16_BYTE( "tss1mtah.2j", 0x0000001, 0x800000, CRC(697c26ed) SHA1(72f6f69e89496ba0c6183b35c3bde71f5a3c721f) )
@ -1481,7 +1564,7 @@ ROM_START( timcrs2b )
ROM_REGION( 0x80000, "audio", 0 ) /* Hitachi H8/3002 MCU code */ ROM_REGION( 0x80000, "audio", 0 ) /* Hitachi H8/3002 MCU code */
ROM_LOAD16_WORD_SWAP( "tss3verb.3", 0x000000, 0x080000, CRC(41e41994) SHA1(eabc1a307c329070bfc6486cb68169c94ff8a162) ) ROM_LOAD16_WORD_SWAP( "tss3verb.3", 0x000000, 0x080000, CRC(41e41994) SHA1(eabc1a307c329070bfc6486cb68169c94ff8a162) )
ROM_REGION( 0x40000, "ioboard", 0 ) /* I/O board HD643334 H8/300 MCU code */ ROM_REGION( 0x40000, "ioboard", 0 ) /* I/O board HD643334 H8/3344 MCU code */
ROM_LOAD( "tssioprog.ic3", 0x000000, 0x040000, CRC(edad4538) SHA1(1330189184a636328d956c0e435f8d9ad2e96a80) ) ROM_LOAD( "tssioprog.ic3", 0x000000, 0x040000, CRC(edad4538) SHA1(1330189184a636328d956c0e435f8d9ad2e96a80) )
ROM_REGION( 0x2000000, "sprite", 0 ) /* sprite? tilemap? tiles */ ROM_REGION( 0x2000000, "sprite", 0 ) /* sprite? tilemap? tiles */
@ -1637,6 +1720,7 @@ ROM_END
/* Games */ /* Games */
GAME( 1997, rapidrvr, 0, gorgon, 0, ss23, ROT0, "Namco", "Rapid River (RD3 Ver. C)", GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_IMPERFECT_SOUND ) GAME( 1997, rapidrvr, 0, gorgon, 0, ss23, ROT0, "Namco", "Rapid River (RD3 Ver. C)", GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_IMPERFECT_SOUND )
GAME( 1997, motoxgo, 0, s23, 0, ss23, ROT0, "Namco", "Motocross Go! (MG3 Ver. A)", GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_IMPERFECT_SOUND )
GAME( 1997, timecrs2, 0, s23, 0, ss23, ROT0, "Namco", "Time Crisis 2 (TSS3 Ver. B)", GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_IMPERFECT_SOUND ) GAME( 1997, timecrs2, 0, s23, 0, ss23, ROT0, "Namco", "Time Crisis 2 (TSS3 Ver. B)", GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_IMPERFECT_SOUND )
GAME( 1997, timcrs2b, timecrs2, s23, 0, ss23, ROT0, "Namco", "Time Crisis 2 (TSS2 Ver. B)", GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_IMPERFECT_SOUND ) GAME( 1997, timcrs2b, timecrs2, s23, 0, ss23, ROT0, "Namco", "Time Crisis 2 (TSS2 Ver. B)", GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_IMPERFECT_SOUND )
GAME( 1999, 500gp, 0, ss23, 0, ss23, ROT0, "Namco", "500GP", GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_IMPERFECT_SOUND ) GAME( 1999, 500gp, 0, ss23, 0, ss23, ROT0, "Namco", "500GP", GAME_NOT_WORKING | GAME_UNEMULATED_PROTECTION | GAME_IMPERFECT_SOUND )

View File

@ -184,6 +184,7 @@ CPUS += GMS30C2216
CPUS += GMS30C2232 CPUS += GMS30C2232
CPUS += I960 CPUS += I960
CPUS += H83002 CPUS += H83002
CPUS += H83344
CPUS += V810 CPUS += V810
CPUS += M37702 CPUS += M37702
CPUS += M37710 CPUS += M37710

View File

@ -862,6 +862,7 @@ const game_driver * const drivers[] =
/* Namco System 23 */ /* Namco System 23 */
DRIVER( rapidrvr ) /* (c) 1997 */ DRIVER( rapidrvr ) /* (c) 1997 */
DRIVER( motoxgo ) /* (c) 1997 */
DRIVER( timecrs2 ) /* (c) 1997 */ DRIVER( timecrs2 ) /* (c) 1997 */
DRIVER( timcrs2b ) /* (c) 1997 */ DRIVER( timcrs2b ) /* (c) 1997 */
DRIVER( 500gp ) /* (c) 1999 */ DRIVER( 500gp ) /* (c) 1999 */