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