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