1 // 2 // Copyright (c) 2004 K. Wilkins 3 // 4 // This software is provided 'as-is', without any express or implied warranty. 5 // In no event will the authors be held liable for any damages arising from 6 // the use of this software. 7 // 8 // Permission is granted to anyone to use this software for any purpose, 9 // including commercial applications, and to alter it and redistribute it 10 // freely, subject to the following restrictions: 11 // 12 // 1. The origin of this software must not be misrepresented; you must not 13 // claim that you wrote the original software. If you use this software 14 // in a product, an acknowledgment in the product documentation would be 15 // appreciated but is not required. 16 // 17 // 2. Altered source versions must be plainly marked as such, and must not 18 // be misrepresented as being the original software. 19 // 20 // 3. This notice may not be removed or altered from any source distribution. 21 // 22 23 ////////////////////////////////////////////////////////////////////////////// 24 // Handy - An Atari Lynx Emulator // 25 // Copyright (c) 1996,1997 // 26 // K. Wilkins // 27 ////////////////////////////////////////////////////////////////////////////// 28 // System object header file // 29 ////////////////////////////////////////////////////////////////////////////// 30 // // 31 // This header file provides the interface definition and inline code for // 32 // the system object, this object if what binds together all of the Handy // 33 // hardware enmulation objects, its the glue that holds the system together // 34 // // 35 // K. Wilkins // 36 // August 1997 // 37 // // 38 ////////////////////////////////////////////////////////////////////////////// 39 // Revision History: // 40 // ----------------- // 41 // // 42 // 01Aug1997 KW Document header added & class documented. // 43 // // 44 ////////////////////////////////////////////////////////////////////////////// 45 46 #ifndef SYSTEM_H 47 #define SYSTEM_H 48 49 #pragma inline_depth (255) 50 #pragma inline_recursion (on) 51 52 #ifdef _LYNXDBG 53 54 //#ifdef _DEBUG 55 //#define new DEBUG_NEW 56 //#undef THIS_FILE 57 //static char THIS_FILE[] = __FILE__; 58 //#endif 59 60 #endif 61 62 #include "machine.h" 63 64 #define HANDY_SYSTEM_FREQ 16000000 65 #define HANDY_TIMER_FREQ 20 66 #define HANDY_AUDIO_SAMPLE_FREQ 48000 67 #define HANDY_AUDIO_SAMPLE_PERIOD (HANDY_SYSTEM_FREQ/HANDY_AUDIO_SAMPLE_FREQ) 68 #define HANDY_AUDIO_WAVESHAPER_TABLE_LENGTH 0x200000 69 70 #ifdef SDL_PATCH 71 //#define HANDY_AUDIO_BUFFER_SIZE 4096 // Needed for SDL 8bit MONO 72 //#define HANDY_AUDIO_BUFFER_SIZE 8192 // Needed for SDL STEREO 8bit 73 #define HANDY_AUDIO_BUFFER_SIZE 16384 // Needed for SDL STEREO 16bit 74 #else 75 //#define HANDY_AUDIO_BUFFER_SIZE (HANDY_AUDIO_SAMPLE_FREQ/4) 76 #define HANDY_AUDIO_BUFFER_SIZE (HANDY_AUDIO_SAMPLE_FREQ) 77 #endif 78 79 80 #define HANDY_FILETYPE_LNX 0 81 #define HANDY_FILETYPE_HOMEBREW 1 82 #define HANDY_FILETYPE_SNAPSHOT 2 83 #define HANDY_FILETYPE_ILLEGAL 3 84 #define HANDY_FILETYPE_RAW 4 85 86 #define HANDY_SCREEN_WIDTH 160 87 #define HANDY_SCREEN_HEIGHT 102 88 // 89 // Define the global variable list 90 // 91 92 #ifdef SYSTEM_CPP 93 ULONG gSystemCycleCount=0; 94 ULONG gNextTimerEvent=0; 95 ULONG gCPUWakeupTime=0; 96 ULONG gIRQEntryCycle=0; 97 ULONG gCPUBootAddress=0; 98 ULONG gBreakpointHit=FALSE; 99 ULONG gSingleStepMode=FALSE; 100 ULONG gSingleStepModeSprites=FALSE; 101 ULONG gSystemIRQ=FALSE; 102 ULONG gSystemNMI=FALSE; 103 ULONG gSystemCPUSleep=FALSE; 104 ULONG gSystemCPUSleep_Saved=FALSE; 105 ULONG gSystemHalt=FALSE; 106 ULONG gThrottleMaxPercentage=100; 107 ULONG gThrottleLastTimerCount=0; 108 ULONG gThrottleNextCycleCheckpoint=0; 109 110 volatile ULONG gTimerCount=0; 111 112 ULONG gAudioEnabled=FALSE; 113 UBYTE gAudioBuffer[HANDY_AUDIO_BUFFER_SIZE]; 114 ULONG gAudioBufferPointer=0; 115 ULONG gAudioLastUpdateCycle=0; 116 117 CErrorInterface *gError=NULL; 118 #else 119 120 extern ULONG gSystemCycleCount; 121 extern ULONG gNextTimerEvent; 122 extern ULONG gCPUWakeupTime; 123 extern ULONG gIRQEntryCycle; 124 extern ULONG gCPUBootAddress; 125 extern ULONG gBreakpointHit; 126 extern ULONG gSingleStepMode; 127 extern ULONG gSingleStepModeSprites; 128 extern ULONG gSystemIRQ; 129 extern ULONG gSystemNMI; 130 extern ULONG gSystemCPUSleep; 131 extern ULONG gSystemCPUSleep_Saved; 132 extern ULONG gSystemHalt; 133 extern ULONG gThrottleMaxPercentage; 134 extern ULONG gThrottleLastTimerCount; 135 extern ULONG gThrottleNextCycleCheckpoint; 136 137 extern volatile ULONG gTimerCount; 138 139 extern ULONG gAudioEnabled; 140 extern UBYTE gAudioBuffer[HANDY_AUDIO_BUFFER_SIZE]; 141 extern ULONG gAudioBufferPointer; 142 extern ULONG gAudioLastUpdateCycle; 143 144 extern CErrorInterface *gError; 145 #endif 146 147 typedef struct lssfile 148 { 149 UBYTE *memptr; 150 ULONG index; 151 ULONG index_limit; 152 } LSS_FILE; 153 154 int lss_read(void* dest, int varsize, int varcount, LSS_FILE *fp); 155 int lss_write(void* src, int varsize, int varcount, LSS_FILE *fp); 156 int lss_printf(LSS_FILE *fp, const char *str); 157 158 // 159 // Define the interfaces before we start pulling in the classes 160 // as many classes look for articles from the interfaces to 161 // allow compilation 162 163 #include "sysbase.h" 164 165 class CSystem; 166 167 // 168 // Now pull in the parts that build the system 169 // 170 #include "lynxbase.h" 171 //#include "memfault.h" 172 #include "ram.h" 173 #include "rom.h" 174 #include "memmap.h" 175 #include "cart.h" 176 #include "eeprom.h" 177 #include "susie.h" 178 #include "mikie.h" 179 #include "c65c02.h" 180 181 #include <stdint.h> 182 183 #define TOP_START 0xfc00 184 #define TOP_MASK 0x03ff 185 #define TOP_SIZE 0x400 186 #define SYSTEM_SIZE 65536 187 188 #define LSS_VERSION_OLD "LSS2" 189 #define LSS_VERSION "LSS3" 190 191 class CSystem : public CSystemBase 192 { 193 public: 194 CSystem(const char* gamefile, const char* romfile,bool useEmu); 195 ~CSystem(); 196 void SaveEEPROM(void); 197 198 public: 199 void HLE_BIOS_FE00(void); 200 void HLE_BIOS_FE19(void); 201 void HLE_BIOS_FE4A(void); 202 void HLE_BIOS_FF80(void); 203 void Reset(void); 204 size_t ContextSize(void); 205 bool ContextSave(LSS_FILE *fp); 206 bool ContextLoad(LSS_FILE *fp); 207 bool IsZip(char *filename); 208 Update(void)209 inline void Update(void) 210 { 211 // fprintf(stderr, "sys update\n"); 212 // 213 // Only update if there is a predicted timer event 214 // 215 if(gSystemCycleCount>=gNextTimerEvent) 216 { 217 mMikie->Update(); 218 } 219 // 220 // Step the processor through 1 instruction 221 // 222 mCpu->Update(); 223 // fprintf(stderr, "end cpu update\n"); 224 225 #ifdef _LYNXDBG 226 // Check breakpoint 227 static ULONG lastcycle=0; 228 if(lastcycle<mCycleCountBreakpoint && gSystemCycleCount>=mCycleCountBreakpoint) gBreakpointHit=TRUE; 229 lastcycle=gSystemCycleCount; 230 231 // Check single step mode 232 if(gSingleStepMode) gBreakpointHit=TRUE; 233 #endif 234 235 // 236 // If the CPU is asleep then skip to the next timer event 237 // 238 if(gSystemCPUSleep) 239 { 240 gSystemCycleCount=gNextTimerEvent; 241 } 242 243 // fprintf(stderr, "end sys update\n"); 244 } 245 246 // 247 // We MUST have separate CPU & RAM peek & poke handlers as all CPU accesses must 248 // go thru the address generator at $FFF9 249 // 250 // BUT, Mikie video refresh & Susie see the whole system as RAM 251 // 252 // Complete and utter wankers, its taken me 1 week to find the 2 lines 253 // in all the documentation that mention this fact, the mother of all 254 // bugs has been found and FIXED....... 255 256 // 257 // CPU 258 // Poke_CPU(ULONG addr,UBYTE data)259 inline void Poke_CPU(ULONG addr, UBYTE data) { mMemoryHandlers[addr]->Poke(addr,data);}; Peek_CPU(ULONG addr)260 inline UBYTE Peek_CPU(ULONG addr) { return mMemoryHandlers[addr]->Peek(addr);}; PokeW_CPU(ULONG addr,UWORD data)261 inline void PokeW_CPU(ULONG addr,UWORD data) { mMemoryHandlers[addr]->Poke(addr,data&0xff);addr++;mMemoryHandlers[addr]->Poke(addr,data>>8);}; PeekW_CPU(ULONG addr)262 inline UWORD PeekW_CPU(ULONG addr) {return ((mMemoryHandlers[addr]->Peek(addr))+(mMemoryHandlers[addr]->Peek(addr+1)<<8));}; 263 264 // 265 // RAM 266 // Poke_RAM(ULONG addr,UBYTE data)267 inline void Poke_RAM(ULONG addr, UBYTE data) { mRam->Poke(addr,data);}; Peek_RAM(ULONG addr)268 inline UBYTE Peek_RAM(ULONG addr) { return mRam->Peek(addr);}; PokeW_RAM(ULONG addr,UWORD data)269 inline void PokeW_RAM(ULONG addr,UWORD data) { mRam->Poke(addr,data&0xff);addr++;mRam->Poke(addr,data>>8);}; PeekW_RAM(ULONG addr)270 inline UWORD PeekW_RAM(ULONG addr) {return ((mRam->Peek(addr))+(mRam->Peek(addr+1)<<8));}; 271 272 // High level cart access for debug etc 273 Poke_CART(ULONG addr,UBYTE data)274 inline void Poke_CART(ULONG addr, UBYTE data) {mCart->Poke(addr,data);}; Peek_CART(ULONG addr)275 inline UBYTE Peek_CART(ULONG addr) {return mCart->Peek(addr);}; CartBank(EMMODE bank)276 inline void CartBank(EMMODE bank) {mCart->BankSelect(bank);}; CartSize(void)277 inline ULONG CartSize(void) {return mCart->ObjectSize();}; CartGetName(void)278 inline const char* CartGetName(void) { return mCart->CartGetName();}; CartGetManufacturer(void)279 inline const char* CartGetManufacturer(void) { return mCart->CartGetManufacturer();}; CartGetRotate(void)280 inline ULONG CartGetRotate(void) {return mCart->CartGetRotate();}; 281 282 // Low level cart access for Suzy, Mikey 283 Poke_CARTB0(UBYTE data)284 inline void Poke_CARTB0(UBYTE data) {mCart->Poke0(data);}; Poke_CARTB1(UBYTE data)285 inline void Poke_CARTB1(UBYTE data) {mCart->Poke1(data);}; Poke_CARTB0A(UBYTE data)286 inline void Poke_CARTB0A(UBYTE data) {mCart->Poke0A(data);}; Poke_CARTB1A(UBYTE data)287 inline void Poke_CARTB1A(UBYTE data) {mCart->Poke1A(data);}; Peek_CARTB0(void)288 inline UBYTE Peek_CARTB0(void) {return mCart->Peek0();} Peek_CARTB1(void)289 inline UBYTE Peek_CARTB1(void) {return mCart->Peek1();} Peek_CARTB0A(void)290 inline UBYTE Peek_CARTB0A(void) {return mCart->Peek0A();} Peek_CARTB1A(void)291 inline UBYTE Peek_CARTB1A(void) {return mCart->Peek1A();} CartAddressStrobe(bool strobe)292 inline void CartAddressStrobe(bool strobe) {mCart->CartAddressStrobe(strobe);}; CartAddressData(bool data)293 inline void CartAddressData(bool data) {mCart->CartAddressData(data);}; 294 295 // Low level CPU access 296 SetRegs(C6502_REGS & regs)297 void SetRegs(C6502_REGS ®s) {mCpu->SetRegs(regs);}; GetRegs(C6502_REGS & regs)298 void GetRegs(C6502_REGS ®s) {mCpu->GetRegs(regs);}; 299 300 // Mikey system interfacing 301 DisplaySetAttributes(ULONG Rotate,ULONG Format,ULONG Pitch,UBYTE * (* DisplayCallback)(ULONG objref),ULONG objref)302 void DisplaySetAttributes(ULONG Rotate,ULONG Format,ULONG Pitch,UBYTE* (*DisplayCallback)(ULONG objref),ULONG objref) { mMikie->DisplaySetAttributes(Rotate,Format,Pitch,DisplayCallback,objref); }; 303 ComLynxCable(int status)304 void ComLynxCable(int status) { mMikie->ComLynxCable(status); }; ComLynxRxData(int data)305 void ComLynxRxData(int data) { mMikie->ComLynxRxData(data); }; ComLynxTxCallback(void (* function)(int data,ULONG objref),ULONG objref)306 void ComLynxTxCallback(void (*function)(int data,ULONG objref),ULONG objref) { mMikie->ComLynxTxCallback(function,objref); }; 307 308 // Suzy system interfacing 309 PaintSprites(void)310 ULONG PaintSprites(void) {return mSusie->PaintSprites();}; 311 312 // Miscellaneous 313 SetButtonData(ULONG data)314 void SetButtonData(ULONG data) {mSusie->SetButtonData(data);}; GetButtonData(void)315 ULONG GetButtonData(void) {return mSusie->GetButtonData();}; SetCycleBreakpoint(ULONG breakpoint)316 void SetCycleBreakpoint(ULONG breakpoint) {mCycleCountBreakpoint=breakpoint;}; GetRamPointer(void)317 UBYTE* GetRamPointer(void) {return mRam->GetRamPointer();}; 318 #ifdef _LYNXDBG 319 void DebugTrace(int address); 320 321 void DebugSetCallback(void (*function)(ULONG objref, char *message),ULONG objref); 322 323 void (*mpDebugCallback)(ULONG objref, char *message); 324 ULONG mDebugCallbackObject; 325 #endif 326 327 public: 328 ULONG mCycleCountBreakpoint; 329 CLynxBase *mMemoryHandlers[SYSTEM_SIZE]; 330 CCart *mCart; 331 CRom *mRom; 332 CMemMap *mMemMap; 333 CRam *mRam; 334 C65C02 *mCpu; 335 CMikie *mMikie; 336 CSusie *mSusie; 337 CEEPROM *mEEPROM; 338 339 ULONG mFileType; 340 }; 341 342 #endif 343