system.h
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 emulation 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 #include "emuapi.h" 50 51 // #pragma inline_depth (255) 52 // #pragma inline_recursion (on) 53 54 #include <cstdint> 55 56 typedef int8_t SBYTE; 57 typedef uint8_t UBYTE; 58 typedef int16_t SWORD; 59 typedef uint16_t UWORD; 60 typedef int32_t SLONG; 61 typedef uint32_t ULONG; 62 63 //typedef UBYTE HandyPixel; 64 typedef UWORD HandyPixel; 65 66 extern ULONG crc32_le(ULONG crc, UBYTE const * buf, ULONG len); 67 68 69 70 #ifndef TRUE 71 #define TRUE true 72 #endif 73 74 #ifndef FALSE 75 #define FALSE false 76 #endif 77 78 #define HANDY_SYSTEM_FREQ 16000000 79 #define HANDY_TIMER_FREQ 20 80 #define HANDY_AUDIO_SAMPLE_FREQ 22050 //22050 //24000 // 48000 81 #define HANDY_AUDIO_SAMPLE_PERIOD (HANDY_SYSTEM_FREQ/HANDY_AUDIO_SAMPLE_FREQ) 82 #define AUDIO_BUFFER_LENGTH 4096 //512 //((HANDY_AUDIO_SAMPLE_FREQ/60+25)*2) 83 84 85 #ifdef SDL_PATCH 86 //#define HANDY_AUDIO_BUFFER_SIZE 4096 // Needed for SDL 8bit MONO 87 //#define HANDY_AUDIO_BUFFER_SIZE 8192 // Needed for SDL STEREO 8bit 88 //#define HANDY_AUDIO_BUFFER_SIZE 16384 // Needed for SDL STEREO 16bit 89 #else 90 //#define HANDY_AUDIO_BUFFER_SIZE (HANDY_AUDIO_SAMPLE_FREQ/4) 91 //#define HANDY_AUDIO_BUFFER_SIZE (HANDY_AUDIO_SAMPLE_FREQ) 92 #endif 93 94 95 #define HANDY_FILETYPE_LNX 0 96 #define HANDY_FILETYPE_HOMEBREW 1 97 #define HANDY_FILETYPE_SNAPSHOT 2 98 #define HANDY_FILETYPE_ILLEGAL 3 99 #define HANDY_FILETYPE_RAW 4 100 101 #define HANDY_SCREEN_WIDTH 160 102 #define HANDY_SCREEN_HEIGHT 102 103 104 #define OUTPUT_SCREEN_WIDTH 160 105 #define OUTPUT_SCREEN_HEIGHT (HANDY_SCREEN_HEIGHT*2) 106 #define OUTPUT_SCREEN_STRIDE 160 107 108 // 109 // Define the global variable list 110 // 111 extern ULONG gSystemCycleCount; 112 extern ULONG gNextTimerEvent; 113 extern ULONG gCPUWakeupTime; 114 extern ULONG gIRQEntryCycle; 115 extern ULONG gCPUBootAddress; 116 extern ULONG gBreakpointHit; 117 extern ULONG gSingleStepMode; 118 extern ULONG gSingleStepModeSprites; 119 extern ULONG gSystemIRQ; 120 extern ULONG gSystemNMI; 121 extern ULONG gSystemCPUSleep; 122 extern ULONG gSystemCPUSleep_Saved; 123 extern ULONG gSystemHalt; 124 extern ULONG gThrottleMaxPercentage; 125 extern ULONG gThrottleLastTimerCount; 126 extern ULONG gThrottleNextCycleCheckpoint; 127 extern ULONG gEndOfFrame; 128 extern ULONG gTimerCount; 129 extern ULONG gRenderFrame; 130 131 extern ULONG gAudioEnabled; 132 extern ULONG *gAudioBuffer; 133 extern ULONG gAudioBufferPointer; 134 extern ULONG gAudioLastUpdateCycle; 135 extern UBYTE *gPrimaryFrameBuffer; 136 137 // typedef struct lssfile 138 // { 139 // UBYTE *memptr; 140 // ULONG index; 141 // ULONG index_limit; 142 // } LSS_FILE; 143 144 // int lss_read(void* dest, int varsize, int varcount, LSS_FILE *fp); 145 // int lss_write(void* src, int varsize, int varcount, LSS_FILE *fp); 146 // int lss_printf(LSS_FILE *fp, const char *str); 147 148 #define LSS_FILE FILE 149 #define lss_read(d, vs, vc, fp) (fread(d, vs, vc, fp) > 0) 150 #define lss_write(s, vs, vc, fp) (fwrite(s, vs, vc, fp) > 0) 151 #define lss_printf(fp, str) (fputs(str, fp) >= 0) 152 153 // 154 // Define logging functions 155 // 156 157 //#include <rg_system.h> 158 //#define log_printf(x...) printf(x) 159 //#define log_printf(x...) rg_system_log(RG_LOG_USER, NULL, x) 160 #define log_printf(x...) 161 162 163 // 164 // Define the interfaces before we start pulling in the classes 165 // as many classes look for articles from the interfaces to 166 // allow compilation 167 168 #include "sysbase.h" 169 170 class CSystem; 171 172 // 173 // Now pull in the parts that build the system 174 // 175 #include "lynxbase.h" 176 #include "ram.h" 177 #include "cart.h" 178 #include "eeprom.h" 179 #include "susie.h" 180 #include "mikie.h" 181 #include "c65c02.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 "LSS3" 189 190 class CSystem : public CSystemBase 191 { 192 public: 193 CSystem(const char* gamefile, long displayformat, long samplerate); 194 ~CSystem(); 195 196 public: 197 void HLE_BIOS_FE00(void); 198 void HLE_BIOS_FE19(void); 199 void HLE_BIOS_FE4A(void); 200 void HLE_BIOS_FF80(void); 201 void Reset(void); 202 bool ContextSave(LSS_FILE *fp); 203 bool ContextLoad(LSS_FILE *fp); 204 void SaveEEPROM(void); 205 206 inline void Update(void) 207 { 208 // 209 // Only update if there is a predicted timer event 210 // 211 if(gSystemCycleCount>=gNextTimerEvent) 212 { 213 mMikie->Update(); 214 } 215 // 216 // Step the processor through 1 instruction 217 // 218 mCpu->Update(); 219 220 #ifdef _LYNXDBG 221 // Check breakpoint 222 static ULONG lastcycle=0; 223 if(lastcycle<mCycleCountBreakpoint && gSystemCycleCount>=mCycleCountBreakpoint) gBreakpointHit=TRUE; 224 lastcycle=gSystemCycleCount; 225 226 // Check single step mode 227 if(gSingleStepMode) gBreakpointHit=TRUE; 228 #endif 229 230 // 231 // If the CPU is asleep then skip to the next timer event 232 // 233 if(gSystemCPUSleep) 234 { 235 gSystemCycleCount=gNextTimerEvent; 236 } 237 } 238 239 inline void UpdateFrame(bool draw) 240 { 241 gEndOfFrame = FALSE; 242 gRenderFrame = draw; 243 244 while(gEndOfFrame != TRUE) 245 { 246 if(gSystemCycleCount>=gNextTimerEvent) 247 { 248 mMikie->Update(); 249 } 250 251 mCpu->Update(); 252 253 #ifdef _LYNXDBG 254 // Check breakpoint 255 static ULONG lastcycle=0; 256 if(lastcycle<mCycleCountBreakpoint && gSystemCycleCount>=mCycleCountBreakpoint) gBreakpointHit=TRUE; 257 lastcycle=gSystemCycleCount; 258 259 // Check single step mode 260 if(gSingleStepMode) gBreakpointHit=TRUE; 261 #endif 262 263 if(gSystemCPUSleep) 264 { 265 gSystemCycleCount=gNextTimerEvent; 266 } 267 } 268 } 269 270 // 271 // CPU 272 // 273 inline void Poke_CPU(ULONG addr, UBYTE data) { 274 if (addr < 0xFC00) { // 0000-FBFF Always RAM 275 // mRamPointer[addr] = data; 276 // return; 277 } 278 else if (addr == 0xFFF9) { // MMU 279 mMemMapReg = data; 280 return; 281 } 282 else if ((addr >> 8) == 0xFC) { // FC00-FCFF Susie area 283 if ((mMemMapReg & 0x1) == 0) { 284 mSusie->Poke(addr, data); 285 return; 286 } 287 } 288 else if ((addr >> 8) == 0xFD) { // FD00-FDFF Mikie area 289 if ((mMemMapReg & 0x2) == 0) { 290 mMikie->Poke(addr, data); 291 return; 292 } 293 } 294 else if (addr < 0xFFF8) { // FE00-FFF7 Bios ROM 295 if ((mMemMapReg & 0x4) == 0) 296 return; 297 } 298 else { // FFFA-FFFF Vector area 299 if ((mMemMapReg & 0x8) == 0) 300 return; 301 } 302 303 mRamPointer[addr] = data; 304 }; 305 inline UBYTE Peek_CPU(ULONG addr) { 306 if (addr < 0xFC00) { // 0000-FBFF Always RAM 307 // return mRamPointer[addr]; 308 } 309 else if (addr == 0xFFF9) { 310 return mMemMapReg; 311 } 312 else if ((addr >> 8) == 0xFC) { // FC00-FCFF Susie area 313 if ((mMemMapReg & 0x1) == 0) 314 return mSusie->Peek(addr); 315 } 316 else if ((addr >> 8) == 0xFD) { // FD00-FDFF Mikie area 317 if ((mMemMapReg & 0x2) == 0) 318 return mMikie->Peek(addr); 319 } 320 else if (addr < 0xFFF8) { // FE00-FFF7 Bios ROM 321 if ((mMemMapReg & 0x4) == 0) 322 return mBiosRom[addr & 0x1FF]; 323 } 324 else { // FFFA-FFFF Vector area 325 if ((mMemMapReg & 0x8) == 0) 326 return mBiosVectors[addr - 0xFFFA]; 327 } 328 329 return mRamPointer[addr]; 330 }; 331 inline void PokeW_CPU(ULONG addr,UWORD data) { Poke_CPU(addr, data&0xff); Poke_CPU(addr + 1, data >> 8); }; 332 inline UWORD PeekW_CPU(ULONG addr) { return ((Peek_CPU(addr))+(Peek_CPU(addr+1)<<8)); }; 333 334 // Mikey system interfacing 335 336 void ComLynxCable(int status) { mMikie->ComLynxCable(status); }; 337 void ComLynxRxData(int data) { mMikie->ComLynxRxData(data); }; 338 void ComLynxTxCallback(void (*function)(int data,ULONG objref),ULONG objref) { mMikie->ComLynxTxCallback(function,objref); }; 339 340 // Miscellaneous 341 342 void SetButtonData(ULONG data) {mSusie->SetButtonData(data);}; 343 ULONG GetButtonData(void) {return mSusie->GetButtonData();}; 344 void SetCycleBreakpoint(ULONG breakpoint) {mCycleCountBreakpoint=breakpoint;}; 345 UBYTE* GetRamPointer(void) {return mRam->GetRamPointer();}; 346 347 // Debugging 348 349 void DebugTrace(int address); 350 void DebugSetCallback(void (*function)(ULONG objref, char *message),ULONG objref); 351 void (*mpDebugCallback)(ULONG objref, char *message); 352 ULONG mDebugCallbackObject; 353 354 public: 355 ULONG mCycleCountBreakpoint; 356 CCart *mCart; 357 CRam *mRam; 358 C65C02 *mCpu; 359 CMikie *mMikie; 360 CSusie *mSusie; 361 CEEPROM *mEEPROM; 362 363 ULONG mFileType; 364 365 UBYTE mMemMapReg; 366 UBYTE *mRamPointer; 367 UBYTE mBiosVectors[0x8]; 368 UBYTE mBiosRom[0x200]; 369 }; 370 371 372 #endif