/** ** 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 . **/ /* * 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 "CPU/Bus.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 /****************************************************************************** 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: CBus *Bus; // memory handlers int (*IRQAck)(int); // IRQ acknowledge callback unsigned char *musashiCtx; // holds CPU state SM68KCtx(void) { Bus = NULL; IRQAck = NULL; musashiCtx = new unsigned char[m68k_context_size()]; memset(musashiCtx, 0, m68k_context_size()); // very important! garbage in context at reset can cause very strange bugs } ~SM68KCtx(void) { Bus = NULL; IRQAck = NULL; delete [] musashiCtx; } } M68KCtx; /****************************************************************************** 68K Interface Unless otherwise noted, all functions operate on the active context. ******************************************************************************/ /* * 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); /* * 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(CBus *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(CBus *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); /****************************************************************************** 68K Handlers Intended for use directly by the 68K core. ******************************************************************************/ extern "C" { /* * 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