sm8500: Converted to C++ (nw)

This commit is contained in:
Wilbert Pol 2013-01-30 19:54:41 +00:00
parent 30b6014d2d
commit 9de1534f04
6 changed files with 1019 additions and 1115 deletions

View File

@ -21,580 +21,402 @@ they are internally.
#include "debugger.h"
#include "sm8500.h"
#define FLAG_C 0x80
#define FLAG_Z 0x40
#define FLAG_S 0x20
#define FLAG_V 0x10
#define FLAG_D 0x08
#define FLAG_H 0x04
#define FLAG_B 0x02
#define FLAG_I 0x01
struct sm8500_state
{
SM8500_CONFIG config;
UINT16 PC;
UINT8 IE0;
UINT8 IE1;
UINT8 IR0;
UINT8 IR1;
UINT8 SYS;
UINT8 CKC;
UINT8 clock_changed;
UINT16 SP;
UINT8 PS0;
UINT8 PS1;
UINT16 IFLAGS;
UINT8 CheckInterrupts;
int halted;
int icount;
device_irq_acknowledge_callback irq_callback;
legacy_cpu_device *device;
address_space *program;
UINT16 oldpc;
UINT8 register_ram[0x108];
};
const device_type SM8500 = &device_creator<sm8500_cpu_device>;
INLINE sm8500_state *get_safe_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == SM8500);
return (sm8500_state *)downcast<legacy_cpu_device *>(device)->token();
}
static const UINT8 sm8500_b2w[8] = {
0, 8, 2, 10, 4, 12, 6, 14
};
INLINE void sm8500_get_sp( sm8500_state *cpustate )
sm8500_cpu_device::sm8500_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: cpu_device(mconfig, SM8500, "SM8500", tag, owner, clock)
, m_program_config("program", ENDIANNESS_BIG, 8, 16, 0)
, m_dma_func(*this)
, m_timer_func(*this)
{
UINT16 data = cpustate->program->read_byte(0x1c) << 8;
cpustate->SP = cpustate->program->read_byte(0x1d);
if (cpustate->SYS&0x40) cpustate->SP |= data;
}
static UINT8 sm85cpu_mem_readbyte( sm8500_state *cpustate, UINT32 offset )
void sm8500_cpu_device::get_sp()
{
m_SP = m_program->read_byte(0x1d);
if (m_SYS & 0x40) m_SP |= ( m_program->read_byte(0x1c) << 8 );
}
UINT8 sm8500_cpu_device::mem_readbyte( UINT32 offset )
{
offset &= 0xffff;
return (offset < 0x10) ? cpustate->register_ram[offset + (cpustate->PS0 & 0xF8)]
: cpustate->program->read_byte( offset );
if ( offset < 0x10)
{
return m_register_ram[offset + (m_PS0 & 0xF8)];
}
return m_program->read_byte( offset );
}
static void sm85cpu_mem_writebyte( sm8500_state *cpustate, UINT32 offset, UINT8 data )
void sm8500_cpu_device::mem_writebyte( UINT32 offset, UINT8 data )
{
UINT8 i;
offset &= 0xffff;
if (offset < 0x10)
cpustate->register_ram[offset + (cpustate->PS0 & 0xF8)] = data;
{
m_register_ram[offset + (m_PS0 & 0xF8)] = data;
}
cpustate->program->write_byte ( offset, data );
m_program->write_byte( offset, data );
switch (offset)
{
case 0x10: cpustate->IE0 = data; break;
case 0x11: cpustate->IE1 = data; break;
case 0x12: cpustate->IR0 = data; break;
case 0x13: cpustate->IR1 = data; break;
case 0x19: cpustate->SYS = data; break;
case 0x1a: cpustate->CKC = data; break;
case 0x10: m_IE0 = data; break;
case 0x11: m_IE1 = data; break;
case 0x12: m_IR0 = data; break;
case 0x13: m_IR1 = data; break;
case 0x19: m_SYS = data; break;
case 0x1a: m_CKC = data; break;
case 0x1c:
case 0x1d: sm8500_get_sp(cpustate); break;
case 0x1e: cpustate->PS0 = data;
case 0x1d: get_sp(); break;
case 0x1e: m_PS0 = data;
for (i = 0; i < 16; i++) // refresh register contents in debugger
cpustate->program->write_byte(i, sm85cpu_mem_readbyte(cpustate, i)); break;
case 0x1f: cpustate->PS1 = data; break;
{
m_program->write_byte(i, mem_readbyte(i));
}
break;
case 0x1f: m_PS1 = data; break;
}
}
INLINE UINT16 sm85cpu_mem_readword( sm8500_state *cpustate, UINT32 address )
void sm8500_cpu_device::device_start()
{
return (sm85cpu_mem_readbyte( cpustate, address ) << 8) | (sm85cpu_mem_readbyte( cpustate, address+1 ));
m_program = &space(AS_PROGRAM);
m_dma_func.resolve_safe();
m_timer_func.resolve_safe();
save_item(NAME(m_PC));
save_item(NAME(m_IE0));
save_item(NAME(m_IE1));
save_item(NAME(m_IR0));
save_item(NAME(m_IR1));
save_item(NAME(m_SYS));
save_item(NAME(m_CKC));
save_item(NAME(m_clock_changed));
save_item(NAME(m_SP));
save_item(NAME(m_PS0));
save_item(NAME(m_PS1));
save_item(NAME(m_IFLAGS));
save_item(NAME(m_CheckInterrupts));
save_item(NAME(m_halted));
save_item(NAME(m_oldpc));
save_pointer(NAME(m_register_ram),0x108);
// Register state for debugger
state_add(SM8500_PC, "PC", m_PC ).callimport().callexport().formatstr("%04X");
state_add(SM8500_SP, "SP", m_SP ).callimport().callexport().formatstr("%04X");
state_add(SM8500_PS, "PS", m_PS0 ).callimport().callexport().formatstr("%04s");
state_add(SM8500_SYS, "SYS", m_SYS ).callimport().callexport().formatstr("%04X");
state_add(SM8500_RR0, "RR0", m_PC ).callimport().callexport().formatstr("%04s");
state_add(SM8500_RR2, "RR2", m_PC ).callimport().callexport().formatstr("%04s");
state_add(SM8500_RR4, "RR4", m_PC ).callimport().callexport().formatstr("%04s");
state_add(SM8500_RR6, "RR6", m_PC ).callimport().callexport().formatstr("%04s");
state_add(SM8500_RR8, "RR8", m_PC ).callimport().callexport().formatstr("%04s");
state_add(SM8500_RR10, "RR10", m_PC ).callimport().callexport().formatstr("%04s");
state_add(SM8500_RR12, "RR12", m_PC ).callimport().callexport().formatstr("%04s");
state_add(SM8500_RR14, "RR14", m_PC ).callimport().callexport().formatstr("%04s");
state_add(STATE_GENPC, "curpc", m_PC).callimport().callexport().formatstr("%8s").noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", m_PS1).formatstr("%8s").noshow();
m_icountptr = &m_icount;
}
INLINE void sm85cpu_mem_writeword( sm8500_state *cpustate, UINT32 address, UINT16 value )
{
sm85cpu_mem_writebyte( cpustate, address, value >> 8 );
sm85cpu_mem_writebyte( cpustate, address+1, value );
}
static CPU_INIT( sm8500 )
void sm8500_cpu_device::state_string_export(const device_state_entry &entry, astring &string)
{
sm8500_state *cpustate = get_safe_token(device);
switch (entry.index())
{
case SM8500_PS:
string.printf( "%04X", ( m_PS0 << 8 ) | m_PS1 );
break;
cpustate->irq_callback = irqcallback;
cpustate->device = device;
cpustate->program = &device->space(AS_PROGRAM);
if ( device->static_config() != NULL ) {
cpustate->config.handle_dma = ((SM8500_CONFIG *)device->static_config())->handle_dma;
cpustate->config.handle_timers = ((SM8500_CONFIG *)device->static_config())->handle_timers;
} else {
cpustate->config.handle_dma = NULL;
cpustate->config.handle_timers = NULL;
case SM8500_RR0:
string.printf( "%04X", mem_readword( 0x00 ) );
break;
case SM8500_RR2:
string.printf( "%04X", mem_readword( 0x02 ) );
break;
case SM8500_RR4:
string.printf( "%04X", mem_readword( 0x04 ) );
break;
case SM8500_RR6:
string.printf( "%04X", mem_readword( 0x06 ) );
break;
case SM8500_RR8:
string.printf( "%04X", mem_readword( 0x08 ) );
break;
case SM8500_RR10:
string.printf( "%04X", mem_readword( 0x0a ) );
break;
case SM8500_RR12:
string.printf( "%04X", mem_readword( 0x0c ) );
break;
case SM8500_RR14:
string.printf( "%04X", mem_readword( 0x0e ) );
break;
case STATE_GENFLAGS:
string.printf( "%c%c%c%c%c%c%c%c",
m_PS1 & FLAG_C ? 'C' : '.',
m_PS1 & FLAG_Z ? 'Z' : '.',
m_PS1 & FLAG_S ? 'S' : '.',
m_PS1 & FLAG_V ? 'V' : '.',
m_PS1 & FLAG_D ? 'D' : '.',
m_PS1 & FLAG_H ? 'H' : '.',
m_PS1 & FLAG_B ? 'B' : '.',
m_PS1 & FLAG_I ? 'I' : '.' );
break;
}
}
static CPU_RESET( sm8500 )
{
sm8500_state *cpustate = get_safe_token(device);
cpustate->PC = 0x1020;
cpustate->clock_changed = 0;
cpustate->halted = 0;
sm85cpu_mem_writeword(cpustate, 0x10, 0); // IE0, IE1
sm85cpu_mem_writeword(cpustate, 0x12, 0); // IR0, IR1
sm85cpu_mem_writeword(cpustate, 0x14, 0xffff); // P0, P1
sm85cpu_mem_writeword(cpustate, 0x16, 0xff00); // P2, P3
sm85cpu_mem_writebyte(cpustate, 0x19, 0); // SYS
sm85cpu_mem_writebyte(cpustate, 0x1a, 0); // CKC
sm85cpu_mem_writebyte(cpustate, 0x1f, 0); // PS1
sm85cpu_mem_writebyte(cpustate, 0x2b, 0xff); // URTT
sm85cpu_mem_writebyte(cpustate, 0x2d, 0x42); // URTS
sm85cpu_mem_writebyte(cpustate, 0x5f, 0x38); // WDTC
void sm8500_cpu_device::device_reset()
{
for ( int i = 0; i < 0x108; i++ )
{
m_register_ram[i] = 0;
}
m_PC = 0x1020;
m_clock_changed = 0;
m_CheckInterrupts = 0;
m_halted = 0;
m_IFLAGS = 0;
mem_writeword(0x10, 0); // IE0, IE1
mem_writeword(0x12, 0); // IR0, IR1
mem_writeword(0x14, 0xffff); // P0, P1
mem_writeword(0x16, 0xff00); // P2, P3
mem_writebyte(0x19, 0); // SYS
mem_writebyte(0x1a, 0); // CKC
mem_writebyte(0x1f, 0); // PS1
mem_writebyte(0x2b, 0xff); // URTT
mem_writebyte(0x2d, 0x42); // URTS
mem_writebyte(0x5f, 0x38); // WDTC
}
static CPU_EXIT( sm8500 )
#define PUSH_BYTE(X) m_SP--; \
if ( ( m_SYS & 0x40 ) == 0 ) m_SP &= 0xFF; \
mem_writebyte( m_SP, X );
void sm8500_cpu_device::take_interrupt(UINT16 vector)
{
}
#define PUSH_BYTE(X) cpustate->SP--; \
if ( ( cpustate->SYS & 0x40 ) == 0 ) cpustate->SP &= 0xFF; \
sm85cpu_mem_writebyte( cpustate, cpustate->SP, X );
INLINE void sm8500_do_interrupt(sm8500_state *cpustate, UINT16 vector) {
/* Get regs from ram */
sm8500_get_sp(cpustate);
cpustate->SYS = cpustate->program->read_byte(0x19);
cpustate->PS1 = cpustate->program->read_byte(0x1f);
get_sp();
m_SYS = m_program->read_byte(0x19);
m_PS1 = m_program->read_byte(0x1f);
/* Push PC */
PUSH_BYTE( cpustate->PC & 0xFF );
PUSH_BYTE( cpustate->PC >> 8 );
PUSH_BYTE( m_PC & 0xFF );
PUSH_BYTE( m_PC >> 8 );
/* Push PS1 */
PUSH_BYTE( cpustate->PS1 );
PUSH_BYTE( m_PS1 );
/* Clear I flag */
cpustate->PS1 &= ~ 0x01;
m_PS1 &= ~ 0x01;
/* save regs to ram */
cpustate->program->write_byte (0x1f, cpustate->PS1);
cpustate->program->write_byte (0x1d, cpustate->SP&0xFF);
if (cpustate->SYS&0x40) cpustate->program->write_byte(0x1c, cpustate->SP>>8);
m_program->write_byte(0x1f, m_PS1);
m_program->write_byte(0x1d, m_SP&0xFF);
if (m_SYS&0x40) m_program->write_byte(0x1c, m_SP>>8);
/* Change PC to address stored at "vector" */
cpustate->PC = sm85cpu_mem_readword( cpustate, vector );
m_PC = mem_readword( vector );
}
INLINE void sm8500_process_interrupts(sm8500_state *cpustate) {
if ( cpustate->CheckInterrupts ) {
void sm8500_cpu_device::process_interrupts()
{
if ( m_CheckInterrupts )
{
int irqline = 0;
while( irqline < 11 ) {
if ( cpustate->IFLAGS & ( 1 << irqline ) ) {
cpustate->halted = 0;
cpustate->IE0 = cpustate->program->read_byte(0x10);
cpustate->IE1 = cpustate->program->read_byte(0x11);
cpustate->IR0 = cpustate->program->read_byte(0x12);
cpustate->IR1 = cpustate->program->read_byte(0x13);
cpustate->PS0 = cpustate->program->read_byte(0x1e);
cpustate->PS1 = cpustate->program->read_byte(0x1f);
switch( irqline ) {
while( irqline < 11 )
{
if ( m_IFLAGS & ( 1 << irqline ) )
{
m_halted = 0;
m_IE0 = m_program->read_byte(0x10);
m_IE1 = m_program->read_byte(0x11);
m_IR0 = m_program->read_byte(0x12);
m_IR1 = m_program->read_byte(0x13);
m_PS0 = m_program->read_byte(0x1e);
m_PS1 = m_program->read_byte(0x1f);
switch( irqline )
{
case WDT_INT:
sm8500_do_interrupt( cpustate, 0x101C );
take_interrupt( 0x101C );
break;
case ILL_INT:
case NMI_INT:
sm8500_do_interrupt( cpustate, 0x101E );
take_interrupt( 0x101E );
break;
case DMA_INT:
cpustate->IR0 |= 0x80;
if ( ( cpustate->IE0 & 0x80 ) && ( ( cpustate->PS0 & 0x07 ) < 8 ) && ( cpustate->PS1 & 0x01 ) ) {
sm8500_do_interrupt( cpustate, 0x1000 );
m_IR0 |= 0x80;
if ( ( m_IE0 & 0x80 ) && ( ( m_PS0 & 0x07 ) < 8 ) && ( m_PS1 & 0x01 ) )
{
take_interrupt( 0x1000 );
}
break;
case TIM0_INT:
cpustate->IR0 |= 0x40;
if ( ( cpustate->IE0 & 0x40 ) && ( ( cpustate->PS0 & 0x07 ) < 8 ) && ( cpustate->PS1 & 0x01 ) ) {
sm8500_do_interrupt( cpustate, 0x1002 );
m_IR0 |= 0x40;
if ( ( m_IE0 & 0x40 ) && ( ( m_PS0 & 0x07 ) < 8 ) && ( m_PS1 & 0x01 ) )
{
take_interrupt( 0x1002 );
}
break;
case EXT_INT:
cpustate->IR0 |= 0x10;
if ( ( cpustate->IE0 & 0x10 ) && ( ( cpustate->PS0 & 0x07 ) < 7 ) && ( cpustate->PS1 & 0x01 ) ) {
sm8500_do_interrupt( cpustate, 0x1006 );
m_IR0 |= 0x10;
if ( ( m_IE0 & 0x10 ) && ( ( m_PS0 & 0x07 ) < 7 ) && ( m_PS1 & 0x01 ) )
{
take_interrupt( 0x1006 );
}
break;
case UART_INT:
cpustate->IR0 |= 0x08;
if ( ( cpustate->IE0 & 0x08 ) && ( ( cpustate->PS0 & 0x07 ) < 6 ) && ( cpustate->PS1 & 0x01 ) ) {
sm8500_do_interrupt( cpustate, 0x1008 );
m_IR0 |= 0x08;
if ( ( m_IE0 & 0x08 ) && ( ( m_PS0 & 0x07 ) < 6 ) && ( m_PS1 & 0x01 ) )
{
take_interrupt( 0x1008 );
}
break;
case LCDC_INT:
cpustate->IR0 |= 0x01;
if ( ( cpustate->IE0 & 0x01 ) && ( ( cpustate->PS0 & 0x07 ) < 5 ) && ( cpustate->PS1 & 0x01 ) ) {
sm8500_do_interrupt( cpustate, 0x100E );
m_IR0 |= 0x01;
if ( ( m_IE0 & 0x01 ) && ( ( m_PS0 & 0x07 ) < 5 ) && ( m_PS1 & 0x01 ) )
{
take_interrupt( 0x100E );
}
break;
case TIM1_INT:
cpustate->IR1 |= 0x40;
if ( ( cpustate->IE1 & 0x40 ) && ( ( cpustate->PS0 & 0x07 ) < 4 ) && ( cpustate->PS1 & 0x01 ) ) {
sm8500_do_interrupt( cpustate, 0x1012 );
m_IR1 |= 0x40;
if ( ( m_IE1 & 0x40 ) && ( ( m_PS0 & 0x07 ) < 4 ) && ( m_PS1 & 0x01 ) )
{
take_interrupt( 0x1012 );
}
break;
case CK_INT:
cpustate->IR1 |= 0x10;
if ( ( cpustate->IE1 & 0x10 ) && ( ( cpustate->PS0 & 0x07 ) < 3 ) && ( cpustate->PS1 & 0x01 ) ) {
sm8500_do_interrupt( cpustate, 0x1016 );
m_IR1 |= 0x10;
if ( ( m_IE1 & 0x10 ) && ( ( m_PS0 & 0x07 ) < 3 ) && ( m_PS1 & 0x01 ) )
{
take_interrupt( 0x1016 );
}
break;
case PIO_INT:
cpustate->IR1 |= 0x04;
if ( ( cpustate->IE1 & 0x04 ) && ( ( cpustate->PS0 & 0x07 ) < 2 ) && ( cpustate->PS1 & 0x01 ) ) {
sm8500_do_interrupt( cpustate, 0x101A );
m_IR1 |= 0x04;
if ( ( m_IE1 & 0x04 ) && ( ( m_PS0 & 0x07 ) < 2 ) && ( m_PS1 & 0x01 ) )
{
take_interrupt( 0x101A );
}
break;
}
cpustate->IFLAGS &= ~ ( 1 << irqline );
cpustate->program->write_byte(0x12, cpustate->IR0);
cpustate->program->write_byte(0x13, cpustate->IR1);
m_IFLAGS &= ~ ( 1 << irqline );
m_program->write_byte(0x12, m_IR0);
m_program->write_byte(0x13, m_IR1);
}
irqline++;
}
}
}
static CPU_EXECUTE( sm8500 )
{
sm8500_state *cpustate = get_safe_token(device);
UINT8 op;
int mycycles;
offs_t sm8500_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
{
extern CPU_DISASSEMBLE( sm8500 );
return CPU_DISASSEMBLE_NAME( sm8500 )(NULL, buffer, pc, oprom, opram, 0);
}
void sm8500_cpu_device::execute_run()
{
do
{
int mycycles = 0;
UINT8 r1,r2;
UINT16 s1,s2;
UINT32 d1,d2;
UINT32 res;
debugger_instruction_hook(device, cpustate->PC);
cpustate->oldpc = cpustate->PC;
mycycles = 0;
sm8500_process_interrupts(cpustate);
if ( !cpustate->halted ) {
op = sm85cpu_mem_readbyte( cpustate, cpustate->PC++ );
cpustate->SYS = cpustate->program->read_byte(0x19);
cpustate->PS0 = cpustate->program->read_byte(0x1e);
cpustate->PS1 = cpustate->program->read_byte(0x1f);
sm8500_get_sp(cpustate);
debugger_instruction_hook(this, m_PC);
m_oldpc = m_PC;
process_interrupts();
if ( !m_halted ) {
UINT8 op = mem_readbyte( m_PC++ );
m_SYS = m_program->read_byte(0x19);
m_PS0 = m_program->read_byte(0x1e);
m_PS1 = m_program->read_byte(0x1f);
get_sp();
switch( op )
{
#include "sm85ops.h"
}
if (cpustate->SYS&0x40) cpustate->program->write_byte(0x1c,cpustate->SP>>8);
cpustate->program->write_byte(0x1d,cpustate->SP&0xFF);
sm85cpu_mem_writebyte(cpustate,0x1e,cpustate->PS0); // need to update debugger
cpustate->program->write_byte(0x1f,cpustate->PS1);
if (m_SYS&0x40) m_program->write_byte(0x1c,m_SP>>8);
m_program->write_byte(0x1d,m_SP&0xFF);
mem_writebyte(0x1e,m_PS0); // need to update debugger
m_program->write_byte(0x1f,m_PS1);
} else {
mycycles = 4;
if ( cpustate->config.handle_dma ) {
cpustate->config.handle_dma( device, mycycles );
}
m_dma_func( mycycles );
}
if ( cpustate->config.handle_timers ) {
cpustate->config.handle_timers( device, mycycles );
}
cpustate->icount -= mycycles;
} while ( cpustate->icount > 0 );
m_timer_func( mycycles );
m_icount -= mycycles;
} while ( m_icount > 0 );
}
static CPU_BURN( sm8500 )
{
sm8500_state *cpustate = get_safe_token(device);
if ( cycles > 0 ) {
/* burn a number of 4 cycles */
int n = ( cycles + 3 ) / 4;
cpustate->icount -= 4 * n;
}
}
static unsigned sm8500_get_reg( sm8500_state *cpustate, int regnum )
void sm8500_cpu_device::execute_set_input( int inptnum, int state )
{
switch( regnum )
m_IR0 = m_program->read_byte(0x12);
m_IR1 = m_program->read_byte(0x13);
if ( state == ASSERT_LINE )
{
case STATE_GENPC:
case SM8500_PC: return cpustate->PC;
case STATE_GENSP:
case SM8500_SP: return cpustate->SP;
case SM8500_PS: return sm85cpu_mem_readword( cpustate, 0x1e );
case SM8500_SYS16: return cpustate->SYS;
case SM8500_RR0: return sm85cpu_mem_readword( cpustate, 0x00 );
case SM8500_RR2: return sm85cpu_mem_readword( cpustate, 0x02 );
case SM8500_RR4: return sm85cpu_mem_readword( cpustate, 0x04 );
case SM8500_RR6: return sm85cpu_mem_readword( cpustate, 0x06 );
case SM8500_RR8: return sm85cpu_mem_readword( cpustate, 0x08 );
case SM8500_RR10: return sm85cpu_mem_readword( cpustate, 0x0A );
case SM8500_RR12: return sm85cpu_mem_readword( cpustate, 0x0C );
case SM8500_RR14: return sm85cpu_mem_readword( cpustate, 0x0E );
case SM8500_IE0: return sm85cpu_mem_readbyte( cpustate, 0x10 );
case SM8500_IE1: return sm85cpu_mem_readbyte( cpustate, 0x11 );
case SM8500_IR0: return sm85cpu_mem_readbyte( cpustate, 0x12 );
case SM8500_IR1: return sm85cpu_mem_readbyte( cpustate, 0x13 );
case SM8500_P0: return sm85cpu_mem_readbyte( cpustate, 0x14 );
case SM8500_P1: return sm85cpu_mem_readbyte( cpustate, 0x15 );
case SM8500_P2: return sm85cpu_mem_readbyte( cpustate, 0x16 );
case SM8500_P3: return sm85cpu_mem_readbyte( cpustate, 0x17 );
case SM8500_SYS: return sm85cpu_mem_readbyte( cpustate, 0x19 );
case SM8500_CKC: return sm85cpu_mem_readbyte( cpustate, 0x1a );
case SM8500_SPH: return sm85cpu_mem_readbyte( cpustate, 0x1c );
case SM8500_SPL: return sm85cpu_mem_readbyte( cpustate, 0x1d );
case SM8500_PS0: return sm85cpu_mem_readbyte( cpustate, 0x1e );
case SM8500_PS1: return sm85cpu_mem_readbyte( cpustate, 0x1f );
case SM8500_P0C: return sm85cpu_mem_readbyte( cpustate, 0x20 );
case SM8500_P1C: return sm85cpu_mem_readbyte( cpustate, 0x21 );
case SM8500_P2C: return sm85cpu_mem_readbyte( cpustate, 0x22 );
case SM8500_P3C: return sm85cpu_mem_readbyte( cpustate, 0x23 );
}
return 0;
}
static void sm8500_set_reg( sm8500_state *cpustate, int regnum, unsigned val )
{
switch( regnum )
{
case STATE_GENPC:
case SM8500_PC: cpustate->PC = val; break;
case STATE_GENSP:
case SM8500_SP: cpustate->SP = val; cpustate->program->write_byte(0x1d, val&0xff); if (cpustate->SYS&0x40) cpustate->program->write_byte(0x1c, val>>8); break;
case SM8500_PS: sm85cpu_mem_writeword( cpustate, 0x1e, val); break;
case SM8500_SYS16: val&=0xff; sm85cpu_mem_writebyte( cpustate, 0x19, val); break;
case SM8500_RR0: sm85cpu_mem_writeword( cpustate, 0x00, val); break;
case SM8500_RR2: sm85cpu_mem_writeword( cpustate, 0x02, val); break;
case SM8500_RR4: sm85cpu_mem_writeword( cpustate, 0x04, val); break;
case SM8500_RR6: sm85cpu_mem_writeword( cpustate, 0x06, val); break;
case SM8500_RR8: sm85cpu_mem_writeword( cpustate, 0x08, val); break;
case SM8500_RR10: sm85cpu_mem_writeword( cpustate, 0x0A, val); break;
case SM8500_RR12: sm85cpu_mem_writeword( cpustate, 0x0C, val); break;
case SM8500_RR14: sm85cpu_mem_writeword( cpustate, 0x0E, val); break;
case SM8500_IE0: sm85cpu_mem_writebyte( cpustate, 0x10, val); break;
case SM8500_IE1: sm85cpu_mem_writebyte( cpustate, 0x11, val); break;
case SM8500_IR0: sm85cpu_mem_writebyte( cpustate, 0x12, val); break;
case SM8500_IR1: sm85cpu_mem_writebyte( cpustate, 0x13, val); break;
case SM8500_P0: sm85cpu_mem_writebyte( cpustate, 0x14, val); break;
case SM8500_P1: sm85cpu_mem_writebyte( cpustate, 0x15, val); break;
case SM8500_P2: sm85cpu_mem_writebyte( cpustate, 0x16, val); break;
case SM8500_P3: sm85cpu_mem_writebyte( cpustate, 0x17, val); break;
case SM8500_SYS: sm85cpu_mem_writebyte( cpustate, 0x19, val); break;
case SM8500_CKC: sm85cpu_mem_writebyte( cpustate, 0x1a, val); if ( val & 0x80 ) { cpustate->clock_changed = 1; }; break;
case SM8500_SPH: sm85cpu_mem_writebyte( cpustate, 0x1c, val); break;
case SM8500_SPL: sm85cpu_mem_writebyte( cpustate, 0x1d, val); break;
case SM8500_PS0: sm85cpu_mem_writebyte( cpustate, 0x1e, val); break;
case SM8500_PS1: sm85cpu_mem_writebyte( cpustate, 0x1f, val); break;
case SM8500_P0C: sm85cpu_mem_writebyte( cpustate, 0x20, val); break;
case SM8500_P1C: sm85cpu_mem_writebyte( cpustate, 0x21, val); break;
case SM8500_P2C: sm85cpu_mem_writebyte( cpustate, 0x22, val); break;
case SM8500_P3C: sm85cpu_mem_writebyte( cpustate, 0x23, val); break;
}
}
static void sm8500_set_irq_line( sm8500_state *cpustate, int irqline, int state )
{
cpustate->IR0 = cpustate->program->read_byte(0x12);
cpustate->IR1 = cpustate->program->read_byte(0x13);
if ( state == ASSERT_LINE ) {
cpustate->IFLAGS |= ( 0x01 << irqline );
cpustate->CheckInterrupts = 1;
switch( irqline ) {
case DMA_INT: cpustate->IR0 |= 0x80; break;
case TIM0_INT: cpustate->IR0 |= 0x40; break;
case EXT_INT: cpustate->IR0 |= 0x10; break;
case UART_INT: cpustate->IR0 |= 0x08; break;
case LCDC_INT: cpustate->IR0 |= 0x01; break;
case TIM1_INT: cpustate->IR1 |= 0x40; break;
case CK_INT: cpustate->IR1 |= 0x10; break;
case PIO_INT: cpustate->IR1 |= 0x04; break;
}
} else {
cpustate->IFLAGS &= ~( 0x01 << irqline );
switch( irqline ) {
case DMA_INT: cpustate->IR0 &= ~0x80; break;
case TIM0_INT: cpustate->IR0 &= ~0x40; break;
case EXT_INT: cpustate->IR0 &= ~0x10; break;
case UART_INT: cpustate->IR0 &= ~0x08; break;
case LCDC_INT: cpustate->IR0 &= ~0x01; break;
case TIM1_INT: cpustate->IR1 &= ~0x40; break;
case CK_INT: cpustate->IR1 &= ~0x10; break;
case PIO_INT: cpustate->IR1 &= ~0x04; break;
}
if ( 0 == cpustate->IFLAGS ) {
cpustate->CheckInterrupts = 0;
m_IFLAGS |= ( 0x01 << inptnum );
m_CheckInterrupts = 1;
switch( inptnum )
{
case DMA_INT: m_IR0 |= 0x80; break;
case TIM0_INT: m_IR0 |= 0x40; break;
case EXT_INT: m_IR0 |= 0x10; break;
case UART_INT: m_IR0 |= 0x08; break;
case LCDC_INT: m_IR0 |= 0x01; break;
case TIM1_INT: m_IR1 |= 0x40; break;
case CK_INT: m_IR1 |= 0x10; break;
case PIO_INT: m_IR1 |= 0x04; break;
}
}
cpustate->program->write_byte(0x12, cpustate->IR0);
cpustate->program->write_byte(0x13, cpustate->IR1);
}
static CPU_SET_INFO( sm8500 )
{
sm8500_state *cpustate = get_safe_token(device);
switch(state)
else
{
case CPUINFO_INT_INPUT_STATE + 0:
case CPUINFO_INT_INPUT_STATE + 1:
case CPUINFO_INT_INPUT_STATE + 2:
case CPUINFO_INT_INPUT_STATE + 3:
case CPUINFO_INT_INPUT_STATE + 4:
case CPUINFO_INT_INPUT_STATE + 5:
case CPUINFO_INT_INPUT_STATE + 6:
case CPUINFO_INT_INPUT_STATE + 7:
case CPUINFO_INT_INPUT_STATE + 8:
case CPUINFO_INT_INPUT_STATE + 9:
case CPUINFO_INT_INPUT_STATE + 10:
sm8500_set_irq_line( cpustate, state - CPUINFO_INT_INPUT_STATE, info->i ); break;
case CPUINFO_INT_REGISTER + SM8500_RR0:
case CPUINFO_INT_REGISTER + SM8500_RR2:
case CPUINFO_INT_REGISTER + SM8500_RR4:
case CPUINFO_INT_REGISTER + SM8500_RR6:
case CPUINFO_INT_REGISTER + SM8500_RR8:
case CPUINFO_INT_REGISTER + SM8500_RR10:
case CPUINFO_INT_REGISTER + SM8500_RR12:
case CPUINFO_INT_REGISTER + SM8500_RR14:
case CPUINFO_INT_REGISTER + SM8500_PC:
case CPUINFO_INT_REGISTER + SM8500_SP:
case CPUINFO_INT_REGISTER + SM8500_PS:
case CPUINFO_INT_REGISTER + SM8500_SYS16:
case CPUINFO_INT_REGISTER + SM8500_SYS:
case CPUINFO_INT_REGISTER + SM8500_IE0:
case CPUINFO_INT_REGISTER + SM8500_IE1:
case CPUINFO_INT_REGISTER + SM8500_IR0:
case CPUINFO_INT_REGISTER + SM8500_IR1:
case CPUINFO_INT_REGISTER + SM8500_P0:
case CPUINFO_INT_REGISTER + SM8500_P1:
case CPUINFO_INT_REGISTER + SM8500_P2:
case CPUINFO_INT_REGISTER + SM8500_P3:
case CPUINFO_INT_REGISTER + SM8500_CKC:
case CPUINFO_INT_REGISTER + SM8500_SPH:
case CPUINFO_INT_REGISTER + SM8500_SPL:
case CPUINFO_INT_REGISTER + SM8500_PS0:
case CPUINFO_INT_REGISTER + SM8500_PS1:
case CPUINFO_INT_REGISTER + SM8500_P0C:
case CPUINFO_INT_REGISTER + SM8500_P1C:
case CPUINFO_INT_REGISTER + SM8500_P2C:
case CPUINFO_INT_REGISTER + SM8500_P3C:
sm8500_set_reg( cpustate, state - CPUINFO_INT_REGISTER, info->i ); break;
m_IFLAGS &= ~( 0x01 << inptnum );
switch( inptnum )
{
case DMA_INT: m_IR0 &= ~0x80; break;
case TIM0_INT: m_IR0 &= ~0x40; break;
case EXT_INT: m_IR0 &= ~0x10; break;
case UART_INT: m_IR0 &= ~0x08; break;
case LCDC_INT: m_IR0 &= ~0x01; break;
case TIM1_INT: m_IR1 &= ~0x40; break;
case CK_INT: m_IR1 &= ~0x10; break;
case PIO_INT: m_IR1 &= ~0x04; break;
}
if ( 0 == m_IFLAGS )
{
m_CheckInterrupts = 0;
}
}
m_program->write_byte(0x12, m_IR0);
m_program->write_byte(0x13, m_IR1);
}
CPU_GET_INFO( sm8500 )
{
sm8500_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
switch(state)
{
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(sm8500_state); break;
case CPUINFO_INT_INPUT_LINES: info->i = 8; break;
case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0xff; break;
case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 5; break;
case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
case CPUINFO_INT_MAX_CYCLES: info->i = 16; break;
case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break;
case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break;
case CPUINFO_INT_INPUT_STATE + 0:
case CPUINFO_INT_INPUT_STATE + 1:
case CPUINFO_INT_INPUT_STATE + 2:
case CPUINFO_INT_INPUT_STATE + 3:
case CPUINFO_INT_INPUT_STATE + 4:
case CPUINFO_INT_INPUT_STATE + 5:
case CPUINFO_INT_INPUT_STATE + 6:
case CPUINFO_INT_INPUT_STATE + 7:
case CPUINFO_INT_INPUT_STATE + 8:
case CPUINFO_INT_INPUT_STATE + 9:
case CPUINFO_INT_INPUT_STATE + 10: info->i = cpustate->IFLAGS & ( 1 << (state - CPUINFO_INT_INPUT_STATE)); break;
case CPUINFO_INT_REGISTER + SM8500_RR0:
case CPUINFO_INT_REGISTER + SM8500_RR2:
case CPUINFO_INT_REGISTER + SM8500_RR4:
case CPUINFO_INT_REGISTER + SM8500_RR6:
case CPUINFO_INT_REGISTER + SM8500_RR8:
case CPUINFO_INT_REGISTER + SM8500_RR10:
case CPUINFO_INT_REGISTER + SM8500_RR12:
case CPUINFO_INT_REGISTER + SM8500_RR14:
case CPUINFO_INT_REGISTER + SM8500_PC:
case CPUINFO_INT_REGISTER + SM8500_SP:
case CPUINFO_INT_REGISTER + SM8500_PS:
case CPUINFO_INT_REGISTER + SM8500_SYS16:
case CPUINFO_INT_REGISTER + SM8500_SYS:
case CPUINFO_INT_REGISTER + SM8500_IE0:
case CPUINFO_INT_REGISTER + SM8500_IE1:
case CPUINFO_INT_REGISTER + SM8500_IR0:
case CPUINFO_INT_REGISTER + SM8500_IR1:
case CPUINFO_INT_REGISTER + SM8500_P0:
case CPUINFO_INT_REGISTER + SM8500_P1:
case CPUINFO_INT_REGISTER + SM8500_P2:
case CPUINFO_INT_REGISTER + SM8500_P3:
case CPUINFO_INT_REGISTER + SM8500_CKC:
case CPUINFO_INT_REGISTER + SM8500_SPH:
case CPUINFO_INT_REGISTER + SM8500_SPL:
case CPUINFO_INT_REGISTER + SM8500_PS0:
case CPUINFO_INT_REGISTER + SM8500_PS1:
case CPUINFO_INT_REGISTER + SM8500_P0C:
case CPUINFO_INT_REGISTER + SM8500_P1C:
case CPUINFO_INT_REGISTER + SM8500_P2C:
case CPUINFO_INT_REGISTER + SM8500_P3C:
info->i = sm8500_get_reg( cpustate, state - CPUINFO_INT_REGISTER ); break;
case CPUINFO_INT_REGISTER + STATE_GENPC: info->i = sm8500_get_reg( cpustate, SM8500_PC ); break;
case CPUINFO_INT_REGISTER + STATE_GENSP: info->i = sm8500_get_reg( cpustate, SM8500_SP ); break;
case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->oldpc; break;
case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(sm8500); break;
case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(sm8500); break;
case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(sm8500); break;
case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(sm8500); break;
case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(sm8500); break;
case CPUINFO_FCT_BURN: info->burn = CPU_BURN_NAME(sm8500); break;
case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(sm8500); break;
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
case CPUINFO_STR_NAME: strcpy( info->s, "sm8500" ); break;
case CPUINFO_STR_FAMILY: strcpy( info->s, "Sharp SM8500" ); break;
case CPUINFO_STR_VERSION: strcpy( info->s, "0.1" ); break;
case CPUINFO_STR_SOURCE_FILE: strcpy( info->s, __FILE__ ); break;
case CPUINFO_STR_CREDITS: strcpy( info->s, "Copyright The MESS Team." ); break;
case CPUINFO_STR_FLAGS:
sprintf( info->s, "%c%c%c%c%c%c%c%c",
cpustate->PS1 & FLAG_C ? 'C' : '.',
cpustate->PS1 & FLAG_Z ? 'Z' : '.',
cpustate->PS1 & FLAG_S ? 'S' : '.',
cpustate->PS1 & FLAG_V ? 'V' : '.',
cpustate->PS1 & FLAG_D ? 'D' : '.',
cpustate->PS1 & FLAG_H ? 'H' : '.',
cpustate->PS1 & FLAG_B ? 'B' : '.',
cpustate->PS1 & FLAG_I ? 'I' : '.' );
break;
case CPUINFO_STR_REGISTER + SM8500_RR0: sprintf(info->s, "RR0:%04X", sm85cpu_mem_readword( cpustate, 0x00 ) ); break;
case CPUINFO_STR_REGISTER + SM8500_RR2: sprintf(info->s, "RR2:%04X", sm85cpu_mem_readword( cpustate, 0x02 ) ); break;
case CPUINFO_STR_REGISTER + SM8500_RR4: sprintf(info->s, "RR4:%04X", sm85cpu_mem_readword( cpustate, 0x04 ) ); break;
case CPUINFO_STR_REGISTER + SM8500_RR6: sprintf(info->s, "RR6:%04X", sm85cpu_mem_readword( cpustate, 0x06 ) ); break;
case CPUINFO_STR_REGISTER + SM8500_RR8: sprintf(info->s, "RR8:%04X", sm85cpu_mem_readword( cpustate, 0x08 ) ); break;
case CPUINFO_STR_REGISTER + SM8500_RR10: sprintf(info->s, "RR10:%04X", sm85cpu_mem_readword( cpustate, 0x0A ) ); break;
case CPUINFO_STR_REGISTER + SM8500_RR12: sprintf(info->s, "RR12:%04X", sm85cpu_mem_readword( cpustate, 0x0C ) ); break;
case CPUINFO_STR_REGISTER + SM8500_RR14: sprintf(info->s, "RR14:%04X", sm85cpu_mem_readword( cpustate, 0x0E ) ); break;
case CPUINFO_STR_REGISTER + SM8500_PC: sprintf(info->s, "PC:%04X", cpustate->PC); break;
case CPUINFO_STR_REGISTER + SM8500_SP: sprintf(info->s, "SP:%04X", cpustate->SP); break;
case CPUINFO_STR_REGISTER + SM8500_PS: sprintf(info->s, "PS:%04X", ( cpustate->PS0 << 8 ) | cpustate->PS1 ); break;
case CPUINFO_STR_REGISTER + SM8500_SYS16: sprintf(info->s, "SYS:%02X", cpustate->SYS ); break;
}
}
DEFINE_LEGACY_CPU_DEVICE(SM8500, sm8500);

View File

@ -3,24 +3,13 @@
#ifndef __SM8500_H__
#define __SM8500_H__
#define MCFG_SM8500_DMA_CB(_devcb) \
sm8500_cpu_device::set_dma_cb(*device, DEVCB2_##_devcb); \
struct SM8500_CONFIG {
void (*handle_dma)(device_t *device, int cycles);
void (*handle_timers)(device_t *device, int cycles);
};
/* interrupts */
#define ILL_INT 0
#define DMA_INT 1
#define TIM0_INT 2
#define EXT_INT 3
#define UART_INT 4
#define LCDC_INT 5
#define TIM1_INT 6
#define CK_INT 7
#define PIO_INT 8
#define WDT_INT 9
#define NMI_INT 10
#define MCFG_SM8500_TIMER_CB(_devcb) \
sm8500_cpu_device::set_timer_cb(*device, DEVCB2_##_devcb); \
enum
{
@ -32,8 +21,98 @@ enum
SM8500_SPH, SM8500_SPL, SM8500_PS0, SM8500_PS1, SM8500_P0C, SM8500_P1C, SM8500_P2C, SM8500_P3C,
};
DECLARE_LEGACY_CPU_DEVICE(SM8500, sm8500);
extern CPU_DISASSEMBLE( sm8500 );
class sm8500_cpu_device : public cpu_device
{
public:
// construction/destruction
sm8500_cpu_device(const machine_config &mconfig, const char *_tag, device_t *_owner, UINT32 _clock);
// static configuration helpers
template<class _Object> static devcb2_base &set_dma_cb(device_t &device, _Object object) { return downcast<sm8500_cpu_device &>(device).m_dma_func.set_callback(object); }
template<class _Object> static devcb2_base &set_timer_cb(device_t &device, _Object object) { return downcast<sm8500_cpu_device &>(device).m_timer_func.set_callback(object); }
/* interrupts */
static const int ILL_INT = 0;
static const int DMA_INT = 1;
static const int TIM0_INT = 2;
static const int EXT_INT = 3;
static const int UART_INT = 4;
static const int LCDC_INT = 5;
static const int TIM1_INT = 6;
static const int CK_INT = 7;
static const int PIO_INT = 8;
static const int WDT_INT = 9;
static const int NMI_INT = 10;
protected:
// Flags
static const UINT8 FLAG_C = 0x80;
static const UINT8 FLAG_Z = 0x40;
static const UINT8 FLAG_S = 0x20;
static const UINT8 FLAG_V = 0x10;
static const UINT8 FLAG_D = 0x08;
static const UINT8 FLAG_H = 0x04;
static const UINT8 FLAG_B = 0x02;
static const UINT8 FLAG_I = 0x01;
// device-level overrides
virtual void device_start();
virtual void device_reset();
// device_execute_interface overrides
virtual UINT32 execute_min_cycles() const { return 1; }
virtual UINT32 execute_max_cycles() const { return 16; }
virtual UINT32 execute_input_lines() const { return 11; }
virtual void execute_run();
virtual void execute_set_input(int inputnum, int state);
// device_memory_interface overrides
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; }
// device_state_interface overrides
void state_string_export(const device_state_entry &entry, astring &string);
// device_disasm_interface overrides
virtual UINT32 disasm_min_opcode_bytes() const { return 1; }
virtual UINT32 disasm_max_opcode_bytes() const { return 5; }
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
inline void get_sp();
inline UINT8 mem_readbyte(UINT32 offset);
inline void mem_writebyte(UINT32 offset, UINT8 data);
inline UINT16 mem_readword(UINT32 address) { return (mem_readbyte(address ) << 8) | (mem_readbyte(address+1)); }
inline void mem_writeword(UINT32 address, UINT16 value) { mem_writebyte(address, value >> 8); mem_writebyte(address+1, value); }
inline void take_interrupt(UINT16 vector);
void process_interrupts();
address_space_config m_program_config;
devcb2_write8 m_dma_func;
devcb2_write8 m_timer_func;
UINT16 m_PC;
UINT8 m_IE0;
UINT8 m_IE1;
UINT8 m_IR0;
UINT8 m_IR1;
UINT8 m_SYS;
UINT8 m_CKC;
UINT8 m_clock_changed;
UINT16 m_SP;
UINT8 m_PS0;
UINT8 m_PS1;
UINT16 m_IFLAGS;
UINT8 m_CheckInterrupts;
int m_halted;
int m_icount;
address_space *m_program;
UINT16 m_oldpc;
UINT8 m_register_ram[0x108];
};
extern const device_type SM8500;
#endif /* __SM8500_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -33,11 +33,6 @@ static ADDRESS_MAP_START(gamecom_mem_map, AS_PROGRAM, 8, gamecom_state)
AM_RANGE( 0xE000, 0xFFFF ) AM_RAM AM_SHARE("p_nvram")// AM_SHARE("nvram") /* Extended I/O, Extended RAM */
ADDRESS_MAP_END
static const SM8500_CONFIG gamecom_cpu_config = {
gamecom_handle_dma,
gamecom_update_timers
};
static INPUT_PORTS_START( gamecom )
PORT_START("IN0")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_NAME( "Up" )
@ -91,14 +86,15 @@ UINT32 gamecom_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap,
INTERRUPT_GEN_MEMBER(gamecom_state::gamecom_interrupt)
{
m_maincpu->set_input_line(LCDC_INT, ASSERT_LINE );
m_maincpu->set_input_line(sm8500_cpu_device::LCDC_INT, ASSERT_LINE );
}
static MACHINE_CONFIG_START( gamecom, gamecom_state )
/* basic machine hardware */
MCFG_CPU_ADD( "maincpu", SM8500, XTAL_11_0592MHz/2 ) /* actually it's an sm8521 microcontroller containing an sm8500 cpu */
MCFG_CPU_PROGRAM_MAP( gamecom_mem_map)
MCFG_CPU_CONFIG( gamecom_cpu_config )
MCFG_SM8500_DMA_CB( WRITE8( gamecom_state, gamecom_handle_dma ) )
MCFG_SM8500_TIMER_CB( WRITE8( gamecom_state, gamecom_update_timers ) )
MCFG_CPU_VBLANK_INT_DRIVER("screen", gamecom_state, gamecom_interrupt)
MCFG_QUANTUM_TIME(attotime::from_hz(60))

View File

@ -258,6 +258,8 @@ public:
INTERRUPT_GEN_MEMBER(gamecom_interrupt);
TIMER_CALLBACK_MEMBER(gamecom_clock_timer_callback);
TIMER_CALLBACK_MEMBER(gamecom_scanline);
DECLARE_WRITE8_MEMBER( gamecom_handle_dma );
DECLARE_WRITE8_MEMBER( gamecom_update_timers );
protected:
required_memory_bank m_bank1;
@ -279,7 +281,4 @@ protected:
extern DEVICE_IMAGE_LOAD( gamecom_cart1 );
extern DEVICE_IMAGE_LOAD( gamecom_cart2 );
extern void gamecom_handle_dma( device_t *device, int cycles );
extern void gamecom_update_timers( device_t *device, int cycles );
#endif /* GAMECOM_H_ */

View File

@ -10,7 +10,7 @@ TIMER_CALLBACK_MEMBER(gamecom_state::gamecom_clock_timer_callback)
UINT8 * RAM = m_region_maincpu->base();
UINT8 val = ( ( RAM[SM8521_CLKT] & 0x3F ) + 1 ) & 0x3F;
RAM[SM8521_CLKT] = ( RAM[SM8521_CLKT] & 0xC0 ) | val;
m_maincpu->set_input_line(CK_INT, ASSERT_LINE );
m_maincpu->set_input_line(sm8500_cpu_device::CK_INT, ASSERT_LINE );
}
void gamecom_state::machine_reset()
@ -353,194 +353,202 @@ WRITE8_MEMBER( gamecom_state::gamecom_internal_w )
Their usage is also not explained properly in the manuals. Guess we'll have to wait
for them to show up in some rom images...
*/
void gamecom_handle_dma( device_t *device, int cycles )
WRITE8_MEMBER( gamecom_state::gamecom_handle_dma )
{
gamecom_state *state = device->machine().driver_data<gamecom_state>();
UINT8 * RAM = state->memregion("maincpu")->base();
UINT8 data = RAM[SM8521_DMC];
state->m_dma.overwrite_mode = data & 0x01;
state->m_dma.transfer_mode = data & 0x06;
state->m_dma.decrement_x = data & 0x08;
state->m_dma.decrement_y = data & 0x10;
state->m_dma.enabled = data & 0x80;
if ( !state->m_dma.enabled ) return;
UINT8 * RAM = m_region_maincpu->base();
UINT8 dmc = RAM[SM8521_DMC];
m_dma.overwrite_mode = dmc & 0x01;
m_dma.transfer_mode = dmc & 0x06;
m_dma.decrement_x = dmc & 0x08;
m_dma.decrement_y = dmc & 0x10;
m_dma.enabled = dmc & 0x80;
if ( !m_dma.enabled )
{
return;
}
if ( m_dma.decrement_x || m_dma.decrement_y )
{
popmessage( "TODO: Decrement-x and decrement-y are not supported yet\n" );
}
if ( state->m_dma.decrement_x || state->m_dma.decrement_y )
logerror( "TODO: Decrement-x and decrement-y are not supported yet\n" );
state->m_dma.width_x = RAM[SM8521_DMDX];
state->m_dma.width_x_count = 0;
state->m_dma.width_y = RAM[SM8521_DMDY];
state->m_dma.width_y_count = 0;
state->m_dma.source_x = RAM[SM8521_DMX1];
state->m_dma.source_x_current = state->m_dma.source_x;
state->m_dma.source_y = RAM[SM8521_DMY1];
state->m_dma.source_width = ( RAM[SM8521_LCH] & 0x20 ) ? 50 : 40;
state->m_dma.dest_x = RAM[SM8521_DMX2];
state->m_dma.dest_x_current = state->m_dma.dest_x;
state->m_dma.dest_y = RAM[SM8521_DMY2];
state->m_dma.dest_width = ( RAM[SM8521_LCH] & 0x20 ) ? 50 : 40;
state->m_dma.palette[0] = RAM[SM8521_DMPL] & 0x03;
state->m_dma.palette[1] = ( RAM[SM8521_DMPL] >> 2 ) & 3;
state->m_dma.palette[2] = ( RAM[SM8521_DMPL] >> 4 ) & 3;
state->m_dma.palette[3] = RAM[SM8521_DMPL] >> 6;
state->m_dma.source_mask = 0x1FFF;
state->m_dma.dest_mask = 0x1FFF;
// logerror("DMA: width %Xx%X, source (%X,%X), dest (%X,%X), transfer_mode %X, banks %X \n", state->m_dma.width_x, state->m_dma.width_y, state->m_dma.source_x, state->m_dma.source_y, state->m_dma.dest_x, state->m_dma.dest_y, state->m_dma.transfer_mode, RAM[SM8521_DMVP] );
// logerror( " Palette: %d, %d, %d, %d\n", state->m_dma.palette[0], state->m_dma.palette[1], state->m_dma.palette[2], state->m_dma.palette[3] );
switch( state->m_dma.transfer_mode )
m_dma.width_x = RAM[SM8521_DMDX];
m_dma.width_x_count = 0;
m_dma.width_y = RAM[SM8521_DMDY];
m_dma.width_y_count = 0;
m_dma.source_x = RAM[SM8521_DMX1];
m_dma.source_x_current = m_dma.source_x;
m_dma.source_y = RAM[SM8521_DMY1];
m_dma.source_width = ( RAM[SM8521_LCH] & 0x20 ) ? 50 : 40;
m_dma.dest_x = RAM[SM8521_DMX2];
m_dma.dest_x_current = m_dma.dest_x;
m_dma.dest_y = RAM[SM8521_DMY2];
m_dma.dest_width = ( RAM[SM8521_LCH] & 0x20 ) ? 50 : 40;
m_dma.palette[0] = RAM[SM8521_DMPL] & 0x03;
m_dma.palette[1] = ( RAM[SM8521_DMPL] >> 2 ) & 3;
m_dma.palette[2] = ( RAM[SM8521_DMPL] >> 4 ) & 3;
m_dma.palette[3] = RAM[SM8521_DMPL] >> 6;
m_dma.source_mask = 0x1FFF;
m_dma.dest_mask = 0x1FFF;
// logerror("DMA: width %Xx%X, source (%X,%X), dest (%X,%X), transfer_mode %X, banks %X \n", m_dma.width_x, m_dma.width_y, m_dma.source_x, m_dma.source_y, m_dma.dest_x, m_dma.dest_y, m_dma.transfer_mode, RAM[SM8521_DMVP] );
// logerror( " Palette: %d, %d, %d, %d\n", m_dma.palette[0], m_dma.palette[1], m_dma.palette[2], m_dma.palette[3] );
switch( m_dma.transfer_mode )
{
case 0x00:
/* VRAM->VRAM */
state->m_dma.source_bank = &state->m_p_videoram[(RAM[SM8521_DMVP] & 0x01) ? 0x2000 : 0x0000];
state->m_dma.dest_bank = &state->m_p_videoram[(RAM[SM8521_DMVP] & 0x02) ? 0x2000 : 0x0000];
m_dma.source_bank = &m_p_videoram[(RAM[SM8521_DMVP] & 0x01) ? 0x2000 : 0x0000];
m_dma.dest_bank = &m_p_videoram[(RAM[SM8521_DMVP] & 0x02) ? 0x2000 : 0x0000];
break;
case 0x02:
/* ROM->VRAM */
// logerror( "DMA DMBR = %X\n", RAM[SM8521_DMBR] );
state->m_dma.source_width = 64;
state->m_dma.source_mask = 0x3FFF;
m_dma.source_width = 64;
m_dma.source_mask = 0x3FFF;
if ( RAM[SM8521_DMBR] < 16 )
state->m_dma.source_bank = state->memregion("kernel")->base() + (RAM[SM8521_DMBR] << 14);
{
m_dma.source_bank = m_region_kernel->base() + (RAM[SM8521_DMBR] << 14);
}
else
if (state->m_cartridge)
state->m_dma.source_bank = state->m_cartridge + (RAM[SM8521_DMBR] << 14);
{
if (m_cartridge)
{
m_dma.source_bank = m_cartridge + (RAM[SM8521_DMBR] << 14);
}
}
state->m_dma.dest_bank = &state->m_p_videoram[(RAM[SM8521_DMVP] & 0x02) ? 0x2000 : 0x0000];
m_dma.dest_bank = &m_p_videoram[(RAM[SM8521_DMVP] & 0x02) ? 0x2000 : 0x0000];
break;
case 0x04:
/* Extend RAM->VRAM */
state->m_dma.source_width = 64;
state->m_dma.source_bank = &state->m_p_nvram[0x0000];
state->m_dma.dest_bank = &state->m_p_videoram[(RAM[SM8521_DMVP] & 0x02) ? 0x2000 : 0x0000];
m_dma.source_width = 64;
m_dma.source_bank = &m_p_nvram[0x0000];
m_dma.dest_bank = &m_p_videoram[(RAM[SM8521_DMVP] & 0x02) ? 0x2000 : 0x0000];
break;
case 0x06:
/* VRAM->Extend RAM */
state->m_dma.source_bank = &state->m_p_videoram[(RAM[SM8521_DMVP] & 0x01) ? 0x2000 : 0x0000];
state->m_dma.dest_width = 64;
state->m_dma.dest_bank = &state->m_p_nvram[0x0000];
m_dma.source_bank = &m_p_videoram[(RAM[SM8521_DMVP] & 0x01) ? 0x2000 : 0x0000];
m_dma.dest_width = 64;
m_dma.dest_bank = &m_p_nvram[0x0000];
break;
}
state->m_dma.source_current = state->m_dma.source_width * state->m_dma.source_y;
state->m_dma.source_current += state->m_dma.source_x >> 2;
state->m_dma.dest_current = state->m_dma.dest_width * state->m_dma.dest_y;
state->m_dma.dest_current += state->m_dma.dest_x >> 2;
state->m_dma.source_line = state->m_dma.source_current;
state->m_dma.dest_line = state->m_dma.dest_current;
state->m_dma.state_count = 0;
m_dma.source_current = m_dma.source_width * m_dma.source_y;
m_dma.source_current += m_dma.source_x >> 2;
m_dma.dest_current = m_dma.dest_width * m_dma.dest_y;
m_dma.dest_current += m_dma.dest_x >> 2;
m_dma.source_line = m_dma.source_current;
m_dma.dest_line = m_dma.dest_current;
m_dma.state_count = 0;
unsigned y_count, x_count;
for( y_count = 0; y_count <= state->m_dma.width_y; y_count++ )
for( y_count = 0; y_count <= m_dma.width_y; y_count++ )
{
for( x_count = 0; x_count <= state->m_dma.width_x; x_count++ )
for( x_count = 0; x_count <= m_dma.width_x; x_count++ )
{
int source_pixel = 0;
int dest_pixel = 0;
int src_addr = state->m_dma.source_current & state->m_dma.source_mask;
int dest_addr = state->m_dma.dest_current & state->m_dma.dest_mask;
int src_addr = m_dma.source_current & m_dma.source_mask;
int dest_addr = m_dma.dest_current & m_dma.dest_mask;
/* handle DMA for 1 pixel */
/* Read pixel data */
switch ( state->m_dma.source_x_current & 0x03 )
switch ( m_dma.source_x_current & 0x03 )
{
case 0x00: source_pixel = state->m_dma.source_bank[src_addr] >> 6; break;
case 0x01: source_pixel = ( state->m_dma.source_bank[src_addr] >> 4 ) & 3; break;
case 0x02: source_pixel = ( state->m_dma.source_bank[src_addr] >> 2 ) & 3; break;
case 0x03: source_pixel = state->m_dma.source_bank[src_addr] & 3; break;
case 0x00: source_pixel = m_dma.source_bank[src_addr] >> 6; break;
case 0x01: source_pixel = ( m_dma.source_bank[src_addr] >> 4 ) & 3; break;
case 0x02: source_pixel = ( m_dma.source_bank[src_addr] >> 2 ) & 3; break;
case 0x03: source_pixel = m_dma.source_bank[src_addr] & 3; break;
}
if ( !state->m_dma.overwrite_mode && source_pixel == 0 )
if ( !m_dma.overwrite_mode && source_pixel == 0 )
{
switch ( state->m_dma.dest_x_current & 0x03 )
switch ( m_dma.dest_x_current & 0x03 )
{
case 0x00: dest_pixel = state->m_dma.dest_bank[dest_addr] >> 6; break;
case 0x01: dest_pixel = ( state->m_dma.dest_bank[dest_addr] >> 4 ) & 3; break;
case 0x02: dest_pixel = ( state->m_dma.dest_bank[dest_addr] >> 2 ) & 3; break;
case 0x03: dest_pixel = state->m_dma.dest_bank[dest_addr] & 3; break;
case 0x00: dest_pixel = m_dma.dest_bank[dest_addr] >> 6; break;
case 0x01: dest_pixel = ( m_dma.dest_bank[dest_addr] >> 4 ) & 3; break;
case 0x02: dest_pixel = ( m_dma.dest_bank[dest_addr] >> 2 ) & 3; break;
case 0x03: dest_pixel = m_dma.dest_bank[dest_addr] & 3; break;
}
source_pixel = dest_pixel;
}
/* Translate pixel data using DMA palette. */
/* Not sure if this should be done before the compound stuff - WP */
source_pixel = state->m_dma.palette[ source_pixel ];
source_pixel = m_dma.palette[ source_pixel ];
/* Write pixel data */
switch( state->m_dma.dest_x_current & 0x03 )
switch( m_dma.dest_x_current & 0x03 )
{
case 0x00:
state->m_dma.dest_bank[dest_addr] = ( state->m_dma.dest_bank[dest_addr] & 0x3F ) | ( source_pixel << 6 );
m_dma.dest_bank[dest_addr] = ( m_dma.dest_bank[dest_addr] & 0x3F ) | ( source_pixel << 6 );
break;
case 0x01:
state->m_dma.dest_bank[dest_addr] = ( state->m_dma.dest_bank[dest_addr] & 0xCF ) | ( source_pixel << 4 );
m_dma.dest_bank[dest_addr] = ( m_dma.dest_bank[dest_addr] & 0xCF ) | ( source_pixel << 4 );
break;
case 0x02:
state->m_dma.dest_bank[dest_addr] = ( state->m_dma.dest_bank[dest_addr] & 0xF3 ) | ( source_pixel << 2 );
m_dma.dest_bank[dest_addr] = ( m_dma.dest_bank[dest_addr] & 0xF3 ) | ( source_pixel << 2 );
break;
case 0x03:
state->m_dma.dest_bank[dest_addr] = ( state->m_dma.dest_bank[dest_addr] & 0xFC ) | source_pixel;
m_dma.dest_bank[dest_addr] = ( m_dma.dest_bank[dest_addr] & 0xFC ) | source_pixel;
break;
}
/* Advance a pixel */
if ( state->m_dma.decrement_x )
if ( m_dma.decrement_x )
{
state->m_dma.source_x_current--;
if ( ( state->m_dma.source_x_current & 0x03 ) == 0x03 )
state->m_dma.source_current--;
m_dma.source_x_current--;
if ( ( m_dma.source_x_current & 0x03 ) == 0x03 )
m_dma.source_current--;
}
else
{
state->m_dma.source_x_current++;
if ( ( state->m_dma.source_x_current & 0x03 ) == 0x00 )
state->m_dma.source_current++;
m_dma.source_x_current++;
if ( ( m_dma.source_x_current & 0x03 ) == 0x00 )
m_dma.source_current++;
}
state->m_dma.dest_x_current++;
if ( ( state->m_dma.dest_x_current & 0x03 ) == 0x00 )
state->m_dma.dest_current++;
m_dma.dest_x_current++;
if ( ( m_dma.dest_x_current & 0x03 ) == 0x00 )
m_dma.dest_current++;
}
/* Advance a line */
state->m_dma.source_x_current = state->m_dma.source_x;
state->m_dma.dest_x_current = state->m_dma.dest_x;
state->m_dma.source_line += state->m_dma.source_width;
state->m_dma.source_current = state->m_dma.source_line;
state->m_dma.dest_line += state->m_dma.dest_width;
state->m_dma.dest_current = state->m_dma.dest_line;
m_dma.source_x_current = m_dma.source_x;
m_dma.dest_x_current = m_dma.dest_x;
m_dma.source_line += m_dma.source_width;
m_dma.source_current = m_dma.source_line;
m_dma.dest_line += m_dma.dest_width;
m_dma.dest_current = m_dma.dest_line;
}
state->m_dma.enabled = 0;
device->machine().device("maincpu")->execute().set_input_line(DMA_INT, ASSERT_LINE );
m_dma.enabled = 0;
m_maincpu->set_input_line(sm8500_cpu_device::DMA_INT, ASSERT_LINE );
}
void gamecom_update_timers( device_t *device, int cycles )
WRITE8_MEMBER( gamecom_state::gamecom_update_timers )
{
gamecom_state *state = device->machine().driver_data<gamecom_state>();
UINT8 * RAM = state->memregion("maincpu")->base();
if ( state->m_timer[0].enabled )
UINT8 * RAM = m_region_maincpu->base();
if ( m_timer[0].enabled )
{
state->m_timer[0].state_count += cycles;
while ( state->m_timer[0].state_count >= state->m_timer[0].state_limit )
m_timer[0].state_count += data;
while ( m_timer[0].state_count >= m_timer[0].state_limit )
{
state->m_timer[0].state_count -= state->m_timer[0].state_limit;
m_timer[0].state_count -= m_timer[0].state_limit;
RAM[SM8521_TM0D]++;
if ( RAM[SM8521_TM0D] >= state->m_timer[0].check_value )
if ( RAM[SM8521_TM0D] >= m_timer[0].check_value )
{
RAM[SM8521_TM0D] = 0;
device->machine().device("maincpu")->execute().set_input_line(TIM0_INT, ASSERT_LINE );
m_maincpu->set_input_line(sm8500_cpu_device::TIM0_INT, ASSERT_LINE );
}
}
}
if ( state->m_timer[1].enabled )
if ( m_timer[1].enabled )
{
state->m_timer[1].state_count += cycles;
while ( state->m_timer[1].state_count >= state->m_timer[1].state_limit )
m_timer[1].state_count += data;
while ( m_timer[1].state_count >= m_timer[1].state_limit )
{
state->m_timer[1].state_count -= state->m_timer[1].state_limit;
m_timer[1].state_count -= m_timer[1].state_limit;
RAM[SM8521_TM1D]++;
if ( RAM[SM8521_TM1D] >= state->m_timer[1].check_value )
if ( RAM[SM8521_TM1D] >= m_timer[1].check_value )
{
RAM[SM8521_TM1D] = 0;
device->machine().device("maincpu")->execute().set_input_line(TIM1_INT, ASSERT_LINE );
m_maincpu->set_input_line(sm8500_cpu_device::TIM1_INT, ASSERT_LINE );
}
}
}