// // Copyright (c) 2004 K. Wilkins // // This software is provided 'as-is', without any express or implied warranty. // In no event will the authors be held liable for any damages arising from // the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; you must not // claim that you wrote the original software. If you use this software // in a product, an acknowledgment in the product documentation would be // appreciated but is not required. // // 2. Altered source versions must be plainly marked as such, and must not // be misrepresented as being the original software. // // 3. This notice may not be removed or altered from any source distribution. // ////////////////////////////////////////////////////////////////////////////// // Handy - An Atari Lynx Emulator // // Copyright (c) 1996,1997 // // K. Wilkins // ////////////////////////////////////////////////////////////////////////////// // System object header file // ////////////////////////////////////////////////////////////////////////////// // // // This header file provides the interface definition and inline code for // // the system object, this object if what binds together all of the Handy // // hardware enmulation objects, its the glue that holds the system together // // // // K. Wilkins // // August 1997 // // // ////////////////////////////////////////////////////////////////////////////// // Revision History: // // ----------------- // // // // 01Aug1997 KW Document header added & class documented. // // // ////////////////////////////////////////////////////////////////////////////// #ifndef SYSTEM_H #define SYSTEM_H #include "machine.h" #include #define HANDY_SYSTEM_FREQ 16000000 #define HANDY_TIMER_FREQ 20 #define HANDY_FILETYPE_LNX 0 #define HANDY_FILETYPE_HOMEBREW 1 #define HANDY_FILETYPE_SNAPSHOT 2 #define HANDY_FILETYPE_ILLEGAL 3 #define HANDY_SCREEN_WIDTH 160 #define HANDY_SCREEN_HEIGHT 102 // // Define the global variable list // /* #ifdef SYSTEM_CPP uint32 gSuzieDoneTime = 0; uint32 gSystemCycleCount=0; uint32 gNextTimerEvent=0; uint32 gCPUBootAddress=0; uint32 gSystemIRQ=FALSE; uint32 gSystemNMI=FALSE; uint32 gSystemCPUSleep=FALSE; uint32 gSystemHalt=FALSE; #else extern uint32 gSystemCycleCount; extern uint32 gSuzieDoneTime; extern uint32 gNextTimerEvent; extern uint32 gCPUBootAddress; extern uint32 gSystemIRQ; extern uint32 gSystemNMI; extern uint32 gSystemCPUSleep; extern uint32 gSystemHalt; #endif */ // // Define the interfaces before we start pulling in the classes // as many classes look for articles from the interfaces to // allow compilation #include "sysbase.h" class CSystem; // // Now pull in the parts that build the system // #include "lynxbase.h" #include "ram.h" #include "rom.h" #include "memmap.h" #include "cart.h" #include "susie.h" #include "mikie.h" #include "c65c02.h" #define TOP_START 0xfc00 #define TOP_MASK 0x03ff #define TOP_SIZE 0x400 #define SYSTEM_SIZE 65536 class CSystem : public CSystemBase { public: CSystem(const uint8 *, uint32, const uint8*, uint32, int, int, bool) MDFN_COLD; ~CSystem() MDFN_COLD; public: void Reset() MDFN_COLD; inline void Update(uint32 targetclock) { // Only update if there is a predicted timer event if(gSystemCycleCount >= gNextTimerEvent) { mMikie->Update(); } // Step the processor through 1 instruction mCpu->Update(); // If the CPU is asleep then skip to the next timer event if(gSystemCPUSleep) { gSystemCycleCount = std::min(gNextTimerEvent, targetclock); } } void Blit(const uint32 *src); bool Advance(int buttons, uint32 *vbuff, int16 *sbuff, int &sbuffsize); bool GetSaveRamPtr(int &size, uint8 *&data) { return mCart->GetSaveRamPtr(size, data); } void GetReadOnlyCartPtrs(int &s0, uint8 *&p0, int &s1, uint8 *&p1) { mCart->GetReadOnlyPtrs(s0, p0, s1, p1); } // // We MUST have separate CPU & RAM peek & poke handlers as all CPU accesses must // go thru the address generator at $FFF9 // // BUT, Mikie video refresh & Susie see the whole system as RAM // // Complete and utter wankers, its taken me 1 week to find the 2 lines // in all the documentation that mention this fact, the mother of all // bugs has been found and FIXED....... // CPU inline void Poke_CPU(uint32 addr, uint8 data) { mMemoryHandlers[addr]->Poke(addr,data);}; inline uint8 Peek_CPU(uint32 addr) { return mMemoryHandlers[addr]->Peek(addr);}; inline void PokeW_CPU(uint32 addr,uint16 data) { mMemoryHandlers[addr]->Poke(addr,data&0xff);addr++;mMemoryHandlers[addr]->Poke(addr,data>>8);}; inline uint16 PeekW_CPU(uint32 addr) {return ((mMemoryHandlers[addr]->Peek(addr))+(mMemoryHandlers[addr]->Peek(addr+1)<<8));}; // RAM inline void Poke_RAM(uint32 addr, uint8 data) { mRam->Poke(addr,data);}; inline uint8 Peek_RAM(uint32 addr) { return mRam->Peek(addr);}; inline void PokeW_RAM(uint32 addr,uint16 data) { mRam->Poke(addr,data&0xff);addr++;mRam->Poke(addr,data>>8);}; inline uint16 PeekW_RAM(uint32 addr) {return ((mRam->Peek(addr))+(mRam->Peek(addr+1)<<8));}; // High level cart access for debug etc inline void Poke_CART(uint32 addr, uint8 data) {mCart->Poke(addr,data);}; inline uint8 Peek_CART(uint32 addr) {return mCart->Peek(addr);}; inline void CartBank(EMMODE bank) {mCart->BankSelect(bank);}; inline uint32 CartSize() {return mCart->ObjectSize();}; // Low level cart access for Suzy, Mikey inline void Poke_CARTB0(uint8 data) {mCart->Poke0(data);}; inline void Poke_CARTB1(uint8 data) {mCart->Poke1(data);}; inline uint8 Peek_CARTB0() {return mCart->Peek0();} inline uint8 Peek_CARTB1() {return mCart->Peek1();} inline void CartAddressStrobe(bool strobe) {mCart->CartAddressStrobe(strobe);}; inline void CartAddressData(bool data) {mCart->CartAddressData(data);}; // Low level CPU access void SetRegs(C6502_REGS ®s) {mCpu->SetRegs(regs);}; void GetRegs(C6502_REGS ®s) {mCpu->GetRegs(regs);}; // Mikey system interfacing void ComLynxCable(int status) { mMikie->ComLynxCable(status); }; void ComLynxRxData(int data) { mMikie->ComLynxRxData(data); }; void ComLynxTxCallback(void (*function)(int data,uint32 objref),uint32 objref) { mMikie->ComLynxTxCallback(function,objref); }; // Suzy system interfacing uint32 PaintSprites() {return mSusie->PaintSprites();}; // Miscellaneous void SetButtonData(uint32 data); // uint32 GetButtonData() {return mSusie->GetButtonData();}; uint8* GetRamPointer() {return mRam->GetRamPointer();}; public: CLynxBase *mMemoryHandlers[SYSTEM_SIZE]; CCart *mCart; CRom *mRom; CMemMap *mMemMap; CRam *mRam; C65C02 *mCpu; CMikie *mMikie; CSusie *mSusie; // old globals uint32 gSuzieDoneTime; uint32 gSystemCycleCount; uint32 gNextTimerEvent; uint32 gSystemIRQ; uint32 gSystemNMI; uint32 gSystemCPUSleep; uint32 gSystemHalt; // this is set in various places, but never tested, anywhere? // frame overflow detection int frameoverflow; // rotation of the device int rotate; // video dest uint32 *videobuffer; templatevoid SyncState(NewState *ns); }; #endif