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 // Mikey chip emulation class                                               //
29 //////////////////////////////////////////////////////////////////////////////
30 //                                                                          //
31 // This class emulates all of the Mikey hardware with the exception of the  //
32 // CPU and memory selector. Update() does most of the work and does screen  //
33 // DMA and counter updates, it also schecules in which cycle the next timer //
34 // update will occur so that the CSystem->Update() doesnt have to call it   //
35 // every cycle, massive speedup but big complexity headache.                //
36 //                                                                          //
37 //    K. Wilkins                                                            //
38 // August 1997                                                              //
39 //                                                                          //
40 //////////////////////////////////////////////////////////////////////////////
41 // Revision History:                                                        //
42 // -----------------                                                        //
43 //                                                                          //
44 // 01Aug1997 KW Document header added & class documented.                   //
45 //                                                                          //
46 //////////////////////////////////////////////////////////////////////////////
47 
48 #define MIKIE_CPP
49 
50 //#include <crtdbg.h>
51 //#define	TRACE_MIKIE
52 
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include "system.h"
57 #include "mikie.h"
58 #include "lynxdef.h"
59 
60 
BlowOut(void)61 void CMikie::BlowOut(void)
62 {
63    char addr[100];
64    C6502_REGS regs;
65    mSystem.GetRegs(regs);
66    sprintf(addr,"Runtime Error - System Halted\nCMikie::Poke() - Read/Write to counter clocks at PC=$%04x.",regs.PC);
67    if(gError) gError->Warning(addr);
68    gSystemHalt=TRUE;
69 }
70 
71 
CMikie(CSystem & parent)72    CMikie::CMikie(CSystem& parent)
73 :mSystem(parent)
74 {
75    TRACE_MIKIE0("CMikie()");
76 
77    mpDisplayBits=NULL;
78    mpDisplayCurrent=NULL;
79    mpRamPointer=NULL;
80 
81    mDisplayRotate=MIKIE_BAD_MODE;
82    mDisplayFormat=MIKIE_PIXEL_FORMAT_16BPP_555;
83    mpDisplayCallback=NULL;
84    mDisplayCallbackObject=0;
85 
86    mUART_CABLE_PRESENT=FALSE;
87    mpUART_TX_CALLBACK=NULL;
88 
89    int loop;
90    for(loop=0;loop<16;loop++) mPalette[loop].Index=loop;
91    for(loop=0;loop<4096;loop++) mColourMap[loop]=0;
92 
93    mikbuf.set_sample_rate(HANDY_AUDIO_SAMPLE_FREQ, 60);
94    mikbuf.clock_rate(HANDY_SYSTEM_FREQ / 4);
95    mikbuf.bass_freq(60);
96    miksynth.volume(0.50);
97    miksynth.treble_eq(0);
98 
99    Reset();
100 }
101 
~CMikie()102 CMikie::~CMikie()
103 {
104    TRACE_MIKIE0("~CMikie()");
105 }
106 
107 
Reset(void)108 void CMikie::Reset(void)
109 {
110    TRACE_MIKIE0("Reset()");
111 
112    mAudioInputComparator=FALSE;	// Initialises to unknown
113    mDisplayAddress=0x00;			// Initialises to unknown
114    mLynxLine=0;
115    mLynxLineDMACounter=0;
116    mLynxAddr=0;
117 
118    mTimerStatusFlags=0x00;		// Initialises to ZERO, i.e No IRQ's
119    mTimerInterruptMask=0x00;
120 
121    mpRamPointer=mSystem.GetRamPointer();	// Fetch pointer to system RAM
122 
123    mTIM_0_BKUP=0;
124    mTIM_0_ENABLE_RELOAD=0;
125    mTIM_0_ENABLE_COUNT=0;
126    mTIM_0_LINKING=0;
127    mTIM_0_CURRENT=0;
128    mTIM_0_TIMER_DONE=0;
129    mTIM_0_LAST_CLOCK=0;
130    mTIM_0_BORROW_IN=0;
131    mTIM_0_BORROW_OUT=0;
132    mTIM_0_LAST_LINK_CARRY=0;
133    mTIM_0_LAST_COUNT=0;
134 
135    mTIM_1_BKUP=0;
136    mTIM_1_ENABLE_RELOAD=0;
137    mTIM_1_ENABLE_COUNT=0;
138    mTIM_1_LINKING=0;
139    mTIM_1_CURRENT=0;
140    mTIM_1_TIMER_DONE=0;
141    mTIM_1_LAST_CLOCK=0;
142    mTIM_1_BORROW_IN=0;
143    mTIM_1_BORROW_OUT=0;
144    mTIM_1_LAST_LINK_CARRY=0;
145    mTIM_1_LAST_COUNT=0;
146 
147    mTIM_2_BKUP=0;
148    mTIM_2_ENABLE_RELOAD=0;
149    mTIM_2_ENABLE_COUNT=0;
150    mTIM_2_LINKING=0;
151    mTIM_2_CURRENT=0;
152    mTIM_2_TIMER_DONE=0;
153    mTIM_2_LAST_CLOCK=0;
154    mTIM_2_BORROW_IN=0;
155    mTIM_2_BORROW_OUT=0;
156    mTIM_2_LAST_LINK_CARRY=0;
157    mTIM_2_LAST_COUNT=0;
158 
159    mTIM_3_BKUP=0;
160    mTIM_3_ENABLE_RELOAD=0;
161    mTIM_3_ENABLE_COUNT=0;
162    mTIM_3_LINKING=0;
163    mTIM_3_CURRENT=0;
164    mTIM_3_TIMER_DONE=0;
165    mTIM_3_LAST_CLOCK=0;
166    mTIM_3_BORROW_IN=0;
167    mTIM_3_BORROW_OUT=0;
168    mTIM_3_LAST_LINK_CARRY=0;
169    mTIM_3_LAST_COUNT=0;
170 
171    mTIM_4_BKUP=0;
172    mTIM_4_ENABLE_RELOAD=0;
173    mTIM_4_ENABLE_COUNT=0;
174    mTIM_4_LINKING=0;
175    mTIM_4_CURRENT=0;
176    mTIM_4_TIMER_DONE=0;
177    mTIM_4_LAST_CLOCK=0;
178    mTIM_4_BORROW_IN=0;
179    mTIM_4_BORROW_OUT=0;
180    mTIM_4_LAST_LINK_CARRY=0;
181    mTIM_4_LAST_COUNT=0;
182 
183    mTIM_5_BKUP=0;
184    mTIM_5_ENABLE_RELOAD=0;
185    mTIM_5_ENABLE_COUNT=0;
186    mTIM_5_LINKING=0;
187    mTIM_5_CURRENT=0;
188    mTIM_5_TIMER_DONE=0;
189    mTIM_5_LAST_CLOCK=0;
190    mTIM_5_BORROW_IN=0;
191    mTIM_5_BORROW_OUT=0;
192    mTIM_5_LAST_LINK_CARRY=0;
193    mTIM_5_LAST_COUNT=0;
194 
195    mTIM_6_BKUP=0;
196    mTIM_6_ENABLE_RELOAD=0;
197    mTIM_6_ENABLE_COUNT=0;
198    mTIM_6_LINKING=0;
199    mTIM_6_CURRENT=0;
200    mTIM_6_TIMER_DONE=0;
201    mTIM_6_LAST_CLOCK=0;
202    mTIM_6_BORROW_IN=0;
203    mTIM_6_BORROW_OUT=0;
204    mTIM_6_LAST_LINK_CARRY=0;
205    mTIM_6_LAST_COUNT=0;
206 
207    mTIM_7_BKUP=0;
208    mTIM_7_ENABLE_RELOAD=0;
209    mTIM_7_ENABLE_COUNT=0;
210    mTIM_7_LINKING=0;
211    mTIM_7_CURRENT=0;
212    mTIM_7_TIMER_DONE=0;
213    mTIM_7_LAST_CLOCK=0;
214    mTIM_7_BORROW_IN=0;
215    mTIM_7_BORROW_OUT=0;
216    mTIM_7_LAST_LINK_CARRY=0;
217    mTIM_7_LAST_COUNT=0;
218 
219    mAUDIO_0_BKUP=0;
220    mAUDIO_0_ENABLE_RELOAD=0;
221    mAUDIO_0_ENABLE_COUNT=0;
222    mAUDIO_0_LINKING=0;
223    mAUDIO_0_CURRENT=0;
224    mAUDIO_0_TIMER_DONE=0;
225    mAUDIO_0_LAST_CLOCK=0;
226    mAUDIO_0_BORROW_IN=0;
227    mAUDIO_0_BORROW_OUT=0;
228    mAUDIO_0_LAST_LINK_CARRY=0;
229    mAUDIO_0_LAST_COUNT=0;
230    mAUDIO_0_VOLUME=0;
231    mAUDIO_OUTPUT[0]=0;
232    mAUDIO_0_INTEGRATE_ENABLE=0;
233    mAUDIO_0_WAVESHAPER=0;
234 
235    mAUDIO_1_BKUP=0;
236    mAUDIO_1_ENABLE_RELOAD=0;
237    mAUDIO_1_ENABLE_COUNT=0;
238    mAUDIO_1_LINKING=0;
239    mAUDIO_1_CURRENT=0;
240    mAUDIO_1_TIMER_DONE=0;
241    mAUDIO_1_LAST_CLOCK=0;
242    mAUDIO_1_BORROW_IN=0;
243    mAUDIO_1_BORROW_OUT=0;
244    mAUDIO_1_LAST_LINK_CARRY=0;
245    mAUDIO_1_LAST_COUNT=0;
246    mAUDIO_1_VOLUME=0;
247    mAUDIO_OUTPUT[1]=0;
248    mAUDIO_1_INTEGRATE_ENABLE=0;
249    mAUDIO_1_WAVESHAPER=0;
250 
251    mAUDIO_2_BKUP=0;
252    mAUDIO_2_ENABLE_RELOAD=0;
253    mAUDIO_2_ENABLE_COUNT=0;
254    mAUDIO_2_LINKING=0;
255    mAUDIO_2_CURRENT=0;
256    mAUDIO_2_TIMER_DONE=0;
257    mAUDIO_2_LAST_CLOCK=0;
258    mAUDIO_2_BORROW_IN=0;
259    mAUDIO_2_BORROW_OUT=0;
260    mAUDIO_2_LAST_LINK_CARRY=0;
261    mAUDIO_2_LAST_COUNT=0;
262    mAUDIO_2_VOLUME=0;
263    mAUDIO_OUTPUT[2]=0;
264    mAUDIO_2_INTEGRATE_ENABLE=0;
265    mAUDIO_2_WAVESHAPER=0;
266 
267    mAUDIO_3_BKUP=0;
268    mAUDIO_3_ENABLE_RELOAD=0;
269    mAUDIO_3_ENABLE_COUNT=0;
270    mAUDIO_3_LINKING=0;
271    mAUDIO_3_CURRENT=0;
272    mAUDIO_3_TIMER_DONE=0;
273    mAUDIO_3_LAST_CLOCK=0;
274    mAUDIO_3_BORROW_IN=0;
275    mAUDIO_3_BORROW_OUT=0;
276    mAUDIO_3_LAST_LINK_CARRY=0;
277    mAUDIO_3_LAST_COUNT=0;
278    mAUDIO_3_VOLUME=0;
279    mAUDIO_OUTPUT[3]=0;
280    mAUDIO_3_INTEGRATE_ENABLE=0;
281    mAUDIO_3_WAVESHAPER=0;
282 
283    mSTEREO=0x00;	// xored! All channels enabled
284    mPAN=0x00;      // all channels panning OFF
285    mAUDIO_ATTEN[0]=0xff; // Full volume
286    mAUDIO_ATTEN[1]=0xff;
287    mAUDIO_ATTEN[2]=0xff;
288    mAUDIO_ATTEN[3]=0xff;
289 
290    // Start with an empty palette
291 
292    for(int loop=0;loop<16;loop++) {
293       mPalette[loop].Index=loop;
294    }
295 
296    // Initialise IODAT register
297 
298    mIODAT=0x00;
299    mIODIR=0x00;
300    mIODAT_REST_SIGNAL=0x00;
301 
302    //
303    // Initialise display control register vars
304    //
305    mDISPCTL_DMAEnable=FALSE;
306    mDISPCTL_Flip=FALSE;
307    mDISPCTL_FourColour=0;
308    mDISPCTL_Colour=0;
309 
310    //
311    // Initialise the UART variables
312    //
313    mUART_RX_IRQ_ENABLE=0;
314    mUART_TX_IRQ_ENABLE=0;
315 
316    mUART_TX_COUNTDOWN=UART_TX_INACTIVE;
317    mUART_RX_COUNTDOWN=UART_RX_INACTIVE;
318 
319    mUART_Rx_input_ptr=0;
320    mUART_Rx_output_ptr=0;
321    mUART_Rx_waiting=0;
322    mUART_Rx_framing_error=0;
323    mUART_Rx_overun_error=0;
324 
325    mUART_SENDBREAK=0;
326    mUART_TX_DATA=0;
327    mUART_RX_DATA=0;
328    mUART_RX_READY=0;
329 
330    mUART_PARITY_ENABLE=0;
331    mUART_PARITY_EVEN=0;
332 }
333 
GetLfsrNext(ULONG current)334 ULONG CMikie::GetLfsrNext(ULONG current)
335 {
336    // The table is built thus:
337    //	Bits 0-11  LFSR					(12 Bits)
338    //  Bits 12-20 Feedback switches	(9 Bits)
339    //     (Order = 7,0,1,2,3,4,5,10,11)
340    //  Order is mangled to make peek/poke easier as
341    //  bit 7 is in a seperate register
342    //
343    // Total 21 bits = 2MWords @ 4 Bytes/Word = 8MB !!!!!
344    //
345    // If the index is a combination of Current LFSR+Feedback the
346    // table will give the next value.
347 
348    static ULONG switches,lfsr,next,swloop,result;
349    static const ULONG switchbits[9]={7,0,1,2,3,4,5,10,11};
350 
351    switches=current>>12;
352    lfsr=current&0xfff;
353    result=0;
354    for(swloop=0;swloop<9;swloop++) {
355       if((switches>>swloop)&0x001) result^=(lfsr>>switchbits[swloop])&0x001;
356    }
357    result=(result)?0:1;
358    next=(switches<<12)|((lfsr<<1)&0xffe)|result;
359    return next;
360 }
361 
ContextSave(LSS_FILE * fp)362 bool CMikie::ContextSave(LSS_FILE *fp)
363 {
364    TRACE_MIKIE0("ContextSave()");
365 
366    if(!lss_printf(fp,"CMikie::ContextSave")) return 0;
367 
368    if(!lss_write(&mDisplayAddress,sizeof(ULONG),1,fp)) return 0;
369    if(!lss_write(&mAudioInputComparator,sizeof(ULONG),1,fp)) return 0;
370    if(!lss_write(&mTimerStatusFlags,sizeof(ULONG),1,fp)) return 0;
371    if(!lss_write(&mTimerInterruptMask,sizeof(ULONG),1,fp)) return 0;
372 
373    if(!lss_write(mPalette,sizeof(TPALETTE),16,fp)) return 0;
374 
375    if(!lss_write(&mIODAT,sizeof(ULONG),1,fp)) return 0;
376    if(!lss_write(&mIODAT_REST_SIGNAL,sizeof(ULONG),1,fp)) return 0;
377    if(!lss_write(&mIODIR,sizeof(ULONG),1,fp)) return 0;
378 
379    if(!lss_write(&mDISPCTL_DMAEnable,sizeof(ULONG),1,fp)) return 0;
380    if(!lss_write(&mDISPCTL_Flip,sizeof(ULONG),1,fp)) return 0;
381    if(!lss_write(&mDISPCTL_FourColour,sizeof(ULONG),1,fp)) return 0;
382    if(!lss_write(&mDISPCTL_Colour,sizeof(ULONG),1,fp)) return 0;
383 
384    if(!lss_write(&mTIM_0_BKUP,sizeof(ULONG),1,fp)) return 0;
385    if(!lss_write(&mTIM_0_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
386    if(!lss_write(&mTIM_0_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
387    if(!lss_write(&mTIM_0_LINKING,sizeof(ULONG),1,fp)) return 0;
388    if(!lss_write(&mTIM_0_CURRENT,sizeof(ULONG),1,fp)) return 0;
389    if(!lss_write(&mTIM_0_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
390    if(!lss_write(&mTIM_0_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
391    if(!lss_write(&mTIM_0_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
392    if(!lss_write(&mTIM_0_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
393    if(!lss_write(&mTIM_0_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
394    if(!lss_write(&mTIM_0_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
395 
396    if(!lss_write(&mTIM_1_BKUP,sizeof(ULONG),1,fp)) return 0;
397    if(!lss_write(&mTIM_1_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
398    if(!lss_write(&mTIM_1_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
399    if(!lss_write(&mTIM_1_LINKING,sizeof(ULONG),1,fp)) return 0;
400    if(!lss_write(&mTIM_1_CURRENT,sizeof(ULONG),1,fp)) return 0;
401    if(!lss_write(&mTIM_1_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
402    if(!lss_write(&mTIM_1_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
403    if(!lss_write(&mTIM_1_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
404    if(!lss_write(&mTIM_1_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
405    if(!lss_write(&mTIM_1_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
406    if(!lss_write(&mTIM_1_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
407 
408    if(!lss_write(&mTIM_2_BKUP,sizeof(ULONG),1,fp)) return 0;
409    if(!lss_write(&mTIM_2_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
410    if(!lss_write(&mTIM_2_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
411    if(!lss_write(&mTIM_2_LINKING,sizeof(ULONG),1,fp)) return 0;
412    if(!lss_write(&mTIM_2_CURRENT,sizeof(ULONG),1,fp)) return 0;
413    if(!lss_write(&mTIM_2_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
414    if(!lss_write(&mTIM_2_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
415    if(!lss_write(&mTIM_2_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
416    if(!lss_write(&mTIM_2_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
417    if(!lss_write(&mTIM_2_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
418    if(!lss_write(&mTIM_2_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
419 
420    if(!lss_write(&mTIM_3_BKUP,sizeof(ULONG),1,fp)) return 0;
421    if(!lss_write(&mTIM_3_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
422    if(!lss_write(&mTIM_3_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
423    if(!lss_write(&mTIM_3_LINKING,sizeof(ULONG),1,fp)) return 0;
424    if(!lss_write(&mTIM_3_CURRENT,sizeof(ULONG),1,fp)) return 0;
425    if(!lss_write(&mTIM_3_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
426    if(!lss_write(&mTIM_3_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
427    if(!lss_write(&mTIM_3_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
428    if(!lss_write(&mTIM_3_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
429    if(!lss_write(&mTIM_3_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
430    if(!lss_write(&mTIM_3_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
431 
432    if(!lss_write(&mTIM_4_BKUP,sizeof(ULONG),1,fp)) return 0;
433    if(!lss_write(&mTIM_4_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
434    if(!lss_write(&mTIM_4_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
435    if(!lss_write(&mTIM_4_LINKING,sizeof(ULONG),1,fp)) return 0;
436    if(!lss_write(&mTIM_4_CURRENT,sizeof(ULONG),1,fp)) return 0;
437    if(!lss_write(&mTIM_4_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
438    if(!lss_write(&mTIM_4_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
439    if(!lss_write(&mTIM_4_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
440    if(!lss_write(&mTIM_4_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
441    if(!lss_write(&mTIM_4_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
442    if(!lss_write(&mTIM_4_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
443 
444    if(!lss_write(&mTIM_5_BKUP,sizeof(ULONG),1,fp)) return 0;
445    if(!lss_write(&mTIM_5_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
446    if(!lss_write(&mTIM_5_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
447    if(!lss_write(&mTIM_5_LINKING,sizeof(ULONG),1,fp)) return 0;
448    if(!lss_write(&mTIM_5_CURRENT,sizeof(ULONG),1,fp)) return 0;
449    if(!lss_write(&mTIM_5_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
450    if(!lss_write(&mTIM_5_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
451    if(!lss_write(&mTIM_5_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
452    if(!lss_write(&mTIM_5_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
453    if(!lss_write(&mTIM_5_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
454    if(!lss_write(&mTIM_5_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
455 
456    if(!lss_write(&mTIM_6_BKUP,sizeof(ULONG),1,fp)) return 0;
457    if(!lss_write(&mTIM_6_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
458    if(!lss_write(&mTIM_6_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
459    if(!lss_write(&mTIM_6_LINKING,sizeof(ULONG),1,fp)) return 0;
460    if(!lss_write(&mTIM_6_CURRENT,sizeof(ULONG),1,fp)) return 0;
461    if(!lss_write(&mTIM_6_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
462    if(!lss_write(&mTIM_6_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
463    if(!lss_write(&mTIM_6_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
464    if(!lss_write(&mTIM_6_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
465    if(!lss_write(&mTIM_6_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
466    if(!lss_write(&mTIM_6_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
467 
468    if(!lss_write(&mTIM_7_BKUP,sizeof(ULONG),1,fp)) return 0;
469    if(!lss_write(&mTIM_7_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
470    if(!lss_write(&mTIM_7_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
471    if(!lss_write(&mTIM_7_LINKING,sizeof(ULONG),1,fp)) return 0;
472    if(!lss_write(&mTIM_7_CURRENT,sizeof(ULONG),1,fp)) return 0;
473    if(!lss_write(&mTIM_7_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
474    if(!lss_write(&mTIM_7_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
475    if(!lss_write(&mTIM_7_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
476    if(!lss_write(&mTIM_7_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
477    if(!lss_write(&mTIM_7_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
478    if(!lss_write(&mTIM_7_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
479 
480    if(!lss_write(&mAUDIO_0_BKUP,sizeof(ULONG),1,fp)) return 0;
481    if(!lss_write(&mAUDIO_0_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
482    if(!lss_write(&mAUDIO_0_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
483    if(!lss_write(&mAUDIO_0_LINKING,sizeof(ULONG),1,fp)) return 0;
484    if(!lss_write(&mAUDIO_0_CURRENT,sizeof(ULONG),1,fp)) return 0;
485    if(!lss_write(&mAUDIO_0_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
486    if(!lss_write(&mAUDIO_0_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
487    if(!lss_write(&mAUDIO_0_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
488    if(!lss_write(&mAUDIO_0_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
489    if(!lss_write(&mAUDIO_0_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
490    if(!lss_write(&mAUDIO_0_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
491    if(!lss_write(&mAUDIO_0_VOLUME,sizeof(SBYTE),1,fp)) return 0;
492    if(!lss_write(&mAUDIO_OUTPUT[0],sizeof(SBYTE),1,fp)) return 0;
493    if(!lss_write(&mAUDIO_0_INTEGRATE_ENABLE,sizeof(ULONG),1,fp)) return 0;
494    if(!lss_write(&mAUDIO_0_WAVESHAPER,sizeof(ULONG),1,fp)) return 0;
495 
496    if(!lss_write(&mAUDIO_1_BKUP,sizeof(ULONG),1,fp)) return 0;
497    if(!lss_write(&mAUDIO_1_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
498    if(!lss_write(&mAUDIO_1_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
499    if(!lss_write(&mAUDIO_1_LINKING,sizeof(ULONG),1,fp)) return 0;
500    if(!lss_write(&mAUDIO_1_CURRENT,sizeof(ULONG),1,fp)) return 0;
501    if(!lss_write(&mAUDIO_1_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
502    if(!lss_write(&mAUDIO_1_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
503    if(!lss_write(&mAUDIO_1_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
504    if(!lss_write(&mAUDIO_1_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
505    if(!lss_write(&mAUDIO_1_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
506    if(!lss_write(&mAUDIO_1_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
507    if(!lss_write(&mAUDIO_1_VOLUME,sizeof(SBYTE),1,fp)) return 0;
508    if(!lss_write(&mAUDIO_OUTPUT[1],sizeof(SBYTE),1,fp)) return 0;
509    if(!lss_write(&mAUDIO_1_INTEGRATE_ENABLE,sizeof(ULONG),1,fp)) return 0;
510    if(!lss_write(&mAUDIO_1_WAVESHAPER,sizeof(ULONG),1,fp)) return 0;
511 
512    if(!lss_write(&mAUDIO_2_BKUP,sizeof(ULONG),1,fp)) return 0;
513    if(!lss_write(&mAUDIO_2_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
514    if(!lss_write(&mAUDIO_2_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
515    if(!lss_write(&mAUDIO_2_LINKING,sizeof(ULONG),1,fp)) return 0;
516    if(!lss_write(&mAUDIO_2_CURRENT,sizeof(ULONG),1,fp)) return 0;
517    if(!lss_write(&mAUDIO_2_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
518    if(!lss_write(&mAUDIO_2_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
519    if(!lss_write(&mAUDIO_2_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
520    if(!lss_write(&mAUDIO_2_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
521    if(!lss_write(&mAUDIO_2_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
522    if(!lss_write(&mAUDIO_2_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
523    if(!lss_write(&mAUDIO_2_VOLUME,sizeof(SBYTE),1,fp)) return 0;
524    if(!lss_write(&mAUDIO_OUTPUT[2],sizeof(SBYTE),1,fp)) return 0;
525    if(!lss_write(&mAUDIO_2_INTEGRATE_ENABLE,sizeof(ULONG),1,fp)) return 0;
526    if(!lss_write(&mAUDIO_2_WAVESHAPER,sizeof(ULONG),1,fp)) return 0;
527 
528    if(!lss_write(&mAUDIO_3_BKUP,sizeof(ULONG),1,fp)) return 0;
529    if(!lss_write(&mAUDIO_3_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
530    if(!lss_write(&mAUDIO_3_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
531    if(!lss_write(&mAUDIO_3_LINKING,sizeof(ULONG),1,fp)) return 0;
532    if(!lss_write(&mAUDIO_3_CURRENT,sizeof(ULONG),1,fp)) return 0;
533    if(!lss_write(&mAUDIO_3_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
534    if(!lss_write(&mAUDIO_3_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
535    if(!lss_write(&mAUDIO_3_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
536    if(!lss_write(&mAUDIO_3_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
537    if(!lss_write(&mAUDIO_3_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
538    if(!lss_write(&mAUDIO_3_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
539    if(!lss_write(&mAUDIO_3_VOLUME,sizeof(SBYTE),1,fp)) return 0;
540    if(!lss_write(&mAUDIO_OUTPUT[3],sizeof(SBYTE),1,fp)) return 0;
541    if(!lss_write(&mAUDIO_3_INTEGRATE_ENABLE,sizeof(ULONG),1,fp)) return 0;
542    if(!lss_write(&mAUDIO_3_WAVESHAPER,sizeof(ULONG),1,fp)) return 0;
543 
544    if(!lss_write(&mSTEREO,sizeof(ULONG),1,fp)) return 0;
545 
546    //
547    // Serial related variables
548    //
549    if(!lss_write(&mUART_RX_IRQ_ENABLE,sizeof(ULONG),1,fp)) return 0;
550    if(!lss_write(&mUART_TX_IRQ_ENABLE,sizeof(ULONG),1,fp)) return 0;
551 
552    if(!lss_write(&mUART_TX_COUNTDOWN,sizeof(ULONG),1,fp)) return 0;
553    if(!lss_write(&mUART_RX_COUNTDOWN,sizeof(ULONG),1,fp)) return 0;
554 
555    if(!lss_write(&mUART_SENDBREAK,sizeof(ULONG),1,fp)) return 0;
556    if(!lss_write(&mUART_TX_DATA,sizeof(ULONG),1,fp)) return 0;
557    if(!lss_write(&mUART_RX_DATA,sizeof(ULONG),1,fp)) return 0;
558    if(!lss_write(&mUART_RX_READY,sizeof(ULONG),1,fp)) return 0;
559 
560    if(!lss_write(&mUART_PARITY_ENABLE,sizeof(ULONG),1,fp)) return 0;
561    if(!lss_write(&mUART_PARITY_EVEN,sizeof(ULONG),1,fp)) return 0;
562 
563    return 1;
564 }
565 
ContextLoad(LSS_FILE * fp)566 bool CMikie::ContextLoad(LSS_FILE *fp)
567 {
568    TRACE_MIKIE0("ContextLoad()");
569 
570    char teststr[100]="XXXXXXXXXXXXXXXXXXX";
571    if(!lss_read(teststr,sizeof(char),19,fp)) return 0;
572    if(strcmp(teststr,"CMikie::ContextSave")!=0) return 0;
573 
574    if(!lss_read(&mDisplayAddress,sizeof(ULONG),1,fp)) return 0;
575    if(!lss_read(&mAudioInputComparator,sizeof(ULONG),1,fp)) return 0;
576    if(!lss_read(&mTimerStatusFlags,sizeof(ULONG),1,fp)) return 0;
577    if(!lss_read(&mTimerInterruptMask,sizeof(ULONG),1,fp)) return 0;
578 
579    if(!lss_read(mPalette,sizeof(TPALETTE),16,fp)) return 0;
580 
581    if(!lss_read(&mIODAT,sizeof(ULONG),1,fp)) return 0;
582    if(!lss_read(&mIODAT_REST_SIGNAL,sizeof(ULONG),1,fp)) return 0;
583    if(!lss_read(&mIODIR,sizeof(ULONG),1,fp)) return 0;
584 
585    if(!lss_read(&mDISPCTL_DMAEnable,sizeof(ULONG),1,fp)) return 0;
586    if(!lss_read(&mDISPCTL_Flip,sizeof(ULONG),1,fp)) return 0;
587    if(!lss_read(&mDISPCTL_FourColour,sizeof(ULONG),1,fp)) return 0;
588    if(!lss_read(&mDISPCTL_Colour,sizeof(ULONG),1,fp)) return 0;
589 
590    if(!lss_read(&mTIM_0_BKUP,sizeof(ULONG),1,fp)) return 0;
591    if(!lss_read(&mTIM_0_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
592    if(!lss_read(&mTIM_0_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
593    if(!lss_read(&mTIM_0_LINKING,sizeof(ULONG),1,fp)) return 0;
594    if(!lss_read(&mTIM_0_CURRENT,sizeof(ULONG),1,fp)) return 0;
595    if(!lss_read(&mTIM_0_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
596    if(!lss_read(&mTIM_0_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
597    if(!lss_read(&mTIM_0_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
598    if(!lss_read(&mTIM_0_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
599    if(!lss_read(&mTIM_0_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
600    if(!lss_read(&mTIM_0_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
601 
602    if(!lss_read(&mTIM_1_BKUP,sizeof(ULONG),1,fp)) return 0;
603    if(!lss_read(&mTIM_1_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
604    if(!lss_read(&mTIM_1_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
605    if(!lss_read(&mTIM_1_LINKING,sizeof(ULONG),1,fp)) return 0;
606    if(!lss_read(&mTIM_1_CURRENT,sizeof(ULONG),1,fp)) return 0;
607    if(!lss_read(&mTIM_1_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
608    if(!lss_read(&mTIM_1_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
609    if(!lss_read(&mTIM_1_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
610    if(!lss_read(&mTIM_1_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
611    if(!lss_read(&mTIM_1_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
612    if(!lss_read(&mTIM_1_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
613 
614    if(!lss_read(&mTIM_2_BKUP,sizeof(ULONG),1,fp)) return 0;
615    if(!lss_read(&mTIM_2_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
616    if(!lss_read(&mTIM_2_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
617    if(!lss_read(&mTIM_2_LINKING,sizeof(ULONG),1,fp)) return 0;
618    if(!lss_read(&mTIM_2_CURRENT,sizeof(ULONG),1,fp)) return 0;
619    if(!lss_read(&mTIM_2_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
620    if(!lss_read(&mTIM_2_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
621    if(!lss_read(&mTIM_2_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
622    if(!lss_read(&mTIM_2_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
623    if(!lss_read(&mTIM_2_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
624    if(!lss_read(&mTIM_2_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
625 
626    if(!lss_read(&mTIM_3_BKUP,sizeof(ULONG),1,fp)) return 0;
627    if(!lss_read(&mTIM_3_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
628    if(!lss_read(&mTIM_3_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
629    if(!lss_read(&mTIM_3_LINKING,sizeof(ULONG),1,fp)) return 0;
630    if(!lss_read(&mTIM_3_CURRENT,sizeof(ULONG),1,fp)) return 0;
631    if(!lss_read(&mTIM_3_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
632    if(!lss_read(&mTIM_3_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
633    if(!lss_read(&mTIM_3_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
634    if(!lss_read(&mTIM_3_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
635    if(!lss_read(&mTIM_3_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
636    if(!lss_read(&mTIM_3_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
637 
638    if(!lss_read(&mTIM_4_BKUP,sizeof(ULONG),1,fp)) return 0;
639    if(!lss_read(&mTIM_4_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
640    if(!lss_read(&mTIM_4_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
641    if(!lss_read(&mTIM_4_LINKING,sizeof(ULONG),1,fp)) return 0;
642    if(!lss_read(&mTIM_4_CURRENT,sizeof(ULONG),1,fp)) return 0;
643    if(!lss_read(&mTIM_4_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
644    if(!lss_read(&mTIM_4_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
645    if(!lss_read(&mTIM_4_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
646    if(!lss_read(&mTIM_4_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
647    if(!lss_read(&mTIM_4_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
648    if(!lss_read(&mTIM_4_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
649 
650    if(!lss_read(&mTIM_5_BKUP,sizeof(ULONG),1,fp)) return 0;
651    if(!lss_read(&mTIM_5_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
652    if(!lss_read(&mTIM_5_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
653    if(!lss_read(&mTIM_5_LINKING,sizeof(ULONG),1,fp)) return 0;
654    if(!lss_read(&mTIM_5_CURRENT,sizeof(ULONG),1,fp)) return 0;
655    if(!lss_read(&mTIM_5_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
656    if(!lss_read(&mTIM_5_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
657    if(!lss_read(&mTIM_5_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
658    if(!lss_read(&mTIM_5_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
659    if(!lss_read(&mTIM_5_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
660    if(!lss_read(&mTIM_5_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
661 
662    if(!lss_read(&mTIM_6_BKUP,sizeof(ULONG),1,fp)) return 0;
663    if(!lss_read(&mTIM_6_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
664    if(!lss_read(&mTIM_6_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
665    if(!lss_read(&mTIM_6_LINKING,sizeof(ULONG),1,fp)) return 0;
666    if(!lss_read(&mTIM_6_CURRENT,sizeof(ULONG),1,fp)) return 0;
667    if(!lss_read(&mTIM_6_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
668    if(!lss_read(&mTIM_6_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
669    if(!lss_read(&mTIM_6_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
670    if(!lss_read(&mTIM_6_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
671    if(!lss_read(&mTIM_6_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
672    if(!lss_read(&mTIM_6_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
673 
674    if(!lss_read(&mTIM_7_BKUP,sizeof(ULONG),1,fp)) return 0;
675    if(!lss_read(&mTIM_7_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
676    if(!lss_read(&mTIM_7_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
677    if(!lss_read(&mTIM_7_LINKING,sizeof(ULONG),1,fp)) return 0;
678    if(!lss_read(&mTIM_7_CURRENT,sizeof(ULONG),1,fp)) return 0;
679    if(!lss_read(&mTIM_7_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
680    if(!lss_read(&mTIM_7_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
681    if(!lss_read(&mTIM_7_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
682    if(!lss_read(&mTIM_7_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
683    if(!lss_read(&mTIM_7_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
684    if(!lss_read(&mTIM_7_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
685 
686    if(!lss_read(&mAUDIO_0_BKUP,sizeof(ULONG),1,fp)) return 0;
687    if(!lss_read(&mAUDIO_0_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
688    if(!lss_read(&mAUDIO_0_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
689    if(!lss_read(&mAUDIO_0_LINKING,sizeof(ULONG),1,fp)) return 0;
690    if(!lss_read(&mAUDIO_0_CURRENT,sizeof(ULONG),1,fp)) return 0;
691    if(!lss_read(&mAUDIO_0_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
692    if(!lss_read(&mAUDIO_0_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
693    if(!lss_read(&mAUDIO_0_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
694    if(!lss_read(&mAUDIO_0_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
695    if(!lss_read(&mAUDIO_0_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
696    if(!lss_read(&mAUDIO_0_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
697    if(!lss_read(&mAUDIO_0_VOLUME,sizeof(SBYTE),1,fp)) return 0;
698    if(!lss_read(&mAUDIO_OUTPUT[0],sizeof(SBYTE),1,fp)) return 0;
699    if(!lss_read(&mAUDIO_0_INTEGRATE_ENABLE,sizeof(ULONG),1,fp)) return 0;
700    if(!lss_read(&mAUDIO_0_WAVESHAPER,sizeof(ULONG),1,fp)) return 0;
701 
702    if(!lss_read(&mAUDIO_1_BKUP,sizeof(ULONG),1,fp)) return 0;
703    if(!lss_read(&mAUDIO_1_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
704    if(!lss_read(&mAUDIO_1_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
705    if(!lss_read(&mAUDIO_1_LINKING,sizeof(ULONG),1,fp)) return 0;
706    if(!lss_read(&mAUDIO_1_CURRENT,sizeof(ULONG),1,fp)) return 0;
707    if(!lss_read(&mAUDIO_1_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
708    if(!lss_read(&mAUDIO_1_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
709    if(!lss_read(&mAUDIO_1_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
710    if(!lss_read(&mAUDIO_1_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
711    if(!lss_read(&mAUDIO_1_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
712    if(!lss_read(&mAUDIO_1_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
713    if(!lss_read(&mAUDIO_1_VOLUME,sizeof(SBYTE),1,fp)) return 0;
714    if(!lss_read(&mAUDIO_OUTPUT[1],sizeof(SBYTE),1,fp)) return 0;
715    if(!lss_read(&mAUDIO_1_INTEGRATE_ENABLE,sizeof(ULONG),1,fp)) return 0;
716    if(!lss_read(&mAUDIO_1_WAVESHAPER,sizeof(ULONG),1,fp)) return 0;
717 
718    if(!lss_read(&mAUDIO_2_BKUP,sizeof(ULONG),1,fp)) return 0;
719    if(!lss_read(&mAUDIO_2_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
720    if(!lss_read(&mAUDIO_2_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
721    if(!lss_read(&mAUDIO_2_LINKING,sizeof(ULONG),1,fp)) return 0;
722    if(!lss_read(&mAUDIO_2_CURRENT,sizeof(ULONG),1,fp)) return 0;
723    if(!lss_read(&mAUDIO_2_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
724    if(!lss_read(&mAUDIO_2_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
725    if(!lss_read(&mAUDIO_2_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
726    if(!lss_read(&mAUDIO_2_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
727    if(!lss_read(&mAUDIO_2_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
728    if(!lss_read(&mAUDIO_2_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
729    if(!lss_read(&mAUDIO_2_VOLUME,sizeof(SBYTE),1,fp)) return 0;
730    if(!lss_read(&mAUDIO_OUTPUT[2],sizeof(SBYTE),1,fp)) return 0;
731    if(!lss_read(&mAUDIO_2_INTEGRATE_ENABLE,sizeof(ULONG),1,fp)) return 0;
732    if(!lss_read(&mAUDIO_2_WAVESHAPER,sizeof(ULONG),1,fp)) return 0;
733 
734    if(!lss_read(&mAUDIO_3_BKUP,sizeof(ULONG),1,fp)) return 0;
735    if(!lss_read(&mAUDIO_3_ENABLE_RELOAD,sizeof(ULONG),1,fp)) return 0;
736    if(!lss_read(&mAUDIO_3_ENABLE_COUNT,sizeof(ULONG),1,fp)) return 0;
737    if(!lss_read(&mAUDIO_3_LINKING,sizeof(ULONG),1,fp)) return 0;
738    if(!lss_read(&mAUDIO_3_CURRENT,sizeof(ULONG),1,fp)) return 0;
739    if(!lss_read(&mAUDIO_3_TIMER_DONE,sizeof(ULONG),1,fp)) return 0;
740    if(!lss_read(&mAUDIO_3_LAST_CLOCK,sizeof(ULONG),1,fp)) return 0;
741    if(!lss_read(&mAUDIO_3_BORROW_IN,sizeof(ULONG),1,fp)) return 0;
742    if(!lss_read(&mAUDIO_3_BORROW_OUT,sizeof(ULONG),1,fp)) return 0;
743    if(!lss_read(&mAUDIO_3_LAST_LINK_CARRY,sizeof(ULONG),1,fp)) return 0;
744    if(!lss_read(&mAUDIO_3_LAST_COUNT,sizeof(ULONG),1,fp)) return 0;
745    if(!lss_read(&mAUDIO_3_VOLUME,sizeof(SBYTE),1,fp)) return 0;
746    if(!lss_read(&mAUDIO_OUTPUT[3],sizeof(SBYTE),1,fp)) return 0;
747    if(!lss_read(&mAUDIO_3_INTEGRATE_ENABLE,sizeof(ULONG),1,fp)) return 0;
748    if(!lss_read(&mAUDIO_3_WAVESHAPER,sizeof(ULONG),1,fp)) return 0;
749 
750    if(!lss_read(&mSTEREO,sizeof(ULONG),1,fp)) return 0;
751 
752    //
753    // Serial related variables
754    //
755    if(!lss_read(&mUART_RX_IRQ_ENABLE,sizeof(ULONG),1,fp)) return 0;
756    if(!lss_read(&mUART_TX_IRQ_ENABLE,sizeof(ULONG),1,fp)) return 0;
757 
758    if(!lss_read(&mUART_TX_COUNTDOWN,sizeof(ULONG),1,fp)) return 0;
759    if(!lss_read(&mUART_RX_COUNTDOWN,sizeof(ULONG),1,fp)) return 0;
760 
761    if(!lss_read(&mUART_SENDBREAK,sizeof(ULONG),1,fp)) return 0;
762    if(!lss_read(&mUART_TX_DATA,sizeof(ULONG),1,fp)) return 0;
763    if(!lss_read(&mUART_RX_DATA,sizeof(ULONG),1,fp)) return 0;
764    if(!lss_read(&mUART_RX_READY,sizeof(ULONG),1,fp)) return 0;
765 
766    if(!lss_read(&mUART_PARITY_ENABLE,sizeof(ULONG),1,fp)) return 0;
767    if(!lss_read(&mUART_PARITY_EVEN,sizeof(ULONG),1,fp)) return 0;
768 
769    mikbuf.clear();
770    return 1;
771 }
772 
PresetForHomebrew(void)773 void CMikie::PresetForHomebrew(void)
774 {
775    TRACE_MIKIE0("PresetForHomebrew()");
776 
777    //
778    // After all of that nice timer init we'll start timers running as some homebrew
779    // i.e LR.O doesn't bother to setup the timers
780 
781    mTIM_0_BKUP=0x9e;
782    mTIM_0_ENABLE_RELOAD=TRUE;
783    mTIM_0_ENABLE_COUNT=TRUE;
784 
785    mTIM_2_BKUP=0x68;
786    mTIM_2_ENABLE_RELOAD=TRUE;
787    mTIM_2_ENABLE_COUNT=TRUE;
788    mTIM_2_LINKING=7;
789 
790    mDISPCTL_DMAEnable=TRUE;
791    mDISPCTL_Flip=FALSE;
792    mDISPCTL_FourColour=0;
793    mDISPCTL_Colour=TRUE;
794 }
795 
ComLynxCable(int status)796 void CMikie::ComLynxCable(int status)
797 {
798    mUART_CABLE_PRESENT=status;
799 }
800 
ComLynxRxData(int data)801 void CMikie::ComLynxRxData(int data)
802 {
803    TRACE_MIKIE1("ComLynxRxData() - Received %04x",data);
804    // Copy over the data
805    if(mUART_Rx_waiting<UART_MAX_RX_QUEUE) {
806       // Trigger incoming receive IF none waiting otherwise
807       // we NEVER get to receive it!!!
808       if(!mUART_Rx_waiting) mUART_RX_COUNTDOWN=UART_RX_TIME_PERIOD;
809 
810       // Receive the byte
811       mUART_Rx_input_queue[mUART_Rx_input_ptr]=data;
812       mUART_Rx_input_ptr=(++mUART_Rx_input_ptr)%UART_MAX_RX_QUEUE;
813       mUART_Rx_waiting++;
814       TRACE_MIKIE2("ComLynxRxData() - input ptr=%02d waiting=%02d",mUART_Rx_input_ptr,mUART_Rx_waiting);
815    } else {
816       TRACE_MIKIE0("ComLynxRxData() - UART RX Overun");
817    }
818 }
819 
ComLynxTxLoopback(int data)820 void CMikie::ComLynxTxLoopback(int data)
821 {
822    TRACE_MIKIE1("ComLynxTxLoopback() - Received %04x",data);
823 
824    if(mUART_Rx_waiting<UART_MAX_RX_QUEUE) {
825       // Trigger incoming receive IF none waiting otherwise
826       // we NEVER get to receive it!!!
827       if(!mUART_Rx_waiting) mUART_RX_COUNTDOWN=UART_RX_TIME_PERIOD;
828 
829       // Receive the byte - INSERT into front of queue
830       mUART_Rx_output_ptr=(--mUART_Rx_output_ptr)%UART_MAX_RX_QUEUE;
831       mUART_Rx_input_queue[mUART_Rx_output_ptr]=data;
832       mUART_Rx_waiting++;
833       TRACE_MIKIE2("ComLynxTxLoopback() - input ptr=%02d waiting=%02d",mUART_Rx_input_ptr,mUART_Rx_waiting);
834    } else {
835       TRACE_MIKIE0("ComLynxTxLoopback() - UART RX Overun");
836    }
837 }
838 
ComLynxTxCallback(void (* function)(int data,ULONG objref),ULONG objref)839 void CMikie::ComLynxTxCallback(void (*function)(int data,ULONG objref),ULONG objref)
840 {
841    mpUART_TX_CALLBACK=function;
842    mUART_TX_CALLBACK_OBJECT=objref;
843 }
844 
845 
DisplaySetAttributes(ULONG Rotate,ULONG Format,ULONG Pitch,UBYTE * (* RenderCallback)(ULONG objref),ULONG objref)846 void CMikie::DisplaySetAttributes(ULONG Rotate,ULONG Format,ULONG Pitch,UBYTE* (*RenderCallback)(ULONG objref),ULONG objref)
847 {
848    mDisplayRotate=Rotate;
849    mDisplayFormat=Format;
850    mDisplayPitch=Pitch;
851    mpDisplayCallback=RenderCallback;
852    mDisplayCallbackObject=objref;
853 
854    mpDisplayCurrent=NULL;
855 
856    if(mpDisplayCallback) {
857       mpDisplayBits=(*mpDisplayCallback)(mDisplayCallbackObject);
858    } else {
859       mpDisplayBits=NULL;
860    }
861 
862    //
863    // Calculate the colour lookup tabes for the relevant mode
864    //
865    TPALETTE Spot;
866 
867    switch(mDisplayFormat) {
868       case MIKIE_PIXEL_FORMAT_8BPP:
869          for(Spot.Index=0;Spot.Index<4096;Spot.Index++) {
870             mColourMap[Spot.Index]=(Spot.Colours.Red<<4)&0xe0;
871             mColourMap[Spot.Index]|=(Spot.Colours.Green<<1)&0x1c;
872             mColourMap[Spot.Index]|=(Spot.Colours.Blue>>2)&0x03;
873          }
874          break;
875       case MIKIE_PIXEL_FORMAT_16BPP_BGR555:
876          for(Spot.Index=0;Spot.Index<4096;Spot.Index++) {
877             mColourMap[Spot.Index]=((Spot.Colours.Blue<<11)&0x7800) | (Spot.Colours.Blue<<7)&0x0400;
878             mColourMap[Spot.Index]|=((Spot.Colours.Green<<6)&0x03c0) | ((Spot.Colours.Green<<2)&0x0020);
879             mColourMap[Spot.Index]|=((Spot.Colours.Red<<1)&0x001e) | ((Spot.Colours.Red>>3)&0x0001);
880          }
881          break;
882       case MIKIE_PIXEL_FORMAT_16BPP_555:
883          for(Spot.Index=0;Spot.Index<4096;Spot.Index++) {
884             mColourMap[Spot.Index]=((Spot.Colours.Red<<11)&0x7800) | (Spot.Colours.Red<<7)&0x0400;
885             mColourMap[Spot.Index]|=((Spot.Colours.Green<<6)&0x03c0) | ((Spot.Colours.Green<<2)&0x0020);
886             mColourMap[Spot.Index]|=((Spot.Colours.Blue<<1)&0x001e) | ((Spot.Colours.Blue>>3)&0x0001);
887          }
888          break;
889       case MIKIE_PIXEL_FORMAT_16BPP_565:
890          for(Spot.Index=0;Spot.Index<4096;Spot.Index++) {
891             mColourMap[Spot.Index]=((Spot.Colours.Red<<12)&0xf000) | (Spot.Colours.Red<<8)&0x0800;
892             mColourMap[Spot.Index]|=((Spot.Colours.Green<<7)&0x0780) | ((Spot.Colours.Green<<3)&0x0060);
893             mColourMap[Spot.Index]|=((Spot.Colours.Blue<<1)&0x001e) | ((Spot.Colours.Blue>>3)&0x0001);
894          }
895          break;
896       case MIKIE_PIXEL_FORMAT_24BPP:
897       case MIKIE_PIXEL_FORMAT_32BPP:
898          for(Spot.Index=0;Spot.Index<4096;Spot.Index++) {
899             mColourMap[Spot.Index]=((Spot.Colours.Red<<20)&0x00f00000) | ((Spot.Colours.Red<<16)&0x000f0000);
900             mColourMap[Spot.Index]|=((Spot.Colours.Green<<12)&0x0000f000) | ((Spot.Colours.Green<<8)&0x00000f00);
901             mColourMap[Spot.Index]|=((Spot.Colours.Blue<<4)&0x000000f0) | ((Spot.Colours.Blue<<0)&0x0000000f);
902          }
903          break;
904       default:
905          if(gError) gError->Warning("CMikie::SetScreenAttributes() - Unrecognised display format");
906          for(Spot.Index=0;Spot.Index<4096;Spot.Index++) mColourMap[Spot.Index]=0;
907          break;
908    }
909 
910    // Reset screen related counters/vars
911    mTIM_0_CURRENT=0;
912    mTIM_2_CURRENT=0;
913 
914    // Fix lastcount so that timer update will definately occur
915    mTIM_0_LAST_COUNT-=(1<<(4+mTIM_0_LINKING))+1;
916    mTIM_2_LAST_COUNT-=(1<<(4+mTIM_2_LINKING))+1;
917 
918    // Force immediate timer update
919    gNextTimerEvent=gSystemCycleCount;
920 }
921 
922 
DisplayRenderLine(void)923 ULONG CMikie::DisplayRenderLine(void)
924 {
925    UBYTE *bitmap_tmp=NULL;
926    ULONG source,loop;
927    ULONG work_done=0;
928 
929    if(!mpDisplayBits) return 0;
930    if(!mpDisplayCurrent) return 0;
931    if(!mDISPCTL_DMAEnable) return 0;
932 
933    //	if(mLynxLine&0x80000000) return 0;
934 
935    // Set the timer interrupt flag
936    if(mTimerInterruptMask&0x01) {
937       TRACE_MIKIE0("Update() - TIMER0 IRQ Triggered (Line Timer)");
938       mTimerStatusFlags|=0x01;
939       gSystemIRQ=TRUE;	// Added 19/09/06 fix for IRQ issue
940    }
941 
942    // Logic says it should be 101 but testing on an actual lynx shows the rest
943    // persiod is between lines 102,101,100 with the new line being latched at
944    // the beginning of count==99 hence the code below !!
945 
946    // Emulate REST signal
947    if(mLynxLine==mTIM_2_BKUP-2 || mLynxLine==mTIM_2_BKUP-3 || mLynxLine==mTIM_2_BKUP-4) mIODAT_REST_SIGNAL=TRUE;
948    else mIODAT_REST_SIGNAL=FALSE;
949 
950    if(mLynxLine==(mTIM_2_BKUP-3)) {
951       if(mDISPCTL_Flip) {
952          mLynxAddr=mDisplayAddress&0xfffc;
953          mLynxAddr+=3;
954       } else {
955          mLynxAddr=mDisplayAddress&0xfffc;
956       }
957       // Trigger line rending to start
958       mLynxLineDMACounter=102;
959    }
960 
961    // Decrement line counter logic
962    if(mLynxLine) mLynxLine--;
963 
964    // Do 102 lines, nothing more, less is OK.
965    if(mLynxLineDMACounter) {
966       //		TRACE_MIKIE1("Update() - Screen DMA, line %03d",line_count);
967       mLynxLineDMACounter--;
968 
969       // Cycle hit for a 80 RAM access in rendering a line
970       work_done+=(80+100)*DMA_RDWR_CYC;
971 
972       // Mikie screen DMA can only see the system RAM....
973       // (Step through bitmap, line at a time)
974 
975       // Assign the temporary pointer;
976       bitmap_tmp=mpDisplayCurrent;
977 
978       switch(mDisplayRotate) {
979          case MIKIE_NO_ROTATE:
980             if(mDisplayFormat==MIKIE_PIXEL_FORMAT_8BPP) {
981                for(loop=0;loop<SCREEN_WIDTH/2;loop++) {
982                   source=mpRamPointer[mLynxAddr];
983                   if(mDISPCTL_Flip) {
984                      mLynxAddr--;
985                      *(bitmap_tmp)=(UBYTE)mColourMap[mPalette[source&0x0f].Index];
986                      bitmap_tmp+=sizeof(UBYTE);
987                      *(bitmap_tmp)=(UBYTE)mColourMap[mPalette[source>>4].Index];
988                      bitmap_tmp+=sizeof(UBYTE);
989                   } else {
990                      mLynxAddr++;
991                      *(bitmap_tmp)=(UBYTE)mColourMap[mPalette[source>>4].Index];
992                      bitmap_tmp+=sizeof(UBYTE);
993                      *(bitmap_tmp)=(UBYTE)mColourMap[mPalette[source&0x0f].Index];
994                      bitmap_tmp+=sizeof(UBYTE);
995                   }
996                }
997             } else if(mDisplayFormat==MIKIE_PIXEL_FORMAT_16BPP_BGR555 || mDisplayFormat==MIKIE_PIXEL_FORMAT_16BPP_555 || mDisplayFormat==MIKIE_PIXEL_FORMAT_16BPP_565) {
998                for(loop=0;loop<SCREEN_WIDTH/2;loop++) {
999                   source=mpRamPointer[mLynxAddr];
1000                   if(mDISPCTL_Flip) {
1001                      mLynxAddr--;
1002                      *((UWORD*)(bitmap_tmp))=(UWORD)mColourMap[mPalette[source&0x0f].Index];
1003                      bitmap_tmp+=sizeof(UWORD);
1004                      *((UWORD*)(bitmap_tmp))=(UWORD)mColourMap[mPalette[source>>4].Index];
1005                      bitmap_tmp+=sizeof(UWORD);
1006                   } else {
1007                      mLynxAddr++;
1008                      *((UWORD*)(bitmap_tmp))=(UWORD)mColourMap[mPalette[source>>4].Index];
1009                      bitmap_tmp+=sizeof(UWORD);
1010                      *((UWORD*)(bitmap_tmp))=(UWORD)mColourMap[mPalette[source&0x0f].Index];
1011                      bitmap_tmp+=sizeof(UWORD);
1012                   }
1013                }
1014             } else if(mDisplayFormat==MIKIE_PIXEL_FORMAT_24BPP) {
1015                ULONG pixel;
1016                for(loop=0;loop<SCREEN_WIDTH/2;loop++) {
1017                   source=mpRamPointer[mLynxAddr];
1018                   if(mDISPCTL_Flip) {
1019                      mLynxAddr--;
1020                      pixel=mColourMap[mPalette[source&0x0f].Index];
1021                      *bitmap_tmp++=(UBYTE)pixel;
1022                      pixel>>=8;
1023                      *bitmap_tmp++=(UBYTE)pixel;
1024                      pixel>>=8;
1025                      *bitmap_tmp++=(UBYTE)pixel;
1026                      pixel=mColourMap[mPalette[source>>4].Index];
1027                      *bitmap_tmp++=(UBYTE)pixel;
1028                      pixel>>=8;
1029                      *bitmap_tmp++=(UBYTE)pixel;
1030                      pixel>>=8;
1031                      *bitmap_tmp++=(UBYTE)pixel;
1032                   } else {
1033                      mLynxAddr++;
1034                      pixel=mColourMap[mPalette[source>>4].Index];
1035                      *bitmap_tmp++=(UBYTE)pixel;
1036                      pixel>>=8;
1037                      *bitmap_tmp++=(UBYTE)pixel;
1038                      pixel>>=8;
1039                      *bitmap_tmp++=(UBYTE)pixel;
1040                      pixel=mColourMap[mPalette[source&0x0f].Index];
1041                      *bitmap_tmp++=(UBYTE)pixel;
1042                      pixel>>=8;
1043                      *bitmap_tmp++=(UBYTE)pixel;
1044                      pixel>>=8;
1045                      *bitmap_tmp++=(UBYTE)pixel;
1046                   }
1047                }
1048             } else if(mDisplayFormat==MIKIE_PIXEL_FORMAT_32BPP) {
1049                for(loop=0;loop<SCREEN_WIDTH/2;loop++) {
1050                   source=mpRamPointer[mLynxAddr];
1051                   if(mDISPCTL_Flip) {
1052                      mLynxAddr--;
1053                      *((ULONG*)(bitmap_tmp))=mColourMap[mPalette[source&0x0f].Index];
1054                      bitmap_tmp+=sizeof(ULONG);
1055                      *((ULONG*)(bitmap_tmp))=mColourMap[mPalette[source>>4].Index];
1056                      bitmap_tmp+=sizeof(ULONG);
1057                   } else {
1058                      mLynxAddr++;
1059                      *((ULONG*)(bitmap_tmp))=mColourMap[mPalette[source>>4].Index];
1060                      bitmap_tmp+=sizeof(ULONG);
1061                      *((ULONG*)(bitmap_tmp))=mColourMap[mPalette[source&0x0f].Index];
1062                      bitmap_tmp+=sizeof(ULONG);
1063                   }
1064                }
1065             }
1066             mpDisplayCurrent+=mDisplayPitch;
1067             break;
1068          case MIKIE_ROTATE_L:
1069             if(mDisplayFormat==MIKIE_PIXEL_FORMAT_8BPP) {
1070                for(loop=0;loop<SCREEN_WIDTH/2;loop++) {
1071                   source=mpRamPointer[mLynxAddr];
1072                   if(mDISPCTL_Flip) {
1073                      mLynxAddr--;
1074                      *(bitmap_tmp)=(UBYTE)mColourMap[mPalette[source&0x0f].Index];
1075                      bitmap_tmp+=mDisplayPitch;
1076                      *(bitmap_tmp)=(UBYTE)mColourMap[mPalette[source>>4].Index];
1077                      bitmap_tmp+=mDisplayPitch;
1078                   } else {
1079                      mLynxAddr++;
1080                      *(bitmap_tmp)=(UBYTE)mColourMap[mPalette[source>>4].Index];
1081                      bitmap_tmp+=mDisplayPitch;
1082                      *(bitmap_tmp)=(UBYTE)mColourMap[mPalette[source&0x0f].Index];
1083                      bitmap_tmp+=mDisplayPitch;
1084                   }
1085                }
1086                mpDisplayCurrent-=sizeof(UBYTE);
1087             } else if(mDisplayFormat==MIKIE_PIXEL_FORMAT_16BPP_BGR555 || mDisplayFormat==MIKIE_PIXEL_FORMAT_16BPP_555 || mDisplayFormat==MIKIE_PIXEL_FORMAT_16BPP_565) {
1088                for(loop=0;loop<SCREEN_WIDTH/2;loop++) {
1089                   source=mpRamPointer[mLynxAddr];
1090                   if(mDISPCTL_Flip) {
1091                      mLynxAddr--;
1092                      *((UWORD*)(bitmap_tmp))=(UWORD)mColourMap[mPalette[source&0x0f].Index];
1093                      bitmap_tmp+=mDisplayPitch;
1094                      *((UWORD*)(bitmap_tmp))=(UWORD)mColourMap[mPalette[source>>4].Index];
1095                      bitmap_tmp+=mDisplayPitch;
1096                   } else {
1097                      mLynxAddr++;
1098                      *((UWORD*)(bitmap_tmp))=(UWORD)mColourMap[mPalette[source>>4].Index];
1099                      bitmap_tmp+=mDisplayPitch;
1100                      *((UWORD*)(bitmap_tmp))=(UWORD)mColourMap[mPalette[source&0x0f].Index];
1101                      bitmap_tmp+=mDisplayPitch;
1102                   }
1103                }
1104                mpDisplayCurrent-=sizeof(UWORD);
1105             } else if(mDisplayFormat==MIKIE_PIXEL_FORMAT_24BPP) {
1106                ULONG pixel;
1107                for(loop=0;loop<SCREEN_WIDTH/2;loop++) {
1108                   source=mpRamPointer[mLynxAddr];
1109                   if(mDISPCTL_Flip) {
1110                      mLynxAddr--;
1111                      pixel=mColourMap[mPalette[source&0x0f].Index];
1112                      *(bitmap_tmp)=(UBYTE)pixel;
1113                      pixel>>=8;
1114                      *(bitmap_tmp+1)=(UBYTE)pixel;
1115                      pixel>>=8;
1116                      *(bitmap_tmp+2)=(UBYTE)pixel;
1117                      bitmap_tmp+=mDisplayPitch;
1118                      pixel=mColourMap[mPalette[source>>4].Index];
1119                      *(bitmap_tmp)=(UBYTE)pixel;
1120                      pixel>>=8;
1121                      *(bitmap_tmp+1)=(UBYTE)pixel;
1122                      pixel>>=8;
1123                      *(bitmap_tmp+2)=(UBYTE)pixel;
1124                      bitmap_tmp+=mDisplayPitch;
1125                   } else {
1126                      mLynxAddr++;
1127                      pixel=mColourMap[mPalette[source>>4].Index];
1128                      *(bitmap_tmp)=(UBYTE)pixel;
1129                      pixel>>=8;
1130                      *(bitmap_tmp+1)=(UBYTE)pixel;
1131                      pixel>>=8;
1132                      *(bitmap_tmp+2)=(UBYTE)pixel;
1133                      bitmap_tmp+=mDisplayPitch;
1134                      pixel=mColourMap[mPalette[source&0x0f].Index];
1135                      *(bitmap_tmp)=(UBYTE)pixel;
1136                      pixel>>=8;
1137                      *(bitmap_tmp+1)=(UBYTE)pixel;
1138                      pixel>>=8;
1139                      *(bitmap_tmp+2)=(UBYTE)pixel;
1140                      bitmap_tmp+=mDisplayPitch;
1141                   }
1142                }
1143                mpDisplayCurrent-=3;
1144             } else if(mDisplayFormat==MIKIE_PIXEL_FORMAT_32BPP) {
1145                for(loop=0;loop<SCREEN_WIDTH/2;loop++) {
1146                   source=mpRamPointer[mLynxAddr];
1147                   if(mDISPCTL_Flip) {
1148                      mLynxAddr--;
1149                      *((ULONG*)(bitmap_tmp))=mColourMap[mPalette[source&0x0f].Index];
1150                      bitmap_tmp+=mDisplayPitch;
1151                      *((ULONG*)(bitmap_tmp))=mColourMap[mPalette[source>>4].Index];
1152                      bitmap_tmp+=mDisplayPitch;
1153                   } else {
1154                      mLynxAddr++;
1155                      *((ULONG*)(bitmap_tmp))=mColourMap[mPalette[source>>4].Index];
1156                      bitmap_tmp+=mDisplayPitch;
1157                      *((ULONG*)(bitmap_tmp))=mColourMap[mPalette[source&0x0f].Index];
1158                      bitmap_tmp+=mDisplayPitch;
1159                   }
1160                }
1161                mpDisplayCurrent-=sizeof(ULONG);
1162             }
1163             break;
1164          case MIKIE_ROTATE_R:
1165             if(mDisplayFormat==MIKIE_PIXEL_FORMAT_8BPP) {
1166                for(loop=0;loop<SCREEN_WIDTH/2;loop++) {
1167                   source=mpRamPointer[mLynxAddr];
1168                   if(mDISPCTL_Flip) {
1169                      mLynxAddr--;
1170                      *(bitmap_tmp)=(UBYTE)mColourMap[mPalette[source&0x0f].Index];
1171                      bitmap_tmp-=mDisplayPitch;
1172                      *(bitmap_tmp)=(UBYTE)mColourMap[mPalette[source>>4].Index];
1173                      bitmap_tmp-=mDisplayPitch;
1174                   } else {
1175                      mLynxAddr++;
1176                      *(bitmap_tmp)=(UBYTE)mColourMap[mPalette[source>>4].Index];
1177                      bitmap_tmp-=mDisplayPitch;
1178                      *(bitmap_tmp)=(UBYTE)mColourMap[mPalette[source&0x0f].Index];
1179                      bitmap_tmp-=mDisplayPitch;
1180                   }
1181                }
1182                mpDisplayCurrent+=sizeof(UBYTE);
1183             } else if(mDisplayFormat==MIKIE_PIXEL_FORMAT_16BPP_BGR555 || mDisplayFormat==MIKIE_PIXEL_FORMAT_16BPP_555 || mDisplayFormat==MIKIE_PIXEL_FORMAT_16BPP_565) {
1184                for(loop=0;loop<SCREEN_WIDTH/2;loop++) {
1185                   source=mpRamPointer[mLynxAddr];
1186                   if(mDISPCTL_Flip) {
1187                      mLynxAddr--;
1188                      *((UWORD*)(bitmap_tmp))=(UWORD)mColourMap[mPalette[source&0x0f].Index];
1189                      bitmap_tmp-=mDisplayPitch;
1190                      *((UWORD*)(bitmap_tmp))=(UWORD)mColourMap[mPalette[source>>4].Index];
1191                      bitmap_tmp-=mDisplayPitch;
1192                   } else {
1193                      mLynxAddr++;
1194                      *((UWORD*)(bitmap_tmp))=(UWORD)mColourMap[mPalette[source>>4].Index];
1195                      bitmap_tmp-=mDisplayPitch;
1196                      *((UWORD*)(bitmap_tmp))=(UWORD)mColourMap[mPalette[source&0x0f].Index];
1197                      bitmap_tmp-=mDisplayPitch;
1198                   }
1199                }
1200                mpDisplayCurrent+=sizeof(UWORD);
1201             } else if(mDisplayFormat==MIKIE_PIXEL_FORMAT_24BPP) {
1202                ULONG pixel;
1203                for(loop=0;loop<SCREEN_WIDTH/2;loop++) {
1204                   source=mpRamPointer[mLynxAddr];
1205                   if(mDISPCTL_Flip) {
1206                      mLynxAddr--;
1207                      pixel=mColourMap[mPalette[source&0x0f].Index];
1208                      *(bitmap_tmp)=(UBYTE)pixel;
1209                      pixel>>=8;
1210                      *(bitmap_tmp+1)=(UBYTE)pixel;
1211                      pixel>>=8;
1212                      *(bitmap_tmp+2)=(UBYTE)pixel;
1213                      bitmap_tmp-=mDisplayPitch;
1214                      pixel=mColourMap[mPalette[source>>4].Index];
1215                      *(bitmap_tmp)=(UBYTE)pixel;
1216                      pixel>>=8;
1217                      *(bitmap_tmp+1)=(UBYTE)pixel;
1218                      pixel>>=8;
1219                      *(bitmap_tmp+2)=(UBYTE)pixel;
1220                      bitmap_tmp-=mDisplayPitch;
1221                   } else {
1222                      mLynxAddr++;
1223                      pixel=mColourMap[mPalette[source>>4].Index];
1224                      *(bitmap_tmp)=(UBYTE)pixel;
1225                      pixel>>=8;
1226                      *(bitmap_tmp+1)=(UBYTE)pixel;
1227                      pixel>>=8;
1228                      *(bitmap_tmp+2)=(UBYTE)pixel;
1229                      bitmap_tmp-=mDisplayPitch;
1230                      pixel=mColourMap[mPalette[source&0x0f].Index];
1231                      *(bitmap_tmp)=(UBYTE)pixel;
1232                      pixel>>=8;
1233                      *(bitmap_tmp+1)=(UBYTE)pixel;
1234                      pixel>>=8;
1235                      *(bitmap_tmp+2)=(UBYTE)pixel;
1236                      bitmap_tmp-=mDisplayPitch;
1237                   }
1238                }
1239                mpDisplayCurrent+=3;
1240             } else if(mDisplayFormat==MIKIE_PIXEL_FORMAT_32BPP) {
1241                for(loop=0;loop<SCREEN_WIDTH/2;loop++) {
1242                   source=mpRamPointer[mLynxAddr];
1243                   if(mDISPCTL_Flip) {
1244                      mLynxAddr--;
1245                      *((ULONG*)(bitmap_tmp))=mColourMap[mPalette[source&0x0f].Index];
1246                      bitmap_tmp-=mDisplayPitch;
1247                      *((ULONG*)(bitmap_tmp))=mColourMap[mPalette[source>>4].Index];
1248                      bitmap_tmp-=mDisplayPitch;
1249                   } else {
1250                      mLynxAddr++;
1251                      *((ULONG*)(bitmap_tmp))=mColourMap[mPalette[source>>4].Index];
1252                      bitmap_tmp-=mDisplayPitch;
1253                      *((ULONG*)(bitmap_tmp))=mColourMap[mPalette[source&0x0f].Index];
1254                      bitmap_tmp-=mDisplayPitch;
1255                   }
1256                }
1257                mpDisplayCurrent+=sizeof(ULONG);
1258             }
1259             break;
1260          default:
1261             break;
1262       }
1263    }
1264    return work_done;
1265 }
1266 
DisplayEndOfFrame(void)1267 ULONG CMikie::DisplayEndOfFrame(void)
1268 {
1269    // Stop any further line rendering
1270    mLynxLineDMACounter=0;
1271    mLynxLine=mTIM_2_BKUP;
1272 
1273    if(gCPUWakeupTime) {
1274       gCPUWakeupTime = 0;
1275       ClearCPUSleep();
1276    }
1277 
1278    // Set the timer status flag
1279    if(mTimerInterruptMask&0x04) {
1280       TRACE_MIKIE0("Update() - TIMER2 IRQ Triggered (Frame Timer)");
1281       mTimerStatusFlags|=0x04;
1282       gSystemIRQ=TRUE;	// Added 19/09/06 fix for IRQ issue
1283    }
1284 
1285    //	TRACE_MIKIE0("Update() - Frame end");
1286    // Trigger the callback to the display sub-system to render the
1287    // display and fetch the new pointer to be used for the lynx
1288    // display buffer for the forthcoming frame
1289    if(mpDisplayCallback) mpDisplayBits=(*mpDisplayCallback)(mDisplayCallbackObject);
1290 
1291    // Reinitialise the screen buffer pointer
1292    // Make any necessary adjustment for rotation
1293    switch(mDisplayRotate) {
1294       case MIKIE_ROTATE_L:
1295          mpDisplayCurrent=mpDisplayBits;
1296          switch(mDisplayFormat) {
1297             case MIKIE_PIXEL_FORMAT_8BPP:
1298                mpDisplayCurrent+=1*(HANDY_SCREEN_HEIGHT-1);
1299                break;
1300             case MIKIE_PIXEL_FORMAT_16BPP_BGR555:
1301             case MIKIE_PIXEL_FORMAT_16BPP_555:
1302             case MIKIE_PIXEL_FORMAT_16BPP_565:
1303                mpDisplayCurrent+=2*(HANDY_SCREEN_HEIGHT-1);
1304                break;
1305             case MIKIE_PIXEL_FORMAT_24BPP:
1306                mpDisplayCurrent+=3*(HANDY_SCREEN_HEIGHT-1);
1307                break;
1308             case MIKIE_PIXEL_FORMAT_32BPP:
1309                mpDisplayCurrent+=4*(HANDY_SCREEN_HEIGHT-1);
1310                break;
1311             default:
1312                break;
1313          }
1314          break;
1315       case MIKIE_ROTATE_R:
1316          mpDisplayCurrent=mpDisplayBits+(mDisplayPitch*(HANDY_SCREEN_WIDTH-1));
1317          break;
1318       case MIKIE_NO_ROTATE:
1319       default:
1320          mpDisplayCurrent=mpDisplayBits;
1321          break;
1322    }
1323 
1324    mikbuf.end_frame((gSystemCycleCount - gAudioLastUpdateCycle) / 4);
1325    gAudioBufferPointer = mikbuf.read_samples((blip_sample_t*) gAudioBuffer, HANDY_AUDIO_BUFFER_SIZE / 2) * 2;
1326 
1327    return 0;
1328 }
1329 
1330 // Peek/Poke memory handlers
1331 
Poke(ULONG addr,UBYTE data)1332 void CMikie::Poke(ULONG addr,UBYTE data)
1333 {
1334    switch(addr&0xff) {
1335       case (TIM0BKUP&0xff):
1336          mTIM_0_BKUP=data;
1337          TRACE_MIKIE2("Poke(TIM0BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1338          break;
1339       case (TIM1BKUP&0xff):
1340          mTIM_1_BKUP=data;
1341          TRACE_MIKIE2("Poke(TIM1BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1342          break;
1343       case (TIM2BKUP&0xff):
1344          mTIM_2_BKUP=data;
1345          TRACE_MIKIE2("Poke(TIM2BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1346          break;
1347       case (TIM3BKUP&0xff):
1348          mTIM_3_BKUP=data;
1349          TRACE_MIKIE2("Poke(TIM3BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1350          break;
1351       case (TIM4BKUP&0xff):
1352          mTIM_4_BKUP=data;
1353          TRACE_MIKIE2("Poke(TIM4BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1354          break;
1355       case (TIM5BKUP&0xff):
1356          mTIM_5_BKUP=data;
1357          TRACE_MIKIE2("Poke(TIM5BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1358          break;
1359       case (TIM6BKUP&0xff):
1360          mTIM_6_BKUP=data;
1361          TRACE_MIKIE2("Poke(TIM6BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1362          break;
1363       case (TIM7BKUP&0xff):
1364          mTIM_7_BKUP=data;
1365          TRACE_MIKIE2("Poke(TIM7BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1366          break;
1367 
1368 
1369       case (TIM0CTLA&0xff):
1370          mTimerInterruptMask&=(0x01^0xff);
1371          mTimerInterruptMask|=(data&0x80)?0x01:0x00;
1372          mTIM_0_ENABLE_RELOAD=data&0x10;
1373          mTIM_0_ENABLE_COUNT=data&0x08;
1374          mTIM_0_LINKING=data&0x07;
1375          if(data&0x40) mTIM_0_TIMER_DONE=0;
1376          if(data&0x48) {
1377             mTIM_0_LAST_COUNT=gSystemCycleCount;
1378             gNextTimerEvent=gSystemCycleCount;
1379          }
1380          TRACE_MIKIE2("Poke(TIM0CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1381          break;
1382       case (TIM1CTLA&0xff):
1383          mTimerInterruptMask&=(0x02^0xff);
1384          mTimerInterruptMask|=(data&0x80)?0x02:0x00;
1385          mTIM_1_ENABLE_RELOAD=data&0x10;
1386          mTIM_1_ENABLE_COUNT=data&0x08;
1387          mTIM_1_LINKING=data&0x07;
1388          if(data&0x40) mTIM_1_TIMER_DONE=0;
1389          if(data&0x48) {
1390             mTIM_1_LAST_COUNT=gSystemCycleCount;
1391             gNextTimerEvent=gSystemCycleCount;
1392          }
1393          TRACE_MIKIE2("Poke(TIM1CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1394          break;
1395       case (TIM2CTLA&0xff):
1396          mTimerInterruptMask&=(0x04^0xff);
1397          mTimerInterruptMask|=(data&0x80)?0x04:0x00;
1398          mTIM_2_ENABLE_RELOAD=data&0x10;
1399          mTIM_2_ENABLE_COUNT=data&0x08;
1400          mTIM_2_LINKING=data&0x07;
1401          if(data&0x40) mTIM_2_TIMER_DONE=0;
1402          if(data&0x48) {
1403             mTIM_2_LAST_COUNT=gSystemCycleCount;
1404             gNextTimerEvent=gSystemCycleCount;
1405          }
1406          TRACE_MIKIE2("Poke(TIM2CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1407          break;
1408       case (TIM3CTLA&0xff):
1409          mTimerInterruptMask&=(0x08^0xff);
1410          mTimerInterruptMask|=(data&0x80)?0x08:0x00;
1411          mTIM_3_ENABLE_RELOAD=data&0x10;
1412          mTIM_3_ENABLE_COUNT=data&0x08;
1413          mTIM_3_LINKING=data&0x07;
1414          if(data&0x40) mTIM_3_TIMER_DONE=0;
1415          if(data&0x48) {
1416             mTIM_3_LAST_COUNT=gSystemCycleCount;
1417             gNextTimerEvent=gSystemCycleCount;
1418          }
1419          TRACE_MIKIE2("Poke(TIM3CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1420          break;
1421       case (TIM4CTLA&0xff):
1422          // Timer 4 can never generate interrupts as its timer output is used
1423          // to drive the UART clock generator
1424          mTIM_4_ENABLE_RELOAD=data&0x10;
1425          mTIM_4_ENABLE_COUNT=data&0x08;
1426          mTIM_4_LINKING=data&0x07;
1427          if(data&0x40) mTIM_4_TIMER_DONE=0;
1428          if(data&0x48) {
1429             mTIM_4_LAST_COUNT=gSystemCycleCount;
1430             gNextTimerEvent=gSystemCycleCount;
1431          }
1432          TRACE_MIKIE2("Poke(TIM4CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1433          break;
1434       case (TIM5CTLA&0xff):
1435          mTimerInterruptMask&=(0x20^0xff);
1436          mTimerInterruptMask|=(data&0x80)?0x20:0x00;
1437          mTIM_5_ENABLE_RELOAD=data&0x10;
1438          mTIM_5_ENABLE_COUNT=data&0x08;
1439          mTIM_5_LINKING=data&0x07;
1440          if(data&0x40) mTIM_5_TIMER_DONE=0;
1441          if(data&0x48) {
1442             mTIM_5_LAST_COUNT=gSystemCycleCount;
1443             gNextTimerEvent=gSystemCycleCount;
1444          }
1445          TRACE_MIKIE2("Poke(TIM5CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1446          break;
1447       case (TIM6CTLA&0xff):
1448          mTimerInterruptMask&=(0x40^0xff);
1449          mTimerInterruptMask|=(data&0x80)?0x40:0x00;
1450          mTIM_6_ENABLE_RELOAD=data&0x10;
1451          mTIM_6_ENABLE_COUNT=data&0x08;
1452          mTIM_6_LINKING=data&0x07;
1453          if(data&0x40) mTIM_6_TIMER_DONE=0;
1454          if(data&0x48) {
1455             mTIM_6_LAST_COUNT=gSystemCycleCount;
1456             gNextTimerEvent=gSystemCycleCount;
1457          }
1458          TRACE_MIKIE2("Poke(TIM6CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1459          break;
1460       case (TIM7CTLA&0xff):
1461          mTimerInterruptMask&=(0x80^0xff);
1462          mTimerInterruptMask|=(data&0x80)?0x80:0x00;
1463          mTIM_7_ENABLE_RELOAD=data&0x10;
1464          mTIM_7_ENABLE_COUNT=data&0x08;
1465          mTIM_7_LINKING=data&0x07;
1466          if(data&0x40) mTIM_7_TIMER_DONE=0;
1467          if(data&0x48) {
1468             mTIM_7_LAST_COUNT=gSystemCycleCount;
1469             gNextTimerEvent=gSystemCycleCount;
1470          }
1471          TRACE_MIKIE2("Poke(TIM7CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1472          break;
1473 
1474 
1475       case (TIM0CNT&0xff):
1476          mTIM_0_CURRENT=data;
1477          gNextTimerEvent=gSystemCycleCount;
1478          TRACE_MIKIE2("Poke(TIM0CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1479          break;
1480       case (TIM1CNT&0xff):
1481          mTIM_1_CURRENT=data;
1482          gNextTimerEvent=gSystemCycleCount;
1483          TRACE_MIKIE2("Poke(TIM1CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1484          break;
1485       case (TIM2CNT&0xff):
1486          mTIM_2_CURRENT=data;
1487          gNextTimerEvent=gSystemCycleCount;
1488          TRACE_MIKIE2("Poke(TIM2CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1489          break;
1490       case (TIM3CNT&0xff):
1491          mTIM_3_CURRENT=data;
1492          gNextTimerEvent=gSystemCycleCount;
1493          TRACE_MIKIE2("Poke(TIM3CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1494          break;
1495       case (TIM4CNT&0xff):
1496          mTIM_4_CURRENT=data;
1497          gNextTimerEvent=gSystemCycleCount;
1498          TRACE_MIKIE2("Poke(TIM4CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1499          break;
1500       case (TIM5CNT&0xff):
1501          mTIM_5_CURRENT=data;
1502          gNextTimerEvent=gSystemCycleCount;
1503          TRACE_MIKIE2("Poke(TIM5CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1504          break;
1505       case (TIM6CNT&0xff):
1506          mTIM_6_CURRENT=data;
1507          gNextTimerEvent=gSystemCycleCount;
1508          TRACE_MIKIE2("Poke(TIM6CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1509          break;
1510       case (TIM7CNT&0xff):
1511          mTIM_7_CURRENT=data;
1512          gNextTimerEvent=gSystemCycleCount;
1513          TRACE_MIKIE2("Poke(TIM7CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1514          break;
1515 
1516       case (TIM0CTLB&0xff):
1517          mTIM_0_TIMER_DONE=data&0x08;
1518          mTIM_0_LAST_CLOCK=data&0x04;
1519          mTIM_0_BORROW_IN=data&0x02;
1520          mTIM_0_BORROW_OUT=data&0x01;
1521          TRACE_MIKIE2("Poke(TIM0CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1522          //			BlowOut();
1523          break;
1524       case (TIM1CTLB&0xff):
1525          mTIM_1_TIMER_DONE=data&0x08;
1526          mTIM_1_LAST_CLOCK=data&0x04;
1527          mTIM_1_BORROW_IN=data&0x02;
1528          mTIM_1_BORROW_OUT=data&0x01;
1529          TRACE_MIKIE2("Poke(TIM1CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1530          //			BlowOut();
1531          break;
1532       case (TIM2CTLB&0xff):
1533          mTIM_2_TIMER_DONE=data&0x08;
1534          mTIM_2_LAST_CLOCK=data&0x04;
1535          mTIM_2_BORROW_IN=data&0x02;
1536          mTIM_2_BORROW_OUT=data&0x01;
1537          TRACE_MIKIE2("Poke(TIM2CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1538          //			BlowOut();
1539          break;
1540       case (TIM3CTLB&0xff):
1541          mTIM_3_TIMER_DONE=data&0x08;
1542          mTIM_3_LAST_CLOCK=data&0x04;
1543          mTIM_3_BORROW_IN=data&0x02;
1544          mTIM_3_BORROW_OUT=data&0x01;
1545          TRACE_MIKIE2("Poke(TIM3CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1546          //			BlowOut();
1547          break;
1548       case (TIM4CTLB&0xff):
1549          mTIM_4_TIMER_DONE=data&0x08;
1550          mTIM_4_LAST_CLOCK=data&0x04;
1551          mTIM_4_BORROW_IN=data&0x02;
1552          mTIM_4_BORROW_OUT=data&0x01;
1553          TRACE_MIKIE2("Poke(TIM4CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1554          //			BlowOut();
1555          break;
1556       case (TIM5CTLB&0xff):
1557          mTIM_5_TIMER_DONE=data&0x08;
1558          mTIM_5_LAST_CLOCK=data&0x04;
1559          mTIM_5_BORROW_IN=data&0x02;
1560          mTIM_5_BORROW_OUT=data&0x01;
1561          TRACE_MIKIE2("Poke(TIM5CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1562          //			BlowOut();
1563          break;
1564       case (TIM6CTLB&0xff):
1565          mTIM_6_TIMER_DONE=data&0x08;
1566          mTIM_6_LAST_CLOCK=data&0x04;
1567          mTIM_6_BORROW_IN=data&0x02;
1568          mTIM_6_BORROW_OUT=data&0x01;
1569          TRACE_MIKIE2("Poke(TIM6CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1570          //			BlowOut();
1571          break;
1572       case (TIM7CTLB&0xff):
1573          mTIM_7_TIMER_DONE=data&0x08;
1574          mTIM_7_LAST_CLOCK=data&0x04;
1575          mTIM_7_BORROW_IN=data&0x02;
1576          mTIM_7_BORROW_OUT=data&0x01;
1577          TRACE_MIKIE2("Poke(TIM7CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1578          //			BlowOut();
1579          break;
1580 
1581       case (AUD0VOL&0xff):
1582          mAUDIO_0_VOLUME=(SBYTE)data;
1583          TRACE_MIKIE2("Poke(AUD0VOL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1584          break;
1585       case (AUD0SHFTFB&0xff):
1586          mAUDIO_0_WAVESHAPER&=0x001fff;
1587          mAUDIO_0_WAVESHAPER|=(ULONG)data<<13;
1588          TRACE_MIKIE2("Poke(AUD0SHFTB,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1589          break;
1590       case (AUD0OUTVAL&0xff):
1591          mAUDIO_OUTPUT[0]=data;
1592          TRACE_MIKIE2("Poke(AUD0OUTVAL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1593          break;
1594       case (AUD0L8SHFT&0xff):
1595          mAUDIO_0_WAVESHAPER&=0x1fff00;
1596          mAUDIO_0_WAVESHAPER|=data;
1597          TRACE_MIKIE2("Poke(AUD0L8SHFT,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1598          break;
1599       case (AUD0TBACK&0xff):
1600          // Counter is disabled when backup is zero for optimisation
1601          // due to the fact that the output frequency will be above audio
1602          // range, we must update the last use position to stop problems
1603          if(!mAUDIO_0_BKUP && data) {
1604             mAUDIO_0_LAST_COUNT=gSystemCycleCount;
1605             gNextTimerEvent=gSystemCycleCount;
1606          }
1607          mAUDIO_0_BKUP=data;
1608          TRACE_MIKIE2("Poke(AUD0TBACK,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1609          break;
1610       case (AUD0CTL&0xff):
1611          mAUDIO_0_ENABLE_RELOAD=data&0x10;
1612          mAUDIO_0_ENABLE_COUNT=data&0x08;
1613          mAUDIO_0_LINKING=data&0x07;
1614          mAUDIO_0_INTEGRATE_ENABLE=data&0x20;
1615          if(data&0x40) mAUDIO_0_TIMER_DONE=0;
1616          mAUDIO_0_WAVESHAPER&=0x1fefff;
1617          mAUDIO_0_WAVESHAPER|=(data&0x80)?0x001000:0x000000;
1618          if(data&0x48) {
1619             mAUDIO_0_LAST_COUNT=gSystemCycleCount;
1620             gNextTimerEvent=gSystemCycleCount;
1621          }
1622          TRACE_MIKIE2("Poke(AUD0CTL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1623          break;
1624       case (AUD0COUNT&0xff):
1625          mAUDIO_0_CURRENT=data;
1626          TRACE_MIKIE2("Poke(AUD0COUNT,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1627          break;
1628       case (AUD0MISC&0xff):
1629          mAUDIO_0_WAVESHAPER&=0x1ff0ff;
1630          mAUDIO_0_WAVESHAPER|=(data&0xf0)<<4;
1631          mAUDIO_0_BORROW_IN=data&0x02;
1632          mAUDIO_0_BORROW_OUT=data&0x01;
1633          mAUDIO_0_LAST_CLOCK=data&0x04;
1634          TRACE_MIKIE2("Poke(AUD0MISC,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1635          break;
1636 
1637       case (AUD1VOL&0xff):
1638          mAUDIO_1_VOLUME=(SBYTE)data;
1639          TRACE_MIKIE2("Poke(AUD1VOL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1640          break;
1641       case (AUD1SHFTFB&0xff):
1642          mAUDIO_1_WAVESHAPER&=0x001fff;
1643          mAUDIO_1_WAVESHAPER|=(ULONG)data<<13;
1644          TRACE_MIKIE2("Poke(AUD1SHFTFB,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1645          break;
1646       case (AUD1OUTVAL&0xff):
1647          mAUDIO_OUTPUT[1]=data;
1648          TRACE_MIKIE2("Poke(AUD1OUTVAL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1649          break;
1650       case (AUD1L8SHFT&0xff):
1651          mAUDIO_1_WAVESHAPER&=0x1fff00;
1652          mAUDIO_1_WAVESHAPER|=data;
1653          TRACE_MIKIE2("Poke(AUD1L8SHFT,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1654          break;
1655       case (AUD1TBACK&0xff):
1656          // Counter is disabled when backup is zero for optimisation
1657          // due to the fact that the output frequency will be above audio
1658          // range, we must update the last use position to stop problems
1659          if(!mAUDIO_1_BKUP && data) {
1660             mAUDIO_1_LAST_COUNT=gSystemCycleCount;
1661             gNextTimerEvent=gSystemCycleCount;
1662          }
1663          mAUDIO_1_BKUP=data;
1664          TRACE_MIKIE2("Poke(AUD1TBACK,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1665          break;
1666       case (AUD1CTL&0xff):
1667          mAUDIO_1_ENABLE_RELOAD=data&0x10;
1668          mAUDIO_1_ENABLE_COUNT=data&0x08;
1669          mAUDIO_1_LINKING=data&0x07;
1670          mAUDIO_1_INTEGRATE_ENABLE=data&0x20;
1671          if(data&0x40) mAUDIO_1_TIMER_DONE=0;
1672          mAUDIO_1_WAVESHAPER&=0x1fefff;
1673          mAUDIO_1_WAVESHAPER|=(data&0x80)?0x001000:0x000000;
1674          if(data&0x48) {
1675             mAUDIO_1_LAST_COUNT=gSystemCycleCount;
1676             gNextTimerEvent=gSystemCycleCount;
1677          }
1678          TRACE_MIKIE2("Poke(AUD1CTL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1679          break;
1680       case (AUD1COUNT&0xff):
1681          mAUDIO_1_CURRENT=data;
1682          TRACE_MIKIE2("Poke(AUD1COUNT,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1683          break;
1684       case (AUD1MISC&0xff):
1685          mAUDIO_1_WAVESHAPER&=0x1ff0ff;
1686          mAUDIO_1_WAVESHAPER|=(data&0xf0)<<4;
1687          mAUDIO_1_BORROW_IN=data&0x02;
1688          mAUDIO_1_BORROW_OUT=data&0x01;
1689          mAUDIO_1_LAST_CLOCK=data&0x04;
1690          TRACE_MIKIE2("Poke(AUD1MISC,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1691          break;
1692 
1693       case (AUD2VOL&0xff):
1694          mAUDIO_2_VOLUME=(SBYTE)data;
1695          TRACE_MIKIE2("Poke(AUD2VOL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1696          break;
1697       case (AUD2SHFTFB&0xff):
1698          mAUDIO_2_WAVESHAPER&=0x001fff;
1699          mAUDIO_2_WAVESHAPER|=(ULONG)data<<13;
1700          TRACE_MIKIE2("Poke(AUD2VSHFTFB,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1701          break;
1702       case (AUD2OUTVAL&0xff):
1703          mAUDIO_OUTPUT[2]=data;
1704          TRACE_MIKIE2("Poke(AUD2OUTVAL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1705          break;
1706       case (AUD2L8SHFT&0xff):
1707          mAUDIO_2_WAVESHAPER&=0x1fff00;
1708          mAUDIO_2_WAVESHAPER|=data;
1709          TRACE_MIKIE2("Poke(AUD2L8SHFT,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1710          break;
1711       case (AUD2TBACK&0xff):
1712          // Counter is disabled when backup is zero for optimisation
1713          // due to the fact that the output frequency will be above audio
1714          // range, we must update the last use position to stop problems
1715          if(!mAUDIO_2_BKUP && data) {
1716             mAUDIO_2_LAST_COUNT=gSystemCycleCount;
1717             gNextTimerEvent=gSystemCycleCount;
1718          }
1719          mAUDIO_2_BKUP=data;
1720          TRACE_MIKIE2("Poke(AUD2TBACK,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1721          break;
1722       case (AUD2CTL&0xff):
1723          mAUDIO_2_ENABLE_RELOAD=data&0x10;
1724          mAUDIO_2_ENABLE_COUNT=data&0x08;
1725          mAUDIO_2_LINKING=data&0x07;
1726          mAUDIO_2_INTEGRATE_ENABLE=data&0x20;
1727          if(data&0x40) mAUDIO_2_TIMER_DONE=0;
1728          mAUDIO_2_WAVESHAPER&=0x1fefff;
1729          mAUDIO_2_WAVESHAPER|=(data&0x80)?0x001000:0x000000;
1730          if(data&0x48) {
1731             mAUDIO_2_LAST_COUNT=gSystemCycleCount;
1732             gNextTimerEvent=gSystemCycleCount;
1733          }
1734          TRACE_MIKIE2("Poke(AUD2CTL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1735          break;
1736       case (AUD2COUNT&0xff):
1737          mAUDIO_2_CURRENT=data;
1738          TRACE_MIKIE2("Poke(AUD2COUNT,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1739          break;
1740       case (AUD2MISC&0xff):
1741          mAUDIO_2_WAVESHAPER&=0x1ff0ff;
1742          mAUDIO_2_WAVESHAPER|=(data&0xf0)<<4;
1743          mAUDIO_2_BORROW_IN=data&0x02;
1744          mAUDIO_2_BORROW_OUT=data&0x01;
1745          mAUDIO_2_LAST_CLOCK=data&0x04;
1746          TRACE_MIKIE2("Poke(AUD2MISC,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1747          break;
1748 
1749       case (AUD3VOL&0xff):
1750          mAUDIO_3_VOLUME=(SBYTE)data;
1751          TRACE_MIKIE2("Poke(AUD3VOL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1752          break;
1753       case (AUD3SHFTFB&0xff):
1754          mAUDIO_3_WAVESHAPER&=0x001fff;
1755          mAUDIO_3_WAVESHAPER|=(ULONG)data<<13;
1756          TRACE_MIKIE2("Poke(AUD3SHFTFB,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1757          break;
1758       case (AUD3OUTVAL&0xff):
1759          mAUDIO_OUTPUT[3]=data;
1760          TRACE_MIKIE2("Poke(AUD3OUTVAL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1761          break;
1762       case (AUD3L8SHFT&0xff):
1763          mAUDIO_3_WAVESHAPER&=0x1fff00;
1764          mAUDIO_3_WAVESHAPER|=data;
1765          TRACE_MIKIE2("Poke(AUD3L8SHFT,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1766          break;
1767       case (AUD3TBACK&0xff):
1768          // Counter is disabled when backup is zero for optimisation
1769          // due to the fact that the output frequency will be above audio
1770          // range, we must update the last use position to stop problems
1771          if(!mAUDIO_3_BKUP && data) {
1772             mAUDIO_3_LAST_COUNT=gSystemCycleCount;
1773             gNextTimerEvent=gSystemCycleCount;
1774          }
1775          mAUDIO_3_BKUP=data;
1776          TRACE_MIKIE2("Poke(AUD3TBACK,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1777          break;
1778       case (AUD3CTL&0xff):
1779          mAUDIO_3_ENABLE_RELOAD=data&0x10;
1780          mAUDIO_3_ENABLE_COUNT=data&0x08;
1781          mAUDIO_3_LINKING=data&0x07;
1782          mAUDIO_3_INTEGRATE_ENABLE=data&0x20;
1783          if(data&0x40) mAUDIO_3_TIMER_DONE=0;
1784          mAUDIO_3_WAVESHAPER&=0x1fefff;
1785          mAUDIO_3_WAVESHAPER|=(data&0x80)?0x001000:0x000000;
1786          if(data&0x48) {
1787             mAUDIO_3_LAST_COUNT=gSystemCycleCount;
1788             gNextTimerEvent=gSystemCycleCount;
1789          }
1790          TRACE_MIKIE2("Poke(AUD3CTL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1791          break;
1792       case (AUD3COUNT&0xff):
1793          mAUDIO_3_CURRENT=data;
1794          TRACE_MIKIE2("Poke(AUD3COUNT,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1795          break;
1796       case (AUD3MISC&0xff):
1797          mAUDIO_3_WAVESHAPER&=0x1ff0ff;
1798          mAUDIO_3_WAVESHAPER|=(data&0xf0)<<4;
1799          mAUDIO_3_BORROW_IN=data&0x02;
1800          mAUDIO_3_BORROW_OUT=data&0x01;
1801          mAUDIO_3_LAST_CLOCK=data&0x04;
1802          TRACE_MIKIE2("Poke(AUD3MISC,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1803          break;
1804 
1805       case (ATTEN_A&0xff):
1806          mAUDIO_ATTEN[0] = data;
1807          TRACE_MIKIE2("Poke(ATTEN_A ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1808          break;
1809       case (ATTEN_B&0xff):
1810          mAUDIO_ATTEN[1] = data;
1811          TRACE_MIKIE2("Poke(ATTEN_B ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1812          break;
1813       case (ATTEN_C&0xff):
1814          mAUDIO_ATTEN[2] = data;
1815          TRACE_MIKIE2("Poke(ATTEN_C ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1816          break;
1817       case (ATTEN_D&0xff):
1818          mAUDIO_ATTEN[3] = data;
1819          TRACE_MIKIE2("Poke(ATTEN_D ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1820          break;
1821       case (MPAN&0xff):
1822          TRACE_MIKIE2("Poke(MPAN ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1823          mPAN = data;
1824          break;
1825 
1826       case (MSTEREO&0xff):
1827          TRACE_MIKIE2("Poke(MSTEREO,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1828          mSTEREO=data;
1829          //			if(!(mSTEREO&0x11) && (data&0x11))
1830          //			{
1831          //				mAUDIO_0_LAST_COUNT=gSystemCycleCount;
1832          //				gNextTimerEvent=gSystemCycleCount;
1833          //			}
1834          //			if(!(mSTEREO&0x22) && (data&0x22))
1835          //			{
1836          //				mAUDIO_1_LAST_COUNT=gSystemCycleCount;
1837          //				gNextTimerEvent=gSystemCycleCount;
1838          //			}
1839          //			if(!(mSTEREO&0x44) && (data&0x44))
1840          //			{
1841          //				mAUDIO_2_LAST_COUNT=gSystemCycleCount;
1842          //				gNextTimerEvent=gSystemCycleCount;
1843          //			}
1844          //			if(!(mSTEREO&0x88) && (data&0x88))
1845          //			{
1846          //				mAUDIO_3_LAST_COUNT=gSystemCycleCount;
1847          //				gNextTimerEvent=gSystemCycleCount;
1848          //			}
1849          break;
1850 
1851       case (INTRST&0xff):
1852          data^=0xff;
1853          mTimerStatusFlags&=data;
1854          gNextTimerEvent=gSystemCycleCount;
1855          // 22/09/06 Fix to championship rally, IRQ not getting cleared with edge triggered system
1856          gSystemIRQ=(mTimerStatusFlags&mTimerInterruptMask)?TRUE:FALSE;
1857          // 22/09/06 Fix to championship rally, IRQ not getting cleared with edge triggered system
1858          TRACE_MIKIE2("Poke(INTRST  ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1859          break;
1860 
1861       case (INTSET&0xff):
1862          TRACE_MIKIE2("Poke(INTSET  ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1863          mTimerStatusFlags|=data;
1864          // 22/09/06 Fix to championship rally, IRQ not getting cleared with edge triggered system
1865          gSystemIRQ=(mTimerStatusFlags&mTimerInterruptMask)?TRUE:FALSE;
1866          // 22/09/06 Fix to championship rally, IRQ not getting cleared with edge triggered system
1867          gNextTimerEvent=gSystemCycleCount;
1868          break;
1869 
1870       case (SYSCTL1&0xff):
1871          TRACE_MIKIE2("Poke(SYSCTL1 ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1872          if(!(data&0x02)) {
1873             char addr[256];
1874             C6502_REGS regs;
1875             mSystem.GetRegs(regs);
1876             sprintf(addr,"Runtime Alert - System Halted\nCMikie::Poke(SYSCTL1) - Lynx power down occured at PC=$%04x.\nResetting system.",regs.PC);
1877             if(gError) gError->Warning(addr);
1878             mSystem.Reset();
1879             gSystemHalt=TRUE;
1880          }
1881          mSystem.CartAddressStrobe((data&0x01)?TRUE:FALSE);
1882          if(mSystem.mEEPROM->Available()) mSystem.mEEPROM->ProcessEepromCounter(mSystem.mCart->GetCounterValue());
1883          break;
1884 
1885       case (MIKEYSREV&0xff):
1886          TRACE_MIKIE2("Poke(MIKEYSREV,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1887          break;
1888 
1889       case (IODIR&0xff):
1890          TRACE_MIKIE2("Poke(IODIR   ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1891          mIODIR=data;
1892          if(mSystem.mEEPROM->Available()) mSystem.mEEPROM->ProcessEepromIO(mIODIR,mIODAT);
1893          break;
1894 
1895       case (IODAT&0xff):
1896          TRACE_MIKIE2("Poke(IODAT   ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1897          mIODAT=data;
1898          mSystem.CartAddressData((mIODAT&0x02)?TRUE:FALSE);
1899          // Enable cart writes to BANK1 on AUDIN if AUDIN is set to output
1900          if(mIODIR&0x10) mSystem.mCart->mWriteEnableBank1=(mIODAT&0x10)?TRUE:FALSE;// there is no reason to use AUDIN as Write Enable or latch. private patch??? TODO
1901          if(mSystem.mEEPROM->Available()) mSystem.mEEPROM->ProcessEepromIO(mIODIR,mIODAT);
1902          break;
1903 
1904       case (SERCTL&0xff):
1905          TRACE_MIKIE2("Poke(SERCTL  ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1906          mUART_TX_IRQ_ENABLE=(data&0x80)?true:false;
1907          mUART_RX_IRQ_ENABLE=(data&0x40)?true:false;
1908          mUART_PARITY_ENABLE=(data&0x10)?true:false;
1909          mUART_SENDBREAK=data&0x02;
1910          mUART_PARITY_EVEN=data&0x01;
1911 
1912          // Reset all errors if required
1913          if(data&0x08) {
1914             mUART_Rx_overun_error=0;
1915             mUART_Rx_framing_error=0;
1916          }
1917 
1918          if(mUART_SENDBREAK) {
1919             // Trigger send break, it will self sustain as long as sendbreak is set
1920             mUART_TX_COUNTDOWN=UART_TX_TIME_PERIOD;
1921             // Loop back what we transmitted
1922             ComLynxTxLoopback(UART_BREAK_CODE);
1923          }
1924          break;
1925 
1926       case (SERDAT&0xff):
1927          TRACE_MIKIE2("Poke(SERDAT ,%04x) at PC=%04x",data,mSystem.mCpu->GetPC());
1928          //
1929          // Fake transmission, set counter to be decremented by Timer 4
1930          //
1931          // ComLynx only has one output pin, hence Rx & Tx are shorted
1932          // therefore any transmitted data will loopback
1933          //
1934          mUART_TX_DATA=data;
1935          // Calculate Parity data
1936          if(mUART_PARITY_ENABLE) {
1937             // Calc parity value
1938             // Leave at zero !!
1939          } else {
1940             // If disabled then the PAREVEN bit is sent
1941             if(mUART_PARITY_EVEN) data|=0x0100;
1942          }
1943          // Set countdown to transmission
1944          mUART_TX_COUNTDOWN=UART_TX_TIME_PERIOD;
1945          // Loop back what we transmitted
1946          ComLynxTxLoopback(mUART_TX_DATA);
1947          break;
1948 
1949       case (SDONEACK&0xff):
1950          TRACE_MIKIE2("Poke(SDONEACK,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1951          break;
1952       case (CPUSLEEP&0xff):
1953          TRACE_MIKIE2("Poke(CPUSLEEP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1954          //
1955          // We must do "cycles_used" cycles of the system with the CPU sleeping
1956          // to compensate for the sprite painting, Mikie update will autowake the
1957          // CPU at the right time.
1958          //
1959          {
1960             TRACE_MIKIE0("*********************************************************");
1961             TRACE_MIKIE0("****               CPU SLEEP STARTED                 ****");
1962             TRACE_MIKIE0("*********************************************************");
1963             SLONG cycles_used=(SLONG)mSystem.PaintSprites();
1964             gCPUWakeupTime=gSystemCycleCount+cycles_used;
1965             SetCPUSleep();
1966             TRACE_MIKIE2("Poke(CPUSLEEP,%02x) wakeup at cycle =%012d",data,gCPUWakeupTime);
1967          }
1968          break;
1969 
1970       case (DISPCTL&0xff):
1971          TRACE_MIKIE2("Poke(DISPCTL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1972          {
1973             TDISPCTL tmp;
1974             tmp.Byte=data;
1975             mDISPCTL_DMAEnable=tmp.Bits.DMAEnable;
1976             mDISPCTL_Flip=tmp.Bits.Flip;
1977             mDISPCTL_FourColour=tmp.Bits.FourColour;
1978             mDISPCTL_Colour=tmp.Bits.Colour;
1979          }
1980          break;
1981       case (PBKUP&0xff):
1982          TRACE_MIKIE2("Poke(PBKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1983          break;
1984 
1985       case (DISPADRL&0xff):
1986          TRACE_MIKIE2("Poke(DISPADRL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1987          mDisplayAddress&=0xff00;
1988          mDisplayAddress+=data;
1989          break;
1990 
1991       case (DISPADRH&0xff):
1992          TRACE_MIKIE2("Poke(DISPADRH,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1993          mDisplayAddress&=0x00ff;
1994          mDisplayAddress+=(data<<8);
1995          break;
1996 
1997       case (Mtest0&0xff):
1998       case (Mtest1&0xff):
1999          // Test registers are unimplemented
2000          // lets hope no programs use them.
2001          TRACE_MIKIE2("Poke(MTEST0/1,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
2002       case (Mtest2&0xff):
2003          // Test registers are unimplemented
2004          // lets hope no programs use them.
2005          if(gError) gError->Warning("CMikie::Poke() - Write to MTEST2");
2006          TRACE_MIKIE2("Poke(MTEST2,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
2007          break;
2008 
2009       case (0xfd97&0xff): {
2010          // This code is to intercept calls to the fake ROM
2011          int mPC = mSystem.mCpu->GetPC();
2012          if(mPC>=0xFE00 && mPC<0xFFF0) {
2013             switch(mPC) {
2014                case 0xFE00+3:
2015                   mSystem.HLE_BIOS_FE00();
2016                   break;
2017                case 0xFE19+3:
2018                   mSystem.HLE_BIOS_FE19();
2019                   break;
2020                case 0xFE4A+3:
2021                   mSystem.HLE_BIOS_FE4A();
2022                   break;
2023                case 0xFF80+3:
2024                   mSystem.HLE_BIOS_FF80();
2025                   break;
2026                default:
2027                   printf("ROM code missing...\n");
2028                   break;
2029                }
2030             }
2031          };
2032          break;
2033       case (GREEN0&0xff):
2034       case (GREEN1&0xff):
2035       case (GREEN2&0xff):
2036       case (GREEN3&0xff):
2037       case (GREEN4&0xff):
2038       case (GREEN5&0xff):
2039       case (GREEN6&0xff):
2040       case (GREEN7&0xff):
2041       case (GREEN8&0xff):
2042       case (GREEN9&0xff):
2043       case (GREENA&0xff):
2044       case (GREENB&0xff):
2045       case (GREENC&0xff):
2046       case (GREEND&0xff):
2047       case (GREENE&0xff):
2048       case (GREENF&0xff):
2049          TRACE_MIKIE2("Poke(GREENPAL0-F,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
2050          mPalette[addr&0x0f].Colours.Green=data&0x0f;
2051          break;
2052 
2053       case (BLUERED0&0xff):
2054       case (BLUERED1&0xff):
2055       case (BLUERED2&0xff):
2056       case (BLUERED3&0xff):
2057       case (BLUERED4&0xff):
2058       case (BLUERED5&0xff):
2059       case (BLUERED6&0xff):
2060       case (BLUERED7&0xff):
2061       case (BLUERED8&0xff):
2062       case (BLUERED9&0xff):
2063       case (BLUEREDA&0xff):
2064       case (BLUEREDB&0xff):
2065       case (BLUEREDC&0xff):
2066       case (BLUEREDD&0xff):
2067       case (BLUEREDE&0xff):
2068       case (BLUEREDF&0xff):
2069          TRACE_MIKIE2("Poke(BLUEREDPAL0-F,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
2070          mPalette[addr&0x0f].Colours.Blue=(data&0xf0)>>4;
2071          mPalette[addr&0x0f].Colours.Red=data&0x0f;
2072          break;
2073 
2074          // Errors on read only register accesses
2075 
2076       case (MAGRDY0&0xff):
2077       case (MAGRDY1&0xff):
2078       case (AUDIN&0xff):
2079       case (MIKEYHREV&0xff):
2080          TRACE_MIKIE3("Poke(%04x,%02x) - Poke to read only register location at PC=%04x",addr,data,mSystem.mCpu->GetPC());
2081          break;
2082 
2083          // Errors on illegal location accesses
2084 
2085       default:
2086          TRACE_MIKIE3("Poke(%04x,%02x) - Poke to illegal location at PC=%04x",addr,data,mSystem.mCpu->GetPC());
2087          break;
2088    }
2089 
2090    if(addr >= AUD0VOL && addr <= MSTEREO)
2091 	  UpdateSound();
2092 }
2093 
2094 
2095 
Peek(ULONG addr)2096 UBYTE CMikie::Peek(ULONG addr)
2097 {
2098    switch(addr & 0xff) {
2099    // Timer control registers
2100       case (TIM0BKUP&0xff):
2101          TRACE_MIKIE2("Peek(TIM0KBUP ,%02x) at PC=%04x",mTIM_0_BKUP,mSystem.mCpu->GetPC());
2102          return (UBYTE)mTIM_0_BKUP;
2103       case (TIM1BKUP&0xff):
2104          TRACE_MIKIE2("Peek(TIM1KBUP ,%02x) at PC=%04x",mTIM_1_BKUP,mSystem.mCpu->GetPC());
2105          return (UBYTE)mTIM_1_BKUP;
2106       case (TIM2BKUP&0xff):
2107          TRACE_MIKIE2("Peek(TIM2KBUP ,%02x) at PC=%04x",mTIM_2_BKUP,mSystem.mCpu->GetPC());
2108          return (UBYTE)mTIM_2_BKUP;
2109       case (TIM3BKUP&0xff):
2110          TRACE_MIKIE2("Peek(TIM3KBUP ,%02x) at PC=%04x",mTIM_3_BKUP,mSystem.mCpu->GetPC());
2111          return (UBYTE)mTIM_3_BKUP;
2112       case (TIM4BKUP&0xff):
2113          TRACE_MIKIE2("Peek(TIM4KBUP ,%02x) at PC=%04x",mTIM_4_BKUP,mSystem.mCpu->GetPC());
2114          return (UBYTE)mTIM_4_BKUP;
2115       case (TIM5BKUP&0xff):
2116          TRACE_MIKIE2("Peek(TIM5KBUP ,%02x) at PC=%04x",mTIM_5_BKUP,mSystem.mCpu->GetPC());
2117          return (UBYTE)mTIM_5_BKUP;
2118       case (TIM6BKUP&0xff):
2119          TRACE_MIKIE2("Peek(TIM6KBUP ,%02x) at PC=%04x",mTIM_6_BKUP,mSystem.mCpu->GetPC());
2120          return (UBYTE)mTIM_6_BKUP;
2121       case (TIM7BKUP&0xff):
2122          TRACE_MIKIE2("Peek(TIM7KBUP ,%02x) at PC=%04x",mTIM_7_BKUP,mSystem.mCpu->GetPC());
2123          return (UBYTE)mTIM_7_BKUP;
2124       case (TIM0CTLA&0xff): {
2125          UBYTE retval=0;
2126          retval|=(mTimerInterruptMask&0x01)?0x80:0x00;
2127          retval|=(mTIM_0_ENABLE_RELOAD)?0x10:0x00;
2128          retval|=(mTIM_0_ENABLE_COUNT)?0x08:0x00;
2129          retval|=mTIM_0_LINKING;
2130          TRACE_MIKIE2("Peek(TIM0CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2131          return retval;
2132       }
2133       case (TIM1CTLA&0xff): {
2134          UBYTE retval=0;
2135          retval|=(mTimerInterruptMask&0x02)?0x80:0x00;
2136          retval|=(mTIM_1_ENABLE_RELOAD)?0x10:0x00;
2137          retval|=(mTIM_1_ENABLE_COUNT)?0x08:0x00;
2138          retval|=mTIM_1_LINKING;
2139          TRACE_MIKIE2("Peek(TIM1CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2140          return retval;
2141       }
2142       case (TIM2CTLA&0xff): {
2143          UBYTE retval=0;
2144          retval|=(mTimerInterruptMask&0x04)?0x80:0x00;
2145          retval|=(mTIM_2_ENABLE_RELOAD)?0x10:0x00;
2146          retval|=(mTIM_2_ENABLE_COUNT)?0x08:0x00;
2147          retval|=mTIM_2_LINKING;
2148          TRACE_MIKIE2("Peek(TIM2CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2149          return retval;
2150       }
2151       case (TIM3CTLA&0xff): {
2152          UBYTE retval=0;
2153          retval|=(mTimerInterruptMask&0x08)?0x80:0x00;
2154          retval|=(mTIM_3_ENABLE_RELOAD)?0x10:0x00;
2155          retval|=(mTIM_3_ENABLE_COUNT)?0x08:0x00;
2156          retval|=mTIM_3_LINKING;
2157          TRACE_MIKIE2("Peek(TIM3CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2158          return retval;
2159       }
2160       case (TIM4CTLA&0xff): {
2161          UBYTE retval=0;
2162          retval|=(mTimerInterruptMask&0x10)?0x80:0x00;
2163          retval|=(mTIM_4_ENABLE_RELOAD)?0x10:0x00;
2164          retval|=(mTIM_4_ENABLE_COUNT)?0x08:0x00;
2165          retval|=mTIM_4_LINKING;
2166          TRACE_MIKIE2("Peek(TIM4CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2167          return retval;
2168       }
2169       case (TIM5CTLA&0xff): {
2170          UBYTE retval=0;
2171          retval|=(mTimerInterruptMask&0x20)?0x80:0x00;
2172          retval|=(mTIM_5_ENABLE_RELOAD)?0x10:0x00;
2173          retval|=(mTIM_5_ENABLE_COUNT)?0x08:0x00;
2174          retval|=mTIM_5_LINKING;
2175          TRACE_MIKIE2("Peek(TIM5CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2176          return retval;
2177       }
2178       case (TIM6CTLA&0xff): {
2179          UBYTE retval=0;
2180          retval|=(mTimerInterruptMask&0x40)?0x80:0x00;
2181          retval|=(mTIM_6_ENABLE_RELOAD)?0x10:0x00;
2182          retval|=(mTIM_6_ENABLE_COUNT)?0x08:0x00;
2183          retval|=mTIM_6_LINKING;
2184          TRACE_MIKIE2("Peek(TIM6CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2185          return retval;
2186       }
2187       case (TIM7CTLA&0xff): {
2188          UBYTE retval=0;
2189          retval|=(mTimerInterruptMask&0x80)?0x80:0x00;
2190          retval|=(mTIM_7_ENABLE_RELOAD)?0x10:0x00;
2191          retval|=(mTIM_7_ENABLE_COUNT)?0x08:0x00;
2192          retval|=mTIM_7_LINKING;
2193          TRACE_MIKIE2("Peek(TIM7CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2194          return retval;
2195       }
2196       case (TIM0CNT&0xff):
2197          Update();
2198          TRACE_MIKIE2("Peek(TIM0CNT  ,%02x) at PC=%04x",mTIM_0_CURRENT,mSystem.mCpu->GetPC());
2199          return (UBYTE)mTIM_0_CURRENT;
2200       case (TIM1CNT&0xff):
2201          Update();
2202          TRACE_MIKIE2("Peek(TIM1CNT  ,%02x) at PC=%04x",mTIM_1_CURRENT,mSystem.mCpu->GetPC());
2203          return (UBYTE)mTIM_1_CURRENT;
2204       case (TIM2CNT&0xff):
2205          Update();
2206          TRACE_MIKIE2("Peek(TIM2CNT  ,%02x) at PC=%04x",mTIM_2_CURRENT,mSystem.mCpu->GetPC());
2207          return (UBYTE)mTIM_2_CURRENT;
2208       case (TIM3CNT&0xff):
2209          Update();
2210          TRACE_MIKIE2("Peek(TIM3CNT  ,%02x) at PC=%04x",mTIM_3_CURRENT,mSystem.mCpu->GetPC());
2211          return (UBYTE)mTIM_3_CURRENT;
2212       case (TIM4CNT&0xff):
2213          Update();
2214          TRACE_MIKIE2("Peek(TIM4CNT  ,%02x) at PC=%04x",mTIM_4_CURRENT,mSystem.mCpu->GetPC());
2215          return (UBYTE)mTIM_4_CURRENT;
2216       case (TIM5CNT&0xff):
2217          Update();
2218          TRACE_MIKIE2("Peek(TIM5CNT  ,%02x) at PC=%04x",mTIM_5_CURRENT,mSystem.mCpu->GetPC());
2219          return (UBYTE)mTIM_5_CURRENT;
2220       case (TIM6CNT&0xff):
2221          Update();
2222          TRACE_MIKIE2("Peek(TIM6CNT  ,%02x) at PC=%04x",mTIM_6_CURRENT,mSystem.mCpu->GetPC());
2223          return (UBYTE)mTIM_6_CURRENT;
2224       case (TIM7CNT&0xff):
2225          Update();
2226          TRACE_MIKIE2("Peek(TIM7CNT  ,%02x) at PC=%04x",mTIM_7_CURRENT,mSystem.mCpu->GetPC());
2227          return (UBYTE)mTIM_7_CURRENT;
2228 
2229       case (TIM0CTLB&0xff): {
2230          UBYTE retval=0;
2231          retval|=(mTIM_0_TIMER_DONE)?0x08:0x00;
2232          retval|=(mTIM_0_LAST_CLOCK)?0x04:0x00;
2233          retval|=(mTIM_0_BORROW_IN)?0x02:0x00;
2234          retval|=(mTIM_0_BORROW_OUT)?0x01:0x00;
2235          TRACE_MIKIE2("Peek(TIM0CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2236          return retval;
2237       }
2238       case (TIM1CTLB&0xff): {
2239          UBYTE retval=0;
2240          retval|=(mTIM_1_TIMER_DONE)?0x08:0x00;
2241          retval|=(mTIM_1_LAST_CLOCK)?0x04:0x00;
2242          retval|=(mTIM_1_BORROW_IN)?0x02:0x00;
2243          retval|=(mTIM_1_BORROW_OUT)?0x01:0x00;
2244          TRACE_MIKIE2("Peek(TIM1CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2245          return retval;
2246       }
2247       case (TIM2CTLB&0xff): {
2248          UBYTE retval=0;
2249          retval|=(mTIM_2_TIMER_DONE)?0x08:0x00;
2250          retval|=(mTIM_2_LAST_CLOCK)?0x04:0x00;
2251          retval|=(mTIM_2_BORROW_IN)?0x02:0x00;
2252          retval|=(mTIM_2_BORROW_OUT)?0x01:0x00;
2253          TRACE_MIKIE2("Peek(TIM2CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2254          return retval;
2255       }
2256       case (TIM3CTLB&0xff): {
2257          UBYTE retval=0;
2258          retval|=(mTIM_3_TIMER_DONE)?0x08:0x00;
2259          retval|=(mTIM_3_LAST_CLOCK)?0x04:0x00;
2260          retval|=(mTIM_3_BORROW_IN)?0x02:0x00;
2261          retval|=(mTIM_3_BORROW_OUT)?0x01:0x00;
2262          TRACE_MIKIE2("Peek(TIM3CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2263          return retval;
2264       }
2265       case (TIM4CTLB&0xff): {
2266          UBYTE retval=0;
2267          retval|=(mTIM_4_TIMER_DONE)?0x08:0x00;
2268          retval|=(mTIM_4_LAST_CLOCK)?0x04:0x00;
2269          retval|=(mTIM_4_BORROW_IN)?0x02:0x00;
2270          retval|=(mTIM_4_BORROW_OUT)?0x01:0x00;
2271          TRACE_MIKIE2("Peek(TIM4CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2272          return retval;
2273       }
2274       case (TIM5CTLB&0xff): {
2275          UBYTE retval=0;
2276          retval|=(mTIM_5_TIMER_DONE)?0x08:0x00;
2277          retval|=(mTIM_5_LAST_CLOCK)?0x04:0x00;
2278          retval|=(mTIM_5_BORROW_IN)?0x02:0x00;
2279          retval|=(mTIM_5_BORROW_OUT)?0x01:0x00;
2280          TRACE_MIKIE2("Peek(TIM5CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2281          return retval;
2282       }
2283       case (TIM6CTLB&0xff): {
2284          UBYTE retval=0;
2285          retval|=(mTIM_6_TIMER_DONE)?0x08:0x00;
2286          retval|=(mTIM_6_LAST_CLOCK)?0x04:0x00;
2287          retval|=(mTIM_6_BORROW_IN)?0x02:0x00;
2288          retval|=(mTIM_6_BORROW_OUT)?0x01:0x00;
2289          TRACE_MIKIE2("Peek(TIM6CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2290          return retval;
2291       }
2292       case (TIM7CTLB&0xff): {
2293          UBYTE retval=0;
2294          retval|=(mTIM_7_TIMER_DONE)?0x08:0x00;
2295          retval|=(mTIM_7_LAST_CLOCK)?0x04:0x00;
2296          retval|=(mTIM_7_BORROW_IN)?0x02:0x00;
2297          retval|=(mTIM_7_BORROW_OUT)?0x01:0x00;
2298          TRACE_MIKIE2("Peek(TIM7CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2299          return retval;
2300       }
2301 
2302       // Audio control registers
2303 
2304       case (AUD0VOL&0xff):
2305          TRACE_MIKIE2("Peek(AUD0VOL,%02x) at PC=%04x",(UBYTE)mAUDIO_0_VOLUME,mSystem.mCpu->GetPC());
2306          return (UBYTE)mAUDIO_0_VOLUME;
2307       case (AUD0SHFTFB&0xff):
2308          TRACE_MIKIE2("Peek(AUD0SHFTFB,%02x) at PC=%04x",(UBYTE)(mAUDIO_0_WAVESHAPER>>13)&0xff,mSystem.mCpu->GetPC());
2309          return (UBYTE)((mAUDIO_0_WAVESHAPER>>13)&0xff);
2310       case (AUD0OUTVAL&0xff):
2311          TRACE_MIKIE2("Peek(AUD0OUTVAL,%02x) at PC=%04x",(UBYTE)mAUDIO_OUTPUT[0],mSystem.mCpu->GetPC());
2312          return (UBYTE)mAUDIO_OUTPUT[0];
2313       case (AUD0L8SHFT&0xff):
2314          TRACE_MIKIE2("Peek(AUD0L8SHFT,%02x) at PC=%04x",(UBYTE)(mAUDIO_0_WAVESHAPER&0xff),mSystem.mCpu->GetPC());
2315          return (UBYTE)(mAUDIO_0_WAVESHAPER&0xff);
2316       case (AUD0TBACK&0xff):
2317          TRACE_MIKIE2("Peek(AUD0TBACK,%02x) at PC=%04x",(UBYTE)mAUDIO_0_BKUP,mSystem.mCpu->GetPC());
2318          return (UBYTE)mAUDIO_0_BKUP;
2319       case (AUD0CTL&0xff): {
2320          UBYTE retval=0;
2321          retval|=(mAUDIO_0_INTEGRATE_ENABLE)?0x20:0x00;
2322          retval|=(mAUDIO_0_ENABLE_RELOAD)?0x10:0x00;
2323          retval|=(mAUDIO_0_ENABLE_COUNT)?0x08:0x00;
2324          retval|=(mAUDIO_0_WAVESHAPER&0x001000)?0x80:0x00;
2325          retval|=mAUDIO_0_LINKING;
2326          TRACE_MIKIE2("Peek(AUD0CTL,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2327          return retval;
2328       }
2329       case (AUD0COUNT&0xff):
2330          TRACE_MIKIE2("Peek(AUD0COUNT,%02x) at PC=%04x",(UBYTE)mAUDIO_0_CURRENT,mSystem.mCpu->GetPC());
2331          return (UBYTE)mAUDIO_0_CURRENT;
2332       case (AUD0MISC&0xff): {
2333          UBYTE retval=0;
2334          retval|=(mAUDIO_0_BORROW_OUT)?0x01:0x00;
2335          retval|=(mAUDIO_0_BORROW_IN)?0x02:0x00;
2336          retval|=(mAUDIO_0_LAST_CLOCK)?0x08:0x00;
2337          retval|=(mAUDIO_0_WAVESHAPER>>4)&0xf0;
2338          TRACE_MIKIE2("Peek(AUD0MISC,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2339          return retval;
2340       }
2341 
2342       case (AUD1VOL&0xff):
2343          TRACE_MIKIE2("Peek(AUD1VOL,%02x) at PC=%04x",(UBYTE)mAUDIO_1_VOLUME,mSystem.mCpu->GetPC());
2344          return (UBYTE)mAUDIO_1_VOLUME;
2345       case (AUD1SHFTFB&0xff):
2346          TRACE_MIKIE2("Peek(AUD1SHFTFB,%02x) at PC=%04x",(UBYTE)(mAUDIO_1_WAVESHAPER>>13)&0xff,mSystem.mCpu->GetPC());
2347          return (UBYTE)((mAUDIO_1_WAVESHAPER>>13)&0xff);
2348       case (AUD1OUTVAL&0xff):
2349          TRACE_MIKIE2("Peek(AUD1OUTVAL,%02x) at PC=%04x",(UBYTE)mAUDIO_OUTPUT[1],mSystem.mCpu->GetPC());
2350          return (UBYTE)mAUDIO_OUTPUT[1];
2351       case (AUD1L8SHFT&0xff):
2352          TRACE_MIKIE2("Peek(AUD1L8SHFT,%02x) at PC=%04x",(UBYTE)(mAUDIO_1_WAVESHAPER&0xff),mSystem.mCpu->GetPC());
2353          return (UBYTE)(mAUDIO_1_WAVESHAPER&0xff);
2354       case (AUD1TBACK&0xff):
2355          TRACE_MIKIE2("Peek(AUD1TBACK,%02x) at PC=%04x",(UBYTE)mAUDIO_1_BKUP,mSystem.mCpu->GetPC());
2356          return (UBYTE)mAUDIO_1_BKUP;
2357       case (AUD1CTL&0xff): {
2358          UBYTE retval=0;
2359          retval|=(mAUDIO_1_INTEGRATE_ENABLE)?0x20:0x00;
2360          retval|=(mAUDIO_1_ENABLE_RELOAD)?0x10:0x00;
2361          retval|=(mAUDIO_1_ENABLE_COUNT)?0x08:0x00;
2362          retval|=(mAUDIO_1_WAVESHAPER&0x001000)?0x80:0x00;
2363          retval|=mAUDIO_1_LINKING;
2364          TRACE_MIKIE2("Peek(AUD1CTL,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2365          return retval;
2366       }
2367       case (AUD1COUNT&0xff):
2368          TRACE_MIKIE2("Peek(AUD1COUNT,%02x) at PC=%04x",(UBYTE)mAUDIO_1_CURRENT,mSystem.mCpu->GetPC());
2369          return (UBYTE)mAUDIO_1_CURRENT;
2370       case (AUD1MISC&0xff): {
2371          UBYTE retval=0;
2372          retval|=(mAUDIO_1_BORROW_OUT)?0x01:0x00;
2373          retval|=(mAUDIO_1_BORROW_IN)?0x02:0x00;
2374          retval|=(mAUDIO_1_LAST_CLOCK)?0x08:0x00;
2375          retval|=(mAUDIO_1_WAVESHAPER>>4)&0xf0;
2376          TRACE_MIKIE2("Peek(AUD1MISC,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2377          return retval;
2378       }
2379 
2380       case (AUD2VOL&0xff):
2381          TRACE_MIKIE2("Peek(AUD2VOL,%02x) at PC=%04x",(UBYTE)mAUDIO_2_VOLUME,mSystem.mCpu->GetPC());
2382          return (UBYTE)mAUDIO_2_VOLUME;
2383       case (AUD2SHFTFB&0xff):
2384          TRACE_MIKIE2("Peek(AUD2SHFTFB,%02x) at PC=%04x",(UBYTE)(mAUDIO_2_WAVESHAPER>>13)&0xff,mSystem.mCpu->GetPC());
2385          return (UBYTE)((mAUDIO_2_WAVESHAPER>>13)&0xff);
2386       case (AUD2OUTVAL&0xff):
2387          TRACE_MIKIE2("Peek(AUD2OUTVAL,%02x) at PC=%04x",(UBYTE)mAUDIO_OUTPUT[2],mSystem.mCpu->GetPC());
2388          return (UBYTE)mAUDIO_OUTPUT[2];
2389       case (AUD2L8SHFT&0xff):
2390          TRACE_MIKIE2("Peek(AUD2L8SHFT,%02x) at PC=%04x",(UBYTE)(mAUDIO_2_WAVESHAPER&0xff),mSystem.mCpu->GetPC());
2391          return (UBYTE)(mAUDIO_2_WAVESHAPER&0xff);
2392       case (AUD2TBACK&0xff):
2393          TRACE_MIKIE2("Peek(AUD2TBACK,%02x) at PC=%04x",(UBYTE)mAUDIO_2_BKUP,mSystem.mCpu->GetPC());
2394          return (UBYTE)mAUDIO_2_BKUP;
2395       case (AUD2CTL&0xff): {
2396          UBYTE retval=0;
2397          retval|=(mAUDIO_2_INTEGRATE_ENABLE)?0x20:0x00;
2398          retval|=(mAUDIO_2_ENABLE_RELOAD)?0x10:0x00;
2399          retval|=(mAUDIO_2_ENABLE_COUNT)?0x08:0x00;
2400          retval|=(mAUDIO_2_WAVESHAPER&0x001000)?0x80:0x00;
2401          retval|=mAUDIO_2_LINKING;
2402          TRACE_MIKIE2("Peek(AUD2CTL,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2403          return retval;
2404       }
2405       case (AUD2COUNT&0xff):
2406          TRACE_MIKIE2("Peek(AUD2COUNT,%02x) at PC=%04x",(UBYTE)mAUDIO_2_CURRENT,mSystem.mCpu->GetPC());
2407          return (UBYTE)mAUDIO_2_CURRENT;
2408       case (AUD2MISC&0xff): {
2409          UBYTE retval=0;
2410          retval|=(mAUDIO_2_BORROW_OUT)?0x01:0x00;
2411          retval|=(mAUDIO_2_BORROW_IN)?0x02:0x00;
2412          retval|=(mAUDIO_2_LAST_CLOCK)?0x08:0x00;
2413          retval|=(mAUDIO_2_WAVESHAPER>>4)&0xf0;
2414          TRACE_MIKIE2("Peek(AUD2MISC,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2415          return retval;
2416       }
2417 
2418       case (AUD3VOL&0xff):
2419          TRACE_MIKIE2("Peek(AUD3VOL,%02x) at PC=%04x",(UBYTE)mAUDIO_3_VOLUME,mSystem.mCpu->GetPC());
2420          return (UBYTE)mAUDIO_3_VOLUME;
2421       case (AUD3SHFTFB&0xff):
2422          TRACE_MIKIE2("Peek(AUD3SHFTFB,%02x) at PC=%04x",(UBYTE)(mAUDIO_3_WAVESHAPER>>13)&0xff,mSystem.mCpu->GetPC());
2423          return (UBYTE)((mAUDIO_3_WAVESHAPER>>13)&0xff);
2424       case (AUD3OUTVAL&0xff):
2425          TRACE_MIKIE2("Peek(AUD3OUTVAL,%02x) at PC=%04x",(UBYTE)mAUDIO_OUTPUT[3],mSystem.mCpu->GetPC());
2426          return (UBYTE)mAUDIO_OUTPUT[3];
2427       case (AUD3L8SHFT&0xff):
2428          TRACE_MIKIE2("Peek(AUD3L8SHFT,%02x) at PC=%04x",(UBYTE)(mAUDIO_3_WAVESHAPER&0xff),mSystem.mCpu->GetPC());
2429          return (UBYTE)(mAUDIO_3_WAVESHAPER&0xff);
2430       case (AUD3TBACK&0xff):
2431          TRACE_MIKIE2("Peek(AUD3TBACK,%02x) at PC=%04x",(UBYTE)mAUDIO_3_BKUP,mSystem.mCpu->GetPC());
2432          return (UBYTE)mAUDIO_3_BKUP;
2433       case (AUD3CTL&0xff): {
2434          UBYTE retval=0;
2435          retval|=(mAUDIO_3_INTEGRATE_ENABLE)?0x20:0x00;
2436          retval|=(mAUDIO_3_ENABLE_RELOAD)?0x10:0x00;
2437          retval|=(mAUDIO_3_ENABLE_COUNT)?0x08:0x00;
2438          retval|=(mAUDIO_3_WAVESHAPER&0x001000)?0x80:0x00;
2439          retval|=mAUDIO_3_LINKING;
2440          TRACE_MIKIE2("Peek(AUD3CTL,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2441          return retval;
2442       }
2443       case (AUD3COUNT&0xff):
2444          TRACE_MIKIE2("Peek(AUD3COUNT,%02x) at PC=%04x",(UBYTE)mAUDIO_3_CURRENT,mSystem.mCpu->GetPC());
2445          return (UBYTE)mAUDIO_3_CURRENT;
2446       case (AUD3MISC&0xff): {
2447          UBYTE retval=0;
2448          retval|=(mAUDIO_3_BORROW_OUT)?0x01:0x00;
2449          retval|=(mAUDIO_3_BORROW_IN)?0x02:0x00;
2450          retval|=(mAUDIO_3_LAST_CLOCK)?0x08:0x00;
2451          retval|=(mAUDIO_3_WAVESHAPER>>4)&0xf0;
2452          TRACE_MIKIE2("Peek(AUD3MISC,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2453          return retval;
2454       }
2455 
2456       case (ATTEN_A&0xff):
2457          TRACE_MIKIE1("Peek(ATTEN_A) at PC=%04x",mSystem.mCpu->GetPC());
2458          return (UBYTE) mAUDIO_ATTEN[0];
2459       case (ATTEN_B&0xff):
2460          TRACE_MIKIE1("Peek(ATTEN_B) at PC=%04x",mSystem.mCpu->GetPC());
2461          return (UBYTE) mAUDIO_ATTEN[1];
2462       case (ATTEN_C&0xff):
2463          TRACE_MIKIE1("Peek(ATTEN_C) at PC=%04x",mSystem.mCpu->GetPC());
2464          return (UBYTE) mAUDIO_ATTEN[2];
2465       case (ATTEN_D&0xff):
2466          TRACE_MIKIE1("Peek(ATTEN_D) at PC=%04x",mSystem.mCpu->GetPC());
2467          return (UBYTE) mAUDIO_ATTEN[3];
2468       case (MPAN&0xff):
2469          TRACE_MIKIE1("Peek(MPAN) at PC=%04x",mSystem.mCpu->GetPC());
2470          return (UBYTE) mPAN;
2471 
2472       case (MSTEREO&0xff):
2473          TRACE_MIKIE2("Peek(MSTEREO,%02x) at PC=%04x",(UBYTE)mSTEREO^0xff,mSystem.mCpu->GetPC());
2474          return (UBYTE) mSTEREO;
2475 
2476          // Miscellaneous registers
2477 
2478       case (SERCTL&0xff): {
2479          ULONG retval=0;
2480          retval|=(mUART_TX_COUNTDOWN&UART_TX_INACTIVE)?0xA0:0x00;	// Indicate TxDone & TxAllDone
2481          retval|=(mUART_RX_READY)?0x40:0x00;							// Indicate Rx data ready
2482          retval|=(mUART_Rx_overun_error)?0x08:0x0;					// Framing error
2483          retval|=(mUART_Rx_framing_error)?0x04:0x00;					// Rx overrun
2484          retval|=(mUART_RX_DATA&UART_BREAK_CODE)?0x02:0x00;			// Indicate break received
2485          retval|=(mUART_RX_DATA&0x0100)?0x01:0x00;					// Add parity bit
2486          TRACE_MIKIE2("Peek(SERCTL  ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2487          return (UBYTE)retval;
2488       }
2489 
2490       case (SERDAT&0xff):
2491          mUART_RX_READY=0;
2492          TRACE_MIKIE2("Peek(SERDAT  ,%02x) at PC=%04x",(UBYTE)mUART_RX_DATA,mSystem.mCpu->GetPC());
2493          return (UBYTE)(mUART_RX_DATA&0xff);
2494 
2495       case (IODAT&0xff): {
2496          ULONG retval=0;
2497          // IODIR  = output bit : input high (eeprom write done)
2498          if(mSystem.mEEPROM->Available()) {
2499             mSystem.mEEPROM->ProcessEepromBusy();
2500             retval|=(mIODIR&0x10)?mIODAT&0x10:(mSystem.mEEPROM->OutputBit()?0x10:0x00);
2501          } else {
2502             retval|=mIODAT&0x10;
2503          }
2504          retval|=(mIODIR&0x08)?(((mIODAT&0x08)&&mIODAT_REST_SIGNAL)?0x00:0x08):0x00;									// REST   = output bit : input low
2505          retval|=(mIODIR&0x04)?mIODAT&0x04:((mUART_CABLE_PRESENT)?0x04:0x00);	// NOEXP  = output bit : input low
2506          retval|=(mIODIR&0x02)?mIODAT&0x02:0x00;									// CARTAD = output bit : input low
2507          retval|=(mIODIR&0x01)?mIODAT&0x01:0x01;									// EXTPW  = output bit : input high (Power connected)
2508          TRACE_MIKIE2("Peek(IODAT   ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
2509          return (UBYTE)retval;
2510       }
2511 
2512       case (INTRST&0xff):
2513       case (INTSET&0xff):
2514          TRACE_MIKIE2("Peek(INTSET  ,%02x) at PC=%04x",mTimerStatusFlags,mSystem.mCpu->GetPC());
2515          return (UBYTE)mTimerStatusFlags;
2516       case (MAGRDY0&0xff):
2517       case (MAGRDY1&0xff):
2518          TRACE_MIKIE2("Peek(MAGRDY0/1,%02x) at PC=%04x",0x00,mSystem.mCpu->GetPC());
2519          return 0x00;
2520       case (AUDIN&0xff):
2521          //			TRACE_MIKIE2("Peek(AUDIN,%02x) at PC=%04x",mAudioInputComparator?0x80:0x00,mSystem.mCpu->GetPC());
2522          //			if(mAudioInputComparator) return 0x80; else return 0x00;
2523          TRACE_MIKIE2("Peek(AUDIN,%02x) at PC=%04x",0x80,mSystem.mCpu->GetPC());
2524          return 0x80;
2525       case (MIKEYHREV&0xff):
2526          TRACE_MIKIE2("Peek(MIKEYHREV,%02x) at PC=%04x",0x01,mSystem.mCpu->GetPC());
2527          return 0x01;
2528 
2529       // Pallette registers
2530 
2531       case (GREEN0&0xff):
2532       case (GREEN1&0xff):
2533       case (GREEN2&0xff):
2534       case (GREEN3&0xff):
2535       case (GREEN4&0xff):
2536       case (GREEN5&0xff):
2537       case (GREEN6&0xff):
2538       case (GREEN7&0xff):
2539       case (GREEN8&0xff):
2540       case (GREEN9&0xff):
2541       case (GREENA&0xff):
2542       case (GREENB&0xff):
2543       case (GREENC&0xff):
2544       case (GREEND&0xff):
2545       case (GREENE&0xff):
2546       case (GREENF&0xff):
2547          TRACE_MIKIE2("Peek(GREENPAL0-F,%02x) at PC=%04x",mPalette[addr&0x0f].Colours.Green,mSystem.mCpu->GetPC());
2548          return mPalette[addr&0x0f].Colours.Green;
2549       case (BLUERED0&0xff):
2550       case (BLUERED1&0xff):
2551       case (BLUERED2&0xff):
2552       case (BLUERED3&0xff):
2553       case (BLUERED4&0xff):
2554       case (BLUERED5&0xff):
2555       case (BLUERED6&0xff):
2556       case (BLUERED7&0xff):
2557       case (BLUERED8&0xff):
2558       case (BLUERED9&0xff):
2559       case (BLUEREDA&0xff):
2560       case (BLUEREDB&0xff):
2561       case (BLUEREDC&0xff):
2562       case (BLUEREDD&0xff):
2563       case (BLUEREDE&0xff):
2564       case (BLUEREDF&0xff):
2565          TRACE_MIKIE2("Peek(BLUEREDPAL0-F,%02x) at PC=%04x",(mPalette[addr&0x0f].Colours.Red | (mPalette[addr&0x0f].Colours.Blue<<4)),mSystem.mCpu->GetPC());
2566          return (mPalette[addr&0x0f].Colours.Red | (mPalette[addr&0x0f].Colours.Blue<<4));
2567          // Errors on write only register accesses
2568 
2569       // For easier debugging
2570 
2571       case (DISPADRL&0xff):
2572          TRACE_MIKIE2("Peek(DISPADRL,%02x) at PC=%04x",(UBYTE)(mDisplayAddress&0xff),mSystem.mCpu->GetPC());
2573          return (UBYTE)(mDisplayAddress&0xff);
2574       case (DISPADRH&0xff):
2575          TRACE_MIKIE2("Peek(DISPADRH,%02x) at PC=%04x",(UBYTE)(mDisplayAddress>>8)&0xff,mSystem.mCpu->GetPC());
2576          return (UBYTE)(mDisplayAddress>>8)&0xff;
2577 
2578       case (DISPCTL&0xff):
2579       case (SYSCTL1&0xff):
2580       case (MIKEYSREV&0xff):
2581       case (IODIR&0xff):
2582       case (SDONEACK&0xff):
2583       case (CPUSLEEP&0xff):
2584       case (PBKUP&0xff):
2585       case (Mtest0&0xff):
2586       case (Mtest1&0xff):
2587       case (Mtest2&0xff):
2588          TRACE_MIKIE2("Peek(%04x) - Peek from write only register location at PC=$%04x",addr,mSystem.mCpu->GetPC());
2589          break;
2590 
2591       // Register to let programs know handy is running
2592 
2593       case (0xfd97&0xff):
2594          TRACE_MIKIE2("Peek(%04x) - **** HANDY DETECT ATTEMPTED **** at PC=$%04x",addr,mSystem.mCpu->GetPC());
2595          //			gError->Warning("EMULATOR DETECT REGISTER HAS BEEN READ");
2596          break;
2597          //return 0x42;
2598          // Errors on illegal location accesses
2599 
2600       default:
2601          TRACE_MIKIE2("Peek(%04x) - Peek from illegal location at PC=$%04x",addr,mSystem.mCpu->GetPC());
2602          break;
2603    }
2604    return 0xff;
2605 }
2606 
Update(void)2607 inline void CMikie::Update(void)
2608 {
2609    SLONG divide;
2610    SLONG decval;
2611    ULONG tmp;
2612    ULONG mikie_work_done=0;
2613 
2614    //
2615    // To stop problems with cycle count wrap we will check and then correct the
2616    // cycle counter.
2617    //
2618 
2619    //			TRACE_MIKIE0("Update()");
2620 
2621    if(gSystemCycleCount>0xf0000000) {
2622       gSystemCycleCount-=0x80000000;
2623       gThrottleNextCycleCheckpoint-=0x80000000;
2624       gAudioLastUpdateCycle-=0x80000000;
2625       mTIM_0_LAST_COUNT-=0x80000000;
2626       mTIM_1_LAST_COUNT-=0x80000000;
2627       mTIM_2_LAST_COUNT-=0x80000000;
2628       mTIM_3_LAST_COUNT-=0x80000000;
2629       mTIM_4_LAST_COUNT-=0x80000000;
2630       mTIM_5_LAST_COUNT-=0x80000000;
2631       mTIM_6_LAST_COUNT-=0x80000000;
2632       mTIM_7_LAST_COUNT-=0x80000000;
2633       mAUDIO_0_LAST_COUNT-=0x80000000;
2634       mAUDIO_1_LAST_COUNT-=0x80000000;
2635       mAUDIO_2_LAST_COUNT-=0x80000000;
2636       mAUDIO_3_LAST_COUNT-=0x80000000;
2637       // Only correct if sleep is active
2638       if(gCPUWakeupTime) {
2639          gCPUWakeupTime-=0x80000000;
2640          gIRQEntryCycle-=0x80000000;
2641       }
2642    }
2643 
2644    gNextTimerEvent=0xffffffff;
2645 
2646    //
2647    // Check if the CPU needs to be woken up from sleep mode
2648    //
2649    if(gCPUWakeupTime) {
2650       if(gSystemCycleCount>=gCPUWakeupTime) {
2651          TRACE_MIKIE0("*********************************************************");
2652          TRACE_MIKIE0("****              CPU SLEEP COMPLETED                ****");
2653          TRACE_MIKIE0("*********************************************************");
2654          ClearCPUSleep();
2655          gCPUWakeupTime=0;
2656       } else {
2657          if(gCPUWakeupTime>gSystemCycleCount) gNextTimerEvent=gCPUWakeupTime;
2658       }
2659    }
2660 
2661    //	Timer updates, rolled out flat in group order
2662    //
2663    //	Group A:
2664    //	Timer 0 -> Timer 2 -> Timer 4.
2665    //
2666    //	Group B:
2667    //	Timer 1 -> Timer 3 -> Timer 5 -> Timer 7 -> Audio 0 -> Audio 1-> Audio 2 -> Audio 3 -> Timer 1.
2668    //
2669 
2670    //
2671    // Within each timer code block we will predict the cycle count number of
2672    // the next timer event
2673    //
2674    // We don't need to count linked timers as the timer they are linked
2675    // from will always generate earlier events.
2676    //
2677    // As Timer 4 (UART) will generate many events we will ignore it
2678    //
2679    // We set the next event to the end of time at first and let the timers
2680    // overload it. Any writes to timer controls will force next event to
2681    // be immediate and hence a new preidction will be done. The prediction
2682    // causes overflow as opposed to zero i.e. current+1
2683    // (In reality T0 line counter should always be running.)
2684    //
2685 
2686 
2687    //
2688    // Timer 0 of Group A
2689    //
2690 
2691    //
2692    // Optimisation, assume T0 (Line timer) is never in one-shot,
2693    // never placed in link mode
2694    //
2695 
2696    // KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD ||  ..)
2697    //			if(mTIM_0_ENABLE_COUNT && (mTIM_0_ENABLE_RELOAD || !mTIM_0_TIMER_DONE))
2698    if(mTIM_0_ENABLE_COUNT) {
2699       // Timer 0 has no linking
2700       //				if(mTIM_0_LINKING!=0x07)
2701       {
2702          // Ordinary clocked mode as opposed to linked mode
2703          // 16MHz clock downto 1us == cyclecount >> 4
2704          divide=(4+mTIM_0_LINKING);
2705          decval=(gSystemCycleCount-mTIM_0_LAST_COUNT)>>divide;
2706 
2707          if(decval) {
2708             mTIM_0_LAST_COUNT+=decval<<divide;
2709             mTIM_0_CURRENT-=decval;
2710 
2711             if(mTIM_0_CURRENT&0x80000000) {
2712                // Set carry out
2713                mTIM_0_BORROW_OUT=TRUE;
2714 
2715                //							// Reload if neccessary
2716                //							if(mTIM_0_ENABLE_RELOAD)
2717                //							{
2718                mTIM_0_CURRENT+=mTIM_0_BKUP+1;
2719                //							}
2720                //							else
2721                //							{
2722                //								mTIM_0_CURRENT=0;
2723                //							}
2724 
2725                mTIM_0_TIMER_DONE=TRUE;
2726 
2727                // Interupt flag setting code moved into DisplayRenderLine()
2728 
2729                // Line timer has expired, render a line, we cannot incrememnt
2730                // the global counter at this point as it will screw the other timers
2731                // so we save under work done and inc at the end.
2732                mikie_work_done+=DisplayRenderLine();
2733 
2734             } else {
2735                mTIM_0_BORROW_OUT=FALSE;
2736             }
2737             // Set carry in as we did a count
2738             mTIM_0_BORROW_IN=TRUE;
2739          } else {
2740             // Clear carry in as we didn't count
2741             mTIM_0_BORROW_IN=FALSE;
2742             // Clear carry out
2743             mTIM_0_BORROW_OUT=FALSE;
2744          }
2745       }
2746 
2747       // Prediction for next timer event cycle number
2748 
2749       //				if(mTIM_0_LINKING!=7)
2750       {
2751          // Sometimes timeupdates can be >2x rollover in which case
2752          // then CURRENT may still be negative and we can use it to
2753          // calc the next timer value, we just want another update ASAP
2754          tmp=(mTIM_0_CURRENT&0x80000000)?1:((mTIM_0_CURRENT+1)<<divide);
2755          tmp+=gSystemCycleCount;
2756          if(tmp<gNextTimerEvent) {
2757             gNextTimerEvent=tmp;
2758             //						TRACE_MIKIE1("Update() - TIMER 0 Set NextTimerEvent = %012d",gNextTimerEvent);
2759          }
2760       }
2761       //				TRACE_MIKIE1("Update() - mTIM_0_CURRENT = %012d",mTIM_0_CURRENT);
2762       //				TRACE_MIKIE1("Update() - mTIM_0_BKUP    = %012d",mTIM_0_BKUP);
2763       //				TRACE_MIKIE1("Update() - mTIM_0_LASTCNT = %012d",mTIM_0_LAST_COUNT);
2764       //				TRACE_MIKIE1("Update() - mTIM_0_LINKING = %012d",mTIM_0_LINKING);
2765    }
2766 
2767    //
2768    // Timer 2 of Group A
2769    //
2770 
2771    //
2772    // Optimisation, assume T2 (Frame timer) is never in one-shot
2773    // always in linked mode i.e clocked by Line Timer
2774    //
2775 
2776    // KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD ||  ..)
2777    //			if(mTIM_2_ENABLE_COUNT && (mTIM_2_ENABLE_RELOAD || !mTIM_2_TIMER_DONE))
2778    if(mTIM_2_ENABLE_COUNT) {
2779       decval=0;
2780 
2781       //				if(mTIM_2_LINKING==0x07)
2782       {
2783          if(mTIM_0_BORROW_OUT) decval=1;
2784          mTIM_2_LAST_LINK_CARRY=mTIM_0_BORROW_OUT;
2785       }
2786       //				else
2787       //				{
2788       //					// Ordinary clocked mode as opposed to linked mode
2789       //					// 16MHz clock downto 1us == cyclecount >> 4
2790       //					divide=(4+mTIM_2_LINKING);
2791       //					decval=(gSystemCycleCount-mTIM_2_LAST_COUNT)>>divide;
2792       //				}
2793 
2794       if(decval) {
2795          //					mTIM_2_LAST_COUNT+=decval<<divide;
2796          mTIM_2_CURRENT-=decval;
2797          if(mTIM_2_CURRENT&0x80000000) {
2798             // Set carry out
2799             mTIM_2_BORROW_OUT=TRUE;
2800 
2801             //						// Reload if neccessary
2802             //						if(mTIM_2_ENABLE_RELOAD)
2803             //						{
2804             mTIM_2_CURRENT+=mTIM_2_BKUP+1;
2805             //						}
2806             //						else
2807             //						{
2808             //							mTIM_2_CURRENT=0;
2809             //						}
2810             mTIM_2_TIMER_DONE=TRUE;
2811 
2812             // Interupt flag setting code moved into DisplayEndOfFrame(), also
2813             // park any CPU cycles lost for later inclusion
2814             mikie_work_done+=DisplayEndOfFrame();
2815          } else {
2816             mTIM_2_BORROW_OUT=FALSE;
2817          }
2818          // Set carry in as we did a count
2819          mTIM_2_BORROW_IN=TRUE;
2820       } else {
2821          // Clear carry in as we didn't count
2822          mTIM_2_BORROW_IN=FALSE;
2823          // Clear carry out
2824          mTIM_2_BORROW_OUT=FALSE;
2825       }
2826 
2827       // Prediction for next timer event cycle number
2828       // We dont need to predict this as its the frame timer and will always
2829       // be beaten by the line timer on Timer 0
2830       //				if(mTIM_2_LINKING!=7)
2831       //				{
2832       //					tmp=gSystemCycleCount+((mTIM_2_CURRENT+1)<<divide);
2833       //					if(tmp<gNextTimerEvent)	gNextTimerEvent=tmp;
2834       //				}
2835       //				TRACE_MIKIE1("Update() - mTIM_2_CURRENT = %012d",mTIM_2_CURRENT);
2836       //				TRACE_MIKIE1("Update() - mTIM_2_BKUP    = %012d",mTIM_2_BKUP);
2837       //				TRACE_MIKIE1("Update() - mTIM_2_LASTCNT = %012d",mTIM_2_LAST_COUNT);
2838       //				TRACE_MIKIE1("Update() - mTIM_2_LINKING = %012d",mTIM_2_LINKING);
2839    }
2840 
2841    //
2842    // Timer 4 of Group A
2843    //
2844    // For the sake of speed it is assumed that Timer 4 (UART timer)
2845    // never uses one-shot mode, never uses linking, hence the code
2846    // is commented out. Timer 4 is at the end of a chain and seems
2847    // no reason to update its carry in-out variables
2848    //
2849 
2850    // KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD ||  ..)
2851    //			if(mTIM_4_ENABLE_COUNT && (mTIM_4_ENABLE_RELOAD || !mTIM_4_TIMER_DONE))
2852    if(mTIM_4_ENABLE_COUNT) {
2853       decval=0;
2854 
2855       //				if(mTIM_4_LINKING==0x07)
2856       //				{
2857       ////				if(mTIM_2_BORROW_OUT && !mTIM_4_LAST_LINK_CARRY) decval=1;
2858       //					if(mTIM_2_BORROW_OUT) decval=1;
2859       //					mTIM_4_LAST_LINK_CARRY=mTIM_2_BORROW_OUT;
2860       //				}
2861       //				else
2862       {
2863          // Ordinary clocked mode as opposed to linked mode
2864          // 16MHz clock downto 1us == cyclecount >> 4
2865          // Additional /8 (+3) for 8 clocks per bit transmit
2866          divide=4+3+mTIM_4_LINKING;
2867          decval=(gSystemCycleCount-mTIM_4_LAST_COUNT)>>divide;
2868       }
2869 
2870       if(decval) {
2871          mTIM_4_LAST_COUNT+=decval<<divide;
2872          mTIM_4_CURRENT-=decval;
2873          if(mTIM_4_CURRENT&0x80000000) {
2874             // Set carry out
2875             mTIM_4_BORROW_OUT=TRUE;
2876 
2877             //
2878             // Update the UART counter models for Rx & Tx
2879             //
2880 
2881             //
2882             // According to the docs IRQ's are level triggered and hence will always assert
2883             // what a pain in the arse
2884             //
2885             // Rx & Tx are loopedback due to comlynx structure
2886 
2887             //
2888             // Receive
2889             //
2890             if(!mUART_RX_COUNTDOWN) {
2891                // Fetch a byte from the input queue
2892                if(mUART_Rx_waiting>0) {
2893                   mUART_RX_DATA=mUART_Rx_input_queue[mUART_Rx_output_ptr];
2894                   mUART_Rx_output_ptr=(++mUART_Rx_output_ptr)%UART_MAX_RX_QUEUE;
2895                   mUART_Rx_waiting--;
2896                   TRACE_MIKIE2("Update() - RX Byte output ptr=%02d waiting=%02d",mUART_Rx_output_ptr,mUART_Rx_waiting);
2897                } else {
2898                   TRACE_MIKIE0("Update() - RX Byte but no data waiting ????");
2899                }
2900 
2901                // Retrigger input if more bytes waiting
2902                if(mUART_Rx_waiting>0) {
2903                   mUART_RX_COUNTDOWN=UART_RX_TIME_PERIOD+UART_RX_NEXT_DELAY;
2904                   TRACE_MIKIE1("Update() - RX Byte retriggered, %d waiting",mUART_Rx_waiting);
2905                } else {
2906                   mUART_RX_COUNTDOWN=UART_RX_INACTIVE;
2907                   TRACE_MIKIE0("Update() - RX Byte nothing waiting, deactivated");
2908                }
2909 
2910                // If RX_READY already set then we have an overrun
2911                // as previous byte hasnt been read
2912                if(mUART_RX_READY) mUART_Rx_overun_error=1;
2913 
2914                // Flag byte as being recvd
2915                mUART_RX_READY=1;
2916             } else if(!(mUART_RX_COUNTDOWN&UART_RX_INACTIVE)) {
2917                mUART_RX_COUNTDOWN--;
2918             }
2919 
2920             if(!mUART_TX_COUNTDOWN) {
2921                if(mUART_SENDBREAK) {
2922                   mUART_TX_DATA=UART_BREAK_CODE;
2923                   // Auto-Respawn new transmit
2924                   mUART_TX_COUNTDOWN=UART_TX_TIME_PERIOD;
2925                   // Loop back what we transmitted
2926                   ComLynxTxLoopback(mUART_TX_DATA);
2927                } else {
2928                   // Serial activity finished
2929                   mUART_TX_COUNTDOWN=UART_TX_INACTIVE;
2930                }
2931 
2932                // If a networking object is attached then use its callback to send the data byte.
2933                if(mpUART_TX_CALLBACK) {
2934                   TRACE_MIKIE0("Update() - UART_TX_CALLBACK");
2935                   (*mpUART_TX_CALLBACK)(mUART_TX_DATA,mUART_TX_CALLBACK_OBJECT);
2936                }
2937 
2938             } else if(!(mUART_TX_COUNTDOWN&UART_TX_INACTIVE)) {
2939                mUART_TX_COUNTDOWN--;
2940             }
2941 
2942             // Set the timer status flag
2943             // Timer 4 is the uart timer and doesn't generate IRQ's using this method
2944 
2945             // 16 Clocks = 1 bit transmission. Hold separate Rx & Tx counters
2946 
2947             // Reload if neccessary
2948             //						if(mTIM_4_ENABLE_RELOAD)
2949             //						{
2950             mTIM_4_CURRENT+=mTIM_4_BKUP+1;
2951             // The low reload values on TIM4 coupled with a longer
2952             // timer service delay can sometimes cause
2953             // an underun, check and fix
2954             if(mTIM_4_CURRENT&0x80000000) {
2955                mTIM_4_CURRENT=mTIM_4_BKUP;
2956                mTIM_4_LAST_COUNT=gSystemCycleCount;
2957             }
2958             //						}
2959             //						else
2960             //						{
2961             //							mTIM_4_CURRENT=0;
2962             //						}
2963             //						mTIM_4_TIMER_DONE=TRUE;
2964          }
2965          //					else
2966          //					{
2967          //						mTIM_4_BORROW_OUT=FALSE;
2968          //					}
2969          //					// Set carry in as we did a count
2970          //					mTIM_4_BORROW_IN=TRUE;
2971       }
2972       //				else
2973       //				{
2974       //					// Clear carry in as we didn't count
2975       //					mTIM_4_BORROW_IN=FALSE;
2976       //					// Clear carry out
2977       //					mTIM_4_BORROW_OUT=FALSE;
2978       //				}
2979       //
2980       //				// Prediction for next timer event cycle number
2981       //
2982       //				if(mTIM_4_LINKING!=7)
2983       //				{
2984       // Sometimes timeupdates can be >2x rollover in which case
2985       // then CURRENT may still be negative and we can use it to
2986       // calc the next timer value, we just want another update ASAP
2987       tmp=(mTIM_4_CURRENT&0x80000000)?1:((mTIM_4_CURRENT+1)<<divide);
2988       tmp+=gSystemCycleCount;
2989       if(tmp<gNextTimerEvent) {
2990          gNextTimerEvent=tmp;
2991          TRACE_MIKIE1("Update() - TIMER 4 Set NextTimerEvent = %012d",gNextTimerEvent);
2992       }
2993       //				}
2994       //				TRACE_MIKIE1("Update() - mTIM_4_CURRENT = %012d",mTIM_4_CURRENT);
2995       //				TRACE_MIKIE1("Update() - mTIM_4_BKUP    = %012d",mTIM_4_BKUP);
2996       //				TRACE_MIKIE1("Update() - mTIM_4_LASTCNT = %012d",mTIM_4_LAST_COUNT);
2997       //				TRACE_MIKIE1("Update() - mTIM_4_LINKING = %012d",mTIM_4_LINKING);
2998    }
2999 
3000    // Emulate the UART bug where UART IRQ is level sensitive
3001    // in that it will continue to generate interrupts as long
3002    // as they are enabled and the interrupt condition is true
3003 
3004    // If Tx is inactive i.e ready for a byte to eat and the
3005    // IRQ is enabled then generate it always
3006    if((mUART_TX_COUNTDOWN&UART_TX_INACTIVE) && mUART_TX_IRQ_ENABLE) {
3007       TRACE_MIKIE0("Update() - UART TX IRQ Triggered");
3008       mTimerStatusFlags|=0x10;
3009       gSystemIRQ=TRUE;	// Added 19/09/06 fix for IRQ issue
3010    }
3011    // Is data waiting and the interrupt enabled, if so then
3012    // what are we waiting for....
3013    if(mUART_RX_READY && mUART_RX_IRQ_ENABLE) {
3014       TRACE_MIKIE0("Update() - UART RX IRQ Triggered");
3015       mTimerStatusFlags|=0x10;
3016       gSystemIRQ=TRUE;	// Added 19/09/06 fix for IRQ issue
3017    }
3018 
3019    //
3020    // Timer 1 of Group B
3021    //
3022    // KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD ||  ..)
3023    if(mTIM_1_ENABLE_COUNT && (mTIM_1_ENABLE_RELOAD || !mTIM_1_TIMER_DONE)) {
3024       if(mTIM_1_LINKING!=0x07) {
3025          // Ordinary clocked mode as opposed to linked mode
3026          // 16MHz clock downto 1us == cyclecount >> 4
3027          divide=(4+mTIM_1_LINKING);
3028          decval=(gSystemCycleCount-mTIM_1_LAST_COUNT)>>divide;
3029 
3030          if(decval) {
3031             mTIM_1_LAST_COUNT+=decval<<divide;
3032             mTIM_1_CURRENT-=decval;
3033             if(mTIM_1_CURRENT&0x80000000) {
3034                // Set carry out
3035                mTIM_1_BORROW_OUT=TRUE;
3036 
3037                // Set the timer status flag
3038                if(mTimerInterruptMask&0x02) {
3039                   TRACE_MIKIE0("Update() - TIMER1 IRQ Triggered");
3040                   mTimerStatusFlags|=0x02;
3041                   gSystemIRQ=TRUE;	// Added 19/09/06 fix for IRQ issue
3042                }
3043 
3044                // Reload if neccessary
3045                if(mTIM_1_ENABLE_RELOAD) {
3046                   mTIM_1_CURRENT+=mTIM_1_BKUP+1;
3047                } else {
3048                   mTIM_1_CURRENT=0;
3049                }
3050                mTIM_1_TIMER_DONE=TRUE;
3051             } else {
3052                mTIM_1_BORROW_OUT=FALSE;
3053             }
3054             // Set carry in as we did a count
3055             mTIM_1_BORROW_IN=TRUE;
3056          } else {
3057             // Clear carry in as we didn't count
3058             mTIM_1_BORROW_IN=FALSE;
3059             // Clear carry out
3060             mTIM_1_BORROW_OUT=FALSE;
3061          }
3062       }
3063 
3064       // Prediction for next timer event cycle number
3065 
3066       if(mTIM_1_LINKING!=7) {
3067          // Sometimes timeupdates can be >2x rollover in which case
3068          // then CURRENT may still be negative and we can use it to
3069          // calc the next timer value, we just want another update ASAP
3070          tmp=(mTIM_1_CURRENT&0x80000000)?1:((mTIM_1_CURRENT+1)<<divide);
3071          tmp+=gSystemCycleCount;
3072          if(tmp<gNextTimerEvent) {
3073             gNextTimerEvent=tmp;
3074             TRACE_MIKIE1("Update() - TIMER 1 Set NextTimerEvent = %012d",gNextTimerEvent);
3075          }
3076       }
3077       //				TRACE_MIKIE1("Update() - mTIM_1_CURRENT = %012d",mTIM_1_CURRENT);
3078       //				TRACE_MIKIE1("Update() - mTIM_1_BKUP    = %012d",mTIM_1_BKUP);
3079       //				TRACE_MIKIE1("Update() - mTIM_1_LASTCNT = %012d",mTIM_1_LAST_COUNT);
3080       //				TRACE_MIKIE1("Update() - mTIM_1_LINKING = %012d",mTIM_1_LINKING);
3081    }
3082 
3083    //
3084    // Timer 3 of Group A
3085    //
3086    // KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD ||  ..)
3087    if(mTIM_3_ENABLE_COUNT && (mTIM_3_ENABLE_RELOAD || !mTIM_3_TIMER_DONE)) {
3088       decval=0;
3089 
3090       if(mTIM_3_LINKING==0x07) {
3091          if(mTIM_1_BORROW_OUT) decval=1;
3092             mTIM_3_LAST_LINK_CARRY=mTIM_1_BORROW_OUT;
3093       } else {
3094          // Ordinary clocked mode as opposed to linked mode
3095          // 16MHz clock downto 1us == cyclecount >> 4
3096          divide=(4+mTIM_3_LINKING);
3097          decval=(gSystemCycleCount-mTIM_3_LAST_COUNT)>>divide;
3098       }
3099 
3100       if(decval) {
3101          mTIM_3_LAST_COUNT+=decval<<divide;
3102          mTIM_3_CURRENT-=decval;
3103          if(mTIM_3_CURRENT&0x80000000) {
3104             // Set carry out
3105             mTIM_3_BORROW_OUT=TRUE;
3106 
3107             // Set the timer status flag
3108             if(mTimerInterruptMask&0x08) {
3109                TRACE_MIKIE0("Update() - TIMER3 IRQ Triggered");
3110                mTimerStatusFlags|=0x08;
3111                gSystemIRQ=TRUE;	// Added 19/09/06 fix for IRQ issue
3112             }
3113 
3114             // Reload if neccessary
3115             if(mTIM_3_ENABLE_RELOAD) {
3116                mTIM_3_CURRENT+=mTIM_3_BKUP+1;
3117             } else {
3118                mTIM_3_CURRENT=0;
3119             }
3120             mTIM_3_TIMER_DONE=TRUE;
3121          } else {
3122             mTIM_3_BORROW_OUT=FALSE;
3123          }
3124          // Set carry in as we did a count
3125          mTIM_3_BORROW_IN=TRUE;
3126       } else {
3127          // Clear carry in as we didn't count
3128          mTIM_3_BORROW_IN=FALSE;
3129          // Clear carry out
3130          mTIM_3_BORROW_OUT=FALSE;
3131       }
3132 
3133       // Prediction for next timer event cycle number
3134 
3135       if(mTIM_3_LINKING!=7) {
3136          // Sometimes timeupdates can be >2x rollover in which case
3137          // then CURRENT may still be negative and we can use it to
3138          // calc the next timer value, we just want another update ASAP
3139          tmp=(mTIM_3_CURRENT&0x80000000)?1:((mTIM_3_CURRENT+1)<<divide);
3140          tmp+=gSystemCycleCount;
3141          if(tmp<gNextTimerEvent) {
3142             gNextTimerEvent=tmp;
3143             TRACE_MIKIE1("Update() - TIMER 3 Set NextTimerEvent = %012d",gNextTimerEvent);
3144          }
3145       }
3146       //				TRACE_MIKIE1("Update() - mTIM_3_CURRENT = %012d",mTIM_3_CURRENT);
3147       //				TRACE_MIKIE1("Update() - mTIM_3_BKUP    = %012d",mTIM_3_BKUP);
3148       //				TRACE_MIKIE1("Update() - mTIM_3_LASTCNT = %012d",mTIM_3_LAST_COUNT);
3149       //				TRACE_MIKIE1("Update() - mTIM_3_LINKING = %012d",mTIM_3_LINKING);
3150    }
3151 
3152    //
3153    // Timer 5 of Group A
3154    //
3155    // KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD ||  ..)
3156    if(mTIM_5_ENABLE_COUNT && (mTIM_5_ENABLE_RELOAD || !mTIM_5_TIMER_DONE)) {
3157       decval=0;
3158 
3159       if(mTIM_5_LINKING==0x07) {
3160          if(mTIM_3_BORROW_OUT) decval=1;
3161             mTIM_5_LAST_LINK_CARRY=mTIM_3_BORROW_OUT;
3162       } else {
3163          // Ordinary clocked mode as opposed to linked mode
3164          // 16MHz clock downto 1us == cyclecount >> 4
3165          divide=(4+mTIM_5_LINKING);
3166          decval=(gSystemCycleCount-mTIM_5_LAST_COUNT)>>divide;
3167       }
3168 
3169       if(decval) {
3170          mTIM_5_LAST_COUNT+=decval<<divide;
3171          mTIM_5_CURRENT-=decval;
3172          if(mTIM_5_CURRENT&0x80000000) {
3173             // Set carry out
3174             mTIM_5_BORROW_OUT=TRUE;
3175 
3176             // Set the timer status flag
3177             if(mTimerInterruptMask&0x20) {
3178                TRACE_MIKIE0("Update() - TIMER5 IRQ Triggered");
3179                mTimerStatusFlags|=0x20;
3180                gSystemIRQ=TRUE;	// Added 19/09/06 fix for IRQ issue
3181             }
3182 
3183             // Reload if neccessary
3184             if(mTIM_5_ENABLE_RELOAD) {
3185                mTIM_5_CURRENT+=mTIM_5_BKUP+1;
3186             } else {
3187                mTIM_5_CURRENT=0;
3188             }
3189             mTIM_5_TIMER_DONE=TRUE;
3190          } else {
3191             mTIM_5_BORROW_OUT=FALSE;
3192          }
3193          // Set carry in as we did a count
3194          mTIM_5_BORROW_IN=TRUE;
3195       } else {
3196          // Clear carry in as we didn't count
3197          mTIM_5_BORROW_IN=FALSE;
3198          // Clear carry out
3199          mTIM_5_BORROW_OUT=FALSE;
3200       }
3201 
3202       // Prediction for next timer event cycle number
3203 
3204       if(mTIM_5_LINKING!=7) {
3205          // Sometimes timeupdates can be >2x rollover in which case
3206          // then CURRENT may still be negative and we can use it to
3207          // calc the next timer value, we just want another update ASAP
3208          tmp=(mTIM_5_CURRENT&0x80000000)?1:((mTIM_5_CURRENT+1)<<divide);
3209          tmp+=gSystemCycleCount;
3210          if(tmp<gNextTimerEvent) {
3211             gNextTimerEvent=tmp;
3212             TRACE_MIKIE1("Update() - TIMER 5 Set NextTimerEvent = %012d",gNextTimerEvent);
3213          }
3214       }
3215       //				TRACE_MIKIE1("Update() - mTIM_5_CURRENT = %012d",mTIM_5_CURRENT);
3216       //				TRACE_MIKIE1("Update() - mTIM_5_BKUP    = %012d",mTIM_5_BKUP);
3217       //				TRACE_MIKIE1("Update() - mTIM_5_LASTCNT = %012d",mTIM_5_LAST_COUNT);
3218       //				TRACE_MIKIE1("Update() - mTIM_5_LINKING = %012d",mTIM_5_LINKING);
3219    }
3220 
3221    //
3222    // Timer 7 of Group A
3223    //
3224    // KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD ||  ..)
3225    if(mTIM_7_ENABLE_COUNT && (mTIM_7_ENABLE_RELOAD || !mTIM_7_TIMER_DONE)) {
3226       decval=0;
3227 
3228       if(mTIM_7_LINKING==0x07) {
3229          if(mTIM_5_BORROW_OUT) decval=1;
3230             mTIM_7_LAST_LINK_CARRY=mTIM_5_BORROW_OUT;
3231       } else {
3232           // Ordinary clocked mode as opposed to linked mode
3233           // 16MHz clock downto 1us == cyclecount >> 4
3234           divide=(4+mTIM_7_LINKING);
3235           decval=(gSystemCycleCount-mTIM_7_LAST_COUNT)>>divide;
3236       }
3237 
3238       if(decval) {
3239          mTIM_7_LAST_COUNT+=decval<<divide;
3240          mTIM_7_CURRENT-=decval;
3241          if(mTIM_7_CURRENT&0x80000000) {
3242             // Set carry out
3243             mTIM_7_BORROW_OUT=TRUE;
3244 
3245             // Set the timer status flag
3246             if(mTimerInterruptMask&0x80) {
3247                TRACE_MIKIE0("Update() - TIMER7 IRQ Triggered");
3248                mTimerStatusFlags|=0x80;
3249                gSystemIRQ=TRUE;	// Added 19/09/06 fix for IRQ issue
3250             }
3251 
3252             // Reload if neccessary
3253             if(mTIM_7_ENABLE_RELOAD) {
3254                mTIM_7_CURRENT+=mTIM_7_BKUP+1;
3255             } else {
3256                mTIM_7_CURRENT=0;
3257             }
3258             mTIM_7_TIMER_DONE=TRUE;
3259 
3260          } else {
3261             mTIM_7_BORROW_OUT=FALSE;
3262          }
3263          // Set carry in as we did a count
3264          mTIM_7_BORROW_IN=TRUE;
3265       } else {
3266          // Clear carry in as we didn't count
3267          mTIM_7_BORROW_IN=FALSE;
3268          // Clear carry out
3269          mTIM_7_BORROW_OUT=FALSE;
3270       }
3271 
3272       // Prediction for next timer event cycle number
3273 
3274       if(mTIM_7_LINKING!=7) {
3275          // Sometimes timeupdates can be >2x rollover in which case
3276          // then CURRENT may still be negative and we can use it to
3277          // calc the next timer value, we just want another update ASAP
3278          tmp=(mTIM_7_CURRENT&0x80000000)?1:((mTIM_7_CURRENT+1)<<divide);
3279          tmp+=gSystemCycleCount;
3280          if(tmp<gNextTimerEvent) {
3281             gNextTimerEvent=tmp;
3282             TRACE_MIKIE1("Update() - TIMER 7 Set NextTimerEvent = %012d",gNextTimerEvent);
3283          }
3284       }
3285       //				TRACE_MIKIE1("Update() - mTIM_7_CURRENT = %012d",mTIM_7_CURRENT);
3286       //				TRACE_MIKIE1("Update() - mTIM_7_BKUP    = %012d",mTIM_7_BKUP);
3287       //				TRACE_MIKIE1("Update() - mTIM_7_LASTCNT = %012d",mTIM_7_LAST_COUNT);
3288       //				TRACE_MIKIE1("Update() - mTIM_7_LINKING = %012d",mTIM_7_LINKING);
3289    }
3290 
3291    //
3292    // Timer 6 has no group
3293    //
3294    // KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD ||  ..)
3295    if(mTIM_6_ENABLE_COUNT && (mTIM_6_ENABLE_RELOAD || !mTIM_6_TIMER_DONE)) {
3296       //				if(mTIM_6_LINKING!=0x07)
3297       {
3298          // Ordinary clocked mode as opposed to linked mode
3299          // 16MHz clock downto 1us == cyclecount >> 4
3300          divide=(4+mTIM_6_LINKING);
3301          decval=(gSystemCycleCount-mTIM_6_LAST_COUNT)>>divide;
3302 
3303          if(decval) {
3304             mTIM_6_LAST_COUNT+=decval<<divide;
3305             mTIM_6_CURRENT-=decval;
3306             if(mTIM_6_CURRENT&0x80000000) {
3307                // Set carry out
3308                mTIM_6_BORROW_OUT=TRUE;
3309 
3310                // Set the timer status flag
3311                if(mTimerInterruptMask&0x40) {
3312                   TRACE_MIKIE0("Update() - TIMER6 IRQ Triggered");
3313                   mTimerStatusFlags|=0x40;
3314                   gSystemIRQ=TRUE;	// Added 19/09/06 fix for IRQ issue
3315                }
3316 
3317                // Reload if neccessary
3318                if(mTIM_6_ENABLE_RELOAD) {
3319                   mTIM_6_CURRENT+=mTIM_6_BKUP+1;
3320                } else {
3321                   mTIM_6_CURRENT=0;
3322                }
3323                mTIM_6_TIMER_DONE=TRUE;
3324             } else {
3325                mTIM_6_BORROW_OUT=FALSE;
3326             }
3327             // Set carry in as we did a count
3328             mTIM_6_BORROW_IN=TRUE;
3329          } else {
3330             // Clear carry in as we didn't count
3331             mTIM_6_BORROW_IN=FALSE;
3332             // Clear carry out
3333             mTIM_6_BORROW_OUT=FALSE;
3334          }
3335       }
3336 
3337       // Prediction for next timer event cycle number
3338       // (Timer 6 doesn't support linking)
3339 
3340       //				if(mTIM_6_LINKING!=7)
3341       {
3342          // Sometimes timeupdates can be >2x rollover in which case
3343          // then CURRENT may still be negative and we can use it to
3344          // calc the next timer value, we just want another update ASAP
3345          tmp=(mTIM_6_CURRENT&0x80000000)?1:((mTIM_6_CURRENT+1)<<divide);
3346          tmp+=gSystemCycleCount;
3347          if(tmp<gNextTimerEvent) {
3348             gNextTimerEvent=tmp;
3349             TRACE_MIKIE1("Update() - TIMER 6 Set NextTimerEvent = %012d",gNextTimerEvent);
3350          }
3351       }
3352       //				TRACE_MIKIE1("Update() - mTIM_6_CURRENT = %012d",mTIM_6_CURRENT);
3353       //				TRACE_MIKIE1("Update() - mTIM_6_BKUP    = %012d",mTIM_6_BKUP);
3354       //				TRACE_MIKIE1("Update() - mTIM_6_LASTCNT = %012d",mTIM_6_LAST_COUNT);
3355       //				TRACE_MIKIE1("Update() - mTIM_6_LINKING = %012d",mTIM_6_LINKING);
3356    }
3357 
3358    //
3359    // If sound is enabled then update the sound subsystem
3360    //
3361    if(gAudioEnabled) {
3362       //
3363       // Audio 0
3364       //
3365       //				if(mAUDIO_0_ENABLE_COUNT && !mAUDIO_0_TIMER_DONE && mAUDIO_0_VOLUME && mAUDIO_0_BKUP)
3366       if(mAUDIO_0_ENABLE_COUNT && (mAUDIO_0_ENABLE_RELOAD || !mAUDIO_0_TIMER_DONE)) {
3367          decval=0;
3368 
3369          if(mAUDIO_0_LINKING==0x07) {
3370             if(mTIM_7_BORROW_OUT) decval=1;
3371                mAUDIO_0_LAST_LINK_CARRY=mTIM_7_BORROW_OUT;
3372          } else {
3373             // Ordinary clocked mode as opposed to linked mode
3374             // 16MHz clock downto 1us == cyclecount >> 4
3375             divide=(4+mAUDIO_0_LINKING);
3376             decval=(gSystemCycleCount-mAUDIO_0_LAST_COUNT)>>divide;
3377          }
3378 
3379          if(decval) {
3380             mAUDIO_0_LAST_COUNT+=decval<<divide;
3381             mAUDIO_0_CURRENT-=decval;
3382             if(mAUDIO_0_CURRENT&0x80000000) {
3383                // Set carry out
3384                mAUDIO_0_BORROW_OUT=TRUE;
3385 
3386                // Reload if neccessary
3387                if(mAUDIO_0_ENABLE_RELOAD) {
3388                   mAUDIO_0_CURRENT+=mAUDIO_0_BKUP+1;
3389                   if(mAUDIO_0_CURRENT&0x80000000) mAUDIO_0_CURRENT=0;
3390                } else {
3391                   // Set timer done
3392                   mAUDIO_0_TIMER_DONE=TRUE;
3393                   mAUDIO_0_CURRENT=0;
3394                }
3395 
3396                //
3397                // Update audio circuitry
3398                //
3399                if(mAUDIO_0_BKUP || mAUDIO_0_LINKING)
3400                   mAUDIO_0_WAVESHAPER=GetLfsrNext(mAUDIO_0_WAVESHAPER);
3401 
3402                if(mAUDIO_0_INTEGRATE_ENABLE) {
3403                   SLONG temp=mAUDIO_OUTPUT[0];
3404                   if(mAUDIO_0_WAVESHAPER&0x0001) temp+=mAUDIO_0_VOLUME;
3405                   else temp-=mAUDIO_0_VOLUME;
3406                   if(temp>127) temp=127;
3407                   if(temp<-128) temp=-128;
3408                   mAUDIO_OUTPUT[0]=(SBYTE)temp;
3409                } else {
3410                   if(mAUDIO_0_WAVESHAPER&0x0001) mAUDIO_OUTPUT[0]=mAUDIO_0_VOLUME;
3411                   else mAUDIO_OUTPUT[0]=-mAUDIO_0_VOLUME;
3412                }
3413             } else {
3414                mAUDIO_0_BORROW_OUT=FALSE;
3415             }
3416             // Set carry in as we did a count
3417             mAUDIO_0_BORROW_IN=TRUE;
3418          } else {
3419             // Clear carry in as we didn't count
3420             mAUDIO_0_BORROW_IN=FALSE;
3421             // Clear carry out
3422             mAUDIO_0_BORROW_OUT=FALSE;
3423          }
3424 
3425          // Prediction for next timer event cycle number
3426 
3427          if(mAUDIO_0_LINKING!=7) {
3428             // Sometimes timeupdates can be >2x rollover in which case
3429             // then CURRENT may still be negative and we can use it to
3430             // calc the next timer value, we just want another update ASAP
3431             tmp=(mAUDIO_0_CURRENT&0x80000000)?1:((mAUDIO_0_CURRENT+1)<<divide);
3432             tmp+=gSystemCycleCount;
3433             if(tmp<gNextTimerEvent) {
3434                gNextTimerEvent=tmp;
3435                TRACE_MIKIE1("Update() - AUDIO 0 Set NextTimerEvent = %012d",gNextTimerEvent);
3436             }
3437          }
3438          //					TRACE_MIKIE1("Update() - mAUDIO_0_CURRENT = %012d",mAUDIO_0_CURRENT);
3439          //					TRACE_MIKIE1("Update() - mAUDIO_0_BKUP    = %012d",mAUDIO_0_BKUP);
3440          //					TRACE_MIKIE1("Update() - mAUDIO_0_LASTCNT = %012d",mAUDIO_0_LAST_COUNT);
3441          //					TRACE_MIKIE1("Update() - mAUDIO_0_LINKING = %012d",mAUDIO_0_LINKING);
3442       }
3443 
3444       //
3445       // Audio 1
3446       //
3447       //				if(mAUDIO_1_ENABLE_COUNT && !mAUDIO_1_TIMER_DONE && mAUDIO_1_VOLUME && mAUDIO_1_BKUP)
3448       if(mAUDIO_1_ENABLE_COUNT && (mAUDIO_1_ENABLE_RELOAD || !mAUDIO_1_TIMER_DONE)) {
3449          decval=0;
3450 
3451          if(mAUDIO_1_LINKING==0x07) {
3452             if(mAUDIO_0_BORROW_OUT) decval=1;
3453             mAUDIO_1_LAST_LINK_CARRY=mAUDIO_0_BORROW_OUT;
3454          } else {
3455             // Ordinary clocked mode as opposed to linked mode
3456             // 16MHz clock downto 1us == cyclecount >> 4
3457             divide=(4+mAUDIO_1_LINKING);
3458             decval=(gSystemCycleCount-mAUDIO_1_LAST_COUNT)>>divide;
3459          }
3460 
3461          if(decval) {
3462             mAUDIO_1_LAST_COUNT+=decval<<divide;
3463             mAUDIO_1_CURRENT-=decval;
3464             if(mAUDIO_1_CURRENT&0x80000000) {
3465                // Set carry out
3466                mAUDIO_1_BORROW_OUT=TRUE;
3467 
3468                // Reload if neccessary
3469                if(mAUDIO_1_ENABLE_RELOAD) {
3470                   mAUDIO_1_CURRENT+=mAUDIO_1_BKUP+1;
3471                   if(mAUDIO_1_CURRENT&0x80000000) mAUDIO_1_CURRENT=0;
3472                } else {
3473                   // Set timer done
3474                   mAUDIO_1_TIMER_DONE=TRUE;
3475                   mAUDIO_1_CURRENT=0;
3476                }
3477 
3478                //
3479                // Update audio circuitry
3480                //
3481                if(mAUDIO_1_BKUP || mAUDIO_1_LINKING)
3482                   mAUDIO_1_WAVESHAPER=GetLfsrNext(mAUDIO_1_WAVESHAPER);
3483 
3484                if(mAUDIO_1_INTEGRATE_ENABLE) {
3485                   SLONG temp=mAUDIO_OUTPUT[1];
3486                   if(mAUDIO_1_WAVESHAPER&0x0001) temp+=mAUDIO_1_VOLUME;
3487                   else temp-=mAUDIO_1_VOLUME;
3488                   if(temp>127) temp=127;
3489                   if(temp<-128) temp=-128;
3490                   mAUDIO_OUTPUT[1]=(SBYTE)temp;
3491                } else {
3492                   if(mAUDIO_1_WAVESHAPER&0x0001) mAUDIO_OUTPUT[1]=mAUDIO_1_VOLUME;
3493                   else mAUDIO_OUTPUT[1]=-mAUDIO_1_VOLUME;
3494                }
3495             } else {
3496                mAUDIO_1_BORROW_OUT=FALSE;
3497             }
3498             // Set carry in as we did a count
3499             mAUDIO_1_BORROW_IN=TRUE;
3500          } else {
3501             // Clear carry in as we didn't count
3502             mAUDIO_1_BORROW_IN=FALSE;
3503             // Clear carry out
3504             mAUDIO_1_BORROW_OUT=FALSE;
3505          }
3506 
3507          // Prediction for next timer event cycle number
3508 
3509          if(mAUDIO_1_LINKING!=7) {
3510             // Sometimes timeupdates can be >2x rollover in which case
3511             // then CURRENT may still be negative and we can use it to
3512             // calc the next timer value, we just want another update ASAP
3513             tmp=(mAUDIO_1_CURRENT&0x80000000)?1:((mAUDIO_1_CURRENT+1)<<divide);
3514             tmp+=gSystemCycleCount;
3515             if(tmp<gNextTimerEvent) {
3516                gNextTimerEvent=tmp;
3517                TRACE_MIKIE1("Update() - AUDIO 1 Set NextTimerEvent = %012d",gNextTimerEvent);
3518             }
3519          }
3520          //					TRACE_MIKIE1("Update() - mAUDIO_1_CURRENT = %012d",mAUDIO_1_CURRENT);
3521          //					TRACE_MIKIE1("Update() - mAUDIO_1_BKUP    = %012d",mAUDIO_1_BKUP);
3522          //					TRACE_MIKIE1("Update() - mAUDIO_1_LASTCNT = %012d",mAUDIO_1_LAST_COUNT);
3523          //					TRACE_MIKIE1("Update() - mAUDIO_1_LINKING = %012d",mAUDIO_1_LINKING);
3524       }
3525 
3526       //
3527       // Audio 2
3528       //
3529       //				if(mAUDIO_2_ENABLE_COUNT && !mAUDIO_2_TIMER_DONE && mAUDIO_2_VOLUME && mAUDIO_2_BKUP)
3530       if(mAUDIO_2_ENABLE_COUNT && (mAUDIO_2_ENABLE_RELOAD || !mAUDIO_2_TIMER_DONE)) {
3531          decval=0;
3532 
3533          if(mAUDIO_2_LINKING==0x07) {
3534             if(mAUDIO_1_BORROW_OUT) decval=1;
3535             mAUDIO_2_LAST_LINK_CARRY=mAUDIO_1_BORROW_OUT;
3536          } else {
3537             // Ordinary clocked mode as opposed to linked mode
3538             // 16MHz clock downto 1us == cyclecount >> 4
3539             divide=(4+mAUDIO_2_LINKING);
3540             decval=(gSystemCycleCount-mAUDIO_2_LAST_COUNT)>>divide;
3541          }
3542 
3543          if(decval) {
3544             mAUDIO_2_LAST_COUNT+=decval<<divide;
3545             mAUDIO_2_CURRENT-=decval;
3546             if(mAUDIO_2_CURRENT&0x80000000) {
3547                // Set carry out
3548                mAUDIO_2_BORROW_OUT=TRUE;
3549 
3550                // Reload if neccessary
3551                if(mAUDIO_2_ENABLE_RELOAD) {
3552                   mAUDIO_2_CURRENT+=mAUDIO_2_BKUP+1;
3553                   if(mAUDIO_2_CURRENT&0x80000000) mAUDIO_2_CURRENT=0;
3554                } else {
3555                   // Set timer done
3556                   mAUDIO_2_TIMER_DONE=TRUE;
3557                   mAUDIO_2_CURRENT=0;
3558                }
3559 
3560                //
3561                // Update audio circuitry
3562                //
3563                if(mAUDIO_2_BKUP || mAUDIO_2_LINKING)
3564                   mAUDIO_2_WAVESHAPER=GetLfsrNext(mAUDIO_2_WAVESHAPER);
3565 
3566                if(mAUDIO_2_INTEGRATE_ENABLE) {
3567                   SLONG temp=mAUDIO_OUTPUT[2];
3568                   if(mAUDIO_2_WAVESHAPER&0x0001) temp+=mAUDIO_2_VOLUME;
3569                   else temp-=mAUDIO_2_VOLUME;
3570                   if(temp>127) temp=127;
3571                   if(temp<-128) temp=-128;
3572                   mAUDIO_OUTPUT[2]=(SBYTE)temp;
3573                } else {
3574                   if(mAUDIO_2_WAVESHAPER&0x0001) mAUDIO_OUTPUT[2]=mAUDIO_2_VOLUME;
3575                   else mAUDIO_OUTPUT[2]=-mAUDIO_2_VOLUME;
3576                }
3577             } else {
3578                mAUDIO_2_BORROW_OUT=FALSE;
3579             }
3580             // Set carry in as we did a count
3581             mAUDIO_2_BORROW_IN=TRUE;
3582          } else {
3583             // Clear carry in as we didn't count
3584             mAUDIO_2_BORROW_IN=FALSE;
3585             // Clear carry out
3586             mAUDIO_2_BORROW_OUT=FALSE;
3587          }
3588 
3589          // Prediction for next timer event cycle number
3590 
3591          if(mAUDIO_2_LINKING!=7) {
3592             // Sometimes timeupdates can be >2x rollover in which case
3593             // then CURRENT may still be negative and we can use it to
3594             // calc the next timer value, we just want another update ASAP
3595             tmp=(mAUDIO_2_CURRENT&0x80000000)?1:((mAUDIO_2_CURRENT+1)<<divide);
3596             tmp+=gSystemCycleCount;
3597             if(tmp<gNextTimerEvent) {
3598                gNextTimerEvent=tmp;
3599                TRACE_MIKIE1("Update() - AUDIO 2 Set NextTimerEvent = %012d",gNextTimerEvent);
3600             }
3601          }
3602          //					TRACE_MIKIE1("Update() - mAUDIO_2_CURRENT = %012d",mAUDIO_2_CURRENT);
3603          //					TRACE_MIKIE1("Update() - mAUDIO_2_BKUP    = %012d",mAUDIO_2_BKUP);
3604          //					TRACE_MIKIE1("Update() - mAUDIO_2_LASTCNT = %012d",mAUDIO_2_LAST_COUNT);
3605          //					TRACE_MIKIE1("Update() - mAUDIO_2_LINKING = %012d",mAUDIO_2_LINKING);
3606       }
3607 
3608       //
3609       // Audio 3
3610       //
3611       //				if(mAUDIO_3_ENABLE_COUNT && !mAUDIO_3_TIMER_DONE && mAUDIO_3_VOLUME && mAUDIO_3_BKUP)
3612       if(mAUDIO_3_ENABLE_COUNT && (mAUDIO_3_ENABLE_RELOAD || !mAUDIO_3_TIMER_DONE)) {
3613          decval=0;
3614 
3615          if(mAUDIO_3_LINKING==0x07) {
3616             if(mAUDIO_2_BORROW_OUT) decval=1;
3617             mAUDIO_3_LAST_LINK_CARRY=mAUDIO_2_BORROW_OUT;
3618          } else {
3619             // Ordinary clocked mode as opposed to linked mode
3620             // 16MHz clock downto 1us == cyclecount >> 4
3621             divide=(4+mAUDIO_3_LINKING);
3622             decval=(gSystemCycleCount-mAUDIO_3_LAST_COUNT)>>divide;
3623          }
3624 
3625          if(decval) {
3626             mAUDIO_3_LAST_COUNT+=decval<<divide;
3627             mAUDIO_3_CURRENT-=decval;
3628             if(mAUDIO_3_CURRENT&0x80000000) {
3629                // Set carry out
3630                mAUDIO_3_BORROW_OUT=TRUE;
3631 
3632                // Reload if neccessary
3633                if(mAUDIO_3_ENABLE_RELOAD) {
3634                   mAUDIO_3_CURRENT+=mAUDIO_3_BKUP+1;
3635                   if(mAUDIO_3_CURRENT&0x80000000) mAUDIO_3_CURRENT=0;
3636                } else {
3637                   // Set timer done
3638                   mAUDIO_3_TIMER_DONE=TRUE;
3639                   mAUDIO_3_CURRENT=0;
3640                }
3641 
3642                //
3643                // Update audio circuitry
3644                //
3645                if(mAUDIO_3_BKUP || mAUDIO_3_LINKING)
3646                   mAUDIO_3_WAVESHAPER=GetLfsrNext(mAUDIO_3_WAVESHAPER);
3647 
3648                if(mAUDIO_3_INTEGRATE_ENABLE) {
3649                   SLONG temp=mAUDIO_OUTPUT[3];
3650                   if(mAUDIO_3_WAVESHAPER&0x0001) temp+=mAUDIO_3_VOLUME;
3651                   else temp-=mAUDIO_3_VOLUME;
3652                   if(temp>127) temp=127;
3653                   if(temp<-128) temp=-128;
3654                   mAUDIO_OUTPUT[3]=(SBYTE)temp;
3655                } else {
3656                   if(mAUDIO_3_WAVESHAPER&0x0001) mAUDIO_OUTPUT[3]=mAUDIO_3_VOLUME;
3657                   else mAUDIO_OUTPUT[3]=-mAUDIO_3_VOLUME;
3658                }
3659             } else {
3660                mAUDIO_3_BORROW_OUT=FALSE;
3661             }
3662             // Set carry in as we did a count
3663             mAUDIO_3_BORROW_IN=TRUE;
3664          } else {
3665             // Clear carry in as we didn't count
3666             mAUDIO_3_BORROW_IN=FALSE;
3667             // Clear carry out
3668             mAUDIO_3_BORROW_OUT=FALSE;
3669          }
3670 
3671          // Prediction for next timer event cycle number
3672 
3673          if(mAUDIO_3_LINKING!=7) {
3674             // Sometimes timeupdates can be >2x rollover in which case
3675             // then CURRENT may still be negative and we can use it to
3676             // calc the next timer value, we just want another update ASAP
3677             tmp=(mAUDIO_3_CURRENT&0x80000000)?1:((mAUDIO_3_CURRENT+1)<<divide);
3678             tmp+=gSystemCycleCount;
3679             if(tmp<gNextTimerEvent) {
3680                gNextTimerEvent=tmp;
3681                TRACE_MIKIE1("Update() - AUDIO 3 Set NextTimerEvent = %012d",gNextTimerEvent);
3682             }
3683          }
3684          //					TRACE_MIKIE1("Update() - mAUDIO_3_CURRENT = %012d",mAUDIO_3_CURRENT);
3685          //					TRACE_MIKIE1("Update() - mAUDIO_3_BKUP    = %012d",mAUDIO_3_BKUP);
3686          //					TRACE_MIKIE1("Update() - mAUDIO_3_LASTCNT = %012d",mAUDIO_3_LAST_COUNT);
3687          //					TRACE_MIKIE1("Update() - mAUDIO_3_LINKING = %012d",mAUDIO_3_LINKING);
3688       }
3689 
3690       UpdateSound();
3691    }
3692 
3693    //			if(gSystemCycleCount==gNextTimerEvent) gError->Warning("CMikie::Update() - gSystemCycleCount==gNextTimerEvent, system lock likely");
3694    //			TRACE_MIKIE1("Update() - NextTimerEvent = %012d",gNextTimerEvent);
3695 
3696    // Update system IRQ status as a result of timer activity
3697    gSystemIRQ=(mTimerStatusFlags)?true:false;
3698    if(gSystemIRQ && gSystemCPUSleep) { ClearCPUSleep(); /*puts("ARLARM"); */ }
3699    //else if(gSuzieDoneTime) SetCPUSleep();
3700 
3701    // Now all the timer updates are done we can increment the system
3702    // counter for any work done within the Update() function, gSystemCycleCounter
3703    // cannot be updated until this point otherwise it screws up the counters.
3704    gSystemCycleCount+=mikie_work_done;
3705 }
3706 
UpdateSound(void)3707 inline void CMikie::UpdateSound(void)
3708 {
3709    int cur_lsample = 0;
3710    int cur_rsample = 0;
3711    int x;
3712 
3713    for(x = 0; x < 4; x++){
3714       /// Assumption (seems there is no documentation for the Attenuation registers)
3715       /// a) they are linear from $0 to $f - checked!
3716       /// b) an attenuation of $0 is equal to channel OFF (bits in mSTEREO not set) - checked!
3717       /// c) an attenuation of $f is NOT equal to no attenuation (bits in PAN not set), $10 would be - checked!
3718       /// These assumptions can only checked with an oszilloscope... - done
3719       /// the values stored in mSTEREO are NOT bit-inverted ...
3720       /// mSTEREO was found to be set like that already (why?), but unused
3721 
3722       if(!(mSTEREO & (0x10 << x))) {
3723          if(mPAN & (0x10 << x))
3724             cur_lsample += (mAUDIO_OUTPUT[x]*(mAUDIO_ATTEN[x]&0xF0))/(16*16); /// NOT /15*16 see remark above
3725          else
3726             cur_lsample += mAUDIO_OUTPUT[x];
3727       }
3728       if(!(mSTEREO & (0x01 << x))) {
3729          if(mPAN & (0x01 << x))
3730             cur_rsample += (mAUDIO_OUTPUT[x]*(mAUDIO_ATTEN[x]&0x0F))/16; /// NOT /15 see remark above
3731          else
3732             cur_rsample += mAUDIO_OUTPUT[x];
3733       }
3734    }
3735 
3736    static int last_lsample = 0;
3737    static int last_rsample = 0;
3738 
3739    if(cur_lsample != last_lsample) {
3740       miksynth.offset_inline((gSystemCycleCount - gAudioLastUpdateCycle) / 4, cur_lsample - last_lsample, mikbuf.left());
3741       last_lsample = cur_lsample;
3742    }
3743 
3744    if(cur_rsample != last_rsample) {
3745       miksynth.offset_inline((gSystemCycleCount - gAudioLastUpdateCycle) / 4, cur_rsample - last_rsample, mikbuf.right());
3746       last_rsample = cur_rsample;
3747    }
3748 }
3749