/** ** 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 . **/ /* * 68K.h * * Header file for 68K CPU interface. Caution: 68K emulator is not thread-safe. * * TO-DO List: * ----------- * - Optimize things, perhaps by using FASTCALL */ #ifndef INCLUDED_68K_H #define INCLUDED_68K_H #include #include "Types.h" #include "Musashi/m68k.h" #include "Musashi/m68kctx.h" #include "CPU/Bus.h" #include "BlockFile.h" // 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 #ifdef SUPERMODEL_DEBUGGER namespace Debugger { class CMusashi68KDebug; } #endif // SUPERMODEL_DEBUGGER /****************************************************************************** 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 /****************************************************************************** CPU Context ******************************************************************************/ /* * M68KCtx: * * Complete state of a single 68K. Do NOT manipulate these directly. Set the * context and then use the M68K* functions below to attach a bus and IRQ * callback to the active context. */ typedef struct SM68KCtx { public: m68ki_cpu_core musashiCtx; // CPU context IBus *Bus; // memory handlers int (*IRQAck)(int); // IRQ acknowledge callback #ifdef SUPERMODEL_DEBUGGER Debugger::CMusashi68KDebug *Debug; // holds debugger (if attached) #endif // SUPERMODEL_DEBUGGER SM68KCtx(void) { Bus = NULL; IRQAck = NULL; memset(&musashiCtx, 0, sizeof(musashiCtx)); // very important! garbage in context at reset can cause very strange bugs #ifdef SUPERMODEL_DEBUGGER Debug = NULL; #endif // SUPERMODEL_DEBUGGER } ~SM68KCtx(void) { Bus = NULL; IRQAck = NULL; } } M68KCtx;; /****************************************************************************** 68K Interface Unless otherwise noted, all functions operate on the active context. ******************************************************************************/ /* * M68KGetARegister(n): * * Parameters: * n Register number (0-7). * * Returns: * Register An. */ extern UINT32 M68KGetARegister(int n); /* * M68KSetARegister(n, v): * * Parameters: * n Register number (0-7). * v Value to set register An to. */ extern void M68KSetARegister(int n, UINT32 v); /* * M68KGetDRegister(n): * * Parameters: * n Register number (0-7). * * Returns: * Register Dn. */ extern UINT32 M68KGetDRegister(int n); /* * M68KGetDRegister(n, v): * * Parameters: * n Register number (0-7). * v Value to set register Dn to. */ extern void M68KSetDRegister(int n, UINT32 v); /* * M68KGetPC(): * * Returns: * Current program counter. */ extern UINT32 M68KGetPC(void); /* * M68KSaveState(StateFile, name): * * Saves the CPU state to the block file. * * Parameters: * StateFile Block file. * name Name of block to create (e.g. "Main 68K"), to facilitate * multiple 68K states in the same file. */ extern void M68KSaveState(CBlockFile *StateFile, const char *name); /* * M68KLoadState(StateFile, name): * * Loads the CPU state. * * Parameters: * StateFile Block file. * name Name of block to load. */ extern void M68KLoadState(CBlockFile *StateFile, const char *name); /* * 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 for the currently active CPU. The * default behavior is to always assume autovectored interrupts. * * Parameters: * F Callback function. */ extern void M68KSetIRQCallback(int (*F)(int)); /* * 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. * This must be set up before any 68K-related emulation functions are invoked * or the program will crash! * * Parameters: * BusPtr Pointer to bus object to use for all address space accesses. */ extern void M68KAttachBus(IBus *BusPtr); /* * M68KInit(): * * Initializes the 68K emulator. Must be called once per program session prior * to any 68K emulation functions. A context must be mapped before calling * this. * * Returns: * Always returns OKAY. */ extern bool M68KInit(void); /* * M68KGetContext(M68KCtx *Dest): * * Copies the internal (active) 68K context back to the destination. * * Parameters: * Dest Location to which to copy 68K context. */ extern void M68KGetContext(M68KCtx *Dest); /* * M68KSetContext(M68KCtx *Src): * * Sets the specified 68K context by copying it to the internal context. * * Parameters: * Src Location from which to copy 68K context. */ extern void M68KSetContext(M68KCtx *Src); #ifdef SUPERMODEL_DEBUGGER #define DBG68K_REG_PC 0 #define DBG68K_REG_SR 1 #define DBG68K_REG_SP 2 #define DBG68K_REG_D0 3 #define DBG68K_REG_D1 4 #define DBG68K_REG_D2 5 #define DBG68K_REG_D3 6 #define DBG68K_REG_D4 7 #define DBG68K_REG_D5 8 #define DBG68K_REG_D6 9 #define DBG68K_REG_D7 10 #define DBG68K_REG_A0 11 #define DBG68K_REG_A1 12 #define DBG68K_REG_A2 13 #define DBG68K_REG_A3 14 #define DBG68K_REG_A4 15 #define DBG68K_REG_A5 16 #define DBG68K_REG_A6 17 #define DBG68K_REG_A7 18 /* * M68KGetRegister(ctx, reg): * * Parameters: * ctx Musashi 68K context. * reg Register (use DBG68K_REG_* macros). * * Returns: * Register value. */ UINT32 M68KGetRegister(SM68KCtx *ctx, unsigned reg); /* * M68KSetRegister(ctx, reg, value): * * Parameters: * ctx Musashi 68K context. * reg Register (use DBG68K_REG_* macros). * value Vale to write. * * Returns: * True if successful, false if register does not exist. */ UINT32 M68KSetRegister(SM68KCtx *ctx, unsigned reg, UINT32 val); #endif // SUPERMODEL_DEBUGGER /****************************************************************************** 68K Handlers Intended for use directly by the 68K core. ******************************************************************************/ extern "C" { #ifdef SUPERMODEL_DEBUGGER extern void M68KDebugCallback(); #endif // SUPERMODEL_DEBUGGER /* * 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); } // extern "C" #endif // INCLUDED_68K_H