mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-25 23:25:40 +00:00
Fixed 68K save state problem: pending interrupts were not being saved, sometimes causing the DSB2 to take an invalid interrupt (from the sound board 68K) after loading a save state. Save states are no longer compatible with previous revision.
This commit is contained in:
parent
cf73207c98
commit
e6f19c40ef
|
@ -217,19 +217,19 @@ $(OBJ_DIR)/m68kmake.exe: Src/CPU/68K/Musashi/m68kmake.c
|
||||||
$(OBJ_DIR)/m68kops.h: $(OBJ_DIR)/m68kmake.exe Src/CPU/68K/Musashi/m68k_in.c
|
$(OBJ_DIR)/m68kops.h: $(OBJ_DIR)/m68kmake.exe Src/CPU/68K/Musashi/m68k_in.c
|
||||||
$(OBJ_DIR)/m68kmake.exe $(OBJ_DIR) Src/CPU/68K/Musashi/m68k_in.c
|
$(OBJ_DIR)/m68kmake.exe $(OBJ_DIR) Src/CPU/68K/Musashi/m68k_in.c
|
||||||
|
|
||||||
$(OBJ_DIR)/m68kcpu.obj: Src/CPU/68K/Musashi/m68kcpu.c $(OBJ_DIR)/m68kops.h Src/CPU/68K/Musashi/m68k.h Src/CPU/68K/Musashi/m68kconf.h
|
$(OBJ_DIR)/m68kcpu.obj: Src/CPU/68K/Musashi/m68kcpu.c $(OBJ_DIR)/m68kops.h Src/CPU/68K/Musashi/m68k.h Src/CPU/68K/Musashi/m68kconf.h Src/CPU/68K/Musashi/m68kctx.h
|
||||||
$(CC) $< $(CFLAGS) /Fo$(OBJ_DIR)/m68kcpu.obj /I "$(OBJ_DIR)" /I "Src\CPU\68K\Musashi" /DINLINE="static __inline"
|
$(CC) $< $(CFLAGS) /Fo$(OBJ_DIR)/m68kcpu.obj /I "$(OBJ_DIR)" /I "Src\CPU\68K\Musashi" /DINLINE="static __inline"
|
||||||
|
|
||||||
$(OBJ_DIR)/m68kops.obj: $(OBJ_DIR)/m68kops.c $(OBJ_DIR)/m68kmake.exe $(OBJ_DIR)/m68kops.h Src/CPU/68K/Musashi/m68k.h Src/CPU/68K/Musashi/m68kconf.h
|
$(OBJ_DIR)/m68kops.obj: $(OBJ_DIR)/m68kops.c $(OBJ_DIR)/m68kmake.exe $(OBJ_DIR)/m68kops.h Src/CPU/68K/Musashi/m68k.h Src/CPU/68K/Musashi/m68kconf.h Src/CPU/68K/Musashi/m68kctx.h
|
||||||
$(CC) $< $(CFLAGS) /Fo$(OBJ_DIR)/m68kops.obj /I "Src\CPU\68K\Musashi" /DINLINE="static __inline"
|
$(CC) $< $(CFLAGS) /Fo$(OBJ_DIR)/m68kops.obj /I "Src\CPU\68K\Musashi" /DINLINE="static __inline"
|
||||||
|
|
||||||
$(OBJ_DIR)/m68kopac.obj: $(OBJ_DIR)/m68kopac.c $(OBJ_DIR)/m68kmake.exe $(OBJ_DIR)/m68kops.h Src/CPU/68K/Musashi/m68k.h Src/CPU/68K/Musashi/m68kconf.h
|
$(OBJ_DIR)/m68kopac.obj: $(OBJ_DIR)/m68kopac.c $(OBJ_DIR)/m68kmake.exe $(OBJ_DIR)/m68kops.h Src/CPU/68K/Musashi/m68k.h Src/CPU/68K/Musashi/m68kconf.h Src/CPU/68K/Musashi/m68kctx.h
|
||||||
$(CC) $< $(CFLAGS) /Fo$(OBJ_DIR)/m68kopac.obj /I "Src\CPU\68K\Musashi" /DINLINE="static __inline"
|
$(CC) $< $(CFLAGS) /Fo$(OBJ_DIR)/m68kopac.obj /I "Src\CPU\68K\Musashi" /DINLINE="static __inline"
|
||||||
|
|
||||||
$(OBJ_DIR)/m68kopdm.obj: $(OBJ_DIR)/m68kopdm.c $(OBJ_DIR)/m68kmake.exe $(OBJ_DIR)/m68kops.h Src/CPU/68K/Musashi/m68k.h Src/CPU/68K/Musashi/m68kconf.h
|
$(OBJ_DIR)/m68kopdm.obj: $(OBJ_DIR)/m68kopdm.c $(OBJ_DIR)/m68kmake.exe $(OBJ_DIR)/m68kops.h Src/CPU/68K/Musashi/m68k.h Src/CPU/68K/Musashi/m68kconf.h Src/CPU/68K/Musashi/m68kctx.h
|
||||||
$(CC) $< $(CFLAGS) /Fo$(OBJ_DIR)/m68kopdm.obj /I "Src\CPU\68K\Musashi" /DINLINE="static __inline"
|
$(CC) $< $(CFLAGS) /Fo$(OBJ_DIR)/m68kopdm.obj /I "Src\CPU\68K\Musashi" /DINLINE="static __inline"
|
||||||
|
|
||||||
$(OBJ_DIR)/m68kopnz.obj: $(OBJ_DIR)/m68kopnz.c $(OBJ_DIR)/m68kmake.exe $(OBJ_DIR)/m68kops.h Src/CPU/68K/Musashi/m68k.h Src/CPU/68K/Musashi/m68kconf.h
|
$(OBJ_DIR)/m68kopnz.obj: $(OBJ_DIR)/m68kopnz.c $(OBJ_DIR)/m68kmake.exe $(OBJ_DIR)/m68kops.h Src/CPU/68K/Musashi/m68k.h Src/CPU/68K/Musashi/m68kconf.h Src/CPU/68K/Musashi/m68kctx.h
|
||||||
$(CC) $< $(CFLAGS) /Fo$(OBJ_DIR)/m68kopnz.obj /I "Src\CPU\68K\Musashi" /DINLINE="static __inline"
|
$(CC) $< $(CFLAGS) /Fo$(OBJ_DIR)/m68kopnz.obj /I "Src\CPU\68K\Musashi" /DINLINE="static __inline"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -108,49 +108,54 @@ void M68KSaveState(CBlockFile *StateFile, const char *name)
|
||||||
StateFile->NewBlock(name, __FILE__);
|
StateFile->NewBlock(name, __FILE__);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Rather than writing the context directly to the save state, each
|
* Rather than writing the context directly, the get/set register
|
||||||
* register is copied into an array first to ensure the same result across
|
* functions are used, ensuring that all context members are packed/
|
||||||
* different compilers (in case the struct is ordered differently). This
|
* unpacked correctly.
|
||||||
* also prevents us from inadvertently modifying the callback pointers.
|
|
||||||
*
|
*
|
||||||
* Note: Some of these are undoubtedly 68010 or 68020 registers and not
|
* Note: Some of these are undoubtedly 68010 or 68020 registers and not
|
||||||
* really necessary. But if the layout is changed now, the save state
|
* really necessary. But if the layout is changed now, the save state
|
||||||
* version has to be changed, so don't do it!
|
* version has to be changed, so don't do it!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
UINT32 data[31];
|
UINT32 data[34];
|
||||||
|
m68ki_cpu_core Ctx;
|
||||||
|
|
||||||
data[0] = m68k_get_reg(NULL, M68K_REG_D0);
|
m68k_get_context(&Ctx);
|
||||||
data[1] = m68k_get_reg(NULL, M68K_REG_D1);
|
|
||||||
data[2] = m68k_get_reg(NULL, M68K_REG_D2);
|
data[0] = Ctx.int_level;
|
||||||
data[3] = m68k_get_reg(NULL, M68K_REG_D3);
|
data[1] = Ctx.int_cycles;
|
||||||
data[4] = m68k_get_reg(NULL, M68K_REG_D4);
|
data[2] = Ctx.stopped;
|
||||||
data[5] = m68k_get_reg(NULL, M68K_REG_D5);
|
data[3] = m68k_get_reg(NULL, M68K_REG_D0);
|
||||||
data[6] = m68k_get_reg(NULL, M68K_REG_D6);
|
data[4] = m68k_get_reg(NULL, M68K_REG_D1);
|
||||||
data[7] = m68k_get_reg(NULL, M68K_REG_D7);
|
data[5] = m68k_get_reg(NULL, M68K_REG_D2);
|
||||||
data[8] = m68k_get_reg(NULL, M68K_REG_A0);
|
data[6] = m68k_get_reg(NULL, M68K_REG_D3);
|
||||||
data[9] = m68k_get_reg(NULL, M68K_REG_A1);
|
data[7] = m68k_get_reg(NULL, M68K_REG_D4);
|
||||||
data[10] = m68k_get_reg(NULL, M68K_REG_A2);
|
data[8] = m68k_get_reg(NULL, M68K_REG_D5);
|
||||||
data[11] = m68k_get_reg(NULL, M68K_REG_A3);
|
data[9] = m68k_get_reg(NULL, M68K_REG_D6);
|
||||||
data[12] = m68k_get_reg(NULL, M68K_REG_A4);
|
data[10] = m68k_get_reg(NULL, M68K_REG_D7);
|
||||||
data[13] = m68k_get_reg(NULL, M68K_REG_A5);
|
data[11] = m68k_get_reg(NULL, M68K_REG_A0);
|
||||||
data[14] = m68k_get_reg(NULL, M68K_REG_A6);
|
data[12] = m68k_get_reg(NULL, M68K_REG_A1);
|
||||||
data[15] = m68k_get_reg(NULL, M68K_REG_A7);
|
data[13] = m68k_get_reg(NULL, M68K_REG_A2);
|
||||||
data[16] = m68k_get_reg(NULL, M68K_REG_PC);
|
data[14] = m68k_get_reg(NULL, M68K_REG_A3);
|
||||||
data[17] = m68k_get_reg(NULL, M68K_REG_SR);
|
data[15] = m68k_get_reg(NULL, M68K_REG_A4);
|
||||||
data[18] = m68k_get_reg(NULL, M68K_REG_SP);
|
data[16] = m68k_get_reg(NULL, M68K_REG_A5);
|
||||||
data[19] = m68k_get_reg(NULL, M68K_REG_USP);
|
data[17] = m68k_get_reg(NULL, M68K_REG_A6);
|
||||||
data[20] = m68k_get_reg(NULL, M68K_REG_ISP);
|
data[18] = m68k_get_reg(NULL, M68K_REG_A7);
|
||||||
data[21] = m68k_get_reg(NULL, M68K_REG_MSP);
|
data[19] = m68k_get_reg(NULL, M68K_REG_PC);
|
||||||
data[22] = m68k_get_reg(NULL, M68K_REG_SFC);
|
data[20] = m68k_get_reg(NULL, M68K_REG_SR);
|
||||||
data[23] = m68k_get_reg(NULL, M68K_REG_DFC);
|
data[21] = m68k_get_reg(NULL, M68K_REG_SP);
|
||||||
data[24] = m68k_get_reg(NULL, M68K_REG_VBR);
|
data[22] = m68k_get_reg(NULL, M68K_REG_USP);
|
||||||
data[25] = m68k_get_reg(NULL, M68K_REG_CACR);
|
data[23] = m68k_get_reg(NULL, M68K_REG_ISP);
|
||||||
data[26] = m68k_get_reg(NULL, M68K_REG_CAAR);
|
data[24] = m68k_get_reg(NULL, M68K_REG_MSP);
|
||||||
data[27] = m68k_get_reg(NULL, M68K_REG_PREF_ADDR);
|
data[25] = m68k_get_reg(NULL, M68K_REG_SFC);
|
||||||
data[28] = m68k_get_reg(NULL, M68K_REG_PREF_DATA);
|
data[26] = m68k_get_reg(NULL, M68K_REG_DFC);
|
||||||
data[29] = m68k_get_reg(NULL, M68K_REG_PPC);
|
data[27] = m68k_get_reg(NULL, M68K_REG_VBR);
|
||||||
data[30] = m68k_get_reg(NULL, M68K_REG_IR);
|
data[28] = m68k_get_reg(NULL, M68K_REG_CACR);
|
||||||
|
data[29] = m68k_get_reg(NULL, M68K_REG_CAAR);
|
||||||
|
data[30] = m68k_get_reg(NULL, M68K_REG_PREF_ADDR);
|
||||||
|
data[31] = m68k_get_reg(NULL, M68K_REG_PREF_DATA);
|
||||||
|
data[32] = m68k_get_reg(NULL, M68K_REG_PPC);
|
||||||
|
data[33] = m68k_get_reg(NULL, M68K_REG_IR);
|
||||||
|
|
||||||
StateFile->Write(data, sizeof(data));
|
StateFile->Write(data, sizeof(data));
|
||||||
}
|
}
|
||||||
|
@ -163,40 +168,48 @@ void M68KLoadState(CBlockFile *StateFile, const char *name)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT32 data[31];
|
UINT32 data[34];
|
||||||
|
m68ki_cpu_core Ctx;
|
||||||
|
|
||||||
StateFile->Read(data, sizeof(data));
|
StateFile->Read(data, sizeof(data));
|
||||||
m68k_set_reg(M68K_REG_D0, data[0]);
|
|
||||||
m68k_set_reg(M68K_REG_D1, data[1]);
|
// These must be set first, to ensure another contexts' IRQs aren't active when PC is changed
|
||||||
m68k_set_reg(M68K_REG_D2, data[2]);
|
m68k_get_context(&Ctx);
|
||||||
m68k_set_reg(M68K_REG_D3, data[3]);
|
Ctx.int_level = data[0];
|
||||||
m68k_set_reg(M68K_REG_D4, data[4]);
|
Ctx.int_cycles = data[1];
|
||||||
m68k_set_reg(M68K_REG_D5, data[5]);
|
Ctx.stopped = data[2];
|
||||||
m68k_set_reg(M68K_REG_D6, data[6]);
|
m68k_set_context(&Ctx); // write them back to context
|
||||||
m68k_set_reg(M68K_REG_D7, data[7]);
|
m68k_set_reg(M68K_REG_D0, data[3]);
|
||||||
m68k_set_reg(M68K_REG_A0, data[8]);
|
m68k_set_reg(M68K_REG_D1, data[4]);
|
||||||
m68k_set_reg(M68K_REG_A1, data[9]);
|
m68k_set_reg(M68K_REG_D2, data[5]);
|
||||||
m68k_set_reg(M68K_REG_A2, data[10]);
|
m68k_set_reg(M68K_REG_D3, data[6]);
|
||||||
m68k_set_reg(M68K_REG_A3, data[11]);
|
m68k_set_reg(M68K_REG_D4, data[7]);
|
||||||
m68k_set_reg(M68K_REG_A4, data[12]);
|
m68k_set_reg(M68K_REG_D5, data[8]);
|
||||||
m68k_set_reg(M68K_REG_A5, data[13]);
|
m68k_set_reg(M68K_REG_D6, data[9]);
|
||||||
m68k_set_reg(M68K_REG_A6, data[14]);
|
m68k_set_reg(M68K_REG_D7, data[10]);
|
||||||
m68k_set_reg(M68K_REG_A7, data[15]);
|
m68k_set_reg(M68K_REG_A0, data[11]);
|
||||||
m68k_set_reg(M68K_REG_PC, data[16]);
|
m68k_set_reg(M68K_REG_A1, data[12]);
|
||||||
m68k_set_reg(M68K_REG_SR, data[17]);
|
m68k_set_reg(M68K_REG_A2, data[13]);
|
||||||
m68k_set_reg(M68K_REG_SP, data[18]);
|
m68k_set_reg(M68K_REG_A3, data[14]);
|
||||||
m68k_set_reg(M68K_REG_USP, data[19]);
|
m68k_set_reg(M68K_REG_A4, data[15]);
|
||||||
m68k_set_reg(M68K_REG_ISP, data[20]);
|
m68k_set_reg(M68K_REG_A5, data[16]);
|
||||||
m68k_set_reg(M68K_REG_MSP, data[21]);
|
m68k_set_reg(M68K_REG_A6, data[17]);
|
||||||
m68k_set_reg(M68K_REG_SFC, data[22]);
|
m68k_set_reg(M68K_REG_A7, data[18]);
|
||||||
m68k_set_reg(M68K_REG_DFC, data[23]);
|
m68k_set_reg(M68K_REG_PC, data[19]);
|
||||||
m68k_set_reg(M68K_REG_VBR, data[24]);
|
m68k_set_reg(M68K_REG_SR, data[20]);
|
||||||
m68k_set_reg(M68K_REG_CACR, data[25]);
|
m68k_set_reg(M68K_REG_SP, data[21]);
|
||||||
m68k_set_reg(M68K_REG_CAAR, data[26]);
|
m68k_set_reg(M68K_REG_USP, data[22]);
|
||||||
m68k_set_reg(M68K_REG_PREF_ADDR, data[27]);
|
m68k_set_reg(M68K_REG_ISP, data[23]);
|
||||||
m68k_set_reg(M68K_REG_PREF_DATA, data[28]);
|
m68k_set_reg(M68K_REG_MSP, data[24]);
|
||||||
m68k_set_reg(M68K_REG_PPC, data[29]);
|
m68k_set_reg(M68K_REG_SFC, data[25]);
|
||||||
m68k_set_reg(M68K_REG_IR, data[30]);
|
m68k_set_reg(M68K_REG_DFC, data[26]);
|
||||||
|
m68k_set_reg(M68K_REG_VBR, data[27]);
|
||||||
|
m68k_set_reg(M68K_REG_CACR, data[28]);
|
||||||
|
m68k_set_reg(M68K_REG_CAAR, data[29]);
|
||||||
|
m68k_set_reg(M68K_REG_PREF_ADDR, data[30]);
|
||||||
|
m68k_set_reg(M68K_REG_PREF_DATA, data[31]);
|
||||||
|
m68k_set_reg(M68K_REG_PPC, data[32]);
|
||||||
|
m68k_set_reg(M68K_REG_IR, data[33]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emulation functions
|
// Emulation functions
|
||||||
|
@ -236,14 +249,14 @@ void M68KGetContext(M68KCtx *Dest)
|
||||||
{
|
{
|
||||||
Dest->IRQAck = IRQAck;
|
Dest->IRQAck = IRQAck;
|
||||||
Dest->Bus = Bus;
|
Dest->Bus = Bus;
|
||||||
m68k_get_context(Dest->musashiCtx);
|
m68k_get_context(&(Dest->musashiCtx));
|
||||||
}
|
}
|
||||||
|
|
||||||
void M68KSetContext(M68KCtx *Src)
|
void M68KSetContext(M68KCtx *Src)
|
||||||
{
|
{
|
||||||
IRQAck = Src->IRQAck;
|
IRQAck = Src->IRQAck;
|
||||||
Bus = Src->Bus;
|
Bus = Src->Bus;
|
||||||
m68k_set_context(Src->musashiCtx);
|
m68k_set_context(&(Src->musashiCtx));
|
||||||
}
|
}
|
||||||
|
|
||||||
// One-time initialization
|
// One-time initialization
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
#include "Musashi/m68k.h"
|
#include "Musashi/m68k.h"
|
||||||
|
#include "Musashi/m68kctx.h"
|
||||||
#include "CPU/Bus.h"
|
#include "CPU/Bus.h"
|
||||||
|
|
||||||
// This doesn't work for now (needs to be added to the prototypes in m68k.h for m68k_read_memory*)
|
// This doesn't work for now (needs to be added to the prototypes in m68k.h for m68k_read_memory*)
|
||||||
|
@ -67,23 +68,21 @@
|
||||||
typedef struct SM68KCtx
|
typedef struct SM68KCtx
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
m68ki_cpu_core musashiCtx; // CPU context
|
||||||
CBus *Bus; // memory handlers
|
CBus *Bus; // memory handlers
|
||||||
int (*IRQAck)(int); // IRQ acknowledge callback
|
int (*IRQAck)(int); // IRQ acknowledge callback
|
||||||
unsigned char *musashiCtx; // holds CPU state
|
|
||||||
|
|
||||||
SM68KCtx(void)
|
SM68KCtx(void)
|
||||||
{
|
{
|
||||||
Bus = NULL;
|
Bus = NULL;
|
||||||
IRQAck = NULL;
|
IRQAck = NULL;
|
||||||
musashiCtx = new unsigned char[m68k_context_size()];
|
memset(&musashiCtx, 0, sizeof(musashiCtx)); // very important! garbage in context at reset can cause very strange bugs
|
||||||
memset(musashiCtx, 0, m68k_context_size()); // very important! garbage in context at reset can cause very strange bugs
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~SM68KCtx(void)
|
~SM68KCtx(void)
|
||||||
{
|
{
|
||||||
Bus = NULL;
|
Bus = NULL;
|
||||||
IRQAck = NULL;
|
IRQAck = NULL;
|
||||||
delete [] musashiCtx;
|
|
||||||
}
|
}
|
||||||
} M68KCtx;
|
} M68KCtx;
|
||||||
|
|
||||||
|
|
|
@ -836,63 +836,7 @@
|
||||||
/* =============================== PROTOTYPES ============================= */
|
/* =============================== PROTOTYPES ============================= */
|
||||||
/* ======================================================================== */
|
/* ======================================================================== */
|
||||||
|
|
||||||
typedef struct
|
#include "m68kctx.h"
|
||||||
{
|
|
||||||
uint cpu_type; /* CPU Type: 68000, 68008, 68010, 68EC020, or 68020 */
|
|
||||||
uint dar[16]; /* Data and Address Registers */
|
|
||||||
uint ppc; /* Previous program counter */
|
|
||||||
uint pc; /* Program Counter */
|
|
||||||
uint sp[7]; /* User, Interrupt, and Master Stack Pointers */
|
|
||||||
uint vbr; /* Vector Base Register (m68010+) */
|
|
||||||
uint sfc; /* Source Function Code Register (m68010+) */
|
|
||||||
uint dfc; /* Destination Function Code Register (m68010+) */
|
|
||||||
uint cacr; /* Cache Control Register (m68020, unemulated) */
|
|
||||||
uint caar; /* Cache Address Register (m68020, unemulated) */
|
|
||||||
uint ir; /* Instruction Register */
|
|
||||||
uint t1_flag; /* Trace 1 */
|
|
||||||
uint t0_flag; /* Trace 0 */
|
|
||||||
uint s_flag; /* Supervisor */
|
|
||||||
uint m_flag; /* Master/Interrupt state */
|
|
||||||
uint x_flag; /* Extend */
|
|
||||||
uint n_flag; /* Negative */
|
|
||||||
uint not_z_flag; /* Zero, inverted for speedups */
|
|
||||||
uint v_flag; /* Overflow */
|
|
||||||
uint c_flag; /* Carry */
|
|
||||||
uint int_mask; /* I0-I2 */
|
|
||||||
uint int_level; /* State of interrupt pins IPL0-IPL2 -- ASG: changed from ints_pending */
|
|
||||||
uint int_cycles; /* ASG: extra cycles from generated interrupts */
|
|
||||||
uint stopped; /* Stopped state */
|
|
||||||
uint pref_addr; /* Last prefetch address */
|
|
||||||
uint pref_data; /* Data in the prefetch queue */
|
|
||||||
uint address_mask; /* Available address pins */
|
|
||||||
uint sr_mask; /* Implemented status register bits */
|
|
||||||
uint instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */
|
|
||||||
uint run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */
|
|
||||||
|
|
||||||
/* Clocks required for instructions / exceptions */
|
|
||||||
uint cyc_bcc_notake_b;
|
|
||||||
uint cyc_bcc_notake_w;
|
|
||||||
uint cyc_dbcc_f_noexp;
|
|
||||||
uint cyc_dbcc_f_exp;
|
|
||||||
uint cyc_scc_r_true;
|
|
||||||
uint cyc_movem_w;
|
|
||||||
uint cyc_movem_l;
|
|
||||||
uint cyc_shift;
|
|
||||||
uint cyc_reset;
|
|
||||||
uint8* cyc_instruction;
|
|
||||||
uint8* cyc_exception;
|
|
||||||
|
|
||||||
/* Callbacks to host */
|
|
||||||
int (*int_ack_callback)(int int_line); /* Interrupt Acknowledge */
|
|
||||||
void (*bkpt_ack_callback)(unsigned int data); /* Breakpoint Acknowledge */
|
|
||||||
void (*reset_instr_callback)(void); /* Called when a RESET instruction is encountered */
|
|
||||||
void (*cmpild_instr_callback)(unsigned int, int); /* Called when a CMPI.L #v, Dn instruction is encountered */
|
|
||||||
void (*rte_instr_callback)(void); /* Called when a RTE instruction is encountered */
|
|
||||||
void (*pc_changed_callback)(unsigned int new_pc); /* Called when the PC changes by a large amount */
|
|
||||||
void (*set_fc_callback)(unsigned int new_fc); /* Called when the CPU function code changes */
|
|
||||||
void (*instr_hook_callback)(void); /* Called every instruction cycle prior to execution */
|
|
||||||
|
|
||||||
} m68ki_cpu_core;
|
|
||||||
|
|
||||||
|
|
||||||
extern m68ki_cpu_core m68ki_cpu;
|
extern m68ki_cpu_core m68ki_cpu;
|
||||||
|
@ -2010,7 +1954,9 @@ void m68ki_exception_interrupt(uint int_level)
|
||||||
INLINE void m68ki_check_interrupts(void)
|
INLINE void m68ki_check_interrupts(void)
|
||||||
{
|
{
|
||||||
if(CPU_INT_LEVEL > FLAG_INT_MASK)
|
if(CPU_INT_LEVEL > FLAG_INT_MASK)
|
||||||
|
{
|
||||||
m68ki_exception_interrupt(CPU_INT_LEVEL>>8);
|
m68ki_exception_interrupt(CPU_INT_LEVEL>>8);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
87
Src/CPU/68K/Musashi/m68kctx.h
Normal file
87
Src/CPU/68K/Musashi/m68kctx.h
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/**
|
||||||
|
** Supermodel
|
||||||
|
** A Sega Model 3 Arcade Emulator.
|
||||||
|
** Copyright 2011 Bart Trzynadlowski
|
||||||
|
**
|
||||||
|
** This file is part of Supermodel.
|
||||||
|
**
|
||||||
|
** Supermodel is free software: you can redistribute it and/or modify it under
|
||||||
|
** the terms of the GNU General Public License as published by the Free
|
||||||
|
** Software Foundation, either version 3 of the License, or (at your option)
|
||||||
|
** any later version.
|
||||||
|
**
|
||||||
|
** Supermodel is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
** more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU General Public License along
|
||||||
|
** with Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* m68kctx.h
|
||||||
|
*
|
||||||
|
* Musashi CPU context. This was made a separate file to more easily facilitate
|
||||||
|
* save state management. It is used internally by m68kcpu.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Types.h" // Supermodel types
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
UINT32 cpu_type; /* CPU Type: 68000, 68008, 68010, 68EC020, or 68020 */
|
||||||
|
UINT32 dar[16]; /* Data and Address Registers */
|
||||||
|
UINT32 ppc; /* Previous program counter */
|
||||||
|
UINT32 pc; /* Program Counter */
|
||||||
|
UINT32 sp[7]; /* User, Interrupt, and Master Stack Pointers */
|
||||||
|
UINT32 vbr; /* Vector Base Register (m68010+) */
|
||||||
|
UINT32 sfc; /* Source Function Code Register (m68010+) */
|
||||||
|
UINT32 dfc; /* Destination Function Code Register (m68010+) */
|
||||||
|
UINT32 cacr; /* Cache Control Register (m68020, unemulated) */
|
||||||
|
UINT32 caar; /* Cache Address Register (m68020, unemulated) */
|
||||||
|
UINT32 ir; /* Instruction Register */
|
||||||
|
UINT32 t1_flag; /* Trace 1 */
|
||||||
|
UINT32 t0_flag; /* Trace 0 */
|
||||||
|
UINT32 s_flag; /* Supervisor */
|
||||||
|
UINT32 m_flag; /* Master/Interrupt state */
|
||||||
|
UINT32 x_flag; /* Extend */
|
||||||
|
UINT32 n_flag; /* Negative */
|
||||||
|
UINT32 not_z_flag; /* Zero, inverted for speedups */
|
||||||
|
UINT32 v_flag; /* Overflow */
|
||||||
|
UINT32 c_flag; /* Carry */
|
||||||
|
UINT32 int_mask; /* I0-I2 */
|
||||||
|
UINT32 int_level; /* State of interrupt pins IPL0-IPL2 -- ASG: changed from ints_pending */
|
||||||
|
UINT32 int_cycles; /* ASG: extra cycles from generated interrupts */
|
||||||
|
UINT32 stopped; /* Stopped state */
|
||||||
|
UINT32 pref_addr; /* Last prefetch address */
|
||||||
|
UINT32 pref_data; /* Data in the prefetch queue */
|
||||||
|
UINT32 address_mask; /* Available address pins */
|
||||||
|
UINT32 sr_mask; /* Implemented status register bits */
|
||||||
|
UINT32 instr_mode; /* Stores whether we are in instruction mode or group 0/1 exception mode */
|
||||||
|
UINT32 run_mode; /* Stores whether we are processing a reset, bus error, address error, or something else */
|
||||||
|
|
||||||
|
/* Clocks required for instructions / exceptions */
|
||||||
|
UINT32 cyc_bcc_notake_b;
|
||||||
|
UINT32 cyc_bcc_notake_w;
|
||||||
|
UINT32 cyc_dbcc_f_noexp;
|
||||||
|
UINT32 cyc_dbcc_f_exp;
|
||||||
|
UINT32 cyc_scc_r_true;
|
||||||
|
UINT32 cyc_movem_w;
|
||||||
|
UINT32 cyc_movem_l;
|
||||||
|
UINT32 cyc_shift;
|
||||||
|
UINT32 cyc_reset;
|
||||||
|
UINT8* cyc_instruction;
|
||||||
|
UINT8* cyc_exception;
|
||||||
|
|
||||||
|
/* Callbacks to host */
|
||||||
|
int (*int_ack_callback)(int int_line); /* Interrupt Acknowledge */
|
||||||
|
void (*bkpt_ack_callback)(unsigned int data); /* Breakpoint Acknowledge */
|
||||||
|
void (*reset_instr_callback)(void); /* Called when a RESET instruction is encountered */
|
||||||
|
void (*cmpild_instr_callback)(unsigned int, int); /* Called when a CMPI.L #v, Dn instruction is encountered */
|
||||||
|
void (*rte_instr_callback)(void); /* Called when a RTE instruction is encountered */
|
||||||
|
void (*pc_changed_callback)(unsigned int new_pc); /* Called when the PC changes by a large amount */
|
||||||
|
void (*set_fc_callback)(unsigned int new_fc); /* Called when the CPU function code changes */
|
||||||
|
void (*instr_hook_callback)(void); /* Called every instruction cycle prior to execution */
|
||||||
|
|
||||||
|
} m68ki_cpu_core;
|
|
@ -509,10 +509,6 @@ void CDSB1::SaveState(CBlockFile *StateFile)
|
||||||
|
|
||||||
// Z80 CPU state
|
// Z80 CPU state
|
||||||
Z80.SaveState(StateFile, "DSB1 Z80");
|
Z80.SaveState(StateFile, "DSB1 Z80");
|
||||||
|
|
||||||
//DEBUG
|
|
||||||
//printf("usingMPEGStart=%X usingMPEGEnd=%X\n", usingMPEGStart, usingMPEGEnd);
|
|
||||||
//printf("usingLoopStart=%X usingLoopEnd=%X\n", usingLoopStart, usingLoopEnd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CDSB1::LoadState(CBlockFile *StateFile)
|
void CDSB1::LoadState(CBlockFile *StateFile)
|
||||||
|
@ -558,10 +554,6 @@ void CDSB1::LoadState(CBlockFile *StateFile)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
MPEG_StopPlaying();
|
MPEG_StopPlaying();
|
||||||
|
|
||||||
//DEBUG
|
|
||||||
//printf("usingMPEGStart=%X usingMPEGEnd=%X\n", usingMPEGStart, usingMPEGEnd);
|
|
||||||
//printf("usingLoopStart=%X usingLoopEnd=%X\n", usingLoopStart, usingLoopEnd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Offsets of memory regions within DSB1's pool
|
// Offsets of memory regions within DSB1's pool
|
||||||
|
@ -1075,6 +1067,7 @@ void CDSB2::SaveState(CBlockFile *StateFile)
|
||||||
M68KSaveState(StateFile, "DSB2 68K");
|
M68KSaveState(StateFile, "DSB2 68K");
|
||||||
|
|
||||||
//DEBUG
|
//DEBUG
|
||||||
|
//printf("DSB2 PC=%06X\n", M68KGetPC());
|
||||||
//printf("mpegStart=%X, mpegEnd=%X\n", mpegStart, mpegEnd);
|
//printf("mpegStart=%X, mpegEnd=%X\n", mpegStart, mpegEnd);
|
||||||
//printf("usingMPEGStart=%X, usingMPEGEnd=%X\n", usingMPEGStart, usingMPEGEnd);
|
//printf("usingMPEGStart=%X, usingMPEGEnd=%X\n", usingMPEGStart, usingMPEGEnd);
|
||||||
//printf("usingLoopStart=%X, usingLoopEnd=%X\n", usingLoopStart, usingLoopEnd);
|
//printf("usingLoopStart=%X, usingLoopEnd=%X\n", usingLoopStart, usingLoopEnd);
|
||||||
|
@ -1125,6 +1118,7 @@ void CDSB2::LoadState(CBlockFile *StateFile)
|
||||||
MPEG_StopPlaying();
|
MPEG_StopPlaying();
|
||||||
|
|
||||||
//DEBUG
|
//DEBUG
|
||||||
|
//printf("DSB2 PC=%06X\n", M68KGetPC());
|
||||||
//printf("mpegStart=%X, mpegEnd=%X\n", mpegStart, mpegEnd);
|
//printf("mpegStart=%X, mpegEnd=%X\n", mpegStart, mpegEnd);
|
||||||
//printf("usingMPEGStart=%X, usingMPEGEnd=%X\n", usingMPEGStart, usingMPEGEnd);
|
//printf("usingMPEGStart=%X, usingMPEGEnd=%X\n", usingMPEGStart, usingMPEGEnd);
|
||||||
//printf("usingLoopStart=%X, usingLoopEnd=%X\n", usingLoopStart, usingLoopEnd);
|
//printf("usingLoopStart=%X, usingLoopEnd=%X\n", usingLoopStart, usingLoopEnd);
|
||||||
|
|
|
@ -53,7 +53,7 @@ int m1fread(unsigned char *buf, int size1, int size2, void *f)
|
||||||
|
|
||||||
if (in_file) return fread(buf, size1, size2, (FILE *) f);
|
if (in_file) return fread(buf, size1, size2, (FILE *) f);
|
||||||
|
|
||||||
//printf("total=%X, offset=%X, end=%X\n", total, offset, end);
|
//printf("fstart=%X, total=%X, offset=%X, end=%X\n", fstart, total, offset, end);
|
||||||
|
|
||||||
// if past EOF
|
// if past EOF
|
||||||
if ((total + offset) >= end)
|
if ((total + offset) >= end)
|
||||||
|
|
Loading…
Reference in a new issue