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 &regs) {mCpu->SetRegs(regs);};
GetRegs(C6502_REGS & regs)298       void   GetRegs(C6502_REGS &regs) {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