Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/lynx/mikie.cpp
2 views
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 "system.h"
54
#include "mikie.h"
55
#include "lynxdef.h"
56
57
/*
58
void CMikie::BlowOut()
59
{
60
C6502_REGS regs;
61
mSystem.GetRegs(regs);
62
//sprintf(addr,"Runtime Error - System Halted\nCMikie::Poke() - Read/Write to counter clocks at PC=$%04x.",regs.PC);
63
//gError->Warning(addr);
64
gSystemHalt=TRUE;
65
}
66
*/
67
68
CMikie::CMikie(CSystem& parent)
69
:mSystem(parent)
70
{
71
TRACE_MIKIE0("CMikie()");
72
73
int loop;
74
for(loop=0;loop<16;loop++) mPalette[loop].Index=loop;
75
76
DisplaySetAttributes();
77
78
Reset();
79
}
80
81
CMikie::~CMikie()
82
{
83
TRACE_MIKIE0("~CMikie()");
84
}
85
86
void CMikie::SetCPUSleep() { mSystem.gSystemCPUSleep = true; }
87
void CMikie::ClearCPUSleep() { mSystem.gSystemCPUSleep = false; }
88
89
90
void CMikie::Reset()
91
{
92
TRACE_MIKIE0("Reset()");
93
94
mAudioInputComparator=FALSE; // Initialises to unknown
95
mDisplayAddress=0x00; // Initialises to unknown
96
mLynxLine=0;
97
mLynxLineDMACounter=0;
98
mLynxAddr=0;
99
100
mpDisplayCurrentLine = 0;
101
102
mTimerStatusFlags=0x00; // Initialises to ZERO, i.e No IRQ's
103
mTimerInterruptMask=0x00;
104
105
mpRamPointer=mSystem.GetRamPointer(); // Fetch pointer to system RAM
106
107
mTIM_0_BKUP=0;
108
mTIM_0_ENABLE_RELOAD=0;
109
mTIM_0_ENABLE_COUNT=0;
110
mTIM_0_LINKING=0;
111
mTIM_0_CURRENT=0;
112
mTIM_0_TIMER_DONE=0;
113
mTIM_0_LAST_CLOCK=0;
114
mTIM_0_BORROW_IN=0;
115
mTIM_0_BORROW_OUT=0;
116
mTIM_0_LAST_LINK_CARRY=0;
117
mTIM_0_LAST_COUNT=0;
118
119
mTIM_1_BKUP=0;
120
mTIM_1_ENABLE_RELOAD=0;
121
mTIM_1_ENABLE_COUNT=0;
122
mTIM_1_LINKING=0;
123
mTIM_1_CURRENT=0;
124
mTIM_1_TIMER_DONE=0;
125
mTIM_1_LAST_CLOCK=0;
126
mTIM_1_BORROW_IN=0;
127
mTIM_1_BORROW_OUT=0;
128
mTIM_1_LAST_LINK_CARRY=0;
129
mTIM_1_LAST_COUNT=0;
130
131
mTIM_2_BKUP=0;
132
mTIM_2_ENABLE_RELOAD=0;
133
mTIM_2_ENABLE_COUNT=0;
134
mTIM_2_LINKING=0;
135
mTIM_2_CURRENT=0;
136
mTIM_2_TIMER_DONE=0;
137
mTIM_2_LAST_CLOCK=0;
138
mTIM_2_BORROW_IN=0;
139
mTIM_2_BORROW_OUT=0;
140
mTIM_2_LAST_LINK_CARRY=0;
141
mTIM_2_LAST_COUNT=0;
142
143
mTIM_3_BKUP=0;
144
mTIM_3_ENABLE_RELOAD=0;
145
mTIM_3_ENABLE_COUNT=0;
146
mTIM_3_LINKING=0;
147
mTIM_3_CURRENT=0;
148
mTIM_3_TIMER_DONE=0;
149
mTIM_3_LAST_CLOCK=0;
150
mTIM_3_BORROW_IN=0;
151
mTIM_3_BORROW_OUT=0;
152
mTIM_3_LAST_LINK_CARRY=0;
153
mTIM_3_LAST_COUNT=0;
154
155
mTIM_4_BKUP=0;
156
mTIM_4_ENABLE_RELOAD=0;
157
mTIM_4_ENABLE_COUNT=0;
158
mTIM_4_LINKING=0;
159
mTIM_4_CURRENT=0;
160
mTIM_4_TIMER_DONE=0;
161
mTIM_4_LAST_CLOCK=0;
162
mTIM_4_BORROW_IN=0;
163
mTIM_4_BORROW_OUT=0;
164
mTIM_4_LAST_LINK_CARRY=0;
165
mTIM_4_LAST_COUNT=0;
166
167
mTIM_5_BKUP=0;
168
mTIM_5_ENABLE_RELOAD=0;
169
mTIM_5_ENABLE_COUNT=0;
170
mTIM_5_LINKING=0;
171
mTIM_5_CURRENT=0;
172
mTIM_5_TIMER_DONE=0;
173
mTIM_5_LAST_CLOCK=0;
174
mTIM_5_BORROW_IN=0;
175
mTIM_5_BORROW_OUT=0;
176
mTIM_5_LAST_LINK_CARRY=0;
177
mTIM_5_LAST_COUNT=0;
178
179
mTIM_6_BKUP=0;
180
mTIM_6_ENABLE_RELOAD=0;
181
mTIM_6_ENABLE_COUNT=0;
182
mTIM_6_LINKING=0;
183
mTIM_6_CURRENT=0;
184
mTIM_6_TIMER_DONE=0;
185
mTIM_6_LAST_CLOCK=0;
186
mTIM_6_BORROW_IN=0;
187
mTIM_6_BORROW_OUT=0;
188
mTIM_6_LAST_LINK_CARRY=0;
189
mTIM_6_LAST_COUNT=0;
190
191
mTIM_7_BKUP=0;
192
mTIM_7_ENABLE_RELOAD=0;
193
mTIM_7_ENABLE_COUNT=0;
194
mTIM_7_LINKING=0;
195
mTIM_7_CURRENT=0;
196
mTIM_7_TIMER_DONE=0;
197
mTIM_7_LAST_CLOCK=0;
198
mTIM_7_BORROW_IN=0;
199
mTIM_7_BORROW_OUT=0;
200
mTIM_7_LAST_LINK_CARRY=0;
201
mTIM_7_LAST_COUNT=0;
202
203
for(int y = 0; y < 4; y++)
204
{
205
mAUDIO_BKUP[y]=0;
206
mAUDIO_ENABLE_RELOAD[y]=0;
207
mAUDIO_ENABLE_COUNT[y]=0;
208
mAUDIO_LINKING[y]=0;
209
mAUDIO_CURRENT[y]=0;
210
mAUDIO_TIMER_DONE[y]=0;
211
mAUDIO_LAST_CLOCK[y]=0;
212
mAUDIO_BORROW_IN[y]=0;
213
mAUDIO_BORROW_OUT[y]=0;
214
mAUDIO_LAST_LINK_CARRY[y]=0;
215
mAUDIO_LAST_COUNT[y]=0;
216
mAUDIO_VOLUME[y]=0;
217
mAUDIO_INTEGRATE_ENABLE[y]=0;
218
mAUDIO_WAVESHAPER[y]=0;
219
220
mAUDIO_OUTPUT[y] = 0;
221
}
222
mSTEREO=0xff; // xored! All channels enabled
223
mPAN=0x00; // all channels panning OFF
224
mAUDIO_ATTEN[0]=0xff; // Full volume
225
mAUDIO_ATTEN[1]=0xff;
226
mAUDIO_ATTEN[2]=0xff;
227
mAUDIO_ATTEN[3]=0xff;
228
229
// Start with an empty palette
230
231
for(int loop=0;loop<16;loop++)
232
{
233
mPalette[loop].Index=loop;
234
}
235
236
// Initialise IODAT register
237
238
mIODAT=0x00;
239
mIODIR=0x00;
240
mIODAT_REST_SIGNAL=0x00;
241
242
// Initialise display control register vars
243
mDISPCTL_DMAEnable=FALSE;
244
mDISPCTL_Flip=FALSE;
245
mDISPCTL_FourColour=0;
246
mDISPCTL_Colour=0;
247
248
// Initialise the UART variables
249
mUART_RX_IRQ_ENABLE=0;
250
mUART_TX_IRQ_ENABLE=0;
251
252
mUART_TX_COUNTDOWN=UART_TX_INACTIVE;
253
mUART_RX_COUNTDOWN=UART_RX_INACTIVE;
254
255
mUART_Rx_input_ptr=0;
256
mUART_Rx_output_ptr=0;
257
mUART_Rx_waiting=0;
258
mUART_Rx_framing_error=0;
259
mUART_Rx_overun_error=0;
260
261
mUART_SENDBREAK=0;
262
mUART_TX_DATA=0;
263
mUART_RX_DATA=0;
264
mUART_RX_READY=0;
265
266
mUART_PARITY_ENABLE=0;
267
mUART_PARITY_EVEN=0;
268
}
269
270
uint32 CMikie::GetLfsrNext(uint32 current)
271
{
272
// The table is built thus:
273
// Bits 0-11 LFSR (12 Bits)
274
// Bits 12-20 Feedback switches (9 Bits)
275
// (Order = 7,0,1,2,3,4,5,10,11)
276
// Order is mangled to make peek/poke easier as
277
// bit 7 is in a seperate register
278
//
279
// Total 21 bits = 2MWords @ 4 Bytes/Word = 8MB !!!!!
280
//
281
// If the index is a combination of Current LFSR+Feedback the
282
// table will give the next value.
283
284
uint32 switches,lfsr,next,swloop,result;
285
static const uint32 switchbits[9]={7,0,1,2,3,4,5,10,11};
286
287
switches=current>>12;
288
lfsr=current&0xfff;
289
result=0;
290
for(swloop=0;swloop<9;swloop++)
291
{
292
if((switches>>swloop)&0x001) result^=(lfsr>>switchbits[swloop])&0x001;
293
}
294
result=(result)?0:1;
295
next=(switches<<12)|((lfsr<<1)&0xffe)|result;
296
return next;
297
}
298
299
void CMikie::ComLynxCable(int status)
300
{
301
mUART_CABLE_PRESENT=status;
302
}
303
304
void CMikie::ComLynxRxData(int data)
305
{
306
TRACE_MIKIE1("ComLynxRxData() - Received %04x",data);
307
// Copy over the data
308
if(mUART_Rx_waiting<UART_MAX_RX_QUEUE)
309
{
310
// Trigger incoming receive IF none waiting otherwise
311
// we NEVER get to receive it!!!
312
if(!mUART_Rx_waiting) mUART_RX_COUNTDOWN=UART_RX_TIME_PERIOD;
313
314
// Receive the byte
315
mUART_Rx_input_queue[mUART_Rx_input_ptr]=data;
316
mUART_Rx_input_ptr = (mUART_Rx_input_ptr + 1) % UART_MAX_RX_QUEUE;
317
mUART_Rx_waiting++;
318
TRACE_MIKIE2("ComLynxRxData() - input ptr=%02d waiting=%02d",mUART_Rx_input_ptr,mUART_Rx_waiting);
319
}
320
else
321
{
322
TRACE_MIKIE0("ComLynxRxData() - UART RX Overun");
323
}
324
}
325
326
void CMikie::ComLynxTxLoopback(int data)
327
{
328
TRACE_MIKIE1("ComLynxTxLoopback() - Received %04x",data);
329
330
if(mUART_Rx_waiting<UART_MAX_RX_QUEUE)
331
{
332
// Trigger incoming receive IF none waiting otherwise
333
// we NEVER get to receive it!!!
334
if(!mUART_Rx_waiting) mUART_RX_COUNTDOWN=UART_RX_TIME_PERIOD;
335
336
// Receive the byte - INSERT into front of queue
337
mUART_Rx_output_ptr = (mUART_Rx_output_ptr - 1) % UART_MAX_RX_QUEUE;
338
mUART_Rx_input_queue[mUART_Rx_output_ptr]=data;
339
mUART_Rx_waiting++;
340
TRACE_MIKIE2("ComLynxTxLoopback() - input ptr=%02d waiting=%02d",mUART_Rx_input_ptr,mUART_Rx_waiting);
341
}
342
else
343
{
344
TRACE_MIKIE0("ComLynxTxLoopback() - UART RX Overun");
345
}
346
}
347
348
void CMikie::ComLynxTxCallback(void (*function)(int data,uint32 objref),uint32 objref)
349
{
350
mpUART_TX_CALLBACK=function;
351
mUART_TX_CALLBACK_OBJECT=objref;
352
}
353
354
355
void CMikie::DisplaySetAttributes()
356
{
357
//
358
// Calculate the colour lookup tabes for the relevant mode
359
//
360
TPALETTE Spot;
361
362
for(Spot.Index=0;Spot.Index<4096;Spot.Index++)
363
{
364
mColourMap[Spot.Index] =
365
0xff000000 |
366
(Spot.Colours.Red * 15 + 30) << 16 |
367
(Spot.Colours.Green * 15 + 30) << 8 |
368
(Spot.Colours.Blue * 15 + 30);
369
}
370
}
371
372
void CMikie::BlankLineSurface()
373
{
374
uint32* bitmap_tmp = framebuffer + mpDisplayCurrentLine * SCREEN_WIDTH;
375
for (int i = 0; i < SCREEN_WIDTH; i++)
376
bitmap_tmp[i] = 0xff000000;
377
}
378
379
void CMikie::CopyLineSurface()
380
{
381
uint32* bitmap_tmp = framebuffer + mpDisplayCurrentLine * SCREEN_WIDTH;
382
383
for (int loop = 0; loop < SCREEN_WIDTH / 2; loop++)
384
{
385
uint32 source = mpRamPointer[(uint16)mLynxAddr];
386
if(mDISPCTL_Flip)
387
{
388
mLynxAddr--;
389
*bitmap_tmp=mColourMap[mPalette[source&0x0f].Index];
390
bitmap_tmp++;
391
*bitmap_tmp=mColourMap[mPalette[source>>4].Index];
392
bitmap_tmp++;
393
}
394
else
395
{
396
mLynxAddr++;
397
*bitmap_tmp = mColourMap[mPalette[source>>4].Index];
398
bitmap_tmp++;
399
*bitmap_tmp = mColourMap[mPalette[source&0x0f].Index];
400
bitmap_tmp++;
401
}
402
}
403
}
404
405
uint32 CMikie::DisplayRenderLine()
406
{
407
uint32 work_done=0;
408
409
if(!mDISPCTL_DMAEnable) return 0;
410
// if(mLynxLine&0x80000000) return 0;
411
412
// Set the timer interrupt flag
413
if(mTimerInterruptMask&0x01)
414
{
415
TRACE_MIKIE0("Update() - TIMER0 IRQ Triggered (Line Timer)");
416
mTimerStatusFlags|=0x01;
417
}
418
419
// Logic says it should be 101 but testing on an actual lynx shows the rest
420
// persiod is between lines 102,101,100 with the new line being latched at
421
// the beginning of count==99 hence the code below !!
422
423
// Emulate REST signal
424
if(mLynxLine==mTIM_2_BKUP-2 || mLynxLine==mTIM_2_BKUP-3 || mLynxLine==mTIM_2_BKUP-4) mIODAT_REST_SIGNAL=TRUE; else mIODAT_REST_SIGNAL=FALSE;
425
426
if(mLynxLine==(mTIM_2_BKUP-3))
427
{
428
if(mDISPCTL_Flip)
429
{
430
mLynxAddr=mDisplayAddress&0xfffc;
431
mLynxAddr+=3;
432
}
433
else
434
{
435
mLynxAddr=mDisplayAddress&0xfffc;
436
}
437
// Trigger line rending to start
438
mLynxLineDMACounter=102;
439
}
440
441
// Decrement line counter logic
442
if(mLynxLine) mLynxLine--;
443
444
// Do 102 lines, nothing more, less is OK.
445
if(mLynxLineDMACounter)
446
{
447
// TRACE_MIKIE1("Update() - Screen DMA, line %03d",line_count);
448
mLynxLineDMACounter--;
449
450
// Cycle hit for a 80 RAM access in rendering a line
451
work_done+=80*DMA_RDWR_CYC;
452
453
// Mikie screen DMA can only see the system RAM....
454
// (Step through bitmap, line at a time)
455
456
if (mpDisplayCurrentLine < 102)
457
{
458
CopyLineSurface();
459
}
460
else
461
{
462
// ??
463
printf("Lynx Line Overflow: %d\n", mpDisplayCurrentLine);
464
}
465
466
mpDisplayCurrentLine++;
467
}
468
return work_done;
469
}
470
471
uint32 CMikie::DisplayEndOfFrame()
472
{
473
// Stop any further line rendering
474
mLynxLineDMACounter=0;
475
mLynxLine=mTIM_2_BKUP;
476
477
// Set the timer status flag
478
if(mTimerInterruptMask&0x04)
479
{
480
TRACE_MIKIE0("Update() - TIMER2 IRQ Triggered (Frame Timer)");
481
mTimerStatusFlags|=0x04;
482
}
483
484
// blank remaining lines and blit to output
485
while (mpDisplayCurrentLine < 102)
486
{
487
BlankLineSurface();
488
mpDisplayCurrentLine++;
489
}
490
491
mSystem.Blit(framebuffer);
492
493
mpDisplayCurrentLine = 0;
494
return 0;
495
}
496
497
// Peek/Poke memory handlers
498
499
void CMikie::Poke(uint32 addr,uint8 data)
500
{
501
/* Sound register area */
502
if(addr >= 0xFD20 && addr <= 0xFD3F)
503
{
504
int which = (addr - 0xFD20) >> 3; // Each channel gets 8 ports/registers
505
switch(addr & 0x7)
506
{
507
case (AUD0VOL&0x7):
508
mAUDIO_VOLUME[which]=(int8)data;
509
TRACE_MIKIE2("Poke(AUD0VOL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
510
CombobulateSound(mSystem.gSystemCycleCount - startTS);
511
break;
512
case (AUD0SHFTFB&0x7):
513
mAUDIO_WAVESHAPER[which]&=0x001fff;
514
mAUDIO_WAVESHAPER[which]|=(uint32)data<<13;
515
TRACE_MIKIE2("Poke(AUD0SHFTB,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
516
CombobulateSound(mSystem.gSystemCycleCount - startTS);
517
break;
518
case (AUD0OUTVAL&0x7):
519
mAUDIO_OUTPUT[which]=data;
520
TRACE_MIKIE2("Poke(AUD0OUTVAL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
521
CombobulateSound(mSystem.gSystemCycleCount - startTS);
522
break;
523
case (AUD0L8SHFT&0x7):
524
mAUDIO_WAVESHAPER[which]&=0x1fff00;
525
mAUDIO_WAVESHAPER[which]|=data;
526
TRACE_MIKIE2("Poke(AUD0L8SHFT,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
527
CombobulateSound(mSystem.gSystemCycleCount - startTS);
528
break;
529
case (AUD0TBACK&0x7):
530
mAUDIO_BKUP[which]=data;
531
TRACE_MIKIE2("Poke(AUD0TBACK,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
532
CombobulateSound(mSystem.gSystemCycleCount - startTS);
533
break;
534
case (AUD0CTL&0x7):
535
mAUDIO_ENABLE_RELOAD[which]=data&0x10;
536
mAUDIO_ENABLE_COUNT[which]=data&0x08;
537
mAUDIO_LINKING[which]=data&0x07;
538
mAUDIO_INTEGRATE_ENABLE[which]=data&0x20;
539
if(data&0x40) mAUDIO_TIMER_DONE[which]=0;
540
mAUDIO_WAVESHAPER[which]&=0x1fefff;
541
mAUDIO_WAVESHAPER[which]|=(data&0x80)?0x001000:0x000000;
542
if(data&0x48)
543
{
544
mAUDIO_LAST_COUNT[which]=mSystem.gSystemCycleCount;
545
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
546
}
547
TRACE_MIKIE2("Poke(AUD0CTL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
548
CombobulateSound(mSystem.gSystemCycleCount - startTS);
549
break;
550
case (AUD0COUNT&0x7):
551
mAUDIO_CURRENT[which]=data;
552
TRACE_MIKIE2("Poke(AUD0COUNT,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
553
CombobulateSound(mSystem.gSystemCycleCount - startTS);
554
break;
555
case (AUD0MISC&0x7):
556
mAUDIO_WAVESHAPER[which]&=0x1ff0ff;
557
mAUDIO_WAVESHAPER[which]|=(data&0xf0)<<4;
558
mAUDIO_BORROW_IN[which]=data&0x02;
559
mAUDIO_BORROW_OUT[which]=data&0x01;
560
mAUDIO_LAST_CLOCK[which]=data&0x04;
561
TRACE_MIKIE2("Poke(AUD0MISC,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
562
CombobulateSound(mSystem.gSystemCycleCount - startTS);
563
break;
564
}
565
}
566
else switch(addr&0xff)
567
{
568
case (TIM0BKUP&0xff):
569
mTIM_0_BKUP=data;
570
TRACE_MIKIE2("Poke(TIM0BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
571
break;
572
case (TIM1BKUP&0xff):
573
mTIM_1_BKUP=data;
574
TRACE_MIKIE2("Poke(TIM1BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
575
break;
576
case (TIM2BKUP&0xff):
577
mTIM_2_BKUP=data;
578
TRACE_MIKIE2("Poke(TIM2BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
579
break;
580
case (TIM3BKUP&0xff):
581
mTIM_3_BKUP=data;
582
TRACE_MIKIE2("Poke(TIM3BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
583
break;
584
case (TIM4BKUP&0xff):
585
mTIM_4_BKUP=data;
586
TRACE_MIKIE2("Poke(TIM4BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
587
break;
588
case (TIM5BKUP&0xff):
589
mTIM_5_BKUP=data;
590
TRACE_MIKIE2("Poke(TIM5BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
591
break;
592
case (TIM6BKUP&0xff):
593
mTIM_6_BKUP=data;
594
TRACE_MIKIE2("Poke(TIM6BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
595
break;
596
case (TIM7BKUP&0xff):
597
mTIM_7_BKUP=data;
598
TRACE_MIKIE2("Poke(TIM7BKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
599
break;
600
601
602
case (TIM0CTLA&0xff):
603
mTimerInterruptMask&=(0x01^0xff);
604
mTimerInterruptMask|=(data&0x80)?0x01:0x00;
605
mTIM_0_ENABLE_RELOAD=data&0x10;
606
mTIM_0_ENABLE_COUNT=data&0x08;
607
mTIM_0_LINKING=data&0x07;
608
if(data&0x40) mTIM_0_TIMER_DONE=0;
609
if(data&0x48)
610
{
611
mTIM_0_LAST_COUNT=mSystem.gSystemCycleCount;
612
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
613
}
614
TRACE_MIKIE2("Poke(TIM0CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
615
break;
616
case (TIM1CTLA&0xff):
617
mTimerInterruptMask&=(0x02^0xff);
618
mTimerInterruptMask|=(data&0x80)?0x02:0x00;
619
mTIM_1_ENABLE_RELOAD=data&0x10;
620
mTIM_1_ENABLE_COUNT=data&0x08;
621
mTIM_1_LINKING=data&0x07;
622
if(data&0x40) mTIM_1_TIMER_DONE=0;
623
if(data&0x48)
624
{
625
mTIM_1_LAST_COUNT=mSystem.gSystemCycleCount;
626
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
627
}
628
TRACE_MIKIE2("Poke(TIM1CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
629
break;
630
case (TIM2CTLA&0xff):
631
mTimerInterruptMask&=(0x04^0xff);
632
mTimerInterruptMask|=(data&0x80)?0x04:0x00;
633
mTIM_2_ENABLE_RELOAD=data&0x10;
634
mTIM_2_ENABLE_COUNT=data&0x08;
635
mTIM_2_LINKING=data&0x07;
636
if(data&0x40) mTIM_2_TIMER_DONE=0;
637
if(data&0x48)
638
{
639
mTIM_2_LAST_COUNT=mSystem.gSystemCycleCount;
640
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
641
}
642
TRACE_MIKIE2("Poke(TIM2CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
643
break;
644
case (TIM3CTLA&0xff):
645
mTimerInterruptMask&=(0x08^0xff);
646
mTimerInterruptMask|=(data&0x80)?0x08:0x00;
647
mTIM_3_ENABLE_RELOAD=data&0x10;
648
mTIM_3_ENABLE_COUNT=data&0x08;
649
mTIM_3_LINKING=data&0x07;
650
if(data&0x40) mTIM_3_TIMER_DONE=0;
651
if(data&0x48)
652
{
653
mTIM_3_LAST_COUNT=mSystem.gSystemCycleCount;
654
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
655
}
656
TRACE_MIKIE2("Poke(TIM3CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
657
break;
658
case (TIM4CTLA&0xff):
659
// Timer 4 can never generate interrupts as its timer output is used
660
// to drive the UART clock generator
661
mTIM_4_ENABLE_RELOAD=data&0x10;
662
mTIM_4_ENABLE_COUNT=data&0x08;
663
mTIM_4_LINKING=data&0x07;
664
if(data&0x40) mTIM_4_TIMER_DONE=0;
665
if(data&0x48)
666
{
667
mTIM_4_LAST_COUNT=mSystem.gSystemCycleCount;
668
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
669
}
670
TRACE_MIKIE2("Poke(TIM4CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
671
break;
672
case (TIM5CTLA&0xff):
673
mTimerInterruptMask&=(0x20^0xff);
674
mTimerInterruptMask|=(data&0x80)?0x20:0x00;
675
mTIM_5_ENABLE_RELOAD=data&0x10;
676
mTIM_5_ENABLE_COUNT=data&0x08;
677
mTIM_5_LINKING=data&0x07;
678
if(data&0x40) mTIM_5_TIMER_DONE=0;
679
if(data&0x48)
680
{
681
mTIM_5_LAST_COUNT=mSystem.gSystemCycleCount;
682
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
683
}
684
TRACE_MIKIE2("Poke(TIM5CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
685
break;
686
case (TIM6CTLA&0xff):
687
mTimerInterruptMask&=(0x40^0xff);
688
mTimerInterruptMask|=(data&0x80)?0x40:0x00;
689
mTIM_6_ENABLE_RELOAD=data&0x10;
690
mTIM_6_ENABLE_COUNT=data&0x08;
691
mTIM_6_LINKING=data&0x07;
692
if(data&0x40) mTIM_6_TIMER_DONE=0;
693
if(data&0x48)
694
{
695
mTIM_6_LAST_COUNT=mSystem.gSystemCycleCount;
696
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
697
}
698
TRACE_MIKIE2("Poke(TIM6CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
699
break;
700
case (TIM7CTLA&0xff):
701
mTimerInterruptMask&=(0x80^0xff);
702
mTimerInterruptMask|=(data&0x80)?0x80:0x00;
703
mTIM_7_ENABLE_RELOAD=data&0x10;
704
mTIM_7_ENABLE_COUNT=data&0x08;
705
mTIM_7_LINKING=data&0x07;
706
if(data&0x40) mTIM_7_TIMER_DONE=0;
707
if(data&0x48)
708
{
709
mTIM_7_LAST_COUNT=mSystem.gSystemCycleCount;
710
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
711
}
712
TRACE_MIKIE2("Poke(TIM7CTLA,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
713
break;
714
715
716
case (TIM0CNT&0xff):
717
mTIM_0_CURRENT=data;
718
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
719
TRACE_MIKIE2("Poke(TIM0CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
720
break;
721
case (TIM1CNT&0xff):
722
mTIM_1_CURRENT=data;
723
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
724
TRACE_MIKIE2("Poke(TIM1CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
725
break;
726
case (TIM2CNT&0xff):
727
mTIM_2_CURRENT=data;
728
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
729
TRACE_MIKIE2("Poke(TIM2CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
730
break;
731
case (TIM3CNT&0xff):
732
mTIM_3_CURRENT=data;
733
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
734
TRACE_MIKIE2("Poke(TIM3CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
735
break;
736
case (TIM4CNT&0xff):
737
mTIM_4_CURRENT=data;
738
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
739
TRACE_MIKIE2("Poke(TIM4CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
740
break;
741
case (TIM5CNT&0xff):
742
mTIM_5_CURRENT=data;
743
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
744
TRACE_MIKIE2("Poke(TIM5CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
745
break;
746
case (TIM6CNT&0xff):
747
mTIM_6_CURRENT=data;
748
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
749
TRACE_MIKIE2("Poke(TIM6CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
750
break;
751
case (TIM7CNT&0xff):
752
mTIM_7_CURRENT=data;
753
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
754
TRACE_MIKIE2("Poke(TIM7CNT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
755
break;
756
757
case (TIM0CTLB&0xff):
758
mTIM_0_TIMER_DONE=data&0x08;
759
mTIM_0_LAST_CLOCK=data&0x04;
760
mTIM_0_BORROW_IN=data&0x02;
761
mTIM_0_BORROW_OUT=data&0x01;
762
TRACE_MIKIE2("Poke(TIM0CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
763
// BlowOut();
764
break;
765
case (TIM1CTLB&0xff):
766
mTIM_1_TIMER_DONE=data&0x08;
767
mTIM_1_LAST_CLOCK=data&0x04;
768
mTIM_1_BORROW_IN=data&0x02;
769
mTIM_1_BORROW_OUT=data&0x01;
770
TRACE_MIKIE2("Poke(TIM1CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
771
// BlowOut();
772
break;
773
case (TIM2CTLB&0xff):
774
mTIM_2_TIMER_DONE=data&0x08;
775
mTIM_2_LAST_CLOCK=data&0x04;
776
mTIM_2_BORROW_IN=data&0x02;
777
mTIM_2_BORROW_OUT=data&0x01;
778
TRACE_MIKIE2("Poke(TIM2CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
779
// BlowOut();
780
break;
781
case (TIM3CTLB&0xff):
782
mTIM_3_TIMER_DONE=data&0x08;
783
mTIM_3_LAST_CLOCK=data&0x04;
784
mTIM_3_BORROW_IN=data&0x02;
785
mTIM_3_BORROW_OUT=data&0x01;
786
TRACE_MIKIE2("Poke(TIM3CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
787
// BlowOut();
788
break;
789
case (TIM4CTLB&0xff):
790
mTIM_4_TIMER_DONE=data&0x08;
791
mTIM_4_LAST_CLOCK=data&0x04;
792
mTIM_4_BORROW_IN=data&0x02;
793
mTIM_4_BORROW_OUT=data&0x01;
794
TRACE_MIKIE2("Poke(TIM4CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
795
// BlowOut();
796
break;
797
case (TIM5CTLB&0xff):
798
mTIM_5_TIMER_DONE=data&0x08;
799
mTIM_5_LAST_CLOCK=data&0x04;
800
mTIM_5_BORROW_IN=data&0x02;
801
mTIM_5_BORROW_OUT=data&0x01;
802
TRACE_MIKIE2("Poke(TIM5CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
803
// BlowOut();
804
break;
805
case (TIM6CTLB&0xff):
806
mTIM_6_TIMER_DONE=data&0x08;
807
mTIM_6_LAST_CLOCK=data&0x04;
808
mTIM_6_BORROW_IN=data&0x02;
809
mTIM_6_BORROW_OUT=data&0x01;
810
TRACE_MIKIE2("Poke(TIM6CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
811
// BlowOut();
812
break;
813
case (TIM7CTLB&0xff):
814
mTIM_7_TIMER_DONE=data&0x08;
815
mTIM_7_LAST_CLOCK=data&0x04;
816
mTIM_7_BORROW_IN=data&0x02;
817
mTIM_7_BORROW_OUT=data&0x01;
818
TRACE_MIKIE2("Poke(TIM7CTLB ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
819
// BlowOut();
820
break;
821
822
case (ATTEN_A&0xff):
823
mAUDIO_ATTEN[0] = data;
824
TRACE_MIKIE2("Poke(ATTEN_A ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
825
CombobulateSound(mSystem.gSystemCycleCount - startTS);
826
break;
827
case (ATTEN_B&0xff):
828
mAUDIO_ATTEN[1] = data;
829
TRACE_MIKIE2("Poke(ATTEN_B ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
830
CombobulateSound(mSystem.gSystemCycleCount - startTS);
831
break;
832
case (ATTEN_C&0xff):
833
mAUDIO_ATTEN[2] = data;
834
TRACE_MIKIE2("Poke(ATTEN_C ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
835
CombobulateSound(mSystem.gSystemCycleCount - startTS);
836
break;
837
case (ATTEN_D&0xff):
838
mAUDIO_ATTEN[3] = data;
839
TRACE_MIKIE2("Poke(ATTEN_D ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
840
CombobulateSound(mSystem.gSystemCycleCount - startTS);
841
break;
842
case (MPAN&0xff):
843
TRACE_MIKIE2("Poke(MPAN ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
844
mPAN = data;
845
CombobulateSound(mSystem.gSystemCycleCount - startTS);
846
break;
847
848
case (MSTEREO&0xff):
849
TRACE_MIKIE2("Poke(MSTEREO ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
850
data^=0xff;
851
mSTEREO=data;
852
CombobulateSound(mSystem.gSystemCycleCount - startTS);
853
break;
854
855
case (INTRST&0xff):
856
data^=0xff;
857
mTimerStatusFlags&=data;
858
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
859
TRACE_MIKIE2("Poke(INTRST ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
860
break;
861
862
case (INTSET&0xff):
863
TRACE_MIKIE2("Poke(INTSET ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
864
mTimerStatusFlags|=data;
865
mSystem.gNextTimerEvent=mSystem.gSystemCycleCount;
866
break;
867
868
case (SYSCTL1&0xff):
869
TRACE_MIKIE2("Poke(SYSCTL1 ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
870
if(!(data&0x02))
871
{
872
C6502_REGS regs;
873
mSystem.GetRegs(regs);
874
TRACE_MIKIE1("Runtime Alert - System Halted\nCMikie::Poke(SYSCTL1) - Lynx power down occured at PC=$%04x.\nResetting system.",regs.PC);
875
// can't reset in the middle of a frame, screws the timekeeping; and it doesn't make a difference anyway
876
// mSystem.Reset();
877
mSystem.gSystemHalt=TRUE;
878
}
879
mSystem.CartAddressStrobe((data&0x01)?TRUE:FALSE);
880
break;
881
882
case (MIKEYSREV&0xff):
883
TRACE_MIKIE2("Poke(MIKEYSREV,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
884
break;
885
886
case (IODIR&0xff):
887
TRACE_MIKIE2("Poke(IODIR ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
888
mIODIR=data;
889
break;
890
891
case (IODAT&0xff):
892
TRACE_MIKIE2("Poke(IODAT ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
893
mIODAT=data;
894
mSystem.CartAddressData((mIODAT&0x02)?TRUE:FALSE);
895
// Enable cart writes to BANK1 on AUDIN if AUDIN is set to output
896
if(mIODIR&0x10) mSystem.mCart->mWriteEnableBank1=(mIODAT&0x10)?true:false;
897
break;
898
899
case (SERCTL&0xff):
900
TRACE_MIKIE2("Poke(SERCTL ,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
901
mUART_TX_IRQ_ENABLE=(data&0x80)?true:false;
902
mUART_RX_IRQ_ENABLE=(data&0x40)?true:false;
903
mUART_PARITY_ENABLE=(data&0x10)?true:false;
904
mUART_SENDBREAK=data&0x02;
905
mUART_PARITY_EVEN=data&0x01;
906
907
// Reset all errors if required
908
if(data&0x08)
909
{
910
mUART_Rx_overun_error=0;
911
mUART_Rx_framing_error=0;
912
}
913
914
if(mUART_SENDBREAK)
915
{
916
// Trigger send break, it will self sustain as long as sendbreak is set
917
mUART_TX_COUNTDOWN=UART_TX_TIME_PERIOD;
918
// Loop back what we transmitted
919
ComLynxTxLoopback(UART_BREAK_CODE);
920
}
921
break;
922
923
case (SERDAT&0xff):
924
TRACE_MIKIE2("Poke(SERDAT ,%04x) at PC=%04x",data,mSystem.mCpu->GetPC());
925
//
926
// Fake transmission, set counter to be decremented by Timer 4
927
//
928
// ComLynx only has one output pin, hence Rx & Tx are shorted
929
// therefore any transmitted data will loopback
930
//
931
mUART_TX_DATA=data;
932
// Calculate Parity data
933
if(mUART_PARITY_ENABLE)
934
{
935
// Calc parity value
936
// Leave at zero !!
937
}
938
else
939
{
940
// If disabled then the PAREVEN bit is sent
941
if(mUART_PARITY_EVEN) data|=0x0100;
942
}
943
// Set countdown to transmission
944
mUART_TX_COUNTDOWN=UART_TX_TIME_PERIOD;
945
// Loop back what we transmitted
946
ComLynxTxLoopback(mUART_TX_DATA);
947
break;
948
949
case (SDONEACK&0xff):
950
TRACE_MIKIE2("Poke(SDONEACK,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
951
break;
952
case (CPUSLEEP&0xff):
953
mSystem.gSuzieDoneTime = mSystem.gSystemCycleCount+mSystem.PaintSprites();
954
SetCPUSleep();
955
break;
956
957
case (DISPCTL&0xff):
958
TRACE_MIKIE2("Poke(DISPCTL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
959
{
960
TDISPCTL tmp;
961
tmp.Byte=data;
962
mDISPCTL_DMAEnable=tmp.Bits.DMAEnable;
963
mDISPCTL_Flip=tmp.Bits.Flip;
964
mDISPCTL_FourColour=tmp.Bits.FourColour;
965
mDISPCTL_Colour=tmp.Bits.Colour;
966
}
967
break;
968
case (PBKUP&0xff):
969
TRACE_MIKIE2("Poke(PBKUP,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
970
break;
971
972
case (DISPADRL&0xff):
973
TRACE_MIKIE2("Poke(DISPADRL,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
974
mDisplayAddress&=0xff00;
975
mDisplayAddress+=data;
976
break;
977
978
case (DISPADRH&0xff):
979
TRACE_MIKIE2("Poke(DISPADRH,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
980
mDisplayAddress&=0x00ff;
981
mDisplayAddress+=(data<<8);
982
break;
983
984
case (Mtest0&0xff):
985
case (Mtest1&0xff):
986
// Test registers are unimplemented
987
// lets hope no programs use them.
988
TRACE_MIKIE2("Poke(MTEST0/1,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
989
case (Mtest2&0xff):
990
// Test registers are unimplemented
991
// lets hope no programs use them.
992
//gError->Warning("CMikie::Poke() - Write to MTEST2");
993
TRACE_MIKIE2("Poke(MTEST2,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
994
break;
995
996
case (GREEN0&0xff):
997
case (GREEN1&0xff):
998
case (GREEN2&0xff):
999
case (GREEN3&0xff):
1000
case (GREEN4&0xff):
1001
case (GREEN5&0xff):
1002
case (GREEN6&0xff):
1003
case (GREEN7&0xff):
1004
case (GREEN8&0xff):
1005
case (GREEN9&0xff):
1006
case (GREENA&0xff):
1007
case (GREENB&0xff):
1008
case (GREENC&0xff):
1009
case (GREEND&0xff):
1010
case (GREENE&0xff):
1011
case (GREENF&0xff):
1012
TRACE_MIKIE2("Poke(GREENPAL0-F,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1013
mPalette[addr&0x0f].Colours.Green=data&0x0f;
1014
break;
1015
1016
case (BLUERED0&0xff):
1017
case (BLUERED1&0xff):
1018
case (BLUERED2&0xff):
1019
case (BLUERED3&0xff):
1020
case (BLUERED4&0xff):
1021
case (BLUERED5&0xff):
1022
case (BLUERED6&0xff):
1023
case (BLUERED7&0xff):
1024
case (BLUERED8&0xff):
1025
case (BLUERED9&0xff):
1026
case (BLUEREDA&0xff):
1027
case (BLUEREDB&0xff):
1028
case (BLUEREDC&0xff):
1029
case (BLUEREDD&0xff):
1030
case (BLUEREDE&0xff):
1031
case (BLUEREDF&0xff):
1032
TRACE_MIKIE2("Poke(BLUEREDPAL0-F,%02x) at PC=%04x",data,mSystem.mCpu->GetPC());
1033
mPalette[addr&0x0f].Colours.Blue=(data&0xf0)>>4;
1034
mPalette[addr&0x0f].Colours.Red=data&0x0f;
1035
break;
1036
1037
// Errors on read only register accesses
1038
1039
case (MAGRDY0&0xff):
1040
case (MAGRDY1&0xff):
1041
case (AUDIN&0xff):
1042
case (MIKEYHREV&0xff):
1043
TRACE_MIKIE3("Poke(%04x,%02x) - Poke to read only register location at PC=%04x",addr,data,mSystem.mCpu->GetPC());
1044
break;
1045
1046
// Errors on illegal location accesses
1047
1048
default:
1049
TRACE_MIKIE3("Poke(%04x,%02x) - Poke to illegal location at PC=%04x",addr,data,mSystem.mCpu->GetPC());
1050
break;
1051
}
1052
}
1053
1054
1055
1056
uint8 CMikie::Peek(uint32 addr)
1057
{
1058
/* Sound register area */
1059
if(addr >= 0xFD20 && addr <= 0xFD3F)
1060
{
1061
int which = (addr - 0xFD20) >> 3; // Each channel gets 8 ports/registers
1062
switch(addr & 0x7)
1063
{
1064
case (AUD0VOL&0x7):
1065
return (uint8)mAUDIO_VOLUME[which];
1066
break;
1067
case (AUD0SHFTFB&0x7):
1068
return (uint8)((mAUDIO_WAVESHAPER[which]>>13)&0xff);
1069
break;
1070
case (AUD0OUTVAL&0x7):
1071
return (uint8)mAUDIO_OUTPUT[which];
1072
break;
1073
case (AUD0L8SHFT&0x7):
1074
return (uint8)(mAUDIO_WAVESHAPER[which]&0xff);
1075
break;
1076
case (AUD0TBACK&0x7):
1077
return (uint8)mAUDIO_BKUP[which];
1078
break;
1079
case (AUD0CTL&0x7):
1080
{
1081
uint8 retval=0;
1082
retval|=(mAUDIO_INTEGRATE_ENABLE[which])?0x20:0x00;
1083
retval|=(mAUDIO_ENABLE_RELOAD[which])?0x10:0x00;
1084
retval|=(mAUDIO_ENABLE_COUNT[which])?0x08:0x00;
1085
retval|=(mAUDIO_WAVESHAPER[which]&0x001000)?0x80:0x00;
1086
retval|=mAUDIO_LINKING[which];
1087
return retval;
1088
}
1089
break;
1090
case (AUD0COUNT&0x7):
1091
return (uint8)mAUDIO_CURRENT[which];
1092
break;
1093
case (AUD0MISC&0x7):
1094
{
1095
uint8 retval=0;
1096
retval|=(mAUDIO_BORROW_OUT[which])?0x01:0x00;
1097
retval|=(mAUDIO_BORROW_IN[which])?0x02:0x00;
1098
retval|=(mAUDIO_LAST_CLOCK[which])?0x08:0x00;
1099
retval|=(mAUDIO_WAVESHAPER[which]>>4)&0xf0;
1100
return retval;
1101
}
1102
break;
1103
}
1104
}
1105
else switch(addr&0xff)
1106
{
1107
1108
// Timer control registers
1109
1110
case (TIM0BKUP&0xff):
1111
TRACE_MIKIE2("Peek(TIM0KBUP ,%02x) at PC=%04x",mTIM_0_BKUP,mSystem.mCpu->GetPC());
1112
return (uint8)mTIM_0_BKUP;
1113
break;
1114
case (TIM1BKUP&0xff):
1115
TRACE_MIKIE2("Peek(TIM1KBUP ,%02x) at PC=%04x",mTIM_1_BKUP,mSystem.mCpu->GetPC());
1116
return (uint8)mTIM_1_BKUP;
1117
break;
1118
case (TIM2BKUP&0xff):
1119
TRACE_MIKIE2("Peek(TIM2KBUP ,%02x) at PC=%04x",mTIM_2_BKUP,mSystem.mCpu->GetPC());
1120
return (uint8)mTIM_2_BKUP;
1121
break;
1122
case (TIM3BKUP&0xff):
1123
TRACE_MIKIE2("Peek(TIM3KBUP ,%02x) at PC=%04x",mTIM_3_BKUP,mSystem.mCpu->GetPC());
1124
return (uint8)mTIM_3_BKUP;
1125
break;
1126
case (TIM4BKUP&0xff):
1127
TRACE_MIKIE2("Peek(TIM4KBUP ,%02x) at PC=%04x",mTIM_4_BKUP,mSystem.mCpu->GetPC());
1128
return (uint8)mTIM_4_BKUP;
1129
break;
1130
case (TIM5BKUP&0xff):
1131
TRACE_MIKIE2("Peek(TIM5KBUP ,%02x) at PC=%04x",mTIM_5_BKUP,mSystem.mCpu->GetPC());
1132
return (uint8)mTIM_5_BKUP;
1133
break;
1134
case (TIM6BKUP&0xff):
1135
TRACE_MIKIE2("Peek(TIM6KBUP ,%02x) at PC=%04x",mTIM_6_BKUP,mSystem.mCpu->GetPC());
1136
return (uint8)mTIM_6_BKUP;
1137
break;
1138
case (TIM7BKUP&0xff):
1139
TRACE_MIKIE2("Peek(TIM7KBUP ,%02x) at PC=%04x",mTIM_7_BKUP,mSystem.mCpu->GetPC());
1140
return (uint8)mTIM_7_BKUP;
1141
break;
1142
1143
case (TIM0CTLA&0xff):
1144
{
1145
uint8 retval=0;
1146
retval|=(mTimerInterruptMask&0x01)?0x80:0x00;
1147
retval|=(mTIM_0_ENABLE_RELOAD)?0x10:0x00;
1148
retval|=(mTIM_0_ENABLE_COUNT)?0x08:0x00;
1149
retval|=mTIM_0_LINKING;
1150
TRACE_MIKIE2("Peek(TIM0CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1151
return retval;
1152
}
1153
break;
1154
case (TIM1CTLA&0xff):
1155
{
1156
uint8 retval=0;
1157
retval|=(mTimerInterruptMask&0x02)?0x80:0x00;
1158
retval|=(mTIM_1_ENABLE_RELOAD)?0x10:0x00;
1159
retval|=(mTIM_1_ENABLE_COUNT)?0x08:0x00;
1160
retval|=mTIM_1_LINKING;
1161
TRACE_MIKIE2("Peek(TIM1CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1162
return retval;
1163
}
1164
break;
1165
case (TIM2CTLA&0xff):
1166
{
1167
uint8 retval=0;
1168
retval|=(mTimerInterruptMask&0x04)?0x80:0x00;
1169
retval|=(mTIM_2_ENABLE_RELOAD)?0x10:0x00;
1170
retval|=(mTIM_2_ENABLE_COUNT)?0x08:0x00;
1171
retval|=mTIM_2_LINKING;
1172
TRACE_MIKIE2("Peek(TIM2CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1173
return retval;
1174
}
1175
break;
1176
case (TIM3CTLA&0xff):
1177
{
1178
uint8 retval=0;
1179
retval|=(mTimerInterruptMask&0x08)?0x80:0x00;
1180
retval|=(mTIM_3_ENABLE_RELOAD)?0x10:0x00;
1181
retval|=(mTIM_3_ENABLE_COUNT)?0x08:0x00;
1182
retval|=mTIM_3_LINKING;
1183
TRACE_MIKIE2("Peek(TIM3CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1184
return retval;
1185
}
1186
break;
1187
case (TIM4CTLA&0xff):
1188
{
1189
uint8 retval=0;
1190
retval|=(mTimerInterruptMask&0x10)?0x80:0x00;
1191
retval|=(mTIM_4_ENABLE_RELOAD)?0x10:0x00;
1192
retval|=(mTIM_4_ENABLE_COUNT)?0x08:0x00;
1193
retval|=mTIM_4_LINKING;
1194
TRACE_MIKIE2("Peek(TIM4CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1195
return retval;
1196
}
1197
break;
1198
case (TIM5CTLA&0xff):
1199
{
1200
uint8 retval=0;
1201
retval|=(mTimerInterruptMask&0x20)?0x80:0x00;
1202
retval|=(mTIM_5_ENABLE_RELOAD)?0x10:0x00;
1203
retval|=(mTIM_5_ENABLE_COUNT)?0x08:0x00;
1204
retval|=mTIM_5_LINKING;
1205
TRACE_MIKIE2("Peek(TIM5CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1206
return retval;
1207
}
1208
break;
1209
case (TIM6CTLA&0xff):
1210
{
1211
uint8 retval=0;
1212
retval|=(mTimerInterruptMask&0x40)?0x80:0x00;
1213
retval|=(mTIM_6_ENABLE_RELOAD)?0x10:0x00;
1214
retval|=(mTIM_6_ENABLE_COUNT)?0x08:0x00;
1215
retval|=mTIM_6_LINKING;
1216
TRACE_MIKIE2("Peek(TIM6CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1217
return retval;
1218
}
1219
break;
1220
case (TIM7CTLA&0xff):
1221
{
1222
uint8 retval=0;
1223
retval|=(mTimerInterruptMask&0x80)?0x80:0x00;
1224
retval|=(mTIM_7_ENABLE_RELOAD)?0x10:0x00;
1225
retval|=(mTIM_7_ENABLE_COUNT)?0x08:0x00;
1226
retval|=mTIM_7_LINKING;
1227
TRACE_MIKIE2("Peek(TIM7CTLA ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1228
return retval;
1229
}
1230
break;
1231
1232
case (TIM0CNT&0xff):
1233
Update();
1234
TRACE_MIKIE2("Peek(TIM0CNT ,%02x) at PC=%04x",mTIM_0_CURRENT,mSystem.mCpu->GetPC());
1235
return (uint8)mTIM_0_CURRENT;
1236
break;
1237
case (TIM1CNT&0xff):
1238
Update();
1239
TRACE_MIKIE2("Peek(TIM1CNT ,%02x) at PC=%04x",mTIM_1_CURRENT,mSystem.mCpu->GetPC());
1240
return (uint8)mTIM_1_CURRENT;
1241
break;
1242
case (TIM2CNT&0xff):
1243
Update();
1244
TRACE_MIKIE2("Peek(TIM2CNT ,%02x) at PC=%04x",mTIM_2_CURRENT,mSystem.mCpu->GetPC());
1245
return (uint8)mTIM_2_CURRENT;
1246
break;
1247
case (TIM3CNT&0xff):
1248
Update();
1249
TRACE_MIKIE2("Peek(TIM3CNT ,%02x) at PC=%04x",mTIM_3_CURRENT,mSystem.mCpu->GetPC());
1250
return (uint8)mTIM_3_CURRENT;
1251
break;
1252
case (TIM4CNT&0xff):
1253
Update();
1254
TRACE_MIKIE2("Peek(TIM4CNT ,%02x) at PC=%04x",mTIM_4_CURRENT,mSystem.mCpu->GetPC());
1255
return (uint8)mTIM_4_CURRENT;
1256
break;
1257
case (TIM5CNT&0xff):
1258
Update();
1259
TRACE_MIKIE2("Peek(TIM5CNT ,%02x) at PC=%04x",mTIM_5_CURRENT,mSystem.mCpu->GetPC());
1260
return (uint8)mTIM_5_CURRENT;
1261
break;
1262
case (TIM6CNT&0xff):
1263
Update();
1264
TRACE_MIKIE2("Peek(TIM6CNT ,%02x) at PC=%04x",mTIM_6_CURRENT,mSystem.mCpu->GetPC());
1265
return (uint8)mTIM_6_CURRENT;
1266
break;
1267
case (TIM7CNT&0xff):
1268
Update();
1269
TRACE_MIKIE2("Peek(TIM7CNT ,%02x) at PC=%04x",mTIM_7_CURRENT,mSystem.mCpu->GetPC());
1270
return (uint8)mTIM_7_CURRENT;
1271
break;
1272
1273
case (TIM0CTLB&0xff):
1274
{
1275
uint8 retval=0;
1276
retval|=(mTIM_0_TIMER_DONE)?0x08:0x00;
1277
retval|=(mTIM_0_LAST_CLOCK)?0x04:0x00;
1278
retval|=(mTIM_0_BORROW_IN)?0x02:0x00;
1279
retval|=(mTIM_0_BORROW_OUT)?0x01:0x00;
1280
TRACE_MIKIE2("Peek(TIM0CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1281
return retval;
1282
}
1283
// BlowOut();
1284
break;
1285
case (TIM1CTLB&0xff):
1286
{
1287
uint8 retval=0;
1288
retval|=(mTIM_1_TIMER_DONE)?0x08:0x00;
1289
retval|=(mTIM_1_LAST_CLOCK)?0x04:0x00;
1290
retval|=(mTIM_1_BORROW_IN)?0x02:0x00;
1291
retval|=(mTIM_1_BORROW_OUT)?0x01:0x00;
1292
TRACE_MIKIE2("Peek(TIM1CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1293
return retval;
1294
}
1295
// BlowOut();
1296
break;
1297
case (TIM2CTLB&0xff):
1298
{
1299
uint8 retval=0;
1300
retval|=(mTIM_2_TIMER_DONE)?0x08:0x00;
1301
retval|=(mTIM_2_LAST_CLOCK)?0x04:0x00;
1302
retval|=(mTIM_2_BORROW_IN)?0x02:0x00;
1303
retval|=(mTIM_2_BORROW_OUT)?0x01:0x00;
1304
TRACE_MIKIE2("Peek(TIM2CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1305
return retval;
1306
}
1307
// BlowOut();
1308
break;
1309
case (TIM3CTLB&0xff):
1310
{
1311
uint8 retval=0;
1312
retval|=(mTIM_3_TIMER_DONE)?0x08:0x00;
1313
retval|=(mTIM_3_LAST_CLOCK)?0x04:0x00;
1314
retval|=(mTIM_3_BORROW_IN)?0x02:0x00;
1315
retval|=(mTIM_3_BORROW_OUT)?0x01:0x00;
1316
TRACE_MIKIE2("Peek(TIM3CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1317
return retval;
1318
}
1319
// BlowOut();
1320
break;
1321
case (TIM4CTLB&0xff):
1322
{
1323
uint8 retval=0;
1324
retval|=(mTIM_4_TIMER_DONE)?0x08:0x00;
1325
retval|=(mTIM_4_LAST_CLOCK)?0x04:0x00;
1326
retval|=(mTIM_4_BORROW_IN)?0x02:0x00;
1327
retval|=(mTIM_4_BORROW_OUT)?0x01:0x00;
1328
TRACE_MIKIE2("Peek(TIM4CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1329
return retval;
1330
}
1331
// BlowOut();
1332
break;
1333
case (TIM5CTLB&0xff):
1334
{
1335
uint8 retval=0;
1336
retval|=(mTIM_5_TIMER_DONE)?0x08:0x00;
1337
retval|=(mTIM_5_LAST_CLOCK)?0x04:0x00;
1338
retval|=(mTIM_5_BORROW_IN)?0x02:0x00;
1339
retval|=(mTIM_5_BORROW_OUT)?0x01:0x00;
1340
TRACE_MIKIE2("Peek(TIM5CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1341
return retval;
1342
}
1343
// BlowOut();
1344
break;
1345
case (TIM6CTLB&0xff):
1346
{
1347
uint8 retval=0;
1348
retval|=(mTIM_6_TIMER_DONE)?0x08:0x00;
1349
retval|=(mTIM_6_LAST_CLOCK)?0x04:0x00;
1350
retval|=(mTIM_6_BORROW_IN)?0x02:0x00;
1351
retval|=(mTIM_6_BORROW_OUT)?0x01:0x00;
1352
TRACE_MIKIE2("Peek(TIM6CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1353
return retval;
1354
}
1355
// BlowOut();
1356
break;
1357
case (TIM7CTLB&0xff):
1358
{
1359
uint8 retval=0;
1360
retval|=(mTIM_7_TIMER_DONE)?0x08:0x00;
1361
retval|=(mTIM_7_LAST_CLOCK)?0x04:0x00;
1362
retval|=(mTIM_7_BORROW_IN)?0x02:0x00;
1363
retval|=(mTIM_7_BORROW_OUT)?0x01:0x00;
1364
TRACE_MIKIE2("Peek(TIM7CTLB ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1365
return retval;
1366
}
1367
// BlowOut();
1368
break;
1369
1370
// Extra audio control registers
1371
1372
case (ATTEN_A&0xff):
1373
TRACE_MIKIE1("Peek(ATTEN_A) at PC=%04x",mSystem.mCpu->GetPC());
1374
return (uint8) mAUDIO_ATTEN[0];
1375
break;
1376
case (ATTEN_B&0xff):
1377
TRACE_MIKIE1("Peek(ATTEN_B) at PC=%04x",mSystem.mCpu->GetPC());
1378
return (uint8) mAUDIO_ATTEN[1];
1379
break;
1380
case (ATTEN_C&0xff):
1381
TRACE_MIKIE1("Peek(ATTEN_C) at PC=%04x",mSystem.mCpu->GetPC());
1382
return (uint8) mAUDIO_ATTEN[2];
1383
break;
1384
case (ATTEN_D&0xff):
1385
TRACE_MIKIE1("Peek(ATTEN_D) at PC=%04x",mSystem.mCpu->GetPC());
1386
return (uint8) mAUDIO_ATTEN[3];
1387
break;
1388
case (MPAN&0xff):
1389
TRACE_MIKIE1("Peek(MPAN) at PC=%04x",mSystem.mCpu->GetPC());
1390
return (uint8) mPAN;
1391
break;
1392
1393
case (MSTEREO&0xff):
1394
TRACE_MIKIE2("Peek(MSTEREO,%02x) at PC=%04x",(uint8)mSTEREO^0xff,mSystem.mCpu->GetPC());
1395
return (uint8) mSTEREO^0xff;
1396
break;
1397
1398
// Miscellaneous registers
1399
1400
case (SERCTL&0xff):
1401
{
1402
uint32 retval=0;
1403
retval|=(mUART_TX_COUNTDOWN&UART_TX_INACTIVE)?0xA0:0x00; // Indicate TxDone & TxAllDone
1404
retval|=(mUART_RX_READY)?0x40:0x00; // Indicate Rx data ready
1405
retval|=(mUART_Rx_overun_error)?0x08:0x0; // Framing error
1406
retval|=(mUART_Rx_framing_error)?0x04:0x00; // Rx overrun
1407
retval|=(mUART_RX_DATA&UART_BREAK_CODE)?0x02:0x00; // Indicate break received
1408
retval|=(mUART_RX_DATA&0x0100)?0x01:0x00; // Add parity bit
1409
TRACE_MIKIE2("Peek(SERCTL ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1410
return (uint8)retval;
1411
}
1412
break;
1413
1414
case (SERDAT&0xff):
1415
mUART_RX_READY=0;
1416
TRACE_MIKIE2("Peek(SERDAT ,%02x) at PC=%04x",(uint8)mUART_RX_DATA,mSystem.mCpu->GetPC());
1417
return (uint8)(mUART_RX_DATA&0xff);
1418
break;
1419
1420
case (IODAT&0xff):
1421
{
1422
uint32 retval=0;
1423
retval|=(mIODIR&0x10)?mIODAT&0x10:0x10; // IODIR = output bit : input high (eeprom write done)
1424
retval|=(mIODIR&0x08)?(((mIODAT&0x08)&&mIODAT_REST_SIGNAL)?0x00:0x08):0x00; // REST = output bit : input low
1425
retval|=(mIODIR&0x04)?mIODAT&0x04:((mUART_CABLE_PRESENT)?0x04:0x00); // NOEXP = output bit : input low
1426
retval|=(mIODIR&0x02)?mIODAT&0x02:0x00; // CARTAD = output bit : input low
1427
retval|=(mIODIR&0x01)?mIODAT&0x01:0x01; // EXTPW = output bit : input high (Power connected)
1428
TRACE_MIKIE2("Peek(IODAT ,%02x) at PC=%04x",retval,mSystem.mCpu->GetPC());
1429
return (uint8)retval;
1430
}
1431
break;
1432
1433
case (INTRST&0xff):
1434
case (INTSET&0xff):
1435
TRACE_MIKIE2("Peek(INTSET ,%02x) at PC=%04x",mTimerStatusFlags,mSystem.mCpu->GetPC());
1436
return (uint8)mTimerStatusFlags;
1437
break;
1438
1439
case (MAGRDY0&0xff):
1440
case (MAGRDY1&0xff):
1441
TRACE_MIKIE2("Peek(MAGRDY0/1,%02x) at PC=%04x",0x00,mSystem.mCpu->GetPC());
1442
return 0x00;
1443
break;
1444
1445
case (AUDIN&0xff):
1446
// TRACE_MIKIE2("Peek(AUDIN,%02x) at PC=%04x",mAudioInputComparator?0x80:0x00,mSystem.mCpu->GetPC());
1447
// if(mAudioInputComparator) return 0x80; else return 0x00;
1448
TRACE_MIKIE2("Peek(AUDIN,%02x) at PC=%04x",0x80,mSystem.mCpu->GetPC());
1449
return 0x80;
1450
break;
1451
1452
case (MIKEYHREV&0xff):
1453
TRACE_MIKIE2("Peek(MIKEYHREV,%02x) at PC=%04x",0x01,mSystem.mCpu->GetPC());
1454
return 0x01;
1455
break;
1456
1457
// Pallette registers
1458
1459
case (GREEN0&0xff):
1460
case (GREEN1&0xff):
1461
case (GREEN2&0xff):
1462
case (GREEN3&0xff):
1463
case (GREEN4&0xff):
1464
case (GREEN5&0xff):
1465
case (GREEN6&0xff):
1466
case (GREEN7&0xff):
1467
case (GREEN8&0xff):
1468
case (GREEN9&0xff):
1469
case (GREENA&0xff):
1470
case (GREENB&0xff):
1471
case (GREENC&0xff):
1472
case (GREEND&0xff):
1473
case (GREENE&0xff):
1474
case (GREENF&0xff):
1475
TRACE_MIKIE2("Peek(GREENPAL0-F,%02x) at PC=%04x",mPalette[addr&0x0f].Colours.Green,mSystem.mCpu->GetPC());
1476
return mPalette[addr&0x0f].Colours.Green;
1477
break;
1478
1479
case (BLUERED0&0xff):
1480
case (BLUERED1&0xff):
1481
case (BLUERED2&0xff):
1482
case (BLUERED3&0xff):
1483
case (BLUERED4&0xff):
1484
case (BLUERED5&0xff):
1485
case (BLUERED6&0xff):
1486
case (BLUERED7&0xff):
1487
case (BLUERED8&0xff):
1488
case (BLUERED9&0xff):
1489
case (BLUEREDA&0xff):
1490
case (BLUEREDB&0xff):
1491
case (BLUEREDC&0xff):
1492
case (BLUEREDD&0xff):
1493
case (BLUEREDE&0xff):
1494
case (BLUEREDF&0xff):
1495
TRACE_MIKIE2("Peek(BLUEREDPAL0-F,%02x) at PC=%04x",(mPalette[addr&0x0f].Colours.Red | (mPalette[addr&0x0f].Colours.Blue<<4)),mSystem.mCpu->GetPC());
1496
return (mPalette[addr&0x0f].Colours.Red | (mPalette[addr&0x0f].Colours.Blue<<4));
1497
break;
1498
1499
// Errors on write only register accesses
1500
1501
// For easier debugging
1502
1503
case (DISPADRL&0xff):
1504
TRACE_MIKIE2("Peek(DISPADRL,%02x) at PC=%04x",(uint8)(mDisplayAddress&0xff),mSystem.mCpu->GetPC());
1505
return (uint8)(mDisplayAddress&0xff);
1506
case (DISPADRH&0xff):
1507
TRACE_MIKIE2("Peek(DISPADRH,%02x) at PC=%04x",(uint8)(mDisplayAddress>>8)&0xff,mSystem.mCpu->GetPC());
1508
return (uint8)(mDisplayAddress>>8)&0xff;
1509
1510
case (DISPCTL&0xff):
1511
case (SYSCTL1&0xff):
1512
case (MIKEYSREV&0xff):
1513
case (IODIR&0xff):
1514
case (SDONEACK&0xff):
1515
case (CPUSLEEP&0xff):
1516
case (PBKUP&0xff):
1517
case (Mtest0&0xff):
1518
case (Mtest1&0xff):
1519
case (Mtest2&0xff):
1520
TRACE_MIKIE2("Peek(%04x) - Peek from write only register location at PC=$%04x",addr,mSystem.mCpu->GetPC());
1521
break;
1522
1523
// Register to let programs know handy is running
1524
1525
case (0xfd97&0xff):
1526
TRACE_MIKIE2("Peek(%04x) - **** HANDY DETECT ATTEMPTED **** at PC=$%04x",addr,mSystem.mCpu->GetPC());
1527
// gError->Warning("EMULATOR DETECT REGISTER HAS BEEN READ");
1528
return 0x42;
1529
break;
1530
1531
// Errors on illegal location accesses
1532
1533
default:
1534
TRACE_MIKIE2("Peek(%04x) - Peek from illegal location at PC=$%04x",addr,mSystem.mCpu->GetPC());
1535
break;
1536
}
1537
return 0xff;
1538
}
1539
1540
1541
void CMikie::CombobulateSound(uint32 teatime)
1542
{
1543
int cur_lsample = 0;
1544
int cur_rsample = 0;
1545
int x;
1546
1547
teatime >>= 2;
1548
for(x = 0; x < 4; x++)
1549
{
1550
/// Assumption (seems there is no documentation for the Attenuation registers)
1551
/// a) they are linear from $0 to $f
1552
/// b) an attenuation of $0 is equal to channel OFF (bits in mSTEREO not set)
1553
/// c) an attenuation of $f is equal to no attenuation (bits in PAN not set)
1554
/// These assumptions can only checked with an oszilloscope...
1555
/// the values stored in mSTEREO are bit-inverted ...
1556
/// mSTEREO was found to be set like that already (why?), but unused
1557
1558
if(mSTEREO & (0x10 << x))
1559
{
1560
if(mPAN & (0x10 << x))
1561
cur_lsample += (mAUDIO_OUTPUT[x]*(mAUDIO_ATTEN[x]&0xF0))/(15*16);
1562
else
1563
cur_lsample += mAUDIO_OUTPUT[x];
1564
}
1565
if(mSTEREO & (0x01 << x))
1566
{
1567
if(mPAN & (0x01 << x))
1568
cur_rsample += (mAUDIO_OUTPUT[x]*(mAUDIO_ATTEN[x]&0x0F))/15;
1569
else
1570
cur_rsample += mAUDIO_OUTPUT[x];
1571
}
1572
}
1573
if(cur_lsample != last_lsample)
1574
{
1575
miksynth.offset_inline(teatime, cur_lsample - last_lsample, mikbuf.left());
1576
last_lsample = cur_lsample;
1577
}
1578
if(cur_rsample != last_rsample)
1579
{
1580
miksynth.offset_inline(teatime, cur_rsample - last_rsample, mikbuf.right());
1581
last_rsample = cur_rsample;
1582
}
1583
}
1584
1585
void CMikie::CheckWrap()
1586
{
1587
//
1588
// To stop problems with cycle count wrap we will check and then correct the
1589
// cycle counter.
1590
//
1591
#define DEC(X) do { if((X)) { (X) -= 0x80000000; } } while (0)
1592
1593
if(mSystem.gSystemCycleCount>0xf0000000)
1594
{
1595
DEC(mSystem.gSystemCycleCount);
1596
DEC(mTIM_0_LAST_COUNT);
1597
DEC(mTIM_1_LAST_COUNT);
1598
DEC(mTIM_2_LAST_COUNT);
1599
DEC(mTIM_3_LAST_COUNT);
1600
DEC(mTIM_4_LAST_COUNT);
1601
DEC(mTIM_5_LAST_COUNT);
1602
DEC(mTIM_6_LAST_COUNT);
1603
DEC(mTIM_7_LAST_COUNT);
1604
DEC(mAUDIO_LAST_COUNT[0]);
1605
DEC(mAUDIO_LAST_COUNT[1]);
1606
DEC(mAUDIO_LAST_COUNT[2]);
1607
DEC(mAUDIO_LAST_COUNT[3]);
1608
DEC(startTS);
1609
DEC(mSystem.gSuzieDoneTime);
1610
DEC(mSystem.gNextTimerEvent);
1611
}
1612
#undef DEC
1613
}
1614
1615
void CMikie::Update()
1616
{
1617
int32 divide;
1618
int32 decval;
1619
uint32 tmp;
1620
uint32 mikie_work_done=0;
1621
1622
1623
// TRACE_MIKIE0("Update()");
1624
1625
mSystem.gNextTimerEvent=0xffffffff;
1626
1627
if(mSystem.gSuzieDoneTime)
1628
{
1629
if(mSystem.gSystemCycleCount >= mSystem.gSuzieDoneTime)
1630
{
1631
ClearCPUSleep();
1632
mSystem.gSuzieDoneTime = 0;
1633
}
1634
else if(mSystem.gSuzieDoneTime > mSystem.gSystemCycleCount) mSystem.gNextTimerEvent = mSystem.gSuzieDoneTime;
1635
}
1636
1637
// Timer updates, rolled out flat in group order
1638
//
1639
// Group A:
1640
// Timer 0 -> Timer 2 -> Timer 4.
1641
//
1642
// Group B:
1643
// Timer 1 -> Timer 3 -> Timer 5 -> Timer 7 -> Audio 0 -> Audio 1-> Audio 2 -> Audio 3 -> Timer 1.
1644
//
1645
1646
//
1647
// Within each timer code block we will predict the cycle count number of
1648
// the next timer event
1649
//
1650
// We don't need to count linked timers as the timer they are linked
1651
// from will always generate earlier events.
1652
//
1653
// As Timer 4 (UART) will generate many events we will ignore it
1654
//
1655
// We set the next event to the end of time at first and let the timers
1656
// overload it. Any writes to timer controls will force next event to
1657
// be immediate and hence a new preidction will be done. The prediction
1658
// causes overflow as opposed to zero i.e. current+1
1659
// (In reality T0 line counter should always be running.)
1660
//
1661
1662
1663
//
1664
// Timer 0 of Group A
1665
//
1666
1667
//
1668
// Optimisation, assume T0 (Line timer) is never in one-shot,
1669
// never placed in link mode
1670
//
1671
1672
// KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD || ..)
1673
// if(mTIM_0_ENABLE_COUNT && (mTIM_0_ENABLE_RELOAD || !mTIM_0_TIMER_DONE))
1674
if(mTIM_0_ENABLE_COUNT)
1675
{
1676
// Timer 0 has no linking
1677
// if(mTIM_0_LINKING!=0x07)
1678
{
1679
// Ordinary clocked mode as opposed to linked mode
1680
// 16MHz clock downto 1us == cyclecount >> 4
1681
divide=(4+mTIM_0_LINKING);
1682
decval=(mSystem.gSystemCycleCount-mTIM_0_LAST_COUNT)>>divide;
1683
1684
if(decval)
1685
{
1686
mTIM_0_LAST_COUNT+=decval<<divide;
1687
mTIM_0_CURRENT-=decval;
1688
1689
if(mTIM_0_CURRENT&0x80000000)
1690
{
1691
// Set carry out
1692
mTIM_0_BORROW_OUT=TRUE;
1693
1694
// // Reload if neccessary
1695
// if(mTIM_0_ENABLE_RELOAD)
1696
// {
1697
mTIM_0_CURRENT+=mTIM_0_BKUP+1;
1698
// }
1699
// else
1700
// {
1701
// mTIM_0_CURRENT=0;
1702
// }
1703
1704
mTIM_0_TIMER_DONE=TRUE;
1705
1706
// Interupt flag setting code moved into DisplayRenderLine()
1707
1708
// Line timer has expired, render a line, we cannot incrememnt
1709
// the global counter at this point as it will screw the other timers
1710
// so we save under work done and inc at the end.
1711
mikie_work_done+=DisplayRenderLine();
1712
1713
}
1714
else
1715
{
1716
mTIM_0_BORROW_OUT=FALSE;
1717
}
1718
// Set carry in as we did a count
1719
mTIM_0_BORROW_IN=TRUE;
1720
}
1721
else
1722
{
1723
// Clear carry in as we didn't count
1724
mTIM_0_BORROW_IN=FALSE;
1725
// Clear carry out
1726
mTIM_0_BORROW_OUT=FALSE;
1727
}
1728
}
1729
1730
// Prediction for next timer event cycle number
1731
1732
// if(mTIM_0_LINKING!=7)
1733
{
1734
// Sometimes timeupdates can be >2x rollover in which case
1735
// then CURRENT may still be negative and we can use it to
1736
// calc the next timer value, we just want another update ASAP
1737
tmp=(mTIM_0_CURRENT&0x80000000)?1:((mTIM_0_CURRENT+1)<<divide);
1738
tmp+=mSystem.gSystemCycleCount;
1739
if(tmp<mSystem.gNextTimerEvent)
1740
{
1741
mSystem.gNextTimerEvent=tmp;
1742
// TRACE_MIKIE1("Update() - TIMER 0 Set NextTimerEvent = %012d",gNextTimerEvent);
1743
}
1744
}
1745
// TRACE_MIKIE1("Update() - mTIM_0_CURRENT = %012d",mTIM_0_CURRENT);
1746
// TRACE_MIKIE1("Update() - mTIM_0_BKUP = %012d",mTIM_0_BKUP);
1747
// TRACE_MIKIE1("Update() - mTIM_0_LASTCNT = %012d",mTIM_0_LAST_COUNT);
1748
// TRACE_MIKIE1("Update() - mTIM_0_LINKING = %012d",mTIM_0_LINKING);
1749
}
1750
1751
//
1752
// Timer 2 of Group A
1753
//
1754
1755
//
1756
// Optimisation, assume T2 (Frame timer) is never in one-shot
1757
// always in linked mode i.e clocked by Line Timer
1758
//
1759
1760
// KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD || ..)
1761
// if(mTIM_2_ENABLE_COUNT && (mTIM_2_ENABLE_RELOAD || !mTIM_2_TIMER_DONE))
1762
if(mTIM_2_ENABLE_COUNT)
1763
{
1764
decval=0;
1765
1766
// if(mTIM_2_LINKING==0x07)
1767
{
1768
if(mTIM_0_BORROW_OUT) decval=1;
1769
mTIM_2_LAST_LINK_CARRY=mTIM_0_BORROW_OUT;
1770
divide = 0;
1771
}
1772
// else
1773
// {
1774
// // Ordinary clocked mode as opposed to linked mode
1775
// // 16MHz clock downto 1us == cyclecount >> 4
1776
// divide=(4+mTIM_2_LINKING);
1777
// decval=(gSystemCycleCount-mTIM_2_LAST_COUNT)>>divide;
1778
// }
1779
1780
if(decval)
1781
{
1782
// mTIM_2_LAST_COUNT+=decval<<divide;
1783
mTIM_2_CURRENT-=decval;
1784
if(mTIM_2_CURRENT&0x80000000)
1785
{
1786
// Set carry out
1787
mTIM_2_BORROW_OUT=TRUE;
1788
1789
// // Reload if neccessary
1790
// if(mTIM_2_ENABLE_RELOAD)
1791
// {
1792
mTIM_2_CURRENT+=mTIM_2_BKUP+1;
1793
// }
1794
// else
1795
// {
1796
// mTIM_2_CURRENT=0;
1797
// }
1798
mTIM_2_TIMER_DONE=TRUE;
1799
1800
// Interupt flag setting code moved into DisplayEndOfFrame(), also
1801
// park any CPU cycles lost for later inclusion
1802
mikie_work_done+=DisplayEndOfFrame();
1803
}
1804
else
1805
{
1806
mTIM_2_BORROW_OUT=FALSE;
1807
}
1808
// Set carry in as we did a count
1809
mTIM_2_BORROW_IN=TRUE;
1810
}
1811
else
1812
{
1813
// Clear carry in as we didn't count
1814
mTIM_2_BORROW_IN=FALSE;
1815
// Clear carry out
1816
mTIM_2_BORROW_OUT=FALSE;
1817
}
1818
1819
// Prediction for next timer event cycle number
1820
// We dont need to predict this as its the frame timer and will always
1821
// be beaten by the line timer on Timer 0
1822
// if(mTIM_2_LINKING!=7)
1823
// {
1824
// tmp=gSystemCycleCount+((mTIM_2_CURRENT+1)<<divide);
1825
// if(tmp<gNextTimerEvent) gNextTimerEvent=tmp;
1826
// }
1827
// TRACE_MIKIE1("Update() - mTIM_2_CURRENT = %012d",mTIM_2_CURRENT);
1828
// TRACE_MIKIE1("Update() - mTIM_2_BKUP = %012d",mTIM_2_BKUP);
1829
// TRACE_MIKIE1("Update() - mTIM_2_LASTCNT = %012d",mTIM_2_LAST_COUNT);
1830
// TRACE_MIKIE1("Update() - mTIM_2_LINKING = %012d",mTIM_2_LINKING);
1831
}
1832
1833
//
1834
// Timer 4 of Group A
1835
//
1836
// For the sake of speed it is assumed that Timer 4 (UART timer)
1837
// never uses one-shot mode, never uses linking, hence the code
1838
// is commented out. Timer 4 is at the end of a chain and seems
1839
// no reason to update its carry in-out variables
1840
//
1841
1842
// KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD || ..)
1843
// if(mTIM_4_ENABLE_COUNT && (mTIM_4_ENABLE_RELOAD || !mTIM_4_TIMER_DONE))
1844
if(mTIM_4_ENABLE_COUNT)
1845
{
1846
decval=0;
1847
1848
// if(mTIM_4_LINKING==0x07)
1849
// {
1850
//// if(mTIM_2_BORROW_OUT && !mTIM_4_LAST_LINK_CARRY) decval=1;
1851
// if(mTIM_2_BORROW_OUT) decval=1;
1852
// mTIM_4_LAST_LINK_CARRY=mTIM_2_BORROW_OUT;
1853
// }
1854
// else
1855
{
1856
// Ordinary clocked mode as opposed to linked mode
1857
// 16MHz clock downto 1us == cyclecount >> 4
1858
// Additional /8 (+3) for 8 clocks per bit transmit
1859
divide=4+3+mTIM_4_LINKING;
1860
decval=(mSystem.gSystemCycleCount-mTIM_4_LAST_COUNT)>>divide;
1861
}
1862
1863
if(decval)
1864
{
1865
mTIM_4_LAST_COUNT+=decval<<divide;
1866
mTIM_4_CURRENT-=decval;
1867
if(mTIM_4_CURRENT&0x80000000)
1868
{
1869
// Set carry out
1870
mTIM_4_BORROW_OUT=TRUE;
1871
1872
//
1873
// Update the UART counter models for Rx & Tx
1874
//
1875
1876
//
1877
// According to the docs IRQ's are level triggered and hence will always assert
1878
// what a pain in the arse
1879
//
1880
// Rx & Tx are loopedback due to comlynx structure
1881
1882
//
1883
// Receive
1884
//
1885
if(!mUART_RX_COUNTDOWN)
1886
{
1887
// Fetch a byte from the input queue
1888
if(mUART_Rx_waiting>0)
1889
{
1890
mUART_RX_DATA=mUART_Rx_input_queue[mUART_Rx_output_ptr];
1891
mUART_Rx_output_ptr = (mUART_Rx_output_ptr + 1) % UART_MAX_RX_QUEUE;
1892
mUART_Rx_waiting--;
1893
TRACE_MIKIE2("Update() - RX Byte output ptr=%02d waiting=%02d",mUART_Rx_output_ptr,mUART_Rx_waiting);
1894
}
1895
else
1896
{
1897
TRACE_MIKIE0("Update() - RX Byte but no data waiting ????");
1898
}
1899
1900
// Retrigger input if more bytes waiting
1901
if(mUART_Rx_waiting>0)
1902
{
1903
mUART_RX_COUNTDOWN=UART_RX_TIME_PERIOD+UART_RX_NEXT_DELAY;
1904
TRACE_MIKIE1("Update() - RX Byte retriggered, %d waiting",mUART_Rx_waiting);
1905
}
1906
else
1907
{
1908
mUART_RX_COUNTDOWN=UART_RX_INACTIVE;
1909
TRACE_MIKIE0("Update() - RX Byte nothing waiting, deactivated");
1910
}
1911
1912
// If RX_READY already set then we have an overrun
1913
// as previous byte hasnt been read
1914
if(mUART_RX_READY) mUART_Rx_overun_error=1;
1915
1916
// Flag byte as being recvd
1917
mUART_RX_READY=1;
1918
}
1919
else if(!(mUART_RX_COUNTDOWN&UART_RX_INACTIVE))
1920
{
1921
mUART_RX_COUNTDOWN--;
1922
}
1923
1924
if(!mUART_TX_COUNTDOWN)
1925
{
1926
if(mUART_SENDBREAK)
1927
{
1928
mUART_TX_DATA=UART_BREAK_CODE;
1929
// Auto-Respawn new transmit
1930
mUART_TX_COUNTDOWN=UART_TX_TIME_PERIOD;
1931
// Loop back what we transmitted
1932
ComLynxTxLoopback(mUART_TX_DATA);
1933
}
1934
else
1935
{
1936
// Serial activity finished
1937
mUART_TX_COUNTDOWN=UART_TX_INACTIVE;
1938
}
1939
1940
// If a networking object is attached then use its callback to send the data byte.
1941
if(mpUART_TX_CALLBACK)
1942
{
1943
TRACE_MIKIE0("Update() - UART_TX_CALLBACK");
1944
(*mpUART_TX_CALLBACK)(mUART_TX_DATA,mUART_TX_CALLBACK_OBJECT);
1945
}
1946
1947
}
1948
else if(!(mUART_TX_COUNTDOWN&UART_TX_INACTIVE))
1949
{
1950
mUART_TX_COUNTDOWN--;
1951
}
1952
1953
// Set the timer status flag
1954
// Timer 4 is the uart timer and doesn't generate IRQ's using this method
1955
1956
// 16 Clocks = 1 bit transmission. Hold separate Rx & Tx counters
1957
1958
// Reload if neccessary
1959
// if(mTIM_4_ENABLE_RELOAD)
1960
// {
1961
mTIM_4_CURRENT+=mTIM_4_BKUP+1;
1962
// The low reload values on TIM4 coupled with a longer
1963
// timer service delay can sometimes cause
1964
// an underun, check and fix
1965
if(mTIM_4_CURRENT&0x80000000)
1966
{
1967
mTIM_4_CURRENT=mTIM_4_BKUP;
1968
mTIM_4_LAST_COUNT=mSystem.gSystemCycleCount;
1969
}
1970
// }
1971
// else
1972
// {
1973
// mTIM_4_CURRENT=0;
1974
// }
1975
// mTIM_4_TIMER_DONE=TRUE;
1976
}
1977
// else
1978
// {
1979
// mTIM_4_BORROW_OUT=FALSE;
1980
// }
1981
// // Set carry in as we did a count
1982
// mTIM_4_BORROW_IN=TRUE;
1983
}
1984
// else
1985
// {
1986
// // Clear carry in as we didn't count
1987
// mTIM_4_BORROW_IN=FALSE;
1988
// // Clear carry out
1989
// mTIM_4_BORROW_OUT=FALSE;
1990
// }
1991
//
1992
// // Prediction for next timer event cycle number
1993
//
1994
// if(mTIM_4_LINKING!=7)
1995
// {
1996
// Sometimes timeupdates can be >2x rollover in which case
1997
// then CURRENT may still be negative and we can use it to
1998
// calc the next timer value, we just want another update ASAP
1999
tmp=(mTIM_4_CURRENT&0x80000000)?1:((mTIM_4_CURRENT+1)<<divide);
2000
tmp+=mSystem.gSystemCycleCount;
2001
if(tmp<mSystem.gNextTimerEvent)
2002
{
2003
mSystem.gNextTimerEvent=tmp;
2004
TRACE_MIKIE1("Update() - TIMER 4 Set NextTimerEvent = %012d",gNextTimerEvent);
2005
}
2006
// }
2007
// TRACE_MIKIE1("Update() - mTIM_4_CURRENT = %012d",mTIM_4_CURRENT);
2008
// TRACE_MIKIE1("Update() - mTIM_4_BKUP = %012d",mTIM_4_BKUP);
2009
// TRACE_MIKIE1("Update() - mTIM_4_LASTCNT = %012d",mTIM_4_LAST_COUNT);
2010
// TRACE_MIKIE1("Update() - mTIM_4_LINKING = %012d",mTIM_4_LINKING);
2011
}
2012
2013
// Emulate the UART bug where UART IRQ is level sensitive
2014
// in that it will continue to generate interrupts as long
2015
// as they are enabled and the interrupt condition is true
2016
2017
// If Tx is inactive i.e ready for a byte to eat and the
2018
// IRQ is enabled then generate it always
2019
if((mUART_TX_COUNTDOWN&UART_TX_INACTIVE) && mUART_TX_IRQ_ENABLE)
2020
{
2021
TRACE_MIKIE0("Update() - UART TX IRQ Triggered");
2022
mTimerStatusFlags|=0x10;
2023
}
2024
// Is data waiting and the interrupt enabled, if so then
2025
// what are we waiting for....
2026
if(mUART_RX_READY && mUART_RX_IRQ_ENABLE)
2027
{
2028
TRACE_MIKIE0("Update() - UART RX IRQ Triggered");
2029
mTimerStatusFlags|=0x10;
2030
}
2031
2032
//
2033
// Timer 1 of Group B
2034
//
2035
// KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD || ..)
2036
if(mTIM_1_ENABLE_COUNT && (mTIM_1_ENABLE_RELOAD || !mTIM_1_TIMER_DONE))
2037
{
2038
divide = 0;
2039
if(mTIM_1_LINKING!=0x07)
2040
{
2041
// Ordinary clocked mode as opposed to linked mode
2042
// 16MHz clock downto 1us == cyclecount >> 4
2043
divide=(4+mTIM_1_LINKING);
2044
decval=(mSystem.gSystemCycleCount-mTIM_1_LAST_COUNT)>>divide;
2045
2046
if(decval)
2047
{
2048
mTIM_1_LAST_COUNT+=decval<<divide;
2049
mTIM_1_CURRENT-=decval;
2050
if(mTIM_1_CURRENT&0x80000000)
2051
{
2052
// Set carry out
2053
mTIM_1_BORROW_OUT=TRUE;
2054
2055
// Set the timer status flag
2056
if(mTimerInterruptMask&0x02)
2057
{
2058
TRACE_MIKIE0("Update() - TIMER1 IRQ Triggered");
2059
mTimerStatusFlags|=0x02;
2060
}
2061
2062
// Reload if neccessary
2063
if(mTIM_1_ENABLE_RELOAD)
2064
{
2065
mTIM_1_CURRENT+=mTIM_1_BKUP+1;
2066
}
2067
else
2068
{
2069
mTIM_1_CURRENT=0;
2070
}
2071
mTIM_1_TIMER_DONE=TRUE;
2072
}
2073
else
2074
{
2075
mTIM_1_BORROW_OUT=FALSE;
2076
}
2077
// Set carry in as we did a count
2078
mTIM_1_BORROW_IN=TRUE;
2079
}
2080
else
2081
{
2082
// Clear carry in as we didn't count
2083
mTIM_1_BORROW_IN=FALSE;
2084
// Clear carry out
2085
mTIM_1_BORROW_OUT=FALSE;
2086
}
2087
}
2088
2089
// Prediction for next timer event cycle number
2090
2091
if(mTIM_1_LINKING!=7)
2092
{
2093
// Sometimes timeupdates can be >2x rollover in which case
2094
// then CURRENT may still be negative and we can use it to
2095
// calc the next timer value, we just want another update ASAP
2096
tmp=(mTIM_1_CURRENT&0x80000000)?1:((mTIM_1_CURRENT+1)<<divide);
2097
tmp+=mSystem.gSystemCycleCount;
2098
if(tmp<mSystem.gNextTimerEvent)
2099
{
2100
mSystem.gNextTimerEvent=tmp;
2101
TRACE_MIKIE1("Update() - TIMER 1 Set NextTimerEvent = %012d",gNextTimerEvent);
2102
}
2103
}
2104
// TRACE_MIKIE1("Update() - mTIM_1_CURRENT = %012d",mTIM_1_CURRENT);
2105
// TRACE_MIKIE1("Update() - mTIM_1_BKUP = %012d",mTIM_1_BKUP);
2106
// TRACE_MIKIE1("Update() - mTIM_1_LASTCNT = %012d",mTIM_1_LAST_COUNT);
2107
// TRACE_MIKIE1("Update() - mTIM_1_LINKING = %012d",mTIM_1_LINKING);
2108
}
2109
2110
//
2111
// Timer 3 of Group A
2112
//
2113
// KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD || ..)
2114
if(mTIM_3_ENABLE_COUNT && (mTIM_3_ENABLE_RELOAD || !mTIM_3_TIMER_DONE))
2115
{
2116
decval=0;
2117
2118
if(mTIM_3_LINKING==0x07)
2119
{
2120
if(mTIM_1_BORROW_OUT) decval=1;
2121
mTIM_3_LAST_LINK_CARRY=mTIM_1_BORROW_OUT;
2122
divide = 0;
2123
}
2124
else
2125
{
2126
// Ordinary clocked mode as opposed to linked mode
2127
// 16MHz clock downto 1us == cyclecount >> 4
2128
divide=(4+mTIM_3_LINKING);
2129
decval=(mSystem.gSystemCycleCount-mTIM_3_LAST_COUNT)>>divide;
2130
}
2131
2132
if(decval)
2133
{
2134
mTIM_3_LAST_COUNT+=decval<<divide;
2135
mTIM_3_CURRENT-=decval;
2136
if(mTIM_3_CURRENT&0x80000000)
2137
{
2138
// Set carry out
2139
mTIM_3_BORROW_OUT=TRUE;
2140
2141
// Set the timer status flag
2142
if(mTimerInterruptMask&0x08)
2143
{
2144
TRACE_MIKIE0("Update() - TIMER3 IRQ Triggered");
2145
mTimerStatusFlags|=0x08;
2146
}
2147
2148
// Reload if neccessary
2149
if(mTIM_3_ENABLE_RELOAD)
2150
{
2151
mTIM_3_CURRENT+=mTIM_3_BKUP+1;
2152
}
2153
else
2154
{
2155
mTIM_3_CURRENT=0;
2156
}
2157
mTIM_3_TIMER_DONE=TRUE;
2158
}
2159
else
2160
{
2161
mTIM_3_BORROW_OUT=FALSE;
2162
}
2163
// Set carry in as we did a count
2164
mTIM_3_BORROW_IN=TRUE;
2165
}
2166
else
2167
{
2168
// Clear carry in as we didn't count
2169
mTIM_3_BORROW_IN=FALSE;
2170
// Clear carry out
2171
mTIM_3_BORROW_OUT=FALSE;
2172
}
2173
2174
// Prediction for next timer event cycle number
2175
2176
if(mTIM_3_LINKING!=7)
2177
{
2178
// Sometimes timeupdates can be >2x rollover in which case
2179
// then CURRENT may still be negative and we can use it to
2180
// calc the next timer value, we just want another update ASAP
2181
tmp=(mTIM_3_CURRENT&0x80000000)?1:((mTIM_3_CURRENT+1)<<divide);
2182
tmp+=mSystem.gSystemCycleCount;
2183
if(tmp<mSystem.gNextTimerEvent)
2184
{
2185
mSystem.gNextTimerEvent=tmp;
2186
TRACE_MIKIE1("Update() - TIMER 3 Set NextTimerEvent = %012d",gNextTimerEvent);
2187
}
2188
}
2189
// TRACE_MIKIE1("Update() - mTIM_3_CURRENT = %012d",mTIM_3_CURRENT);
2190
// TRACE_MIKIE1("Update() - mTIM_3_BKUP = %012d",mTIM_3_BKUP);
2191
// TRACE_MIKIE1("Update() - mTIM_3_LASTCNT = %012d",mTIM_3_LAST_COUNT);
2192
// TRACE_MIKIE1("Update() - mTIM_3_LINKING = %012d",mTIM_3_LINKING);
2193
}
2194
2195
//
2196
// Timer 5 of Group A
2197
//
2198
// KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD || ..)
2199
if(mTIM_5_ENABLE_COUNT && (mTIM_5_ENABLE_RELOAD || !mTIM_5_TIMER_DONE))
2200
{
2201
decval=0;
2202
2203
if(mTIM_5_LINKING==0x07)
2204
{
2205
if(mTIM_3_BORROW_OUT) decval=1;
2206
mTIM_5_LAST_LINK_CARRY=mTIM_3_BORROW_OUT;
2207
divide = 0;
2208
}
2209
else
2210
{
2211
// Ordinary clocked mode as opposed to linked mode
2212
// 16MHz clock downto 1us == cyclecount >> 4
2213
divide=(4+mTIM_5_LINKING);
2214
decval=(mSystem.gSystemCycleCount-mTIM_5_LAST_COUNT)>>divide;
2215
}
2216
2217
if(decval)
2218
{
2219
mTIM_5_LAST_COUNT+=decval<<divide;
2220
mTIM_5_CURRENT-=decval;
2221
if(mTIM_5_CURRENT&0x80000000)
2222
{
2223
// Set carry out
2224
mTIM_5_BORROW_OUT=TRUE;
2225
2226
// Set the timer status flag
2227
if(mTimerInterruptMask&0x20)
2228
{
2229
TRACE_MIKIE0("Update() - TIMER5 IRQ Triggered");
2230
mTimerStatusFlags|=0x20;
2231
}
2232
2233
// Reload if neccessary
2234
if(mTIM_5_ENABLE_RELOAD)
2235
{
2236
mTIM_5_CURRENT+=mTIM_5_BKUP+1;
2237
}
2238
else
2239
{
2240
mTIM_5_CURRENT=0;
2241
}
2242
mTIM_5_TIMER_DONE=TRUE;
2243
}
2244
else
2245
{
2246
mTIM_5_BORROW_OUT=FALSE;
2247
}
2248
// Set carry in as we did a count
2249
mTIM_5_BORROW_IN=TRUE;
2250
}
2251
else
2252
{
2253
// Clear carry in as we didn't count
2254
mTIM_5_BORROW_IN=FALSE;
2255
// Clear carry out
2256
mTIM_5_BORROW_OUT=FALSE;
2257
}
2258
2259
// Prediction for next timer event cycle number
2260
2261
if(mTIM_5_LINKING!=7)
2262
{
2263
// Sometimes timeupdates can be >2x rollover in which case
2264
// then CURRENT may still be negative and we can use it to
2265
// calc the next timer value, we just want another update ASAP
2266
tmp=(mTIM_5_CURRENT&0x80000000)?1:((mTIM_5_CURRENT+1)<<divide);
2267
tmp+=mSystem.gSystemCycleCount;
2268
if(tmp<mSystem.gNextTimerEvent)
2269
{
2270
mSystem.gNextTimerEvent=tmp;
2271
TRACE_MIKIE1("Update() - TIMER 5 Set NextTimerEvent = %012d",gNextTimerEvent);
2272
}
2273
}
2274
// TRACE_MIKIE1("Update() - mTIM_5_CURRENT = %012d",mTIM_5_CURRENT);
2275
// TRACE_MIKIE1("Update() - mTIM_5_BKUP = %012d",mTIM_5_BKUP);
2276
// TRACE_MIKIE1("Update() - mTIM_5_LASTCNT = %012d",mTIM_5_LAST_COUNT);
2277
// TRACE_MIKIE1("Update() - mTIM_5_LINKING = %012d",mTIM_5_LINKING);
2278
}
2279
2280
//
2281
// Timer 7 of Group A
2282
//
2283
// KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD || ..)
2284
if(mTIM_7_ENABLE_COUNT && (mTIM_7_ENABLE_RELOAD || !mTIM_7_TIMER_DONE))
2285
{
2286
decval=0;
2287
2288
if(mTIM_7_LINKING==0x07)
2289
{
2290
if(mTIM_5_BORROW_OUT) decval=1;
2291
mTIM_7_LAST_LINK_CARRY=mTIM_5_BORROW_OUT;
2292
divide = 0;
2293
}
2294
else
2295
{
2296
// Ordinary clocked mode as opposed to linked mode
2297
// 16MHz clock downto 1us == cyclecount >> 4
2298
divide=(4+mTIM_7_LINKING);
2299
decval=(mSystem.gSystemCycleCount-mTIM_7_LAST_COUNT)>>divide;
2300
}
2301
2302
if(decval)
2303
{
2304
mTIM_7_LAST_COUNT+=decval<<divide;
2305
mTIM_7_CURRENT-=decval;
2306
if(mTIM_7_CURRENT&0x80000000)
2307
{
2308
// Set carry out
2309
mTIM_7_BORROW_OUT=TRUE;
2310
2311
// Set the timer status flag
2312
if(mTimerInterruptMask&0x80)
2313
{
2314
TRACE_MIKIE0("Update() - TIMER7 IRQ Triggered");
2315
mTimerStatusFlags|=0x80;
2316
}
2317
2318
// Reload if neccessary
2319
if(mTIM_7_ENABLE_RELOAD)
2320
{
2321
mTIM_7_CURRENT+=mTIM_7_BKUP+1;
2322
}
2323
else
2324
{
2325
mTIM_7_CURRENT=0;
2326
}
2327
mTIM_7_TIMER_DONE=TRUE;
2328
2329
}
2330
else
2331
{
2332
mTIM_7_BORROW_OUT=FALSE;
2333
}
2334
// Set carry in as we did a count
2335
mTIM_7_BORROW_IN=TRUE;
2336
}
2337
else
2338
{
2339
// Clear carry in as we didn't count
2340
mTIM_7_BORROW_IN=FALSE;
2341
// Clear carry out
2342
mTIM_7_BORROW_OUT=FALSE;
2343
}
2344
2345
// Prediction for next timer event cycle number
2346
2347
if(mTIM_7_LINKING!=7)
2348
{
2349
// Sometimes timeupdates can be >2x rollover in which case
2350
// then CURRENT may still be negative and we can use it to
2351
// calc the next timer value, we just want another update ASAP
2352
tmp=(mTIM_7_CURRENT&0x80000000)?1:((mTIM_7_CURRENT+1)<<divide);
2353
tmp+=mSystem.gSystemCycleCount;
2354
if(tmp<mSystem.gNextTimerEvent)
2355
{
2356
mSystem.gNextTimerEvent=tmp;
2357
TRACE_MIKIE1("Update() - TIMER 7 Set NextTimerEvent = %012d",gNextTimerEvent);
2358
}
2359
}
2360
// TRACE_MIKIE1("Update() - mTIM_7_CURRENT = %012d",mTIM_7_CURRENT);
2361
// TRACE_MIKIE1("Update() - mTIM_7_BKUP = %012d",mTIM_7_BKUP);
2362
// TRACE_MIKIE1("Update() - mTIM_7_LASTCNT = %012d",mTIM_7_LAST_COUNT);
2363
// TRACE_MIKIE1("Update() - mTIM_7_LINKING = %012d",mTIM_7_LINKING);
2364
}
2365
2366
//
2367
// Timer 6 has no group
2368
//
2369
// KW bugfix 13/4/99 added (mTIM_x_ENABLE_RELOAD || ..)
2370
if(mTIM_6_ENABLE_COUNT && (mTIM_6_ENABLE_RELOAD || !mTIM_6_TIMER_DONE))
2371
{
2372
// if(mTIM_6_LINKING!=0x07)
2373
{
2374
// Ordinary clocked mode as opposed to linked mode
2375
// 16MHz clock downto 1us == cyclecount >> 4
2376
divide=(4+mTIM_6_LINKING);
2377
decval=(mSystem.gSystemCycleCount-mTIM_6_LAST_COUNT)>>divide;
2378
2379
if(decval)
2380
{
2381
mTIM_6_LAST_COUNT+=decval<<divide;
2382
mTIM_6_CURRENT-=decval;
2383
if(mTIM_6_CURRENT&0x80000000)
2384
{
2385
// Set carry out
2386
mTIM_6_BORROW_OUT=TRUE;
2387
2388
// Set the timer status flag
2389
if(mTimerInterruptMask&0x40)
2390
{
2391
TRACE_MIKIE0("Update() - TIMER6 IRQ Triggered");
2392
mTimerStatusFlags|=0x40;
2393
}
2394
2395
// Reload if neccessary
2396
if(mTIM_6_ENABLE_RELOAD)
2397
{
2398
mTIM_6_CURRENT+=mTIM_6_BKUP+1;
2399
}
2400
else
2401
{
2402
mTIM_6_CURRENT=0;
2403
}
2404
mTIM_6_TIMER_DONE=TRUE;
2405
}
2406
else
2407
{
2408
mTIM_6_BORROW_OUT=FALSE;
2409
}
2410
// Set carry in as we did a count
2411
mTIM_6_BORROW_IN=TRUE;
2412
}
2413
else
2414
{
2415
// Clear carry in as we didn't count
2416
mTIM_6_BORROW_IN=FALSE;
2417
// Clear carry out
2418
mTIM_6_BORROW_OUT=FALSE;
2419
}
2420
}
2421
2422
// Prediction for next timer event cycle number
2423
// (Timer 6 doesn't support linking)
2424
2425
// if(mTIM_6_LINKING!=7)
2426
{
2427
// Sometimes timeupdates can be >2x rollover in which case
2428
// then CURRENT may still be negative and we can use it to
2429
// calc the next timer value, we just want another update ASAP
2430
tmp=(mTIM_6_CURRENT&0x80000000)?1:((mTIM_6_CURRENT+1)<<divide);
2431
tmp+=mSystem.gSystemCycleCount;
2432
if(tmp<mSystem.gNextTimerEvent)
2433
{
2434
mSystem.gNextTimerEvent=tmp;
2435
TRACE_MIKIE1("Update() - TIMER 6 Set NextTimerEvent = %012d",gNextTimerEvent);
2436
}
2437
}
2438
// TRACE_MIKIE1("Update() - mTIM_6_CURRENT = %012d",mTIM_6_CURRENT);
2439
// TRACE_MIKIE1("Update() - mTIM_6_BKUP = %012d",mTIM_6_BKUP);
2440
// TRACE_MIKIE1("Update() - mTIM_6_LASTCNT = %012d",mTIM_6_LAST_COUNT);
2441
// TRACE_MIKIE1("Update() - mTIM_6_LINKING = %012d",mTIM_6_LINKING);
2442
}
2443
2444
//
2445
// Update the sound subsystem
2446
//
2447
{
2448
int y;
2449
for(y = 0; y < 4; y++)
2450
{
2451
if(mAUDIO_ENABLE_COUNT[y] && (mAUDIO_ENABLE_RELOAD[y] || !mAUDIO_TIMER_DONE[y]))
2452
{
2453
decval=0;
2454
2455
if(mAUDIO_LINKING[y]==0x07)
2456
{
2457
int bort;
2458
if(y)
2459
bort = mAUDIO_BORROW_OUT[y - 1];
2460
else
2461
bort = mTIM_7_BORROW_OUT;
2462
2463
if(bort) decval=1;
2464
mAUDIO_LAST_LINK_CARRY[y]=bort;
2465
divide = 0;
2466
}
2467
else
2468
{
2469
// Ordinary clocked mode as opposed to linked mode
2470
// 16MHz clock downto 1us == cyclecount >> 4
2471
divide=(4+mAUDIO_LINKING[y]);
2472
decval=(mSystem.gSystemCycleCount-mAUDIO_LAST_COUNT[y])>>divide;
2473
}
2474
2475
if(decval)
2476
{
2477
mAUDIO_LAST_COUNT[y] += decval<<divide;
2478
mAUDIO_CURRENT[y]-=decval;
2479
if(mAUDIO_CURRENT[y]&0x80000000)
2480
{
2481
// Set carry out
2482
mAUDIO_BORROW_OUT[y]=TRUE;
2483
2484
// Reload if neccessary
2485
if(mAUDIO_ENABLE_RELOAD[y])
2486
{
2487
mAUDIO_CURRENT[y]+=mAUDIO_BKUP[y]+1;
2488
if(mAUDIO_CURRENT[y]&0x80000000) mAUDIO_CURRENT[y]=0;
2489
}
2490
else
2491
{
2492
// Set timer done
2493
mAUDIO_TIMER_DONE[y]=TRUE;
2494
mAUDIO_CURRENT[y]=0;
2495
}
2496
2497
//
2498
// Update audio circuitry
2499
//
2500
if(mAUDIO_BKUP[y] || mAUDIO_LINKING[y])
2501
mAUDIO_WAVESHAPER[y] = GetLfsrNext(mAUDIO_WAVESHAPER[y]);
2502
2503
if(mAUDIO_INTEGRATE_ENABLE[y])
2504
{
2505
int32 temp=mAUDIO_OUTPUT[y];
2506
if(mAUDIO_WAVESHAPER[y]&0x0001) temp+=mAUDIO_VOLUME[y]; else temp-=mAUDIO_VOLUME[y];
2507
if(temp>127) temp=127;
2508
if(temp<-128) temp=-128;
2509
mAUDIO_OUTPUT[y]=(int8)temp;
2510
}
2511
else
2512
{
2513
if(mAUDIO_WAVESHAPER[y]&0x0001) mAUDIO_OUTPUT[y]=mAUDIO_VOLUME[y]; else mAUDIO_OUTPUT[y]=-mAUDIO_VOLUME[y];
2514
}
2515
CombobulateSound(mSystem.gSystemCycleCount - startTS);
2516
}
2517
else
2518
{
2519
mAUDIO_BORROW_OUT[y]=FALSE;
2520
}
2521
// Set carry in as we did a count
2522
mAUDIO_BORROW_IN[y]=TRUE;
2523
}
2524
else
2525
{
2526
// Clear carry in as we didn't count
2527
mAUDIO_BORROW_IN[y]=FALSE;
2528
// Clear carry out
2529
mAUDIO_BORROW_OUT[y]=FALSE;
2530
}
2531
2532
// Prediction for next timer event cycle number
2533
2534
if(mAUDIO_LINKING[y]!=7)
2535
{
2536
// Sometimes timeupdates can be >2x rollover in which case
2537
// then CURRENT may still be negative and we can use it to
2538
// calc the next timer value, we just want another update ASAP
2539
tmp=(mAUDIO_CURRENT[y]&0x80000000)?1:((mAUDIO_CURRENT[y]+1)<<divide);
2540
tmp+=mSystem.gSystemCycleCount;
2541
if(tmp<mSystem.gNextTimerEvent)
2542
{
2543
mSystem.gNextTimerEvent=tmp;
2544
TRACE_MIKIE1("Update() - AUDIO 0 Set NextTimerEvent = %012d",gNextTimerEvent);
2545
}
2546
}
2547
}
2548
}
2549
}
2550
2551
// if(gSystemCycleCount==gNextTimerEvent) gError->Warning("CMikie::Update() - gSystemCycleCount==gNextTimerEvent, system lock likely");
2552
// TRACE_MIKIE1("Update() - NextTimerEvent = %012d",gNextTimerEvent);
2553
2554
// Update system IRQ status as a result of timer activity
2555
// OR is required to ensure serial IRQ's are not masked accidentally
2556
2557
mSystem.gSystemIRQ=(mTimerStatusFlags)?TRUE:FALSE;
2558
if(mSystem.gSystemIRQ && mSystem.gSystemCPUSleep) { ClearCPUSleep(); /*puts("ARLARM"); */ }
2559
//else if(gSuzieDoneTime) SetCPUSleep();
2560
2561
// Now all the timer updates are done we can increment the system
2562
// counter for any work done within the Update() function, gSystemCycleCounter
2563
// cannot be updated until this point otherwise it screws up the counters.
2564
mSystem.gSystemCycleCount+=mikie_work_done;
2565
}
2566
2567
SYNCFUNC(CMikie)
2568
{
2569
NSS(startTS);
2570
// SSS(miksynth);
2571
// SSS(mikbuf);
2572
2573
// mpDisplayCurrent;
2574
NSS(mpDisplayCurrentLine);
2575
NSS(framebuffer);
2576
2577
NSS(last_lsample);
2578
NSS(last_rsample);
2579
2580
NSS(mDisplayAddress);
2581
NSS(mAudioInputComparator);
2582
NSS(mTimerStatusFlags);
2583
NSS(mTimerInterruptMask);
2584
2585
NSS(mPalette);
2586
NSS(mColourMap);
2587
2588
NSS(mIODAT);
2589
NSS(mIODIR);
2590
NSS(mIODAT_REST_SIGNAL);
2591
2592
NSS(mDISPCTL_DMAEnable);
2593
NSS(mDISPCTL_Flip);
2594
NSS(mDISPCTL_FourColour);
2595
NSS(mDISPCTL_Colour);
2596
2597
2598
2599
NSS(mTIM_0_BKUP);
2600
NSS(mTIM_0_ENABLE_RELOAD);
2601
NSS(mTIM_0_ENABLE_COUNT);
2602
NSS(mTIM_0_LINKING);
2603
NSS(mTIM_0_CURRENT);
2604
NSS(mTIM_0_TIMER_DONE);
2605
NSS(mTIM_0_LAST_CLOCK);
2606
NSS(mTIM_0_BORROW_IN);
2607
NSS(mTIM_0_BORROW_OUT);
2608
NSS(mTIM_0_LAST_LINK_CARRY);
2609
NSS(mTIM_0_LAST_COUNT);
2610
2611
NSS(mTIM_1_BKUP);
2612
NSS(mTIM_1_ENABLE_RELOAD);
2613
NSS(mTIM_1_ENABLE_COUNT);
2614
NSS(mTIM_1_LINKING);
2615
NSS(mTIM_1_CURRENT);
2616
NSS(mTIM_1_TIMER_DONE);
2617
NSS(mTIM_1_LAST_CLOCK);
2618
NSS(mTIM_1_BORROW_IN);
2619
NSS(mTIM_1_BORROW_OUT);
2620
NSS(mTIM_1_LAST_LINK_CARRY);
2621
NSS(mTIM_1_LAST_COUNT);
2622
2623
NSS(mTIM_2_BKUP);
2624
NSS(mTIM_2_ENABLE_RELOAD);
2625
NSS(mTIM_2_ENABLE_COUNT);
2626
NSS(mTIM_2_LINKING);
2627
NSS(mTIM_2_CURRENT);
2628
NSS(mTIM_2_TIMER_DONE);
2629
NSS(mTIM_2_LAST_CLOCK);
2630
NSS(mTIM_2_BORROW_IN);
2631
NSS(mTIM_2_BORROW_OUT);
2632
NSS(mTIM_2_LAST_LINK_CARRY);
2633
NSS(mTIM_2_LAST_COUNT);
2634
2635
NSS(mTIM_3_BKUP);
2636
NSS(mTIM_3_ENABLE_RELOAD);
2637
NSS(mTIM_3_ENABLE_COUNT);
2638
NSS(mTIM_3_LINKING);
2639
NSS(mTIM_3_CURRENT);
2640
NSS(mTIM_3_TIMER_DONE);
2641
NSS(mTIM_3_LAST_CLOCK);
2642
NSS(mTIM_3_BORROW_IN);
2643
NSS(mTIM_3_BORROW_OUT);
2644
NSS(mTIM_3_LAST_LINK_CARRY);
2645
NSS(mTIM_3_LAST_COUNT);
2646
2647
NSS(mTIM_4_BKUP);
2648
NSS(mTIM_4_ENABLE_RELOAD);
2649
NSS(mTIM_4_ENABLE_COUNT);
2650
NSS(mTIM_4_LINKING);
2651
NSS(mTIM_4_CURRENT);
2652
NSS(mTIM_4_TIMER_DONE);
2653
NSS(mTIM_4_LAST_CLOCK);
2654
NSS(mTIM_4_BORROW_IN);
2655
NSS(mTIM_4_BORROW_OUT);
2656
NSS(mTIM_4_LAST_LINK_CARRY);
2657
NSS(mTIM_4_LAST_COUNT);
2658
2659
NSS(mTIM_5_BKUP);
2660
NSS(mTIM_5_ENABLE_RELOAD);
2661
NSS(mTIM_5_ENABLE_COUNT);
2662
NSS(mTIM_5_LINKING);
2663
NSS(mTIM_5_CURRENT);
2664
NSS(mTIM_5_TIMER_DONE);
2665
NSS(mTIM_5_LAST_CLOCK);
2666
NSS(mTIM_5_BORROW_IN);
2667
NSS(mTIM_5_BORROW_OUT);
2668
NSS(mTIM_5_LAST_LINK_CARRY);
2669
NSS(mTIM_5_LAST_COUNT);
2670
2671
NSS(mTIM_6_BKUP);
2672
NSS(mTIM_6_ENABLE_RELOAD);
2673
NSS(mTIM_6_ENABLE_COUNT);
2674
NSS(mTIM_6_LINKING);
2675
NSS(mTIM_6_CURRENT);
2676
NSS(mTIM_6_TIMER_DONE);
2677
NSS(mTIM_6_LAST_CLOCK);
2678
NSS(mTIM_6_BORROW_IN);
2679
NSS(mTIM_6_BORROW_OUT);
2680
NSS(mTIM_6_LAST_LINK_CARRY);
2681
NSS(mTIM_6_LAST_COUNT);
2682
2683
NSS(mTIM_7_BKUP);
2684
NSS(mTIM_7_ENABLE_RELOAD);
2685
NSS(mTIM_7_ENABLE_COUNT);
2686
NSS(mTIM_7_LINKING);
2687
NSS(mTIM_7_CURRENT);
2688
NSS(mTIM_7_TIMER_DONE);
2689
NSS(mTIM_7_LAST_CLOCK);
2690
NSS(mTIM_7_BORROW_IN);
2691
NSS(mTIM_7_BORROW_OUT);
2692
NSS(mTIM_7_LAST_LINK_CARRY);
2693
NSS(mTIM_7_LAST_COUNT);
2694
2695
NSS(mAUDIO_BKUP);
2696
NSS(mAUDIO_ENABLE_RELOAD);
2697
NSS(mAUDIO_ENABLE_COUNT);
2698
NSS(mAUDIO_LINKING);
2699
NSS(mAUDIO_CURRENT);
2700
NSS(mAUDIO_TIMER_DONE);
2701
NSS(mAUDIO_LAST_CLOCK);
2702
NSS(mAUDIO_BORROW_IN);
2703
NSS(mAUDIO_BORROW_OUT);
2704
NSS(mAUDIO_LAST_LINK_CARRY);
2705
NSS(mAUDIO_LAST_COUNT);
2706
NSS(mAUDIO_VOLUME);
2707
NSS(mAUDIO_INTEGRATE_ENABLE);
2708
NSS(mAUDIO_WAVESHAPER);
2709
2710
NSS(mAUDIO_OUTPUT);
2711
NSS(mAUDIO_ATTEN);
2712
NSS(mSTEREO);
2713
NSS(mPAN);
2714
2715
2716
2717
NSS(mUART_RX_IRQ_ENABLE);
2718
NSS(mUART_TX_IRQ_ENABLE);
2719
2720
NSS(mUART_RX_COUNTDOWN);
2721
NSS(mUART_TX_COUNTDOWN);
2722
2723
NSS(mUART_SENDBREAK);
2724
NSS(mUART_TX_DATA);
2725
NSS(mUART_RX_DATA);
2726
NSS(mUART_RX_READY);
2727
2728
NSS(mUART_PARITY_ENABLE);
2729
NSS(mUART_PARITY_EVEN);
2730
2731
NSS(mUART_CABLE_PRESENT);
2732
// mpUART_TX_CALLBACK;
2733
// mUART_TX_CALLBACK_OBJECT;
2734
2735
NSS(mUART_Rx_input_queue);
2736
NSS(mUART_Rx_input_ptr);
2737
NSS(mUART_Rx_output_ptr);
2738
NSS(mUART_Rx_waiting);
2739
NSS(mUART_Rx_framing_error);
2740
NSS(mUART_Rx_overun_error);
2741
2742
2743
// mpRamPointer;
2744
NSS(mLynxLine);
2745
NSS(mLynxLineDMACounter);
2746
NSS(mLynxAddr);
2747
}
2748
2749