Fixed numerous opcodes in the AVR8 core [Harmony]

Fixed a register naming issue in the MIPS core [Harmony]
Numerous SuperFX updates: [Harmony]
 - Hooked up RAM and ROM buffering
 - Inlined several more functions
 - Removed debug spew
 - Added the ability to define an external IRQ line callback, and hooked it up to the 65C816
 - Fixed flag calculation for HIB opcode
 - Hooked SuperFX chip up to the SNES machine driver
This commit is contained in:
Ryan Holtz 2009-09-03 23:53:43 +00:00
parent 85d9b4decb
commit b54790792a
13 changed files with 1475 additions and 175 deletions

2
.gitattributes vendored
View File

@ -2874,6 +2874,8 @@ src/mame/machine/snes.c svneol=native#text/plain
src/mame/machine/snesdsp1.c svneol=native#text/plain src/mame/machine/snesdsp1.c svneol=native#text/plain
src/mame/machine/snesdsp2.c svneol=native#text/plain src/mame/machine/snesdsp2.c svneol=native#text/plain
src/mame/machine/snesobc1.c svneol=native#text/plain src/mame/machine/snesobc1.c svneol=native#text/plain
src/mame/machine/snesrtc.c svneol=native#text/plain
src/mame/machine/snessdd1.c svneol=native#text/plain
src/mame/machine/spisprit.c svneol=native#text/plain src/mame/machine/spisprit.c svneol=native#text/plain
src/mame/machine/starwars.c svneol=native#text/plain src/mame/machine/starwars.c svneol=native#text/plain
src/mame/machine/steppers.c svneol=native#text/plain src/mame/machine/steppers.c svneol=native#text/plain

View File

@ -128,6 +128,7 @@ INLINE void PUSH(avr8_state *cpustate, UINT8 val)
UINT16 sp = SPREG; UINT16 sp = SPREG;
WRITE_IO_8(cpustate, sp, val); WRITE_IO_8(cpustate, sp, val);
sp--; sp--;
//printf( "PUSH %02x, new SP = %04x\n", val, sp );
WRITE_IO_8(cpustate, AVR8_IO_SPH, (sp >> 8) & 0x00ff); WRITE_IO_8(cpustate, AVR8_IO_SPH, (sp >> 8) & 0x00ff);
WRITE_IO_8(cpustate, AVR8_IO_SPL, sp & 0x00ff); WRITE_IO_8(cpustate, AVR8_IO_SPL, sp & 0x00ff);
} }
@ -138,9 +139,23 @@ INLINE UINT8 POP(avr8_state *cpustate)
sp++; sp++;
WRITE_IO_8(cpustate, AVR8_IO_SPH, (sp >> 8) & 0x00ff); WRITE_IO_8(cpustate, AVR8_IO_SPH, (sp >> 8) & 0x00ff);
WRITE_IO_8(cpustate, AVR8_IO_SPL, sp & 0x00ff); WRITE_IO_8(cpustate, AVR8_IO_SPL, sp & 0x00ff);
//printf( "POP %02x, new SP = %04x\n", READ_IO_8(cpustate, sp), sp );
return READ_IO_8(cpustate, sp); return READ_IO_8(cpustate, sp);
} }
static void avr8_set_irq_line(avr8_state *cpustate, UINT16 vector, int state)
{
//printf( "OMFG SETTING IRQ LINE\n" );
// Horrible hack, not accurate
if(state)
{
SREG_W(AVR8_SREG_I, 0);
PUSH(cpustate, (cpustate->pc >> 8) & 0x00ff);
PUSH(cpustate, cpustate->pc & 0x00ff);
cpustate->pc = vector;
}
}
/*****************************************************************************/ /*****************************************************************************/
static CPU_INIT( avr8 ) static CPU_INIT( avr8 )
@ -176,6 +191,8 @@ static CPU_EXECUTE( avr8 )
UINT8 rr = 0; UINT8 rr = 0;
UINT8 res = 0; UINT8 res = 0;
UINT16 pd = 0; UINT16 pd = 0;
INT16 sd = 0;
INT32 opcycles = 1;
//UINT16 pr = 0; //UINT16 pr = 0;
avr8_state *cpustate = get_safe_token(device); avr8_state *cpustate = get_safe_token(device);
@ -195,20 +212,22 @@ static CPU_EXECUTE( avr8 )
switch(op & 0x0f00) switch(op & 0x0f00)
{ {
case 0x0000: // NOP case 0x0000: // NOP
//output += sprintf( output, "NOP" );
unimplemented_opcode(cpustate, op);
break; break;
case 0x0100: // MOVW Rd+1:Rd,Rr+1:Rd case 0x0100: // MOVW Rd+1:Rd,Rr+1:Rd
//output += sprintf( output, "MOVW R%d:R%d, R%d:R%d", RD4(op)+1, RD4(op), RR4(op)+1, RR4(op) ); WRITE_IO_8(cpustate, (RD4(op) << 1)+1, READ_IO_8(cpustate, (RR4(op) << 1)+1));
unimplemented_opcode(cpustate, op); WRITE_IO_8(cpustate, RD4(op) << 1, READ_IO_8(cpustate, RR4(op) << 1));
break; break;
case 0x0200: // MULS Rd,Rr case 0x0200: // MULS Rd,Rr
//output += sprintf( output, "MULS R%d, R%d", 16+RD4(op), 16+RR4(op) ); //output += sprintf( output, "MULS R%d, R%d", 16+RD4(op), 16+RR4(op) );
unimplemented_opcode(cpustate, op); unimplemented_opcode(cpustate, op);
break; break;
case 0x0300: // MULSU Rd,Rr case 0x0300: // MULSU Rd,Rr
//output += sprintf( output, "MULSU R%d, R%d", 16+RD4(op), 16+RR4(op) ); sd = (INT8)READ_IO_8(cpustate, 16+RD4(op)) * (UINT8)READ_IO_8(cpustate, 16+RR4(op));
unimplemented_opcode(cpustate, op); WRITE_IO_8(cpustate, 1, (sd >> 8) & 0x00ff);
WRITE_IO_8(cpustate, 0, sd & 0x00ff);
SREG_W(AVR8_SREG_C, (sd & 0x8000) ? 1 : 0);
SREG_W(AVR8_SREG_Z, (sd == 0) ? 1 : 0);
opcycles = 2;
break; break;
case 0x0400: case 0x0400:
case 0x0500: case 0x0500:
@ -228,8 +247,16 @@ static CPU_EXECUTE( avr8 )
case 0x0900: case 0x0900:
case 0x0a00: case 0x0a00:
case 0x0b00: // SBC Rd,Rr case 0x0b00: // SBC Rd,Rr
//output += sprintf( output, "SBC R%d, R%d", RD5(op), RR5(op) ); rd = READ_IO_8(cpustate, RD5(op));
unimplemented_opcode(cpustate, op); rr = READ_IO_8(cpustate, RR5(op));
res = rd - (rr + SREG_R(AVR8_SREG_C));
WRITE_IO_8(cpustate, RD5(op), res);
SREG_W(AVR8_SREG_H, (NOT(BIT(rd,3)) & BIT(rr,3)) | (BIT(rr,3) & BIT(res,3)) | (BIT(res,3) & NOT(BIT(rd,3))));
SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7)));
SREG_W(AVR8_SREG_N, BIT(res,7));
SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7))));
break; break;
case 0x0c00: case 0x0c00:
case 0x0d00: case 0x0d00:
@ -267,8 +294,16 @@ static CPU_EXECUTE( avr8 )
SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7)))); SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7))));
break; break;
case 0x0800: // SUB Rd,Rr case 0x0800: // SUB Rd,Rr
//output += sprintf( output, "SUB R%d, R%d", RD5(op), RR5(op) ); rd = READ_IO_8(cpustate, RD5(op));
unimplemented_opcode(cpustate, op); rr = READ_IO_8(cpustate, RR5(op));
res = rd - rr;
WRITE_IO_8(cpustate, RD5(op), res);
SREG_W(AVR8_SREG_H, (NOT(BIT(rd,3)) & BIT(rr,3)) | (BIT(rr,3) & BIT(res,3)) | (BIT(res,3) & NOT(BIT(rd,3))));
SREG_W(AVR8_SREG_V, (BIT(rd,7) & NOT(BIT(rr,7)) & NOT(BIT(res,7))) | (NOT(BIT(rd,7)) & BIT(rr,7) & BIT(res,7)));
SREG_W(AVR8_SREG_N, BIT(res,7));
SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
SREG_W(AVR8_SREG_C, (NOT(BIT(rd,7)) & BIT(rr,7)) | (BIT(rr,7) & BIT(res,7)) | (BIT(res,7) & NOT(BIT(rd,7))));
break; break;
case 0x0c00: // ADC Rd,Rr case 0x0c00: // ADC Rd,Rr
rd = READ_IO_8(cpustate, RD5(op)); rd = READ_IO_8(cpustate, RD5(op));
@ -361,16 +396,16 @@ static CPU_EXECUTE( avr8 )
unimplemented_opcode(cpustate, op); unimplemented_opcode(cpustate, op);
break; break;
case 0x0008: // LDD Rd,Y+q case 0x0008: // LDD Rd,Y+q
//output += sprintf( output, "LD(D) R%d, Y+%02x", RD5(op), QCONST6(op) ); WRITE_IO_8(cpustate, RD5(op), YREG + QCONST6(op));
unimplemented_opcode(cpustate, op); opcycles = 2;
break; break;
case 0x0200: // STD Z+q,Rr case 0x0200: // STD Z+q,Rr
//output += sprintf( output, "ST(D) Z+%02x, R%d", QCONST6(op), RD5(op) ); //output += sprintf( output, "ST(D) Z+%02x, R%d", QCONST6(op), RD5(op) );
unimplemented_opcode(cpustate, op); unimplemented_opcode(cpustate, op);
break; break;
case 0x0208: // STD Z+q,Rr case 0x0208: // STD Y+q,Rr
//output += sprintf( output, "ST(D) Y+%02x, R%d", QCONST6(op), RD5(op) ); WRITE_IO_8(cpustate, YREG + QCONST6(op), READ_IO_8(cpustate, RD5(op)));
unimplemented_opcode(cpustate, op); opcycles = 2;
break; break;
} }
break; break;
@ -386,6 +421,7 @@ static CPU_EXECUTE( avr8 )
cpustate->pc++; cpustate->pc++;
op |= READ_PRG_16(cpustate, cpustate->pc); op |= READ_PRG_16(cpustate, cpustate->pc);
WRITE_IO_8(cpustate, RD5(op >> 16), READ_IO_8(cpustate, op & 0x0000ffff)); WRITE_IO_8(cpustate, RD5(op >> 16), READ_IO_8(cpustate, op & 0x0000ffff));
opcycles = 2;
break; break;
case 0x0001: // LD Rd,Z+ case 0x0001: // LD Rd,Z+
unimplemented_opcode(cpustate, op); unimplemented_opcode(cpustate, op);
@ -396,6 +432,7 @@ static CPU_EXECUTE( avr8 )
break; break;
case 0x0004: // LPM Rd,Z case 0x0004: // LPM Rd,Z
WRITE_IO_8(cpustate, RD5(op), READ_PRG_8(cpustate, ZREG)); WRITE_IO_8(cpustate, RD5(op), READ_PRG_8(cpustate, ZREG));
opcycles = 3;
break; break;
case 0x0005: // LPM Rd,Z+ case 0x0005: // LPM Rd,Z+
pd = ZREG; pd = ZREG;
@ -403,6 +440,7 @@ static CPU_EXECUTE( avr8 )
pd++; pd++;
WRITE_IO_8(cpustate, 31, (pd >> 8) & 0x00ff); WRITE_IO_8(cpustate, 31, (pd >> 8) & 0x00ff);
WRITE_IO_8(cpustate, 30, pd & 0x00ff); WRITE_IO_8(cpustate, 30, pd & 0x00ff);
opcycles = 3;
break; break;
case 0x0006: // ELPM Rd,Z case 0x0006: // ELPM Rd,Z
//output += sprintf( output, "ELPM R%d, Z", RD5(op) ); //output += sprintf( output, "ELPM R%d, Z", RD5(op) );
@ -425,16 +463,20 @@ static CPU_EXECUTE( avr8 )
unimplemented_opcode(cpustate, op); unimplemented_opcode(cpustate, op);
break; break;
case 0x000d: // LD Rd,X+ case 0x000d: // LD Rd,X+
//output += sprintf( output, "LD R%d, X+", RD5(op) ); pd = XREG;
unimplemented_opcode(cpustate, op); WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, pd));
pd++;
WRITE_IO_8(cpustate, 27, (pd >> 8) & 0x00ff);
WRITE_IO_8(cpustate, 26, pd & 0x00ff);
opcycles = 2;
break; break;
case 0x000e: // LD Rd,-X case 0x000e: // LD Rd,-X
//output += sprintf( output, "LD R%d,-X", RD5(op) ); //output += sprintf( output, "LD R%d,-X", RD5(op) );
unimplemented_opcode(cpustate, op); unimplemented_opcode(cpustate, op);
break; break;
case 0x000f: // POP Rd case 0x000f: // POP Rd
//output += sprintf( output, "POP R%d", RD5(op) ); WRITE_IO_8(cpustate, RD5(op), POP(cpustate));
unimplemented_opcode(cpustate, op); opcycles = 2;
break; break;
default: default:
unimplemented_opcode(cpustate, op); unimplemented_opcode(cpustate, op);
@ -451,6 +493,7 @@ static CPU_EXECUTE( avr8 )
cpustate->pc++; cpustate->pc++;
op |= READ_PRG_16(cpustate, cpustate->pc); op |= READ_PRG_16(cpustate, cpustate->pc);
WRITE_IO_8(cpustate, op & 0x0000ffff, READ_IO_8(cpustate, RD5(op >> 16))); WRITE_IO_8(cpustate, op & 0x0000ffff, READ_IO_8(cpustate, RD5(op >> 16)));
opcycles = 2;
break; break;
case 0x0001: // ST Z+,Rd case 0x0001: // ST Z+,Rd
//output += sprintf( output, "ST Z+, R%d", RD5(op) ); //output += sprintf( output, "ST Z+, R%d", RD5(op) );
@ -471,6 +514,7 @@ static CPU_EXECUTE( avr8 )
case 0x000c: // ST X,Rd case 0x000c: // ST X,Rd
rd = READ_IO_8(cpustate, RD5(op)); rd = READ_IO_8(cpustate, RD5(op));
WRITE_IO_8(cpustate, XREG, rd); WRITE_IO_8(cpustate, XREG, rd);
opcycles = 2;
break; break;
case 0x000d: // ST X+,Rd case 0x000d: // ST X+,Rd
pd = XREG; pd = XREG;
@ -478,14 +522,15 @@ static CPU_EXECUTE( avr8 )
pd++; pd++;
WRITE_IO_8(cpustate, 27, (pd >> 8) & 0x00ff); WRITE_IO_8(cpustate, 27, (pd >> 8) & 0x00ff);
WRITE_IO_8(cpustate, 26, pd & 0x00ff); WRITE_IO_8(cpustate, 26, pd & 0x00ff);
opcycles = 2;
break; break;
case 0x000e: // ST -X,Rd case 0x000e: // ST -X,Rd
//output += sprintf( output, "ST -X , R%d", RD5(op) ); //output += sprintf( output, "ST -X , R%d", RD5(op) );
unimplemented_opcode(cpustate, op); unimplemented_opcode(cpustate, op);
break; break;
case 0x000f: // PUSH Rd case 0x000f: // PUSH Rd
//output += sprintf( output, "PUSH R%d", RD5(op) ); PUSH(cpustate, READ_IO_8(cpustate, RD5(op)));
unimplemented_opcode(cpustate, op); opcycles = 2;
break; break;
default: default:
unimplemented_opcode(cpustate, op); unimplemented_opcode(cpustate, op);
@ -497,12 +542,23 @@ static CPU_EXECUTE( avr8 )
switch(op & 0x000f) switch(op & 0x000f)
{ {
case 0x0000: // COM Rd case 0x0000: // COM Rd
//output += sprintf( output, "COM R%d", RD5(op) ); rd = READ_IO_8(cpustate, RD5(op));
unimplemented_opcode(cpustate, op); rd = ~rd;
SREG_W(AVR8_SREG_C, 1);
SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
SREG_W(AVR8_SREG_N, BIT(res,7));
SREG_W(AVR8_SREG_V, 0);
SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) | SREG_R(AVR8_SREG_V));
break; break;
case 0x0001: // NEG Rd case 0x0001: // NEG Rd
//output += sprintf( output, "NEG R%d", RD5(op) ); rd = READ_IO_8(cpustate, RD5(op));
unimplemented_opcode(cpustate, op); res = 0 - rd;
SREG_W(AVR8_SREG_C, (res == 0) ? 0 : 1);
SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
SREG_W(AVR8_SREG_N, BIT(res,7));
SREG_W(AVR8_SREG_V, (res == 0x80) ? 1 : 0);
SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) | SREG_R(AVR8_SREG_V));
SREG_W(AVR8_SREG_H, BIT(res,3) | BIT(rd,3));
break; break;
case 0x0002: // SWAP Rd case 0x0002: // SWAP Rd
//output += sprintf( output, "SWAP R%d", RD5(op) ); //output += sprintf( output, "SWAP R%d", RD5(op) );
@ -522,8 +578,13 @@ static CPU_EXECUTE( avr8 )
unimplemented_opcode(cpustate, op); unimplemented_opcode(cpustate, op);
break; break;
case 0x0006: // LSR Rd case 0x0006: // LSR Rd
//output += sprintf( output, "LSR R%d", RD5(op) ); rd = READ_IO_8(cpustate, RD5(op));
unimplemented_opcode(cpustate, op); res = rd >> 1;
SREG_W(AVR8_SREG_C, rd & 0x01);
SREG_W(AVR8_SREG_Z, (res == 0) ? 1 :0);
SREG_W(AVR8_SREG_N, 0);
SREG_W(AVR8_SREG_V, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_C));
SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
break; break;
case 0x0007: // ROR Rd case 0x0007: // ROR Rd
//output += sprintf( output, "ROR R%d", RD5(op) ); //output += sprintf( output, "ROR R%d", RD5(op) );
@ -559,21 +620,26 @@ static CPU_EXECUTE( avr8 )
{ {
case 0x0000: // IJMP case 0x0000: // IJMP
cpustate->pc = ZREG - 1; cpustate->pc = ZREG - 1;
opcycles = 2;
break; break;
case 0x0010: // EIJMP case 0x0010: // EIJMP
//output += sprintf( output, "EIJMP" ); //output += sprintf( output, "EIJMP" );
unimplemented_opcode(cpustate, op); unimplemented_opcode(cpustate, op);
break; break;
default: default:
unimplemented_opcode(cpustate, op);
//output += sprintf( output, "Undefined (%04x)", op ); //output += sprintf( output, "Undefined (%04x)", op );
unimplemented_opcode(cpustate, op); unimplemented_opcode(cpustate, op);
break; break;
} }
break; break;
case 0x000a: // DEC Rd case 0x000a: // DEC Rd
//output += sprintf( output, "DEC R%d", RD5(op) ); rd = READ_IO_8(cpustate, RD5(op));
unimplemented_opcode(cpustate, op); res = rd - 1;
SREG_W(AVR8_SREG_V, (rd == 0x7f) ? 1 : 0);
SREG_W(AVR8_SREG_N, BIT(res,7));
SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
WRITE_IO_8(cpustate, RD5(op), res);
break; break;
case 0x000c: case 0x000c:
case 0x000d: // JMP k case 0x000d: // JMP k
@ -603,12 +669,24 @@ static CPU_EXECUTE( avr8 )
switch(op & 0x000f) switch(op & 0x000f)
{ {
case 0x0000: // COM Rd case 0x0000: // COM Rd
//output += sprintf( output, "COM R%d", RD5(op) ); rd = READ_IO_8(cpustate, RD5(op));
unimplemented_opcode(cpustate, op); rd = ~rd;
SREG_W(AVR8_SREG_C, 1);
SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
SREG_W(AVR8_SREG_N, BIT(res,7));
SREG_W(AVR8_SREG_V, 0);
SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) | SREG_R(AVR8_SREG_V));
break; break;
case 0x0001: // NEG Rd case 0x0001: // NEG Rd
//output += sprintf( output, "NEG R%d", RD5(op) ); rd = READ_IO_8(cpustate, RD5(op));
unimplemented_opcode(cpustate, op); res = 0 - rd;
WRITE_IO_8(cpustate, RD5(op), res);
SREG_W(AVR8_SREG_C, (res == 0) ? 0 : 1);
SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
SREG_W(AVR8_SREG_N, BIT(res,7));
SREG_W(AVR8_SREG_V, (res == 0x80) ? 1 : 0);
SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) | SREG_R(AVR8_SREG_V));
SREG_W(AVR8_SREG_H, BIT(res,3) | BIT(rd,3));
break; break;
case 0x0002: // SWAP Rd case 0x0002: // SWAP Rd
//output += sprintf( output, "SWAP R%d", RD5(op) ); //output += sprintf( output, "SWAP R%d", RD5(op) );
@ -628,8 +706,13 @@ static CPU_EXECUTE( avr8 )
unimplemented_opcode(cpustate, op); unimplemented_opcode(cpustate, op);
break; break;
case 0x0006: // LSR Rd case 0x0006: // LSR Rd
//output += sprintf( output, "LSR R%d", RD5(op) ); rd = READ_IO_8(cpustate, RD5(op));
unimplemented_opcode(cpustate, op); res = rd >> 1;
SREG_W(AVR8_SREG_C, rd & 0x01);
SREG_W(AVR8_SREG_Z, (res == 0) ? 1 :0);
SREG_W(AVR8_SREG_N, 0);
SREG_W(AVR8_SREG_V, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_C));
SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
break; break;
case 0x0007: // ROR Rd case 0x0007: // ROR Rd
//output += sprintf( output, "ROR R%d", RD5(op) ); //output += sprintf( output, "ROR R%d", RD5(op) );
@ -642,10 +725,14 @@ static CPU_EXECUTE( avr8 )
cpustate->pc = POP(cpustate); cpustate->pc = POP(cpustate);
cpustate->pc |= POP(cpustate) << 8; cpustate->pc |= POP(cpustate) << 8;
cpustate->pc--; cpustate->pc--;
opcycles = 4;
break; break;
case 0x0010: // RETI case 0x0010: // RETI
//output += sprintf( output, "RETI" ); cpustate->pc = POP(cpustate);
unimplemented_opcode(cpustate, op); cpustate->pc |= POP(cpustate) << 8;
cpustate->pc--;
SREG_W(AVR8_SREG_I, 1);
opcycles = 4;
break; break;
case 0x0080: // SLEEP case 0x0080: // SLEEP
//output += sprintf( output, "SLEEP" ); //output += sprintf( output, "SLEEP" );
@ -661,6 +748,7 @@ static CPU_EXECUTE( avr8 )
break; break;
case 0x00c0: // LPM case 0x00c0: // LPM
WRITE_IO_8(cpustate, 0, READ_PRG_8(cpustate, ZREG)); WRITE_IO_8(cpustate, 0, READ_PRG_8(cpustate, ZREG));
opcycles = 3;
break; break;
case 0x00d0: // ELPM case 0x00d0: // ELPM
//output += sprintf( output, "ELPM" ); //output += sprintf( output, "ELPM" );
@ -698,8 +786,13 @@ static CPU_EXECUTE( avr8 )
} }
break; break;
case 0x000a: // DEC Rd case 0x000a: // DEC Rd
//output += sprintf( output, "DEC R%d", RD5(op) ); rd = READ_IO_8(cpustate, RD5(op));
unimplemented_opcode(cpustate, op); res = rd - 1;
SREG_W(AVR8_SREG_V, (rd == 0x7f) ? 1 : 0);
SREG_W(AVR8_SREG_N, BIT(res,7));
SREG_W(AVR8_SREG_S, SREG_R(AVR8_SREG_N) ^ SREG_R(AVR8_SREG_V));
SREG_W(AVR8_SREG_Z, (res == 0) ? 1 : 0);
WRITE_IO_8(cpustate, RD5(op), res);
break; break;
case 0x000c: case 0x000c:
case 0x000d: // JMP k case 0x000d: // JMP k
@ -727,47 +820,56 @@ static CPU_EXECUTE( avr8 )
break; break;
case 0x0700: // SBIW Rd+1:Rd,K case 0x0700: // SBIW Rd+1:Rd,K
//output += sprintf( output, "SBIW R%d:R%d, 0x%02x", 24+(RD2(op) << 1)+1, 24+(RD2(op) << 1), KCONST6(op) ); //output += sprintf( output, "SBIW R%d:R%d, 0x%02x", 24+(RD2(op) << 1)+1, 24+(RD2(op) << 1), KCONST6(op) );
unimplemented_opcode(cpustate, op);
break; break;
case 0x0800: // CBI A,b case 0x0800: // CBI A,b
//output += sprintf( output, "CBI 0x%02x, %d", ACONST5(op), RR3(op) ); //output += sprintf( output, "CBI 0x%02x, %d", ACONST5(op), RR3(op) );
WRITE_IO_8(cpustate, ACONST5(op), READ_IO_8(cpustate, ACONST5(op)) &~ (1 << RR3(op)));
opcycles = 2;
break; break;
case 0x0900: // SBIC A,b case 0x0900: // SBIC A,b
//output += sprintf( output, "SBIC 0x%02x, %d", ACONST5(op), RR3(op) ); //output += sprintf( output, "SBIC 0x%02x, %d", ACONST5(op), RR3(op) );
unimplemented_opcode(cpustate, op);
break; break;
case 0x0a00: // SBI A,b case 0x0a00: // SBI A,b
//output += sprintf( output, "SBI 0x%02x, %d", ACONST5(op), RR3(op) ); //output += sprintf( output, "SBI 0x%02x, %d", ACONST5(op), RR3(op) );
WRITE_IO_8(cpustate, ACONST5(op), READ_IO_8(cpustate, ACONST5(op)) | (1 << RR3(op)));
opcycles = 2;
break; break;
case 0x0b00: // SBIS A,b case 0x0b00: // SBIS A,b
//output += sprintf( output, "SBIS 0x%02x, %d", ACONST5(op), RR3(op) ); //output += sprintf( output, "SBIS 0x%02x, %d", ACONST5(op), RR3(op) );
unimplemented_opcode(cpustate, op);
break; break;
case 0x0c00: case 0x0c00:
case 0x0d00: case 0x0d00:
case 0x0e00: case 0x0e00:
case 0x0f00: // MUL Rd,Rr case 0x0f00: // MUL Rd,Rr
//output += sprintf( output, "MUL R%d, R%d", RD5(op), RR5(op) ); //output += sprintf( output, "MUL R%d, R%d", RD5(op), RR5(op) );
unimplemented_opcode(cpustate, op);
break; break;
} }
break; break;
case 0xb000: case 0xb000:
unimplemented_opcode(cpustate, op);
if(op & 0x0800) // OUT A,Rr if(op & 0x0800) // OUT A,Rr
{ {
//output += sprintf( output, "OUT 0x%02x, R%d", ACONST6(op), RD5(op) ); WRITE_IO_8(cpustate, 0x20 + ACONST6(op), READ_IO_8(cpustate, RD5(op)));
} }
else // IN Rd,A else // IN Rd,A
{ {
//output += sprintf( output, "IN R%d, 0x%02x", RD5(op), ACONST6(op) ); WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, 0x20 + ACONST6(op)));
} }
break; break;
case 0xc000: // RJMP k case 0xc000: // RJMP k
offs = (INT32)((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff)); offs = (INT32)((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff));
cpustate->pc += offs; cpustate->pc += offs;
opcycles = 2;
break; break;
case 0xd000: // RCALL k case 0xd000: // RCALL k
offs = (INT32)((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff)); offs = (INT32)((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff));
PUSH(cpustate, ((cpustate->pc + 1) >> 8) & 0x00ff); PUSH(cpustate, ((cpustate->pc + 1) >> 8) & 0x00ff);
PUSH(cpustate, (cpustate->pc + 1) & 0x00ff); PUSH(cpustate, (cpustate->pc + 1) & 0x00ff);
cpustate->pc += offs; cpustate->pc += offs;
opcycles = 3;
break; break;
case 0xe000: // LDI Rd,K case 0xe000: // LDI Rd,K
rd = KCONST8(op); rd = KCONST8(op);
@ -785,6 +887,7 @@ static CPU_EXECUTE( avr8 )
offs |= 0xffffff80; offs |= 0xffffff80;
} }
cpustate->pc += offs; cpustate->pc += offs;
opcycles = 2;
} }
break; break;
case 0x0400: // BRSH through BRID case 0x0400: // BRSH through BRID
@ -796,28 +899,54 @@ static CPU_EXECUTE( avr8 )
offs |= 0xffffff80; offs |= 0xffffff80;
} }
cpustate->pc += offs; cpustate->pc += offs;
opcycles = 2;
} }
break; break;
case 0x0800: case 0x0800:
unimplemented_opcode(cpustate, op);
if(op & 0x0200) // BST Rd, b if(op & 0x0200) // BST Rd, b
{ {
//output += sprintf( output, "BST R%d, %d", RD5(op), RR3(op) ); SREG_W(AVR8_SREG_T, (BIT(READ_IO_8(cpustate, RD5(op)),RR3(op))) ? 1 : 0);
} }
else // BLD Rd, b else // BLD Rd, b
{ {
//output += sprintf( output, "BLD R%d, %d", RD5(op), RR3(op) ); if(SREG_R(AVR8_SREG_T))
{
WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, RD5(op)) | (1 << RR3(op)));
}
else
{
WRITE_IO_8(cpustate, RD5(op), READ_IO_8(cpustate, RD5(op)) &~ (1 << RR3(op)));
}
} }
break; break;
case 0x0c00: case 0x0c00:
unimplemented_opcode(cpustate, op);
if(op & 0x0200) // SBRS Rd, b if(op & 0x0200) // SBRS Rd, b
{ {
//output += sprintf( output, "SBRS R%d, %d", RD5(op), RR3(op) ); if(BIT(READ_IO_8(cpustate, RD5(op)),RR3(op)))
{
op = (UINT32)READ_PRG_16(cpustate, cpustate->pc++);
opcycles = 2;
if((op & 0xfe0c) == 0x940c ||
(op & 0xfe0f) == 0xfe0f)
{
cpustate->pc++;
opcycles = 3;
}
}
} }
else // SBRC Rd, b else // SBRC Rd, b
{ {
//output += sprintf( output, "SBRC R%d, %d", RD5(op), RR3(op) ); if(!BIT(READ_IO_8(cpustate, RD5(op)),RR3(op)))
{
op = (UINT32)READ_PRG_16(cpustate, cpustate->pc++);
opcycles = 2;
if((op & 0xfe0c) == 0x940c ||
(op & 0xfc0f) == 0x9000)
{
cpustate->pc++;
opcycles = 3;
}
}
} }
break; break;
} }
@ -826,7 +955,7 @@ static CPU_EXECUTE( avr8 )
cpustate->pc++; cpustate->pc++;
--cpustate->icount; cpustate->icount -= opcycles;
} }
return cycles - cpustate->icount; return cycles - cpustate->icount;
@ -840,6 +969,35 @@ static CPU_SET_INFO( avr8 )
switch (state) switch (state)
{ {
/* interrupt lines/exceptions */
case CPUINFO_INT_INPUT_STATE + AVR8_INT_RESET: avr8_set_irq_line(cpustate, AVR8_INT_RESET, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_INT0: avr8_set_irq_line(cpustate, AVR8_INT_INT0, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_INT1: avr8_set_irq_line(cpustate, AVR8_INT_INT1, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_PCINT0: avr8_set_irq_line(cpustate, AVR8_INT_PCINT0, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_PCINT1: avr8_set_irq_line(cpustate, AVR8_INT_PCINT1, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_PCINT2: avr8_set_irq_line(cpustate, AVR8_INT_PCINT2, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_WDT: avr8_set_irq_line(cpustate, AVR8_INT_WDT, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_T2COMPA: avr8_set_irq_line(cpustate, AVR8_INT_T2COMPA, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_T2COMPB: avr8_set_irq_line(cpustate, AVR8_INT_T2COMPB, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_T2OVF: avr8_set_irq_line(cpustate, AVR8_INT_T2OVF, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_T1CAPT: avr8_set_irq_line(cpustate, AVR8_INT_T1CAPT, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_T1COMPA: avr8_set_irq_line(cpustate, AVR8_INT_T1COMPA, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_T1COMPB: avr8_set_irq_line(cpustate, AVR8_INT_T1COMPB, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_T1OVF: avr8_set_irq_line(cpustate, AVR8_INT_T1OVF, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_T0COMPA: avr8_set_irq_line(cpustate, AVR8_INT_T0COMPA, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_T0COMPB: avr8_set_irq_line(cpustate, AVR8_INT_T0COMPB, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_T0OVF: avr8_set_irq_line(cpustate, AVR8_INT_T0OVF, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_SPI_STC: avr8_set_irq_line(cpustate, AVR8_INT_SPI_STC, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_USART_RX: avr8_set_irq_line(cpustate, AVR8_INT_USART_RX, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_USART_UDRE: avr8_set_irq_line(cpustate, AVR8_INT_USART_UDRE, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_USART_TX: avr8_set_irq_line(cpustate, AVR8_INT_USART_TX, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_ADC: avr8_set_irq_line(cpustate, AVR8_INT_ADC, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_EE_RDY: avr8_set_irq_line(cpustate, AVR8_INT_EE_RDY, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_ANALOG_COMP: avr8_set_irq_line(cpustate, AVR8_INT_ANALOG_COMP, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_TWI: avr8_set_irq_line(cpustate, AVR8_INT_TWI, info->i); break;
case CPUINFO_INT_INPUT_STATE + AVR8_INT_SPM_RDY: avr8_set_irq_line(cpustate, AVR8_INT_SPM_RDY, info->i); break;
/* --- the following bits of info are set as 64-bit signed integers --- */ /* --- the following bits of info are set as 64-bit signed integers --- */
case CPUINFO_INT_PC: /* intentional fallthrough */ case CPUINFO_INT_PC: /* intentional fallthrough */
case CPUINFO_INT_REGISTER + AVR8_PC: cpustate->pc = info->i; break; case CPUINFO_INT_REGISTER + AVR8_PC: cpustate->pc = info->i; break;
@ -966,5 +1124,6 @@ CPU_GET_INFO( avr8 )
case CPUINFO_STR_REGISTER + AVR8_X: sprintf(info->s, "X: %04x", XREG ); break; case CPUINFO_STR_REGISTER + AVR8_X: sprintf(info->s, "X: %04x", XREG ); break;
case CPUINFO_STR_REGISTER + AVR8_Y: sprintf(info->s, "Y: %04x", YREG ); break; case CPUINFO_STR_REGISTER + AVR8_Y: sprintf(info->s, "Y: %04x", YREG ); break;
case CPUINFO_STR_REGISTER + AVR8_Z: sprintf(info->s, "Z: %04x", ZREG ); break; case CPUINFO_STR_REGISTER + AVR8_Z: sprintf(info->s, "Z: %04x", ZREG ); break;
case CPUINFO_STR_REGISTER + AVR8_SP: sprintf(info->s, "SP: %04x", SPREG ); break;
} }
} }

View File

@ -50,6 +50,37 @@ enum
AVR8_X, AVR8_X,
AVR8_Y, AVR8_Y,
AVR8_Z, AVR8_Z,
AVR8_SP,
};
enum
{
AVR8_INT_RESET = 0,
AVR8_INT_INT0,
AVR8_INT_INT1,
AVR8_INT_PCINT0,
AVR8_INT_PCINT1,
AVR8_INT_PCINT2,
AVR8_INT_WDT,
AVR8_INT_T2COMPA,
AVR8_INT_T2COMPB,
AVR8_INT_T2OVF,
AVR8_INT_T1CAPT,
AVR8_INT_T1COMPA,
AVR8_INT_T1COMPB,
AVR8_INT_T1OVF,
AVR8_INT_T0COMPA,
AVR8_INT_T0COMPB,
AVR8_INT_T0OVF,
AVR8_INT_SPI_STC,
AVR8_INT_USART_RX,
AVR8_INT_USART_UDRE,
AVR8_INT_USART_TX,
AVR8_INT_ADC,
AVR8_INT_EE_RDY,
AVR8_INT_ANALOG_COMP,
AVR8_INT_TWI,
AVR8_INT_SPM_RDY,
}; };
CPU_GET_INFO( avr8 ); CPU_GET_INFO( avr8 );

View File

@ -38,7 +38,7 @@ CPU_DISASSEMBLE( avr8 )
output += sprintf( output, "NOP" ); output += sprintf( output, "NOP" );
break; break;
case 0x0100: case 0x0100:
output += sprintf( output, "MOVW R%d:R%d, R%d:R%d", RD4(op)+1, RD4(op), RR4(op)+1, RR4(op) ); output += sprintf( output, "MOVW R%d:R%d, R%d:R%d", (RD4(op) << 1)+1, RD4(op) << 1, (RR4(op) << 1)+1, RR4(op) << 1 );
break; break;
case 0x0200: case 0x0200:
output += sprintf( output, "MULS R%d, R%d", 16+RD4(op), 16+RR4(op) ); output += sprintf( output, "MULS R%d, R%d", 16+RD4(op), 16+RR4(op) );

View File

@ -558,38 +558,38 @@ void mips3com_get_info(mips3_state *mips, UINT32 state, cpuinfo *info)
case CPUINFO_STR_REGISTER + MIPS3_WIRED: sprintf(info->s, "Wired:%08X", (UINT32)mips->cpr[0][COP0_Wired]); break; case CPUINFO_STR_REGISTER + MIPS3_WIRED: sprintf(info->s, "Wired:%08X", (UINT32)mips->cpr[0][COP0_Wired]); break;
case CPUINFO_STR_REGISTER + MIPS3_BADVADDR: sprintf(info->s, "BadVAddr:%08X", (UINT32)mips->cpr[0][COP0_BadVAddr]); break; case CPUINFO_STR_REGISTER + MIPS3_BADVADDR: sprintf(info->s, "BadVAddr:%08X", (UINT32)mips->cpr[0][COP0_BadVAddr]); break;
case CPUINFO_STR_REGISTER + MIPS3_R0: sprintf(info->s, "R0: %08X%08X", (UINT32)(mips->r[0] >> 32), (UINT32)mips->r[0]); break; case CPUINFO_STR_REGISTER + MIPS3_R0: sprintf(info->s, "$zero: %08X%08X", (UINT32)(mips->r[0] >> 32), (UINT32)mips->r[0]); break;
case CPUINFO_STR_REGISTER + MIPS3_R1: sprintf(info->s, "R1: %08X%08X", (UINT32)(mips->r[1] >> 32), (UINT32)mips->r[1]); break; case CPUINFO_STR_REGISTER + MIPS3_R1: sprintf(info->s, " $at: %08X%08X", (UINT32)(mips->r[1] >> 32), (UINT32)mips->r[1]); break;
case CPUINFO_STR_REGISTER + MIPS3_R2: sprintf(info->s, "R2: %08X%08X", (UINT32)(mips->r[2] >> 32), (UINT32)mips->r[2]); break; case CPUINFO_STR_REGISTER + MIPS3_R2: sprintf(info->s, " $v0: %08X%08X", (UINT32)(mips->r[2] >> 32), (UINT32)mips->r[2]); break;
case CPUINFO_STR_REGISTER + MIPS3_R3: sprintf(info->s, "R3: %08X%08X", (UINT32)(mips->r[3] >> 32), (UINT32)mips->r[3]); break; case CPUINFO_STR_REGISTER + MIPS3_R3: sprintf(info->s, " $v1: %08X%08X", (UINT32)(mips->r[3] >> 32), (UINT32)mips->r[3]); break;
case CPUINFO_STR_REGISTER + MIPS3_R4: sprintf(info->s, "R4: %08X%08X", (UINT32)(mips->r[4] >> 32), (UINT32)mips->r[4]); break; case CPUINFO_STR_REGISTER + MIPS3_R4: sprintf(info->s, " $a0: %08X%08X", (UINT32)(mips->r[4] >> 32), (UINT32)mips->r[4]); break;
case CPUINFO_STR_REGISTER + MIPS3_R5: sprintf(info->s, "R5: %08X%08X", (UINT32)(mips->r[5] >> 32), (UINT32)mips->r[5]); break; case CPUINFO_STR_REGISTER + MIPS3_R5: sprintf(info->s, " $a1: %08X%08X", (UINT32)(mips->r[5] >> 32), (UINT32)mips->r[5]); break;
case CPUINFO_STR_REGISTER + MIPS3_R6: sprintf(info->s, "R6: %08X%08X", (UINT32)(mips->r[6] >> 32), (UINT32)mips->r[6]); break; case CPUINFO_STR_REGISTER + MIPS3_R6: sprintf(info->s, " $a2: %08X%08X", (UINT32)(mips->r[6] >> 32), (UINT32)mips->r[6]); break;
case CPUINFO_STR_REGISTER + MIPS3_R7: sprintf(info->s, "R7: %08X%08X", (UINT32)(mips->r[7] >> 32), (UINT32)mips->r[7]); break; case CPUINFO_STR_REGISTER + MIPS3_R7: sprintf(info->s, " $a3: %08X%08X", (UINT32)(mips->r[7] >> 32), (UINT32)mips->r[7]); break;
case CPUINFO_STR_REGISTER + MIPS3_R8: sprintf(info->s, "R8: %08X%08X", (UINT32)(mips->r[8] >> 32), (UINT32)mips->r[8]); break; case CPUINFO_STR_REGISTER + MIPS3_R8: sprintf(info->s, " $t0: %08X%08X", (UINT32)(mips->r[8] >> 32), (UINT32)mips->r[8]); break;
case CPUINFO_STR_REGISTER + MIPS3_R9: sprintf(info->s, "R9: %08X%08X", (UINT32)(mips->r[9] >> 32), (UINT32)mips->r[9]); break; case CPUINFO_STR_REGISTER + MIPS3_R9: sprintf(info->s, " $t1: %08X%08X", (UINT32)(mips->r[9] >> 32), (UINT32)mips->r[9]); break;
case CPUINFO_STR_REGISTER + MIPS3_R10: sprintf(info->s, "R10:%08X%08X", (UINT32)(mips->r[10] >> 32), (UINT32)mips->r[10]); break; case CPUINFO_STR_REGISTER + MIPS3_R10: sprintf(info->s, " $t2:%08X%08X", (UINT32)(mips->r[10] >> 32), (UINT32)mips->r[10]); break;
case CPUINFO_STR_REGISTER + MIPS3_R11: sprintf(info->s, "R11:%08X%08X", (UINT32)(mips->r[11] >> 32), (UINT32)mips->r[11]); break; case CPUINFO_STR_REGISTER + MIPS3_R11: sprintf(info->s, " $t3:%08X%08X", (UINT32)(mips->r[11] >> 32), (UINT32)mips->r[11]); break;
case CPUINFO_STR_REGISTER + MIPS3_R12: sprintf(info->s, "R12:%08X%08X", (UINT32)(mips->r[12] >> 32), (UINT32)mips->r[12]); break; case CPUINFO_STR_REGISTER + MIPS3_R12: sprintf(info->s, " $t4:%08X%08X", (UINT32)(mips->r[12] >> 32), (UINT32)mips->r[12]); break;
case CPUINFO_STR_REGISTER + MIPS3_R13: sprintf(info->s, "R13:%08X%08X", (UINT32)(mips->r[13] >> 32), (UINT32)mips->r[13]); break; case CPUINFO_STR_REGISTER + MIPS3_R13: sprintf(info->s, " $t5:%08X%08X", (UINT32)(mips->r[13] >> 32), (UINT32)mips->r[13]); break;
case CPUINFO_STR_REGISTER + MIPS3_R14: sprintf(info->s, "R14:%08X%08X", (UINT32)(mips->r[14] >> 32), (UINT32)mips->r[14]); break; case CPUINFO_STR_REGISTER + MIPS3_R14: sprintf(info->s, " $t6:%08X%08X", (UINT32)(mips->r[14] >> 32), (UINT32)mips->r[14]); break;
case CPUINFO_STR_REGISTER + MIPS3_R15: sprintf(info->s, "R15:%08X%08X", (UINT32)(mips->r[15] >> 32), (UINT32)mips->r[15]); break; case CPUINFO_STR_REGISTER + MIPS3_R15: sprintf(info->s, " $t7:%08X%08X", (UINT32)(mips->r[15] >> 32), (UINT32)mips->r[15]); break;
case CPUINFO_STR_REGISTER + MIPS3_R16: sprintf(info->s, "R16:%08X%08X", (UINT32)(mips->r[16] >> 32), (UINT32)mips->r[16]); break; case CPUINFO_STR_REGISTER + MIPS3_R16: sprintf(info->s, " $s0:%08X%08X", (UINT32)(mips->r[16] >> 32), (UINT32)mips->r[16]); break;
case CPUINFO_STR_REGISTER + MIPS3_R17: sprintf(info->s, "R17:%08X%08X", (UINT32)(mips->r[17] >> 32), (UINT32)mips->r[17]); break; case CPUINFO_STR_REGISTER + MIPS3_R17: sprintf(info->s, " $s1:%08X%08X", (UINT32)(mips->r[17] >> 32), (UINT32)mips->r[17]); break;
case CPUINFO_STR_REGISTER + MIPS3_R18: sprintf(info->s, "R18:%08X%08X", (UINT32)(mips->r[18] >> 32), (UINT32)mips->r[18]); break; case CPUINFO_STR_REGISTER + MIPS3_R18: sprintf(info->s, " $s2:%08X%08X", (UINT32)(mips->r[18] >> 32), (UINT32)mips->r[18]); break;
case CPUINFO_STR_REGISTER + MIPS3_R19: sprintf(info->s, "R19:%08X%08X", (UINT32)(mips->r[19] >> 32), (UINT32)mips->r[19]); break; case CPUINFO_STR_REGISTER + MIPS3_R19: sprintf(info->s, " $s3:%08X%08X", (UINT32)(mips->r[19] >> 32), (UINT32)mips->r[19]); break;
case CPUINFO_STR_REGISTER + MIPS3_R20: sprintf(info->s, "R20:%08X%08X", (UINT32)(mips->r[20] >> 32), (UINT32)mips->r[20]); break; case CPUINFO_STR_REGISTER + MIPS3_R20: sprintf(info->s, " $s4:%08X%08X", (UINT32)(mips->r[20] >> 32), (UINT32)mips->r[20]); break;
case CPUINFO_STR_REGISTER + MIPS3_R21: sprintf(info->s, "R21:%08X%08X", (UINT32)(mips->r[21] >> 32), (UINT32)mips->r[21]); break; case CPUINFO_STR_REGISTER + MIPS3_R21: sprintf(info->s, " $s5:%08X%08X", (UINT32)(mips->r[21] >> 32), (UINT32)mips->r[21]); break;
case CPUINFO_STR_REGISTER + MIPS3_R22: sprintf(info->s, "R22:%08X%08X", (UINT32)(mips->r[22] >> 32), (UINT32)mips->r[22]); break; case CPUINFO_STR_REGISTER + MIPS3_R22: sprintf(info->s, " $s6:%08X%08X", (UINT32)(mips->r[22] >> 32), (UINT32)mips->r[22]); break;
case CPUINFO_STR_REGISTER + MIPS3_R23: sprintf(info->s, "R23:%08X%08X", (UINT32)(mips->r[23] >> 32), (UINT32)mips->r[23]); break; case CPUINFO_STR_REGISTER + MIPS3_R23: sprintf(info->s, " $s7:%08X%08X", (UINT32)(mips->r[23] >> 32), (UINT32)mips->r[23]); break;
case CPUINFO_STR_REGISTER + MIPS3_R24: sprintf(info->s, "R24:%08X%08X", (UINT32)(mips->r[24] >> 32), (UINT32)mips->r[24]); break; case CPUINFO_STR_REGISTER + MIPS3_R24: sprintf(info->s, " $t8:%08X%08X", (UINT32)(mips->r[24] >> 32), (UINT32)mips->r[24]); break;
case CPUINFO_STR_REGISTER + MIPS3_R25: sprintf(info->s, "R25:%08X%08X", (UINT32)(mips->r[25] >> 32), (UINT32)mips->r[25]); break; case CPUINFO_STR_REGISTER + MIPS3_R25: sprintf(info->s, " $t9:%08X%08X", (UINT32)(mips->r[25] >> 32), (UINT32)mips->r[25]); break;
case CPUINFO_STR_REGISTER + MIPS3_R26: sprintf(info->s, "R26:%08X%08X", (UINT32)(mips->r[26] >> 32), (UINT32)mips->r[26]); break; case CPUINFO_STR_REGISTER + MIPS3_R26: sprintf(info->s, " $k0:%08X%08X", (UINT32)(mips->r[26] >> 32), (UINT32)mips->r[26]); break;
case CPUINFO_STR_REGISTER + MIPS3_R27: sprintf(info->s, "R27:%08X%08X", (UINT32)(mips->r[27] >> 32), (UINT32)mips->r[27]); break; case CPUINFO_STR_REGISTER + MIPS3_R27: sprintf(info->s, " $k1:%08X%08X", (UINT32)(mips->r[27] >> 32), (UINT32)mips->r[27]); break;
case CPUINFO_STR_REGISTER + MIPS3_R28: sprintf(info->s, "R28:%08X%08X", (UINT32)(mips->r[28] >> 32), (UINT32)mips->r[28]); break; case CPUINFO_STR_REGISTER + MIPS3_R28: sprintf(info->s, " $gp:%08X%08X", (UINT32)(mips->r[28] >> 32), (UINT32)mips->r[28]); break;
case CPUINFO_STR_REGISTER + MIPS3_R29: sprintf(info->s, "R29:%08X%08X", (UINT32)(mips->r[29] >> 32), (UINT32)mips->r[29]); break; case CPUINFO_STR_REGISTER + MIPS3_R29: sprintf(info->s, " $sp:%08X%08X", (UINT32)(mips->r[29] >> 32), (UINT32)mips->r[29]); break;
case CPUINFO_STR_REGISTER + MIPS3_R30: sprintf(info->s, "R30:%08X%08X", (UINT32)(mips->r[30] >> 32), (UINT32)mips->r[30]); break; case CPUINFO_STR_REGISTER + MIPS3_R30: sprintf(info->s, " $fp:%08X%08X", (UINT32)(mips->r[30] >> 32), (UINT32)mips->r[30]); break;
case CPUINFO_STR_REGISTER + MIPS3_R31: sprintf(info->s, "R31:%08X%08X", (UINT32)(mips->r[31] >> 32), (UINT32)mips->r[31]); break; case CPUINFO_STR_REGISTER + MIPS3_R31: sprintf(info->s, " $ra:%08X%08X", (UINT32)(mips->r[31] >> 32), (UINT32)mips->r[31]); break;
case CPUINFO_STR_REGISTER + MIPS3_HI: sprintf(info->s, "HI: %08X%08X", (UINT32)(mips->r[REG_HI] >> 32), (UINT32)mips->r[REG_HI]); break; case CPUINFO_STR_REGISTER + MIPS3_HI: sprintf(info->s, "HI: %08X%08X", (UINT32)(mips->r[REG_HI] >> 32), (UINT32)mips->r[REG_HI]); break;
case CPUINFO_STR_REGISTER + MIPS3_LO: sprintf(info->s, "LO: %08X%08X", (UINT32)(mips->r[REG_LO] >> 32), (UINT32)mips->r[REG_LO]); break; case CPUINFO_STR_REGISTER + MIPS3_LO: sprintf(info->s, "LO: %08X%08X", (UINT32)(mips->r[REG_LO] >> 32), (UINT32)mips->r[REG_LO]); break;

View File

@ -11,10 +11,10 @@
static const char *const reg[32] = static const char *const reg[32] =
{ {
"0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "$0", "$at", "$v0", "$v1", "$a0", "$a1", "$a2", "$a3",
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7",
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", "$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7",
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" "$t8", "$t9", "$k0", "$k1", "$gp", "$sp", "$fp", "$ra"
}; };

View File

@ -18,7 +18,12 @@ typedef struct
typedef struct _superfx_state superfx_state; typedef struct _superfx_state superfx_state;
struct _superfx_state struct _superfx_state
{ {
superfx_config config;
devcb_resolved_write_line out_irq_func;
UINT8 pipeline; UINT8 pipeline;
UINT16 ramaddr; // RAM Address
UINT16 r[16]; // GPRs UINT16 r[16]; // GPRs
UINT16 sfr; // Status Flag Register UINT16 sfr; // Status Flag Register
@ -41,7 +46,6 @@ struct _superfx_state
UINT32 ramcl; // Clock ticks until RAMDR is valid; UINT32 ramcl; // Clock ticks until RAMDR is valid;
UINT16 ramar; // RAM Buffer Address Register UINT16 ramar; // RAM Buffer Address Register
UINT8 ramdr; // RAM Buffer Data Register UINT8 ramdr; // RAM Buffer Data Register
UINT16 ramaddr; // RAM Address
UINT16 *sreg; // Source Register (From) UINT16 *sreg; // Source Register (From)
UINT8 sreg_idx;// Source Register (To), index UINT8 sreg_idx;// Source Register (To), index
@ -81,17 +85,24 @@ static void superfx_cache_mmio_write(superfx_state *cpustate, UINT32 addr, UINT8
static void superfx_memory_reset(superfx_state *cpustate); static void superfx_memory_reset(superfx_state *cpustate);
INLINE UINT8 superfx_bus_read(superfx_state *cpustate, UINT32 addr); INLINE UINT8 superfx_bus_read(superfx_state *cpustate, UINT32 addr);
INLINE void superfx_bus_write(superfx_state *cpustate, UINT32 addr, UINT8 data); INLINE void superfx_bus_write(superfx_state *cpustate, UINT32 addr, UINT8 data);
static void superfx_pixelcache_flush(superfx_state *cpustate, INT32 line); INLINE void superfx_pixelcache_flush(superfx_state *cpustate, INT32 line);
static void superfx_plot(superfx_state *cpustate, UINT8 x, UINT8 y); INLINE void superfx_plot(superfx_state *cpustate, UINT8 x, UINT8 y);
static UINT8 superfx_rpix(superfx_state *cpustate, UINT8 r1, UINT8 r2); static UINT8 superfx_rpix(superfx_state *cpustate, UINT8 r1, UINT8 r2);
static UINT8 superfx_color(superfx_state *cpustate, UINT8 source); INLINE UINT8 superfx_color(superfx_state *cpustate, UINT8 source);
INLINE void superfx_rambuffer_sync(superfx_state *cpustate);
INLINE UINT8 superfx_rambuffer_read(superfx_state *cpustate, UINT16 addr); INLINE UINT8 superfx_rambuffer_read(superfx_state *cpustate, UINT16 addr);
INLINE void superfx_rambuffer_write(superfx_state *cpustate, UINT16 addr, UINT8 val); INLINE void superfx_rambuffer_write(superfx_state *cpustate, UINT16 addr, UINT8 val);
INLINE void superfx_rombuffer_sync(superfx_state *cpustate);
INLINE void superfx_rombuffer_update(superfx_state *cpustate);
INLINE UINT8 superfx_rombuffer_read(superfx_state *cpustate);
INLINE void superfx_gpr_write(superfx_state *cpustate, UINT8 r, UINT16 data); INLINE void superfx_gpr_write(superfx_state *cpustate, UINT8 r, UINT16 data);
INLINE UINT8 superfx_op_read(superfx_state *cpustate, UINT16 addr); INLINE UINT8 superfx_op_read(superfx_state *cpustate, UINT16 addr);
INLINE UINT8 superfx_peekpipe(superfx_state *cpustate); INLINE UINT8 superfx_peekpipe(superfx_state *cpustate);
INLINE UINT8 superfx_pipe(superfx_state *cpustate); INLINE UINT8 superfx_pipe(superfx_state *cpustate);
static void superfx_add_clocks_internal(superfx_state *cpustate, INT32 clocks); INLINE void superfx_add_clocks_internal(superfx_state *cpustate, UINT32 clocks);
static void superfx_timing_reset(superfx_state *cpustate); static void superfx_timing_reset(superfx_state *cpustate);
/*****************************************************************************/ /*****************************************************************************/
@ -137,14 +148,12 @@ static void superfx_cache_flush(superfx_state *cpustate)
static UINT8 superfx_cache_mmio_read(superfx_state *cpustate, UINT32 addr) static UINT8 superfx_cache_mmio_read(superfx_state *cpustate, UINT32 addr)
{ {
addr = (addr + cpustate->cbr) & 0x1ff; addr = (addr + cpustate->cbr) & 0x1ff;
printf( "superfx_cache_mmio_read: %04x = %02x\n", addr, cpustate->cache.buffer[addr] );
return cpustate->cache.buffer[addr]; return cpustate->cache.buffer[addr];
} }
static void superfx_cache_mmio_write(superfx_state *cpustate, UINT32 addr, UINT8 data) static void superfx_cache_mmio_write(superfx_state *cpustate, UINT32 addr, UINT8 data)
{ {
addr = (addr + cpustate->cbr) & 0x1ff; addr = (addr + cpustate->cbr) & 0x1ff;
printf( "superfx_cache_mmio_write: %04x = %02x\n", addr, data );
cpustate->cache.buffer[addr] = data; cpustate->cache.buffer[addr] = data;
if((addr & 15) == 15) if((addr & 15) == 15)
{ {
@ -180,7 +189,7 @@ INLINE void superfx_bus_write(superfx_state *cpustate, UINT32 addr, UINT8 data)
memory_write_byte(cpustate->program, addr, data); memory_write_byte(cpustate->program, addr, data);
} }
static void superfx_pixelcache_flush(superfx_state *cpustate, INT32 line) INLINE void superfx_pixelcache_flush(superfx_state *cpustate, INT32 line)
{ {
UINT8 x = cpustate->pixelcache[line].offset << 3; UINT8 x = cpustate->pixelcache[line].offset << 3;
UINT8 y = cpustate->pixelcache[line].offset >> 5; UINT8 y = cpustate->pixelcache[line].offset >> 5;
@ -225,7 +234,6 @@ static void superfx_pixelcache_flush(superfx_state *cpustate, INT32 line)
{ {
superfx_add_clocks_internal(cpustate, cpustate->memory_access_speed); superfx_add_clocks_internal(cpustate, cpustate->memory_access_speed);
data &= cpustate->pixelcache[line].bitpend; data &= cpustate->pixelcache[line].bitpend;
//printf( "superfx_pixelcache_flush: calling superfx_bus_read\n" );
data |= superfx_bus_read(cpustate, addr + byte) & ~cpustate->pixelcache[line].bitpend; data |= superfx_bus_read(cpustate, addr + byte) & ~cpustate->pixelcache[line].bitpend;
} }
superfx_add_clocks_internal(cpustate, cpustate->memory_access_speed); superfx_add_clocks_internal(cpustate, cpustate->memory_access_speed);
@ -235,13 +243,11 @@ static void superfx_pixelcache_flush(superfx_state *cpustate, INT32 line)
cpustate->pixelcache[line].bitpend = 0x00; cpustate->pixelcache[line].bitpend = 0x00;
} }
static void superfx_plot(superfx_state *cpustate, UINT8 x, UINT8 y) INLINE void superfx_plot(superfx_state *cpustate, UINT8 x, UINT8 y)
{ {
UINT8 color = cpustate->colr; UINT8 color = cpustate->colr;
UINT16 offset = (y << 5) + (x >> 3); UINT16 offset = (y << 5) + (x >> 3);
//printf( "%08x: plot: %d, %d = %02x\n", cpustate->r[15], x, y, color );
if((cpustate->por & SUPERFX_POR_DITHER) != 0 && (cpustate->scmr & SUPERFX_SCMR_MD) != 3) if((cpustate->por & SUPERFX_POR_DITHER) != 0 && (cpustate->scmr & SUPERFX_SCMR_MD) != 3)
{ {
if((x ^ y) & 1) if((x ^ y) & 1)
@ -282,42 +288,20 @@ static void superfx_plot(superfx_state *cpustate, UINT8 x, UINT8 y)
if(offset != cpustate->pixelcache[0].offset) if(offset != cpustate->pixelcache[0].offset)
{ {
superfx_pixelcache_flush(cpustate, 1); superfx_pixelcache_flush(cpustate, 1);
cpustate->pixelcache[1].bitpend = cpustate->pixelcache[0].bitpend;
cpustate->pixelcache[1].offset = cpustate->pixelcache[0].offset;
cpustate->pixelcache[1].data[0] = cpustate->pixelcache[0].data[0];
cpustate->pixelcache[1].data[1] = cpustate->pixelcache[0].data[1];
cpustate->pixelcache[1].data[2] = cpustate->pixelcache[0].data[2];
cpustate->pixelcache[1].data[3] = cpustate->pixelcache[0].data[3];
cpustate->pixelcache[1].data[4] = cpustate->pixelcache[0].data[4];
cpustate->pixelcache[1].data[5] = cpustate->pixelcache[0].data[5];
cpustate->pixelcache[1].data[6] = cpustate->pixelcache[0].data[6];
cpustate->pixelcache[1].data[7] = cpustate->pixelcache[0].data[7];
cpustate->pixelcache[1] = cpustate->pixelcache[0]; cpustate->pixelcache[1] = cpustate->pixelcache[0];
cpustate->pixelcache[0].bitpend = 0x00; cpustate->pixelcache[0].bitpend = 0x00;
cpustate->pixelcache[0].offset = offset; cpustate->pixelcache[0].offset = offset;
} }
x = (x & 7) ^ 7; x = (x & 7) ^ 7;
cpustate->pixelcache[0].data[x] = 0x0f;//color; cpustate->pixelcache[0].data[x] = color;
cpustate->pixelcache[0].bitpend |= 1 << x; cpustate->pixelcache[0].bitpend |= 1 << x;
if(cpustate->pixelcache[0].bitpend == 0xff) if(cpustate->pixelcache[0].bitpend == 0xff)
{ {
superfx_pixelcache_flush(cpustate, 1); superfx_pixelcache_flush(cpustate, 1);
cpustate->pixelcache[1].bitpend = cpustate->pixelcache[0].bitpend; cpustate->pixelcache[1] = cpustate->pixelcache[0];
cpustate->pixelcache[1].offset = cpustate->pixelcache[0].offset;
cpustate->pixelcache[1].data[0] = cpustate->pixelcache[0].data[0];
cpustate->pixelcache[1].data[1] = cpustate->pixelcache[0].data[1];
cpustate->pixelcache[1].data[2] = cpustate->pixelcache[0].data[2];
cpustate->pixelcache[1].data[3] = cpustate->pixelcache[0].data[3];
cpustate->pixelcache[1].data[4] = cpustate->pixelcache[0].data[4];
cpustate->pixelcache[1].data[5] = cpustate->pixelcache[0].data[5];
cpustate->pixelcache[1].data[6] = cpustate->pixelcache[0].data[6];
cpustate->pixelcache[1].data[7] = cpustate->pixelcache[0].data[7];
cpustate->pixelcache[0].bitpend = 0x00; cpustate->pixelcache[0].bitpend = 0x00;
} }
//superfx_pixelcache_flush(cpustate, 1);
//superfx_pixelcache_flush(cpustate, 0);
} }
static UINT8 superfx_rpix(superfx_state *cpustate, UINT8 x, UINT8 y) static UINT8 superfx_rpix(superfx_state *cpustate, UINT8 x, UINT8 y)
@ -359,14 +343,11 @@ static UINT8 superfx_rpix(superfx_state *cpustate, UINT8 x, UINT8 y)
data |= ((superfx_bus_read(cpustate, addr + byte) >> x) & 1) << n; data |= ((superfx_bus_read(cpustate, addr + byte) >> x) & 1) << n;
} }
//printf( "%08x: superfx_rpix; %d, %d = %02x\n", (cpustate->pbr << 16) | cpustate->r[15], x, y, data );
return data; return data;
} }
static UINT8 superfx_color(superfx_state *cpustate, UINT8 source) INLINE UINT8 superfx_color(superfx_state *cpustate, UINT8 source)
{ {
//printf("superfx_color\n" );
if(cpustate->por & SUPERFX_POR_HIGHNIBBLE) if(cpustate->por & SUPERFX_POR_HIGHNIBBLE)
{ {
return (cpustate->colr & 0xf0) | (source >> 4); return (cpustate->colr & 0xf0) | (source >> 4);
@ -378,20 +359,56 @@ static UINT8 superfx_color(superfx_state *cpustate, UINT8 source)
return source; return source;
} }
INLINE void superfx_rambuffer_sync(superfx_state *cpustate)
{
if(cpustate->ramcl)
{
superfx_add_clocks_internal(cpustate, cpustate->ramcl);
}
}
INLINE UINT8 superfx_rambuffer_read(superfx_state *cpustate, UINT16 addr) INLINE UINT8 superfx_rambuffer_read(superfx_state *cpustate, UINT16 addr)
{ {
superfx_rambuffer_sync(cpustate);
return superfx_bus_read(cpustate, 0x700000 + (cpustate->rambr << 16) + addr); return superfx_bus_read(cpustate, 0x700000 + (cpustate->rambr << 16) + addr);
} }
INLINE void superfx_rambuffer_write(superfx_state *cpustate, UINT16 addr, UINT8 data) INLINE void superfx_rambuffer_write(superfx_state *cpustate, UINT16 addr, UINT8 data)
{ {
superfx_bus_write(cpustate, 0x700000 + (cpustate->rambr << 16) + addr, data); superfx_rambuffer_sync(cpustate);
cpustate->ramcl = cpustate->memory_access_speed;
cpustate->ramar = addr;
cpustate->ramdr = data;
}
static void superfx_rombuffer_sync(superfx_state *cpustate)
{
if(cpustate->romcl)
{
superfx_add_clocks_internal(cpustate, cpustate->romcl);
}
}
static void superfx_rombuffer_update(superfx_state *cpustate)
{
cpustate->sfr |= SUPERFX_SFR_R;
cpustate->romcl = cpustate->memory_access_speed;
}
static UINT8 superfx_rombuffer_read(superfx_state *cpustate)
{
superfx_rombuffer_sync(cpustate);
return cpustate->romdr;
} }
INLINE void superfx_gpr_write(superfx_state *cpustate, UINT8 r, UINT16 data) INLINE void superfx_gpr_write(superfx_state *cpustate, UINT8 r, UINT16 data)
{ {
cpustate->r[r] = data; cpustate->r[r] = data;
if(r == 15) if(r == 14)
{
superfx_rombuffer_update(cpustate);
}
else if(r == 15)
{ {
cpustate->r15_modified = 1; cpustate->r15_modified = 1;
} }
@ -421,7 +438,20 @@ INLINE UINT8 superfx_op_read(superfx_state *cpustate, UINT16 addr)
return cpustate->cache.buffer[offset]; return cpustate->cache.buffer[offset];
} }
return superfx_bus_read(cpustate, (cpustate->pbr << 16) + addr); if(cpustate->pbr <= 0x5f)
{
//$[00-5f]:[0000-ffff] ROM
superfx_rombuffer_sync(cpustate);
superfx_add_clocks_internal(cpustate, cpustate->memory_access_speed);
return superfx_bus_read(cpustate, (cpustate->pbr << 16) + addr);
}
else
{
//$[60-7f]:[0000-ffff] RAM
superfx_rambuffer_sync(cpustate);
superfx_add_clocks_internal(cpustate, cpustate->memory_access_speed);
return superfx_bus_read(cpustate, (cpustate->pbr << 16) + addr);
}
} }
INLINE UINT8 superfx_peekpipe(superfx_state *cpustate) INLINE UINT8 superfx_peekpipe(superfx_state *cpustate)
@ -468,6 +498,7 @@ UINT8 superfx_mmio_read(const device_config *cpu, UINT32 addr)
UINT8 r = cpustate->sfr >> 8; UINT8 r = cpustate->sfr >> 8;
cpustate->sfr &= ~SUPERFX_SFR_IRQ; cpustate->sfr &= ~SUPERFX_SFR_IRQ;
cpustate->irq = 0; cpustate->irq = 0;
devcb_call_write_line(&cpustate->out_irq_func, cpustate->irq);
return r; return r;
} }
@ -490,8 +521,6 @@ UINT8 superfx_mmio_read(const device_config *cpu, UINT32 addr)
return cpustate->cbr >> 8; return cpustate->cbr >> 8;
} }
printf( "Unsuppoted mmio read: %08x\n", addr );
return 0; return 0;
} }
@ -506,8 +535,6 @@ void superfx_mmio_write(const device_config *cpu, UINT32 addr, UINT8 data)
return superfx_cache_mmio_write(cpustate, addr - 0x3100, data); return superfx_cache_mmio_write(cpustate, addr - 0x3100, data);
} }
//printf( "superfx_mmio_write: %08x = %02x\n", addr, data );
if(addr >= 0x3000 && addr <= 0x301f) if(addr >= 0x3000 && addr <= 0x301f)
{ {
UINT32 n = (addr >> 1) & 0xf; UINT32 n = (addr >> 1) & 0xf;
@ -523,7 +550,6 @@ void superfx_mmio_write(const device_config *cpu, UINT32 addr, UINT8 data)
if(addr == 0x301f) if(addr == 0x301f)
{ {
cpustate->sfr |= SUPERFX_SFR_G; cpustate->sfr |= SUPERFX_SFR_G;
//printf( "new PC: %04x\n", cpustate->r[15] );
} }
return; return;
} }
@ -572,14 +598,29 @@ void superfx_mmio_write(const device_config *cpu, UINT32 addr, UINT8 data)
case 0x303a: case 0x303a:
cpustate->scmr = data; cpustate->scmr = data;
break; break;
default:
printf( "Unsuppoted mmio write: %08x = %02x\n", addr, data );
} }
} }
static void superfx_add_clocks_internal(superfx_state *cpustate, INT32 clocks) INLINE void superfx_add_clocks_internal(superfx_state *cpustate, UINT32 clocks)
{ {
if(cpustate->romcl)
{
cpustate->romcl -= MIN(clocks, cpustate->romcl);
if(cpustate->romcl == 0)
{
cpustate->sfr &= ~SUPERFX_SFR_R;
cpustate->romdr = superfx_bus_read(cpustate, (cpustate->rombr << 16) + cpustate->r[14]);
}
}
if(cpustate->ramcl)
{
cpustate->ramcl -= MIN(clocks, cpustate->ramcl);
if(cpustate->ramcl == 0)
{
superfx_bus_write(cpustate, 0x700000 + (cpustate->rambr << 16) + cpustate->ramar, cpustate->ramdr);
}
}
} }
static void superfx_timing_reset(superfx_state *cpustate) static void superfx_timing_reset(superfx_state *cpustate)
@ -637,6 +678,13 @@ static CPU_INIT( superfx )
cpustate->device = device; cpustate->device = device;
cpustate->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM); cpustate->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM);
if (device->static_config != NULL)
{
cpustate->config = *(superfx_config *)device->static_config;
}
devcb_resolve_write_line(&cpustate->out_irq_func, &cpustate->config.out_irq_func, device);
} }
static CPU_EXIT( superfx ) static CPU_EXIT( superfx )
@ -707,18 +755,17 @@ static CPU_EXECUTE( superfx )
op = superfx_peekpipe(cpustate); op = superfx_peekpipe(cpustate);
//printf( "Executing op at %06x: %02x\n", (cpustate->pbr << 16) | cpustate->r[15], op );
switch(op) switch(op)
{ {
case 0x00: // STOP case 0x00: // STOP
if(!(cpustate->cfgr & SUPERFX_CFGR_IRQ)) if((cpustate->cfgr & SUPERFX_CFGR_IRQ) == 0)
{ {
cpustate->sfr |= SUPERFX_SFR_IRQ; cpustate->sfr |= SUPERFX_SFR_IRQ;
cpustate->irq = 1; cpustate->irq = 1;
devcb_call_write_line(&cpustate->out_irq_func, cpustate->irq ? ASSERT_LINE : CLEAR_LINE );
} }
cpustate->sfr &= ~SUPERFX_SFR_G; cpustate->sfr &= ~SUPERFX_SFR_G;
cpustate->pipeline = 0x01; cpustate->pipeline = 0x01;
cpustate->por = 0x00;
superfx_regs_reset(cpustate); superfx_regs_reset(cpustate);
break; break;
case 0x01: // NOP case 0x01: // NOP
@ -848,7 +895,7 @@ static CPU_EXECUTE( superfx )
case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: // TO case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: // TO
if(!(cpustate->sfr & SUPERFX_SFR_B)) if((cpustate->sfr & SUPERFX_SFR_B) == 0)
{ {
cpustate->dreg = &cpustate->r[op & 0xf]; cpustate->dreg = &cpustate->r[op & 0xf];
cpustate->dreg_idx = op & 0xf; cpustate->dreg_idx = op & 0xf;
@ -959,7 +1006,6 @@ static CPU_EXECUTE( superfx )
} }
else else
{ // CMODE { // CMODE
//printf( "CMODE: %04x\n", *(cpustate->sreg) );
cpustate->por = *(cpustate->sreg); cpustate->por = *(cpustate->sreg);
superfx_regs_reset(cpustate); superfx_regs_reset(cpustate);
} }
@ -1148,7 +1194,7 @@ static CPU_EXECUTE( superfx )
} }
else else
{ // LJMP { // LJMP
cpustate->pbr = cpustate->r[op & 0xf] & 0x7f; cpustate->pbr = cpustate->r[op & 0xf];
superfx_gpr_write(cpustate, 15, *(cpustate->sreg)); superfx_gpr_write(cpustate, 15, *(cpustate->sreg));
cpustate->cbr = cpustate->r[15] & 0xfff0; cpustate->cbr = cpustate->r[15] & 0xfff0;
superfx_cache_flush(cpustate); superfx_cache_flush(cpustate);
@ -1157,7 +1203,7 @@ static CPU_EXECUTE( superfx )
break; break;
case 0x9e: // LOB case 0x9e: // LOB
superfx_gpr_write(cpustate, cpustate->dreg_idx, (UINT16)(*(cpustate->sreg)) & 0xff); superfx_gpr_write(cpustate, cpustate->dreg_idx, (UINT16)(*(cpustate->sreg)) & 0x00ff);
cpustate->sfr &= ~(SUPERFX_SFR_S | SUPERFX_SFR_Z); cpustate->sfr &= ~(SUPERFX_SFR_S | SUPERFX_SFR_Z);
cpustate->sfr |= (*(cpustate->dreg) & 0x80) ? SUPERFX_SFR_S : 0; cpustate->sfr |= (*(cpustate->dreg) & 0x80) ? SUPERFX_SFR_S : 0;
cpustate->sfr |= (*(cpustate->dreg) == 0) ? SUPERFX_SFR_Z : 0; cpustate->sfr |= (*(cpustate->dreg) == 0) ? SUPERFX_SFR_Z : 0;
@ -1210,7 +1256,7 @@ static CPU_EXECUTE( superfx )
case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7: case 0xb0: case 0xb1: case 0xb2: case 0xb3: case 0xb4: case 0xb5: case 0xb6: case 0xb7:
case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: // FROM case 0xb8: case 0xb9: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: // FROM
if(!(cpustate->sfr & SUPERFX_SFR_B)) if((cpustate->sfr & SUPERFX_SFR_B) == 0)
{ {
cpustate->sreg = &(cpustate->r[op & 0xf]); cpustate->sreg = &(cpustate->r[op & 0xf]);
cpustate->sreg_idx = op & 0xf; cpustate->sreg_idx = op & 0xf;
@ -1226,8 +1272,10 @@ static CPU_EXECUTE( superfx )
break; break;
case 0xc0: // HIB case 0xc0: // HIB
superfx_gpr_write(cpustate, cpustate->dreg_idx, (UINT16)*(cpustate->sreg) >> 8); superfx_gpr_write(cpustate, cpustate->dreg_idx, (*(cpustate->sreg)) >> 8);
superfx_dreg_sfr_sz_update(cpustate); cpustate->sfr &= ~(SUPERFX_SFR_S | SUPERFX_SFR_Z);
cpustate->sfr |= (*(cpustate->dreg) & 0x80) ? SUPERFX_SFR_S : 0;
cpustate->sfr |= (*(cpustate->dreg) == 0) ? SUPERFX_SFR_Z : 0;
superfx_regs_reset(cpustate); superfx_regs_reset(cpustate);
break; break;
@ -1266,14 +1314,16 @@ static CPU_EXECUTE( superfx )
{ {
case SUPERFX_SFR_ALT0: // GETC case SUPERFX_SFR_ALT0: // GETC
case SUPERFX_SFR_ALT1: // GETC case SUPERFX_SFR_ALT1: // GETC
cpustate->colr = superfx_color(cpustate, superfx_bus_read(cpustate, (cpustate->rombr << 16) + cpustate->r[14])); cpustate->colr = superfx_color(cpustate, superfx_rombuffer_read(cpustate));
superfx_regs_reset(cpustate); superfx_regs_reset(cpustate);
break; break;
case SUPERFX_SFR_ALT2: // RAMB case SUPERFX_SFR_ALT2: // RAMB
superfx_rambuffer_sync(cpustate);
cpustate->rambr = *(cpustate->sreg); cpustate->rambr = *(cpustate->sreg);
superfx_regs_reset(cpustate); superfx_regs_reset(cpustate);
break; break;
case SUPERFX_SFR_ALT3: // ROMB case SUPERFX_SFR_ALT3: // ROMB
superfx_rombuffer_sync(cpustate);
cpustate->rombr = *(cpustate->sreg); cpustate->rombr = *(cpustate->sreg);
superfx_regs_reset(cpustate); superfx_regs_reset(cpustate);
break; break;
@ -1291,7 +1341,7 @@ static CPU_EXECUTE( superfx )
case 0xef: // GETB / GETBH / GETBL / GETBS case 0xef: // GETB / GETBH / GETBL / GETBS
{ {
UINT8 byte = superfx_bus_read(cpustate, (cpustate->rombr << 16) + cpustate->r[14]); UINT8 byte = superfx_rombuffer_read(cpustate);
switch(cpustate->sfr & SUPERFX_SFR_ALT) switch(cpustate->sfr & SUPERFX_SFR_ALT)
{ {
case SUPERFX_SFR_ALT0: // GETB case SUPERFX_SFR_ALT0: // GETB

View File

@ -1,6 +1,8 @@
#ifndef __SUPERFX_H__ #ifndef __SUPERFX_H__
#define __SUPERFX_H__ #define __SUPERFX_H__
#include "devcb.h"
enum enum
{ {
SUPERFX_PC = 1, SUPERFX_PC = 1,
@ -82,6 +84,13 @@ enum
#define SUPERFX_CFGR_IRQ 0x80 // IRQ #define SUPERFX_CFGR_IRQ 0x80 // IRQ
#define SUPERFX_CFGR_MS0 0x20 // MS0 #define SUPERFX_CFGR_MS0 0x20 // MS0
typedef struct _superfx_config superfx_config;
struct _superfx_config
{
devcb_write_line out_irq_func; /* IRQ changed callback */
};
#define SUPERFX_CONFIG(name) const superfx_config (name) =
CPU_GET_INFO( superfx ); CPU_GET_INFO( superfx );
#define CPU_SUPERFX CPU_GET_INFO_NAME( superfx ) #define CPU_SUPERFX CPU_GET_INFO_NAME( superfx )

View File

@ -1,6 +1,7 @@
#ifndef _SNES_H_ #ifndef _SNES_H_
#define _SNES_H_ #define _SNES_H_
#include "devcb.h"
#include "streams.h" #include "streams.h"
/* /*
@ -365,13 +366,12 @@ HAS_SDD1,
HAS_OBC1, HAS_OBC1,
HAS_RTC, HAS_RTC,
HAS_Z80GB, HAS_Z80GB,
HAS_C4, HAS_CX4,
HAS_ST010, HAS_ST010,
HAS_ST011, HAS_ST011,
HAS_ST018, HAS_ST018,
HAS_SPC7110, HAS_SPC7110,
HAS_SPC7110_RTC, HAS_SPC7110_RTC,
HAS_CX4,
HAS_UNK HAS_UNK
}; };
@ -400,6 +400,17 @@ extern WRITE8_HANDLER( snes_w_bank5 );
extern WRITE8_HANDLER( snes_w_bank6 ); extern WRITE8_HANDLER( snes_w_bank6 );
extern WRITE8_HANDLER( snes_w_bank7 ); extern WRITE8_HANDLER( snes_w_bank7 );
extern READ8_HANDLER( superfx_r_bank1 );
extern READ8_HANDLER( superfx_r_bank2 );
extern READ8_HANDLER( superfx_r_bank3 );
extern READ8_HANDLER( superfx_r_bank4 );
extern WRITE8_HANDLER( superfx_w_bank1 );
extern WRITE8_HANDLER( superfx_w_bank2 );
extern WRITE8_HANDLER( superfx_w_bank3 );
extern WRITE8_HANDLER( superfx_w_bank4 );
WRITE_LINE_DEVICE_HANDLER( snes_extern_irq_w );
extern UINT8 snes_has_addon_chip; extern UINT8 snes_has_addon_chip;
extern void snes_gdma( const address_space *space, UINT8 channels ); extern void snes_gdma( const address_space *space, UINT8 channels );

View File

@ -8,19 +8,16 @@
Anthony Kruize Anthony Kruize
Based on the original code by Lee Hammerton (aka Savoury Snax) Based on the original code by Lee Hammerton (aka Savoury Snax)
Thanks to Anomie for invaluable technical information. Thanks to Anomie for invaluable technical information.
Thanks to byuu for invaluable technical information.
***************************************************************************/ ***************************************************************************/
#define __MACHINE_SNES_C #define __MACHINE_SNES_C
#include "driver.h" #include "driver.h"
#include "includes/snes.h" #include "includes/snes.h"
#include "cpu/superfx/superfx.h"
#include "cpu/g65816/g65816.h" #include "cpu/g65816/g65816.h"
// add-on chip emulators
#include "machine/snesdsp1.c"
#include "machine/snesdsp2.c"
#include "machine/snesobc1.c"
/* -- Globals -- */ /* -- Globals -- */
UINT8 *snes_ram = NULL; /* 65816 ram */ UINT8 *snes_ram = NULL; /* 65816 ram */
UINT8 *spc_ram = NULL; /* spc700 ram */ UINT8 *spc_ram = NULL; /* spc700 ram */
@ -58,6 +55,12 @@ static struct
UINT8 oldrol; UINT8 oldrol;
} joypad[4]; } joypad[4];
// add-on chip emulators
#include "machine/snesdsp1.c"
#include "machine/snesdsp2.c"
#include "machine/snesobc1.c"
#include "machine/snesrtc.c"
#include "machine/snessdd1.c"
/************************************* /*************************************
@ -348,6 +351,28 @@ READ8_HANDLER( snes_r_io )
return spc_port_out[offset & 0x3]; return spc_port_out[offset & 0x3];
} }
if(snes_has_addon_chip == HAS_SUPERFX && cputag_get_cpu(space->machine, "superfx") != NULL)
{
if(offset >= 0x3000 && offset < 0x3300)
{
return superfx_mmio_read(cputag_get_cpu(space->machine, "superfx"), offset);
}
}
else if(snes_has_addon_chip == HAS_RTC)
{
if(offset == 0x2800 || offset == 0x2801)
{
return srtc_mmio_read(space->machine, offset);
}
}
else if(snes_has_addon_chip == HAS_SDD1)
{
if(offset >= 0x4800 && offset < 0x4808)
{
return sdd1_mmio_read(space->machine, offset);
}
}
/* offset is from 0x000000 */ /* offset is from 0x000000 */
switch( offset ) switch( offset )
{ {
@ -665,6 +690,8 @@ READ8_HANDLER( snes_r_io )
} }
//printf("unsupported read: offset == %08x\n", offset);
/* Unsupported reads returns open bus */ /* Unsupported reads returns open bus */
// printf("%02x %02x\n",offset,snes_open_bus_r(space,0)); // printf("%02x %02x\n",offset,snes_open_bus_r(space,0));
return snes_open_bus_r(space,0); return snes_open_bus_r(space,0);
@ -687,6 +714,32 @@ WRITE8_HANDLER( snes_w_io )
return; return;
} }
if(snes_has_addon_chip == HAS_SUPERFX && cputag_get_cpu(space->machine, "superfx") != NULL)
{
if(offset >= 0x3000 && offset < 0x3300)
{
superfx_mmio_write(cputag_get_cpu(space->machine, "superfx"), offset, data);
return;
}
}
else if(snes_has_addon_chip == HAS_RTC)
{
if(offset == 0x2800 || offset == 0x2801)
{
srtc_mmio_write(space->machine, offset, data);
return;
}
}
else if(snes_has_addon_chip == HAS_SDD1)
{
if((offset >= 0x4300 && offset < 0x4380) ||
(offset >= 0x4800 && offset < 0x4808))
{
sdd1_mmio_write(space->machine, offset, data);
return;
}
}
/* offset is from 0x000000 */ /* offset is from 0x000000 */
switch( offset ) switch( offset )
{ {
@ -729,7 +782,7 @@ WRITE8_HANDLER( snes_w_io )
break; break;
default: default:
/* Unknown size so default to 8 & 16 */ /* Unknown size so default to 8 & 16 */
printf( "Object size unsupported: %d\n", (data & 0xe0) >> 5 ); logerror( "Object size unsupported: %d\n", (data & 0xe0) >> 5 );
snes_ppu.oam.size[0] = 1; snes_ppu.oam.size[0] = 1;
snes_ppu.oam.size[1] = 2; snes_ppu.oam.size[1] = 2;
@ -1301,9 +1354,16 @@ WRITE8_HANDLER( snes_w_io )
break; break;
} }
logerror("Unsupported MMIO write: offset %08x = %02x\n", offset, data);
snes_ram[offset] = data; snes_ram[offset] = data;
} }
WRITE_LINE_DEVICE_HANDLER( snes_extern_irq_w )
{
cputag_set_input_line(device->machine, "maincpu", G65816_LINE_IRQ, state);
}
/************************************* /*************************************
Memory Handlers Memory Handlers
@ -1391,14 +1451,19 @@ READ8_HANDLER( snes_r_bank1 )
value = snes_r_io(space, address); value = snes_r_io(space, address);
else if (address < 0x8000) else if (address < 0x8000)
{ {
if (snes_has_addon_chip == HAS_OBC1) if (snes_has_addon_chip == HAS_SUPERFX && cputag_get_cpu(space->machine, "superfx") != NULL)
value = snes_ram[0x700000 + (address & 0x1fff)];
else if (snes_has_addon_chip == HAS_OBC1)
value = obc1_read(space, offset); value = obc1_read(space, offset);
else if ((snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000)) else if ((snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000))
value = (address < 0x7000) ? DSP2_read() : 0x00; value = (address < 0x7000) ? DSP2_read() : 0x00;
else if ((snes_cart.mode == SNES_MODE_21) && (snes_has_addon_chip == HAS_DSP1) && (offset < 0x100000)) else if ((snes_cart.mode == SNES_MODE_21) && (snes_has_addon_chip == HAS_DSP1) && (offset < 0x100000))
value = (address < 0x7000) ? DSP1_getDr() : DSP1_getSr(); value = (address < 0x7000) ? DSP1_getDr() : DSP1_getSr();
else else
{
logerror( "snes_r_bank1: Unmapped external chip read: %04x\n", address );
value = 0xff; /* Reserved */ value = 0xff; /* Reserved */
}
} }
else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000)) else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000))
value = (address < 0xc000) ? DSP1_getDr() : DSP1_getSr(); value = (address < 0xc000) ? DSP1_getDr() : DSP1_getSr();
@ -1433,7 +1498,10 @@ READ8_HANDLER( snes_r_bank2 )
value = snes_ram[0x306000 + (offset & mask)]; value = snes_ram[0x306000 + (offset & mask)];
} }
else else
{
logerror( "snes_r_bank2: Unmapped external chip read: %04x\n", address );
value = 0xff; value = 0xff;
}
} }
/* some dsp1 games use these banks 0x30 to 0x3f at address 0x8000 */ /* some dsp1 games use these banks 0x30 to 0x3f at address 0x8000 */
else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1)) else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1))
@ -1471,7 +1539,11 @@ READ8_HANDLER( snes_r_bank4 )
UINT8 value = 0xff; UINT8 value = 0xff;
UINT16 address = offset & 0xffff; UINT16 address = offset & 0xffff;
if (snes_cart.mode & 5) /* Mode 20 & 22 */ if (snes_has_addon_chip == HAS_SUPERFX && cputag_get_cpu(space->machine, "superfx") != NULL)
{
value = snes_ram[0x600000 + offset];
}
else if (snes_cart.mode & 5) /* Mode 20 & 22 */
{ {
if (address >= 0x8000) if (address >= 0x8000)
value = snes_ram[0x600000 + offset]; value = snes_ram[0x600000 + offset];
@ -1479,7 +1551,10 @@ READ8_HANDLER( snes_r_bank4 )
else if (snes_has_addon_chip == HAS_DSP1) else if (snes_has_addon_chip == HAS_DSP1)
value = (address >= 0x4000) ? DSP1_getSr() : DSP1_getDr(); value = (address >= 0x4000) ? DSP1_getSr() : DSP1_getDr();
else else
{
logerror( "snes_r_bank4: Unmapped external chip read: %04x\n", address );
value = 0xff; /* Reserved */ value = 0xff; /* Reserved */
}
} }
else if (snes_cart.mode & 0x0a) /* Mode 21 & 25 */ else if (snes_cart.mode & 0x0a) /* Mode 21 & 25 */
value = snes_ram[0x600000 + offset]; value = snes_ram[0x600000 + offset];
@ -1493,7 +1568,11 @@ READ8_HANDLER( snes_r_bank5 )
UINT8 value; UINT8 value;
UINT16 address = offset & 0xffff; UINT16 address = offset & 0xffff;
if ((snes_cart.mode & 5) &&(address < 0x8000)) /* Mode 20 & 22 */ if (snes_has_addon_chip == HAS_SUPERFX && cputag_get_cpu(space->machine, "superfx") != NULL)
{
value = snes_ram[0x700000 + offset];
}
else if ((snes_cart.mode & 5) &&(address < 0x8000)) /* Mode 20 & 22 */
{ {
if (snes_cart.sram > 0) if (snes_cart.sram > 0)
{ {
@ -1501,10 +1580,15 @@ READ8_HANDLER( snes_r_bank5 )
value = snes_ram[0x700000 + (offset & mask)]; value = snes_ram[0x700000 + (offset & mask)];
} }
else else
{
logerror( "snes_r_bank5: Unmapped external chip read: %04x\n", address );
value = 0xff; /* Reserved */ value = 0xff; /* Reserved */
}
} }
else else
{
value = snes_ram[0x700000 + offset]; value = snes_ram[0x700000 + offset];
}
return value; return value;
} }
@ -1512,12 +1596,14 @@ READ8_HANDLER( snes_r_bank5 )
/* 0x800000 - 0xbfffff */ /* 0x800000 - 0xbfffff */
READ8_HANDLER( snes_r_bank6 ) READ8_HANDLER( snes_r_bank6 )
{ {
UINT8 value; UINT8 value = 0;
UINT16 address = offset & 0xffff; UINT16 address = offset & 0xffff;
if (address < 0x8000) if (address < 0x8000)
{ {
if (snes_cart.mode != SNES_MODE_25) if(address >= 0x6000 && snes_has_addon_chip == HAS_SUPERFX && cputag_get_cpu(space->machine, "superfx") != NULL)
logerror( "snes_r_bank6 hit in Super FX mode, please fix me\n" );
else if (snes_cart.mode != SNES_MODE_25)
value = memory_read_byte(space, offset); value = memory_read_byte(space, offset);
else /* Mode 25 has SRAM not mirrored from lower banks */ else /* Mode 25 has SRAM not mirrored from lower banks */
{ {
@ -1530,7 +1616,10 @@ READ8_HANDLER( snes_r_bank6 )
value = snes_ram[0x806000 + (offset & mask)]; /* SRAM */ value = snes_ram[0x806000 + (offset & mask)]; /* SRAM */
} }
else /* Area 0x6000-0x8000 with offset < 0x300000 is reserved */ else /* Area 0x6000-0x8000 with offset < 0x300000 is reserved */
{
logerror( "snes_r_bank6: Unmapped external chip read: %04x\n", address );
value = 0xff; value = 0xff;
}
} }
} }
else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000)) else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000))
@ -1549,6 +1638,10 @@ READ8_HANDLER( snes_r_bank7 )
UINT8 value; UINT8 value;
UINT16 address = offset & 0xffff; UINT16 address = offset & 0xffff;
if(snes_has_addon_chip == HAS_SUPERFX && cputag_get_cpu(space->machine, "superfx") != NULL)
{
logerror( "snes_r_bank7 hit in Super FX mode, please fix me\n" );
}
if (snes_cart.mode & 5) /* Mode 20 & 22 */ if (snes_cart.mode & 5) /* Mode 20 & 22 */
{ {
if (address < 0x8000) if (address < 0x8000)
@ -1583,7 +1676,7 @@ WRITE8_HANDLER( snes_w_bank1 )
else if ((snes_cart.mode == SNES_MODE_21) && (snes_has_addon_chip == HAS_DSP1) && (offset < 0x100000)) else if ((snes_cart.mode == SNES_MODE_21) && (snes_has_addon_chip == HAS_DSP1) && (offset < 0x100000))
DSP1_setDr(data); DSP1_setDr(data);
else else
logerror( "Attempt to write to reserved address: %X\n", offset ); logerror( "snes_w_bank1: Attempt to write to reserved address: %x = %02x\n", offset, data );
} }
else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000)) else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000))
DSP1_setDr(data); DSP1_setDr(data);
@ -1611,11 +1704,12 @@ WRITE8_HANDLER( snes_w_bank2 )
else if ((snes_cart.mode == SNES_MODE_21) && (snes_cart.sram > 0)) else if ((snes_cart.mode == SNES_MODE_21) && (snes_cart.sram > 0))
{ {
int mask = ((snes_cart.sram * 1024) - 1); /* Limit SRAM size to what's actually present */ int mask = ((snes_cart.sram * 1024) - 1); /* Limit SRAM size to what's actually present */
logerror( "snes_w_bank2 hit in Super FX mode, please fix me if necessary\n" );
offset -= 0x6000; offset -= 0x6000;
snes_ram[0x306000 + (offset & mask)] = data; snes_ram[0x306000 + (offset & mask)] = data;
} }
else else
logerror("Attempt to write to reserved address: %X\n", offset + 0x300000); logerror("snes_w_bank2: Attempt to write to reserved address: %X = %02x\n", offset + 0x300000, data);
} }
/* some dsp1 games use these banks 0x30 to 0x3f at address 0x8000 */ /* some dsp1 games use these banks 0x30 to 0x3f at address 0x8000 */
else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1)) else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1))
@ -1631,17 +1725,29 @@ WRITE8_HANDLER( snes_w_bank4 )
{ {
UINT16 address = offset & 0xffff; UINT16 address = offset & 0xffff;
if (snes_cart.mode & 5) /* Mode 20 & 22 */ if (snes_has_addon_chip == HAS_SUPERFX && cputag_get_cpu(space->machine, "superfx") != NULL)
{
snes_ram[0x600000 + offset] = data;
}
else if (snes_cart.mode & 5) /* Mode 20 & 22 */
{ {
if (address >= 0x8000) if (address >= 0x8000)
{
logerror("Attempt to write to ROM address: %X\n", offset + 0x600000); logerror("Attempt to write to ROM address: %X\n", offset + 0x600000);
}
else if (snes_has_addon_chip == HAS_DSP1) else if (snes_has_addon_chip == HAS_DSP1)
{
DSP1_setDr(data); DSP1_setDr(data);
}
else else
logerror("Attempt to write to reserved address: %X\n", offset + 0x600000); {
logerror("snes_w_bank4: Attempt to write to reserved address: %X = %02x\n", offset + 0x600000, data);
}
} }
else if (snes_cart.mode & 0x0a) else if (snes_cart.mode & 0x0a)
{
logerror("Attempt to write to ROM address: %X\n", offset + 0x600000); logerror("Attempt to write to ROM address: %X\n", offset + 0x600000);
}
} }
/* 0x700000 - 0x7dffff */ /* 0x700000 - 0x7dffff */
@ -1649,7 +1755,11 @@ WRITE8_HANDLER( snes_w_bank5 )
{ {
UINT16 address = offset & 0xffff; UINT16 address = offset & 0xffff;
if ((snes_cart.mode & 5) && (address < 0x8000)) /* Mode 20 & 22 */ if (snes_has_addon_chip == HAS_SUPERFX && cputag_get_cpu(space->machine, "superfx") != NULL)
{
snes_ram[0x700000 + offset] = data;
}
else if ((snes_cart.mode & 5) && (address < 0x8000)) /* Mode 20 & 22 */
{ {
if (snes_cart.sram > 0) if (snes_cart.sram > 0)
{ {
@ -1657,10 +1767,14 @@ WRITE8_HANDLER( snes_w_bank5 )
snes_ram[0x700000 + (offset & mask)] = data; snes_ram[0x700000 + (offset & mask)] = data;
} }
else else
logerror("Attempt to write to reserved address: %X\n", offset + 0x600000); {
logerror("snes_w_bank5: Attempt to write to reserved address: %X = %02x\n", offset + 0x700000, data);
}
} }
else if (snes_cart.mode & 0x0a) else if (snes_cart.mode & 0x0a)
{
logerror("Attempt to write to ROM address: %X\n", offset + 0x700000); logerror("Attempt to write to ROM address: %X\n", offset + 0x700000);
}
} }
@ -1671,6 +1785,10 @@ WRITE8_HANDLER( snes_w_bank6 )
if (address < 0x8000) if (address < 0x8000)
{ {
if (address >= 0x6000 && snes_has_addon_chip == HAS_SUPERFX && cputag_get_cpu(space->machine, "superfx") != NULL)
{
logerror( "snes_w_bank6 hit (RAM) in Super FX mode, please fix me\n" );
}
if (snes_cart.mode != SNES_MODE_25) if (snes_cart.mode != SNES_MODE_25)
{ {
if (offset < 0x300000) if (offset < 0x300000)
@ -1694,13 +1812,15 @@ WRITE8_HANDLER( snes_w_bank6 )
snes_ram[0xb06000 + (offset & mask)] = data; snes_ram[0xb06000 + (offset & mask)] = data;
} }
else /* Area in 0x6000-0x8000 && offset < 0x300000 is Reserved! */ else /* Area in 0x6000-0x8000 && offset < 0x300000 is Reserved! */
logerror("Attempt to write to reserved address: %X\n", offset + 0x800000); logerror("snes_w_bank6: Attempt to write to reserved address: %X = %02x\n", offset + 0x800000, data);
} }
} }
else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000)) else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000))
DSP1_setDr(data); DSP1_setDr(data);
else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000) && (address < 0xc000)) else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000) && (address < 0xc000))
DSP2_write(data); DSP2_write(data);
else if (snes_has_addon_chip == HAS_SUPERFX && cputag_get_cpu(space->machine, "superfx") != NULL)
logerror( "snes_w_bank6 hit (ROM) in Super FX mode, please fix me\n" );
else else
logerror("Attempt to write to ROM address: %X\n", offset + 0x800000); logerror("Attempt to write to ROM address: %X\n", offset + 0x800000);
} }
@ -1711,7 +1831,18 @@ WRITE8_HANDLER( snes_w_bank7 )
{ {
UINT16 address = offset & 0xffff; UINT16 address = offset & 0xffff;
if (snes_cart.mode & 5) /* Mode 20 & 22 */ if (snes_has_addon_chip == HAS_SUPERFX && cputag_get_cpu(space->machine, "superfx") != NULL)
{
if (offset >= 0x200000)
{
logerror( "snes_w_bank7 hit (ROM) in Super FX mode, please fix me\n" );
}
else
{
logerror( "snes_w_bank7 hit (RAM) in Super FX mode, please fix me\n" );
}
}
else if (snes_cart.mode & 5) /* Mode 20 & 22 */
{ {
if (address < 0x8000) if (address < 0x8000)
{ {
@ -1723,7 +1854,7 @@ WRITE8_HANDLER( snes_w_bank7 )
snes_w_bank4(space, offset - 0x200000, data); snes_w_bank4(space, offset - 0x200000, data);
} }
else else
logerror("Attempt to write to ROM address: %X\n", offset + 0xc00000); logerror("snes_w_bank7: Attempt to write to ROM address: %X = %02x\n", offset + 0xc00000, data);
} }
else if (snes_cart.mode & 0x0a) else if (snes_cart.mode & 0x0a)
logerror("Attempt to write to ROM address: %X\n", offset + 0xc00000); logerror("Attempt to write to ROM address: %X\n", offset + 0xc00000);
@ -1872,6 +2003,8 @@ MACHINE_START( snes )
snes_ram[WRMPYA] = 0xff; snes_ram[WRMPYA] = 0xff;
snes_ram[WRDIVL] = 0xff; snes_ram[WRDIVL] = 0xff;
snes_ram[WRDIVH] = 0xff; snes_ram[WRDIVH] = 0xff;
sdd1_init(machine);
} }
MACHINE_RESET( snes ) MACHINE_RESET( snes )
@ -1894,6 +2027,9 @@ MACHINE_RESET( snes )
snes_htmult = 1; snes_htmult = 1;
snes_ppu.interlace = 1; snes_ppu.interlace = 1;
snes_ppu.obj_interlace = 1; snes_ppu.obj_interlace = 1;
srtc_reset(machine);
sdd1_reset(machine);
} }
@ -2314,3 +2450,33 @@ void snes_gdma( const address_space *space, UINT8 channels )
mask <<= 1; mask <<= 1;
} }
} }
READ8_HANDLER( superfx_r_bank1 )
{
return snes_ram[offset | 0x8000];
}
READ8_HANDLER( superfx_r_bank2 )
{
return snes_ram[0x400000 + offset];
}
READ8_HANDLER( superfx_r_bank3 )
{
return snes_ram[0x600000 + offset];
}
WRITE8_HANDLER( superfx_w_bank1 )
{
// Do nothing; can't write to cart ROM.
}
WRITE8_HANDLER( superfx_w_bank2 )
{
// Do nothing; can't write to cart ROM.
}
WRITE8_HANDLER( superfx_w_bank3 )
{
snes_ram[0x600000 + offset] = data;
}

203
src/mame/machine/snesrtc.c Normal file
View File

@ -0,0 +1,203 @@
enum
{
RTCM_Ready,
RTCM_Command,
RTCM_Read,
RTCM_Write
};
typedef struct
{
UINT8 rtc_ram[13];
INT32 rtc_mode;
INT8 rtc_index;
} _snes_rtc_t;
_snes_rtc_t snes_rtc;
const UINT8 srtc_months[12] =
{
31, 28, 31,
30, 31, 30,
31, 31, 30,
31, 30, 31
};
static void srtc_update_time(running_machine *machine)
{
mame_system_time curtime, *systime = &curtime;
mame_get_current_datetime(machine, &curtime);
snes_rtc.rtc_ram[0] = systime->local_time.second % 10;
snes_rtc.rtc_ram[1] = systime->local_time.second / 10;
snes_rtc.rtc_ram[2] = systime->local_time.minute % 10;
snes_rtc.rtc_ram[3] = systime->local_time.minute / 10;
snes_rtc.rtc_ram[4] = systime->local_time.hour % 10;
snes_rtc.rtc_ram[5] = systime->local_time.hour / 10;
snes_rtc.rtc_ram[6] = systime->local_time.mday % 10;
snes_rtc.rtc_ram[7] = systime->local_time.mday / 10;
snes_rtc.rtc_ram[8] = systime->local_time.month;
snes_rtc.rtc_ram[9] = (systime->local_time.year - 1900) % 10;
snes_rtc.rtc_ram[10] = ((systime->local_time.year - 1900) / 10) % 10;
snes_rtc.rtc_ram[11] = (systime->local_time.year - 1900) / 100;
snes_rtc.rtc_ram[12] = systime->local_time.weekday % 7;
}
// Returns day-of-week for specified date
// e.g. 0 = Sunday, 1 = Monday, ... 6 = Saturday
// Usage: weekday(2008, 1, 1) returns the weekday of January 1st, 2008
static UINT8 srtc_weekday(UINT32 year, UINT32 month, UINT32 day)
{
UINT32 y = 1900, m = 1; // Epoch is 1900-01-01
UINT32 sum = 0; // Number of days passed since epoch
year = MAX(1900, year);
month = MAX(1, MIN(12, month));
day = MAX(1, MIN(31, day));
while(y < year)
{
UINT8 leapyear = 0;
if((y % 4) == 0)
{
leapyear = 1;
if((y % 100) == 0 && (y % 400) != 0)
{
leapyear = 0;
}
}
sum += leapyear ? 366 : 365;
y++;
}
while(m < month)
{
UINT32 days = srtc_months[m - 1];
if(days == 28)
{
UINT8 leapyear = 0;
if((y % 4) == 0)
{
leapyear = 1;
if((y % 100) == 0 && (y % 400) != 0)
{
leapyear = 0;
}
}
days += leapyear ? 1 : 0;
}
sum += days;
m++;
}
sum += day - 1;
return (sum + 1) % 7; // 1900-01-01 was a Monday
}
static UINT8 srtc_mmio_read(running_machine *machine, UINT16 addr)
{
addr &= 0xffff;
if(addr == 0x2800)
{
if(snes_rtc.rtc_mode != RTCM_Read)
{
return 0x00;
}
if(snes_rtc.rtc_index < 0)
{
srtc_update_time(machine);
snes_rtc.rtc_index++;
return 0x0f;
}
else if(snes_rtc.rtc_index > 12)
{
snes_rtc.rtc_index = -1;
return 0x0f;
}
else
{
return snes_rtc.rtc_ram[snes_rtc.rtc_index++];
}
}
return 0xff;
}
static void srtc_mmio_write(running_machine *machine, UINT16 addr, UINT8 data)
{
addr &= 0xffff;
if(addr == 0x2801)
{
data &= 0x0f; // Only the low four bits are used
if(data == 0x0d)
{
snes_rtc.rtc_mode = RTCM_Read;
snes_rtc.rtc_index = -1;
return;
}
if(data == 0x0e)
{
snes_rtc.rtc_mode = RTCM_Command;
return;
}
if(data == 0x0f)
{
return; // Unknown behaviour
}
if(snes_rtc.rtc_mode == RTCM_Write)
{
if(snes_rtc.rtc_index >= 0 && snes_rtc.rtc_index < 12)
{
snes_rtc.rtc_ram[snes_rtc.rtc_index++] = data;
if(snes_rtc.rtc_index == 12)
{
// Day of week is automatically calculated and written
UINT8 day = snes_rtc.rtc_ram[6] + snes_rtc.rtc_ram[7] * 10;
UINT8 month = snes_rtc.rtc_ram[8];
UINT8 year = snes_rtc.rtc_ram[9] + snes_rtc.rtc_ram[10] * 10 + snes_rtc.rtc_ram[11] * 100;
year += 1000;
snes_rtc.rtc_ram[snes_rtc.rtc_index++] = srtc_weekday(year, month, day);
}
}
}
else if(snes_rtc.rtc_mode == RTCM_Command)
{
if(data == 0)
{
snes_rtc.rtc_mode = RTCM_Write;
snes_rtc.rtc_index = 0;
}
else if(data == 4)
{
UINT8 i;
snes_rtc.rtc_mode = RTCM_Ready;
snes_rtc.rtc_index = -1;
for(i = 0; i < 13; i++)
{
snes_rtc.rtc_ram[i] = 0;
}
}
else
{
// Unknown behaviour
snes_rtc.rtc_mode = RTCM_Ready;
}
}
}
}
static void srtc_reset(running_machine *machine)
{
snes_rtc.rtc_mode = RTCM_Read;
snes_rtc.rtc_index = -1;
srtc_update_time(machine);
}

667
src/mame/machine/snessdd1.c Normal file
View File

@ -0,0 +1,667 @@
static UINT8 sdd1_read(running_machine* machine, UINT16 addr);
typedef struct //Input Manager
{
running_machine* machine;
UINT32 byte_ptr;
UINT8 bit_count;
} SDD1_IM;
static SDD1_IM* SDD1_IM_ctor(running_machine* machine)
{
SDD1_IM* newclass = (SDD1_IM*)auto_alloc_array(machine, UINT8, sizeof(SDD1_IM));
newclass->machine = machine;
return newclass;
}
static void SDD1_IM_prepareDecomp(SDD1_IM* this, UINT32 in_buf)
{
this->byte_ptr = in_buf;
this->bit_count = 4;
}
static UINT8 SDD1_IM_getCodeword(SDD1_IM* this, const UINT8 code_len)
{
UINT8 codeword;
codeword = sdd1_read(this->machine, this->byte_ptr) << this->bit_count;
++this->bit_count;
if (codeword & 0x80)
{
codeword |= sdd1_read(this->machine, this->byte_ptr + 1) >> (9 - this->bit_count);
this->bit_count += code_len;
}
if (this->bit_count & 0x08)
{
this->byte_ptr++;
this->bit_count &= 0x07;
}
return codeword;
}
typedef struct //Golomb-Code Decoder
{
running_machine* machine;
SDD1_IM* IM;
} SDD1_GCD;
static SDD1_GCD* SDD1_GCD_ctor(running_machine* machine, SDD1_IM* associatedIM)
{
SDD1_GCD* newclass = (SDD1_GCD*)auto_alloc_array(machine, UINT8, sizeof(SDD1_GCD));
newclass->machine = machine;
newclass->IM = associatedIM;
return newclass;
}
static void SDD1_GCD_getRunCount(SDD1_GCD* this, UINT8 code_num, UINT8* MPScount, UINT8* LPSind)
{
const UINT8 run_count[] =
{
0x00, 0x00, 0x01, 0x00, 0x03, 0x01, 0x02, 0x00,
0x07, 0x03, 0x05, 0x01, 0x06, 0x02, 0x04, 0x00,
0x0f, 0x07, 0x0b, 0x03, 0x0d, 0x05, 0x09, 0x01,
0x0e, 0x06, 0x0a, 0x02, 0x0c, 0x04, 0x08, 0x00,
0x1f, 0x0f, 0x17, 0x07, 0x1b, 0x0b, 0x13, 0x03,
0x1d, 0x0d, 0x15, 0x05, 0x19, 0x09, 0x11, 0x01,
0x1e, 0x0e, 0x16, 0x06, 0x1a, 0x0a, 0x12, 0x02,
0x1c, 0x0c, 0x14, 0x04, 0x18, 0x08, 0x10, 0x00,
0x3f, 0x1f, 0x2f, 0x0f, 0x37, 0x17, 0x27, 0x07,
0x3b, 0x1b, 0x2b, 0x0b, 0x33, 0x13, 0x23, 0x03,
0x3d, 0x1d, 0x2d, 0x0d, 0x35, 0x15, 0x25, 0x05,
0x39, 0x19, 0x29, 0x09, 0x31, 0x11, 0x21, 0x01,
0x3e, 0x1e, 0x2e, 0x0e, 0x36, 0x16, 0x26, 0x06,
0x3a, 0x1a, 0x2a, 0x0a, 0x32, 0x12, 0x22, 0x02,
0x3c, 0x1c, 0x2c, 0x0c, 0x34, 0x14, 0x24, 0x04,
0x38, 0x18, 0x28, 0x08, 0x30, 0x10, 0x20, 0x00,
0x7f, 0x3f, 0x5f, 0x1f, 0x6f, 0x2f, 0x4f, 0x0f,
0x77, 0x37, 0x57, 0x17, 0x67, 0x27, 0x47, 0x07,
0x7b, 0x3b, 0x5b, 0x1b, 0x6b, 0x2b, 0x4b, 0x0b,
0x73, 0x33, 0x53, 0x13, 0x63, 0x23, 0x43, 0x03,
0x7d, 0x3d, 0x5d, 0x1d, 0x6d, 0x2d, 0x4d, 0x0d,
0x75, 0x35, 0x55, 0x15, 0x65, 0x25, 0x45, 0x05,
0x79, 0x39, 0x59, 0x19, 0x69, 0x29, 0x49, 0x09,
0x71, 0x31, 0x51, 0x11, 0x61, 0x21, 0x41, 0x01,
0x7e, 0x3e, 0x5e, 0x1e, 0x6e, 0x2e, 0x4e, 0x0e,
0x76, 0x36, 0x56, 0x16, 0x66, 0x26, 0x46, 0x06,
0x7a, 0x3a, 0x5a, 0x1a, 0x6a, 0x2a, 0x4a, 0x0a,
0x72, 0x32, 0x52, 0x12, 0x62, 0x22, 0x42, 0x02,
0x7c, 0x3c, 0x5c, 0x1c, 0x6c, 0x2c, 0x4c, 0x0c,
0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04,
0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
0x70, 0x30, 0x50, 0x10, 0x60, 0x20, 0x40, 0x00,
};
UINT8 codeword = SDD1_IM_getCodeword(this->IM, code_num);
if (codeword & 0x80)
{
*LPSind = 1;
*MPScount = run_count[codeword >> (code_num ^ 0x07)];
}
else
{
*MPScount = (1 << code_num);
}
}
typedef struct // Bits Generator
{
running_machine* machine;
UINT8 code_num;
UINT8 MPScount;
UINT8 LPSind;
SDD1_GCD* GCD;
} SDD1_BG;
static SDD1_BG* SDD1_BG_ctor(running_machine* machine, SDD1_GCD* associatedGCD, UINT8 code)
{
SDD1_BG* newclass = (SDD1_BG*)auto_alloc_array(machine, UINT8, sizeof(SDD1_BG));
newclass->machine = machine;
newclass->code_num = code;
newclass->GCD = associatedGCD;
return newclass;
}
static void SDD1_BG_prepareDecomp(SDD1_BG* this)
{
this->MPScount = 0;
this->LPSind = 0;
}
static UINT8 SDD1_BG_getBit(SDD1_BG* this, UINT8* endOfRun)
{
UINT8 bit;
if (!(this->MPScount || this->LPSind))
{
SDD1_GCD_getRunCount(this->GCD, this->code_num, &(this->MPScount), &(this->LPSind));
}
if (this->MPScount)
{
bit = 0;
this->MPScount--;
}
else
{
bit = 1;
this->LPSind = 0;
}
if (this->MPScount || this->LPSind)
{
(*endOfRun) = 0;
}
else
{
(*endOfRun) = 1;
}
return bit;
}
typedef struct
{
UINT8 code_num;
UINT8 nextIfMPS;
UINT8 nextIfLPS;
} SDD1_PEM_state;
SDD1_PEM_state SDD1_PEM_evolution_table[33] =
{
{ 0,25,25},
{ 0, 2, 1},
{ 0, 3, 1},
{ 0, 4, 2},
{ 0, 5, 3},
{ 1, 6, 4},
{ 1, 7, 5},
{ 1, 8, 6},
{ 1, 9, 7},
{ 2,10, 8},
{ 2,11, 9},
{ 2,12,10},
{ 2,13,11},
{ 3,14,12},
{ 3,15,13},
{ 3,16,14},
{ 3,17,15},
{ 4,18,16},
{ 4,19,17},
{ 5,20,18},
{ 5,21,19},
{ 6,22,20},
{ 6,23,21},
{ 7,24,22},
{ 7,24,23},
{ 0,26, 1},
{ 1,27, 2},
{ 2,28, 4},
{ 3,29, 8},
{ 4,30,12},
{ 5,31,16},
{ 6,32,18},
{ 7,24,22}
};
typedef struct
{
UINT8 status;
UINT8 MPS;
} SDD1_PEM_ContextInfo;
typedef struct //Probability Estimation Module
{
running_machine* machine;
SDD1_PEM_ContextInfo contextInfo[32];
SDD1_BG* BG[8];
} SDD1_PEM;
static SDD1_PEM* SDD1_PEM_ctor(running_machine* machine,
SDD1_BG* associatedBG0, SDD1_BG* associatedBG1,
SDD1_BG* associatedBG2, SDD1_BG* associatedBG3,
SDD1_BG* associatedBG4, SDD1_BG* associatedBG5,
SDD1_BG* associatedBG6, SDD1_BG* associatedBG7)
{
SDD1_PEM* newclass = (SDD1_PEM*)auto_alloc_array(machine, UINT8, sizeof(SDD1_PEM));
newclass->machine = machine;
newclass->BG[0] = associatedBG0;
newclass->BG[1] = associatedBG1;
newclass->BG[2] = associatedBG2;
newclass->BG[3] = associatedBG3;
newclass->BG[4] = associatedBG4;
newclass->BG[5] = associatedBG5;
newclass->BG[6] = associatedBG6;
newclass->BG[7] = associatedBG7;
return newclass;
}
static void SDD1_PEM_prepareDecomp(SDD1_PEM* this)
{
UINT8 i;
for(i = 0; i < 32; i++)
{
this->contextInfo[i].status = 0;
this->contextInfo[i].MPS = 0;
}
}
static UINT8 SDD1_PEM_getBit(SDD1_PEM* this, UINT8 context)
{
UINT8 endOfRun;
UINT8 bit;
SDD1_PEM_ContextInfo *pContInfo = &(this->contextInfo)[context];
UINT8 currStatus = pContInfo->status;
SDD1_PEM_state* pState = &(SDD1_PEM_evolution_table[currStatus]);
UINT8 currentMPS = pContInfo->MPS;
bit = SDD1_BG_getBit(this->BG[pState->code_num], &endOfRun);
if (endOfRun)
{
if (bit)
{
if (!(currStatus & 0xfe))
{
(pContInfo->MPS) ^= 0x01;
}
pContInfo->status = pState->nextIfLPS;
}
else
{
pContInfo->status = pState->nextIfMPS;
}
}
return bit ^ currentMPS;
}
typedef struct
{
running_machine* machine;
UINT8 bitplanesInfo;
UINT8 contextBitsInfo;
UINT8 bit_number;
UINT8 currBitplane;
UINT16 prevBitplaneBits[8];
SDD1_PEM* PEM;
} SDD1_CM;
static SDD1_CM* SDD1_CM_ctor(running_machine* machine, SDD1_PEM* associatedPEM)
{
SDD1_CM* newclass = (SDD1_CM*)auto_alloc_array(machine, UINT8, sizeof(SDD1_CM));
newclass->machine = machine;
newclass->PEM = associatedPEM;
return newclass;
}
static void SDD1_CM_prepareDecomp(SDD1_CM* this, UINT32 first_byte)
{
INT32 i = 0;
this->bitplanesInfo = sdd1_read(this->machine, first_byte) & 0xc0;
this->contextBitsInfo = sdd1_read(this->machine, first_byte) & 0x30;
this->bit_number = 0;
for (i = 0; i < 8; i++)
{
this->prevBitplaneBits[i] = 0;
}
switch(this->bitplanesInfo)
{
case 0x00:
this->currBitplane = 1;
break;
case 0x40:
this->currBitplane = 7;
break;
case 0x80:
this->currBitplane = 3;
break;
}
}
static UINT8 SDD1_CM_getBit(SDD1_CM* this)
{
UINT8 currContext;
UINT16 *context_bits;
UINT8 bit = 0;
switch (this->bitplanesInfo)
{
case 0x00:
this->currBitplane ^= 0x01;
break;
case 0x40:
this->currBitplane ^= 0x01;
if (!(this->bit_number & 0x7f))
{
this->currBitplane = ((this->currBitplane + 2) & 0x07);
}
break;
case 0x80:
this->currBitplane ^= 0x01;
if (!(this->bit_number & 0x7f))
{
this->currBitplane ^= 0x02;
}
break;
case 0xc0:
this->currBitplane = this->bit_number & 0x07;
break;
}
context_bits = &(this->prevBitplaneBits)[this->currBitplane];
currContext = (this->currBitplane & 0x01) << 4;
switch (this->contextBitsInfo)
{
case 0x00:
currContext |= ((*context_bits & 0x01c0) >> 5) | (*context_bits & 0x0001);
break;
case 0x10:
currContext |= ((*context_bits & 0x0180) >> 5) | (*context_bits & 0x0001);
break;
case 0x20:
currContext |= ((*context_bits & 0x00c0) >> 5) | (*context_bits & 0x0001);
break;
case 0x30:
currContext |= ((*context_bits & 0x0180) >> 5) | (*context_bits & 0x0003);
break;
}
bit = SDD1_PEM_getBit(this->PEM, currContext);
*context_bits <<= 1;
*context_bits |= bit;
this->bit_number++;
return bit;
}
typedef struct
{
running_machine* machine;
UINT8 bitplanesInfo;
UINT16 length;
UINT8* buffer;
SDD1_CM* CM;
} SDD1_OL;
static SDD1_OL* SDD1_OL_ctor(running_machine* machine, SDD1_CM* associatedCM)
{
SDD1_OL* newclass = (SDD1_OL*)auto_alloc_array(machine, UINT8, sizeof(SDD1_OL));
newclass->machine = machine;
newclass->CM = associatedCM;
return newclass;
}
static void SDD1_OL_prepareDecomp(SDD1_OL* this, UINT32 first_byte, UINT16 out_len, UINT8 *out_buf)
{
this->bitplanesInfo = sdd1_read(this->machine, first_byte) & 0xc0;
this->length = out_len;
this->buffer = out_buf;
}
static void SDD1_OL_launch(SDD1_OL* this)
{
UINT8 i;
UINT8 register1, register2;
switch(this->bitplanesInfo)
{
case 0x00:
case 0x40:
case 0x80:
i = 1;
do
{ // if length == 0, we output 2^16 bytes
if(!i)
{
*(this->buffer++) = register2;
i = ~i;
}
else
{
for(register1 = register2 = 0, i = 0x80; i; i >>= 1)
{
if(SDD1_CM_getBit(this->CM))
{
register1 |= i;
}
if(SDD1_CM_getBit(this->CM))
{
register2 |= i;
}
}
*(this->buffer++) = register1;
}
} while(--(this->length));
break;
case 0xc0:
do
{
for(register1 = 0, i = 0x01; i; i <<= 1)
{
if(SDD1_CM_getBit(this->CM))
{
register1 |= i;
}
}
*(this->buffer++) = register1;
} while(--(this->length));
break;
}
}
typedef struct
{
running_machine* machine;
SDD1_IM* IM;
SDD1_GCD* GCD;
SDD1_BG* BG0; SDD1_BG* BG1; SDD1_BG* BG2; SDD1_BG* BG3;
SDD1_BG* BG4; SDD1_BG* BG5; SDD1_BG* BG6; SDD1_BG* BG7;
SDD1_PEM* PEM;
SDD1_CM* CM;
SDD1_OL* OL;
} SDD1emu;
static SDD1emu* SDD1emu_ctor(running_machine *machine)
{
SDD1emu* newclass = (SDD1emu*)auto_alloc_array(machine, UINT8, sizeof(SDD1emu));
newclass->machine = machine;
newclass->IM = SDD1_IM_ctor(machine);
newclass->GCD = SDD1_GCD_ctor(machine, newclass->IM);
newclass->BG0 = SDD1_BG_ctor(machine, newclass->GCD, 0);
newclass->BG1 = SDD1_BG_ctor(machine, newclass->GCD, 1);
newclass->BG2 = SDD1_BG_ctor(machine, newclass->GCD, 2);
newclass->BG3 = SDD1_BG_ctor(machine, newclass->GCD, 3);
newclass->BG4 = SDD1_BG_ctor(machine, newclass->GCD, 4);
newclass->BG5 = SDD1_BG_ctor(machine, newclass->GCD, 5);
newclass->BG6 = SDD1_BG_ctor(machine, newclass->GCD, 6);
newclass->BG7 = SDD1_BG_ctor(machine, newclass->GCD, 7);
newclass->PEM = SDD1_PEM_ctor(machine, newclass->BG0, newclass->BG1, newclass->BG2, newclass->BG3,
newclass->BG4, newclass->BG5, newclass->BG6, newclass->BG7);
newclass->CM = SDD1_CM_ctor(machine, newclass->PEM);
newclass->OL = SDD1_OL_ctor(machine, newclass->CM);
return newclass;
}
static void SDD1emu_decompress(SDD1emu* this, UINT32 in_buf, UINT16 out_len, UINT8 *out_buf)
{
SDD1_IM_prepareDecomp(this->IM, in_buf);
SDD1_BG_prepareDecomp(this->BG0);
SDD1_BG_prepareDecomp(this->BG1);
SDD1_BG_prepareDecomp(this->BG2);
SDD1_BG_prepareDecomp(this->BG3);
SDD1_BG_prepareDecomp(this->BG4);
SDD1_BG_prepareDecomp(this->BG5);
SDD1_BG_prepareDecomp(this->BG6);
SDD1_BG_prepareDecomp(this->BG7);
SDD1_PEM_prepareDecomp(this->PEM);
SDD1_CM_prepareDecomp(this->CM, in_buf);
SDD1_OL_prepareDecomp(this->OL, in_buf, out_len, out_buf);
SDD1_OL_launch(this->OL);
}
typedef struct
{
UINT8 sdd1_enable; // channel bit-mask
UINT8 xfer_enable; // channel bit-mask
UINT32 mmc[4]; // memory map controller ROM indices
struct
{
UINT32 addr; // $43x2-$43x4 -- DMA transfer address
UINT16 size; // $43x5-$43x6 -- DMA transfer size
} dma[8];
SDD1emu* sdd1emu;
struct
{
UINT8 *data; // pointer to decompressed S-DD1 data (65536 bytes)
UINT16 offset; // read index into S-DD1 decompression buffer
UINT32 size; // length of data buffer; reads decrement counter, set ready to false at 0
UINT8 ready; // 1 when data[] is valid; 0 to invoke sdd1emu.decompress()
} buffer;
} _snes_sdd1_t;
_snes_sdd1_t snes_sdd1;
static void sdd1_init(running_machine* machine)
{
snes_sdd1.sdd1emu = SDD1emu_ctor(machine);
}
static UINT8 sdd1_mmio_read(running_machine* machine, UINT16 addr)
{
addr &= 0xffff;
switch(addr)
{
case 0x4804:
return (snes_sdd1.mmc[0] >> 20) & 7;
case 0x4805:
return (snes_sdd1.mmc[1] >> 20) & 7;
case 0x4806:
return (snes_sdd1.mmc[2] >> 20) & 7;
case 0x4807:
return (snes_sdd1.mmc[3] >> 20) & 7;
}
return 0xff;
}
static void sdd1_mmio_write(running_machine* machine, UINT16 addr, UINT8 data)
{
addr &= 0xffff;
if((addr & 0x4380) == 0x4300)
{
UINT8 channel = (addr >> 4) & 7;
switch(addr & 15)
{
case 2:
snes_sdd1.dma[channel].addr = (snes_sdd1.dma[channel].addr & 0xffff00) + (data << 0);
break;
case 3:
snes_sdd1.dma[channel].addr = (snes_sdd1.dma[channel].addr & 0xff00ff) + (data << 8);
break;
case 4:
snes_sdd1.dma[channel].addr = (snes_sdd1.dma[channel].addr & 0x00ffff) + (data << 16);
break;
case 5:
snes_sdd1.dma[channel].addr = (snes_sdd1.dma[channel].addr & 0xff00) + (data << 0);
break;
case 6:
snes_sdd1.dma[channel].addr = (snes_sdd1.dma[channel].addr & 0x00ff) + (data << 8);
break;
}
snes_ram[addr] = data;
return;
}
switch(addr)
{
case 0x4800:
snes_sdd1.sdd1_enable = data;
break;
case 0x4801:
snes_sdd1.xfer_enable = data;
break;
case 0x4804:
snes_sdd1.mmc[0] = (data & 7) << 20;
break;
case 0x4805:
snes_sdd1.mmc[1] = (data & 7) << 20;
break;
case 0x4806:
snes_sdd1.mmc[2] = (data & 7) << 20;
break;
case 0x4807:
snes_sdd1.mmc[3] = (data & 7) << 20;
break;
}
}
static UINT8 sdd1_read(running_machine* machine, UINT16 addr)
{
if(snes_sdd1.sdd1_enable & snes_sdd1.xfer_enable)
{
// at least one channel has S-DD1 decompression enabled...
UINT32 i;
for(i = 0; i < 8; i++)
{
if(snes_sdd1.sdd1_enable & snes_sdd1.xfer_enable & (1 << i))
{
// S-DD1 always uses fixed transfer mode, so address will not change during transfer
if(addr == snes_sdd1.dma[i].addr)
{
UINT8 data;
if(!snes_sdd1.buffer.ready)
{
UINT8 temp;
// first byte read for channel performs full decompression.
// this really should stream byte-by-byte, but it's not necessary since the size is known
snes_sdd1.buffer.offset = 0;
snes_sdd1.buffer.size = snes_sdd1.dma[i].size ? snes_sdd1.dma[i].size : 65536;
// sdd1emu calls this function; it needs to access uncompressed data;
// so temporarily disable decompression mode for decompress() call.
temp = snes_sdd1.sdd1_enable;
snes_sdd1.sdd1_enable = 0;
SDD1emu_decompress(snes_sdd1.sdd1emu, addr, snes_sdd1.buffer.size, snes_sdd1.buffer.data);
snes_sdd1.sdd1_enable = temp;
snes_sdd1.buffer.ready = 1;
}
// fetch a decompressed byte; once buffer is depleted, disable channel and invalidate buffer
data = snes_sdd1.buffer.data[(UINT16)snes_sdd1.buffer.offset++];
if(snes_sdd1.buffer.offset >= snes_sdd1.buffer.size)
{
snes_sdd1.buffer.ready = 0;
snes_sdd1.xfer_enable &= ~(1 << i);
}
return data;
} // address matched
} // channel enabled
} // channel loop
} // S-DD1 decompressor enabled
return memory_read_byte(cputag_get_address_space(machine, "maincpu", ADDRESS_SPACE_PROGRAM), snes_sdd1.mmc[(addr >> 20) & 3] + (addr & 0x0fffff));
}
static void sdd1_reset(running_machine *machine)
{
}

View File

@ -1846,5 +1846,7 @@ $(DRIVERS)/galaxian.o: $(MAMESRC)/drivers/galdrvr.c
$(DRIVERS)/mpu4.o: $(MAMESRC)/drivers/mpu4drvr.c $(DRIVERS)/mpu4.o: $(MAMESRC)/drivers/mpu4drvr.c
$(DRIVERS)/neogeo.o: $(MAMESRC)/drivers/neodrvr.c $(DRIVERS)/neogeo.o: $(MAMESRC)/drivers/neodrvr.c
$(MACHINE)/snes.o: $(MAMESRC)/machine/snesdsp1.c \ $(MACHINE)/snes.o: $(MAMESRC)/machine/snesdsp1.c \
$(MAMESRC)/machine/snesdsp2.c \ $(MAMESRC)/machine/snesdsp2.c \
$(MAMESRC)/machine/snesobc1.c $(MAMESRC)/machine/snesobc1.c \
$(MAMESRC)/machine/snesrtc.c \
$(MAMESRC)/machine/snessdd1.c