Created IEmulator interface, renamed CBus to IBus and CPCIDevice to IPCIDevice. Frames now rendered when emulator paused.

This commit is contained in:
Bart Trzynadlowski 2016-04-10 03:42:41 +00:00
parent f52cb3c491
commit 198a469ff7
19 changed files with 285 additions and 240 deletions

View file

@ -46,7 +46,7 @@
******************************************************************************/
// Bus
static CBus *s_Bus = NULL;
static IBus *s_Bus = NULL;
#ifdef SUPERMODEL_DEBUGGER
// Debugger
@ -263,7 +263,7 @@ void M68KSetIRQCallback(int (*F)(int nIRQ))
IRQAck = F;
}
void M68KAttachBus(CBus *BusPtr)
void M68KAttachBus(IBus *BusPtr)
{
s_Bus = BusPtr;
DebugLog("Attached bus to 68K\n");

View file

@ -72,7 +72,7 @@ typedef struct SM68KCtx
{
public:
m68ki_cpu_core musashiCtx; // CPU context
CBus *Bus; // memory handlers
IBus *Bus; // memory handlers
int (*IRQAck)(int); // IRQ acknowledge callback
#ifdef SUPERMODEL_DEBUGGER
CMusashi68KDebug *Debug; // holds debugger (if attached)
@ -215,7 +215,7 @@ extern void M68KReset(void);
extern void M68KSetIRQCallback(int (*F)(int));
/*
* M68KAttachBus(CBus *BusPtr):
* M68KAttachBus(IBus *BusPtr):
*
* Attaches a bus object to the 68K, which will be used to perform all address
* space accesses. The 8, 16, and 32-bit read and write handlers are used.
@ -225,7 +225,7 @@ extern void M68KSetIRQCallback(int (*F)(int));
* Parameters:
* BusPtr Pointer to bus object to use for all address space accesses.
*/
extern void M68KAttachBus(CBus *BusPtr);
extern void M68KAttachBus(IBus *BusPtr);
/*
* M68KInit():

View file

@ -22,7 +22,7 @@
/*
* Bus.h
*
* Header file for the CBus abstract base class.
* Header file for the IBus abstract base class.
*/
#ifndef INCLUDED_BUS_H
@ -30,15 +30,15 @@
/*
* CBus:
* IBus:
*
* An abstract base class for an address bus. Defines handlers for 8-, 16-,
* 32-, and 64-bit random access. Endianness should depend on the application.
* An interface for an address bus. Defines handlers for 8-, 16-, 32-, and 64-
* bit random access. Endianness should depend on the application.
*
* Two buses are supported: a memory bus and an IO bus. All addresses are 32
* bits.
*/
class CBus
class IBus
{
public:
/*

View file

@ -39,7 +39,7 @@ typedef unsigned int UINT;
#define INLINE inline
// Model 3 context provides read/write handlers
static class CBus *Bus = NULL; // pointer to Model 3 bus object (for access handlers)
static class IBus *Bus = NULL; // pointer to Model 3 bus object (for access handlers)
#ifdef SUPERMODEL_DEBUGGER
// Pointer to current PPC debugger (if any)
@ -913,7 +913,7 @@ int ppc_get_timer_ratio()
Supermodel Interface
******************************************************************************/
void ppc_attach_bus(CBus *BusPtr)
void ppc_attach_bus(IBus *BusPtr)
{
Bus = BusPtr;
}

View file

@ -359,7 +359,7 @@ extern int ppc_get_timer_ratio(void);
extern void ppc_set_timer_ratio(int ratio);
// These have been added to support the new Supermodel
extern void ppc_attach_bus(class CBus *BusPtr); // must be called first!
extern void ppc_attach_bus(class IBus *BusPtr); // must be called first!
extern void ppc_save_state(class CBlockFile *SaveState);
extern void ppc_load_state(class CBlockFile *SaveState);
extern UINT32 ppc_get_gpr(unsigned num);

View file

@ -3972,7 +3972,7 @@ void CZ80::LoadState(CBlockFile *StateFile, const char *name)
StateFile->Read(&intLine, sizeof(intLine));
}
void CZ80::Init(CBus *BusPtr, int (*INTF)(CZ80 *Z80))
void CZ80::Init(IBus *BusPtr, int (*INTF)(CZ80 *Z80))
{
Bus = BusPtr;
INTCallback = INTF;

View file

@ -277,7 +277,7 @@ public:
* INTF Pointer to callback function. The function accepts a
* a pointer to the Z80 object that received the interrupt.
*/
void Init(CBus *BusPtr, int (*INTF)(CZ80 *Z80));
void Init(IBus *BusPtr, int (*INTF)(CZ80 *Z80));
#ifdef SUPERMODEL_DEBUGGER
/*
@ -323,7 +323,7 @@ private:
int af_sel; // active AF
// Memory and IO bus
CBus *Bus;
IBus *Bus;
// Interrupts
bool nmiTrigger;

View file

@ -122,7 +122,8 @@ static bool SCRIPTS_MoveMemory(struct NCR53C810Context *Ctx)
// Not implemented: illegal instruction interrupt when src and dest are not aligned the same way
DebugLog("53C810: Move Memory %08X -> %08X, %X\n", src, dest, numBytes);
//if (dest==0x94000000)printf("53C810: Move Memory %08X -> %08X, %X\n", src, dest, numBytes);
// Perform a 32-bit copy if possible
for (i = 0; i < (numBytes/4); i++)
{
@ -477,7 +478,7 @@ void C53C810::Reset(void)
Configuration, Initialization, and Shutdown
******************************************************************************/
void C53C810::Init(CBus *BusObjectPtr, CIRQ *IRQObjectPtr, unsigned scsiIRQBit)
void C53C810::Init(IBus *BusObjectPtr, CIRQ *IRQObjectPtr, unsigned scsiIRQBit)
{
Ctx.Bus = BusObjectPtr;
Ctx.IRQ = IRQObjectPtr;

View file

@ -54,7 +54,7 @@ struct NCR53C810Context
bool halt; // set true if halted by interrupt instruction
// Big endian bus object for DMA memory access and instruction fetching
CBus *Bus;
IBus *Bus;
// IRQ handling
CIRQ *IRQ; // IRQ controller
@ -66,7 +66,7 @@ struct NCR53C810Context
*
* NCR 53C810 SCSI controller device.
*/
class C53C810: public CPCIDevice
class C53C810: public IPCIDevice
{
public:
/*
@ -172,7 +172,7 @@ public:
* scsiIRQBit IRQ identifier bit to pass along to IRQ controller
* when asserting interrupts.
*/
void Init(CBus *BusObjectPtr, CIRQ *IRQObjectPtr, unsigned scsiIRQBit);
void Init(IBus *BusObjectPtr, CIRQ *IRQObjectPtr, unsigned scsiIRQBit);
/*
* C53C810(void):

View file

@ -158,7 +158,7 @@ private:
* Abstract base class defining the common interface for both DSB board types.
*/
class CDSB: public CBus
class CDSB: public IBus
{
public:
/*

View file

@ -52,7 +52,7 @@ public:
/*
* CDriveBoard
*/
class CDriveBoard : public CBus
class CDriveBoard : public IBus
{
public:
/*

217
Src/Model3/IEmulator.h Normal file
View file

@ -0,0 +1,217 @@
//TODO: collapse constructor, Init() and LoadROMSet().
/**
** Supermodel
** A Sega Model 3 Arcade Emulator.
** Copyright 2011 Bart Trzynadlowski, Nik Henson
**
** 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/>.
**/
/*
* IEmulator.h
*
* Header file defining the emulator interface, IEmulator.
*/
#ifndef INCLUDED_IEMULATOR_H
#define INCLUDED_IEMULATOR_H
class CBlockFile;
struct GameInfo;
class CRender2D;
class IRender3D;
class CInputs;
class COutputs;
/*
* IEmulator:
*
* Interface (abstract base class) for emulation.
*/
class IEmulator
{
public:
/*
* SaveState(SaveState):
*
* Saves an image of the current state. Must never be called while emulator
* is running (i.e., inside RunFrame()).
*
* Parameters:
* SaveState Block file to save state information to.
*/
virtual void SaveState(CBlockFile *SaveState) = 0;
/*
* LoadState(SaveState):
*
* Loads and resumes execution from a state image. Modifies data that may
* be used by multiple threads -- use with caution and ensure threads are
* not accessing data that will be touched, this can be done by calling
* PauseThreads beforehand. Must never be called while emulator is running
* (inside RunFrame()).
*
* Parameters:
* SaveState Block file to load state information from.
*/
virtual void LoadState(CBlockFile *SaveState) = 0;
/*
* SaveNVRAM(NVRAM):
*
* Saves an image of the current non-volatile memory state.
*
* Parameters:
* NVRAM Block file to save NVRAM to.
*/
virtual void SaveNVRAM(CBlockFile *NVRAM) = 0;
/*
* LoadNVRAM(NVRAM):
*
* Loads a non-volatile memory state.
*
* Parameters:
* NVRAM Block file to load NVRAM state from.
*/
virtual void LoadNVRAM(CBlockFile *NVRAM) = 0;
/*
* ClearNVRAM(void):
*
* Clears all non-volatile memory.
*/
virtual void ClearNVRAM(void) = 0;
/*
* RunFrame(void):
*
* Runs one video frame.
*/
virtual void RunFrame(void) = 0;
/*
* RenderFrame(void):
*
* Renders one video frame.
*/
virtual void RenderFrame(void) = 0;
/*
* Reset(void):
*
* Resets the system. Does not modify non-volatile memory.
*/
virtual void Reset(void) = 0;
/*
* GetGameInfo(void):
*
* Returns:
* A pointer to the presently loaded game's information structure (or
* NULL if no ROM set has yet been loaded).
*/
virtual const struct GameInfo * GetGameInfo(void) = 0;
/*
* LoadROMSet(GameList, zipFile):
*
* Loads a complete ROM set from the specified ZIP archive.
*
* NOTE: Command line settings will not have been applied here yet.
*
* Parameters:
* GameList List of all supported games and their ROMs.
* zipFile ZIP file to load from.
*
* Returns:
* OKAY if successful, FAIL otherwise. Prints errors.
*/
virtual bool LoadROMSet(const struct GameInfo *GameList, const char *zipFile) = 0;
/*
* AttachRenderers(Render2DPtr, Render3DPtr):
*
* Attaches the renderers to the appropriate device objects.
*
* Parameters:
* Render2DPtr Pointer to a tile renderer object.
* Render3DPtr Same as above but for a 3D renderer.
*/
virtual void AttachRenderers(CRender2D *Render2DPtr, IRender3D *Render3DPtr) = 0;
/*
* AttachInputs(InputsPtr):
*
* Attaches OSD-managed inputs.
*
* Parameters:
* InputsPtr Pointer to the object containing input states.
*/
virtual void AttachInputs(CInputs *InputsPtr) = 0;
/*
* AttachInputs(InputsPtr):
*
* Attaches OSD-managed outputs (cabinet lamps, etc.)
*
* Parameters:
* OutputsPtr Pointer to the object containing output states.
*/
virtual void AttachOutputs(COutputs *OutputsPtr) = 0;
/*
* Init(void):
*
* One-time initialization of the context. Must be called prior to all
* other members.
*
* NOTE: Command line settings will not have been applied here yet.
*
* Returns:
* OKAY is successful, otherwise FAILED if a non-recoverable error
* occurred. Prints own error messages.
*/
virtual bool Init(void) = 0;
/*
* PauseThreads(void):
*
* Flags that any running threads should pause and waits for them to do so.
* Should be used before invoking any method that accesses the internal
* state, eg LoadState or SaveState.
*/
virtual bool PauseThreads(void) = 0;
/*
* ResumeThreads(void):
*
* Flags that any paused threads should resume running.
*/
virtual bool ResumeThreads(void) = 0;
/*
* ~IEmulator(void):
*
* Destructor. Must free all resources.
*/
virtual ~IEmulator(void)
{
}
};
#endif // INCLUDED_IEMULATOR_H

View file

@ -28,6 +28,7 @@
#ifndef INCLUDED_MODEL3_H
#define INCLUDED_MODEL3_H
#include "Model3/IEmulator.h"
#include "Model3/Crypto.h"
/*
@ -89,166 +90,46 @@ private:
*
* A complete Model 3 system.
*
* Inherits CBus in order to pass the address space handlers to devices that
* Inherits IBus in order to pass the address space handlers to devices that
* may need them (CPU, DMA, etc.)
*
* NOTE: Currently NOT re-entrant due to a non-OOP PowerPC core. Do NOT create
* create more than one CModel3 object!
*/
class CModel3: public CBus, public CPCIDevice
class CModel3: public IEmulator, public IBus, public IPCIDevice
{
public:
/*
* ReadPCIConfigSpace(device, reg, bits, offset):
*
* Handles unknown PCI devices. See CPCIDevice definition for more details.
*
* Parameters:
* device Device number.
* reg Register number.
* bits Bit width of access (8, 16, or 32 only).;
* offset Byte offset within register, aligned to the specified bit
* width, and offset from the 32-bit aligned base of the
* register number.
*
* Returns:
* Register data.
*/
// IEmulator interface
bool PauseThreads(void);
bool ResumeThreads(void);
void SaveState(CBlockFile *SaveState);
void LoadState(CBlockFile *SaveState);
void SaveNVRAM(CBlockFile *NVRAM);
void LoadNVRAM(CBlockFile *NVRAM);
void ClearNVRAM(void);
void RunFrame(void);
void RenderFrame(void);
void Reset(void);
const struct GameInfo * GetGameInfo(void);
void AttachRenderers(CRender2D *Render2DPtr, IRender3D *Render3DPtr);
void AttachInputs(CInputs *InputsPtr);
void AttachOutputs(COutputs *OutputsPtr);
bool Init(void);
// IPCIDevice interface
UINT32 ReadPCIConfigSpace(unsigned device, unsigned reg, unsigned bits, unsigned width);
/*
* WritePCIConfigSpace(device, reg, bits, offset, data):
*
* Handles unknown PCI devices. See CPCIDevice definition for more details.
*
* Parameters:
* device Device number.
* reg Register number.
* bits Bit width of access (8, 16, or 32 only).
* offset Byte offset within register, aligned to the specified bit
* width, and offset from the 32-bit aligned base of the
* register number.
* data Data.
*/
void WritePCIConfigSpace(unsigned device, unsigned reg, unsigned bits, unsigned width, UINT32 data);
/*
* Read8(addr):
* Read16(addr):
* Read32(addr):
* Read64(addr):
*
* Read a byte, 16-bit half word, 32-bit word, or 64-bit double word from
* the PowerPC address space. This implements the PowerPC address bus. Note
* that it is big endian, so when accessing from a little endian device,
* the byte order must be manually reversed.
*
* Parameters:
* addr Address to read.
*
* Returns:
* Data at the address.
*/
// IBus interface
UINT8 Read8(UINT32 addr);
UINT16 Read16(UINT32 addr);
UINT32 Read32(UINT32 addr);
UINT64 Read64(UINT32 addr);
/*
* Write8(addr, data):
* Write16(addr, data):
* Write32(addr, data):
* Write64(addr, data):
*
* Write a byte, half word, word, or double word to the PowerPC address
* space. Note that everything is stored in big endian form, so when
* accessing with a little endian device, the byte order must be manually
* reversed.
*
* Parameters:
* addr Address to write.
* data Data to write.
*/
void Write8(UINT32 addr, UINT8 data);
void Write16(UINT32 addr, UINT16 data);
void Write32(UINT32 addr, UINT32 data);
void Write64(UINT32 addr, UINT64 data);
/*
* SaveState(SaveState):
*
* Saves an image of the current state. Must never be called while emulator
* is running (inside RunFrame()).
*
* Parameters:
* SaveState Block file to save state information to.
*/
void SaveState(CBlockFile *SaveState);
/*
* LoadState(SaveState):
*
* Loads and resumes execution from a state image. Modifies data that may
* be used by multiple threads -- use with caution and ensure threads are
* not accessing data that will be touched, this can be done by calling
* PauseThreads beforehand. Must never be called while emulator is running
* (inside RunFrame()).
*
* Parameters:
* SaveState Block file to load state information from.
*/
void LoadState(CBlockFile *SaveState);
/*
* SaveNVRAM(NVRAM):
*
* Saves an image of the current NVRAM state.
*
* Parameters:
* NVRAM Block file to save NVRAM to.
*/
void SaveNVRAM(CBlockFile *NVRAM);
/*
* LoadNVRAM(NVRAM):
*
* Loads an NVRAM image.
*
* Parameters:
* NVRAM Block file to load NVRAM state from.
*/
void LoadNVRAM(CBlockFile *NVRAM);
/*
* ClearNVRAM(void):
*
* Clears all NVRAM (backup RAM and EEPROM).
*/
void ClearNVRAM(void);
/*
* RunFrame(void):
*
* Runs one frame (assuming 60 Hz video refresh rate).
*/
void RunFrame(void);
/*
* Reset(void):
*
* Resets the system. Does not modify non-volatile memory.
*/
void Reset(void);
/*
* GetGameInfo(void):
*
* Returns:
* A pointer to the presently loaded game's information structure (or
* NULL if no ROM set has yet been loaded).
*/
const struct GameInfo * GetGameInfo(void);
/*
* LoadROMSet(GameList, zipFile):
*
@ -264,44 +145,7 @@ public:
* OKAY if successful, FAIL otherwise. Prints errors.
*/
bool LoadROMSet(const struct GameInfo *GameList, const char *zipFile);
/*
* AttachRenderers(Render2DPtr, Render3DPtr):
*
* Attaches the renderers to the appropriate device objects.
*
* Parameters:
* Render2DPtr Pointer to a tile renderer object.
* Render3DPtr Same as above but for a 3D renderer.
*/
void AttachRenderers(CRender2D *Render2DPtr, IRender3D *Render3DPtr);
/*
* AttachInputs(InputsPtr):
*
* Attaches OSD-managed inputs.
*
* Parameters:
* InputsPtr Pointer to the object containing input states.
*/
void AttachInputs(CInputs *InputsPtr);
void AttachOutputs(COutputs *OutputsPtr);
/*
* Init(void):
*
* One-time initialization of the context. Must be called prior to all
* other members. Allocates memory and initializes device states.
*
* NOTE: Command line settings will not have been applied here yet.
*
* Returns:
* OKAY is successful, otherwise FAILED if a non-recoverable error
* occurred. Prints own error messages.
*/
bool Init(void);
/*
* GetSoundBoard(void):
*
@ -322,21 +166,6 @@ public:
*/
CDriveBoard *GetDriveBoard(void);
/*
* PauseThreads(void):
*
* Flags that any running threads should pause and waits for them to do so.
* Should be used before invoking any method that accesses the internal state, eg LoadState or SaveState.
*/
bool PauseThreads(void);
/*
* ResumeThreads(void):
*
* Flags that any paused threads should resume running.
*/
bool ResumeThreads(void);
/*
* DumpTimings(void):
*
@ -381,7 +210,6 @@ private:
void RunMainBoardFrame(void); // Runs PPC main board for a frame
void SyncGPUs(void); // Sync's up GPUs in preparation for rendering - must be called when PPC is not running
void RenderFrame(void); // Renders current frame
bool RunSoundBoardFrame(void); // Runs sound board for a frame
void RunDriveBoardFrame(void); // Runs drive board for a frame

View file

@ -23,9 +23,9 @@
* PCI.cpp
*
* PCI bus and device emulation. Implementation of the CPCIBus class.
* CPCIDevice is just a base class from which others are derived. Only the
* IPCIDevice is just a base class from which others are derived. Only the
* transfer of PCI register data is emulated. Device functionality is
* handled by device objects (derived from CPCIDevice).
* handled by device objects (derived from IPCIDevice).
*
* TO-DO List:
* -----------
@ -112,7 +112,7 @@ void CPCIBus::Reset(void)
* Attaches a device to the PCI bus. This means it is added to a list of
* devices to scan when handling PCI configuration space requests.
*/
void CPCIBus::AttachDevice(unsigned device, CPCIDevice *DeviceObjectPtr)
void CPCIBus::AttachDevice(unsigned device, IPCIDevice *DeviceObjectPtr)
{
struct DeviceObjectLink D;

View file

@ -22,13 +22,13 @@
/*
* PCI.h
*
* Header file for PCI bus and device emulation. Defines the CPCIDevice and
* Header file for PCI bus and device emulation. Defines the IPCIDevice and
* CPCIBus classes.
*
* References
* ----------
* 1. "MPC106 PCI/Bridge/Memory Controller User's Manual" (MPC106UM/D Rev.1)
* Sec.7.4.5 describes the PCI configuration space header, which CPCIDevice-
* Sec.7.4.5 describes the PCI configuration space header, which IPCIDevice-
* derived classes are supposed to implement.
*/
@ -41,12 +41,12 @@ using namespace std;
/*
* CPCIDevice:
* IPCIDevice:
*
* An abstract base class for PCI devices. Devices can inherit this class to
* provide PCI configuration space access handlers.
*/
class CPCIDevice
class IPCIDevice
{
public:
/*
@ -154,7 +154,7 @@ public:
* device PCI ID of the device being attached.
* DeviceObjectPtr Pointer to the device object.
*/
void AttachDevice(unsigned device, CPCIDevice *DeviceObjectPtr);
void AttachDevice(unsigned device, IPCIDevice *DeviceObjectPtr);
/*
* Init(void):
@ -179,7 +179,7 @@ private:
struct DeviceObjectLink
{
unsigned device;
CPCIDevice *DeviceObject;
IPCIDevice *DeviceObject;
};
// An array of device objects

View file

@ -995,7 +995,7 @@ void CReal3D::SetStep(int stepID)
DebugLog("Real3D set to Step %d.%d\n", (step>>4)&0xF, step&0xF);
}
bool CReal3D::Init(const uint8_t *vromPtr, CBus *BusObjectPtr, CIRQ *IRQObjectPtr, unsigned dmaIRQBit)
bool CReal3D::Init(const uint8_t *vromPtr, IBus *BusObjectPtr, CIRQ *IRQObjectPtr, unsigned dmaIRQBit)
{
size_t memSize = (g_Config.gpuMultiThreaded ? MEMORY_POOL_SIZE : MEM_POOL_SIZE_RW);
float memSizeMB = (float)memSize/(float)0x100000;

View file

@ -54,7 +54,7 @@ struct QueuedUploadTextures
* rasterization and matrix transformations are carried out by the graphics
* engine.
*/
class CReal3D: public CPCIDevice
class CReal3D: public IPCIDevice
{
public:
/*
@ -366,7 +366,7 @@ public:
* OKAY if successful otherwise FAIL (not enough memory). Prints own
* errors.
*/
bool Init(const uint8_t *vromPtr, CBus *BusObjectPtr, CIRQ *IRQObjectPtr, unsigned dmaIRQBit);
bool Init(const uint8_t *vromPtr, IBus *BusObjectPtr, CIRQ *IRQObjectPtr, unsigned dmaIRQBit);
/*
* CReal3D(void):
@ -427,7 +427,7 @@ private:
vector<QueuedUploadTextures> queuedUploadTexturesRO; // Read-only copy of queue
// Big endian bus object for DMA memory access
CBus *Bus;
IBus *Bus;
// IRQ handling
CIRQ *IRQ; // IRQ controller

View file

@ -82,7 +82,7 @@ private:
*
* Model 3 sound board (68K CPU + 2 x SCSP).
*/
class CSoundBoard: public CBus
class CSoundBoard: public IBus
{
public:
/*

View file

@ -376,7 +376,7 @@ static void PrintBAT(unsigned regu, unsigned regl)
#endif
}
static void DumpPPCRegisters(CBus *bus)
static void DumpPPCRegisters(IBus *bus)
{
#ifdef DEBUG
for (int i = 0; i < 32; i += 4)
@ -960,12 +960,11 @@ int Supermodel(const char *zipFile, CInputs *Inputs, COutputs *Outputs, CINIFile
startTicks = prevFPSTicks;
while (!quit)
{
// Check if paused
if (!paused)
{
// If not, run one frame
Model3->RunFrame();
}
// Render if paused, otherwise run a frame
if (paused)
Model3->RenderFrame();
else
Model3->RunFrame();
// Poll the inputs
if (!Inputs->Poll(Model3->GetGameInfo(), xOffset, yOffset, xRes, yRes))