mirror of
https://github.com/holub/mame
synced 2025-05-22 13:48:55 +03:00
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:
parent
85d9b4decb
commit
b54790792a
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -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/snesdsp2.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/starwars.c svneol=native#text/plain
|
||||
src/mame/machine/steppers.c svneol=native#text/plain
|
||||
|
@ -128,6 +128,7 @@ INLINE void PUSH(avr8_state *cpustate, UINT8 val)
|
||||
UINT16 sp = SPREG;
|
||||
WRITE_IO_8(cpustate, sp, val);
|
||||
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_SPL, sp & 0x00ff);
|
||||
}
|
||||
@ -138,9 +139,23 @@ INLINE UINT8 POP(avr8_state *cpustate)
|
||||
sp++;
|
||||
WRITE_IO_8(cpustate, AVR8_IO_SPH, (sp >> 8) & 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);
|
||||
}
|
||||
|
||||
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 )
|
||||
@ -176,6 +191,8 @@ static CPU_EXECUTE( avr8 )
|
||||
UINT8 rr = 0;
|
||||
UINT8 res = 0;
|
||||
UINT16 pd = 0;
|
||||
INT16 sd = 0;
|
||||
INT32 opcycles = 1;
|
||||
//UINT16 pr = 0;
|
||||
avr8_state *cpustate = get_safe_token(device);
|
||||
|
||||
@ -195,20 +212,22 @@ static CPU_EXECUTE( avr8 )
|
||||
switch(op & 0x0f00)
|
||||
{
|
||||
case 0x0000: // NOP
|
||||
//output += sprintf( output, "NOP" );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
break;
|
||||
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) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
WRITE_IO_8(cpustate, (RD4(op) << 1)+1, READ_IO_8(cpustate, (RR4(op) << 1)+1));
|
||||
WRITE_IO_8(cpustate, RD4(op) << 1, READ_IO_8(cpustate, RR4(op) << 1));
|
||||
break;
|
||||
case 0x0200: // MULS Rd,Rr
|
||||
//output += sprintf( output, "MULS R%d, R%d", 16+RD4(op), 16+RR4(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
break;
|
||||
case 0x0300: // MULSU Rd,Rr
|
||||
//output += sprintf( output, "MULSU R%d, R%d", 16+RD4(op), 16+RR4(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
sd = (INT8)READ_IO_8(cpustate, 16+RD4(op)) * (UINT8)READ_IO_8(cpustate, 16+RR4(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;
|
||||
case 0x0400:
|
||||
case 0x0500:
|
||||
@ -228,8 +247,16 @@ static CPU_EXECUTE( avr8 )
|
||||
case 0x0900:
|
||||
case 0x0a00:
|
||||
case 0x0b00: // SBC Rd,Rr
|
||||
//output += sprintf( output, "SBC R%d, R%d", RD5(op), RR5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
rd = READ_IO_8(cpustate, RD5(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;
|
||||
case 0x0c00:
|
||||
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))));
|
||||
break;
|
||||
case 0x0800: // SUB Rd,Rr
|
||||
//output += sprintf( output, "SUB R%d, R%d", RD5(op), RR5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
rd = READ_IO_8(cpustate, RD5(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;
|
||||
case 0x0c00: // ADC Rd,Rr
|
||||
rd = READ_IO_8(cpustate, RD5(op));
|
||||
@ -361,16 +396,16 @@ static CPU_EXECUTE( avr8 )
|
||||
unimplemented_opcode(cpustate, op);
|
||||
break;
|
||||
case 0x0008: // LDD Rd,Y+q
|
||||
//output += sprintf( output, "LD(D) R%d, Y+%02x", RD5(op), QCONST6(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
WRITE_IO_8(cpustate, RD5(op), YREG + QCONST6(op));
|
||||
opcycles = 2;
|
||||
break;
|
||||
case 0x0200: // STD Z+q,Rr
|
||||
//output += sprintf( output, "ST(D) Z+%02x, R%d", QCONST6(op), RD5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
break;
|
||||
case 0x0208: // STD Z+q,Rr
|
||||
//output += sprintf( output, "ST(D) Y+%02x, R%d", QCONST6(op), RD5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
case 0x0208: // STD Y+q,Rr
|
||||
WRITE_IO_8(cpustate, YREG + QCONST6(op), READ_IO_8(cpustate, RD5(op)));
|
||||
opcycles = 2;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -386,6 +421,7 @@ static CPU_EXECUTE( avr8 )
|
||||
cpustate->pc++;
|
||||
op |= READ_PRG_16(cpustate, cpustate->pc);
|
||||
WRITE_IO_8(cpustate, RD5(op >> 16), READ_IO_8(cpustate, op & 0x0000ffff));
|
||||
opcycles = 2;
|
||||
break;
|
||||
case 0x0001: // LD Rd,Z+
|
||||
unimplemented_opcode(cpustate, op);
|
||||
@ -396,6 +432,7 @@ static CPU_EXECUTE( avr8 )
|
||||
break;
|
||||
case 0x0004: // LPM Rd,Z
|
||||
WRITE_IO_8(cpustate, RD5(op), READ_PRG_8(cpustate, ZREG));
|
||||
opcycles = 3;
|
||||
break;
|
||||
case 0x0005: // LPM Rd,Z+
|
||||
pd = ZREG;
|
||||
@ -403,6 +440,7 @@ static CPU_EXECUTE( avr8 )
|
||||
pd++;
|
||||
WRITE_IO_8(cpustate, 31, (pd >> 8) & 0x00ff);
|
||||
WRITE_IO_8(cpustate, 30, pd & 0x00ff);
|
||||
opcycles = 3;
|
||||
break;
|
||||
case 0x0006: // ELPM Rd,Z
|
||||
//output += sprintf( output, "ELPM R%d, Z", RD5(op) );
|
||||
@ -425,16 +463,20 @@ static CPU_EXECUTE( avr8 )
|
||||
unimplemented_opcode(cpustate, op);
|
||||
break;
|
||||
case 0x000d: // LD Rd,X+
|
||||
//output += sprintf( output, "LD R%d, X+", RD5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
pd = XREG;
|
||||
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;
|
||||
case 0x000e: // LD Rd,-X
|
||||
//output += sprintf( output, "LD R%d,-X", RD5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
break;
|
||||
case 0x000f: // POP Rd
|
||||
//output += sprintf( output, "POP R%d", RD5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
WRITE_IO_8(cpustate, RD5(op), POP(cpustate));
|
||||
opcycles = 2;
|
||||
break;
|
||||
default:
|
||||
unimplemented_opcode(cpustate, op);
|
||||
@ -451,6 +493,7 @@ static CPU_EXECUTE( avr8 )
|
||||
cpustate->pc++;
|
||||
op |= READ_PRG_16(cpustate, cpustate->pc);
|
||||
WRITE_IO_8(cpustate, op & 0x0000ffff, READ_IO_8(cpustate, RD5(op >> 16)));
|
||||
opcycles = 2;
|
||||
break;
|
||||
case 0x0001: // ST Z+,Rd
|
||||
//output += sprintf( output, "ST Z+, R%d", RD5(op) );
|
||||
@ -471,6 +514,7 @@ static CPU_EXECUTE( avr8 )
|
||||
case 0x000c: // ST X,Rd
|
||||
rd = READ_IO_8(cpustate, RD5(op));
|
||||
WRITE_IO_8(cpustate, XREG, rd);
|
||||
opcycles = 2;
|
||||
break;
|
||||
case 0x000d: // ST X+,Rd
|
||||
pd = XREG;
|
||||
@ -478,14 +522,15 @@ static CPU_EXECUTE( avr8 )
|
||||
pd++;
|
||||
WRITE_IO_8(cpustate, 27, (pd >> 8) & 0x00ff);
|
||||
WRITE_IO_8(cpustate, 26, pd & 0x00ff);
|
||||
opcycles = 2;
|
||||
break;
|
||||
case 0x000e: // ST -X,Rd
|
||||
//output += sprintf( output, "ST -X , R%d", RD5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
break;
|
||||
case 0x000f: // PUSH Rd
|
||||
//output += sprintf( output, "PUSH R%d", RD5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
PUSH(cpustate, READ_IO_8(cpustate, RD5(op)));
|
||||
opcycles = 2;
|
||||
break;
|
||||
default:
|
||||
unimplemented_opcode(cpustate, op);
|
||||
@ -497,12 +542,23 @@ static CPU_EXECUTE( avr8 )
|
||||
switch(op & 0x000f)
|
||||
{
|
||||
case 0x0000: // COM Rd
|
||||
//output += sprintf( output, "COM R%d", RD5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
rd = READ_IO_8(cpustate, RD5(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;
|
||||
case 0x0001: // NEG Rd
|
||||
//output += sprintf( output, "NEG R%d", RD5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
rd = READ_IO_8(cpustate, RD5(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;
|
||||
case 0x0002: // SWAP Rd
|
||||
//output += sprintf( output, "SWAP R%d", RD5(op) );
|
||||
@ -522,8 +578,13 @@ static CPU_EXECUTE( avr8 )
|
||||
unimplemented_opcode(cpustate, op);
|
||||
break;
|
||||
case 0x0006: // LSR Rd
|
||||
//output += sprintf( output, "LSR R%d", RD5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
rd = READ_IO_8(cpustate, RD5(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;
|
||||
case 0x0007: // ROR Rd
|
||||
//output += sprintf( output, "ROR R%d", RD5(op) );
|
||||
@ -559,21 +620,26 @@ static CPU_EXECUTE( avr8 )
|
||||
{
|
||||
case 0x0000: // IJMP
|
||||
cpustate->pc = ZREG - 1;
|
||||
opcycles = 2;
|
||||
break;
|
||||
case 0x0010: // EIJMP
|
||||
//output += sprintf( output, "EIJMP" );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
break;
|
||||
default:
|
||||
unimplemented_opcode(cpustate, op);
|
||||
//output += sprintf( output, "Undefined (%04x)", op );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x000a: // DEC Rd
|
||||
//output += sprintf( output, "DEC R%d", RD5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
rd = READ_IO_8(cpustate, RD5(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;
|
||||
case 0x000c:
|
||||
case 0x000d: // JMP k
|
||||
@ -603,12 +669,24 @@ static CPU_EXECUTE( avr8 )
|
||||
switch(op & 0x000f)
|
||||
{
|
||||
case 0x0000: // COM Rd
|
||||
//output += sprintf( output, "COM R%d", RD5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
rd = READ_IO_8(cpustate, RD5(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;
|
||||
case 0x0001: // NEG Rd
|
||||
//output += sprintf( output, "NEG R%d", RD5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
rd = READ_IO_8(cpustate, RD5(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;
|
||||
case 0x0002: // SWAP Rd
|
||||
//output += sprintf( output, "SWAP R%d", RD5(op) );
|
||||
@ -628,8 +706,13 @@ static CPU_EXECUTE( avr8 )
|
||||
unimplemented_opcode(cpustate, op);
|
||||
break;
|
||||
case 0x0006: // LSR Rd
|
||||
//output += sprintf( output, "LSR R%d", RD5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
rd = READ_IO_8(cpustate, RD5(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;
|
||||
case 0x0007: // ROR Rd
|
||||
//output += sprintf( output, "ROR R%d", RD5(op) );
|
||||
@ -642,10 +725,14 @@ static CPU_EXECUTE( avr8 )
|
||||
cpustate->pc = POP(cpustate);
|
||||
cpustate->pc |= POP(cpustate) << 8;
|
||||
cpustate->pc--;
|
||||
opcycles = 4;
|
||||
break;
|
||||
case 0x0010: // RETI
|
||||
//output += sprintf( output, "RETI" );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
cpustate->pc = POP(cpustate);
|
||||
cpustate->pc |= POP(cpustate) << 8;
|
||||
cpustate->pc--;
|
||||
SREG_W(AVR8_SREG_I, 1);
|
||||
opcycles = 4;
|
||||
break;
|
||||
case 0x0080: // SLEEP
|
||||
//output += sprintf( output, "SLEEP" );
|
||||
@ -661,6 +748,7 @@ static CPU_EXECUTE( avr8 )
|
||||
break;
|
||||
case 0x00c0: // LPM
|
||||
WRITE_IO_8(cpustate, 0, READ_PRG_8(cpustate, ZREG));
|
||||
opcycles = 3;
|
||||
break;
|
||||
case 0x00d0: // ELPM
|
||||
//output += sprintf( output, "ELPM" );
|
||||
@ -698,8 +786,13 @@ static CPU_EXECUTE( avr8 )
|
||||
}
|
||||
break;
|
||||
case 0x000a: // DEC Rd
|
||||
//output += sprintf( output, "DEC R%d", RD5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
rd = READ_IO_8(cpustate, RD5(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;
|
||||
case 0x000c:
|
||||
case 0x000d: // JMP k
|
||||
@ -727,47 +820,56 @@ static CPU_EXECUTE( avr8 )
|
||||
break;
|
||||
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) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
break;
|
||||
case 0x0800: // CBI A,b
|
||||
//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;
|
||||
case 0x0900: // SBIC A,b
|
||||
//output += sprintf( output, "SBIC 0x%02x, %d", ACONST5(op), RR3(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
break;
|
||||
case 0x0a00: // SBI A,b
|
||||
//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;
|
||||
case 0x0b00: // SBIS A,b
|
||||
//output += sprintf( output, "SBIS 0x%02x, %d", ACONST5(op), RR3(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
break;
|
||||
case 0x0c00:
|
||||
case 0x0d00:
|
||||
case 0x0e00:
|
||||
case 0x0f00: // MUL Rd,Rr
|
||||
//output += sprintf( output, "MUL R%d, R%d", RD5(op), RR5(op) );
|
||||
unimplemented_opcode(cpustate, op);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0xb000:
|
||||
unimplemented_opcode(cpustate, op);
|
||||
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
|
||||
{
|
||||
//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;
|
||||
case 0xc000: // RJMP k
|
||||
offs = (INT32)((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff));
|
||||
cpustate->pc += offs;
|
||||
opcycles = 2;
|
||||
break;
|
||||
case 0xd000: // RCALL k
|
||||
offs = (INT32)((op & 0x0800) ? ((op & 0x0fff) | 0xfffff000) : (op & 0x0fff));
|
||||
PUSH(cpustate, ((cpustate->pc + 1) >> 8) & 0x00ff);
|
||||
PUSH(cpustate, (cpustate->pc + 1) & 0x00ff);
|
||||
cpustate->pc += offs;
|
||||
opcycles = 3;
|
||||
break;
|
||||
case 0xe000: // LDI Rd,K
|
||||
rd = KCONST8(op);
|
||||
@ -785,6 +887,7 @@ static CPU_EXECUTE( avr8 )
|
||||
offs |= 0xffffff80;
|
||||
}
|
||||
cpustate->pc += offs;
|
||||
opcycles = 2;
|
||||
}
|
||||
break;
|
||||
case 0x0400: // BRSH through BRID
|
||||
@ -796,28 +899,54 @@ static CPU_EXECUTE( avr8 )
|
||||
offs |= 0xffffff80;
|
||||
}
|
||||
cpustate->pc += offs;
|
||||
opcycles = 2;
|
||||
}
|
||||
break;
|
||||
case 0x0800:
|
||||
unimplemented_opcode(cpustate, op);
|
||||
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
|
||||
{
|
||||
//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;
|
||||
case 0x0c00:
|
||||
unimplemented_opcode(cpustate, op);
|
||||
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
|
||||
{
|
||||
//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;
|
||||
}
|
||||
@ -826,7 +955,7 @@ static CPU_EXECUTE( avr8 )
|
||||
|
||||
cpustate->pc++;
|
||||
|
||||
--cpustate->icount;
|
||||
cpustate->icount -= opcycles;
|
||||
}
|
||||
|
||||
return cycles - cpustate->icount;
|
||||
@ -840,6 +969,35 @@ static CPU_SET_INFO( avr8 )
|
||||
|
||||
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 --- */
|
||||
case CPUINFO_INT_PC: /* intentional fallthrough */
|
||||
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_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_SP: sprintf(info->s, "SP: %04x", SPREG ); break;
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,37 @@ enum
|
||||
AVR8_X,
|
||||
AVR8_Y,
|
||||
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 );
|
||||
|
@ -38,7 +38,7 @@ CPU_DISASSEMBLE( avr8 )
|
||||
output += sprintf( output, "NOP" );
|
||||
break;
|
||||
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;
|
||||
case 0x0200:
|
||||
output += sprintf( output, "MULS R%d, R%d", 16+RD4(op), 16+RR4(op) );
|
||||
|
@ -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_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_R1: sprintf(info->s, "R1: %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_R3: sprintf(info->s, "R3: %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_R5: sprintf(info->s, "R5: %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_R7: sprintf(info->s, "R7: %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_R9: sprintf(info->s, "R9: %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_R11: sprintf(info->s, "R11:%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_R13: sprintf(info->s, "R13:%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_R15: sprintf(info->s, "R15:%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_R17: sprintf(info->s, "R17:%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_R19: sprintf(info->s, "R19:%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_R21: sprintf(info->s, "R21:%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_R23: sprintf(info->s, "R23:%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_R25: sprintf(info->s, "R25:%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_R27: sprintf(info->s, "R27:%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_R29: sprintf(info->s, "R29:%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_R31: sprintf(info->s, "R31:%08X%08X", (UINT32)(mips->r[31] >> 32), (UINT32)mips->r[31]); 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, " $at: %08X%08X", (UINT32)(mips->r[1] >> 32), (UINT32)mips->r[1]); 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, " $v1: %08X%08X", (UINT32)(mips->r[3] >> 32), (UINT32)mips->r[3]); 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, " $a1: %08X%08X", (UINT32)(mips->r[5] >> 32), (UINT32)mips->r[5]); 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, " $a3: %08X%08X", (UINT32)(mips->r[7] >> 32), (UINT32)mips->r[7]); 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, " $t1: %08X%08X", (UINT32)(mips->r[9] >> 32), (UINT32)mips->r[9]); 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, " $t3:%08X%08X", (UINT32)(mips->r[11] >> 32), (UINT32)mips->r[11]); 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, " $t5:%08X%08X", (UINT32)(mips->r[13] >> 32), (UINT32)mips->r[13]); 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, " $t7:%08X%08X", (UINT32)(mips->r[15] >> 32), (UINT32)mips->r[15]); 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, " $s1:%08X%08X", (UINT32)(mips->r[17] >> 32), (UINT32)mips->r[17]); 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, " $s3:%08X%08X", (UINT32)(mips->r[19] >> 32), (UINT32)mips->r[19]); 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, " $s5:%08X%08X", (UINT32)(mips->r[21] >> 32), (UINT32)mips->r[21]); 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, " $s7:%08X%08X", (UINT32)(mips->r[23] >> 32), (UINT32)mips->r[23]); 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, " $t9:%08X%08X", (UINT32)(mips->r[25] >> 32), (UINT32)mips->r[25]); 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, " $k1:%08X%08X", (UINT32)(mips->r[27] >> 32), (UINT32)mips->r[27]); 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, " $sp:%08X%08X", (UINT32)(mips->r[29] >> 32), (UINT32)mips->r[29]); 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, " $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_LO: sprintf(info->s, "LO: %08X%08X", (UINT32)(mips->r[REG_LO] >> 32), (UINT32)mips->r[REG_LO]); break;
|
||||
|
||||
|
@ -11,10 +11,10 @@
|
||||
|
||||
static const char *const reg[32] =
|
||||
{
|
||||
"0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
|
||||
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
|
||||
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
|
||||
"$0", "$at", "$v0", "$v1", "$a0", "$a1", "$a2", "$a3",
|
||||
"$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7",
|
||||
"$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7",
|
||||
"$t8", "$t9", "$k0", "$k1", "$gp", "$sp", "$fp", "$ra"
|
||||
};
|
||||
|
||||
|
||||
|
@ -18,7 +18,12 @@ typedef struct
|
||||
typedef struct _superfx_state superfx_state;
|
||||
struct _superfx_state
|
||||
{
|
||||
superfx_config config;
|
||||
|
||||
devcb_resolved_write_line out_irq_func;
|
||||
|
||||
UINT8 pipeline;
|
||||
UINT16 ramaddr; // RAM Address
|
||||
|
||||
UINT16 r[16]; // GPRs
|
||||
UINT16 sfr; // Status Flag Register
|
||||
@ -41,7 +46,6 @@ struct _superfx_state
|
||||
UINT32 ramcl; // Clock ticks until RAMDR is valid;
|
||||
UINT16 ramar; // RAM Buffer Address Register
|
||||
UINT8 ramdr; // RAM Buffer Data Register
|
||||
UINT16 ramaddr; // RAM Address
|
||||
|
||||
UINT16 *sreg; // Source Register (From)
|
||||
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);
|
||||
INLINE UINT8 superfx_bus_read(superfx_state *cpustate, UINT32 addr);
|
||||
INLINE void superfx_bus_write(superfx_state *cpustate, UINT32 addr, UINT8 data);
|
||||
static void superfx_pixelcache_flush(superfx_state *cpustate, INT32 line);
|
||||
static void superfx_plot(superfx_state *cpustate, UINT8 x, UINT8 y);
|
||||
INLINE void superfx_pixelcache_flush(superfx_state *cpustate, INT32 line);
|
||||
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_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 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 UINT8 superfx_op_read(superfx_state *cpustate, UINT16 addr);
|
||||
INLINE UINT8 superfx_peekpipe(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);
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -137,14 +148,12 @@ static void superfx_cache_flush(superfx_state *cpustate)
|
||||
static UINT8 superfx_cache_mmio_read(superfx_state *cpustate, UINT32 addr)
|
||||
{
|
||||
addr = (addr + cpustate->cbr) & 0x1ff;
|
||||
printf( "superfx_cache_mmio_read: %04x = %02x\n", addr, cpustate->cache.buffer[addr] );
|
||||
return cpustate->cache.buffer[addr];
|
||||
}
|
||||
|
||||
static void superfx_cache_mmio_write(superfx_state *cpustate, UINT32 addr, UINT8 data)
|
||||
{
|
||||
addr = (addr + cpustate->cbr) & 0x1ff;
|
||||
printf( "superfx_cache_mmio_write: %04x = %02x\n", addr, data );
|
||||
cpustate->cache.buffer[addr] = data;
|
||||
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);
|
||||
}
|
||||
|
||||
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 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);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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((x ^ y) & 1)
|
||||
@ -282,42 +288,20 @@ static void superfx_plot(superfx_state *cpustate, UINT8 x, UINT8 y)
|
||||
if(offset != cpustate->pixelcache[0].offset)
|
||||
{
|
||||
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[0].bitpend = 0x00;
|
||||
cpustate->pixelcache[0].offset = offset;
|
||||
}
|
||||
|
||||
x = (x & 7) ^ 7;
|
||||
cpustate->pixelcache[0].data[x] = 0x0f;//color;
|
||||
cpustate->pixelcache[0].data[x] = color;
|
||||
cpustate->pixelcache[0].bitpend |= 1 << x;
|
||||
if(cpustate->pixelcache[0].bitpend == 0xff)
|
||||
{
|
||||
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[0].bitpend = 0x00;
|
||||
}
|
||||
|
||||
//superfx_pixelcache_flush(cpustate, 1);
|
||||
//superfx_pixelcache_flush(cpustate, 0);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//printf( "%08x: superfx_rpix; %d, %d = %02x\n", (cpustate->pbr << 16) | cpustate->r[15], x, y, 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)
|
||||
{
|
||||
return (cpustate->colr & 0xf0) | (source >> 4);
|
||||
@ -378,20 +359,56 @@ static UINT8 superfx_color(superfx_state *cpustate, UINT8 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)
|
||||
{
|
||||
superfx_rambuffer_sync(cpustate);
|
||||
return superfx_bus_read(cpustate, 0x700000 + (cpustate->rambr << 16) + addr);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
cpustate->r[r] = data;
|
||||
if(r == 15)
|
||||
if(r == 14)
|
||||
{
|
||||
superfx_rombuffer_update(cpustate);
|
||||
}
|
||||
else if(r == 15)
|
||||
{
|
||||
cpustate->r15_modified = 1;
|
||||
}
|
||||
@ -421,7 +438,20 @@ INLINE UINT8 superfx_op_read(superfx_state *cpustate, UINT16 addr)
|
||||
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)
|
||||
@ -468,6 +498,7 @@ UINT8 superfx_mmio_read(const device_config *cpu, UINT32 addr)
|
||||
UINT8 r = cpustate->sfr >> 8;
|
||||
cpustate->sfr &= ~SUPERFX_SFR_IRQ;
|
||||
cpustate->irq = 0;
|
||||
devcb_call_write_line(&cpustate->out_irq_func, cpustate->irq);
|
||||
return r;
|
||||
}
|
||||
|
||||
@ -490,8 +521,6 @@ UINT8 superfx_mmio_read(const device_config *cpu, UINT32 addr)
|
||||
return cpustate->cbr >> 8;
|
||||
}
|
||||
|
||||
printf( "Unsuppoted mmio read: %08x\n", addr );
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
//printf( "superfx_mmio_write: %08x = %02x\n", addr, data );
|
||||
|
||||
if(addr >= 0x3000 && addr <= 0x301f)
|
||||
{
|
||||
UINT32 n = (addr >> 1) & 0xf;
|
||||
@ -523,7 +550,6 @@ void superfx_mmio_write(const device_config *cpu, UINT32 addr, UINT8 data)
|
||||
if(addr == 0x301f)
|
||||
{
|
||||
cpustate->sfr |= SUPERFX_SFR_G;
|
||||
//printf( "new PC: %04x\n", cpustate->r[15] );
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -572,14 +598,29 @@ void superfx_mmio_write(const device_config *cpu, UINT32 addr, UINT8 data)
|
||||
case 0x303a:
|
||||
cpustate->scmr = data;
|
||||
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)
|
||||
@ -637,6 +678,13 @@ static CPU_INIT( superfx )
|
||||
|
||||
cpustate->device = device;
|
||||
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 )
|
||||
@ -707,18 +755,17 @@ static CPU_EXECUTE( superfx )
|
||||
|
||||
op = superfx_peekpipe(cpustate);
|
||||
|
||||
//printf( "Executing op at %06x: %02x\n", (cpustate->pbr << 16) | cpustate->r[15], op );
|
||||
switch(op)
|
||||
{
|
||||
case 0x00: // STOP
|
||||
if(!(cpustate->cfgr & SUPERFX_CFGR_IRQ))
|
||||
if((cpustate->cfgr & SUPERFX_CFGR_IRQ) == 0)
|
||||
{
|
||||
cpustate->sfr |= SUPERFX_SFR_IRQ;
|
||||
cpustate->irq = 1;
|
||||
devcb_call_write_line(&cpustate->out_irq_func, cpustate->irq ? ASSERT_LINE : CLEAR_LINE );
|
||||
}
|
||||
cpustate->sfr &= ~SUPERFX_SFR_G;
|
||||
cpustate->pipeline = 0x01;
|
||||
cpustate->por = 0x00;
|
||||
superfx_regs_reset(cpustate);
|
||||
break;
|
||||
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 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_idx = op & 0xf;
|
||||
@ -959,7 +1006,6 @@ static CPU_EXECUTE( superfx )
|
||||
}
|
||||
else
|
||||
{ // CMODE
|
||||
//printf( "CMODE: %04x\n", *(cpustate->sreg) );
|
||||
cpustate->por = *(cpustate->sreg);
|
||||
superfx_regs_reset(cpustate);
|
||||
}
|
||||
@ -1148,7 +1194,7 @@ static CPU_EXECUTE( superfx )
|
||||
}
|
||||
else
|
||||
{ // LJMP
|
||||
cpustate->pbr = cpustate->r[op & 0xf] & 0x7f;
|
||||
cpustate->pbr = cpustate->r[op & 0xf];
|
||||
superfx_gpr_write(cpustate, 15, *(cpustate->sreg));
|
||||
cpustate->cbr = cpustate->r[15] & 0xfff0;
|
||||
superfx_cache_flush(cpustate);
|
||||
@ -1157,7 +1203,7 @@ static CPU_EXECUTE( superfx )
|
||||
break;
|
||||
|
||||
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 |= (*(cpustate->dreg) & 0x80) ? SUPERFX_SFR_S : 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 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_idx = op & 0xf;
|
||||
@ -1226,8 +1272,10 @@ static CPU_EXECUTE( superfx )
|
||||
break;
|
||||
|
||||
case 0xc0: // HIB
|
||||
superfx_gpr_write(cpustate, cpustate->dreg_idx, (UINT16)*(cpustate->sreg) >> 8);
|
||||
superfx_dreg_sfr_sz_update(cpustate);
|
||||
superfx_gpr_write(cpustate, cpustate->dreg_idx, (*(cpustate->sreg)) >> 8);
|
||||
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);
|
||||
break;
|
||||
|
||||
@ -1266,14 +1314,16 @@ static CPU_EXECUTE( superfx )
|
||||
{
|
||||
case SUPERFX_SFR_ALT0: // 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);
|
||||
break;
|
||||
case SUPERFX_SFR_ALT2: // RAMB
|
||||
superfx_rambuffer_sync(cpustate);
|
||||
cpustate->rambr = *(cpustate->sreg);
|
||||
superfx_regs_reset(cpustate);
|
||||
break;
|
||||
case SUPERFX_SFR_ALT3: // ROMB
|
||||
superfx_rombuffer_sync(cpustate);
|
||||
cpustate->rombr = *(cpustate->sreg);
|
||||
superfx_regs_reset(cpustate);
|
||||
break;
|
||||
@ -1291,7 +1341,7 @@ static CPU_EXECUTE( superfx )
|
||||
|
||||
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)
|
||||
{
|
||||
case SUPERFX_SFR_ALT0: // GETB
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef __SUPERFX_H__
|
||||
#define __SUPERFX_H__
|
||||
|
||||
#include "devcb.h"
|
||||
|
||||
enum
|
||||
{
|
||||
SUPERFX_PC = 1,
|
||||
@ -82,6 +84,13 @@ enum
|
||||
#define SUPERFX_CFGR_IRQ 0x80 // IRQ
|
||||
#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 );
|
||||
#define CPU_SUPERFX CPU_GET_INFO_NAME( superfx )
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef _SNES_H_
|
||||
#define _SNES_H_
|
||||
|
||||
#include "devcb.h"
|
||||
#include "streams.h"
|
||||
|
||||
/*
|
||||
@ -365,13 +366,12 @@ HAS_SDD1,
|
||||
HAS_OBC1,
|
||||
HAS_RTC,
|
||||
HAS_Z80GB,
|
||||
HAS_C4,
|
||||
HAS_CX4,
|
||||
HAS_ST010,
|
||||
HAS_ST011,
|
||||
HAS_ST018,
|
||||
HAS_SPC7110,
|
||||
HAS_SPC7110_RTC,
|
||||
HAS_CX4,
|
||||
HAS_UNK
|
||||
};
|
||||
|
||||
@ -400,6 +400,17 @@ extern WRITE8_HANDLER( snes_w_bank5 );
|
||||
extern WRITE8_HANDLER( snes_w_bank6 );
|
||||
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 void snes_gdma( const address_space *space, UINT8 channels );
|
||||
|
@ -8,19 +8,16 @@
|
||||
Anthony Kruize
|
||||
Based on the original code by Lee Hammerton (aka Savoury Snax)
|
||||
Thanks to Anomie for invaluable technical information.
|
||||
Thanks to byuu for invaluable technical information.
|
||||
|
||||
***************************************************************************/
|
||||
#define __MACHINE_SNES_C
|
||||
|
||||
#include "driver.h"
|
||||
#include "includes/snes.h"
|
||||
#include "cpu/superfx/superfx.h"
|
||||
#include "cpu/g65816/g65816.h"
|
||||
|
||||
// add-on chip emulators
|
||||
#include "machine/snesdsp1.c"
|
||||
#include "machine/snesdsp2.c"
|
||||
#include "machine/snesobc1.c"
|
||||
|
||||
/* -- Globals -- */
|
||||
UINT8 *snes_ram = NULL; /* 65816 ram */
|
||||
UINT8 *spc_ram = NULL; /* spc700 ram */
|
||||
@ -58,6 +55,12 @@ static struct
|
||||
UINT8 oldrol;
|
||||
} 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];
|
||||
}
|
||||
|
||||
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 */
|
||||
switch( offset )
|
||||
{
|
||||
@ -665,6 +690,8 @@ READ8_HANDLER( snes_r_io )
|
||||
|
||||
}
|
||||
|
||||
//printf("unsupported read: offset == %08x\n", offset);
|
||||
|
||||
/* Unsupported reads returns open bus */
|
||||
// printf("%02x %02x\n",offset,snes_open_bus_r(space,0));
|
||||
return snes_open_bus_r(space,0);
|
||||
@ -687,6 +714,32 @@ WRITE8_HANDLER( snes_w_io )
|
||||
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 */
|
||||
switch( offset )
|
||||
{
|
||||
@ -729,7 +782,7 @@ WRITE8_HANDLER( snes_w_io )
|
||||
break;
|
||||
default:
|
||||
/* 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[1] = 2;
|
||||
@ -1301,9 +1354,16 @@ WRITE8_HANDLER( snes_w_io )
|
||||
break;
|
||||
}
|
||||
|
||||
logerror("Unsupported MMIO write: offset %08x = %02x\n", 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
|
||||
@ -1391,14 +1451,19 @@ READ8_HANDLER( snes_r_bank1 )
|
||||
value = snes_r_io(space, address);
|
||||
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);
|
||||
else if ((snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000))
|
||||
value = (address < 0x7000) ? DSP2_read() : 0x00;
|
||||
else if ((snes_cart.mode == SNES_MODE_21) && (snes_has_addon_chip == HAS_DSP1) && (offset < 0x100000))
|
||||
value = (address < 0x7000) ? DSP1_getDr() : DSP1_getSr();
|
||||
else
|
||||
{
|
||||
logerror( "snes_r_bank1: Unmapped external chip read: %04x\n", address );
|
||||
value = 0xff; /* Reserved */
|
||||
}
|
||||
}
|
||||
else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP1) && (offset >= 0x200000))
|
||||
value = (address < 0xc000) ? DSP1_getDr() : DSP1_getSr();
|
||||
@ -1433,7 +1498,10 @@ READ8_HANDLER( snes_r_bank2 )
|
||||
value = snes_ram[0x306000 + (offset & mask)];
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror( "snes_r_bank2: Unmapped external chip read: %04x\n", address );
|
||||
value = 0xff;
|
||||
}
|
||||
}
|
||||
/* 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))
|
||||
@ -1471,7 +1539,11 @@ READ8_HANDLER( snes_r_bank4 )
|
||||
UINT8 value = 0xff;
|
||||
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)
|
||||
value = snes_ram[0x600000 + offset];
|
||||
@ -1479,7 +1551,10 @@ READ8_HANDLER( snes_r_bank4 )
|
||||
else if (snes_has_addon_chip == HAS_DSP1)
|
||||
value = (address >= 0x4000) ? DSP1_getSr() : DSP1_getDr();
|
||||
else
|
||||
{
|
||||
logerror( "snes_r_bank4: Unmapped external chip read: %04x\n", address );
|
||||
value = 0xff; /* Reserved */
|
||||
}
|
||||
}
|
||||
else if (snes_cart.mode & 0x0a) /* Mode 21 & 25 */
|
||||
value = snes_ram[0x600000 + offset];
|
||||
@ -1493,7 +1568,11 @@ READ8_HANDLER( snes_r_bank5 )
|
||||
UINT8 value;
|
||||
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)
|
||||
{
|
||||
@ -1501,10 +1580,15 @@ READ8_HANDLER( snes_r_bank5 )
|
||||
value = snes_ram[0x700000 + (offset & mask)];
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror( "snes_r_bank5: Unmapped external chip read: %04x\n", address );
|
||||
value = 0xff; /* Reserved */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value = snes_ram[0x700000 + offset];
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
@ -1512,12 +1596,14 @@ READ8_HANDLER( snes_r_bank5 )
|
||||
/* 0x800000 - 0xbfffff */
|
||||
READ8_HANDLER( snes_r_bank6 )
|
||||
{
|
||||
UINT8 value;
|
||||
UINT8 value = 0;
|
||||
UINT16 address = offset & 0xffff;
|
||||
|
||||
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);
|
||||
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 */
|
||||
}
|
||||
else /* Area 0x6000-0x8000 with offset < 0x300000 is reserved */
|
||||
{
|
||||
logerror( "snes_r_bank6: Unmapped external chip read: %04x\n", address );
|
||||
value = 0xff;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
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 (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))
|
||||
DSP1_setDr(data);
|
||||
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))
|
||||
DSP1_setDr(data);
|
||||
@ -1611,11 +1704,12 @@ WRITE8_HANDLER( snes_w_bank2 )
|
||||
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 */
|
||||
logerror( "snes_w_bank2 hit in Super FX mode, please fix me if necessary\n" );
|
||||
offset -= 0x6000;
|
||||
snes_ram[0x306000 + (offset & mask)] = data;
|
||||
}
|
||||
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 */
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
logerror("Attempt to write to ROM address: %X\n", offset + 0x600000);
|
||||
}
|
||||
else if (snes_has_addon_chip == HAS_DSP1)
|
||||
{
|
||||
DSP1_setDr(data);
|
||||
}
|
||||
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)
|
||||
{
|
||||
logerror("Attempt to write to ROM address: %X\n", offset + 0x600000);
|
||||
}
|
||||
}
|
||||
|
||||
/* 0x700000 - 0x7dffff */
|
||||
@ -1649,7 +1755,11 @@ WRITE8_HANDLER( snes_w_bank5 )
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -1657,10 +1767,14 @@ WRITE8_HANDLER( snes_w_bank5 )
|
||||
snes_ram[0x700000 + (offset & mask)] = data;
|
||||
}
|
||||
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)
|
||||
{
|
||||
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 >= 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 (offset < 0x300000)
|
||||
@ -1694,13 +1812,15 @@ WRITE8_HANDLER( snes_w_bank6 )
|
||||
snes_ram[0xb06000 + (offset & mask)] = data;
|
||||
}
|
||||
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))
|
||||
DSP1_setDr(data);
|
||||
else if ((snes_cart.mode == SNES_MODE_20) && (snes_has_addon_chip == HAS_DSP2) && (offset >= 0x200000) && (address < 0xc000))
|
||||
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
|
||||
logerror("Attempt to write to ROM address: %X\n", offset + 0x800000);
|
||||
}
|
||||
@ -1711,7 +1831,18 @@ WRITE8_HANDLER( snes_w_bank7 )
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -1723,7 +1854,7 @@ WRITE8_HANDLER( snes_w_bank7 )
|
||||
snes_w_bank4(space, offset - 0x200000, data);
|
||||
}
|
||||
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)
|
||||
logerror("Attempt to write to ROM address: %X\n", offset + 0xc00000);
|
||||
@ -1872,6 +2003,8 @@ MACHINE_START( snes )
|
||||
snes_ram[WRMPYA] = 0xff;
|
||||
snes_ram[WRDIVL] = 0xff;
|
||||
snes_ram[WRDIVH] = 0xff;
|
||||
|
||||
sdd1_init(machine);
|
||||
}
|
||||
|
||||
MACHINE_RESET( snes )
|
||||
@ -1894,6 +2027,9 @@ MACHINE_RESET( snes )
|
||||
snes_htmult = 1;
|
||||
snes_ppu.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;
|
||||
}
|
||||
}
|
||||
|
||||
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
203
src/mame/machine/snesrtc.c
Normal 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
667
src/mame/machine/snessdd1.c
Normal 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)
|
||||
{
|
||||
}
|
@ -1846,5 +1846,7 @@ $(DRIVERS)/galaxian.o: $(MAMESRC)/drivers/galdrvr.c
|
||||
$(DRIVERS)/mpu4.o: $(MAMESRC)/drivers/mpu4drvr.c
|
||||
$(DRIVERS)/neogeo.o: $(MAMESRC)/drivers/neodrvr.c
|
||||
$(MACHINE)/snes.o: $(MAMESRC)/machine/snesdsp1.c \
|
||||
$(MAMESRC)/machine/snesdsp2.c \
|
||||
$(MAMESRC)/machine/snesobc1.c
|
||||
$(MAMESRC)/machine/snesdsp2.c \
|
||||
$(MAMESRC)/machine/snesobc1.c \
|
||||
$(MAMESRC)/machine/snesrtc.c \
|
||||
$(MAMESRC)/machine/snessdd1.c
|
||||
|
Loading…
Reference in New Issue
Block a user