mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-22 22:05:38 +00:00
- Added the Musashi 68K emulator by Karl Stenerud. Obtained Karl's explicit permission to relicense the code under GPL.
- Added a 68K interface, CPU/68K/M68K.*. - Moved Turbo68K source files to CPU/68K/Turbo68K. It is no longer used but is being retained in the source tree for now. The LSR instruction has not been fixed in this update. - Changed sound board code to use the new 68K interface (and hence, Musashi). - Changed version string from 0.2-WIP to 0.2a-WIP. This is still an alpha version. - Above changes have broken the 68K debugger.
This commit is contained in:
parent
95d61ce8bb
commit
c73cb830dc
|
@ -47,7 +47,7 @@ ENABLE_DEBUGGER = no
|
||||||
#
|
#
|
||||||
# Experimental sound code ('yes' on 32-bit builds only or 'no')
|
# Experimental sound code ('yes' on 32-bit builds only or 'no')
|
||||||
#
|
#
|
||||||
ENABLE_SOUND = no
|
ENABLE_SOUND = yes
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
@ -118,7 +118,7 @@ OUTFILE = $(BIN_DIR)\Supermodel.exe
|
||||||
CC = "$(VC_BIN)\cl.exe"
|
CC = "$(VC_BIN)\cl.exe"
|
||||||
LD = "$(VC_BIN)\link.exe"
|
LD = "$(VC_BIN)\link.exe"
|
||||||
COMPILER_FLAGS = /I "$(SDL_INCLUDEPATH)" /I "$(ZLIB_INCLUDEPATH)" /I "$(DIRECTX_INCLUDEPATH)" /I "Src\\" /I "Src\OSD\SDL\\" /Ox \
|
COMPILER_FLAGS = /I "$(SDL_INCLUDEPATH)" /I "$(ZLIB_INCLUDEPATH)" /I "$(DIRECTX_INCLUDEPATH)" /I "Src\\" /I "Src\OSD\SDL\\" /Ox \
|
||||||
/D "SUPERMODEL_WIN32" /D "GLEW_STATIC" /D "_MBCS" /D "_CRT_SECURE_NO_WARNINGS" /MT /Gy /W3 /nologo /c /Zi /GL
|
/D "SUPERMODEL_WIN32" /D "GLEW_STATIC" /D "_MBCS" /D "_CRT_SECURE_NO_WARNINGS" /MT /Gy /W3 /nologo /c /Zi /GL /D "DEBUG" /DEBUG
|
||||||
CFLAGS = $(COMPILER_FLAGS) /TC
|
CFLAGS = $(COMPILER_FLAGS) /TC
|
||||||
CPPFLAGS = $(COMPILER_FLAGS) /TP /EHsc
|
CPPFLAGS = $(COMPILER_FLAGS) /TP /EHsc
|
||||||
LFLAGS = /MACHINE:$(ARCH) $(ARCH_LIBS) /LIBPATH:"$(SDL_LIBPATH)" /LIBPATH:"$(ZLIB_LIBPATH)" /LIBPATH:"$(DIRECTX_LIBPATH)" /OUT:"$(OUTFILE)" \
|
LFLAGS = /MACHINE:$(ARCH) $(ARCH_LIBS) /LIBPATH:"$(SDL_LIBPATH)" /LIBPATH:"$(ZLIB_LIBPATH)" /LIBPATH:"$(DIRECTX_LIBPATH)" /OUT:"$(OUTFILE)" \
|
||||||
|
@ -129,7 +129,7 @@ OBJ_LIBS = kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.
|
||||||
#
|
#
|
||||||
# Turbo68K options
|
# Turbo68K options
|
||||||
#
|
#
|
||||||
MAKE68KFLAGS = -singleaddr
|
TURBO68K_FLAGS = -singleaddr
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -145,7 +145,7 @@ endif
|
||||||
# Add compiler flags for various options
|
# Add compiler flags for various options
|
||||||
ifeq ($(strip $(ENABLE_DEBUGGER)),yes)
|
ifeq ($(strip $(ENABLE_DEBUGGER)),yes)
|
||||||
COMPILER_FLAGS += /D "SUPERMODEL_DEBUGGER"
|
COMPILER_FLAGS += /D "SUPERMODEL_DEBUGGER"
|
||||||
MAKE68KFLAGS += -debug
|
TURBO68K_FLAGS += -debug
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(strip $(ENABLE_SOUND)),yes)
|
ifeq ($(strip $(ENABLE_SOUND)),yes)
|
||||||
|
@ -164,16 +164,12 @@ HEADERS = Src/Supermodel.h Src/OSD/SDL/Types.h
|
||||||
OBJ = $(OBJ_DIR)/PPCDisasm.obj $(OBJ_DIR)/Games.obj $(OBJ_DIR)/INIFile.obj $(OBJ_DIR)/BlockFile.obj $(OBJ_DIR)/93C46.obj \
|
OBJ = $(OBJ_DIR)/PPCDisasm.obj $(OBJ_DIR)/Games.obj $(OBJ_DIR)/INIFile.obj $(OBJ_DIR)/BlockFile.obj $(OBJ_DIR)/93C46.obj \
|
||||||
$(OBJ_DIR)/ROMLoad.obj $(OBJ_DIR)/unzip.obj $(OBJ_DIR)/ioapi.obj $(OBJ_DIR)/Error.obj $(OBJ_DIR)/glew.obj $(OBJ_DIR)/Shader.obj \
|
$(OBJ_DIR)/ROMLoad.obj $(OBJ_DIR)/unzip.obj $(OBJ_DIR)/ioapi.obj $(OBJ_DIR)/Error.obj $(OBJ_DIR)/glew.obj $(OBJ_DIR)/Shader.obj \
|
||||||
$(OBJ_DIR)/Real3D.obj $(OBJ_DIR)/Render3D.obj $(OBJ_DIR)/Models.obj $(OBJ_DIR)/Render2D.obj $(OBJ_DIR)/TileGen.obj \
|
$(OBJ_DIR)/Real3D.obj $(OBJ_DIR)/Render3D.obj $(OBJ_DIR)/Models.obj $(OBJ_DIR)/Render2D.obj $(OBJ_DIR)/TileGen.obj \
|
||||||
$(OBJ_DIR)/Model3.obj $(OBJ_DIR)/ppc.obj $(OBJ_DIR)/Main.obj $(OBJ_DIR)/SoundBoard.obj \
|
$(OBJ_DIR)/Model3.obj $(OBJ_DIR)/ppc.obj $(OBJ_DIR)/Main.obj $(OBJ_DIR)/SoundBoard.obj $(OBJ_DIR)/SCSP.obj $(OBJ_DIR)/SCSPDSP.obj $(OBJ_DIR)/M68K.obj\
|
||||||
|
$(OBJ_DIR)/m68kcpu.obj $(OBJ_DIR)/m68kopnz.obj $(OBJ_DIR)/m68kopdm.obj $(OBJ_DIR)/m68kopac.obj $(OBJ_DIR)/m68kops.obj \
|
||||||
$(OBJ_DIR)/IRQ.obj $(OBJ_DIR)/53C810.obj $(OBJ_DIR)/PCI.obj $(OBJ_DIR)/RTC72421.obj $(OBJ_DIR)/MPC10x.obj \
|
$(OBJ_DIR)/IRQ.obj $(OBJ_DIR)/53C810.obj $(OBJ_DIR)/PCI.obj $(OBJ_DIR)/RTC72421.obj $(OBJ_DIR)/MPC10x.obj \
|
||||||
$(OBJ_DIR)/Input.obj $(OBJ_DIR)/Inputs.obj $(OBJ_DIR)/InputSource.obj $(OBJ_DIR)/InputSystem.obj $(OBJ_DIR)/InputTypes.obj \
|
$(OBJ_DIR)/Input.obj $(OBJ_DIR)/Inputs.obj $(OBJ_DIR)/InputSource.obj $(OBJ_DIR)/InputSystem.obj $(OBJ_DIR)/InputTypes.obj \
|
||||||
$(OBJ_DIR)/MultiInputSource.obj $(OBJ_DIR)/SDLInputSystem.obj $(OBJ_DIR)/DirectInputSystem.obj
|
$(OBJ_DIR)/MultiInputSource.obj $(OBJ_DIR)/SDLInputSystem.obj $(OBJ_DIR)/DirectInputSystem.obj
|
||||||
|
|
||||||
# If sound enabled, include Turbo68K and SCSP code
|
|
||||||
ifeq ($(strip $(ENABLE_SOUND)),yes)
|
|
||||||
OBJ += $(OBJ_DIR)/Turbo68K.obj $(OBJ_DIR)/SCSP.obj $(OBJ_DIR)/SCSPDSP.obj
|
|
||||||
endif
|
|
||||||
|
|
||||||
# If built-in debugger enabled, include all debugging classes
|
# If built-in debugger enabled, include all debugging classes
|
||||||
ifeq ($(strip $(ENABLE_DEBUGGER)),yes)
|
ifeq ($(strip $(ENABLE_DEBUGGER)),yes)
|
||||||
OBJ += $(OBJ_DIR)/Debugger.obj $(OBJ_DIR)/ConsoleDebugger.obj $(OBJ_DIR)/SupermodelDebugger.obj $(OBJ_DIR)/CPUDebug.obj \
|
OBJ += $(OBJ_DIR)/Debugger.obj $(OBJ_DIR)/ConsoleDebugger.obj $(OBJ_DIR)/SupermodelDebugger.obj $(OBJ_DIR)/CPUDebug.obj \
|
||||||
|
@ -208,17 +204,51 @@ $(OBJ_DIR):
|
||||||
clean:
|
clean:
|
||||||
del $(OUTFILE)
|
del $(OUTFILE)
|
||||||
del $(OBJ_DIR)\*.obj
|
del $(OBJ_DIR)\*.obj
|
||||||
|
del $(OBJ_DIR)\*.c
|
||||||
|
del $(OBJ_DIR)\*.h
|
||||||
|
del $(OBJ_DIR)\*.exe
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Musashi 68K emulator
|
||||||
|
#
|
||||||
|
# All generated source files are emitted to the object directory. For MSVC,
|
||||||
|
# INLINE must be redefined as "static __inline", which is the syntax in C mode.
|
||||||
|
#
|
||||||
|
$(OBJ_DIR)/m68kmake.exe: Src/CPU/68K/Musashi/m68kmake.c
|
||||||
|
$(CC) $< $(CFLAGS) /Fo$(OBJ_DIR)/m68kmake.obj
|
||||||
|
$(LD) /OUT:$(OBJ_DIR)/m68kmake.exe /SUBSYSTEM:CONSOLE /NOLOGO /MANIFEST:NO /LTCG $(OBJ_DIR)/m68kmake.obj
|
||||||
|
|
||||||
|
$(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)/m68kcpu.obj: Src/CPU/68K/Musashi/m68kcpu.c $(OBJ_DIR)/m68kops.h Src/CPU/68K/Musashi/m68k.h Src/CPU/68K/Musashi/m68kconf.h
|
||||||
|
$(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
|
||||||
|
$(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
|
||||||
|
$(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
|
||||||
|
$(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
|
||||||
|
$(CC) $< $(CFLAGS) /Fo$(OBJ_DIR)/m68kopnz.obj /I "Src\CPU\68K\Musashi" /DINLINE="static __inline"
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Turbo68K
|
# Turbo68K
|
||||||
#
|
#
|
||||||
$(OBJ_DIR)/Make68K.exe: Src/CPU/68K/Make68K.c
|
# 32-bit only.
|
||||||
|
#
|
||||||
|
$(OBJ_DIR)/Make68K.exe: Src/CPU/68K/Turbo68K/Make68K.c
|
||||||
$(CC) $< $(CFLAGS) /Fo$(OBJ_DIR)/Make68K.obj
|
$(CC) $< $(CFLAGS) /Fo$(OBJ_DIR)/Make68K.obj
|
||||||
$(LD) /OUT:$(OBJ_DIR)/Make68K.exe /SUBSYSTEM:CONSOLE /NOLOGO /MANIFEST:NO /LTCG $(OBJ_DIR)/Make68K.obj
|
$(LD) /OUT:$(OBJ_DIR)/Make68K.exe /SUBSYSTEM:CONSOLE /NOLOGO /MANIFEST:NO /LTCG $(OBJ_DIR)/Make68K.obj
|
||||||
|
|
||||||
$(OBJ_DIR)/Turbo68K.obj: $(OBJ_DIR)/Make68K.exe
|
$(OBJ_DIR)/Turbo68K.obj: $(OBJ_DIR)/Make68K.exe
|
||||||
$(OBJ_DIR)/Make68K.exe $(OBJ_DIR)/Turbo68K.asm $(MAKE68KFLAGS)
|
$(OBJ_DIR)/Make68K.exe $(OBJ_DIR)/Turbo68K.asm $(TURBO68K_FLAGS)
|
||||||
nasm $(OBJ_DIR)/Turbo68K.asm -o $(OBJ_DIR)/Turbo68K.obj -f win32
|
nasm $(OBJ_DIR)/Turbo68K.asm -o $(OBJ_DIR)/Turbo68K.obj -f win32
|
||||||
|
|
||||||
|
|
||||||
|
@ -255,6 +285,9 @@ $(OBJ_DIR)/%.obj: Src/Debugger/CPU/%.cpp Src/Debugger/CPU/%.h $(HEADERS)
|
||||||
$(OBJ_DIR)/%.obj: Src/CPU/PowerPC/%.cpp Src/CPU/PowerPC/%.h Src/CPU/PowerPC/ppc603.c Src/CPU/PowerPC/ppc_ops.c $(HEADERS)
|
$(OBJ_DIR)/%.obj: Src/CPU/PowerPC/%.cpp Src/CPU/PowerPC/%.h Src/CPU/PowerPC/ppc603.c Src/CPU/PowerPC/ppc_ops.c $(HEADERS)
|
||||||
$(CC) $< $(CPPFLAGS) /Fo$(OBJ_DIR)/$(*F).obj
|
$(CC) $< $(CPPFLAGS) /Fo$(OBJ_DIR)/$(*F).obj
|
||||||
|
|
||||||
|
$(OBJ_DIR)/%.obj: Src/CPU/68K/%.cpp Src/CPU/68K/%.h $(HEADERS)
|
||||||
|
$(CC) $< $(CPPFLAGS) /Fo$(OBJ_DIR)/$(*F).obj
|
||||||
|
|
||||||
$(OBJ_DIR)/%.obj: Src/Inputs/%.cpp Src/Inputs/%.h $(HEADERS)
|
$(OBJ_DIR)/%.obj: Src/Inputs/%.cpp Src/Inputs/%.h $(HEADERS)
|
||||||
$(CC) $< $(CPPFLAGS) /Fo$(OBJ_DIR)/$(*F).obj
|
$(CC) $< $(CPPFLAGS) /Fo$(OBJ_DIR)/$(*F).obj
|
||||||
|
|
||||||
|
|
241
Src/CPU/68K/M68K.cpp
Normal file
241
Src/CPU/68K/M68K.cpp
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
/**
|
||||||
|
** 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/>.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68K.cpp
|
||||||
|
*
|
||||||
|
* 68K CPU interface. This is presently just a wrapper for the Musashi 68K core
|
||||||
|
* and therefore, only a single CPU is supported. In the future, we may want to
|
||||||
|
* add in another 68K core (eg., Turbo68K, A68K, or a recompiler).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Supermodel.h"
|
||||||
|
#include "Musashi/m68k.h" // Musashi 68K core
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
68K Interface
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
// Interface function pointers
|
||||||
|
static int (*IRQAck)(int nIRQ) = NULL;
|
||||||
|
static UINT8 (*Fetch8)(UINT32 addr) = NULL;
|
||||||
|
static UINT16 (*Fetch16)(UINT32 addr) = NULL;
|
||||||
|
static UINT32 (*Fetch32)(UINT32 addr) = NULL;
|
||||||
|
static UINT8 (*Read8)(UINT32 addr) = NULL;
|
||||||
|
static UINT16 (*Read16)(UINT32 addr) = NULL;
|
||||||
|
static UINT32 (*Read32)(UINT32 addr) = NULL;
|
||||||
|
static void (*Write8)(UINT32 addr, UINT8 data) = NULL;
|
||||||
|
static void (*Write16)(UINT32 addr, UINT16 data) = NULL;
|
||||||
|
static void (*Write32)(UINT32 addr, UINT32 data) = NULL;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
// CPU state
|
||||||
|
|
||||||
|
UINT32 M68KGetARegister(int n)
|
||||||
|
{
|
||||||
|
m68k_register_t r;
|
||||||
|
|
||||||
|
switch (n)
|
||||||
|
{
|
||||||
|
case 0: r = M68K_REG_A0; break;
|
||||||
|
case 1: r = M68K_REG_A1; break;
|
||||||
|
case 2: r = M68K_REG_A2; break;
|
||||||
|
case 3: r = M68K_REG_A3; break;
|
||||||
|
case 4: r = M68K_REG_A4; break;
|
||||||
|
case 5: r = M68K_REG_A5; break;
|
||||||
|
case 6: r = M68K_REG_A6; break;
|
||||||
|
case 7: r = M68K_REG_A7; break;
|
||||||
|
default: r = M68K_REG_A7; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m68k_get_reg(NULL, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 M68KGetDRegister(int n)
|
||||||
|
{
|
||||||
|
m68k_register_t r;
|
||||||
|
|
||||||
|
switch (n)
|
||||||
|
{
|
||||||
|
case 0: r = M68K_REG_D0; break;
|
||||||
|
case 1: r = M68K_REG_D1; break;
|
||||||
|
case 2: r = M68K_REG_D2; break;
|
||||||
|
case 3: r = M68K_REG_D3; break;
|
||||||
|
case 4: r = M68K_REG_D4; break;
|
||||||
|
case 5: r = M68K_REG_D5; break;
|
||||||
|
case 6: r = M68K_REG_D6; break;
|
||||||
|
case 7: r = M68K_REG_D7; break;
|
||||||
|
default: r = M68K_REG_D7; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m68k_get_reg(NULL, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT32 M68KGetPC(void)
|
||||||
|
{
|
||||||
|
return m68k_get_reg(NULL, M68K_REG_PC);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emulation functions
|
||||||
|
|
||||||
|
void M68KSetIRQ(int irqLevel)
|
||||||
|
{
|
||||||
|
m68k_set_irq(irqLevel);
|
||||||
|
}
|
||||||
|
|
||||||
|
int M68KRun(int numCycles)
|
||||||
|
{
|
||||||
|
return m68k_execute(numCycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
void M68KReset(void)
|
||||||
|
{
|
||||||
|
m68k_pulse_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback setup
|
||||||
|
|
||||||
|
void M68KSetIRQCallback(int (*F)(int nIRQ))
|
||||||
|
{
|
||||||
|
IRQAck = F;
|
||||||
|
}
|
||||||
|
|
||||||
|
void M68KSetFetch8Callback(UINT8 (*F)(UINT32))
|
||||||
|
{
|
||||||
|
Fetch8 = F;
|
||||||
|
}
|
||||||
|
|
||||||
|
void M68KSetFetch16Callback(UINT16 (*F)(UINT32))
|
||||||
|
{
|
||||||
|
Fetch16 = F;
|
||||||
|
}
|
||||||
|
|
||||||
|
void M68KSetFetch32Callback(UINT32 (*F)(UINT32))
|
||||||
|
{
|
||||||
|
Fetch32 = F;
|
||||||
|
}
|
||||||
|
|
||||||
|
void M68KSetRead8Callback(UINT8 (*F)(UINT32))
|
||||||
|
{
|
||||||
|
Read8 = F;
|
||||||
|
}
|
||||||
|
|
||||||
|
void M68KSetRead16Callback(UINT16 (*F)(UINT32))
|
||||||
|
{
|
||||||
|
Read16 = F;
|
||||||
|
}
|
||||||
|
|
||||||
|
void M68KSetRead32Callback(UINT32 (*F)(UINT32))
|
||||||
|
{
|
||||||
|
Read32 = F;
|
||||||
|
}
|
||||||
|
|
||||||
|
void M68KSetWrite8Callback(void (*F)(UINT32,UINT8))
|
||||||
|
{
|
||||||
|
Write8 = F;
|
||||||
|
}
|
||||||
|
|
||||||
|
void M68KSetWrite16Callback(void (*F)(UINT32,UINT16))
|
||||||
|
{
|
||||||
|
Write16 = F;
|
||||||
|
}
|
||||||
|
|
||||||
|
void M68KSetWrite32Callback(void (*F)(UINT32,UINT32))
|
||||||
|
{
|
||||||
|
Write32 = F;
|
||||||
|
}
|
||||||
|
|
||||||
|
// One-time initialization
|
||||||
|
|
||||||
|
BOOL M68KInit(void)
|
||||||
|
{
|
||||||
|
m68k_init();
|
||||||
|
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
|
||||||
|
m68k_set_int_ack_callback(M68KIRQCallback);
|
||||||
|
return OKAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
Musashi 68K Handlers
|
||||||
|
|
||||||
|
Musashi/m68kconf.h has been configured to call these directly.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
int M68KIRQCallback(int nIRQ)
|
||||||
|
{
|
||||||
|
if (NULL == IRQAck)
|
||||||
|
return M68K_IRQ_AUTOVECTOR;
|
||||||
|
else
|
||||||
|
return IRQAck(nIRQ);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int FASTCALL M68KFetch8(unsigned int a)
|
||||||
|
{
|
||||||
|
return Fetch8(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int FASTCALL M68KFetch16(unsigned int a)
|
||||||
|
{
|
||||||
|
return Fetch16(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int FASTCALL M68KFetch32(unsigned int a)
|
||||||
|
{
|
||||||
|
return Fetch32(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int FASTCALL M68KRead8(unsigned int a)
|
||||||
|
{
|
||||||
|
return Read8(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int FASTCALL M68KRead16(unsigned int a)
|
||||||
|
{
|
||||||
|
return Read16(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int FASTCALL M68KRead32(unsigned int a)
|
||||||
|
{
|
||||||
|
return Read32(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FASTCALL M68KWrite8(unsigned int a, unsigned int d)
|
||||||
|
{
|
||||||
|
Write8(a, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FASTCALL M68KWrite16(unsigned int a, unsigned int d)
|
||||||
|
{
|
||||||
|
Write16(a, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FASTCALL M68KWrite32(unsigned int a, unsigned int d)
|
||||||
|
{
|
||||||
|
Write32(a, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern "C"
|
252
Src/CPU/68K/M68K.h
Normal file
252
Src/CPU/68K/M68K.h
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
/**
|
||||||
|
** 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/>.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68K.h
|
||||||
|
*
|
||||||
|
* Header file for 68K CPU interface. Caution: there is only a single 68K core
|
||||||
|
* available to Supermodel right now. Therefore, multiple 68K CPUs are not
|
||||||
|
* presently supported. See M68K.c for more details.
|
||||||
|
*
|
||||||
|
* TO-DO List:
|
||||||
|
* -----------
|
||||||
|
* - Optimize things, perhaps by using FASTCALL
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef INCLUDED_M68K_H
|
||||||
|
#define INCLUDED_M68K_H
|
||||||
|
|
||||||
|
#include "Types.h"
|
||||||
|
#include "Musashi/m68k.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This doesn't work for now (needs to be added to the prototypes in m68k.h for m68k_read_memory*)
|
||||||
|
//#ifndef FASTCALL
|
||||||
|
#undef FASTCALL
|
||||||
|
#define FASTCALL
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
Definitions
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
// IRQ callback special return values
|
||||||
|
#define M68K_IRQ_AUTOVECTOR M68K_INT_ACK_AUTOVECTOR // signals an autovectored interrupt
|
||||||
|
#define M68K_IRQ_SPURIOUS M68K_INT_ACK_SPURIOUS // signals a spurious interrupt
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
68K Interface
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68KGetDRegister(int n):
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* n Register number (0-7).
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Register An.
|
||||||
|
*/
|
||||||
|
extern UINT32 M68KGetARegister(int n);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68KGetDRegister(int n):
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* n Register number (0-7).
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Register Dn.
|
||||||
|
*/
|
||||||
|
extern UINT32 M68KGetDRegister(int reg);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68KGetPC():
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Current program counter.
|
||||||
|
*/
|
||||||
|
extern UINT32 M68KGetPC(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68KSetIRQ(irqLevel):
|
||||||
|
*
|
||||||
|
* Sets the interrupt level (IPL2-IPL0 pins).
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* irqLevel The interrupt level (1-7) or 0 to clear the interrupt.
|
||||||
|
*/
|
||||||
|
extern void M68KSetIRQ(int irqLevel);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68KRun(numCycles):
|
||||||
|
*
|
||||||
|
* Runs the 68K.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* numCycles Number of cycles to run.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Number of cycles executed.
|
||||||
|
*/
|
||||||
|
extern int M68KRun(int numCycles);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68KReset():
|
||||||
|
*
|
||||||
|
* Resets the 68K.
|
||||||
|
*/
|
||||||
|
extern void M68KReset(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68KSetIRQCallback(F):
|
||||||
|
*
|
||||||
|
* Installs an interrupt acknowledge callback. The default behavior is to
|
||||||
|
* always assume autovectored interrupts.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* F Callback function.
|
||||||
|
*/
|
||||||
|
extern void M68KSetIRQCallback(int (*F)(int));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68KSetFetch8Callback(F):
|
||||||
|
* M68KSetFetch16Callback(F):
|
||||||
|
* M68KSetFetch32Callback(F):
|
||||||
|
* M68KSetRead8Callback(F):
|
||||||
|
* M68KSetRead16Callback(F):
|
||||||
|
* M68KSetRead32Callback(F):
|
||||||
|
* M68KSetWrite8Callback(F):
|
||||||
|
* M68KSetWrite16Callback(F):
|
||||||
|
* M68KSetWrite32Callback(F):
|
||||||
|
*
|
||||||
|
* Installs address space handler callbacks. There is no default behavior;
|
||||||
|
* these must all be set up before any 68K-related emulation functions are
|
||||||
|
* invoked.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* F Callback function.
|
||||||
|
*/
|
||||||
|
extern void M68KSetFetch8Callback(UINT8 (*F)(UINT32));
|
||||||
|
extern void M68KSetFetch16Callback(UINT16 (*F)(UINT32));
|
||||||
|
extern void M68KSetFetch32Callback(UINT32 (*F)(UINT32));
|
||||||
|
extern void M68KSetRead8Callback(UINT8 (*F)(UINT32));
|
||||||
|
extern void M68KSetRead16Callback(UINT16 (*F)(UINT32));
|
||||||
|
extern void M68KSetRead32Callback(UINT32 (*F)(UINT32));
|
||||||
|
extern void M68KSetWrite8Callback(void (*F)(UINT32,UINT8));
|
||||||
|
extern void M68KSetWrite16Callback(void (*F)(UINT32,UINT16));
|
||||||
|
extern void M68KSetWrite32Callback(void (*F)(UINT32,UINT32));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68KInit():
|
||||||
|
*
|
||||||
|
* Initializes the 68K emulator. Must be called once per program session prior
|
||||||
|
* to any other 68K interface calls.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* Always returns OKAY.
|
||||||
|
*/
|
||||||
|
extern BOOL M68KInit(void);
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
68K Handlers
|
||||||
|
|
||||||
|
Intended for use directly by the 68K core.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68KIRQCallback(nIRQ):
|
||||||
|
*
|
||||||
|
* Interrupt acknowledge callback. Called when an interrupt is being serviced.
|
||||||
|
* Actually implemented by calling a user-supplied callback.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* nIRQ IRQ level (1-7).
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* The interrupt vector to use, M68K_IRQ_AUTOVECTOR, or
|
||||||
|
* M68K_IRQ_SPURIOUS. If no callback has been installed, the default
|
||||||
|
* callback is used and always returns M68K_IRQ_AUTOVECTOR.
|
||||||
|
*/
|
||||||
|
extern int M68KIRQCallback(int nIRQ);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68KFetch8(a):
|
||||||
|
* M68KFetch16(a):
|
||||||
|
* M68KFetch32(a):
|
||||||
|
*
|
||||||
|
* Read data from the program address space.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* a Address to read from.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* The 8, 16, or 32-bit value read.
|
||||||
|
*/
|
||||||
|
unsigned int FASTCALL M68KFetch8(unsigned int a);
|
||||||
|
unsigned int FASTCALL M68KFetch16(unsigned int a);
|
||||||
|
unsigned int FASTCALL M68KFetch32(unsigned int a);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68KRead8(a):
|
||||||
|
* M68KRead16(a):
|
||||||
|
* M68KRead32(a):
|
||||||
|
*
|
||||||
|
* Read data from the data address space.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* a Address to read from.
|
||||||
|
*
|
||||||
|
* Returns:
|
||||||
|
* The 8, 16, or 32-bit value read.
|
||||||
|
*/
|
||||||
|
unsigned int FASTCALL M68KRead8(unsigned int a);
|
||||||
|
unsigned int FASTCALL M68KRead16(unsigned int a);
|
||||||
|
unsigned int FASTCALL M68KRead32(unsigned int a);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* M68KWrite8(a, d):
|
||||||
|
* M68KWrite16(a, d):
|
||||||
|
* M68KWrite32(a, d):
|
||||||
|
*
|
||||||
|
* Writes to the data address space.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
* a Address to write to.
|
||||||
|
* d Data to write.
|
||||||
|
*/
|
||||||
|
void FASTCALL M68KWrite8(unsigned int a, unsigned int d);
|
||||||
|
void FASTCALL M68KWrite16(unsigned int a, unsigned int d);
|
||||||
|
void FASTCALL M68KWrite32(unsigned int a, unsigned int d);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif // INCLUDED_M68K_H
|
395
Src/CPU/68K/Musashi/m68k.h
Normal file
395
Src/CPU/68K/Musashi/m68k.h
Normal file
|
@ -0,0 +1,395 @@
|
||||||
|
/**
|
||||||
|
** 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/>.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* m68k.h
|
||||||
|
*
|
||||||
|
* Header file for the Musashi 68K emulator.
|
||||||
|
*
|
||||||
|
* Permission was obtained from Karl Stenerud to apply the GPL license to this
|
||||||
|
* code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef M68K__HEADER
|
||||||
|
#define M68K__HEADER
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ========================= LICENSING & COPYRIGHT ======================== */
|
||||||
|
/* ======================================================================== */
|
||||||
|
/*
|
||||||
|
* MUSASHI
|
||||||
|
* Version 3.3
|
||||||
|
*
|
||||||
|
* A portable Motorola M680x0 processor emulation engine.
|
||||||
|
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code may be freely used for non-commercial purposes as long as this
|
||||||
|
* copyright notice remains unaltered in the source code and any binary files
|
||||||
|
* containing this code in compiled form.
|
||||||
|
*
|
||||||
|
* All other lisencing terms must be negotiated with the author
|
||||||
|
* (Karl Stenerud).
|
||||||
|
*
|
||||||
|
* The latest version of this code can be obtained at:
|
||||||
|
* http://kstenerud.cjb.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ============================ GENERAL DEFINES =========================== */
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
|
||||||
|
/* There are 7 levels of interrupt to the 68K.
|
||||||
|
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
|
||||||
|
*/
|
||||||
|
#define M68K_IRQ_NONE 0
|
||||||
|
#define M68K_IRQ_1 1
|
||||||
|
#define M68K_IRQ_2 2
|
||||||
|
#define M68K_IRQ_3 3
|
||||||
|
#define M68K_IRQ_4 4
|
||||||
|
#define M68K_IRQ_5 5
|
||||||
|
#define M68K_IRQ_6 6
|
||||||
|
#define M68K_IRQ_7 7
|
||||||
|
|
||||||
|
|
||||||
|
/* Special interrupt acknowledge values.
|
||||||
|
* Use these as special returns from the interrupt acknowledge callback
|
||||||
|
* (specified later in this header).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Causes an interrupt autovector (0x18 + interrupt level) to be taken.
|
||||||
|
* This happens in a real 68K if VPA or AVEC is asserted during an interrupt
|
||||||
|
* acknowledge cycle instead of DTACK.
|
||||||
|
*/
|
||||||
|
#define M68K_INT_ACK_AUTOVECTOR 0xffffffff
|
||||||
|
|
||||||
|
/* Causes the spurious interrupt vector (0x18) to be taken
|
||||||
|
* This happens in a real 68K if BERR is asserted during the interrupt
|
||||||
|
* acknowledge cycle (i.e. no devices responded to the acknowledge).
|
||||||
|
*/
|
||||||
|
#define M68K_INT_ACK_SPURIOUS 0xfffffffe
|
||||||
|
|
||||||
|
|
||||||
|
/* CPU types for use in m68k_set_cpu_type() */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
M68K_CPU_TYPE_INVALID,
|
||||||
|
M68K_CPU_TYPE_68000,
|
||||||
|
M68K_CPU_TYPE_68008,
|
||||||
|
M68K_CPU_TYPE_68010,
|
||||||
|
M68K_CPU_TYPE_68EC020,
|
||||||
|
M68K_CPU_TYPE_68020,
|
||||||
|
M68K_CPU_TYPE_68030, /* Supported by disassembler ONLY */
|
||||||
|
M68K_CPU_TYPE_68040 /* Supported by disassembler ONLY */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Registers used by m68k_get_reg() and m68k_set_reg() */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
/* Real registers */
|
||||||
|
M68K_REG_D0, /* Data registers */
|
||||||
|
M68K_REG_D1,
|
||||||
|
M68K_REG_D2,
|
||||||
|
M68K_REG_D3,
|
||||||
|
M68K_REG_D4,
|
||||||
|
M68K_REG_D5,
|
||||||
|
M68K_REG_D6,
|
||||||
|
M68K_REG_D7,
|
||||||
|
M68K_REG_A0, /* Address registers */
|
||||||
|
M68K_REG_A1,
|
||||||
|
M68K_REG_A2,
|
||||||
|
M68K_REG_A3,
|
||||||
|
M68K_REG_A4,
|
||||||
|
M68K_REG_A5,
|
||||||
|
M68K_REG_A6,
|
||||||
|
M68K_REG_A7,
|
||||||
|
M68K_REG_PC, /* Program Counter */
|
||||||
|
M68K_REG_SR, /* Status Register */
|
||||||
|
M68K_REG_SP, /* The current Stack Pointer (located in A7) */
|
||||||
|
M68K_REG_USP, /* User Stack Pointer */
|
||||||
|
M68K_REG_ISP, /* Interrupt Stack Pointer */
|
||||||
|
M68K_REG_MSP, /* Master Stack Pointer */
|
||||||
|
M68K_REG_SFC, /* Source Function Code */
|
||||||
|
M68K_REG_DFC, /* Destination Function Code */
|
||||||
|
M68K_REG_VBR, /* Vector Base Register */
|
||||||
|
M68K_REG_CACR, /* Cache Control Register */
|
||||||
|
M68K_REG_CAAR, /* Cache Address Register */
|
||||||
|
|
||||||
|
/* Assumed registers */
|
||||||
|
/* These are cheat registers which emulate the 1-longword prefetch
|
||||||
|
* present in the 68000 and 68010.
|
||||||
|
*/
|
||||||
|
M68K_REG_PREF_ADDR, /* Last prefetch address */
|
||||||
|
M68K_REG_PREF_DATA, /* Last prefetch data */
|
||||||
|
|
||||||
|
/* Convenience registers */
|
||||||
|
M68K_REG_PPC, /* Previous value in the program counter */
|
||||||
|
M68K_REG_IR, /* Instruction register */
|
||||||
|
M68K_REG_CPU_TYPE /* Type of CPU being run */
|
||||||
|
} m68k_register_t;
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ====================== FUNCTIONS CALLED BY THE CPU ===================== */
|
||||||
|
/* ======================================================================== */
|
||||||
|
|
||||||
|
/* You will have to implement these functions */
|
||||||
|
|
||||||
|
/* read/write functions called by the CPU to access memory.
|
||||||
|
* while values used are 32 bits, only the appropriate number
|
||||||
|
* of bits are relevant (i.e. in write_memory_8, only the lower 8 bits
|
||||||
|
* of value should be written to memory).
|
||||||
|
*
|
||||||
|
* NOTE: I have separated the immediate and PC-relative memory fetches
|
||||||
|
* from the other memory fetches because some systems require
|
||||||
|
* differentiation between PROGRAM and DATA fetches (usually
|
||||||
|
* for security setups such as encryption).
|
||||||
|
* This separation can either be achieved by setting
|
||||||
|
* M68K_SEPARATE_READS in m68kconf.h and defining
|
||||||
|
* the read functions, or by setting M68K_EMULATE_FC and
|
||||||
|
* making a function code callback function.
|
||||||
|
* Using the callback offers better emulation coverage
|
||||||
|
* because you can also monitor whether the CPU is in SYSTEM or
|
||||||
|
* USER mode, but it is also slower.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Read from anywhere */
|
||||||
|
unsigned int m68k_read_memory_8(unsigned int address);
|
||||||
|
unsigned int m68k_read_memory_16(unsigned int address);
|
||||||
|
unsigned int m68k_read_memory_32(unsigned int address);
|
||||||
|
|
||||||
|
/* Read data immediately following the PC */
|
||||||
|
unsigned int m68k_read_immediate_16(unsigned int address);
|
||||||
|
unsigned int m68k_read_immediate_32(unsigned int address);
|
||||||
|
|
||||||
|
/* Read data relative to the PC */
|
||||||
|
unsigned int m68k_read_pcrelative_8(unsigned int address);
|
||||||
|
unsigned int m68k_read_pcrelative_16(unsigned int address);
|
||||||
|
unsigned int m68k_read_pcrelative_32(unsigned int address);
|
||||||
|
|
||||||
|
/* Memory access for the disassembler */
|
||||||
|
unsigned int m68k_read_disassembler_8 (unsigned int address);
|
||||||
|
unsigned int m68k_read_disassembler_16 (unsigned int address);
|
||||||
|
unsigned int m68k_read_disassembler_32 (unsigned int address);
|
||||||
|
|
||||||
|
/* Write to anywhere */
|
||||||
|
void m68k_write_memory_8(unsigned int address, unsigned int value);
|
||||||
|
void m68k_write_memory_16(unsigned int address, unsigned int value);
|
||||||
|
void m68k_write_memory_32(unsigned int address, unsigned int value);
|
||||||
|
|
||||||
|
/* Special call to simulate undocumented 68k behavior when move.l with a
|
||||||
|
* predecrement destination mode is executed.
|
||||||
|
* To simulate real 68k behavior, first write the high word to
|
||||||
|
* [address+2], and then write the low word to [address].
|
||||||
|
*
|
||||||
|
* Enable this functionality with M68K_SIMULATE_PD_WRITES in m68kconf.h.
|
||||||
|
*/
|
||||||
|
void m68k_write_memory_32_pd(unsigned int address, unsigned int value);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ============================== CALLBACKS =============================== */
|
||||||
|
/* ======================================================================== */
|
||||||
|
|
||||||
|
/* These functions allow you to set callbacks to the host when specific events
|
||||||
|
* occur. Note that you must enable the corresponding value in m68kconf.h
|
||||||
|
* in order for these to do anything useful.
|
||||||
|
* Note: I have defined default callbacks which are used if you have enabled
|
||||||
|
* the corresponding #define in m68kconf.h but either haven't assigned a
|
||||||
|
* callback or have assigned a callback of NULL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Set the callback for an interrupt acknowledge.
|
||||||
|
* You must enable M68K_EMULATE_INT_ACK in m68kconf.h.
|
||||||
|
* The CPU will call the callback with the interrupt level being acknowledged.
|
||||||
|
* The host program must return either a vector from 0x02-0xff, or one of the
|
||||||
|
* special interrupt acknowledge values specified earlier in this header.
|
||||||
|
* If this is not implemented, the CPU will always assume an autovectored
|
||||||
|
* interrupt, and will automatically clear the interrupt request when it
|
||||||
|
* services the interrupt.
|
||||||
|
* Default behavior: return M68K_INT_ACK_AUTOVECTOR.
|
||||||
|
*/
|
||||||
|
void m68k_set_int_ack_callback(int (*callback)(int int_level));
|
||||||
|
|
||||||
|
|
||||||
|
/* Set the callback for a breakpoint acknowledge (68010+).
|
||||||
|
* You must enable M68K_EMULATE_BKPT_ACK in m68kconf.h.
|
||||||
|
* The CPU will call the callback with whatever was in the data field of the
|
||||||
|
* BKPT instruction for 68020+, or 0 for 68010.
|
||||||
|
* Default behavior: do nothing.
|
||||||
|
*/
|
||||||
|
void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data));
|
||||||
|
|
||||||
|
|
||||||
|
/* Set the callback for the RESET instruction.
|
||||||
|
* You must enable M68K_EMULATE_RESET in m68kconf.h.
|
||||||
|
* The CPU calls this callback every time it encounters a RESET instruction.
|
||||||
|
* Default behavior: do nothing.
|
||||||
|
*/
|
||||||
|
void m68k_set_reset_instr_callback(void (*callback)(void));
|
||||||
|
|
||||||
|
|
||||||
|
/* Set the callback for the CMPI.L #v, Dn instruction.
|
||||||
|
* You must enable M68K_CMPILD_HAS_CALLBACK in m68kconf.h.
|
||||||
|
* The CPU calls this callback every time it encounters a CMPI.L #v, Dn instruction.
|
||||||
|
* Default behavior: do nothing.
|
||||||
|
*/
|
||||||
|
void m68k_set_cmpild_instr_callback(void (*callback)(unsigned int val, int reg));
|
||||||
|
|
||||||
|
|
||||||
|
/* Set the callback for the RTE instruction.
|
||||||
|
* You must enable M68K_RTE_HAS_CALLBACK in m68kconf.h.
|
||||||
|
* The CPU calls this callback every time it encounters a RTE instruction.
|
||||||
|
* Default behavior: do nothing.
|
||||||
|
*/
|
||||||
|
void m68k_set_rte_instr_callback(void (*callback)(void));
|
||||||
|
|
||||||
|
|
||||||
|
/* Set the callback for informing of a large PC change.
|
||||||
|
* You must enable M68K_MONITOR_PC in m68kconf.h.
|
||||||
|
* The CPU calls this callback with the new PC value every time the PC changes
|
||||||
|
* by a large value (currently set for changes by longwords).
|
||||||
|
* Default behavior: do nothing.
|
||||||
|
*/
|
||||||
|
void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc));
|
||||||
|
|
||||||
|
|
||||||
|
/* Set the callback for CPU function code changes.
|
||||||
|
* You must enable M68K_EMULATE_FC in m68kconf.h.
|
||||||
|
* The CPU calls this callback with the function code before every memory
|
||||||
|
* access to set the CPU's function code according to what kind of memory
|
||||||
|
* access it is (supervisor/user, program/data and such).
|
||||||
|
* Default behavior: do nothing.
|
||||||
|
*/
|
||||||
|
void m68k_set_fc_callback(void (*callback)(unsigned int new_fc));
|
||||||
|
|
||||||
|
|
||||||
|
/* Set a callback for the instruction cycle of the CPU.
|
||||||
|
* You must enable M68K_INSTRUCTION_HOOK in m68kconf.h.
|
||||||
|
* The CPU calls this callback just before fetching the opcode in the
|
||||||
|
* instruction cycle.
|
||||||
|
* Default behavior: do nothing.
|
||||||
|
*/
|
||||||
|
void m68k_set_instr_hook_callback(void (*callback)(void));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ====================== FUNCTIONS TO ACCESS THE CPU ===================== */
|
||||||
|
/* ======================================================================== */
|
||||||
|
|
||||||
|
/* Use this function to set the CPU type you want to emulate.
|
||||||
|
* Currently supported types are: M68K_CPU_TYPE_68000, M68K_CPU_TYPE_68008,
|
||||||
|
* M68K_CPU_TYPE_68010, M68K_CPU_TYPE_EC020, and M68K_CPU_TYPE_68020.
|
||||||
|
*/
|
||||||
|
void m68k_set_cpu_type(unsigned int cpu_type);
|
||||||
|
|
||||||
|
/* Do whatever initialisations the core requires. Should be called
|
||||||
|
* at least once at init time.
|
||||||
|
*/
|
||||||
|
void m68k_init(void);
|
||||||
|
|
||||||
|
/* Pulse the RESET pin on the CPU.
|
||||||
|
* You *MUST* reset the CPU at least once to initialize the emulation
|
||||||
|
* Note: If you didn't call m68k_set_cpu_type() before resetting
|
||||||
|
* the CPU for the first time, the CPU will be set to
|
||||||
|
* M68K_CPU_TYPE_68000.
|
||||||
|
*/
|
||||||
|
void m68k_pulse_reset(void);
|
||||||
|
|
||||||
|
/* execute num_cycles worth of instructions. returns number of cycles used */
|
||||||
|
int m68k_execute(int num_cycles);
|
||||||
|
|
||||||
|
/* These functions let you read/write/modify the number of cycles left to run
|
||||||
|
* while m68k_execute() is running.
|
||||||
|
* These are useful if the 68k accesses a memory-mapped port on another device
|
||||||
|
* that requires immediate processing by another CPU.
|
||||||
|
*/
|
||||||
|
int m68k_cycles_run(void); /* Number of cycles run so far */
|
||||||
|
int m68k_cycles_remaining(void); /* Number of cycles left */
|
||||||
|
void m68k_modify_timeslice(int cycles); /* Modify cycles left */
|
||||||
|
void m68k_end_timeslice(void); /* End timeslice now */
|
||||||
|
|
||||||
|
/* Set the IPL0-IPL2 pins on the CPU (IRQ).
|
||||||
|
* A transition from < 7 to 7 will cause a non-maskable interrupt (NMI).
|
||||||
|
* Setting IRQ to 0 will clear an interrupt request.
|
||||||
|
*/
|
||||||
|
void m68k_set_irq(unsigned int int_level);
|
||||||
|
|
||||||
|
|
||||||
|
/* Halt the CPU as if you pulsed the HALT pin. */
|
||||||
|
void m68k_pulse_halt(void);
|
||||||
|
|
||||||
|
|
||||||
|
/* Context switching to allow multiple CPUs */
|
||||||
|
|
||||||
|
/* Get the size of the cpu context in bytes */
|
||||||
|
unsigned int m68k_context_size(void);
|
||||||
|
|
||||||
|
/* Get a cpu context */
|
||||||
|
unsigned int m68k_get_context(void* dst);
|
||||||
|
|
||||||
|
/* set the current cpu context */
|
||||||
|
void m68k_set_context(void* dst);
|
||||||
|
|
||||||
|
/* Register the CPU state information */
|
||||||
|
void m68k_state_register(const char *type);
|
||||||
|
|
||||||
|
|
||||||
|
/* Peek at the internals of a CPU context. This can either be a context
|
||||||
|
* retrieved using m68k_get_context() or the currently running context.
|
||||||
|
* If context is NULL, the currently running CPU context will be used.
|
||||||
|
*/
|
||||||
|
unsigned int m68k_get_reg(void* context, m68k_register_t reg);
|
||||||
|
|
||||||
|
/* Poke values into the internals of the currently running CPU context */
|
||||||
|
void m68k_set_reg(m68k_register_t reg, unsigned int value);
|
||||||
|
|
||||||
|
/* Check if an instruction is valid for the specified CPU type */
|
||||||
|
unsigned int m68k_is_valid_instruction(unsigned int instruction, unsigned int cpu_type);
|
||||||
|
|
||||||
|
/* Disassemble 1 instruction using the epecified CPU type at pc. Stores
|
||||||
|
* disassembly in str_buff and returns the size of the instruction in bytes.
|
||||||
|
*/
|
||||||
|
unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_type);
|
||||||
|
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ============================= CONFIGURATION ============================ */
|
||||||
|
/* ======================================================================== */
|
||||||
|
|
||||||
|
/* Import the configuration for this build */
|
||||||
|
#include "m68kconf.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ============================== END OF FILE ============================= */
|
||||||
|
/* ======================================================================== */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* M68K__HEADER */
|
10489
Src/CPU/68K/Musashi/m68k_in.c
Normal file
10489
Src/CPU/68K/Musashi/m68k_in.c
Normal file
File diff suppressed because it is too large
Load diff
237
Src/CPU/68K/Musashi/m68kconf.h
Normal file
237
Src/CPU/68K/Musashi/m68kconf.h
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
/**
|
||||||
|
** 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/>.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* m68kconf.h
|
||||||
|
*
|
||||||
|
* Musashi configuration.
|
||||||
|
*
|
||||||
|
* Permission was obtained from Karl Stenerud to apply the GPL license to this
|
||||||
|
* code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ========================= LICENSING & COPYRIGHT ======================== */
|
||||||
|
/* ======================================================================== */
|
||||||
|
/*
|
||||||
|
* MUSASHI
|
||||||
|
* Version 3.3
|
||||||
|
*
|
||||||
|
* A portable Motorola M680x0 processor emulation engine.
|
||||||
|
* Copyright 1998-2001 Karl Stenerud. All rights reserved.
|
||||||
|
*
|
||||||
|
* This code may be freely used for non-commercial purposes as long as this
|
||||||
|
* copyright notice remains unaltered in the source code and any binary files
|
||||||
|
* containing this code in compiled form.
|
||||||
|
*
|
||||||
|
* All other lisencing terms must be negotiated with the author
|
||||||
|
* (Karl Stenerud).
|
||||||
|
*
|
||||||
|
* The latest version of this code can be obtained at:
|
||||||
|
* http://kstenerud.cjb.net
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef M68KCONF__HEADER
|
||||||
|
#define M68KCONF__HEADER
|
||||||
|
|
||||||
|
#define M68K_COMPILE_FOR_MAME OPT_OFF
|
||||||
|
|
||||||
|
/* Configuration switches.
|
||||||
|
* Use OPT_SPECIFY_HANDLER for configuration options that allow callbacks.
|
||||||
|
* OPT_SPECIFY_HANDLER causes the core to link directly to the function
|
||||||
|
* or macro you specify, rather than using callback functions whose pointer
|
||||||
|
* must be passed in using m68k_set_xxx_callback().
|
||||||
|
*/
|
||||||
|
#define OPT_OFF 0
|
||||||
|
#define OPT_ON 1
|
||||||
|
#define OPT_SPECIFY_HANDLER 2
|
||||||
|
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ============================= CONFIGURATION ============================ */
|
||||||
|
/* ======================================================================== */
|
||||||
|
|
||||||
|
/* Turn ON if you want to use the following M68K variants */
|
||||||
|
#define M68K_EMULATE_008 OPT_OFF
|
||||||
|
#define M68K_EMULATE_010 OPT_OFF
|
||||||
|
#define M68K_EMULATE_EC020 OPT_OFF
|
||||||
|
#define M68K_EMULATE_020 OPT_OFF
|
||||||
|
|
||||||
|
|
||||||
|
/* If ON, the CPU will call m68k_read_immediate_xx() for immediate addressing
|
||||||
|
* and m68k_read_pcrelative_xx() for PC-relative addressing.
|
||||||
|
* If off, all read requests from the CPU will be redirected to m68k_read_xx()
|
||||||
|
*/
|
||||||
|
#define M68K_SEPARATE_READS OPT_OFF
|
||||||
|
|
||||||
|
/* If ON, the CPU will call m68k_write_32_pd() when it executes move.l with a
|
||||||
|
* predecrement destination EA mode instead of m68k_write_32().
|
||||||
|
* To simulate real 68k behavior, m68k_write_32_pd() must first write the high
|
||||||
|
* word to [address+2], and then write the low word to [address].
|
||||||
|
*/
|
||||||
|
#define M68K_SIMULATE_PD_WRITES OPT_OFF
|
||||||
|
|
||||||
|
/* If ON, CPU will call the interrupt acknowledge callback when it services an
|
||||||
|
* interrupt.
|
||||||
|
* If off, all interrupts will be autovectored and all interrupt requests will
|
||||||
|
* auto-clear when the interrupt is serviced.
|
||||||
|
*/
|
||||||
|
#define M68K_EMULATE_INT_ACK OPT_SPECIFY_HANDLER
|
||||||
|
#define M68K_INT_ACK_CALLBACK(A) M68KIRQCallback(A)
|
||||||
|
|
||||||
|
|
||||||
|
/* If ON, CPU will call the breakpoint acknowledge callback when it encounters
|
||||||
|
* a breakpoint instruction and it is running a 68010+.
|
||||||
|
*/
|
||||||
|
#define M68K_EMULATE_BKPT_ACK OPT_OFF
|
||||||
|
#define M68K_BKPT_ACK_CALLBACK() your_bkpt_ack_handler_function()
|
||||||
|
|
||||||
|
|
||||||
|
/* If ON, the CPU will monitor the trace flags and take trace exceptions
|
||||||
|
*/
|
||||||
|
#define M68K_EMULATE_TRACE OPT_OFF
|
||||||
|
|
||||||
|
|
||||||
|
/* If ON, CPU will call the output reset callback when it encounters a reset
|
||||||
|
* instruction.
|
||||||
|
*/
|
||||||
|
#define M68K_EMULATE_RESET OPT_OFF
|
||||||
|
#define M68K_RESET_CALLBACK() M68KResetCallback()
|
||||||
|
|
||||||
|
|
||||||
|
/* If ON, CPU will call the callback when it encounters a cmpi.l #v, dn
|
||||||
|
* instruction.
|
||||||
|
*/
|
||||||
|
#define M68K_CMPILD_HAS_CALLBACK OPT_OFF
|
||||||
|
#define M68K_CMPILD_CALLBACK(v,r) your_cmpild_handler_function(v,r)
|
||||||
|
|
||||||
|
/* If ON, CPU will call the callback when it encounters a rte
|
||||||
|
* instruction.
|
||||||
|
*/
|
||||||
|
#define M68K_RTE_HAS_CALLBACK OPT_OFF
|
||||||
|
#define M68K_RTE_CALLBACK() your_rte_handler_function()
|
||||||
|
|
||||||
|
|
||||||
|
/* If ON, CPU will call the set fc callback on every memory access to
|
||||||
|
* differentiate between user/supervisor, program/data access like a real
|
||||||
|
* 68000 would. This should be enabled and the callback should be set if you
|
||||||
|
* want to properly emulate the m68010 or higher. (moves uses function codes
|
||||||
|
* to read/write data from different address spaces)
|
||||||
|
*/
|
||||||
|
#define M68K_EMULATE_FC OPT_OFF
|
||||||
|
#define M68K_SET_FC_CALLBACK(A) your_set_fc_handler_function(A)
|
||||||
|
|
||||||
|
|
||||||
|
/* If ON, CPU will call the pc changed callback when it changes the PC by a
|
||||||
|
* large value. This allows host programs to be nicer when it comes to
|
||||||
|
* fetching immediate data and instructions on a banked memory system.
|
||||||
|
*/
|
||||||
|
#define M68K_MONITOR_PC OPT_OFF
|
||||||
|
#define M68K_SET_PC_CALLBACK(A) your_pc_changed_handler_function(A)
|
||||||
|
|
||||||
|
|
||||||
|
/* If ON, CPU will call the instruction hook callback before every
|
||||||
|
* instruction.
|
||||||
|
*/
|
||||||
|
#define M68K_INSTRUCTION_HOOK OPT_OFF
|
||||||
|
#define M68K_INSTRUCTION_CALLBACK() your_instruction_hook_function()
|
||||||
|
|
||||||
|
|
||||||
|
/* If ON, the CPU will emulate the 4-byte prefetch queue of a real 68000 */
|
||||||
|
#define M68K_EMULATE_PREFETCH OPT_OFF
|
||||||
|
|
||||||
|
|
||||||
|
/* If ON, the CPU will generate address error exceptions if it tries to
|
||||||
|
* access a word or longword at an odd address.
|
||||||
|
* NOTE: This is only emulated properly for 68000 mode.
|
||||||
|
*/
|
||||||
|
#define M68K_EMULATE_ADDRESS_ERROR OPT_OFF
|
||||||
|
|
||||||
|
|
||||||
|
/* Turn ON to enable logging of illegal instruction calls.
|
||||||
|
* M68K_LOG_FILEHANDLE must be #defined to a stdio file stream.
|
||||||
|
* Turn on M68K_LOG_1010_1111 to log all 1010 and 1111 calls.
|
||||||
|
*/
|
||||||
|
#define M68K_LOG_ENABLE OPT_OFF
|
||||||
|
#define M68K_LOG_1010_1111 OPT_OFF
|
||||||
|
#define M68K_LOG_FILEHANDLE some_file_handle
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------------- COMPATIBILITY ---------------------------- */
|
||||||
|
|
||||||
|
/* The following options set optimizations that violate the current ANSI
|
||||||
|
* standard, but will be compliant under the forthcoming C9X standard.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* If ON, the enulation core will use 64-bit integers to speed up some
|
||||||
|
* operations.
|
||||||
|
*/
|
||||||
|
#define M68K_USE_64_BIT OPT_ON
|
||||||
|
|
||||||
|
|
||||||
|
/* Set to your compiler's static inline keyword to enable it, or
|
||||||
|
* set it to blank to disable it.
|
||||||
|
* If you define INLINE in the makefile, it will override this value.
|
||||||
|
* NOTE: not enabling inline functions will SEVERELY slow down emulation.
|
||||||
|
*/
|
||||||
|
#ifndef INLINE
|
||||||
|
#define INLINE static __inline__ // defined for GCC; if using MSVC, pass INLINE as "static __inline" from Makefile
|
||||||
|
#endif /* INLINE */
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
Supermodel Interface
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "../M68K.h" // Supermodel's 68K interface
|
||||||
|
|
||||||
|
/* Read data relative to the PC */
|
||||||
|
#define m68k_read_pcrelative_8(address) M68KFetch8(address)
|
||||||
|
#define m68k_read_pcrelative_16(address) M68KFetch16(address)
|
||||||
|
#define m68k_read_pcrelative_32(address) M68KFetch32(address)
|
||||||
|
|
||||||
|
/* Read data immediately following the PC */
|
||||||
|
#define m68k_read_immediate_16(address) M68KFetch16(address)
|
||||||
|
#define m68k_read_immediate_32(address) M68KFetch32(address)
|
||||||
|
|
||||||
|
/* Memory access for the disassembler */
|
||||||
|
#define m68k_read_disassembler_8(address) M68KRead8(address)
|
||||||
|
#define m68k_read_disassembler_16(address) M68KRead16(address)
|
||||||
|
#define m68k_read_disassembler_32(address) M68KRead32(address)
|
||||||
|
|
||||||
|
/* Read from anywhere */
|
||||||
|
#define m68k_read_memory_8(address) M68KRead8(address)
|
||||||
|
#define m68k_read_memory_16(address) M68KRead16(address)
|
||||||
|
#define m68k_read_memory_32(address) M68KRead32(address)
|
||||||
|
|
||||||
|
/* Write to anywhere */
|
||||||
|
#define m68k_write_memory_8(address, value) M68KWrite8(address, value)
|
||||||
|
#define m68k_write_memory_16(address, value) M68KWrite16(address, value)
|
||||||
|
#define m68k_write_memory_32(address, value) M68KWrite32(address, value)
|
||||||
|
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ============================== END OF FILE ============================= */
|
||||||
|
/* ======================================================================== */
|
||||||
|
|
||||||
|
#endif /* M68KCONF__HEADER */
|
953
Src/CPU/68K/Musashi/m68kcpu.c
Normal file
953
Src/CPU/68K/Musashi/m68kcpu.c
Normal file
|
@ -0,0 +1,953 @@
|
||||||
|
/**
|
||||||
|
** 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/>.
|
||||||
|
**/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* m68kcpu.c
|
||||||
|
*
|
||||||
|
* Musashi core functions and interface.
|
||||||
|
*
|
||||||
|
* Permission was obtained from Karl Stenerud to apply the GPL license to this
|
||||||
|
* code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ========================= LICENSING & COPYRIGHT ======================== */
|
||||||
|
/* ======================================================================== */
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
static const char* copyright_notice =
|
||||||
|
"MUSASHI\n"
|
||||||
|
"Version 3.3 (2001-01-29)\n"
|
||||||
|
"A portable Motorola M680x0 processor emulation engine.\n"
|
||||||
|
"Copyright 1998-2001 Karl Stenerud. All rights reserved.\n"
|
||||||
|
"\n"
|
||||||
|
"This code may be freely used for non-commercial purpooses as long as this\n"
|
||||||
|
"copyright notice remains unaltered in the source code and any binary files\n"
|
||||||
|
"containing this code in compiled form.\n"
|
||||||
|
"\n"
|
||||||
|
"All other lisencing terms must be negotiated with the author\n"
|
||||||
|
"(Karl Stenerud).\n"
|
||||||
|
"\n"
|
||||||
|
"The latest version of this code can be obtained at:\n"
|
||||||
|
"http://kstenerud.cjb.net\n"
|
||||||
|
;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ================================= NOTES ================================ */
|
||||||
|
/* ======================================================================== */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ================================ INCLUDES ============================== */
|
||||||
|
/* ======================================================================== */
|
||||||
|
|
||||||
|
#include "m68kops.h"
|
||||||
|
#include "m68kcpu.h"
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ================================= DATA ================================= */
|
||||||
|
/* ======================================================================== */
|
||||||
|
|
||||||
|
int m68ki_initial_cycles;
|
||||||
|
int m68ki_remaining_cycles = 0; /* Number of clocks remaining */
|
||||||
|
uint m68ki_tracing = 0;
|
||||||
|
uint m68ki_address_space;
|
||||||
|
|
||||||
|
#ifdef M68K_LOG_ENABLE
|
||||||
|
const char* m68ki_cpu_names[] =
|
||||||
|
{
|
||||||
|
"Invalid CPU",
|
||||||
|
"M68000",
|
||||||
|
"M68008",
|
||||||
|
"Invalid CPU",
|
||||||
|
"M68010",
|
||||||
|
"Invalid CPU",
|
||||||
|
"Invalid CPU",
|
||||||
|
"Invalid CPU",
|
||||||
|
"M68EC020",
|
||||||
|
"Invalid CPU",
|
||||||
|
"Invalid CPU",
|
||||||
|
"Invalid CPU",
|
||||||
|
"Invalid CPU",
|
||||||
|
"Invalid CPU",
|
||||||
|
"Invalid CPU",
|
||||||
|
"Invalid CPU",
|
||||||
|
"M68020"
|
||||||
|
};
|
||||||
|
#endif /* M68K_LOG_ENABLE */
|
||||||
|
|
||||||
|
/* The CPU core */
|
||||||
|
m68ki_cpu_core m68ki_cpu = {0};
|
||||||
|
|
||||||
|
#if M68K_EMULATE_ADDRESS_ERROR
|
||||||
|
jmp_buf m68ki_aerr_trap;
|
||||||
|
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||||
|
|
||||||
|
uint m68ki_aerr_address;
|
||||||
|
uint m68ki_aerr_write_mode;
|
||||||
|
uint m68ki_aerr_fc;
|
||||||
|
|
||||||
|
/* Used by shift & rotate instructions */
|
||||||
|
uint8 m68ki_shift_8_table[65] =
|
||||||
|
{
|
||||||
|
0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff, 0xff
|
||||||
|
};
|
||||||
|
uint16 m68ki_shift_16_table[65] =
|
||||||
|
{
|
||||||
|
0x0000, 0x8000, 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00,
|
||||||
|
0xff80, 0xffc0, 0xffe0, 0xfff0, 0xfff8, 0xfffc, 0xfffe, 0xffff, 0xffff,
|
||||||
|
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||||
|
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||||
|
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||||
|
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||||
|
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
|
||||||
|
0xffff, 0xffff
|
||||||
|
};
|
||||||
|
uint m68ki_shift_32_table[65] =
|
||||||
|
{
|
||||||
|
0x00000000, 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000, 0xf8000000,
|
||||||
|
0xfc000000, 0xfe000000, 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
|
||||||
|
0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000, 0xffff8000,
|
||||||
|
0xffffc000, 0xffffe000, 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
|
||||||
|
0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0, 0xfffffff8,
|
||||||
|
0xfffffffc, 0xfffffffe, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||||
|
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||||
|
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||||
|
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||||
|
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
|
||||||
|
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Number of clock cycles to use for exception processing.
|
||||||
|
* I used 4 for any vectors that are undocumented for processing times.
|
||||||
|
*/
|
||||||
|
uint8 m68ki_exception_cycle_table[3][256] =
|
||||||
|
{
|
||||||
|
{ /* 000 */
|
||||||
|
4, /* 0: Reset - Initial Stack Pointer */
|
||||||
|
4, /* 1: Reset - Initial Program Counter */
|
||||||
|
50, /* 2: Bus Error (unemulated) */
|
||||||
|
50, /* 3: Address Error (unemulated) */
|
||||||
|
34, /* 4: Illegal Instruction */
|
||||||
|
38, /* 5: Divide by Zero -- ASG: changed from 42 */
|
||||||
|
40, /* 6: CHK -- ASG: chanaged from 44 */
|
||||||
|
34, /* 7: TRAPV */
|
||||||
|
34, /* 8: Privilege Violation */
|
||||||
|
34, /* 9: Trace */
|
||||||
|
4, /* 10: 1010 */
|
||||||
|
4, /* 11: 1111 */
|
||||||
|
4, /* 12: RESERVED */
|
||||||
|
4, /* 13: Coprocessor Protocol Violation (unemulated) */
|
||||||
|
4, /* 14: Format Error */
|
||||||
|
44, /* 15: Uninitialized Interrupt */
|
||||||
|
4, /* 16: RESERVED */
|
||||||
|
4, /* 17: RESERVED */
|
||||||
|
4, /* 18: RESERVED */
|
||||||
|
4, /* 19: RESERVED */
|
||||||
|
4, /* 20: RESERVED */
|
||||||
|
4, /* 21: RESERVED */
|
||||||
|
4, /* 22: RESERVED */
|
||||||
|
4, /* 23: RESERVED */
|
||||||
|
44, /* 24: Spurious Interrupt */
|
||||||
|
44, /* 25: Level 1 Interrupt Autovector */
|
||||||
|
44, /* 26: Level 2 Interrupt Autovector */
|
||||||
|
44, /* 27: Level 3 Interrupt Autovector */
|
||||||
|
44, /* 28: Level 4 Interrupt Autovector */
|
||||||
|
44, /* 29: Level 5 Interrupt Autovector */
|
||||||
|
44, /* 30: Level 6 Interrupt Autovector */
|
||||||
|
44, /* 31: Level 7 Interrupt Autovector */
|
||||||
|
34, /* 32: TRAP #0 -- ASG: chanaged from 38 */
|
||||||
|
34, /* 33: TRAP #1 */
|
||||||
|
34, /* 34: TRAP #2 */
|
||||||
|
34, /* 35: TRAP #3 */
|
||||||
|
34, /* 36: TRAP #4 */
|
||||||
|
34, /* 37: TRAP #5 */
|
||||||
|
34, /* 38: TRAP #6 */
|
||||||
|
34, /* 39: TRAP #7 */
|
||||||
|
34, /* 40: TRAP #8 */
|
||||||
|
34, /* 41: TRAP #9 */
|
||||||
|
34, /* 42: TRAP #10 */
|
||||||
|
34, /* 43: TRAP #11 */
|
||||||
|
34, /* 44: TRAP #12 */
|
||||||
|
34, /* 45: TRAP #13 */
|
||||||
|
34, /* 46: TRAP #14 */
|
||||||
|
34, /* 47: TRAP #15 */
|
||||||
|
4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
|
||||||
|
4, /* 49: FP Inexact Result (unemulated) */
|
||||||
|
4, /* 50: FP Divide by Zero (unemulated) */
|
||||||
|
4, /* 51: FP Underflow (unemulated) */
|
||||||
|
4, /* 52: FP Operand Error (unemulated) */
|
||||||
|
4, /* 53: FP Overflow (unemulated) */
|
||||||
|
4, /* 54: FP Signaling NAN (unemulated) */
|
||||||
|
4, /* 55: FP Unimplemented Data Type (unemulated) */
|
||||||
|
4, /* 56: MMU Configuration Error (unemulated) */
|
||||||
|
4, /* 57: MMU Illegal Operation Error (unemulated) */
|
||||||
|
4, /* 58: MMU Access Level Violation Error (unemulated) */
|
||||||
|
4, /* 59: RESERVED */
|
||||||
|
4, /* 60: RESERVED */
|
||||||
|
4, /* 61: RESERVED */
|
||||||
|
4, /* 62: RESERVED */
|
||||||
|
4, /* 63: RESERVED */
|
||||||
|
/* 64-255: User Defined */
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
|
||||||
|
},
|
||||||
|
{ /* 010 */
|
||||||
|
4, /* 0: Reset - Initial Stack Pointer */
|
||||||
|
4, /* 1: Reset - Initial Program Counter */
|
||||||
|
126, /* 2: Bus Error (unemulated) */
|
||||||
|
126, /* 3: Address Error (unemulated) */
|
||||||
|
38, /* 4: Illegal Instruction */
|
||||||
|
44, /* 5: Divide by Zero */
|
||||||
|
44, /* 6: CHK */
|
||||||
|
34, /* 7: TRAPV */
|
||||||
|
38, /* 8: Privilege Violation */
|
||||||
|
38, /* 9: Trace */
|
||||||
|
4, /* 10: 1010 */
|
||||||
|
4, /* 11: 1111 */
|
||||||
|
4, /* 12: RESERVED */
|
||||||
|
4, /* 13: Coprocessor Protocol Violation (unemulated) */
|
||||||
|
4, /* 14: Format Error */
|
||||||
|
44, /* 15: Uninitialized Interrupt */
|
||||||
|
4, /* 16: RESERVED */
|
||||||
|
4, /* 17: RESERVED */
|
||||||
|
4, /* 18: RESERVED */
|
||||||
|
4, /* 19: RESERVED */
|
||||||
|
4, /* 20: RESERVED */
|
||||||
|
4, /* 21: RESERVED */
|
||||||
|
4, /* 22: RESERVED */
|
||||||
|
4, /* 23: RESERVED */
|
||||||
|
46, /* 24: Spurious Interrupt */
|
||||||
|
46, /* 25: Level 1 Interrupt Autovector */
|
||||||
|
46, /* 26: Level 2 Interrupt Autovector */
|
||||||
|
46, /* 27: Level 3 Interrupt Autovector */
|
||||||
|
46, /* 28: Level 4 Interrupt Autovector */
|
||||||
|
46, /* 29: Level 5 Interrupt Autovector */
|
||||||
|
46, /* 30: Level 6 Interrupt Autovector */
|
||||||
|
46, /* 31: Level 7 Interrupt Autovector */
|
||||||
|
38, /* 32: TRAP #0 */
|
||||||
|
38, /* 33: TRAP #1 */
|
||||||
|
38, /* 34: TRAP #2 */
|
||||||
|
38, /* 35: TRAP #3 */
|
||||||
|
38, /* 36: TRAP #4 */
|
||||||
|
38, /* 37: TRAP #5 */
|
||||||
|
38, /* 38: TRAP #6 */
|
||||||
|
38, /* 39: TRAP #7 */
|
||||||
|
38, /* 40: TRAP #8 */
|
||||||
|
38, /* 41: TRAP #9 */
|
||||||
|
38, /* 42: TRAP #10 */
|
||||||
|
38, /* 43: TRAP #11 */
|
||||||
|
38, /* 44: TRAP #12 */
|
||||||
|
38, /* 45: TRAP #13 */
|
||||||
|
38, /* 46: TRAP #14 */
|
||||||
|
38, /* 47: TRAP #15 */
|
||||||
|
4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
|
||||||
|
4, /* 49: FP Inexact Result (unemulated) */
|
||||||
|
4, /* 50: FP Divide by Zero (unemulated) */
|
||||||
|
4, /* 51: FP Underflow (unemulated) */
|
||||||
|
4, /* 52: FP Operand Error (unemulated) */
|
||||||
|
4, /* 53: FP Overflow (unemulated) */
|
||||||
|
4, /* 54: FP Signaling NAN (unemulated) */
|
||||||
|
4, /* 55: FP Unimplemented Data Type (unemulated) */
|
||||||
|
4, /* 56: MMU Configuration Error (unemulated) */
|
||||||
|
4, /* 57: MMU Illegal Operation Error (unemulated) */
|
||||||
|
4, /* 58: MMU Access Level Violation Error (unemulated) */
|
||||||
|
4, /* 59: RESERVED */
|
||||||
|
4, /* 60: RESERVED */
|
||||||
|
4, /* 61: RESERVED */
|
||||||
|
4, /* 62: RESERVED */
|
||||||
|
4, /* 63: RESERVED */
|
||||||
|
/* 64-255: User Defined */
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
|
||||||
|
},
|
||||||
|
{ /* 020 */
|
||||||
|
4, /* 0: Reset - Initial Stack Pointer */
|
||||||
|
4, /* 1: Reset - Initial Program Counter */
|
||||||
|
50, /* 2: Bus Error (unemulated) */
|
||||||
|
50, /* 3: Address Error (unemulated) */
|
||||||
|
20, /* 4: Illegal Instruction */
|
||||||
|
38, /* 5: Divide by Zero */
|
||||||
|
40, /* 6: CHK */
|
||||||
|
20, /* 7: TRAPV */
|
||||||
|
34, /* 8: Privilege Violation */
|
||||||
|
25, /* 9: Trace */
|
||||||
|
20, /* 10: 1010 */
|
||||||
|
20, /* 11: 1111 */
|
||||||
|
4, /* 12: RESERVED */
|
||||||
|
4, /* 13: Coprocessor Protocol Violation (unemulated) */
|
||||||
|
4, /* 14: Format Error */
|
||||||
|
30, /* 15: Uninitialized Interrupt */
|
||||||
|
4, /* 16: RESERVED */
|
||||||
|
4, /* 17: RESERVED */
|
||||||
|
4, /* 18: RESERVED */
|
||||||
|
4, /* 19: RESERVED */
|
||||||
|
4, /* 20: RESERVED */
|
||||||
|
4, /* 21: RESERVED */
|
||||||
|
4, /* 22: RESERVED */
|
||||||
|
4, /* 23: RESERVED */
|
||||||
|
30, /* 24: Spurious Interrupt */
|
||||||
|
30, /* 25: Level 1 Interrupt Autovector */
|
||||||
|
30, /* 26: Level 2 Interrupt Autovector */
|
||||||
|
30, /* 27: Level 3 Interrupt Autovector */
|
||||||
|
30, /* 28: Level 4 Interrupt Autovector */
|
||||||
|
30, /* 29: Level 5 Interrupt Autovector */
|
||||||
|
30, /* 30: Level 6 Interrupt Autovector */
|
||||||
|
30, /* 31: Level 7 Interrupt Autovector */
|
||||||
|
20, /* 32: TRAP #0 */
|
||||||
|
20, /* 33: TRAP #1 */
|
||||||
|
20, /* 34: TRAP #2 */
|
||||||
|
20, /* 35: TRAP #3 */
|
||||||
|
20, /* 36: TRAP #4 */
|
||||||
|
20, /* 37: TRAP #5 */
|
||||||
|
20, /* 38: TRAP #6 */
|
||||||
|
20, /* 39: TRAP #7 */
|
||||||
|
20, /* 40: TRAP #8 */
|
||||||
|
20, /* 41: TRAP #9 */
|
||||||
|
20, /* 42: TRAP #10 */
|
||||||
|
20, /* 43: TRAP #11 */
|
||||||
|
20, /* 44: TRAP #12 */
|
||||||
|
20, /* 45: TRAP #13 */
|
||||||
|
20, /* 46: TRAP #14 */
|
||||||
|
20, /* 47: TRAP #15 */
|
||||||
|
4, /* 48: FP Branch or Set on Unknown Condition (unemulated) */
|
||||||
|
4, /* 49: FP Inexact Result (unemulated) */
|
||||||
|
4, /* 50: FP Divide by Zero (unemulated) */
|
||||||
|
4, /* 51: FP Underflow (unemulated) */
|
||||||
|
4, /* 52: FP Operand Error (unemulated) */
|
||||||
|
4, /* 53: FP Overflow (unemulated) */
|
||||||
|
4, /* 54: FP Signaling NAN (unemulated) */
|
||||||
|
4, /* 55: FP Unimplemented Data Type (unemulated) */
|
||||||
|
4, /* 56: MMU Configuration Error (unemulated) */
|
||||||
|
4, /* 57: MMU Illegal Operation Error (unemulated) */
|
||||||
|
4, /* 58: MMU Access Level Violation Error (unemulated) */
|
||||||
|
4, /* 59: RESERVED */
|
||||||
|
4, /* 60: RESERVED */
|
||||||
|
4, /* 61: RESERVED */
|
||||||
|
4, /* 62: RESERVED */
|
||||||
|
4, /* 63: RESERVED */
|
||||||
|
/* 64-255: User Defined */
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
|
||||||
|
4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8 m68ki_ea_idx_cycle_table[64] =
|
||||||
|
{
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, /* ..01.000 no memory indirect, base NULL */
|
||||||
|
5, /* ..01..01 memory indirect, base NULL, outer NULL */
|
||||||
|
7, /* ..01..10 memory indirect, base NULL, outer 16 */
|
||||||
|
7, /* ..01..11 memory indirect, base NULL, outer 32 */
|
||||||
|
0, 5, 7, 7, 0, 5, 7, 7, 0, 5, 7, 7,
|
||||||
|
2, /* ..10.000 no memory indirect, base 16 */
|
||||||
|
7, /* ..10..01 memory indirect, base 16, outer NULL */
|
||||||
|
9, /* ..10..10 memory indirect, base 16, outer 16 */
|
||||||
|
9, /* ..10..11 memory indirect, base 16, outer 32 */
|
||||||
|
0, 7, 9, 9, 0, 7, 9, 9, 0, 7, 9, 9,
|
||||||
|
6, /* ..11.000 no memory indirect, base 32 */
|
||||||
|
11, /* ..11..01 memory indirect, base 32, outer NULL */
|
||||||
|
13, /* ..11..10 memory indirect, base 32, outer 16 */
|
||||||
|
13, /* ..11..11 memory indirect, base 32, outer 32 */
|
||||||
|
0, 11, 13, 13, 0, 11, 13, 13, 0, 11, 13, 13
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* =============================== CALLBACKS ============================== */
|
||||||
|
/* ======================================================================== */
|
||||||
|
|
||||||
|
/* Default callbacks used if the callback hasn't been set yet, or if the
|
||||||
|
* callback is set to NULL
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Interrupt acknowledge */
|
||||||
|
static int default_int_ack_callback_data;
|
||||||
|
static int default_int_ack_callback(int int_level)
|
||||||
|
{
|
||||||
|
default_int_ack_callback_data = int_level;
|
||||||
|
CPU_INT_LEVEL = 0;
|
||||||
|
return M68K_INT_ACK_AUTOVECTOR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Breakpoint acknowledge */
|
||||||
|
static unsigned int default_bkpt_ack_callback_data;
|
||||||
|
static void default_bkpt_ack_callback(unsigned int data)
|
||||||
|
{
|
||||||
|
default_bkpt_ack_callback_data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called when a reset instruction is executed */
|
||||||
|
static void default_reset_instr_callback(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called when a cmpi.l #v, dn instruction is executed */
|
||||||
|
static void default_cmpild_instr_callback(unsigned int val, int reg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called when a rte instruction is executed */
|
||||||
|
static void default_rte_instr_callback(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called when the program counter changed by a large value */
|
||||||
|
static unsigned int default_pc_changed_callback_data;
|
||||||
|
static void default_pc_changed_callback(unsigned int new_pc)
|
||||||
|
{
|
||||||
|
default_pc_changed_callback_data = new_pc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called every time there's bus activity (read/write to/from memory */
|
||||||
|
static unsigned int default_set_fc_callback_data;
|
||||||
|
static void default_set_fc_callback(unsigned int new_fc)
|
||||||
|
{
|
||||||
|
default_set_fc_callback_data = new_fc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Called every instruction cycle prior to execution */
|
||||||
|
static void default_instr_hook_callback(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if M68K_EMULATE_ADDRESS_ERROR
|
||||||
|
#include <setjmp.h>
|
||||||
|
jmp_buf m68ki_aerr_trap;
|
||||||
|
#endif /* M68K_EMULATE_ADDRESS_ERROR */
|
||||||
|
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ================================= API ================================== */
|
||||||
|
/* ======================================================================== */
|
||||||
|
|
||||||
|
/* Access the internals of the CPU */
|
||||||
|
unsigned int m68k_get_reg(void* context, m68k_register_t regnum)
|
||||||
|
{
|
||||||
|
m68ki_cpu_core* cpu = context != NULL ?(m68ki_cpu_core*)context : &m68ki_cpu;
|
||||||
|
|
||||||
|
switch(regnum)
|
||||||
|
{
|
||||||
|
case M68K_REG_D0: return cpu->dar[0];
|
||||||
|
case M68K_REG_D1: return cpu->dar[1];
|
||||||
|
case M68K_REG_D2: return cpu->dar[2];
|
||||||
|
case M68K_REG_D3: return cpu->dar[3];
|
||||||
|
case M68K_REG_D4: return cpu->dar[4];
|
||||||
|
case M68K_REG_D5: return cpu->dar[5];
|
||||||
|
case M68K_REG_D6: return cpu->dar[6];
|
||||||
|
case M68K_REG_D7: return cpu->dar[7];
|
||||||
|
case M68K_REG_A0: return cpu->dar[8];
|
||||||
|
case M68K_REG_A1: return cpu->dar[9];
|
||||||
|
case M68K_REG_A2: return cpu->dar[10];
|
||||||
|
case M68K_REG_A3: return cpu->dar[11];
|
||||||
|
case M68K_REG_A4: return cpu->dar[12];
|
||||||
|
case M68K_REG_A5: return cpu->dar[13];
|
||||||
|
case M68K_REG_A6: return cpu->dar[14];
|
||||||
|
case M68K_REG_A7: return cpu->dar[15];
|
||||||
|
case M68K_REG_PC: return MASK_OUT_ABOVE_32(cpu->pc);
|
||||||
|
case M68K_REG_SR: return cpu->t1_flag |
|
||||||
|
cpu->t0_flag |
|
||||||
|
(cpu->s_flag << 11) |
|
||||||
|
(cpu->m_flag << 11) |
|
||||||
|
cpu->int_mask |
|
||||||
|
((cpu->x_flag & XFLAG_SET) >> 4) |
|
||||||
|
((cpu->n_flag & NFLAG_SET) >> 4) |
|
||||||
|
((!cpu->not_z_flag) << 2) |
|
||||||
|
((cpu->v_flag & VFLAG_SET) >> 6) |
|
||||||
|
((cpu->c_flag & CFLAG_SET) >> 8);
|
||||||
|
case M68K_REG_SP: return cpu->dar[15];
|
||||||
|
case M68K_REG_USP: return cpu->s_flag ? cpu->sp[0] : cpu->dar[15];
|
||||||
|
case M68K_REG_ISP: return cpu->s_flag && !cpu->m_flag ? cpu->dar[15] : cpu->sp[4];
|
||||||
|
case M68K_REG_MSP: return cpu->s_flag && cpu->m_flag ? cpu->dar[15] : cpu->sp[6];
|
||||||
|
case M68K_REG_SFC: return cpu->sfc;
|
||||||
|
case M68K_REG_DFC: return cpu->dfc;
|
||||||
|
case M68K_REG_VBR: return cpu->vbr;
|
||||||
|
case M68K_REG_CACR: return cpu->cacr;
|
||||||
|
case M68K_REG_CAAR: return cpu->caar;
|
||||||
|
case M68K_REG_PREF_ADDR: return cpu->pref_addr;
|
||||||
|
case M68K_REG_PREF_DATA: return cpu->pref_data;
|
||||||
|
case M68K_REG_PPC: return MASK_OUT_ABOVE_32(cpu->ppc);
|
||||||
|
case M68K_REG_IR: return cpu->ir;
|
||||||
|
case M68K_REG_CPU_TYPE:
|
||||||
|
switch(cpu->cpu_type)
|
||||||
|
{
|
||||||
|
case CPU_TYPE_000: return (unsigned int)M68K_CPU_TYPE_68000;
|
||||||
|
case CPU_TYPE_008: return (unsigned int)M68K_CPU_TYPE_68008;
|
||||||
|
case CPU_TYPE_010: return (unsigned int)M68K_CPU_TYPE_68010;
|
||||||
|
case CPU_TYPE_EC020: return (unsigned int)M68K_CPU_TYPE_68EC020;
|
||||||
|
case CPU_TYPE_020: return (unsigned int)M68K_CPU_TYPE_68020;
|
||||||
|
}
|
||||||
|
return M68K_CPU_TYPE_INVALID;
|
||||||
|
default: return 0;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void m68k_set_reg(m68k_register_t regnum, unsigned int value)
|
||||||
|
{
|
||||||
|
switch(regnum)
|
||||||
|
{
|
||||||
|
case M68K_REG_D0: REG_D[0] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_D1: REG_D[1] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_D2: REG_D[2] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_D3: REG_D[3] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_D4: REG_D[4] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_D5: REG_D[5] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_D6: REG_D[6] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_D7: REG_D[7] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_A0: REG_A[0] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_A1: REG_A[1] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_A2: REG_A[2] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_A3: REG_A[3] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_A4: REG_A[4] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_A5: REG_A[5] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_A6: REG_A[6] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_A7: REG_A[7] = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_PC: m68ki_jump(MASK_OUT_ABOVE_32(value)); return;
|
||||||
|
case M68K_REG_SR: m68ki_set_sr(value); return;
|
||||||
|
case M68K_REG_SP: REG_SP = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_USP: if(FLAG_S)
|
||||||
|
REG_USP = MASK_OUT_ABOVE_32(value);
|
||||||
|
else
|
||||||
|
REG_SP = MASK_OUT_ABOVE_32(value);
|
||||||
|
return;
|
||||||
|
case M68K_REG_ISP: if(FLAG_S && !FLAG_M)
|
||||||
|
REG_SP = MASK_OUT_ABOVE_32(value);
|
||||||
|
else
|
||||||
|
REG_ISP = MASK_OUT_ABOVE_32(value);
|
||||||
|
return;
|
||||||
|
case M68K_REG_MSP: if(FLAG_S && FLAG_M)
|
||||||
|
REG_SP = MASK_OUT_ABOVE_32(value);
|
||||||
|
else
|
||||||
|
REG_MSP = MASK_OUT_ABOVE_32(value);
|
||||||
|
return;
|
||||||
|
case M68K_REG_VBR: REG_VBR = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_SFC: REG_SFC = value & 7; return;
|
||||||
|
case M68K_REG_DFC: REG_DFC = value & 7; return;
|
||||||
|
case M68K_REG_CACR: REG_CACR = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_CAAR: REG_CAAR = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_PPC: REG_PPC = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_IR: REG_IR = MASK_OUT_ABOVE_16(value); return;
|
||||||
|
case M68K_REG_PREF_ADDR: CPU_PREF_ADDR = MASK_OUT_ABOVE_32(value); return;
|
||||||
|
case M68K_REG_CPU_TYPE: m68k_set_cpu_type(value); return;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the callbacks */
|
||||||
|
void m68k_set_int_ack_callback(int (*callback)(int int_level))
|
||||||
|
{
|
||||||
|
CALLBACK_INT_ACK = callback ? callback : default_int_ack_callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void m68k_set_bkpt_ack_callback(void (*callback)(unsigned int data))
|
||||||
|
{
|
||||||
|
CALLBACK_BKPT_ACK = callback ? callback : default_bkpt_ack_callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void m68k_set_reset_instr_callback(void (*callback)(void))
|
||||||
|
{
|
||||||
|
CALLBACK_RESET_INSTR = callback ? callback : default_reset_instr_callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void m68k_set_cmpild_instr_callback(void (*callback)(unsigned int, int))
|
||||||
|
{
|
||||||
|
CALLBACK_CMPILD_INSTR = callback ? callback : default_cmpild_instr_callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void m68k_set_rte_instr_callback(void (*callback)(void))
|
||||||
|
{
|
||||||
|
CALLBACK_RTE_INSTR = callback ? callback : default_rte_instr_callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void m68k_set_pc_changed_callback(void (*callback)(unsigned int new_pc))
|
||||||
|
{
|
||||||
|
CALLBACK_PC_CHANGED = callback ? callback : default_pc_changed_callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void m68k_set_fc_callback(void (*callback)(unsigned int new_fc))
|
||||||
|
{
|
||||||
|
CALLBACK_SET_FC = callback ? callback : default_set_fc_callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
void m68k_set_instr_hook_callback(void (*callback)(void))
|
||||||
|
{
|
||||||
|
CALLBACK_INSTR_HOOK = callback ? callback : default_instr_hook_callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
/* Set the CPU type. */
|
||||||
|
void m68k_set_cpu_type(unsigned int cpu_type)
|
||||||
|
{
|
||||||
|
switch(cpu_type)
|
||||||
|
{
|
||||||
|
case M68K_CPU_TYPE_68000:
|
||||||
|
CPU_TYPE = CPU_TYPE_000;
|
||||||
|
CPU_ADDRESS_MASK = 0x00ffffff;
|
||||||
|
CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
|
||||||
|
CYC_INSTRUCTION = m68ki_cycles[0];
|
||||||
|
CYC_EXCEPTION = m68ki_exception_cycle_table[0];
|
||||||
|
CYC_BCC_NOTAKE_B = -2;
|
||||||
|
CYC_BCC_NOTAKE_W = 2;
|
||||||
|
CYC_DBCC_F_NOEXP = -2;
|
||||||
|
CYC_DBCC_F_EXP = 2;
|
||||||
|
CYC_SCC_R_TRUE = 2;
|
||||||
|
CYC_MOVEM_W = 2;
|
||||||
|
CYC_MOVEM_L = 3;
|
||||||
|
CYC_SHIFT = 1;
|
||||||
|
CYC_RESET = 132;
|
||||||
|
return;
|
||||||
|
case M68K_CPU_TYPE_68008:
|
||||||
|
CPU_TYPE = CPU_TYPE_008;
|
||||||
|
CPU_ADDRESS_MASK = 0x003fffff;
|
||||||
|
CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
|
||||||
|
CYC_INSTRUCTION = m68ki_cycles[0];
|
||||||
|
CYC_EXCEPTION = m68ki_exception_cycle_table[0];
|
||||||
|
CYC_BCC_NOTAKE_B = -2;
|
||||||
|
CYC_BCC_NOTAKE_W = 2;
|
||||||
|
CYC_DBCC_F_NOEXP = -2;
|
||||||
|
CYC_DBCC_F_EXP = 2;
|
||||||
|
CYC_SCC_R_TRUE = 2;
|
||||||
|
CYC_MOVEM_W = 2;
|
||||||
|
CYC_MOVEM_L = 3;
|
||||||
|
CYC_SHIFT = 1;
|
||||||
|
CYC_RESET = 132;
|
||||||
|
return;
|
||||||
|
case M68K_CPU_TYPE_68010:
|
||||||
|
CPU_TYPE = CPU_TYPE_010;
|
||||||
|
CPU_ADDRESS_MASK = 0x00ffffff;
|
||||||
|
CPU_SR_MASK = 0xa71f; /* T1 -- S -- -- I2 I1 I0 -- -- -- X N Z V C */
|
||||||
|
CYC_INSTRUCTION = m68ki_cycles[1];
|
||||||
|
CYC_EXCEPTION = m68ki_exception_cycle_table[1];
|
||||||
|
CYC_BCC_NOTAKE_B = -4;
|
||||||
|
CYC_BCC_NOTAKE_W = 0;
|
||||||
|
CYC_DBCC_F_NOEXP = 0;
|
||||||
|
CYC_DBCC_F_EXP = 6;
|
||||||
|
CYC_SCC_R_TRUE = 0;
|
||||||
|
CYC_MOVEM_W = 2;
|
||||||
|
CYC_MOVEM_L = 3;
|
||||||
|
CYC_SHIFT = 1;
|
||||||
|
CYC_RESET = 130;
|
||||||
|
return;
|
||||||
|
case M68K_CPU_TYPE_68EC020:
|
||||||
|
CPU_TYPE = CPU_TYPE_EC020;
|
||||||
|
CPU_ADDRESS_MASK = 0x00ffffff;
|
||||||
|
CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
|
||||||
|
CYC_INSTRUCTION = m68ki_cycles[2];
|
||||||
|
CYC_EXCEPTION = m68ki_exception_cycle_table[2];
|
||||||
|
CYC_BCC_NOTAKE_B = -2;
|
||||||
|
CYC_BCC_NOTAKE_W = 0;
|
||||||
|
CYC_DBCC_F_NOEXP = 0;
|
||||||
|
CYC_DBCC_F_EXP = 4;
|
||||||
|
CYC_SCC_R_TRUE = 0;
|
||||||
|
CYC_MOVEM_W = 2;
|
||||||
|
CYC_MOVEM_L = 2;
|
||||||
|
CYC_SHIFT = 0;
|
||||||
|
CYC_RESET = 518;
|
||||||
|
return;
|
||||||
|
case M68K_CPU_TYPE_68020:
|
||||||
|
CPU_TYPE = CPU_TYPE_020;
|
||||||
|
CPU_ADDRESS_MASK = 0xffffffff;
|
||||||
|
CPU_SR_MASK = 0xf71f; /* T1 T0 S M -- I2 I1 I0 -- -- -- X N Z V C */
|
||||||
|
CYC_INSTRUCTION = m68ki_cycles[2];
|
||||||
|
CYC_EXCEPTION = m68ki_exception_cycle_table[2];
|
||||||
|
CYC_BCC_NOTAKE_B = -2;
|
||||||
|
CYC_BCC_NOTAKE_W = 0;
|
||||||
|
CYC_DBCC_F_NOEXP = 0;
|
||||||
|
CYC_DBCC_F_EXP = 4;
|
||||||
|
CYC_SCC_R_TRUE = 0;
|
||||||
|
CYC_MOVEM_W = 2;
|
||||||
|
CYC_MOVEM_L = 2;
|
||||||
|
CYC_SHIFT = 0;
|
||||||
|
CYC_RESET = 518;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Execute some instructions until we use up num_cycles clock cycles */
|
||||||
|
/* ASG: removed per-instruction interrupt checks */
|
||||||
|
int m68k_execute(int num_cycles)
|
||||||
|
{
|
||||||
|
/* Make sure we're not stopped */
|
||||||
|
if(!CPU_STOPPED)
|
||||||
|
{
|
||||||
|
/* Set our pool of clock cycles available */
|
||||||
|
SET_CYCLES(num_cycles);
|
||||||
|
m68ki_initial_cycles = num_cycles;
|
||||||
|
|
||||||
|
/* ASG: update cycles */
|
||||||
|
USE_CYCLES(CPU_INT_CYCLES);
|
||||||
|
CPU_INT_CYCLES = 0;
|
||||||
|
|
||||||
|
/* Return point if we had an address error */
|
||||||
|
m68ki_set_address_error_trap(); /* auto-disable (see m68kcpu.h) */
|
||||||
|
|
||||||
|
/* Main loop. Keep going until we run out of clock cycles */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Set tracing accodring to T1. (T0 is done inside instruction) */
|
||||||
|
m68ki_trace_t1(); /* auto-disable (see m68kcpu.h) */
|
||||||
|
|
||||||
|
/* Set the address space for reads */
|
||||||
|
m68ki_use_data_space(); /* auto-disable (see m68kcpu.h) */
|
||||||
|
|
||||||
|
/* Call external hook to peek at CPU */
|
||||||
|
m68ki_instr_hook(); /* auto-disable (see m68kcpu.h) */
|
||||||
|
|
||||||
|
/* Record previous program counter */
|
||||||
|
REG_PPC = REG_PC;
|
||||||
|
|
||||||
|
/* Read an instruction and call its handler */
|
||||||
|
REG_IR = m68ki_read_imm_16();
|
||||||
|
m68ki_instruction_jump_table[REG_IR]();
|
||||||
|
USE_CYCLES(CYC_INSTRUCTION[REG_IR]);
|
||||||
|
|
||||||
|
/* Trace m68k_exception, if necessary */
|
||||||
|
m68ki_exception_if_trace(); /* auto-disable (see m68kcpu.h) */
|
||||||
|
} while(GET_CYCLES() > 0);
|
||||||
|
|
||||||
|
/* set previous PC to current PC for the next entry into the loop */
|
||||||
|
REG_PPC = REG_PC;
|
||||||
|
|
||||||
|
/* ASG: update cycles */
|
||||||
|
USE_CYCLES(CPU_INT_CYCLES);
|
||||||
|
CPU_INT_CYCLES = 0;
|
||||||
|
|
||||||
|
/* return how many clocks we used */
|
||||||
|
return m68ki_initial_cycles - GET_CYCLES();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We get here if the CPU is stopped or halted */
|
||||||
|
SET_CYCLES(0);
|
||||||
|
CPU_INT_CYCLES = 0;
|
||||||
|
|
||||||
|
return num_cycles;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int m68k_cycles_run(void)
|
||||||
|
{
|
||||||
|
return m68ki_initial_cycles - GET_CYCLES();
|
||||||
|
}
|
||||||
|
|
||||||
|
int m68k_cycles_remaining(void)
|
||||||
|
{
|
||||||
|
return GET_CYCLES();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Change the timeslice */
|
||||||
|
void m68k_modify_timeslice(int cycles)
|
||||||
|
{
|
||||||
|
m68ki_initial_cycles += cycles;
|
||||||
|
ADD_CYCLES(cycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void m68k_end_timeslice(void)
|
||||||
|
{
|
||||||
|
m68ki_initial_cycles -= GET_CYCLES();
|
||||||
|
SET_CYCLES(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ASG: rewrote so that the int_level is a mask of the IPL0/IPL1/IPL2 bits */
|
||||||
|
/* KS: Modified so that IPL* bits match with mask positions in the SR
|
||||||
|
* and cleaned out remenants of the interrupt controller.
|
||||||
|
*/
|
||||||
|
void m68k_set_irq(unsigned int int_level)
|
||||||
|
{
|
||||||
|
uint old_level = CPU_INT_LEVEL;
|
||||||
|
CPU_INT_LEVEL = int_level << 8;
|
||||||
|
|
||||||
|
/* A transition from < 7 to 7 always interrupts (NMI) */
|
||||||
|
/* Note: Level 7 can also level trigger like a normal IRQ */
|
||||||
|
if(old_level != 0x0700 && CPU_INT_LEVEL == 0x0700)
|
||||||
|
m68ki_exception_interrupt(7); /* Edge triggered level 7 (NMI) */
|
||||||
|
else
|
||||||
|
m68ki_check_interrupts(); /* Level triggered (IRQ) */
|
||||||
|
}
|
||||||
|
|
||||||
|
void m68k_init(void)
|
||||||
|
{
|
||||||
|
static uint emulation_initialized = 0;
|
||||||
|
|
||||||
|
/* The first call to this function initializes the opcode handler jump table */
|
||||||
|
if(!emulation_initialized)
|
||||||
|
{
|
||||||
|
m68ki_build_opcode_table();
|
||||||
|
emulation_initialized = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
m68k_set_int_ack_callback(NULL);
|
||||||
|
m68k_set_bkpt_ack_callback(NULL);
|
||||||
|
m68k_set_reset_instr_callback(NULL);
|
||||||
|
m68k_set_cmpild_instr_callback(NULL);
|
||||||
|
m68k_set_rte_instr_callback(NULL);
|
||||||
|
m68k_set_pc_changed_callback(NULL);
|
||||||
|
m68k_set_fc_callback(NULL);
|
||||||
|
m68k_set_instr_hook_callback(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pulse the RESET line on the CPU */
|
||||||
|
void m68k_pulse_reset(void)
|
||||||
|
{
|
||||||
|
/* Clear all stop levels and eat up all remaining cycles */
|
||||||
|
CPU_STOPPED = 0;
|
||||||
|
SET_CYCLES(0);
|
||||||
|
|
||||||
|
CPU_RUN_MODE = RUN_MODE_BERR_AERR_RESET;
|
||||||
|
|
||||||
|
/* Turn off tracing */
|
||||||
|
FLAG_T1 = FLAG_T0 = 0;
|
||||||
|
m68ki_clear_trace();
|
||||||
|
/* Interrupt mask to level 7 */
|
||||||
|
FLAG_INT_MASK = 0x0700;
|
||||||
|
/* Reset VBR */
|
||||||
|
REG_VBR = 0;
|
||||||
|
/* Go to supervisor mode */
|
||||||
|
m68ki_set_sm_flag(SFLAG_SET | MFLAG_CLEAR);
|
||||||
|
|
||||||
|
/* Invalidate the prefetch queue */
|
||||||
|
#if M68K_EMULATE_PREFETCH
|
||||||
|
/* Set to arbitrary number since our first fetch is from 0 */
|
||||||
|
CPU_PREF_ADDR = 0x1000;
|
||||||
|
#endif /* M68K_EMULATE_PREFETCH */
|
||||||
|
|
||||||
|
/* Read the initial stack pointer and program counter */
|
||||||
|
m68ki_jump(0);
|
||||||
|
REG_SP = m68ki_read_imm_32();
|
||||||
|
REG_PC = m68ki_read_imm_32();
|
||||||
|
m68ki_jump(REG_PC);
|
||||||
|
|
||||||
|
CPU_RUN_MODE = RUN_MODE_NORMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Pulse the HALT line on the CPU */
|
||||||
|
void m68k_pulse_halt(void)
|
||||||
|
{
|
||||||
|
CPU_STOPPED |= STOP_LEVEL_HALT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Get and set the current CPU context */
|
||||||
|
/* This is to allow for multiple CPUs */
|
||||||
|
unsigned int m68k_context_size()
|
||||||
|
{
|
||||||
|
return sizeof(m68ki_cpu_core);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int m68k_get_context(void* dst)
|
||||||
|
{
|
||||||
|
if(dst) *(m68ki_cpu_core*)dst = m68ki_cpu;
|
||||||
|
return sizeof(m68ki_cpu_core);
|
||||||
|
}
|
||||||
|
|
||||||
|
void m68k_set_context(void* src)
|
||||||
|
{
|
||||||
|
if(src) m68ki_cpu = *(m68ki_cpu_core*)src;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ============================== MAME STUFF ============================== */
|
||||||
|
/* ======================================================================== */
|
||||||
|
|
||||||
|
#if M68K_COMPILE_FOR_MAME == OPT_ON
|
||||||
|
|
||||||
|
#include "state.h"
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
UINT16 sr;
|
||||||
|
int stopped;
|
||||||
|
int halted;
|
||||||
|
} m68k_substate;
|
||||||
|
|
||||||
|
static void m68k_prepare_substate(void)
|
||||||
|
{
|
||||||
|
m68k_substate.sr = m68ki_get_sr();
|
||||||
|
m68k_substate.stopped = (CPU_STOPPED & STOP_LEVEL_STOP) != 0;
|
||||||
|
m68k_substate.halted = (CPU_STOPPED & STOP_LEVEL_HALT) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void m68k_post_load(void)
|
||||||
|
{
|
||||||
|
m68ki_set_sr_noint_nosp(m68k_substate.sr);
|
||||||
|
CPU_STOPPED = m68k_substate.stopped ? STOP_LEVEL_STOP : 0
|
||||||
|
| m68k_substate.halted ? STOP_LEVEL_HALT : 0;
|
||||||
|
m68ki_jump(REG_PC);
|
||||||
|
}
|
||||||
|
|
||||||
|
void m68k_state_register(const char *type)
|
||||||
|
{
|
||||||
|
int cpu = cpu_getactivecpu();
|
||||||
|
|
||||||
|
state_save_register_UINT32(type, cpu, "D" , REG_D, 8);
|
||||||
|
state_save_register_UINT32(type, cpu, "A" , REG_A, 8);
|
||||||
|
state_save_register_UINT32(type, cpu, "PPC" , ®_PPC, 1);
|
||||||
|
state_save_register_UINT32(type, cpu, "PC" , ®_PC, 1);
|
||||||
|
state_save_register_UINT32(type, cpu, "USP" , ®_USP, 1);
|
||||||
|
state_save_register_UINT32(type, cpu, "ISP" , ®_ISP, 1);
|
||||||
|
state_save_register_UINT32(type, cpu, "MSP" , ®_MSP, 1);
|
||||||
|
state_save_register_UINT32(type, cpu, "VBR" , ®_VBR, 1);
|
||||||
|
state_save_register_UINT32(type, cpu, "SFC" , ®_SFC, 1);
|
||||||
|
state_save_register_UINT32(type, cpu, "DFC" , ®_DFC, 1);
|
||||||
|
state_save_register_UINT32(type, cpu, "CACR" , ®_CACR, 1);
|
||||||
|
state_save_register_UINT32(type, cpu, "CAAR" , ®_CAAR, 1);
|
||||||
|
state_save_register_UINT16(type, cpu, "SR" , &m68k_substate.sr, 1);
|
||||||
|
state_save_register_UINT32(type, cpu, "INT_LEVEL" , &CPU_INT_LEVEL, 1);
|
||||||
|
state_save_register_UINT32(type, cpu, "INT_CYCLES", &CPU_INT_CYCLES, 1);
|
||||||
|
state_save_register_int (type, cpu, "STOPPED" , &m68k_substate.stopped);
|
||||||
|
state_save_register_int (type, cpu, "HALTED" , &m68k_substate.halted);
|
||||||
|
state_save_register_UINT32(type, cpu, "PREF_ADDR" , &CPU_PREF_ADDR, 1);
|
||||||
|
state_save_register_UINT32(type, cpu, "PREF_DATA" , &CPU_PREF_DATA, 1);
|
||||||
|
state_save_register_func_presave(m68k_prepare_substate);
|
||||||
|
state_save_register_func_postload(m68k_post_load);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* M68K_COMPILE_FOR_MAME */
|
||||||
|
|
||||||
|
/* ======================================================================== */
|
||||||
|
/* ============================== END OF FILE ============================= */
|
||||||
|
/* ======================================================================== */
|
2022
Src/CPU/68K/Musashi/m68kcpu.h
Normal file
2022
Src/CPU/68K/Musashi/m68kcpu.h
Normal file
File diff suppressed because it is too large
Load diff
3563
Src/CPU/68K/Musashi/m68kdasm.c
Normal file
3563
Src/CPU/68K/Musashi/m68kdasm.c
Normal file
File diff suppressed because it is too large
Load diff
1512
Src/CPU/68K/Musashi/m68kmake.c
Normal file
1512
Src/CPU/68K/Musashi/m68kmake.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1900,14 +1900,14 @@ void CModel3::RunFrame(void)
|
||||||
|
|
||||||
//printf("---*\n");
|
//printf("---*\n");
|
||||||
}
|
}
|
||||||
SoundBoard.RunFrame();
|
|
||||||
IRQ.Deassert(0x40);
|
|
||||||
|
|
||||||
|
|
||||||
// Print out sound command buffer in Scud Race RAM
|
// Print out sound command buffer in Scud Race RAM
|
||||||
printf("cmdbuf=%08X %08X %08X %08X %08X %08X %08X %08X\n", Read32(0x100180), Read32(0x100184), Read32(0x100188), Read32(0x10018C), Read32(0x100190), Read32(0x100194), Read32(0x100198), Read32(0x10019C));
|
printf("cmdbuf=%08X %08X %08X %08X %08X %08X %08X %08X\n", Read32(0x100180), Read32(0x100184), Read32(0x100188), Read32(0x10018C), Read32(0x100190), Read32(0x100194), Read32(0x100198), Read32(0x10019C));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SoundBoard.RunFrame();
|
||||||
|
IRQ.Deassert(0x40);
|
||||||
|
|
||||||
// End frame
|
// End frame
|
||||||
GPU.EndFrame();
|
GPU.EndFrame();
|
||||||
TileGen.EndFrame();
|
TileGen.EndFrame();
|
||||||
|
|
|
@ -34,178 +34,264 @@ static INT16 leftBuffer[44100/60],rightBuffer[44100/60];
|
||||||
static FILE *soundFP;
|
static FILE *soundFP;
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
Global 68K Access Handlers
|
68K Access Handlers
|
||||||
|
|
||||||
The 68K must interface with globally-accessible memory maps and access
|
|
||||||
handlers. Turbo68K uses the __cdecl calling convention. Note that this is not
|
|
||||||
explicitly defined for the Turbo68K functions themselves but in case Turbo68K
|
|
||||||
crashes, this may be the culprit.
|
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
// Prototypes for access handlers
|
// Memory regions passed out of CSoundBoard object for global access handlers
|
||||||
#ifdef SUPERMODEL_SOUND
|
static UINT8 *sbRAM1, *sbRAM2;
|
||||||
static UINT8 __cdecl UnknownRead8(UINT32);
|
static const UINT8 *sbSoundROM, *sbSampleROM;
|
||||||
static UINT16 __cdecl UnknownRead16(UINT32);
|
|
||||||
static UINT32 __cdecl UnknownRead32(UINT32);
|
|
||||||
static void __cdecl UnknownWrite8(UINT32, UINT8);
|
|
||||||
static void __cdecl UnknownWrite16(UINT32, UINT16);
|
|
||||||
static void __cdecl UnknownWrite32(UINT32, UINT32);
|
|
||||||
|
|
||||||
// Memory maps for 68K
|
static UINT8 Read8(UINT32 a)
|
||||||
struct TURBO68K_FETCHREGION mapFetch[] =
|
|
||||||
{
|
{
|
||||||
{ 0x000000, 0x0FFFFF, NULL }, // SCSP1 RAM
|
// SCSP RAM 1
|
||||||
{ 0x200000, 0x2FFFFF, NULL }, // SCSP2 RAM
|
if ((a >= 0x000000) && (a <= 0x0FFFFF))
|
||||||
{ 0x600000, 0x67FFFF, NULL }, // program ROM
|
return sbRAM1[a^1];
|
||||||
{ -1, -1, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TURBO68K_DATAREGION mapRead8[] =
|
// SCSP RAM 2
|
||||||
{
|
else if ((a >= 0x200000) && (a <= 0x2FFFFF))
|
||||||
{ 0x000000, 0x0FFFFF, NULL, NULL }, // SCSP1 RAM
|
return sbRAM2[(a-0x200000)^1];
|
||||||
{ 0x200000, 0x2FFFFF, NULL, NULL }, // SCSP2 RAM
|
|
||||||
{ 0x600000, 0x67FFFF, NULL, NULL }, // program ROM
|
|
||||||
{ 0x800000, 0x9FFFFF, NULL, NULL }, // sample ROM (low 2 MB)
|
|
||||||
{ 0xA00000, 0xDFFFFF, NULL, NULL }, // sample ROM (bank)
|
|
||||||
{ 0xE00000, 0xFFFFFF, NULL, NULL }, // sample ROM (bank)
|
|
||||||
{ 0x100000, 0x10FFFF, NULL, SCSP_Master_r8 },
|
|
||||||
{ 0x300000, 0x30FFFF, NULL, SCSP_Slave_r8 },
|
|
||||||
{ 0x000000, 0xFFFFFF, NULL, UnknownRead8 },
|
|
||||||
{ -1, -1, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TURBO68K_DATAREGION mapRead16[] =
|
// Program ROM
|
||||||
{
|
else if ((a >= 0x600000) && (a <= 0x67FFFF))
|
||||||
{ 0x000000, 0x0FFFFF, NULL, NULL }, // SCSP1 RAM
|
return sbSoundROM[(a-0x600000)^1];
|
||||||
{ 0x200000, 0x2FFFFF, NULL, NULL }, // SCSP2 RAM
|
|
||||||
{ 0x600000, 0x67FFFF, NULL, NULL }, // program ROM
|
|
||||||
{ 0x800000, 0x9FFFFF, NULL, NULL }, // sample ROM (low 2 MB)
|
|
||||||
{ 0xA00000, 0xDFFFFF, NULL, NULL }, // sample ROM (bank)
|
|
||||||
{ 0xE00000, 0xFFFFFF, NULL, NULL }, // sample ROM (bank)
|
|
||||||
{ 0x100000, 0x10FFFF, NULL, SCSP_Master_r16 },
|
|
||||||
{ 0x300000, 0x30FFFF, NULL, SCSP_Slave_r16 },
|
|
||||||
{ 0x000000, 0xFFFFFF, NULL, UnknownRead16 },
|
|
||||||
{ -1, -1, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TURBO68K_DATAREGION mapRead32[] =
|
// Sample ROM (low 2MB, fixed)
|
||||||
{
|
else if ((a >= 0x800000) && (a <= 0x9FFFFF))
|
||||||
{ 0x000000, 0x0FFFFF, NULL, NULL }, // SCSP1 RAM
|
return sbSampleROM[(a-0x800000)^1];
|
||||||
{ 0x200000, 0x2FFFFF, NULL, NULL }, // SCSP2 RAM
|
|
||||||
{ 0x600000, 0x67FFFF, NULL, NULL }, // program ROM
|
|
||||||
{ 0x800000, 0x9FFFFF, NULL, NULL }, // sample ROM (low 2 MB)
|
|
||||||
{ 0xA00000, 0xDFFFFF, NULL, NULL }, // sample ROM (bank)
|
|
||||||
{ 0xE00000, 0xFFFFFF, NULL, NULL }, // sample ROM (bank)
|
|
||||||
{ 0x100000, 0x10FFFF, NULL, SCSP_Master_r32 },
|
|
||||||
{ 0x300000, 0x30FFFF, NULL, SCSP_Slave_r32 },
|
|
||||||
{ 0x000000, 0xFFFFFF, NULL, UnknownRead32 },
|
|
||||||
{ -1, -1, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TURBO68K_DATAREGION mapWrite8[] =
|
// Sample ROM (bank)
|
||||||
{
|
else if ((a >= 0xA00000) && (a <= 0xDFFFFF))
|
||||||
{ 0x000000, 0x0FFFFF, NULL, NULL }, // SCSP1 RAM
|
return sbSampleROM[(a-0x800000)^1];
|
||||||
{ 0x200000, 0x2FFFFF, NULL, NULL }, // SCSP2 RAM
|
|
||||||
{ 0x100000, 0x10FFFF, NULL, SCSP_Master_w8 },
|
|
||||||
{ 0x300000, 0x30FFFF, NULL, SCSP_Slave_w8 },
|
|
||||||
{ 0x000000, 0xFFFFFF, NULL, UnknownWrite8 },
|
|
||||||
{ -1, -1, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TURBO68K_DATAREGION mapWrite16[] =
|
// Sample ROM (bank)
|
||||||
{
|
else if ((a >= 0xE00000) && (a <= 0xFFFFFF))
|
||||||
{ 0x000000, 0x0FFFFF, NULL, NULL }, // SCSP1 RAM
|
return sbSampleROM[(a-0x800000)^1];
|
||||||
{ 0x200000, 0x2FFFFF, NULL, NULL }, // SCSP2 RAM
|
|
||||||
{ 0x100000, 0x10FFFF, NULL, SCSP_Master_w16 },
|
|
||||||
{ 0x300000, 0x30FFFF, NULL, SCSP_Slave_w16 },
|
|
||||||
{ 0x000000, 0xFFFFFF, NULL, UnknownWrite16 },
|
|
||||||
{ -1, -1, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TURBO68K_DATAREGION mapWrite32[] =
|
// SCSP (Master)
|
||||||
{
|
else if ((a >= 0x100000) && (a <= 0x10FFFF))
|
||||||
{ 0x000000, 0x0FFFFF, NULL, NULL }, // SCSP1 RAM
|
return SCSP_Master_r8(a);
|
||||||
{ 0x200000, 0x2FFFFF, NULL, NULL }, // SCSP2 RAM
|
|
||||||
{ 0x100000, 0x10FFFF, NULL, SCSP_Master_w32 },
|
|
||||||
{ 0x300000, 0x30FFFF, NULL, SCSP_Slave_w32 },
|
|
||||||
{ 0x000000, 0xFFFFFF, NULL, UnknownWrite32 },
|
|
||||||
{ -1, -1, NULL, NULL }
|
|
||||||
};
|
|
||||||
|
|
||||||
static UINT8 __cdecl UnknownRead8(UINT32 addr)
|
// SCSP (Slave)
|
||||||
{
|
else if ((a >= 0x300000) && (a <= 0x30FFFF))
|
||||||
printf("68K read from %06X (byte)\n", addr);
|
return SCSP_Slave_r8(a);
|
||||||
return 0;
|
|
||||||
|
// Unknown
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("68K: Unknown read8 %06X\n", a);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT16 __cdecl UnknownRead16(UINT32 addr)
|
static UINT16 Read16(UINT32 a)
|
||||||
{
|
{
|
||||||
printf("68K read from %06X (word)\n", addr);
|
// SCSP RAM 1
|
||||||
return 0;
|
if ((a >= 0x000000) && (a <= 0x0FFFFF))
|
||||||
|
return *(UINT16 *) &sbRAM1[a];
|
||||||
|
|
||||||
|
// SCSP RAM 2
|
||||||
|
else if ((a >= 0x200000) && (a <= 0x2FFFFF))
|
||||||
|
return *(UINT16 *) &sbRAM2[(a-0x200000)];
|
||||||
|
|
||||||
|
// Program ROM
|
||||||
|
else if ((a >= 0x600000) && (a <= 0x67FFFF))
|
||||||
|
return *(UINT16 *) &sbSoundROM[(a-0x600000)];
|
||||||
|
|
||||||
|
// Sample ROM (low 2MB, fixed)
|
||||||
|
else if ((a >= 0x800000) && (a <= 0x9FFFFF))
|
||||||
|
return *(UINT16 *) &sbSampleROM[(a-0x800000)];
|
||||||
|
|
||||||
|
// Sample ROM (bank)
|
||||||
|
else if ((a >= 0xA00000) && (a <= 0xDFFFFF))
|
||||||
|
return *(UINT16 *) &sbSampleROM[(a-0x800000)];
|
||||||
|
|
||||||
|
// Sample ROM (bank)
|
||||||
|
else if ((a >= 0xE00000) && (a <= 0xFFFFFF))
|
||||||
|
return *(UINT16 *) &sbSampleROM[(a-0x800000)];
|
||||||
|
|
||||||
|
// SCSP (Master)
|
||||||
|
else if ((a >= 0x100000) && (a <= 0x10FFFF))
|
||||||
|
return SCSP_Master_r16(a);
|
||||||
|
|
||||||
|
// SCSP (Slave)
|
||||||
|
else if ((a >= 0x300000) && (a <= 0x30FFFF))
|
||||||
|
return SCSP_Slave_r16(a);
|
||||||
|
|
||||||
|
// Unknown
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("68K: Unknown read16 %06X\n", a);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT32 __cdecl UnknownRead32(UINT32 addr)
|
static UINT32 Read32(UINT32 a)
|
||||||
{
|
{
|
||||||
printf("68K read from %06X (longword)\n", addr);
|
// SCSP RAM 1
|
||||||
return 0;
|
if ((a >= 0x000000) && (a <= 0x0FFFFF))
|
||||||
|
return (Read16(a)<<16)|Read16(a+2);
|
||||||
|
|
||||||
|
// SCSP RAM 2
|
||||||
|
else if ((a >= 0x200000) && (a <= 0x2FFFFF))
|
||||||
|
return (Read16(a)<<16)|Read16(a+2);
|
||||||
|
|
||||||
|
// Program ROM
|
||||||
|
else if ((a >= 0x600000) && (a <= 0x67FFFF))
|
||||||
|
return (Read16(a)<<16)|Read16(a+2);
|
||||||
|
|
||||||
|
// Sample ROM (low 2MB, fixed)
|
||||||
|
else if ((a >= 0x800000) && (a <= 0x9FFFFF))
|
||||||
|
return (Read16(a)<<16)|Read16(a+2);
|
||||||
|
|
||||||
|
// Sample ROM (bank)
|
||||||
|
else if ((a >= 0xA00000) && (a <= 0xDFFFFF))
|
||||||
|
return (Read16(a)<<16)|Read16(a+2);
|
||||||
|
|
||||||
|
// Sample ROM (bank)
|
||||||
|
else if ((a >= 0xE00000) && (a <= 0xFFFFFF))
|
||||||
|
return (Read16(a)<<16)|Read16(a+2);
|
||||||
|
|
||||||
|
// SCSP (Master)
|
||||||
|
else if ((a >= 0x100000) && (a <= 0x10FFFF))
|
||||||
|
return SCSP_Master_r32(a);
|
||||||
|
|
||||||
|
// SCSP (Slave)
|
||||||
|
else if ((a >= 0x300000) && (a <= 0x30FFFF))
|
||||||
|
return SCSP_Slave_r32(a);
|
||||||
|
|
||||||
|
// Unknown
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("68K: Unknown read32 %06X\n", a);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Write8 (unsigned int a,unsigned char d)
|
||||||
static void __cdecl UnknownWrite8(UINT32 addr, UINT8 data)
|
|
||||||
{
|
{
|
||||||
printf("68K wrote %06X=%02X\n", addr, data);
|
|
||||||
|
// SCSP RAM 1
|
||||||
|
if ((a >= 0x000000) && (a <= 0x0FFFFF))
|
||||||
|
sbRAM1[a^1] = d;
|
||||||
|
|
||||||
|
// SCSP RAM 2
|
||||||
|
else if ((a >= 0x200000) && (a <= 0x2FFFFF))
|
||||||
|
sbRAM2[(a-0x200000)^1] = d;
|
||||||
|
|
||||||
|
// SCSP (Master)
|
||||||
|
else if ((a >= 0x100000) && (a <= 0x10FFFF))
|
||||||
|
SCSP_Master_w8(a,d);
|
||||||
|
|
||||||
|
// SCSP (Slave)
|
||||||
|
else if ((a >= 0x300000) && (a <= 0x30FFFF))
|
||||||
|
SCSP_Slave_w8(a,d);
|
||||||
|
|
||||||
|
// Unknown
|
||||||
|
else
|
||||||
|
printf("68K: Unknown write8 %06X=%02X\n", a, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __cdecl UnknownWrite16(UINT32 addr, UINT16 data)
|
static void Write16(unsigned int a,unsigned short d)
|
||||||
{
|
{
|
||||||
printf("68K wrote %06X=%04X\n", addr, data);
|
|
||||||
|
// SCSP RAM 1
|
||||||
|
if ((a >= 0x000000) && (a <= 0x0FFFFF))
|
||||||
|
*(UINT16 *) &sbRAM1[a] = d;
|
||||||
|
|
||||||
|
// SCSP RAM 2
|
||||||
|
else if ((a >= 0x200000) && (a <= 0x2FFFFF))
|
||||||
|
*(UINT16 *) &sbRAM2[(a-0x200000)] = d;
|
||||||
|
|
||||||
|
// SCSP (Master)
|
||||||
|
else if ((a >= 0x100000) && (a <= 0x10FFFF))
|
||||||
|
SCSP_Master_w16(a,d);
|
||||||
|
|
||||||
|
// SCSP (Slave)
|
||||||
|
else if ((a >= 0x300000) && (a <= 0x30FFFF))
|
||||||
|
SCSP_Slave_w16(a,d);
|
||||||
|
|
||||||
|
// Unknown
|
||||||
|
else
|
||||||
|
printf("68K: Unknown write16 %06X=%04X\n", a, d);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __cdecl UnknownWrite32(UINT32 addr, UINT32 data)
|
static void Write32(unsigned int a,unsigned int d)
|
||||||
{
|
{
|
||||||
printf("68K wrote %06X=%08X\n", addr, data);
|
// SCSP RAM 1
|
||||||
|
if ((a >= 0x000000) && (a <= 0x0FFFFF))
|
||||||
|
{
|
||||||
|
Write16(a,d>>16);
|
||||||
|
Write16(a+2,d&0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SCSP RAM 2
|
||||||
|
else if ((a >= 0x200000) && (a <= 0x2FFFFF))
|
||||||
|
{
|
||||||
|
Write16(a,d>>16);
|
||||||
|
Write16(a+2,d&0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SCSP (Master)
|
||||||
|
else if ((a >= 0x100000) && (a <= 0x10FFFF))
|
||||||
|
SCSP_Master_w32(a,d);
|
||||||
|
|
||||||
|
// SCSP (Slave)
|
||||||
|
else if ((a >= 0x300000) && (a <= 0x30FFFF))
|
||||||
|
SCSP_Slave_w32(a,d);
|
||||||
|
|
||||||
|
// Unknown
|
||||||
|
else
|
||||||
|
printf("68K: Unknown write32 %06X=%08X\n", a, d);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
Emulation Functions
|
SCSP 68K Callbacks
|
||||||
|
|
||||||
|
The SCSP emulator drives the 68K via callbacks.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
int irqLine = 0;
|
|
||||||
|
// Status of IRQ pins (IPL2-0) on 68K
|
||||||
|
static int irqLine = 0;
|
||||||
|
|
||||||
|
// Interrupt acknowledge callback (TODO: don't need this, default behavior in M68K.cpp is fine)
|
||||||
|
int IRQAck(int irqLevel)
|
||||||
|
{
|
||||||
|
M68KSetIRQ(0);
|
||||||
|
irqLine = 0;
|
||||||
|
return M68K_IRQ_AUTOVECTOR;
|
||||||
|
}
|
||||||
|
|
||||||
// SCSP callback for generating IRQs
|
// SCSP callback for generating IRQs
|
||||||
void SCSP68KIRQCallback(int irqNum)
|
void SCSP68KIRQCallback(int irqLevel)
|
||||||
{
|
{
|
||||||
#ifdef SUPERMODEL_SOUND
|
/*
|
||||||
//printf("IRQ: %d\n", irqNum);
|
* IRQ arbitration logic: only allow higher priority IRQs to be asserted or
|
||||||
irqLine = irqNum;
|
* 0 to clear pending IRQ.
|
||||||
//Turbo68KInterrupt(irqNum, TURBO68K_AUTOVECTOR);
|
*/
|
||||||
#endif
|
if ((irqLevel>irqLine) || (0==irqLevel))
|
||||||
|
{
|
||||||
|
irqLine = irqLevel;
|
||||||
|
|
||||||
|
}
|
||||||
|
M68KSetIRQ(irqLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SCSP callback for running the 68K
|
// SCSP callback for running the 68K
|
||||||
int SCSP68KRunCallback(int numCycles)
|
int SCSP68KRunCallback(int numCycles)
|
||||||
{
|
{
|
||||||
#ifdef SUPERMODEL_SOUND
|
return M68KRun(numCycles);
|
||||||
for (int i = 0; i < numCycles; i++)
|
|
||||||
{
|
|
||||||
if (irqLine)
|
|
||||||
Turbo68KInterrupt(irqLine,TURBO68K_AUTOVECTOR);
|
|
||||||
Turbo68KRun(1);
|
|
||||||
}
|
|
||||||
return numCycles;
|
|
||||||
//Turbo68KRun(numCycles);
|
|
||||||
//return Turbo68KGetElapsedCycles();
|
|
||||||
#else
|
|
||||||
return numCycles;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
Sound Board Emulation
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
void CSoundBoard::WriteMIDIPort(UINT8 data)
|
void CSoundBoard::WriteMIDIPort(UINT8 data)
|
||||||
{
|
{
|
||||||
#ifdef SUPERMODEL_SOUND
|
|
||||||
SCSP_MidiIn(data);
|
SCSP_MidiIn(data);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSoundBoard::RunFrame(void)
|
void CSoundBoard::RunFrame(void)
|
||||||
|
@ -227,18 +313,8 @@ void CSoundBoard::RunFrame(void)
|
||||||
|
|
||||||
void CSoundBoard::Reset(void)
|
void CSoundBoard::Reset(void)
|
||||||
{
|
{
|
||||||
#ifdef SUPERMODEL_SOUND
|
|
||||||
memcpy(ram1, soundROM, 16); // copy 68K vector table
|
memcpy(ram1, soundROM, 16); // copy 68K vector table
|
||||||
Turbo68KReset();
|
M68KReset();
|
||||||
/*
|
|
||||||
printf("68K PC=%06X\n", Turbo68KReadPC());
|
|
||||||
for (int i = 0; i < 1000000; i++)
|
|
||||||
{
|
|
||||||
//printf("%06X\n", Turbo68KReadPC());
|
|
||||||
Turbo68KRun(1);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
#endif
|
|
||||||
DebugLog("Sound Board Reset\n");
|
DebugLog("Sound Board Reset\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,13 +324,12 @@ void CSoundBoard::Reset(void)
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
// Offsets of memory regions within sound board's pool
|
// Offsets of memory regions within sound board's pool
|
||||||
#define OFFSET_RAM1 0 // 1 MB SCSP1 RAM
|
#define OFFSETsbRAM1 0 // 1 MB SCSP1 RAM
|
||||||
#define OFFSET_RAM2 0x100000 // 1 MB SCSP2 RAM
|
#define OFFSETsbRAM2 0x100000 // 1 MB SCSP2 RAM
|
||||||
#define MEMORY_POOL_SIZE (0x100000+0x100000)
|
#define MEMORY_POOL_SIZE (0x100000+0x100000)
|
||||||
|
|
||||||
BOOL CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr, CIRQ *ppcIRQObjectPtr, unsigned soundIRQBit)
|
BOOL CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr, CIRQ *ppcIRQObjectPtr, unsigned soundIRQBit)
|
||||||
{
|
{
|
||||||
#ifdef SUPERMODEL_SOUND
|
|
||||||
float memSizeMB = (float)MEMORY_POOL_SIZE/(float)0x100000;
|
float memSizeMB = (float)MEMORY_POOL_SIZE/(float)0x100000;
|
||||||
|
|
||||||
// Attach IRQ controller
|
// Attach IRQ controller
|
||||||
|
@ -272,32 +347,27 @@ BOOL CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr, CIRQ
|
||||||
memset(memoryPool, 0, MEMORY_POOL_SIZE);
|
memset(memoryPool, 0, MEMORY_POOL_SIZE);
|
||||||
|
|
||||||
// Set up memory pointers
|
// Set up memory pointers
|
||||||
ram1 = &memoryPool[OFFSET_RAM1];
|
ram1 = &memoryPool[OFFSETsbRAM1];
|
||||||
ram2 = &memoryPool[OFFSET_RAM2];
|
ram2 = &memoryPool[OFFSETsbRAM2];
|
||||||
|
|
||||||
|
// Make global copies of memory pointers for 68K access handlers
|
||||||
|
sbRAM1 = ram1;
|
||||||
|
sbRAM2 = ram2;
|
||||||
|
sbSoundROM = soundROM;
|
||||||
|
sbSampleROM = sampleROM;
|
||||||
|
|
||||||
// Initialize 68K core
|
// Initialize 68K core
|
||||||
mapFetch[0].ptr = mapRead8[0].ptr = mapRead16[0].ptr = mapRead32[0].ptr =
|
M68KInit();
|
||||||
mapWrite8[0].ptr = mapWrite16[0].ptr = mapWrite32[0].ptr = (UINT32)ram1 - mapFetch[0].base;;
|
M68KSetIRQCallback(IRQAck);
|
||||||
|
M68KSetFetch8Callback(Read8);
|
||||||
mapFetch[1].ptr = mapRead8[1].ptr = mapRead16[1].ptr = mapRead32[1].ptr =
|
M68KSetFetch16Callback(Read16);
|
||||||
mapWrite8[1].ptr = mapWrite16[1].ptr = mapWrite32[1].ptr = (UINT32)ram2 - mapFetch[1].base;
|
M68KSetFetch32Callback(Read32);
|
||||||
|
M68KSetRead8Callback(Read8);
|
||||||
mapFetch[2].ptr = mapRead8[2].ptr = mapRead16[2].ptr = mapRead32[2].ptr = (UINT32)soundROM - mapFetch[2].base;
|
M68KSetRead16Callback(Read16);
|
||||||
|
M68KSetRead32Callback(Read32);
|
||||||
mapRead8[3].ptr = mapRead16[3].ptr = mapRead32[3].ptr = (UINT32)&sampleROM[0x000000] - mapRead8[3].base;
|
M68KSetWrite8Callback(Write8);
|
||||||
|
M68KSetWrite16Callback(Write16);
|
||||||
mapRead8[4].ptr = mapRead16[4].ptr = mapRead32[4].ptr = (UINT32)&sampleROM[0x200000] - mapRead8[4].base;
|
M68KSetWrite32Callback(Write32);
|
||||||
|
|
||||||
mapRead8[5].ptr = mapRead16[5].ptr = mapRead32[5].ptr = (UINT32)&sampleROM[0x600000] - mapRead8[5].base;
|
|
||||||
|
|
||||||
Turbo68KInit();
|
|
||||||
Turbo68KSetFetch(mapFetch, NULL);
|
|
||||||
Turbo68KSetReadByte(mapRead8, NULL);
|
|
||||||
Turbo68KSetReadWord(mapRead16, NULL);
|
|
||||||
Turbo68KSetReadLong(mapRead32, NULL);
|
|
||||||
Turbo68KSetWriteByte(mapWrite8, NULL);
|
|
||||||
Turbo68KSetWriteWord(mapWrite16, NULL);
|
|
||||||
Turbo68KSetWriteLong(mapWrite32, NULL);
|
|
||||||
|
|
||||||
// Initialize SCSPs
|
// Initialize SCSPs
|
||||||
SCSP_SetBuffers(leftBuffer, rightBuffer, 44100/60);
|
SCSP_SetBuffers(leftBuffer, rightBuffer, 44100/60);
|
||||||
|
@ -307,6 +377,7 @@ BOOL CSoundBoard::Init(const UINT8 *soundROMPtr, const UINT8 *sampleROMPtr, CIRQ
|
||||||
SCSP_SetRAM(1, ram2);
|
SCSP_SetRAM(1, ram2);
|
||||||
|
|
||||||
// Binary logging
|
// Binary logging
|
||||||
|
#ifdef SUPERMODEL_SOUND
|
||||||
soundFP = fopen("sound.bin","wb"); // delete existing file
|
soundFP = fopen("sound.bin","wb"); // delete existing file
|
||||||
fclose(soundFP);
|
fclose(soundFP);
|
||||||
soundFP = fopen("sound.bin","ab"); // append mode
|
soundFP = fopen("sound.bin","ab"); // append mode
|
||||||
|
@ -364,6 +435,7 @@ CSoundBoard::~CSoundBoard(void)
|
||||||
|
|
||||||
}
|
}
|
||||||
//#endif
|
//#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
SCSP_Deinit();
|
SCSP_Deinit();
|
||||||
|
|
||||||
|
@ -374,7 +446,5 @@ CSoundBoard::~CSoundBoard(void)
|
||||||
}
|
}
|
||||||
ram1 = NULL;
|
ram1 = NULL;
|
||||||
ram2 = NULL;
|
ram2 = NULL;
|
||||||
#endif
|
|
||||||
|
|
||||||
DebugLog("Destroyed Sound Board\n");
|
DebugLog("Destroyed Sound Board\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -545,6 +545,9 @@ int Supermodel(const char *zipFile, CInputs *Inputs, unsigned ppcFrequency, unsi
|
||||||
|
|
||||||
SCSP_MidiIn(0xAF);SCSP_MidiIn(0x10);SCSP_MidiIn(0x01);
|
SCSP_MidiIn(0xAF);SCSP_MidiIn(0x10);SCSP_MidiIn(0x01);
|
||||||
*/
|
*/
|
||||||
|
SCSP_MidiIn(0xAF);SCSP_MidiIn(0x10);SCSP_MidiIn(0x00);
|
||||||
|
//static int snd=0xF;
|
||||||
|
//SCSP_MidiIn(0xA0);SCSP_MidiIn(0x11);SCSP_MidiIn(snd++);
|
||||||
//Sound codes:
|
//Sound codes:
|
||||||
// A0 11 xx (0F=time extend, 11=jumbo left right)
|
// A0 11 xx (0F=time extend, 11=jumbo left right)
|
||||||
// AF 10 xx (music -- 01 seems to work)
|
// AF 10 xx (music -- 01 seems to work)
|
||||||
|
@ -635,9 +638,6 @@ int Supermodel(const char *zipFile, CInputs *Inputs, unsigned ppcFrequency, unsi
|
||||||
printf("SR%d=%08X\n", i, ppc_read_sr(i));
|
printf("SR%d=%08X\n", i, ppc_read_sr(i));
|
||||||
printf("SDR1=%08X\n", ppc_read_spr(SPR603E_SDR1));
|
printf("SDR1=%08X\n", ppc_read_spr(SPR603E_SDR1));
|
||||||
*/
|
*/
|
||||||
#ifdef SUPERMODEL_SOUND
|
|
||||||
printf("68K PC =%08X\n", Turbo68KReadPC());
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -22,7 +22,9 @@
|
||||||
/*
|
/*
|
||||||
* Types.h
|
* Types.h
|
||||||
*
|
*
|
||||||
* Fundamental data types.
|
* Fundamental data types. This file is used by both C++ and C modules, so it
|
||||||
|
* must NOT include any C++-specific constructs. Some modules may elect to
|
||||||
|
* include it directly rather than through Supermodel.h.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef INCLUDED_TYPES_H
|
#ifndef INCLUDED_TYPES_H
|
||||||
|
|
|
@ -738,6 +738,7 @@ void SCSP_UpdateSlotReg(int s,int r)
|
||||||
if(KEYONB(s2) && (!s2->active || (s2->active && s2->EG.state==RELEASE)))
|
if(KEYONB(s2) && (!s2->active || (s2->active && s2->EG.state==RELEASE)))
|
||||||
{
|
{
|
||||||
DebugLog("KEYON %d",sl);
|
DebugLog("KEYON %d",sl);
|
||||||
|
printf("KEYON %d\n",sl);
|
||||||
SCSP_StartSlot(s2);
|
SCSP_StartSlot(s2);
|
||||||
}
|
}
|
||||||
if(!KEYONB(s2) && s2->active)
|
if(!KEYONB(s2) && s2->active)
|
||||||
|
@ -880,7 +881,7 @@ void SCSP_UpdateRegR(int reg)
|
||||||
unsigned short v=SCSP->data[0x5/2];
|
unsigned short v=SCSP->data[0x5/2];
|
||||||
v&=0xff00;
|
v&=0xff00;
|
||||||
v|=MidiStack[MidiR];
|
v|=MidiStack[MidiR];
|
||||||
printf("read MIDI\n");
|
//printf("read MIDI\n");
|
||||||
if(MidiR!=MidiW)
|
if(MidiR!=MidiW)
|
||||||
{
|
{
|
||||||
++MidiR;
|
++MidiR;
|
||||||
|
@ -914,6 +915,7 @@ void SCSP_w8(unsigned int addr,unsigned char val)
|
||||||
int slot=addr/0x20;
|
int slot=addr/0x20;
|
||||||
addr&=0x1f;
|
addr&=0x1f;
|
||||||
DebugLog("Slot %02X Reg %02X write byte %04X",slot,addr^1,val);
|
DebugLog("Slot %02X Reg %02X write byte %04X",slot,addr^1,val);
|
||||||
|
printf("Slot %02X Reg %02X write byte %04X\n",slot,addr^1,val);
|
||||||
*((unsigned char *) (SCSP->Slots[slot].datab+(addr^1))) = val;
|
*((unsigned char *) (SCSP->Slots[slot].datab+(addr^1))) = val;
|
||||||
SCSP_UpdateSlotReg(slot,(addr^1)&0x1f);
|
SCSP_UpdateSlotReg(slot,(addr^1)&0x1f);
|
||||||
}
|
}
|
||||||
|
@ -953,6 +955,7 @@ void SCSP_w16(unsigned int addr,unsigned short val)
|
||||||
int slot=addr/0x20;
|
int slot=addr/0x20;
|
||||||
addr&=0x1f;
|
addr&=0x1f;
|
||||||
DebugLog("Slot %02X Reg %02X write word %04X",slot,addr,val);
|
DebugLog("Slot %02X Reg %02X write word %04X",slot,addr,val);
|
||||||
|
printf("Slot %02X Reg %02X write word %04X\n",slot,addr,val);
|
||||||
*((unsigned short *) (SCSP->Slots[slot].datab+(addr))) = val;
|
*((unsigned short *) (SCSP->Slots[slot].datab+(addr))) = val;
|
||||||
SCSP_UpdateSlotReg(slot,addr&0x1f);
|
SCSP_UpdateSlotReg(slot,addr&0x1f);
|
||||||
}
|
}
|
||||||
|
@ -992,6 +995,7 @@ void SCSP_w32(unsigned int addr,unsigned int val)
|
||||||
int slot=addr/0x20;
|
int slot=addr/0x20;
|
||||||
addr&=0x1f;
|
addr&=0x1f;
|
||||||
DebugLog("Slot %02X Reg %02X write dword %08X",slot,addr,val);
|
DebugLog("Slot %02X Reg %02X write dword %08X",slot,addr,val);
|
||||||
|
printf("Slot %02X Reg %02X write dword %08X\n",slot,addr,val);
|
||||||
_asm rol val,16
|
_asm rol val,16
|
||||||
*((unsigned int *) (SCSP->Slots[slot].datab+(addr))) = val;
|
*((unsigned int *) (SCSP->Slots[slot].datab+(addr))) = val;
|
||||||
SCSP_UpdateSlotReg(slot,addr&0x1f);
|
SCSP_UpdateSlotReg(slot,addr&0x1f);
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
Program-Wide Definitions
|
Program-Wide Definitions
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
#define SUPERMODEL_VERSION "0.2-WIP" // version string
|
#define SUPERMODEL_VERSION "0.2a-WIP" // version string
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
|
@ -63,6 +63,10 @@
|
||||||
* INT8 Signed 8-bit integer.
|
* INT8 Signed 8-bit integer.
|
||||||
* FLOAT32 Single-precision, 32-bit floating point number.
|
* FLOAT32 Single-precision, 32-bit floating point number.
|
||||||
* FLOAT64 Double-precision, 64-bit floating point number.
|
* FLOAT64 Double-precision, 64-bit floating point number.
|
||||||
|
*
|
||||||
|
* Types.h is used within C++ and C modules, so it must NOT include any C++-
|
||||||
|
* specific stuff. Some modules may choose to include it directly rather than
|
||||||
|
* use Supermodel.h, so it must exist.
|
||||||
*/
|
*/
|
||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
|
@ -141,9 +145,7 @@ extern void InfoLog(const char *fmt, ...);
|
||||||
#endif // SUPERMODEL_DEBUGGER
|
#endif // SUPERMODEL_DEBUGGER
|
||||||
#include "CPU/PowerPC/PPCDisasm.h"
|
#include "CPU/PowerPC/PPCDisasm.h"
|
||||||
#include "CPU/PowerPC/ppc.h"
|
#include "CPU/PowerPC/ppc.h"
|
||||||
#ifdef SUPERMODEL_SOUND
|
#include "CPU/68K/M68K.h"
|
||||||
#include "CPU/68K/Turbo68K.h"
|
|
||||||
#endif // SUPERMODEL_SOUND
|
|
||||||
#include "Inputs/Input.h"
|
#include "Inputs/Input.h"
|
||||||
#include "Inputs/Inputs.h"
|
#include "Inputs/Inputs.h"
|
||||||
#include "Inputs/InputSource.h"
|
#include "Inputs/InputSource.h"
|
||||||
|
|
Loading…
Reference in a new issue