Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/vbanext/instance.cpp
2 views
1
#include <cstdio>
2
#include <time.h>
3
#include <cstdlib>
4
#include <cstring>
5
#include <algorithm>
6
7
#include <stdint.h>
8
#include <limits.h>
9
#include <math.h>
10
11
#define LSB_FIRST
12
#ifdef SPEEDHAX
13
#error NO SPEEDHAX
14
#endif
15
#define HAVE_HLE_BIOS
16
17
#include "port.h"
18
19
#include "instance.h"
20
21
#include "sound_blargg.h"
22
23
#include "constarrays.h"
24
25
#include "newstate.h"
26
27
#define INLINE
28
29
class Gigazoid
30
{
31
32
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
33
// BEGIN MEMORY.CPP
34
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
35
36
/*============================================================
37
FLASH
38
============================================================ */
39
40
41
#define FLASH_READ_ARRAY 0
42
#define FLASH_CMD_1 1
43
#define FLASH_CMD_2 2
44
#define FLASH_AUTOSELECT 3
45
#define FLASH_CMD_3 4
46
#define FLASH_CMD_4 5
47
#define FLASH_CMD_5 6
48
#define FLASH_ERASE_COMPLETE 7
49
#define FLASH_PROGRAM 8
50
#define FLASH_SETBANK 9
51
52
uint8_t flashSaveMemory[FLASH_128K_SZ];
53
54
int flashState; // = FLASH_READ_ARRAY;
55
int flashReadState; // = FLASH_READ_ARRAY;
56
int flashSize; // = 0x10000;
57
int flashDeviceID; // = 0x1b;
58
int flashManufacturerID; // = 0x32;
59
int flashBank; // = 0;
60
61
void flashInit (void)
62
{
63
memset(flashSaveMemory, 0xff, sizeof(flashSaveMemory));
64
}
65
66
void flashReset()
67
{
68
flashState = FLASH_READ_ARRAY;
69
flashReadState = FLASH_READ_ARRAY;
70
flashBank = 0;
71
}
72
73
uint8_t flashRead(uint32_t address)
74
{
75
address &= 0xFFFF;
76
77
switch(flashReadState) {
78
case FLASH_READ_ARRAY:
79
return flashSaveMemory[(flashBank << 16) + address];
80
case FLASH_AUTOSELECT:
81
switch(address & 0xFF)
82
{
83
case 0:
84
// manufacturer ID
85
return flashManufacturerID;
86
case 1:
87
// device ID
88
return flashDeviceID;
89
}
90
break;
91
case FLASH_ERASE_COMPLETE:
92
flashState = FLASH_READ_ARRAY;
93
flashReadState = FLASH_READ_ARRAY;
94
return 0xFF;
95
};
96
return 0;
97
}
98
99
void flashSaveDecide(uint32_t address, uint8_t byte)
100
{
101
if (address == 0x0e005555)
102
cpuSaveGameFunc = &Gigazoid::flashWrite;
103
else
104
cpuSaveGameFunc = &Gigazoid::sramWrite;
105
106
(this->*cpuSaveGameFunc)(address, byte);
107
}
108
109
void flashWrite(uint32_t address, uint8_t byte)
110
{
111
address &= 0xFFFF;
112
switch(flashState) {
113
case FLASH_READ_ARRAY:
114
if(address == 0x5555 && byte == 0xAA)
115
flashState = FLASH_CMD_1;
116
break;
117
case FLASH_CMD_1:
118
if(address == 0x2AAA && byte == 0x55)
119
flashState = FLASH_CMD_2;
120
else
121
flashState = FLASH_READ_ARRAY;
122
break;
123
case FLASH_CMD_2:
124
if(address == 0x5555) {
125
if(byte == 0x90) {
126
flashState = FLASH_AUTOSELECT;
127
flashReadState = FLASH_AUTOSELECT;
128
} else if(byte == 0x80) {
129
flashState = FLASH_CMD_3;
130
} else if(byte == 0xF0) {
131
flashState = FLASH_READ_ARRAY;
132
flashReadState = FLASH_READ_ARRAY;
133
} else if(byte == 0xA0) {
134
flashState = FLASH_PROGRAM;
135
} else if(byte == 0xB0 && flashSize == 0x20000) {
136
flashState = FLASH_SETBANK;
137
} else {
138
flashState = FLASH_READ_ARRAY;
139
flashReadState = FLASH_READ_ARRAY;
140
}
141
} else {
142
flashState = FLASH_READ_ARRAY;
143
flashReadState = FLASH_READ_ARRAY;
144
}
145
break;
146
case FLASH_CMD_3:
147
if(address == 0x5555 && byte == 0xAA) {
148
flashState = FLASH_CMD_4;
149
} else {
150
flashState = FLASH_READ_ARRAY;
151
flashReadState = FLASH_READ_ARRAY;
152
}
153
break;
154
case FLASH_CMD_4:
155
if(address == 0x2AAA && byte == 0x55) {
156
flashState = FLASH_CMD_5;
157
} else {
158
flashState = FLASH_READ_ARRAY;
159
flashReadState = FLASH_READ_ARRAY;
160
}
161
break;
162
case FLASH_CMD_5:
163
if(byte == 0x30) {
164
// SECTOR ERASE
165
memset(&flashSaveMemory[(flashBank << 16) + (address & 0xF000)],
166
0,
167
0x1000);
168
flashReadState = FLASH_ERASE_COMPLETE;
169
} else if(byte == 0x10) {
170
// CHIP ERASE
171
memset(flashSaveMemory, 0, flashSize);
172
flashReadState = FLASH_ERASE_COMPLETE;
173
} else {
174
flashState = FLASH_READ_ARRAY;
175
flashReadState = FLASH_READ_ARRAY;
176
}
177
break;
178
case FLASH_AUTOSELECT:
179
if(byte == 0xF0) {
180
flashState = FLASH_READ_ARRAY;
181
flashReadState = FLASH_READ_ARRAY;
182
} else if(address == 0x5555 && byte == 0xAA)
183
flashState = FLASH_CMD_1;
184
else {
185
flashState = FLASH_READ_ARRAY;
186
flashReadState = FLASH_READ_ARRAY;
187
}
188
break;
189
case FLASH_PROGRAM:
190
flashSaveMemory[(flashBank<<16)+address] = byte;
191
flashState = FLASH_READ_ARRAY;
192
flashReadState = FLASH_READ_ARRAY;
193
break;
194
case FLASH_SETBANK:
195
if(address == 0) {
196
flashBank = (byte & 1);
197
}
198
flashState = FLASH_READ_ARRAY;
199
flashReadState = FLASH_READ_ARRAY;
200
break;
201
}
202
}
203
204
/*============================================================
205
EEPROM
206
============================================================ */
207
int eepromMode; // = EEPROM_IDLE;
208
int eepromByte; // = 0;
209
int eepromBits; // = 0;
210
int eepromAddress; // = 0;
211
212
u8 eepromData[0x2000];
213
214
u8 eepromBuffer[16];
215
bool eepromInUse; // = false;
216
int eepromSize; // = 512;
217
218
void eepromInit (void)
219
{
220
memset(eepromData, 255, sizeof(eepromData));
221
}
222
223
void eepromReset (void)
224
{
225
eepromMode = EEPROM_IDLE;
226
eepromByte = 0;
227
eepromBits = 0;
228
eepromAddress = 0;
229
eepromInUse = false;
230
eepromSize = 512;
231
}
232
233
int eepromRead (void)
234
{
235
switch(eepromMode)
236
{
237
case EEPROM_IDLE:
238
case EEPROM_READADDRESS:
239
case EEPROM_WRITEDATA:
240
return 1;
241
case EEPROM_READDATA:
242
{
243
eepromBits++;
244
if(eepromBits == 4) {
245
eepromMode = EEPROM_READDATA2;
246
eepromBits = 0;
247
eepromByte = 0;
248
}
249
return 0;
250
}
251
case EEPROM_READDATA2:
252
{
253
int data = 0;
254
int address = eepromAddress << 3;
255
int mask = 1 << (7 - (eepromBits & 7));
256
data = (eepromData[address+eepromByte] & mask) ? 1 : 0;
257
eepromBits++;
258
if((eepromBits & 7) == 0)
259
eepromByte++;
260
if(eepromBits == 0x40)
261
eepromMode = EEPROM_IDLE;
262
return data;
263
}
264
default:
265
return 0;
266
}
267
return 1;
268
}
269
270
void eepromWrite(u8 value)
271
{
272
if(cpuDmaCount == 0)
273
return;
274
int bit = value & 1;
275
switch(eepromMode) {
276
case EEPROM_IDLE:
277
eepromByte = 0;
278
eepromBits = 1;
279
eepromBuffer[eepromByte] = bit;
280
eepromMode = EEPROM_READADDRESS;
281
break;
282
case EEPROM_READADDRESS:
283
eepromBuffer[eepromByte] <<= 1;
284
eepromBuffer[eepromByte] |= bit;
285
eepromBits++;
286
if((eepromBits & 7) == 0) {
287
eepromByte++;
288
}
289
if(cpuDmaCount == 0x11 || cpuDmaCount == 0x51) {
290
if(eepromBits == 0x11) {
291
eepromInUse = true;
292
eepromSize = 0x2000;
293
eepromAddress = ((eepromBuffer[0] & 0x3F) << 8) |
294
((eepromBuffer[1] & 0xFF));
295
if(!(eepromBuffer[0] & 0x40)) {
296
eepromBuffer[0] = bit;
297
eepromBits = 1;
298
eepromByte = 0;
299
eepromMode = EEPROM_WRITEDATA;
300
} else {
301
eepromMode = EEPROM_READDATA;
302
eepromByte = 0;
303
eepromBits = 0;
304
}
305
}
306
} else {
307
if(eepromBits == 9) {
308
eepromInUse = true;
309
eepromAddress = (eepromBuffer[0] & 0x3F);
310
if(!(eepromBuffer[0] & 0x40)) {
311
eepromBuffer[0] = bit;
312
eepromBits = 1;
313
eepromByte = 0;
314
eepromMode = EEPROM_WRITEDATA;
315
} else {
316
eepromMode = EEPROM_READDATA;
317
eepromByte = 0;
318
eepromBits = 0;
319
}
320
}
321
}
322
break;
323
case EEPROM_READDATA:
324
case EEPROM_READDATA2:
325
// should we reset here?
326
eepromMode = EEPROM_IDLE;
327
break;
328
case EEPROM_WRITEDATA:
329
eepromBuffer[eepromByte] <<= 1;
330
eepromBuffer[eepromByte] |= bit;
331
eepromBits++;
332
if((eepromBits & 7) == 0)
333
eepromByte++;
334
if(eepromBits == 0x40)
335
{
336
eepromInUse = true;
337
// write data;
338
for(int i = 0; i < 8; i++)
339
eepromData[(eepromAddress << 3) + i] = eepromBuffer[i];
340
}
341
else if(eepromBits == 0x41)
342
{
343
eepromMode = EEPROM_IDLE;
344
eepromByte = 0;
345
eepromBits = 0;
346
}
347
break;
348
}
349
}
350
351
/*============================================================
352
SRAM
353
============================================================ */
354
355
u8 sramRead(u32 address)
356
{
357
return flashSaveMemory[address & 0xFFFF];
358
}
359
360
void sramWrite(u32 address, u8 byte)
361
{
362
flashSaveMemory[address & 0xFFFF] = byte;
363
}
364
365
void dummyWrite(u32 address, u8 byte)
366
{
367
}
368
369
/*============================================================
370
RTC
371
============================================================ */
372
373
#define IDLE 0
374
#define COMMAND 1
375
#define DATA 2
376
#define READDATA 3
377
378
typedef struct
379
{
380
u8 byte0;
381
u8 byte1;
382
u8 byte2;
383
u8 command;
384
int dataLen;
385
int bits;
386
int state;
387
u8 data[12];
388
} RTCCLOCKDATA;
389
390
RTCCLOCKDATA rtcClockData;
391
bool rtcEnabled; // = false;
392
393
u16 rtcRead(u32 address)
394
{
395
switch(address)
396
{
397
case 0x80000c8:
398
return rtcClockData.byte2;
399
case 0x80000c6:
400
return rtcClockData.byte1;
401
case 0x80000c4:
402
return rtcClockData.byte0;
403
default:
404
return 0;
405
}
406
}
407
408
static u8 toBCD(u8 value)
409
{
410
value = value % 100;
411
int l = value % 10;
412
int h = value / 10;
413
return h * 16 + l;
414
}
415
416
bool rtcWrite(u32 address, u16 value)
417
{
418
if(!rtcEnabled)
419
return false;
420
421
if(address == 0x80000c8)
422
rtcClockData.byte2 = (u8)value; // enable ?
423
else if(address == 0x80000c6)
424
rtcClockData.byte1 = (u8)value; // read/write
425
else if(address == 0x80000c4)
426
{
427
if(rtcClockData.byte2 & 1) // enable
428
{
429
if(rtcClockData.state == IDLE && rtcClockData.byte0 == 1 && value == 5)
430
{
431
rtcClockData.state = COMMAND;
432
rtcClockData.bits = 0;
433
rtcClockData.command = 0;
434
}
435
else if(!(rtcClockData.byte0 & 1) && (value & 1))
436
{ // bit transfer
437
rtcClockData.byte0 = (u8)value;
438
switch(rtcClockData.state)
439
{
440
case COMMAND:
441
rtcClockData.command |= ((value & 2) >> 1) << (7-rtcClockData.bits);
442
rtcClockData.bits++;
443
if(rtcClockData.bits == 8)
444
{
445
rtcClockData.bits = 0;
446
switch(rtcClockData.command)
447
{
448
case 0x60:
449
// not sure what this command does but it doesn't take parameters
450
// maybe it is a reset or stop
451
rtcClockData.state = IDLE;
452
rtcClockData.bits = 0;
453
break;
454
case 0x62:
455
// this sets the control state but not sure what those values are
456
rtcClockData.state = READDATA;
457
rtcClockData.dataLen = 1;
458
break;
459
case 0x63:
460
rtcClockData.dataLen = 1;
461
rtcClockData.data[0] = 0x40;
462
rtcClockData.state = DATA;
463
break;
464
case 0x64:
465
break;
466
case 0x65:
467
{
468
tm newtime;
469
GetTime(newtime);
470
rtcClockData.dataLen = 7;
471
rtcClockData.data[0] = toBCD(newtime.tm_year);
472
rtcClockData.data[1] = toBCD(newtime.tm_mon+1);
473
rtcClockData.data[2] = toBCD(newtime.tm_mday);
474
rtcClockData.data[3] = toBCD(newtime.tm_wday);
475
rtcClockData.data[4] = toBCD(newtime.tm_hour);
476
rtcClockData.data[5] = toBCD(newtime.tm_min);
477
rtcClockData.data[6] = toBCD(newtime.tm_sec);
478
rtcClockData.state = DATA;
479
}
480
break;
481
case 0x67:
482
{
483
tm newtime;
484
GetTime(newtime);
485
rtcClockData.dataLen = 3;
486
rtcClockData.data[0] = toBCD(newtime.tm_hour);
487
rtcClockData.data[1] = toBCD(newtime.tm_min);
488
rtcClockData.data[2] = toBCD(newtime.tm_sec);
489
rtcClockData.state = DATA;
490
}
491
break;
492
default:
493
//systemMessage(0, "Unknown RTC command %02x", rtcClockData.command);
494
rtcClockData.state = IDLE;
495
break;
496
}
497
}
498
break;
499
case DATA:
500
if(rtcClockData.byte1 & 2)
501
{
502
}
503
else
504
{
505
rtcClockData.byte0 = (rtcClockData.byte0 & ~2) |
506
((rtcClockData.data[rtcClockData.bits >> 3] >>
507
(rtcClockData.bits & 7)) & 1)*2;
508
rtcClockData.bits++;
509
if(rtcClockData.bits == 8*rtcClockData.dataLen)
510
{
511
rtcClockData.bits = 0;
512
rtcClockData.state = IDLE;
513
}
514
}
515
break;
516
case READDATA:
517
if(!(rtcClockData.byte1 & 2)) {
518
} else {
519
rtcClockData.data[rtcClockData.bits >> 3] =
520
(rtcClockData.data[rtcClockData.bits >> 3] >> 1) |
521
((value << 6) & 128);
522
rtcClockData.bits++;
523
if(rtcClockData.bits == 8*rtcClockData.dataLen) {
524
rtcClockData.bits = 0;
525
rtcClockData.state = IDLE;
526
}
527
}
528
break;
529
default:
530
break;
531
}
532
} else
533
rtcClockData.byte0 = (u8)value;
534
}
535
}
536
return true;
537
}
538
539
void rtcReset (void)
540
{
541
memset(&rtcClockData, 0, sizeof(rtcClockData));
542
543
rtcClockData.byte0 = 0;
544
rtcClockData.byte1 = 0;
545
rtcClockData.byte2 = 0;
546
rtcClockData.command = 0;
547
rtcClockData.dataLen = 0;
548
rtcClockData.bits = 0;
549
rtcClockData.state = IDLE;
550
}
551
552
// guarantees predictable results regardless of stdlib
553
// could be modified later to better match internal quirks of
554
// the RTC chip actually used
555
struct
556
{
557
int year; // 00..99
558
int month; // 00..11
559
int mday; // 01..31
560
int wday; // 00..06
561
int hour; // 00..23
562
int min; // 00..59
563
int sec; // 00..59
564
565
template<bool isReader>void SyncState(NewState *ns)
566
{
567
NSS(year);
568
NSS(month);
569
NSS(mday);
570
NSS(wday);
571
NSS(hour);
572
NSS(min);
573
NSS(sec);
574
}
575
576
private:
577
int DaysInMonth()
578
{
579
// gba rtc doesn't understand 100/400 exceptions
580
int result = daysinmonth[month];
581
if (month == 1 && year % 4 == 0)
582
result++;
583
return result;
584
}
585
586
public:
587
void Increment()
588
{
589
sec++;
590
if (sec >= 60)
591
{
592
sec = 0;
593
min++;
594
if (min >= 60)
595
{
596
min = 0;
597
hour++;
598
if (hour >= 24)
599
{
600
hour = 0;
601
wday++;
602
if (wday >= 7)
603
wday = 0;
604
mday++;
605
if (mday >= DaysInMonth())
606
{
607
mday = 1;
608
month++;
609
if (month >= 12)
610
{
611
month = 0;
612
year++;
613
if (year >= 100)
614
year = 0;
615
}
616
}
617
}
618
}
619
}
620
}
621
622
} rtcInternalTime;
623
624
void GetTime(tm &times)
625
{
626
if (RTCUseRealTime)
627
{
628
time_t t = time(nullptr);
629
#if defined _MSC_VER
630
gmtime_s(&times, &t);
631
#elif defined __MINGW32__
632
tm *tmp = gmtime(&t);
633
times = *tmp;
634
#elif defined __GNUC__
635
gmtime_r(&t, &times);
636
#endif
637
}
638
else
639
{
640
times.tm_hour = rtcInternalTime.hour;
641
times.tm_mday = rtcInternalTime.mday;
642
times.tm_min = rtcInternalTime.min;
643
times.tm_mon = rtcInternalTime.month;
644
times.tm_sec = rtcInternalTime.sec;
645
times.tm_wday = rtcInternalTime.wday;
646
times.tm_year = rtcInternalTime.year;
647
}
648
}
649
650
int RTCTicks;
651
bool RTCUseRealTime;
652
653
void AdvanceRTC(int ticks)
654
{
655
RTCTicks += ticks;
656
while (RTCTicks >= 16777216)
657
{
658
RTCTicks -= 16777216;
659
rtcInternalTime.Increment();
660
}
661
}
662
663
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
664
// END MEMORY.CPP
665
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
666
667
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
668
// BEGIN SOUND.CPP
669
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
670
#define NR10 0x60
671
#define NR11 0x62
672
#define NR12 0x63
673
#define NR13 0x64
674
#define NR14 0x65
675
#define NR21 0x68
676
#define NR22 0x69
677
#define NR23 0x6c
678
#define NR24 0x6d
679
#define NR30 0x70
680
#define NR31 0x72
681
#define NR32 0x73
682
#define NR33 0x74
683
#define NR34 0x75
684
#define NR41 0x78
685
#define NR42 0x79
686
#define NR43 0x7c
687
#define NR44 0x7d
688
#define NR50 0x80
689
#define NR51 0x81
690
#define NR52 0x84
691
692
/* 1/100th of a second */
693
//#define SOUND_CLOCK_TICKS_ 167772
694
#define SOUNDVOLUME 0.5f
695
#define SOUNDVOLUME_ -1
696
697
/*============================================================
698
CLASS DECLS
699
============================================================ */
700
701
class Blip_Buffer
702
{
703
public:
704
template<bool isReader>void SyncState(NewState *ns)
705
{
706
NSS(clock_rate_);
707
NSS(length_);
708
NSS(sample_rate_);
709
NSS(factor_);
710
NSS(offset_);
711
// int32_t *buffer_; shouldn't need to save
712
NSS(buffer_size_);
713
NSS(reader_accum_);
714
715
}
716
717
Blip_Buffer::Blip_Buffer()
718
{
719
factor_ = INT_MAX;
720
buffer_ = 0;
721
buffer_size_ = 0;
722
sample_rate_ = 0;
723
clock_rate_ = 0;
724
length_ = 0;
725
726
clear();
727
}
728
729
Blip_Buffer::~Blip_Buffer()
730
{
731
free(buffer_);
732
}
733
734
void Blip_Buffer::clear( void)
735
{
736
offset_ = 0;
737
reader_accum_ = 0;
738
if (buffer_)
739
memset( buffer_, 0, (buffer_size_ + BLIP_BUFFER_EXTRA_) * sizeof (int32_t) );
740
}
741
742
const char * Blip_Buffer::set_sample_rate( long new_rate, int msec )
743
{
744
/* start with maximum length that resampled time can represent*/
745
long new_size = (ULONG_MAX >> BLIP_BUFFER_ACCURACY) - BLIP_BUFFER_EXTRA_ - 64;
746
if ( msec != 0)
747
{
748
long s = (new_rate * (msec + 1) + 999) / 1000;
749
if ( s < new_size )
750
new_size = s;
751
}
752
753
if ( buffer_size_ != new_size )
754
{
755
void* p = realloc( buffer_, (new_size + BLIP_BUFFER_EXTRA_) * sizeof *buffer_ );
756
if ( !p )
757
return "Out of memory";
758
buffer_ = (int32_t *) p;
759
}
760
761
buffer_size_ = new_size;
762
763
/* update things based on the sample rate*/
764
sample_rate_ = new_rate;
765
length_ = new_size * 1000 / new_rate - 1;
766
767
/* update these since they depend on sample rate*/
768
if ( clock_rate_ )
769
factor_ = clock_rate_factor( clock_rate_);
770
771
clear();
772
773
return 0;
774
}
775
776
/* Sets number of source time units per second */
777
778
uint32_t Blip_Buffer::clock_rate_factor( long rate ) const
779
{
780
double ratio = (double) sample_rate_ / rate;
781
int32_t factor = (int32_t) floor( ratio * (1L << BLIP_BUFFER_ACCURACY) + 0.5 );
782
return (uint32_t) factor;
783
}
784
long clock_rate_;
785
int length_; /* Length of buffer in milliseconds*/
786
long sample_rate_; /* Current output sample rate*/
787
uint32_t factor_;
788
uint32_t offset_;
789
int32_t *buffer_;
790
int32_t buffer_size_;
791
int32_t reader_accum_;
792
private:
793
Blip_Buffer( const Blip_Buffer& );
794
Blip_Buffer& operator = ( const Blip_Buffer& );
795
};
796
797
class Blip_Synth
798
{
799
public:
800
int delta_factor;
801
802
template<bool isReader>void SyncState(NewState *ns)
803
{
804
NSS(delta_factor);
805
}
806
807
void volume( double v ) { delta_factor = int ((v * 1.0) * (1L << BLIP_SAMPLE_BITS) + 0.5); }
808
INLINE void Blip_Synth::offset_resampled( uint32_t time, int delta, Blip_Buffer* blip_buf ) const
809
{
810
int32_t left, right, phase;
811
int32_t *buf;
812
813
delta *= delta_factor;
814
buf = blip_buf->buffer_ + (time >> BLIP_BUFFER_ACCURACY);
815
phase = (int) (time >> (BLIP_BUFFER_ACCURACY - BLIP_PHASE_BITS) & BLIP_RES_MIN_ONE);
816
817
left = buf [0] + delta;
818
819
right = (delta >> BLIP_PHASE_BITS) * phase;
820
821
left -= right;
822
right += buf [1];
823
824
buf [0] = left;
825
buf [1] = right;
826
}
827
828
INLINE void Blip_Synth::offset( int32_t t, int delta, Blip_Buffer* buf ) const
829
{
830
offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
831
}
832
void offset_inline( int32_t t, int delta, Blip_Buffer* buf ) const {
833
offset_resampled( t * buf->factor_ + buf->offset_, delta, buf );
834
}
835
};
836
837
#define TRIGGER_MASK 0x80
838
#define LENGTH_ENABLED 0x40
839
840
#define VOLUME_SHIFT_PLUS_FOUR 6
841
#define SIZE20_MASK 0x20
842
843
844
845
#define reload_sweep_timer() \
846
sweep_delay = (regs [0] & PERIOD_MASK) >> 4; \
847
if ( !sweep_delay ) \
848
sweep_delay = 8;
849
850
class Gb_Osc
851
{
852
public:
853
Blip_Buffer* outputs [4]; /* NULL, right, left, center*/
854
Blip_Buffer* output; /* where to output sound*/
855
uint8_t * regs; /* osc's 5 registers*/
856
int mode; /* mode_dmg, mode_cgb, mode_agb*/
857
int dac_off_amp; /* amplitude when DAC is off*/
858
int last_amp; /* current amplitude in Blip_Buffer*/
859
Blip_Synth const* good_synth;
860
Blip_Synth const* med_synth;
861
862
int delay; /* clocks until frequency timer expires*/
863
int length_ctr; /* length counter*/
864
unsigned phase; /* waveform phase (or equivalent)*/
865
bool enabled; /* internal enabled flag*/
866
867
template<bool isReader>void SyncState(NewState *ns)
868
{
869
EBS(output, -1);
870
EVS(output, outputs[0], 0);
871
EVS(output, outputs[1], 1);
872
EVS(output, outputs[2], 2);
873
EVS(output, outputs[3], 3);
874
EES(output, nullptr);
875
876
NSS(mode);
877
NSS(dac_off_amp);
878
NSS(last_amp);
879
880
NSS(delay);
881
NSS(length_ctr);
882
NSS(phase);
883
NSS(enabled);
884
}
885
886
void Gb_Osc::clock_length()
887
{
888
if ( (regs [4] & LENGTH_ENABLED) && length_ctr )
889
{
890
if ( --length_ctr <= 0 )
891
enabled = false;
892
}
893
}
894
void Gb_Osc::reset()
895
{
896
output = 0;
897
last_amp = 0;
898
delay = 0;
899
phase = 0;
900
enabled = false;
901
}
902
protected:
903
INLINE void Gb_Osc::update_amp( int32_t time, int new_amp )
904
{
905
int delta = new_amp - last_amp;
906
if ( delta )
907
{
908
last_amp = new_amp;
909
med_synth->offset( time, delta, output );
910
}
911
}
912
int Gb_Osc::write_trig( int frame_phase, int max_len, int old_data )
913
{
914
int data = regs [4];
915
916
if ( (frame_phase & 1) && !(old_data & LENGTH_ENABLED) && length_ctr )
917
{
918
if ( (data & LENGTH_ENABLED))
919
length_ctr--;
920
}
921
922
if ( data & TRIGGER_MASK )
923
{
924
enabled = true;
925
if ( !length_ctr )
926
{
927
length_ctr = max_len;
928
if ( (frame_phase & 1) && (data & LENGTH_ENABLED) )
929
length_ctr--;
930
}
931
}
932
933
if ( !length_ctr )
934
enabled = false;
935
936
return data & TRIGGER_MASK;
937
}
938
};
939
940
class Gb_Env : public Gb_Osc
941
{
942
public:
943
int env_delay;
944
int volume;
945
bool env_enabled;
946
947
template<bool isReader>void SyncState(NewState *ns)
948
{
949
Gb_Osc::SyncState<isReader>(ns);
950
NSS(env_delay);
951
NSS(volume);
952
NSS(env_enabled);
953
}
954
955
void Gb_Env::clock_envelope()
956
{
957
if ( env_enabled && --env_delay <= 0 && reload_env_timer() )
958
{
959
int v = volume + (regs [2] & 0x08 ? +1 : -1);
960
if ( 0 <= v && v <= 15 )
961
volume = v;
962
else
963
env_enabled = false;
964
}
965
}
966
bool Gb_Env::write_register( int frame_phase, int reg, int old, int data )
967
{
968
int const max_len = 64;
969
970
switch ( reg )
971
{
972
case 1:
973
length_ctr = max_len - (data & (max_len - 1));
974
break;
975
976
case 2:
977
if ( !GB_ENV_DAC_ENABLED() )
978
enabled = false;
979
980
zombie_volume( old, data );
981
982
if ( (data & 7) && env_delay == 8 )
983
{
984
env_delay = 1;
985
clock_envelope(); // TODO: really happens at next length clock
986
}
987
break;
988
989
case 4:
990
if ( write_trig( frame_phase, max_len, old ) )
991
{
992
volume = regs [2] >> 4;
993
reload_env_timer();
994
env_enabled = true;
995
if ( frame_phase == 7 )
996
env_delay++;
997
if ( !GB_ENV_DAC_ENABLED() )
998
enabled = false;
999
return true;
1000
}
1001
}
1002
return false;
1003
}
1004
1005
void reset()
1006
{
1007
env_delay = 0;
1008
volume = 0;
1009
Gb_Osc::reset();
1010
}
1011
private:
1012
INLINE void Gb_Env::zombie_volume( int old, int data )
1013
{
1014
int v = volume;
1015
1016
// CGB-05 behavior, very close to AGB behavior as well
1017
if ( (old ^ data) & 8 )
1018
{
1019
if ( !(old & 8) )
1020
{
1021
v++;
1022
if ( old & 7 )
1023
v++;
1024
}
1025
1026
v = 16 - v;
1027
}
1028
else if ( (old & 0x0F) == 8 )
1029
v++;
1030
volume = v & 0x0F;
1031
}
1032
INLINE int Gb_Env::reload_env_timer()
1033
{
1034
int raw = regs [2] & 7;
1035
env_delay = (raw ? raw : 8);
1036
return raw;
1037
}
1038
};
1039
1040
class Gb_Square : public Gb_Env
1041
{
1042
public:
1043
template<bool isReader>void SyncState(NewState *ns)
1044
{
1045
Gb_Env::SyncState<isReader>(ns);
1046
}
1047
1048
bool Gb_Square::write_register( int frame_phase, int reg, int old_data, int data )
1049
{
1050
bool result = Gb_Env::write_register( frame_phase, reg, old_data, data );
1051
if ( result )
1052
delay = (delay & (CLK_MUL_MUL_4 - 1)) + period();
1053
return result;
1054
}
1055
void Gb_Square::run( int32_t time, int32_t end_time )
1056
{
1057
/* Calc duty and phase*/
1058
static unsigned char const duty_offsets [4] = { 1, 1, 3, 7 };
1059
static unsigned char const duties [4] = { 1, 2, 4, 6 };
1060
int const duty_code = regs [1] >> 6;
1061
int32_t duty_offset = duty_offsets [duty_code];
1062
int32_t duty = duties [duty_code];
1063
/* AGB uses inverted duty*/
1064
duty_offset -= duty;
1065
duty = 8 - duty;
1066
int ph = (phase + duty_offset) & 7;
1067
1068
/* Determine what will be generated*/
1069
int vol = 0;
1070
Blip_Buffer* const out = output;
1071
if ( out )
1072
{
1073
int amp = dac_off_amp;
1074
if ( GB_ENV_DAC_ENABLED() )
1075
{
1076
if ( enabled )
1077
vol = volume;
1078
1079
amp = -(vol >> 1);
1080
1081
/* Play inaudible frequencies as constant amplitude*/
1082
if ( GB_OSC_FREQUENCY() >= 0x7FA && delay < CLK_MUL_MUL_32 )
1083
{
1084
amp += (vol * duty) >> 3;
1085
vol = 0;
1086
}
1087
1088
if ( ph < duty )
1089
{
1090
amp += vol;
1091
vol = -vol;
1092
}
1093
}
1094
update_amp( time, amp );
1095
}
1096
1097
/* Generate wave*/
1098
time += delay;
1099
if ( time < end_time )
1100
{
1101
int const per = period();
1102
if ( !vol )
1103
{
1104
/* Maintain phase when not playing*/
1105
int count = (end_time - time + per - 1) / per;
1106
ph += count; /* will be masked below*/
1107
time += (int32_t) count * per;
1108
}
1109
else
1110
{
1111
/* Output amplitude transitions*/
1112
int delta = vol;
1113
do
1114
{
1115
ph = (ph + 1) & 7;
1116
if ( ph == 0 || ph == duty )
1117
{
1118
good_synth->offset_inline( time, delta, out );
1119
delta = -delta;
1120
}
1121
time += per;
1122
}
1123
while ( time < end_time );
1124
1125
if ( delta != vol )
1126
last_amp -= delta;
1127
}
1128
phase = (ph - duty_offset) & 7;
1129
}
1130
delay = time - end_time;
1131
}
1132
1133
void reset()
1134
{
1135
Gb_Env::reset();
1136
delay = 0x40000000; /* TODO: something less hacky (never clocked until first trigger)*/
1137
}
1138
private:
1139
/* Frequency timer period*/
1140
int period() const { return (2048 - GB_OSC_FREQUENCY()) * (CLK_MUL_MUL_4); }
1141
};
1142
1143
class Gb_Sweep_Square : public Gb_Square
1144
{
1145
public:
1146
int sweep_freq;
1147
int sweep_delay;
1148
bool sweep_enabled;
1149
bool sweep_neg;
1150
1151
template<bool isReader>void SyncState(NewState *ns)
1152
{
1153
Gb_Square::SyncState<isReader>(ns);
1154
NSS(sweep_freq);
1155
NSS(sweep_delay);
1156
NSS(sweep_enabled);
1157
NSS(sweep_neg);
1158
}
1159
1160
void Gb_Sweep_Square::clock_sweep()
1161
{
1162
if ( --sweep_delay <= 0 )
1163
{
1164
reload_sweep_timer();
1165
if ( sweep_enabled && (regs [0] & PERIOD_MASK) )
1166
{
1167
calc_sweep( true );
1168
calc_sweep( false );
1169
}
1170
}
1171
}
1172
INLINE void Gb_Sweep_Square::write_register( int frame_phase, int reg, int old_data, int data )
1173
{
1174
if ( reg == 0 && sweep_enabled && sweep_neg && !(data & 0x08) )
1175
enabled = false; // sweep negate disabled after used
1176
1177
if ( Gb_Square::write_register( frame_phase, reg, old_data, data ) )
1178
{
1179
sweep_freq = GB_OSC_FREQUENCY();
1180
sweep_neg = false;
1181
reload_sweep_timer();
1182
sweep_enabled = (regs [0] & (PERIOD_MASK | SHIFT_MASK)) != 0;
1183
if ( regs [0] & SHIFT_MASK )
1184
calc_sweep( false );
1185
}
1186
}
1187
1188
void reset()
1189
{
1190
sweep_freq = 0;
1191
sweep_delay = 0;
1192
sweep_enabled = false;
1193
sweep_neg = false;
1194
Gb_Square::reset();
1195
}
1196
private:
1197
void Gb_Sweep_Square::calc_sweep( bool update )
1198
{
1199
int shift, delta, freq;
1200
1201
shift = regs [0] & SHIFT_MASK;
1202
delta = sweep_freq >> shift;
1203
sweep_neg = (regs [0] & 0x08) != 0;
1204
freq = sweep_freq + (sweep_neg ? -delta : delta);
1205
1206
if ( freq > 0x7FF )
1207
enabled = false;
1208
else if ( shift && update )
1209
{
1210
sweep_freq = freq;
1211
1212
regs [3] = freq & 0xFF;
1213
regs [4] = (regs [4] & ~0x07) | (freq >> 8 & 0x07);
1214
}
1215
}
1216
};
1217
1218
class Gb_Noise : public Gb_Env
1219
{
1220
public:
1221
int divider; /* noise has more complex frequency divider setup*/
1222
1223
template<bool isReader>void SyncState(NewState *ns)
1224
{
1225
Gb_Env::SyncState<isReader>(ns);
1226
NSS(divider);
1227
}
1228
1229
/* Quickly runs LFSR for a large number of clocks. For use when noise is generating*/
1230
/* no sound.*/
1231
unsigned run_lfsr( unsigned s, unsigned mask, int count )
1232
{
1233
/* optimization used in several places:*/
1234
/* ((s & (1 << b)) << n) ^ ((s & (1 << b)) << (n + 1)) = (s & (1 << b)) * (3 << n)*/
1235
1236
if ( mask == 0x4000 )
1237
{
1238
if ( count >= 32767 )
1239
count %= 32767;
1240
1241
/* Convert from Fibonacci to Galois configuration,*/
1242
/* shifted left 1 bit*/
1243
s ^= (s & 1) * 0x8000;
1244
1245
/* Each iteration is equivalent to clocking LFSR 255 times*/
1246
while ( (count -= 255) > 0 )
1247
s ^= ((s & 0xE) << 12) ^ ((s & 0xE) << 11) ^ (s >> 3);
1248
count += 255;
1249
1250
/* Each iteration is equivalent to clocking LFSR 15 times*/
1251
/* (interesting similarity to single clocking below)*/
1252
while ( (count -= 15) > 0 )
1253
s ^= ((s & 2) * (3 << 13)) ^ (s >> 1);
1254
count += 15;
1255
1256
/* Remaining singles*/
1257
do{
1258
--count;
1259
s = ((s & 2) * (3 << 13)) ^ (s >> 1);
1260
}while(count >= 0);
1261
1262
/* Convert back to Fibonacci configuration*/
1263
s &= 0x7FFF;
1264
}
1265
else if ( count < 8)
1266
{
1267
/* won't fully replace upper 8 bits, so have to do the unoptimized way*/
1268
do{
1269
--count;
1270
s = (s >> 1 | mask) ^ (mask & -((s - 1) & 2));
1271
}while(count >= 0);
1272
}
1273
else
1274
{
1275
if ( count > 127 )
1276
{
1277
count %= 127;
1278
if ( !count )
1279
count = 127; /* must run at least once*/
1280
}
1281
1282
/* Need to keep one extra bit of history*/
1283
s = s << 1 & 0xFF;
1284
1285
/* Convert from Fibonacci to Galois configuration,*/
1286
/* shifted left 2 bits*/
1287
s ^= (s & 2) << 7;
1288
1289
/* Each iteration is equivalent to clocking LFSR 7 times*/
1290
/* (interesting similarity to single clocking below)*/
1291
while ( (count -= 7) > 0 )
1292
s ^= ((s & 4) * (3 << 5)) ^ (s >> 1);
1293
count += 7;
1294
1295
/* Remaining singles*/
1296
while ( --count >= 0 )
1297
s = ((s & 4) * (3 << 5)) ^ (s >> 1);
1298
1299
/* Convert back to Fibonacci configuration and*/
1300
/* repeat last 8 bits above significant 7*/
1301
s = (s << 7 & 0x7F80) | (s >> 1 & 0x7F);
1302
}
1303
1304
return s;
1305
}
1306
1307
void Gb_Noise::run( int32_t time, int32_t end_time )
1308
{
1309
/* Determine what will be generated*/
1310
int vol = 0;
1311
Blip_Buffer* const out = output;
1312
if ( out )
1313
{
1314
int amp = dac_off_amp;
1315
if ( GB_ENV_DAC_ENABLED() )
1316
{
1317
if ( enabled )
1318
vol = volume;
1319
1320
amp = -(vol >> 1);
1321
1322
if ( !(phase & 1) )
1323
{
1324
amp += vol;
1325
vol = -vol;
1326
}
1327
}
1328
1329
/* AGB negates final output*/
1330
vol = -vol;
1331
amp = -amp;
1332
1333
update_amp( time, amp );
1334
}
1335
1336
/* Run timer and calculate time of next LFSR clock*/
1337
static unsigned char const period1s [8] = { 1, 2, 4, 6, 8, 10, 12, 14 };
1338
int const period1 = period1s [regs [3] & 7] * CLK_MUL;
1339
{
1340
int extra = (end_time - time) - delay;
1341
int const per2 = GB_NOISE_PERIOD2(8);
1342
time += delay + ((divider ^ (per2 >> 1)) & (per2 - 1)) * period1;
1343
1344
int count = (extra < 0 ? 0 : (extra + period1 - 1) / period1);
1345
divider = (divider - count) & PERIOD2_MASK;
1346
delay = count * period1 - extra;
1347
}
1348
1349
/* Generate wave*/
1350
if ( time < end_time )
1351
{
1352
unsigned const mask = GB_NOISE_LFSR_MASK();
1353
unsigned bits = phase;
1354
1355
int per = GB_NOISE_PERIOD2( period1 * 8 );
1356
if ( GB_NOISE_PERIOD2_INDEX() >= 0xE )
1357
{
1358
time = end_time;
1359
}
1360
else if ( !vol )
1361
{
1362
/* Maintain phase when not playing*/
1363
int count = (end_time - time + per - 1) / per;
1364
time += (int32_t) count * per;
1365
bits = run_lfsr( bits, ~mask, count );
1366
}
1367
else
1368
{
1369
/* Output amplitude transitions*/
1370
int delta = -vol;
1371
do
1372
{
1373
unsigned changed = bits + 1;
1374
bits = bits >> 1 & mask;
1375
if ( changed & 2 )
1376
{
1377
bits |= ~mask;
1378
delta = -delta;
1379
med_synth->offset_inline( time, delta, out );
1380
}
1381
time += per;
1382
}
1383
while ( time < end_time );
1384
1385
if ( delta == vol )
1386
last_amp += delta;
1387
}
1388
phase = bits;
1389
}
1390
}
1391
INLINE void Gb_Noise::write_register( int frame_phase, int reg, int old_data, int data )
1392
{
1393
if ( Gb_Env::write_register( frame_phase, reg, old_data, data ) )
1394
{
1395
phase = 0x7FFF;
1396
delay += CLK_MUL_MUL_8;
1397
}
1398
}
1399
1400
void reset()
1401
{
1402
divider = 0;
1403
Gb_Env::reset();
1404
delay = CLK_MUL_MUL_4; /* TODO: remove?*/
1405
}
1406
};
1407
1408
class Gb_Wave : public Gb_Osc
1409
{
1410
public:
1411
int sample_buf; /* last wave RAM byte read (hardware has this as well)*/
1412
int agb_mask; /* 0xFF if AGB features enabled, 0 otherwise*/
1413
uint8_t* wave_ram; /* 32 bytes (64 nybbles), stored in APU*/
1414
1415
template<bool isReader>void SyncState(NewState *ns)
1416
{
1417
Gb_Osc::SyncState<isReader>(ns);
1418
NSS(sample_buf);
1419
NSS(agb_mask);
1420
}
1421
1422
INLINE void Gb_Wave::write_register( int frame_phase, int reg, int old_data, int data )
1423
{
1424
switch ( reg )
1425
{
1426
case 0:
1427
if ( !GB_WAVE_DAC_ENABLED() )
1428
enabled = false;
1429
break;
1430
1431
case 1:
1432
length_ctr = 256 - data;
1433
break;
1434
1435
case 4:
1436
bool was_enabled = enabled;
1437
if ( write_trig( frame_phase, 256, old_data ) )
1438
{
1439
if ( !GB_WAVE_DAC_ENABLED() )
1440
enabled = false;
1441
phase = 0;
1442
delay = period() + CLK_MUL_MUL_6;
1443
}
1444
}
1445
}
1446
void Gb_Wave::run( int32_t time, int32_t end_time )
1447
{
1448
/* Calc volume*/
1449
static unsigned char const volumes [8] = { 0, 4, 2, 1, 3, 3, 3, 3 };
1450
int const volume_idx = regs [2] >> 5 & (agb_mask | 3); /* 2 bits on DMG/CGB, 3 on AGB*/
1451
int const volume_mul = volumes [volume_idx];
1452
1453
/* Determine what will be generated*/
1454
int playing = false;
1455
Blip_Buffer* const out = output;
1456
if ( out )
1457
{
1458
int amp = dac_off_amp;
1459
if ( GB_WAVE_DAC_ENABLED() )
1460
{
1461
/* Play inaudible frequencies as constant amplitude*/
1462
amp = 128; /* really depends on average of all samples in wave*/
1463
1464
/* if delay is larger, constant amplitude won't start yet*/
1465
if ( GB_OSC_FREQUENCY() <= 0x7FB || delay > CLK_MUL_MUL_15 )
1466
{
1467
if ( volume_mul )
1468
playing = (int) enabled;
1469
1470
amp = (sample_buf << (phase << 2 & 4) & 0xF0) * playing;
1471
}
1472
1473
amp = ((amp * volume_mul) >> VOLUME_SHIFT_PLUS_FOUR) - DAC_BIAS;
1474
}
1475
update_amp( time, amp );
1476
}
1477
1478
/* Generate wave*/
1479
time += delay;
1480
if ( time < end_time )
1481
{
1482
unsigned char const* wave = wave_ram;
1483
1484
/* wave size and bank*/
1485
int const flags = regs [0] & agb_mask;
1486
int const wave_mask = (flags & SIZE20_MASK) | 0x1F;
1487
int swap_banks = 0;
1488
if ( flags & BANK40_MASK)
1489
{
1490
swap_banks = flags & SIZE20_MASK;
1491
wave += BANK_SIZE_DIV_TWO - (swap_banks >> 1);
1492
}
1493
1494
int ph = phase ^ swap_banks;
1495
ph = (ph + 1) & wave_mask; /* pre-advance*/
1496
1497
int const per = period();
1498
if ( !playing )
1499
{
1500
/* Maintain phase when not playing*/
1501
int count = (end_time - time + per - 1) / per;
1502
ph += count; /* will be masked below*/
1503
time += (int32_t) count * per;
1504
}
1505
else
1506
{
1507
/* Output amplitude transitions*/
1508
int lamp = last_amp + DAC_BIAS;
1509
do
1510
{
1511
/* Extract nybble*/
1512
int nybble = wave [ph >> 1] << (ph << 2 & 4) & 0xF0;
1513
ph = (ph + 1) & wave_mask;
1514
1515
/* Scale by volume*/
1516
int amp = (nybble * volume_mul) >> VOLUME_SHIFT_PLUS_FOUR;
1517
1518
int delta = amp - lamp;
1519
if ( delta )
1520
{
1521
lamp = amp;
1522
med_synth->offset_inline( time, delta, out );
1523
}
1524
time += per;
1525
}
1526
while ( time < end_time );
1527
last_amp = lamp - DAC_BIAS;
1528
}
1529
ph = (ph - 1) & wave_mask; /* undo pre-advance and mask position*/
1530
1531
/* Keep track of last byte read*/
1532
if ( enabled )
1533
sample_buf = wave [ph >> 1];
1534
1535
phase = ph ^ swap_banks; /* undo swapped banks*/
1536
}
1537
delay = time - end_time;
1538
}
1539
1540
/* Reads/writes wave RAM*/
1541
INLINE int Gb_Wave::read( unsigned addr ) const
1542
{
1543
int index;
1544
1545
if(enabled)
1546
index = access( addr );
1547
else
1548
index = addr & 0x0F;
1549
1550
unsigned char const * wave_bank = &wave_ram[(~regs[0] & BANK40_MASK) >> 2 & agb_mask];
1551
1552
return (index < 0 ? 0xFF : wave_bank[index]);
1553
}
1554
1555
INLINE void Gb_Wave::write( unsigned addr, int data )
1556
{
1557
int index;
1558
1559
if(enabled)
1560
index = access( addr );
1561
else
1562
index = addr & 0x0F;
1563
1564
unsigned char * wave_bank = &wave_ram[(~regs[0] & BANK40_MASK) >> 2 & agb_mask];
1565
1566
if ( index >= 0 )
1567
wave_bank[index] = data;;
1568
}
1569
1570
1571
void reset()
1572
{
1573
sample_buf = 0;
1574
Gb_Osc::reset();
1575
}
1576
1577
private:
1578
friend class Gb_Apu;
1579
1580
/* Frequency timer period*/
1581
int period() const { return (2048 - GB_OSC_FREQUENCY()) * (CLK_MUL_MUL_2); }
1582
1583
void Gb_Wave::corrupt_wave()
1584
{
1585
int pos = ((phase + 1) & BANK_SIZE_MIN_ONE) >> 1;
1586
if ( pos < 4 )
1587
wave_ram [0] = wave_ram [pos];
1588
else
1589
for ( int i = 4; --i >= 0; )
1590
wave_ram [i] = wave_ram [(pos & ~3) + i];
1591
}
1592
1593
/* Wave index that would be accessed, or -1 if no access would occur*/
1594
int Gb_Wave::access( unsigned addr ) const
1595
{
1596
//if ( mode != MODE_AGB )
1597
//{
1598
// addr = (phase & BANK_SIZE_MIN_ONE) >> 1;
1599
//}
1600
return addr & 0x0F;
1601
}
1602
};
1603
1604
/*============================================================
1605
INLINE CLASS FUNCS
1606
============================================================ */
1607
1608
int16_t soundFinalWave [2048];
1609
static const long soundSampleRate = 44100; // = 22050;
1610
//int SOUND_CLOCK_TICKS; // = SOUND_CLOCK_TICKS_;
1611
//int soundTicks; // = SOUND_CLOCK_TICKS_;
1612
int soundTicksUp; // counts up from 0 being the last time the blips were emptied
1613
1614
int soundEnableFlag; // = 0x3ff; /* emulator channels enabled*/
1615
1616
struct gba_pcm_t
1617
{
1618
int last_amp;
1619
int last_time;
1620
int shift;
1621
Blip_Buffer* output;
1622
1623
template<bool isReader>void SyncState(NewState *ns, Gigazoid *g)
1624
{
1625
NSS(last_amp);
1626
NSS(last_time);
1627
NSS(shift);
1628
1629
// tricky
1630
EBS(output, -1);
1631
EVS(output, &g->bufs_buffer[0], 0);
1632
EVS(output, &g->bufs_buffer[1], 1);
1633
EVS(output, &g->bufs_buffer[2], 2);
1634
EES(output, nullptr);
1635
}
1636
};
1637
1638
struct gba_pcm_fifo_t
1639
{
1640
bool enabled;
1641
uint8_t fifo [32];
1642
int count;
1643
int dac;
1644
int readIndex;
1645
int writeIndex;
1646
int which;
1647
int timer;
1648
gba_pcm_t pcm;
1649
1650
template<bool isReader>void SyncState(NewState *ns, Gigazoid *g)
1651
{
1652
NSS(enabled);
1653
NSS(fifo);
1654
NSS(count);
1655
NSS(dac);
1656
NSS(readIndex);
1657
NSS(writeIndex);
1658
NSS(which);
1659
NSS(timer);
1660
SSS_HACKY(pcm, g);
1661
}
1662
};
1663
1664
gba_pcm_fifo_t pcm [2];
1665
1666
1667
Blip_Synth pcm_synth; // 32 kHz, 16 kHz, 8 kHz
1668
1669
Blip_Buffer bufs_buffer [BUFS_SIZE];
1670
int mixer_samples_read;
1671
1672
void gba_pcm_init (void)
1673
{
1674
pcm[0].pcm.output = 0;
1675
pcm[0].pcm.last_time = 0;
1676
pcm[0].pcm.last_amp = 0;
1677
pcm[0].pcm.shift = 0;
1678
1679
pcm[1].pcm.output = 0;
1680
pcm[1].pcm.last_time = 0;
1681
pcm[1].pcm.last_amp = 0;
1682
pcm[1].pcm.shift = 0;
1683
}
1684
1685
void gba_pcm_apply_control( int pcm_idx, int idx )
1686
{
1687
int ch = 0;
1688
pcm[pcm_idx].pcm.shift = ~ioMem [SGCNT0_H] >> (2 + idx) & 1;
1689
1690
if ( (ioMem [NR52] & 0x80) )
1691
ch = ioMem [SGCNT0_H+1] >> (idx << 2) & 3;
1692
1693
Blip_Buffer* out = 0;
1694
switch ( ch )
1695
{
1696
case 1:
1697
out = &bufs_buffer[1];
1698
break;
1699
case 2:
1700
out = &bufs_buffer[0];
1701
break;
1702
case 3:
1703
out = &bufs_buffer[2];
1704
break;
1705
}
1706
1707
if ( pcm[pcm_idx].pcm.output != out )
1708
{
1709
if ( pcm[pcm_idx].pcm.output )
1710
pcm_synth.offset( soundTicksUp, -pcm[pcm_idx].pcm.last_amp, pcm[pcm_idx].pcm.output );
1711
pcm[pcm_idx].pcm.last_amp = 0;
1712
pcm[pcm_idx].pcm.output = out;
1713
}
1714
}
1715
1716
/*============================================================
1717
GB APU
1718
============================================================ */
1719
1720
/* 0: Square 1, 1: Square 2, 2: Wave, 3: Noise */
1721
#define OSC_COUNT 4
1722
1723
/* Resets hardware to initial power on state BEFORE boot ROM runs. Mode selects*/
1724
/* sound hardware. Additional AGB wave features are enabled separately.*/
1725
#define MODE_AGB 2
1726
1727
#define START_ADDR 0xFF10
1728
#define END_ADDR 0xFF3F
1729
1730
/* Reads and writes must be within the START_ADDR to END_ADDR range, inclusive.*/
1731
/* Addresses outside this range are not mapped to the sound hardware.*/
1732
#define REGISTER_COUNT 48
1733
#define REGS_SIZE 64
1734
1735
/* Clock rate that sound hardware runs at.
1736
* formula: 4194304 * 4
1737
* */
1738
#define CLOCK_RATE 16777216
1739
1740
struct gb_apu_t
1741
{
1742
bool reduce_clicks_;
1743
uint8_t regs[REGS_SIZE]; // last values written to registers
1744
int32_t last_time; // time sound emulator has been run to
1745
int32_t frame_time; // time of next frame sequencer action
1746
int32_t frame_period; // clocks between each frame sequencer step
1747
int32_t frame_phase; // phase of next frame sequencer step
1748
double volume_;
1749
Gb_Osc* oscs [OSC_COUNT];
1750
Gb_Sweep_Square square1;
1751
Gb_Square square2;
1752
Gb_Wave wave;
1753
Gb_Noise noise;
1754
Blip_Synth good_synth;
1755
Blip_Synth med_synth;
1756
1757
template<bool isReader>void SyncState(NewState *ns)
1758
{
1759
NSS(reduce_clicks_);
1760
NSS(regs);
1761
NSS(last_time);
1762
NSS(frame_time);
1763
NSS(frame_period);
1764
NSS(frame_phase);
1765
NSS(volume_);
1766
SSS(square1);
1767
SSS(square2);
1768
SSS(wave);
1769
SSS(noise);
1770
1771
SSS(good_synth);
1772
SSS(med_synth);
1773
}
1774
} gb_apu;
1775
1776
#define VOL_REG 0xFF24
1777
#define STEREO_REG 0xFF25
1778
#define STATUS_REG 0xFF26
1779
#define WAVE_RAM 0xFF30
1780
#define POWER_MASK 0x80
1781
1782
#define OSC_COUNT 4
1783
1784
void gb_apu_reduce_clicks( bool reduce )
1785
{
1786
gb_apu.reduce_clicks_ = reduce;
1787
1788
/* Click reduction makes DAC off generate same output as volume 0*/
1789
int dac_off_amp = 0;
1790
1791
gb_apu.oscs[0]->dac_off_amp = dac_off_amp;
1792
gb_apu.oscs[1]->dac_off_amp = dac_off_amp;
1793
gb_apu.oscs[2]->dac_off_amp = dac_off_amp;
1794
gb_apu.oscs[3]->dac_off_amp = dac_off_amp;
1795
1796
/* AGB always eliminates clicks on wave channel using same method*/
1797
gb_apu.wave.dac_off_amp = -DAC_BIAS;
1798
}
1799
1800
void gb_apu_synth_volume( int iv )
1801
{
1802
double v = gb_apu.volume_ * 0.60 / OSC_COUNT / 15 /*steps*/ / 8 /*master vol range*/ * iv;
1803
gb_apu.good_synth.volume( v );
1804
gb_apu.med_synth .volume( v );
1805
}
1806
1807
void gb_apu_apply_volume (void)
1808
{
1809
int data, left, right, vol_tmp;
1810
data = gb_apu.regs [VOL_REG - START_ADDR];
1811
left = data >> 4 & 7;
1812
right = data & 7;
1813
vol_tmp = left < right ? right : left;
1814
gb_apu_synth_volume( vol_tmp + 1 );
1815
}
1816
1817
void gb_apu_silence_osc( Gb_Osc& o )
1818
{
1819
int delta;
1820
1821
delta = -o.last_amp;
1822
if ( delta )
1823
{
1824
o.last_amp = 0;
1825
if ( o.output )
1826
{
1827
gb_apu.med_synth.offset( gb_apu.last_time, delta, o.output );
1828
}
1829
}
1830
}
1831
1832
void gb_apu_run_until_( int32_t end_time )
1833
{
1834
int32_t time;
1835
1836
do{
1837
/* run oscillators*/
1838
time = end_time;
1839
if ( time > gb_apu.frame_time )
1840
time = gb_apu.frame_time;
1841
1842
gb_apu.square1.run( gb_apu.last_time, time );
1843
gb_apu.square2.run( gb_apu.last_time, time );
1844
gb_apu.wave .run( gb_apu.last_time, time );
1845
gb_apu.noise .run( gb_apu.last_time, time );
1846
gb_apu.last_time = time;
1847
1848
if ( time == end_time )
1849
break;
1850
1851
/* run frame sequencer*/
1852
gb_apu.frame_time += gb_apu.frame_period * CLK_MUL;
1853
switch ( gb_apu.frame_phase++ )
1854
{
1855
case 2:
1856
case 6:
1857
/* 128 Hz*/
1858
gb_apu.square1.clock_sweep();
1859
case 0:
1860
case 4:
1861
/* 256 Hz*/
1862
gb_apu.square1.clock_length();
1863
gb_apu.square2.clock_length();
1864
gb_apu.wave .clock_length();
1865
gb_apu.noise .clock_length();
1866
break;
1867
1868
case 7:
1869
/* 64 Hz*/
1870
gb_apu.frame_phase = 0;
1871
gb_apu.square1.clock_envelope();
1872
gb_apu.square2.clock_envelope();
1873
gb_apu.noise .clock_envelope();
1874
}
1875
}while(1);
1876
}
1877
1878
void gb_apu_write_osc( int index, int reg, int old_data, int data )
1879
{
1880
reg -= index * 5;
1881
switch ( index )
1882
{
1883
case 0:
1884
gb_apu.square1.write_register( gb_apu.frame_phase, reg, old_data, data );
1885
break;
1886
case 1:
1887
gb_apu.square2.write_register( gb_apu.frame_phase, reg, old_data, data );
1888
break;
1889
case 2:
1890
gb_apu.wave.write_register( gb_apu.frame_phase, reg, old_data, data );
1891
break;
1892
case 3:
1893
gb_apu.noise.write_register( gb_apu.frame_phase, reg, old_data, data );
1894
break;
1895
}
1896
}
1897
1898
INLINE int gb_apu_calc_output( int osc )
1899
{
1900
int bits = gb_apu.regs [STEREO_REG - START_ADDR] >> osc;
1901
return (bits >> 3 & 2) | (bits & 1);
1902
}
1903
1904
void gb_apu_write_register( int32_t time, unsigned addr, int data )
1905
{
1906
int reg = addr - START_ADDR;
1907
if ( (unsigned) reg >= REGISTER_COUNT )
1908
return;
1909
1910
if ( addr < STATUS_REG && !(gb_apu.regs [STATUS_REG - START_ADDR] & POWER_MASK) )
1911
return; /* Power is off*/
1912
1913
if ( time > gb_apu.last_time )
1914
gb_apu_run_until_( time );
1915
1916
if ( addr >= WAVE_RAM )
1917
{
1918
gb_apu.wave.write( addr, data );
1919
}
1920
else
1921
{
1922
int old_data = gb_apu.regs [reg];
1923
gb_apu.regs [reg] = data;
1924
1925
if ( addr < VOL_REG )
1926
gb_apu_write_osc( reg / 5, reg, old_data, data ); /* Oscillator*/
1927
else if ( addr == VOL_REG && data != old_data )
1928
{
1929
/* Master volume*/
1930
for ( int i = OSC_COUNT; --i >= 0; )
1931
gb_apu_silence_osc( *gb_apu.oscs [i] );
1932
1933
gb_apu_apply_volume();
1934
}
1935
else if ( addr == STEREO_REG )
1936
{
1937
/* Stereo panning*/
1938
for ( int i = OSC_COUNT; --i >= 0; )
1939
{
1940
Gb_Osc& o = *gb_apu.oscs [i];
1941
Blip_Buffer* out = o.outputs [gb_apu_calc_output( i )];
1942
if ( o.output != out )
1943
{
1944
gb_apu_silence_osc( o );
1945
o.output = out;
1946
}
1947
} }
1948
else if ( addr == STATUS_REG && (data ^ old_data) & POWER_MASK )
1949
{
1950
/* Power control*/
1951
gb_apu.frame_phase = 0;
1952
for ( int i = OSC_COUNT; --i >= 0; )
1953
gb_apu_silence_osc( *gb_apu.oscs [i] );
1954
1955
for ( int i = 0; i < 32; i++ )
1956
gb_apu.regs [i] = 0;
1957
1958
gb_apu.square1.reset();
1959
gb_apu.square2.reset();
1960
gb_apu.wave .reset();
1961
gb_apu.noise .reset();
1962
1963
gb_apu_apply_volume();
1964
1965
gb_apu.square1.length_ctr = 64;
1966
gb_apu.square2.length_ctr = 64;
1967
gb_apu.wave .length_ctr = 256;
1968
gb_apu.noise .length_ctr = 64;
1969
1970
gb_apu.regs [STATUS_REG - START_ADDR] = data;
1971
}
1972
}
1973
}
1974
1975
void gb_apu_reset( uint32_t mode, bool agb_wave )
1976
{
1977
/* Hardware mode*/
1978
mode = MODE_AGB; /* using AGB wave features implies AGB hardware*/
1979
gb_apu.wave.agb_mask = 0xFF;
1980
gb_apu.oscs [0]->mode = mode;
1981
gb_apu.oscs [1]->mode = mode;
1982
gb_apu.oscs [2]->mode = mode;
1983
gb_apu.oscs [3]->mode = mode;
1984
gb_apu_reduce_clicks( gb_apu.reduce_clicks_ );
1985
1986
/* Reset state*/
1987
gb_apu.frame_time = 0;
1988
gb_apu.last_time = 0;
1989
gb_apu.frame_phase = 0;
1990
1991
for ( int i = 0; i < 32; i++ )
1992
gb_apu.regs [i] = 0;
1993
1994
gb_apu.square1.reset();
1995
gb_apu.square2.reset();
1996
gb_apu.wave .reset();
1997
gb_apu.noise .reset();
1998
1999
gb_apu_apply_volume();
2000
2001
gb_apu.square1.length_ctr = 64;
2002
gb_apu.square2.length_ctr = 64;
2003
gb_apu.wave .length_ctr = 256;
2004
gb_apu.noise .length_ctr = 64;
2005
2006
/* Load initial wave RAM*/
2007
static unsigned char const initial_wave [2] [16] = {
2008
{0x84,0x40,0x43,0xAA,0x2D,0x78,0x92,0x3C,0x60,0x59,0x59,0xB0,0x34,0xB8,0x2E,0xDA},
2009
{0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF},
2010
};
2011
for ( int b = 2; --b >= 0; )
2012
{
2013
/* Init both banks (does nothing if not in AGB mode)*/
2014
gb_apu_write_register( 0, 0xFF1A, b * 0x40 );
2015
for ( unsigned i = 0; i < sizeof initial_wave [0]; i++ )
2016
gb_apu_write_register( 0, i + WAVE_RAM, initial_wave [1] [i] );
2017
}
2018
}
2019
2020
void gb_apu_new(void)
2021
{
2022
int i;
2023
2024
gb_apu.wave.wave_ram = &gb_apu.regs [WAVE_RAM - START_ADDR];
2025
2026
gb_apu.oscs [0] = &gb_apu.square1;
2027
gb_apu.oscs [1] = &gb_apu.square2;
2028
gb_apu.oscs [2] = &gb_apu.wave;
2029
gb_apu.oscs [3] = &gb_apu.noise;
2030
2031
for ( i = OSC_COUNT; --i >= 0; )
2032
{
2033
Gb_Osc& o = *gb_apu.oscs [i];
2034
o.regs = &gb_apu.regs [i * 5];
2035
o.output = 0;
2036
o.outputs [0] = 0;
2037
o.outputs [1] = 0;
2038
o.outputs [2] = 0;
2039
o.outputs [3] = 0;
2040
o.good_synth = &gb_apu.good_synth;
2041
o.med_synth = &gb_apu.med_synth;
2042
}
2043
2044
gb_apu.reduce_clicks_ = false;
2045
gb_apu.frame_period = 4194304 / 512; /* 512 Hz*/
2046
2047
gb_apu.volume_ = 1.0;
2048
gb_apu_reset(MODE_AGB, false);
2049
}
2050
2051
2052
2053
void gb_apu_set_output( Blip_Buffer* center, Blip_Buffer* left, Blip_Buffer* right, int osc )
2054
{
2055
int i;
2056
2057
i = osc;
2058
do
2059
{
2060
Gb_Osc& o = *gb_apu.oscs [i];
2061
o.outputs [1] = right;
2062
o.outputs [2] = left;
2063
o.outputs [3] = center;
2064
o.output = o.outputs [gb_apu_calc_output( i )];
2065
++i;
2066
}
2067
while ( i < osc );
2068
}
2069
2070
void gb_apu_volume( double v )
2071
{
2072
if ( gb_apu.volume_ != v )
2073
{
2074
gb_apu.volume_ = v;
2075
gb_apu_apply_volume();
2076
}
2077
}
2078
2079
void gb_apu_apply_stereo (void)
2080
{
2081
int i;
2082
2083
for ( i = OSC_COUNT; --i >= 0; )
2084
{
2085
Gb_Osc& o = *gb_apu.oscs [i];
2086
Blip_Buffer* out = o.outputs [gb_apu_calc_output( i )];
2087
if ( o.output != out )
2088
{
2089
gb_apu_silence_osc( o );
2090
o.output = out;
2091
}
2092
}
2093
}
2094
2095
2096
/*============================================================
2097
GB OSCS
2098
============================================================ */
2099
2100
2101
/*============================================================
2102
BLIP BUFFER
2103
============================================================ */
2104
2105
/* Blip_Buffer 0.4.1. http://www.slack.net/~ant */
2106
2107
#define FIXED_SHIFT 12
2108
#define SAL_FIXED_SHIFT 4096
2109
#define TO_FIXED( f ) int ((f) * SAL_FIXED_SHIFT)
2110
#define FROM_FIXED( f ) ((f) >> FIXED_SHIFT)
2111
2112
2113
2114
/*============================================================
2115
STEREO BUFFER
2116
============================================================ */
2117
2118
/* Uses three buffers (one for center) and outputs stereo sample pairs. */
2119
2120
#define STEREO_BUFFER_SAMPLES_AVAILABLE() ((long)(bufs_buffer[0].offset_ - mixer_samples_read) << 1)
2121
#define stereo_buffer_samples_avail() ((((bufs_buffer [0].offset_ >> BLIP_BUFFER_ACCURACY) - mixer_samples_read) << 1))
2122
2123
2124
const char * stereo_buffer_set_sample_rate( long rate, int msec )
2125
{
2126
mixer_samples_read = 0;
2127
for ( int i = BUFS_SIZE; --i >= 0; )
2128
RETURN_ERR( bufs_buffer [i].set_sample_rate( rate, msec ) );
2129
return 0;
2130
}
2131
2132
void stereo_buffer_clock_rate( long rate )
2133
{
2134
bufs_buffer[2].factor_ = bufs_buffer [2].clock_rate_factor( rate );
2135
bufs_buffer[1].factor_ = bufs_buffer [1].clock_rate_factor( rate );
2136
bufs_buffer[0].factor_ = bufs_buffer [0].clock_rate_factor( rate );
2137
}
2138
2139
void stereo_buffer_clear (void)
2140
{
2141
mixer_samples_read = 0;
2142
bufs_buffer [2].clear();
2143
bufs_buffer [1].clear();
2144
bufs_buffer [0].clear();
2145
}
2146
2147
/* mixers use a single index value to improve performance on register-challenged processors
2148
* offset goes from negative to zero*/
2149
2150
INLINE void stereo_buffer_mixer_read_pairs( int16_t* out, int count )
2151
{
2152
/* TODO: if caller never marks buffers as modified, uses mono*/
2153
/* except that buffer isn't cleared, so caller can encounter*/
2154
/* subtle problems and not realize the cause.*/
2155
mixer_samples_read += count;
2156
int16_t* outtemp = out + count * STEREO;
2157
2158
/* do left + center and right + center separately to reduce register load*/
2159
Blip_Buffer* buf = &bufs_buffer [2];
2160
{
2161
--buf;
2162
--outtemp;
2163
2164
BLIP_READER_BEGIN( side, *buf );
2165
BLIP_READER_BEGIN( center, bufs_buffer[2] );
2166
2167
BLIP_READER_ADJ_( side, mixer_samples_read );
2168
BLIP_READER_ADJ_( center, mixer_samples_read );
2169
2170
int offset = -count;
2171
do
2172
{
2173
int s = (center_reader_accum + side_reader_accum) >> 14;
2174
BLIP_READER_NEXT_IDX_( side, offset );
2175
BLIP_READER_NEXT_IDX_( center, offset );
2176
BLIP_CLAMP( s, s );
2177
2178
++offset; /* before write since out is decremented to slightly before end*/
2179
outtemp [offset * STEREO] = (int16_t) s;
2180
}while ( offset );
2181
2182
BLIP_READER_END( side, *buf );
2183
}
2184
{
2185
--buf;
2186
--outtemp;
2187
2188
BLIP_READER_BEGIN( side, *buf );
2189
BLIP_READER_BEGIN( center, bufs_buffer[2] );
2190
2191
BLIP_READER_ADJ_( side, mixer_samples_read );
2192
BLIP_READER_ADJ_( center, mixer_samples_read );
2193
2194
int offset = -count;
2195
do
2196
{
2197
int s = (center_reader_accum + side_reader_accum) >> 14;
2198
BLIP_READER_NEXT_IDX_( side, offset );
2199
BLIP_READER_NEXT_IDX_( center, offset );
2200
BLIP_CLAMP( s, s );
2201
2202
++offset; /* before write since out is decremented to slightly before end*/
2203
outtemp [offset * STEREO] = (int16_t) s;
2204
}while ( offset );
2205
2206
BLIP_READER_END( side, *buf );
2207
2208
/* only end center once*/
2209
BLIP_READER_END( center, bufs_buffer[2] );
2210
}
2211
}
2212
2213
void blip_buffer_remove_all_samples( long count )
2214
{
2215
uint32_t new_offset = (uint32_t)count << BLIP_BUFFER_ACCURACY;
2216
/* BLIP BUFFER #1 */
2217
bufs_buffer[0].offset_ -= new_offset;
2218
bufs_buffer[1].offset_ -= new_offset;
2219
bufs_buffer[2].offset_ -= new_offset;
2220
2221
/* copy remaining samples to beginning and clear old samples*/
2222
long remain = (bufs_buffer[0].offset_ >> BLIP_BUFFER_ACCURACY) + BLIP_BUFFER_EXTRA_;
2223
memmove( bufs_buffer[0].buffer_, bufs_buffer[0].buffer_ + count, remain * sizeof *bufs_buffer[0].buffer_ );
2224
memset( bufs_buffer[0].buffer_ + remain, 0, count * sizeof(*bufs_buffer[0].buffer_));
2225
2226
remain = (bufs_buffer[1].offset_ >> BLIP_BUFFER_ACCURACY) + BLIP_BUFFER_EXTRA_;
2227
memmove( bufs_buffer[1].buffer_, bufs_buffer[1].buffer_ + count, remain * sizeof *bufs_buffer[1].buffer_ );
2228
memset( bufs_buffer[1].buffer_ + remain, 0, count * sizeof(*bufs_buffer[1].buffer_));
2229
2230
remain = (bufs_buffer[2].offset_ >> BLIP_BUFFER_ACCURACY) + BLIP_BUFFER_EXTRA_;
2231
memmove( bufs_buffer[2].buffer_, bufs_buffer[2].buffer_ + count, remain * sizeof *bufs_buffer[2].buffer_ );
2232
memset( bufs_buffer[2].buffer_ + remain, 0, count * sizeof(*bufs_buffer[2].buffer_));
2233
}
2234
2235
long stereo_buffer_read_samples( int16_t * out, long out_size )
2236
{
2237
int pair_count;
2238
2239
out_size = (STEREO_BUFFER_SAMPLES_AVAILABLE() < out_size) ? STEREO_BUFFER_SAMPLES_AVAILABLE() : out_size;
2240
2241
pair_count = int (out_size >> 1);
2242
if ( pair_count )
2243
{
2244
stereo_buffer_mixer_read_pairs( out, pair_count );
2245
blip_buffer_remove_all_samples( mixer_samples_read );
2246
mixer_samples_read = 0;
2247
}
2248
return out_size;
2249
}
2250
2251
void gba_to_gb_sound_parallel( int * __restrict addr, int * __restrict addr2 )
2252
{
2253
uint32_t addr1_table = *addr - 0x60;
2254
uint32_t addr2_table = *addr2 - 0x60;
2255
*addr = table [addr1_table];
2256
*addr2 = table [addr2_table];
2257
}
2258
2259
void pcm_fifo_write_control( int data, int data2)
2260
{
2261
pcm[0].enabled = (data & 0x0300) ? true : false;
2262
pcm[0].timer = (data & 0x0400) ? 1 : 0;
2263
2264
if ( data & 0x0800 )
2265
{
2266
// Reset
2267
pcm[0].writeIndex = 0;
2268
pcm[0].readIndex = 0;
2269
pcm[0].count = 0;
2270
pcm[0].dac = 0;
2271
memset(pcm[0].fifo, 0, sizeof(pcm[0].fifo));
2272
}
2273
2274
gba_pcm_apply_control( 0, pcm[0].which );
2275
2276
if(pcm[0].pcm.output)
2277
{
2278
int time = soundTicksUp;
2279
2280
pcm[0].dac = (int8_t)pcm[0].dac >> pcm[0].pcm.shift;
2281
int delta = pcm[0].dac - pcm[0].pcm.last_amp;
2282
if ( delta )
2283
{
2284
pcm[0].pcm.last_amp = pcm[0].dac;
2285
pcm_synth.offset( time, delta, pcm[0].pcm.output );
2286
}
2287
pcm[0].pcm.last_time = time;
2288
}
2289
2290
pcm[1].enabled = (data2 & 0x0300) ? true : false;
2291
pcm[1].timer = (data2 & 0x0400) ? 1 : 0;
2292
2293
if ( data2 & 0x0800 )
2294
{
2295
// Reset
2296
pcm[1].writeIndex = 0;
2297
pcm[1].readIndex = 0;
2298
pcm[1].count = 0;
2299
pcm[1].dac = 0;
2300
memset( pcm[1].fifo, 0, sizeof(pcm[1].fifo));
2301
}
2302
2303
gba_pcm_apply_control( 1, pcm[1].which );
2304
2305
if(pcm[1].pcm.output)
2306
{
2307
int time = soundTicksUp;
2308
2309
pcm[1].dac = (int8_t)pcm[1].dac >> pcm[1].pcm.shift;
2310
int delta = pcm[1].dac - pcm[1].pcm.last_amp;
2311
if ( delta )
2312
{
2313
pcm[1].pcm.last_amp = pcm[1].dac;
2314
pcm_synth.offset( time, delta, pcm[1].pcm.output );
2315
}
2316
pcm[1].pcm.last_time = time;
2317
}
2318
}
2319
2320
void soundEvent_u16_parallel(uint32_t address[])
2321
{
2322
for(int i = 0; i < 8; i++)
2323
{
2324
switch ( address[i] )
2325
{
2326
case SGCNT0_H:
2327
//Begin of Write SGCNT0_H
2328
WRITE16LE( &ioMem [SGCNT0_H], 0 & 0x770F );
2329
pcm_fifo_write_control(0, 0);
2330
2331
gb_apu_volume( apu_vols [ioMem [SGCNT0_H] & 3] );
2332
//End of SGCNT0_H
2333
break;
2334
2335
case FIFOA_L:
2336
case FIFOA_H:
2337
pcm[0].fifo [pcm[0].writeIndex ] = 0;
2338
pcm[0].fifo [pcm[0].writeIndex+1] = 0;
2339
pcm[0].count += 2;
2340
pcm[0].writeIndex = (pcm[0].writeIndex + 2) & 31;
2341
WRITE16LE( &ioMem[address[i]], 0 );
2342
break;
2343
2344
case FIFOB_L:
2345
case FIFOB_H:
2346
pcm[1].fifo [pcm[1].writeIndex ] = 0;
2347
pcm[1].fifo [pcm[1].writeIndex+1] = 0;
2348
pcm[1].count += 2;
2349
pcm[1].writeIndex = (pcm[1].writeIndex + 2) & 31;
2350
WRITE16LE( &ioMem[address[i]], 0 );
2351
break;
2352
2353
case 0x88:
2354
WRITE16LE( &ioMem[address[i]], 0 );
2355
break;
2356
2357
default:
2358
{
2359
int gb_addr[2] = {address[i] & ~1, address[i] | 1};
2360
uint32_t address_array[2] = {address[i] & ~ 1, address[i] | 1};
2361
uint8_t data_array[2] = {0};
2362
gba_to_gb_sound_parallel(&gb_addr[0], &gb_addr[1]);
2363
soundEvent_u8_parallel(gb_addr, address_array, data_array);
2364
break;
2365
}
2366
}
2367
}
2368
}
2369
2370
void gba_pcm_fifo_timer_overflowed( unsigned pcm_idx )
2371
{
2372
if ( pcm[pcm_idx].count <= 16 )
2373
{
2374
// Need to fill FIFO
2375
CPUCheckDMA( 3, pcm[pcm_idx].which ? 4 : 2 );
2376
2377
if ( pcm[pcm_idx].count <= 16 )
2378
{
2379
// Not filled by DMA, so fill with 16 bytes of silence
2380
int reg = pcm[pcm_idx].which ? FIFOB_L : FIFOA_L;
2381
2382
uint32_t address_array[8] = {reg, reg+2, reg, reg+2, reg, reg+2, reg, reg+2};
2383
soundEvent_u16_parallel(address_array);
2384
}
2385
}
2386
2387
// Read next sample from FIFO
2388
pcm[pcm_idx].count--;
2389
pcm[pcm_idx].dac = pcm[pcm_idx].fifo [pcm[pcm_idx].readIndex];
2390
pcm[pcm_idx].readIndex = (pcm[pcm_idx].readIndex + 1) & 31;
2391
2392
if(pcm[pcm_idx].pcm.output)
2393
{
2394
int time = soundTicksUp;
2395
2396
pcm[pcm_idx].dac = (int8_t)pcm[pcm_idx].dac >> pcm[pcm_idx].pcm.shift;
2397
int delta = pcm[pcm_idx].dac - pcm[pcm_idx].pcm.last_amp;
2398
if ( delta )
2399
{
2400
pcm[pcm_idx].pcm.last_amp = pcm[pcm_idx].dac;
2401
pcm_synth.offset( time, delta, pcm[pcm_idx].pcm.output );
2402
}
2403
pcm[pcm_idx].pcm.last_time = time;
2404
}
2405
}
2406
2407
void soundEvent_u8_parallel(int gb_addr[], uint32_t address[], uint8_t data[])
2408
{
2409
for(uint32_t i = 0; i < 2; i++)
2410
{
2411
ioMem[address[i]] = data[i];
2412
gb_apu_write_register( soundTicksUp, gb_addr[i], data[i] );
2413
2414
if ( address[i] == NR52 )
2415
{
2416
gba_pcm_apply_control(0, 0 );
2417
gba_pcm_apply_control(1, 1 );
2418
}
2419
// TODO: what about byte writes to SGCNT0_H etc.?
2420
}
2421
}
2422
2423
void soundEvent_u8(int gb_addr, uint32_t address, uint8_t data)
2424
{
2425
ioMem[address] = data;
2426
gb_apu_write_register( soundTicksUp, gb_addr, data );
2427
2428
if ( address == NR52 )
2429
{
2430
gba_pcm_apply_control(0, 0 );
2431
gba_pcm_apply_control(1, 1 );
2432
}
2433
// TODO: what about byte writes to SGCNT0_H etc.?
2434
}
2435
2436
2437
void soundEvent_u16(uint32_t address, uint16_t data)
2438
{
2439
switch ( address )
2440
{
2441
case SGCNT0_H:
2442
//Begin of Write SGCNT0_H
2443
WRITE16LE( &ioMem [SGCNT0_H], data & 0x770F );
2444
pcm_fifo_write_control( data, data >> 4);
2445
2446
gb_apu_volume( apu_vols [ioMem [SGCNT0_H] & 3] );
2447
//End of SGCNT0_H
2448
break;
2449
2450
case FIFOA_L:
2451
case FIFOA_H:
2452
pcm[0].fifo [pcm[0].writeIndex ] = data & 0xFF;
2453
pcm[0].fifo [pcm[0].writeIndex+1] = data >> 8;
2454
pcm[0].count += 2;
2455
pcm[0].writeIndex = (pcm[0].writeIndex + 2) & 31;
2456
WRITE16LE( &ioMem[address], data );
2457
break;
2458
2459
case FIFOB_L:
2460
case FIFOB_H:
2461
pcm[1].fifo [pcm[1].writeIndex ] = data & 0xFF;
2462
pcm[1].fifo [pcm[1].writeIndex+1] = data >> 8;
2463
pcm[1].count += 2;
2464
pcm[1].writeIndex = (pcm[1].writeIndex + 2) & 31;
2465
WRITE16LE( &ioMem[address], data );
2466
break;
2467
2468
case 0x88:
2469
data &= 0xC3FF;
2470
WRITE16LE( &ioMem[address], data );
2471
break;
2472
2473
default:
2474
{
2475
int gb_addr[2] = {address & ~1, address | 1};
2476
uint32_t address_array[2] = {address & ~ 1, address | 1};
2477
uint8_t data_array[2] = {(uint8_t)data, (uint8_t)(data >> 8)};
2478
gba_to_gb_sound_parallel(&gb_addr[0], &gb_addr[1]);
2479
soundEvent_u8_parallel(gb_addr, address_array, data_array);
2480
break;
2481
}
2482
}
2483
}
2484
2485
void soundTimerOverflow(int timer)
2486
{
2487
if ( timer == pcm[0].timer && pcm[0].enabled )
2488
gba_pcm_fifo_timer_overflowed(0);
2489
if ( timer == pcm[1].timer && pcm[1].enabled )
2490
gba_pcm_fifo_timer_overflowed(1);
2491
}
2492
2493
void process_sound_tick_fn (void)
2494
{
2495
// Run sound hardware to present
2496
pcm[0].pcm.last_time -= soundTicksUp;
2497
if ( pcm[0].pcm.last_time < -2048 )
2498
pcm[0].pcm.last_time = -2048;
2499
2500
pcm[1].pcm.last_time -= soundTicksUp;
2501
if ( pcm[1].pcm.last_time < -2048 )
2502
pcm[1].pcm.last_time = -2048;
2503
2504
/* Emulates sound hardware up to a specified time, ends current time
2505
frame, then starts a new frame at time 0 */
2506
2507
if(soundTicksUp > gb_apu.last_time)
2508
gb_apu_run_until_( soundTicksUp );
2509
2510
gb_apu.frame_time -= soundTicksUp;
2511
gb_apu.last_time -= soundTicksUp;
2512
2513
bufs_buffer[2].offset_ += soundTicksUp * bufs_buffer[2].factor_;
2514
bufs_buffer[1].offset_ += soundTicksUp * bufs_buffer[1].factor_;
2515
bufs_buffer[0].offset_ += soundTicksUp * bufs_buffer[0].factor_;
2516
2517
2518
// dump all the samples available
2519
// VBA will only ever store 1 frame worth of samples
2520
int numSamples = stereo_buffer_read_samples( (int16_t*) soundFinalWave, stereo_buffer_samples_avail());
2521
systemOnWriteDataToSoundBuffer(soundFinalWave, numSamples);
2522
2523
soundTicksUp = 0;
2524
}
2525
2526
void apply_muting (void)
2527
{
2528
// PCM
2529
gba_pcm_apply_control(1, 0 );
2530
gba_pcm_apply_control(1, 1 );
2531
2532
// APU
2533
gb_apu_set_output( &bufs_buffer[2], &bufs_buffer[0], &bufs_buffer[1], 0 );
2534
gb_apu_set_output( &bufs_buffer[2], &bufs_buffer[0], &bufs_buffer[1], 1 );
2535
gb_apu_set_output( &bufs_buffer[2], &bufs_buffer[0], &bufs_buffer[1], 2 );
2536
gb_apu_set_output( &bufs_buffer[2], &bufs_buffer[0], &bufs_buffer[1], 3 );
2537
}
2538
2539
2540
void remake_stereo_buffer (void)
2541
{
2542
if ( !ioMem )
2543
return;
2544
2545
// Clears pointers kept to old stereo_buffer
2546
gba_pcm_init();
2547
2548
// Stereo_Buffer
2549
2550
mixer_samples_read = 0;
2551
stereo_buffer_set_sample_rate( soundSampleRate, BLIP_DEFAULT_LENGTH );
2552
stereo_buffer_clock_rate( CLOCK_RATE );
2553
2554
// PCM
2555
pcm [0].which = 0;
2556
pcm [1].which = 1;
2557
2558
// APU
2559
gb_apu_new();
2560
gb_apu_reset( MODE_AGB, true );
2561
2562
stereo_buffer_clear();
2563
2564
soundTicksUp = 0;
2565
2566
apply_muting();
2567
2568
gb_apu_volume(apu_vols [ioMem [SGCNT0_H] & 3] );
2569
2570
pcm_synth.volume( 0.66 / 256 * SOUNDVOLUME_ );
2571
}
2572
2573
void soundReset (void)
2574
{
2575
remake_stereo_buffer();
2576
//Begin of Reset APU
2577
gb_apu_reset( MODE_AGB, true );
2578
2579
stereo_buffer_clear();
2580
2581
soundTicksUp = 0;
2582
2583
// Sound Event (NR52)
2584
int gb_addr = table[NR52 - 0x60];
2585
if ( gb_addr )
2586
{
2587
ioMem[NR52] = 0x80;
2588
gb_apu_write_register( soundTicksUp, gb_addr, 0x80 );
2589
2590
gba_pcm_apply_control(0, 0 );
2591
gba_pcm_apply_control(1, 1 );
2592
}
2593
2594
// TODO: what about byte writes to SGCNT0_H etc.?
2595
// End of Sound Event (NR52)
2596
}
2597
/*
2598
void soundSetSampleRate(long sampleRate)
2599
{
2600
if ( soundSampleRate != sampleRate )
2601
{
2602
soundSampleRate = sampleRate;
2603
remake_stereo_buffer();
2604
}
2605
}
2606
*/
2607
2608
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2609
// END SOUND.CPP
2610
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2611
2612
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2613
// BEGIN GBA.CPP
2614
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2615
/*============================================================
2616
GBA INLINE
2617
============================================================ */
2618
2619
#define UPDATE_REG(address, value) WRITE16LE(((u16 *)&ioMem[address]),value);
2620
#define ARM_PREFETCH_NEXT cpuPrefetch[1] = CPUReadMemoryQuick(bus.armNextPC+4);
2621
#define THUMB_PREFETCH_NEXT cpuPrefetch[1] = CPUReadHalfWordQuick(bus.armNextPC+2);
2622
2623
#define ARM_PREFETCH \
2624
{\
2625
cpuPrefetch[0] = CPUReadMemoryQuick(bus.armNextPC);\
2626
cpuPrefetch[1] = CPUReadMemoryQuick(bus.armNextPC+4);\
2627
}
2628
2629
#define THUMB_PREFETCH \
2630
{\
2631
cpuPrefetch[0] = CPUReadHalfWordQuick(bus.armNextPC);\
2632
cpuPrefetch[1] = CPUReadHalfWordQuick(bus.armNextPC+2);\
2633
}
2634
2635
int cpuNextEvent; // = 0;
2636
bool holdState; // = false;
2637
uint32_t cpuPrefetch[2];
2638
int cpuTotalTicks; // = 0;
2639
uint8_t memoryWait[16];
2640
uint8_t memoryWaitSeq[16];
2641
uint8_t memoryWait32[16];
2642
uint8_t memoryWaitSeq32[16];
2643
2644
uint8_t biosProtected[4];
2645
uint8_t cpuBitsSet[256];
2646
2647
bool N_FLAG; // = 0;
2648
bool C_FLAG; // = 0;
2649
bool Z_FLAG; // = 0;
2650
bool V_FLAG; // = 0;
2651
bool armState; // = true;
2652
bool armIrqEnable; // = true;
2653
int armMode; // = 0x1f;
2654
2655
typedef enum
2656
{
2657
REG_DISPCNT = 0x000,
2658
REG_DISPSTAT = 0x002,
2659
REG_VCOUNT = 0x003,
2660
REG_BG0CNT = 0x004,
2661
REG_BG1CNT = 0x005,
2662
REG_BG2CNT = 0x006,
2663
REG_BG3CNT = 0x007,
2664
REG_BG0HOFS = 0x08,
2665
REG_BG0VOFS = 0x09,
2666
REG_BG1HOFS = 0x0A,
2667
REG_BG1VOFS = 0x0B,
2668
REG_BG2HOFS = 0x0C,
2669
REG_BG2VOFS = 0x0D,
2670
REG_BG3HOFS = 0x0E,
2671
REG_BG3VOFS = 0x0F,
2672
REG_BG2PA = 0x10,
2673
REG_BG2PB = 0x11,
2674
REG_BG2PC = 0x12,
2675
REG_BG2PD = 0x13,
2676
REG_BG2X_L = 0x14,
2677
REG_BG2X_H = 0x15,
2678
REG_BG2Y_L = 0x16,
2679
REG_BG2Y_H = 0x17,
2680
REG_BG3PA = 0x18,
2681
REG_BG3PB = 0x19,
2682
REG_BG3PC = 0x1A,
2683
REG_BG3PD = 0x1B,
2684
REG_BG3X_L = 0x1C,
2685
REG_BG3X_H = 0x1D,
2686
REG_BG3Y_L = 0x1E,
2687
REG_BG3Y_H = 0x1F,
2688
REG_WIN0H = 0x20,
2689
REG_WIN1H = 0x21,
2690
REG_WIN0V = 0x22,
2691
REG_WIN1V = 0x23,
2692
REG_WININ = 0x24,
2693
REG_WINOUT = 0x25,
2694
REG_BLDCNT = 0x28,
2695
REG_BLDALPHA = 0x29,
2696
REG_BLDY = 0x2A,
2697
REG_TM0D = 0x80,
2698
REG_TM0CNT = 0x81,
2699
REG_TM1D = 0x82,
2700
REG_TM1CNT = 0x83,
2701
REG_TM2D = 0x84,
2702
REG_TM2CNT = 0x85,
2703
REG_TM3D = 0x86,
2704
REG_TM3CNT = 0x87,
2705
REG_P1 = 0x098,
2706
REG_P1CNT = 0x099,
2707
REG_RCNT = 0x9A,
2708
REG_IE = 0x100,
2709
REG_IF = 0x101,
2710
REG_IME = 0x104,
2711
REG_HALTCNT = 0x180
2712
} hardware_register;
2713
2714
uint16_t io_registers[1024 * 16];
2715
2716
u16 MOSAIC;
2717
2718
uint16_t BG2X_L ;
2719
uint16_t BG2X_H ;
2720
uint16_t BG2Y_L ;
2721
uint16_t BG2Y_H ;
2722
uint16_t BG3X_L ;
2723
uint16_t BG3X_H ;
2724
uint16_t BG3Y_L ;
2725
uint16_t BG3Y_H ;
2726
uint16_t BLDMOD ;
2727
uint16_t COLEV ;
2728
uint16_t COLY ;
2729
uint16_t DM0SAD_L ;
2730
uint16_t DM0SAD_H ;
2731
uint16_t DM0DAD_L ;
2732
uint16_t DM0DAD_H ;
2733
uint16_t DM0CNT_L ;
2734
uint16_t DM0CNT_H ;
2735
uint16_t DM1SAD_L ;
2736
uint16_t DM1SAD_H ;
2737
uint16_t DM1DAD_L ;
2738
uint16_t DM1DAD_H ;
2739
uint16_t DM1CNT_L ;
2740
uint16_t DM1CNT_H ;
2741
uint16_t DM2SAD_L ;
2742
uint16_t DM2SAD_H ;
2743
uint16_t DM2DAD_L ;
2744
uint16_t DM2DAD_H ;
2745
uint16_t DM2CNT_L ;
2746
uint16_t DM2CNT_H ;
2747
uint16_t DM3SAD_L ;
2748
uint16_t DM3SAD_H ;
2749
uint16_t DM3DAD_L ;
2750
uint16_t DM3DAD_H ;
2751
uint16_t DM3CNT_L ;
2752
uint16_t DM3CNT_H ;
2753
2754
uint8_t timerOnOffDelay ;
2755
uint16_t timer0Value ;
2756
uint32_t dma0Source ;
2757
uint32_t dma0Dest ;
2758
uint32_t dma1Source ;
2759
uint32_t dma1Dest ;
2760
uint32_t dma2Source ;
2761
uint32_t dma2Dest ;
2762
uint32_t dma3Source ;
2763
uint32_t dma3Dest ;
2764
void (Gigazoid::*cpuSaveGameFunc)(uint32_t,uint8_t);
2765
bool fxOn ;
2766
bool windowOn ;
2767
2768
int cpuDmaTicksToUpdate;
2769
2770
int IRQTicks;
2771
bool intState;
2772
2773
bus_t bus;
2774
graphics_t graphics;
2775
2776
memoryMap map[256];
2777
int clockTicks;
2778
2779
int romSize; // = 0x2000000;
2780
uint32_t line[6][240];
2781
bool gfxInWin[2][240];
2782
int lineOBJpixleft[128];
2783
int joy;
2784
2785
int gfxBG2Changed;
2786
int gfxBG3Changed;
2787
2788
int gfxBG2X;
2789
int gfxBG2Y;
2790
int gfxBG3X;
2791
int gfxBG3Y;
2792
2793
bool ioReadable[0x400];
2794
2795
//int gfxLastVCOUNT = 0;
2796
2797
// Waitstates when accessing data
2798
2799
#define DATATICKS_ACCESS_BUS_PREFETCH(address, value) \
2800
int addr = (address >> 24) & 15; \
2801
if ((addr>=0x08) || (addr < 0x02)) \
2802
{ \
2803
bus.busPrefetchCount=0; \
2804
bus.busPrefetch=false; \
2805
} \
2806
else if (bus.busPrefetch) \
2807
{ \
2808
int waitState = value; \
2809
waitState = (1 & ~waitState) | (waitState & waitState); \
2810
bus.busPrefetchCount = ((bus.busPrefetchCount+1)<<waitState) - 1; \
2811
}
2812
2813
/* Waitstates when accessing data */
2814
2815
#define DATATICKS_ACCESS_32BIT(address) (memoryWait32[(address >> 24) & 15])
2816
#define DATATICKS_ACCESS_32BIT_SEQ(address) (memoryWaitSeq32[(address >> 24) & 15])
2817
#define DATATICKS_ACCESS_16BIT(address) (memoryWait[(address >> 24) & 15])
2818
#define DATATICKS_ACCESS_16BIT_SEQ(address) (memoryWaitSeq[(address >> 24) & 15])
2819
2820
// Waitstates when executing opcode
2821
INLINE int codeTicksAccess(u32 address, u8 bit32) // THUMB NON SEQ
2822
{
2823
int addr, ret;
2824
2825
addr = (address>>24) & 15;
2826
2827
if (unsigned(addr - 0x08) <= 5)
2828
{
2829
if (bus.busPrefetchCount&0x1)
2830
{
2831
if (bus.busPrefetchCount&0x2)
2832
{
2833
bus.busPrefetchCount = ((bus.busPrefetchCount&0xFF)>>2) | (bus.busPrefetchCount&0xFFFFFF00);
2834
return 0;
2835
}
2836
bus.busPrefetchCount = ((bus.busPrefetchCount&0xFF)>>1) | (bus.busPrefetchCount&0xFFFFFF00);
2837
return memoryWaitSeq[addr]-1;
2838
}
2839
}
2840
bus.busPrefetchCount = 0;
2841
2842
if(bit32) /* ARM NON SEQ */
2843
ret = memoryWait32[addr];
2844
else /* THUMB NON SEQ */
2845
ret = memoryWait[addr];
2846
2847
return ret;
2848
}
2849
2850
INLINE int codeTicksAccessSeq16(u32 address) // THUMB SEQ
2851
{
2852
int addr = (address>>24) & 15;
2853
2854
if (unsigned(addr - 0x08) <= 5)
2855
{
2856
if (bus.busPrefetchCount&0x1)
2857
{
2858
bus.busPrefetchCount = ((bus.busPrefetchCount&0xFF)>>1) | (bus.busPrefetchCount&0xFFFFFF00);
2859
return 0;
2860
}
2861
else if (bus.busPrefetchCount>0xFF)
2862
{
2863
bus.busPrefetchCount=0;
2864
return memoryWait[addr];
2865
}
2866
}
2867
else
2868
bus.busPrefetchCount = 0;
2869
2870
return memoryWaitSeq[addr];
2871
}
2872
2873
INLINE int codeTicksAccessSeq32(u32 address) // ARM SEQ
2874
{
2875
int addr = (address>>24)&15;
2876
2877
if (unsigned(addr - 0x08) <= 5)
2878
{
2879
if (bus.busPrefetchCount&0x1)
2880
{
2881
if (bus.busPrefetchCount&0x2)
2882
{
2883
bus.busPrefetchCount = ((bus.busPrefetchCount&0xFF)>>2) | (bus.busPrefetchCount&0xFFFFFF00);
2884
return 0;
2885
}
2886
bus.busPrefetchCount = ((bus.busPrefetchCount&0xFF)>>1) | (bus.busPrefetchCount&0xFFFFFF00);
2887
return memoryWaitSeq[addr];
2888
}
2889
else if (bus.busPrefetchCount > 0xFF)
2890
{
2891
bus.busPrefetchCount=0;
2892
return memoryWait32[addr];
2893
}
2894
}
2895
return memoryWaitSeq32[addr];
2896
}
2897
2898
#define CPUReadByteQuick(addr) map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]
2899
#define CPUReadHalfWordQuick(addr) READ16LE(((u16*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
2900
#define CPUReadMemoryQuick(addr) READ32LE(((u32*)&map[(addr)>>24].address[(addr) & map[(addr)>>24].mask]))
2901
2902
bool stopState;
2903
#ifdef USE_MOTION_SENSOR
2904
extern bool cpuEEPROMSensorEnabled;
2905
#endif
2906
bool timer0On ;
2907
int timer0Ticks ;
2908
int timer0Reload ;
2909
int timer0ClockReload ;
2910
uint16_t timer1Value ;
2911
bool timer1On ;
2912
int timer1Ticks ;
2913
int timer1Reload ;
2914
int timer1ClockReload ;
2915
uint16_t timer2Value ;
2916
bool timer2On ;
2917
int timer2Ticks ;
2918
int timer2Reload ;
2919
int timer2ClockReload ;
2920
uint16_t timer3Value ;
2921
bool timer3On ;
2922
int timer3Ticks ;
2923
int timer3Reload ;
2924
int timer3ClockReload ;
2925
2926
INLINE u32 CPUReadMemory(u32 address)
2927
{
2928
if (readCallback)
2929
readCallback(address);
2930
2931
u32 value;
2932
switch(address >> 24)
2933
{
2934
case 0:
2935
/* BIOS */
2936
if(bus.reg[15].I >> 24)
2937
{
2938
if(address < 0x4000)
2939
value = READ32LE(((u32 *)&biosProtected));
2940
else goto unreadable;
2941
}
2942
else
2943
value = READ32LE(((u32 *)&bios[address & 0x3FFC]));
2944
break;
2945
case 0x02:
2946
/* external work RAM */
2947
value = READ32LE(((u32 *)&workRAM[address & 0x3FFFC]));
2948
break;
2949
case 0x03:
2950
/* internal work RAM */
2951
value = READ32LE(((u32 *)&internalRAM[address & 0x7ffC]));
2952
break;
2953
case 0x04:
2954
/* I/O registers */
2955
if (address == 0x4000130)
2956
{
2957
if (padCallback)
2958
padCallback();
2959
lagged = false;
2960
}
2961
if((address < 0x4000400) && ioReadable[address & 0x3fc])
2962
{
2963
if(ioReadable[(address & 0x3fc) + 2])
2964
value = READ32LE(((u32 *)&ioMem[address & 0x3fC]));
2965
else
2966
value = READ16LE(((u16 *)&ioMem[address & 0x3fc]));
2967
}
2968
else
2969
goto unreadable;
2970
break;
2971
case 0x05:
2972
/* palette RAM */
2973
value = READ32LE(((u32 *)&graphics.paletteRAM[address & 0x3fC]));
2974
break;
2975
case 0x06:
2976
/* VRAM */
2977
address = (address & 0x1fffc);
2978
if (((io_registers[REG_DISPCNT] & 7) >2) && ((address & 0x1C000) == 0x18000))
2979
{
2980
value = 0;
2981
break;
2982
}
2983
if ((address & 0x18000) == 0x18000)
2984
address &= 0x17fff;
2985
value = READ32LE(((u32 *)&vram[address]));
2986
break;
2987
case 0x07:
2988
/* OAM RAM */
2989
value = READ32LE(((u32 *)&oam[address & 0x3FC]));
2990
break;
2991
case 0x08:
2992
case 0x09:
2993
case 0x0A:
2994
case 0x0B:
2995
case 0x0C:
2996
/* gamepak ROM */
2997
value = READ32LE(((u32 *)&rom[address&0x1FFFFFC]));
2998
break;
2999
case 0x0D:
3000
value = eepromRead();
3001
break;
3002
case 14:
3003
case 15:
3004
value = flashRead(address) * 0x01010101;
3005
break;
3006
default:
3007
unreadable:
3008
if(armState)
3009
value = CPUReadHalfWordQuick(bus.reg[15].I + (address & 2));
3010
else
3011
value = CPUReadHalfWordQuick(bus.reg[15].I);
3012
}
3013
3014
if(address & 3) {
3015
int shift = (address & 3) << 3;
3016
value = (value >> shift) | (value << (32 - shift));
3017
}
3018
return value;
3019
}
3020
3021
INLINE u32 CPUReadHalfWord(u32 address)
3022
{
3023
if (readCallback)
3024
readCallback(address);
3025
3026
u32 value;
3027
switch(address >> 24)
3028
{
3029
case 0:
3030
if (bus.reg[15].I >> 24)
3031
{
3032
if(address < 0x4000)
3033
value = READ16LE(((u16 *)&biosProtected[address&2]));
3034
else
3035
goto unreadable;
3036
}
3037
else
3038
value = READ16LE(((u16 *)&bios[address & 0x3FFE]));
3039
break;
3040
case 2:
3041
value = READ16LE(((u16 *)&workRAM[address & 0x3FFFE]));
3042
break;
3043
case 3:
3044
value = READ16LE(((u16 *)&internalRAM[address & 0x7ffe]));
3045
break;
3046
case 4:
3047
if (address == 0x4000130)
3048
{
3049
if (padCallback)
3050
padCallback();
3051
lagged = false;
3052
}
3053
3054
if((address < 0x4000400) && ioReadable[address & 0x3fe])
3055
{
3056
value = READ16LE(((u16 *)&ioMem[address & 0x3fe]));
3057
if (((address & 0x3fe)>0xFF) && ((address & 0x3fe)<0x10E))
3058
{
3059
if (((address & 0x3fe) == 0x100) && timer0On)
3060
value = 0xFFFF - ((timer0Ticks-cpuTotalTicks) >> timer0ClockReload);
3061
else
3062
if (((address & 0x3fe) == 0x104) && timer1On && !(io_registers[REG_TM1CNT] & 4))
3063
value = 0xFFFF - ((timer1Ticks-cpuTotalTicks) >> timer1ClockReload);
3064
else
3065
if (((address & 0x3fe) == 0x108) && timer2On && !(io_registers[REG_TM2CNT] & 4))
3066
value = 0xFFFF - ((timer2Ticks-cpuTotalTicks) >> timer2ClockReload);
3067
else
3068
if (((address & 0x3fe) == 0x10C) && timer3On && !(io_registers[REG_TM3CNT] & 4))
3069
value = 0xFFFF - ((timer3Ticks-cpuTotalTicks) >> timer3ClockReload);
3070
}
3071
}
3072
else goto unreadable;
3073
break;
3074
case 5:
3075
value = READ16LE(((u16 *)&graphics.paletteRAM[address & 0x3fe]));
3076
break;
3077
case 6:
3078
address = (address & 0x1fffe);
3079
if (((io_registers[REG_DISPCNT] & 7) >2) && ((address & 0x1C000) == 0x18000))
3080
{
3081
value = 0;
3082
break;
3083
}
3084
if ((address & 0x18000) == 0x18000)
3085
address &= 0x17fff;
3086
value = READ16LE(((u16 *)&vram[address]));
3087
break;
3088
case 7:
3089
value = READ16LE(((u16 *)&oam[address & 0x3fe]));
3090
break;
3091
case 8:
3092
case 9:
3093
case 10:
3094
case 11:
3095
case 12:
3096
if(rtcEnabled && (address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8))
3097
value = rtcRead(address);
3098
else
3099
value = READ16LE(((u16 *)&rom[address & 0x1FFFFFE]));
3100
break;
3101
case 13:
3102
value = eepromRead();
3103
break;
3104
case 14:
3105
value = flashRead(address) * 0x0101;
3106
break;
3107
default:
3108
unreadable:
3109
{
3110
int param = bus.reg[15].I;
3111
if(armState)
3112
param += (address & 2);
3113
value = CPUReadHalfWordQuick(param);
3114
}
3115
break;
3116
}
3117
3118
if(address & 1)
3119
value = (value >> 8) | (value << 24);
3120
3121
return value;
3122
}
3123
3124
INLINE u16 CPUReadHalfWordSigned(u32 address)
3125
{
3126
u16 value = CPUReadHalfWord(address);
3127
if((address & 1))
3128
value = (s8)value;
3129
return value;
3130
}
3131
3132
INLINE u8 CPUReadByte(u32 address)
3133
{
3134
if (readCallback)
3135
readCallback(address);
3136
3137
switch(address >> 24)
3138
{
3139
case 0:
3140
if (bus.reg[15].I >> 24)
3141
{
3142
if(address < 0x4000)
3143
return biosProtected[address & 3];
3144
else
3145
goto unreadable;
3146
}
3147
return bios[address & 0x3FFF];
3148
case 2:
3149
return workRAM[address & 0x3FFFF];
3150
case 3:
3151
return internalRAM[address & 0x7fff];
3152
case 4:
3153
if (address == 0x4000130 || address == 0x4000131)
3154
{
3155
if (padCallback)
3156
padCallback();
3157
lagged = false;
3158
}
3159
3160
if((address < 0x4000400) && ioReadable[address & 0x3ff])
3161
return ioMem[address & 0x3ff];
3162
else goto unreadable;
3163
case 5:
3164
return graphics.paletteRAM[address & 0x3ff];
3165
case 6:
3166
address = (address & 0x1ffff);
3167
if (((io_registers[REG_DISPCNT] & 7) >2) && ((address & 0x1C000) == 0x18000))
3168
return 0;
3169
if ((address & 0x18000) == 0x18000)
3170
address &= 0x17fff;
3171
return vram[address];
3172
case 7:
3173
return oam[address & 0x3ff];
3174
case 8:
3175
case 9:
3176
case 10:
3177
case 11:
3178
case 12:
3179
return rom[address & 0x1FFFFFF];
3180
case 13:
3181
return eepromRead();
3182
case 14:
3183
#ifdef USE_MOTION_SENSOR
3184
if(cpuEEPROMSensorEnabled)
3185
{
3186
switch(address & 0x00008f00)
3187
{
3188
case 0x8200:
3189
return systemGetSensorX() & 255;
3190
case 0x8300:
3191
return (systemGetSensorX() >> 8)|0x80;
3192
case 0x8400:
3193
return systemGetSensorY() & 255;
3194
case 0x8500:
3195
return systemGetSensorY() >> 8;
3196
}
3197
}
3198
#endif
3199
return flashRead(address);
3200
default:
3201
unreadable:
3202
if(armState)
3203
return CPUReadByteQuick(bus.reg[15].I+(address & 3));
3204
else
3205
return CPUReadByteQuick(bus.reg[15].I+(address & 1));
3206
}
3207
}
3208
3209
INLINE void CPUWriteMemory(u32 address, u32 value)
3210
{
3211
if (writeCallback)
3212
writeCallback(address);
3213
3214
switch(address >> 24)
3215
{
3216
case 0x02:
3217
WRITE32LE(((u32 *)&workRAM[address & 0x3FFFC]), value);
3218
break;
3219
case 0x03:
3220
WRITE32LE(((u32 *)&internalRAM[address & 0x7ffC]), value);
3221
break;
3222
case 0x04:
3223
if(address < 0x4000400)
3224
{
3225
CPUUpdateRegister((address & 0x3FC), value & 0xFFFF);
3226
CPUUpdateRegister((address & 0x3FC) + 2, (value >> 16));
3227
}
3228
break;
3229
case 0x05:
3230
WRITE32LE(((u32 *)&graphics.paletteRAM[address & 0x3FC]), value);
3231
break;
3232
case 0x06:
3233
address = (address & 0x1fffc);
3234
if (((io_registers[REG_DISPCNT] & 7) >2) && ((address & 0x1C000) == 0x18000))
3235
return;
3236
if ((address & 0x18000) == 0x18000)
3237
address &= 0x17fff;
3238
3239
3240
WRITE32LE(((u32 *)&vram[address]), value);
3241
break;
3242
case 0x07:
3243
WRITE32LE(((u32 *)&oam[address & 0x3fc]), value);
3244
break;
3245
case 0x0D:
3246
if (cpuEEPROMEnabled)
3247
eepromWrite(value);
3248
break;
3249
case 0x0E:
3250
(this->*cpuSaveGameFunc)(address, (u8)value);
3251
break;
3252
default:
3253
break;
3254
}
3255
}
3256
3257
INLINE void CPUWriteHalfWord(u32 address, u16 value)
3258
{
3259
if (writeCallback)
3260
writeCallback(address);
3261
3262
switch(address >> 24)
3263
{
3264
case 2:
3265
WRITE16LE(((u16 *)&workRAM[address & 0x3FFFE]),value);
3266
break;
3267
case 3:
3268
WRITE16LE(((u16 *)&internalRAM[address & 0x7ffe]), value);
3269
break;
3270
case 4:
3271
if(address < 0x4000400)
3272
CPUUpdateRegister(address & 0x3fe, value);
3273
break;
3274
case 5:
3275
WRITE16LE(((u16 *)&graphics.paletteRAM[address & 0x3fe]), value);
3276
break;
3277
case 6:
3278
address = (address & 0x1fffe);
3279
if (((io_registers[REG_DISPCNT] & 7) >2) && ((address & 0x1C000) == 0x18000))
3280
return;
3281
if ((address & 0x18000) == 0x18000)
3282
address &= 0x17fff;
3283
WRITE16LE(((u16 *)&vram[address]), value);
3284
break;
3285
case 7:
3286
WRITE16LE(((u16 *)&oam[address & 0x3fe]), value);
3287
break;
3288
case 8:
3289
case 9:
3290
if(address == 0x80000c4 || address == 0x80000c6 || address == 0x80000c8)
3291
if(!rtcWrite(address, value))
3292
break;
3293
break;
3294
case 13:
3295
if(cpuEEPROMEnabled)
3296
eepromWrite((u8)value);
3297
break;
3298
case 14:
3299
(this->*cpuSaveGameFunc)(address, (u8)value);
3300
break;
3301
default:
3302
break;
3303
}
3304
}
3305
3306
INLINE void CPUWriteByte(u32 address, u8 b)
3307
{
3308
if (writeCallback)
3309
writeCallback(address);
3310
3311
switch(address >> 24)
3312
{
3313
case 2:
3314
workRAM[address & 0x3FFFF] = b;
3315
break;
3316
case 3:
3317
internalRAM[address & 0x7fff] = b;
3318
break;
3319
case 4:
3320
if(address < 0x4000400)
3321
{
3322
switch(address & 0x3FF)
3323
{
3324
case 0x60:
3325
case 0x61:
3326
case 0x62:
3327
case 0x63:
3328
case 0x64:
3329
case 0x65:
3330
case 0x68:
3331
case 0x69:
3332
case 0x6c:
3333
case 0x6d:
3334
case 0x70:
3335
case 0x71:
3336
case 0x72:
3337
case 0x73:
3338
case 0x74:
3339
case 0x75:
3340
case 0x78:
3341
case 0x79:
3342
case 0x7c:
3343
case 0x7d:
3344
case 0x80:
3345
case 0x81:
3346
case 0x84:
3347
case 0x85:
3348
case 0x90:
3349
case 0x91:
3350
case 0x92:
3351
case 0x93:
3352
case 0x94:
3353
case 0x95:
3354
case 0x96:
3355
case 0x97:
3356
case 0x98:
3357
case 0x99:
3358
case 0x9a:
3359
case 0x9b:
3360
case 0x9c:
3361
case 0x9d:
3362
case 0x9e:
3363
case 0x9f:
3364
{
3365
int gb_addr = table[(address & 0xFF) - 0x60];
3366
soundEvent_u8(gb_addr, address&0xFF, b);
3367
}
3368
break;
3369
case 0x301: // HALTCNT, undocumented
3370
if(b == 0x80)
3371
stopState = true;
3372
holdState = 1;
3373
cpuNextEvent = cpuTotalTicks;
3374
break;
3375
default: // every other register
3376
{
3377
u32 lowerBits = address & 0x3fe;
3378
uint16_t param;
3379
if(address & 1)
3380
param = (READ16LE(&ioMem[lowerBits]) & 0x00FF) | (b << 8);
3381
else
3382
param = (READ16LE(&ioMem[lowerBits]) & 0xFF00) | b;
3383
3384
CPUUpdateRegister(lowerBits, param);
3385
}
3386
break;
3387
}
3388
}
3389
break;
3390
case 5:
3391
// no need to switch
3392
*((u16 *)&graphics.paletteRAM[address & 0x3FE]) = (b << 8) | b;
3393
break;
3394
case 6:
3395
address = (address & 0x1fffe);
3396
if (((io_registers[REG_DISPCNT] & 7) >2) && ((address & 0x1C000) == 0x18000))
3397
return;
3398
if ((address & 0x18000) == 0x18000)
3399
address &= 0x17fff;
3400
3401
// no need to switch
3402
// byte writes to OBJ VRAM are ignored
3403
if ((address) < objTilesAddress[((io_registers[REG_DISPCNT] & 7)+1)>>2])
3404
*((u16 *)&vram[address]) = (b << 8) | b;
3405
break;
3406
case 7:
3407
// no need to switch
3408
// byte writes to OAM are ignored
3409
// *((u16 *)&oam[address & 0x3FE]) = (b << 8) | b;
3410
break;
3411
case 13:
3412
if(cpuEEPROMEnabled)
3413
eepromWrite(b);
3414
break;
3415
case 14:
3416
(this->*cpuSaveGameFunc)(address, b);
3417
break;
3418
default:
3419
break;
3420
}
3421
}
3422
3423
3424
/*============================================================
3425
BIOS
3426
============================================================ */
3427
3428
void BIOS_RegisterRamReset(u32 flags)
3429
{
3430
// no need to trace here. this is only called directly from GBA.cpp
3431
// to emulate bios initialization
3432
3433
CPUUpdateRegister(0x0, 0x80);
3434
3435
if(flags)
3436
{
3437
if(flags & 0x01)
3438
memset(workRAM, 0, 0x40000); // clear work RAM
3439
3440
if(flags & 0x02)
3441
memset(internalRAM, 0, 0x7e00); // don't clear 0x7e00-0x7fff, clear internal RAM
3442
3443
if(flags & 0x04)
3444
memset(graphics.paletteRAM, 0, 0x400); // clear palette RAM
3445
3446
if(flags & 0x08)
3447
memset(vram, 0, 0x18000); // clear VRAM
3448
3449
if(flags & 0x10)
3450
memset(oam, 0, 0x400); // clean OAM
3451
3452
if(flags & 0x80) {
3453
int i;
3454
for(i = 0; i < 0x10; i++)
3455
CPUUpdateRegister(0x200+i*2, 0);
3456
3457
for(i = 0; i < 0xF; i++)
3458
CPUUpdateRegister(0x4+i*2, 0);
3459
3460
for(i = 0; i < 0x20; i++)
3461
CPUUpdateRegister(0x20+i*2, 0);
3462
3463
for(i = 0; i < 0x18; i++)
3464
CPUUpdateRegister(0xb0+i*2, 0);
3465
3466
CPUUpdateRegister(0x130, 0);
3467
CPUUpdateRegister(0x20, 0x100);
3468
CPUUpdateRegister(0x30, 0x100);
3469
CPUUpdateRegister(0x26, 0x100);
3470
CPUUpdateRegister(0x36, 0x100);
3471
}
3472
3473
if(flags & 0x20) {
3474
int i;
3475
for(i = 0; i < 8; i++)
3476
CPUUpdateRegister(0x110+i*2, 0);
3477
CPUUpdateRegister(0x134, 0x8000);
3478
for(i = 0; i < 7; i++)
3479
CPUUpdateRegister(0x140+i*2, 0);
3480
}
3481
3482
if(flags & 0x40) {
3483
int i;
3484
CPUWriteByte(0x4000084, 0);
3485
CPUWriteByte(0x4000084, 0x80);
3486
CPUWriteMemory(0x4000080, 0x880e0000);
3487
CPUUpdateRegister(0x88, CPUReadHalfWord(0x4000088)&0x3ff);
3488
CPUWriteByte(0x4000070, 0x70);
3489
for(i = 0; i < 8; i++)
3490
CPUUpdateRegister(0x90+i*2, 0);
3491
CPUWriteByte(0x4000070, 0);
3492
for(i = 0; i < 8; i++)
3493
CPUUpdateRegister(0x90+i*2, 0);
3494
CPUWriteByte(0x4000084, 0);
3495
}
3496
}
3497
}
3498
3499
void BIOS_SoftReset (void)
3500
{
3501
armState = true;
3502
armMode = 0x1F;
3503
armIrqEnable = false;
3504
C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false;
3505
bus.reg[13].I = 0x03007F00;
3506
bus.reg[14].I = 0x00000000;
3507
bus.reg[16].I = 0x00000000;
3508
bus.reg[R13_IRQ].I = 0x03007FA0;
3509
bus.reg[R14_IRQ].I = 0x00000000;
3510
bus.reg[SPSR_IRQ].I = 0x00000000;
3511
bus.reg[R13_SVC].I = 0x03007FE0;
3512
bus.reg[R14_SVC].I = 0x00000000;
3513
bus.reg[SPSR_SVC].I = 0x00000000;
3514
u8 b = internalRAM[0x7ffa];
3515
3516
memset(&internalRAM[0x7e00], 0, 0x200);
3517
3518
if(b) {
3519
bus.armNextPC = 0x02000000;
3520
bus.reg[15].I = 0x02000004;
3521
} else {
3522
bus.armNextPC = 0x08000000;
3523
bus.reg[15].I = 0x08000004;
3524
}
3525
}
3526
3527
#define BIOS_REGISTER_RAM_RESET() BIOS_RegisterRamReset(bus.reg[0].I);
3528
3529
#define CPU_UPDATE_CPSR() \
3530
{ \
3531
uint32_t CPSR; \
3532
CPSR = bus.reg[16].I & 0x40; \
3533
if(N_FLAG) \
3534
CPSR |= 0x80000000; \
3535
if(Z_FLAG) \
3536
CPSR |= 0x40000000; \
3537
if(C_FLAG) \
3538
CPSR |= 0x20000000; \
3539
if(V_FLAG) \
3540
CPSR |= 0x10000000; \
3541
if(!armState) \
3542
CPSR |= 0x00000020; \
3543
if(!armIrqEnable) \
3544
CPSR |= 0x80; \
3545
CPSR |= (armMode & 0x1F); \
3546
bus.reg[16].I = CPSR; \
3547
}
3548
3549
#define CPU_SOFTWARE_INTERRUPT() \
3550
{ \
3551
uint32_t PC = bus.reg[15].I; \
3552
bool savedArmState = armState; \
3553
if(armMode != 0x13) \
3554
CPUSwitchMode(0x13, true, false); \
3555
bus.reg[14].I = PC - (savedArmState ? 4 : 2); \
3556
bus.reg[15].I = 0x08; \
3557
armState = true; \
3558
armIrqEnable = false; \
3559
bus.armNextPC = 0x08; \
3560
ARM_PREFETCH; \
3561
bus.reg[15].I += 4; \
3562
}
3563
3564
void CPUUpdateFlags(bool breakLoop)
3565
{
3566
uint32_t CPSR = bus.reg[16].I;
3567
3568
N_FLAG = (CPSR & 0x80000000) ? true: false;
3569
Z_FLAG = (CPSR & 0x40000000) ? true: false;
3570
C_FLAG = (CPSR & 0x20000000) ? true: false;
3571
V_FLAG = (CPSR & 0x10000000) ? true: false;
3572
armState = (CPSR & 0x20) ? false : true;
3573
armIrqEnable = (CPSR & 0x80) ? false : true;
3574
if (breakLoop && armIrqEnable && (io_registers[REG_IF] & io_registers[REG_IE]) && (io_registers[REG_IME] & 1))
3575
cpuNextEvent = cpuTotalTicks;
3576
}
3577
3578
void CPUSoftwareInterrupt(int comment)
3579
{
3580
if(armState)
3581
comment >>= 16;
3582
3583
CPU_SOFTWARE_INTERRUPT();
3584
}
3585
3586
3587
/*============================================================
3588
GBA ARM CORE
3589
============================================================ */
3590
3591
#ifdef _MSC_VER
3592
// Disable "empty statement" warnings
3593
#pragma warning(disable: 4390)
3594
// Visual C's inline assembler treats "offset" as a reserved word, so we
3595
// tell it otherwise. If you want to use it, write "OFFSET" in capitals.
3596
#define offset offset_
3597
#endif
3598
3599
void armUnknownInsn(u32 opcode)
3600
{
3601
u32 PC = bus.reg[15].I;
3602
bool savedArmState = armState;
3603
if(armMode != 0x1b )
3604
CPUSwitchMode(0x1b, true, false);
3605
bus.reg[14].I = PC - (savedArmState ? 4 : 2);
3606
bus.reg[15].I = 0x04;
3607
armState = true;
3608
armIrqEnable = false;
3609
bus.armNextPC = 0x04;
3610
ARM_PREFETCH;
3611
bus.reg[15].I += 4;
3612
}
3613
3614
// Common macros //////////////////////////////////////////////////////////
3615
3616
#define NEG(i) ((i) >> 31)
3617
#define POS(i) ((~(i)) >> 31)
3618
3619
// The following macros are used for optimization; any not defined for a
3620
// particular compiler/CPU combination default to the C core versions.
3621
//
3622
// ALU_INIT_C: Used at the beginning of ALU instructions (AND/EOR/...).
3623
// (ALU_INIT_NC) Can consist of variable declarations, like the C core,
3624
// or the start of a continued assembly block, like the
3625
// x86-optimized version. The _C version is used when the
3626
// carry flag from the shift operation is needed (logical
3627
// operations that set condition codes, like ANDS); the
3628
// _NC version is used when the carry result is ignored.
3629
// VALUE_XXX: Retrieve the second operand's value for an ALU instruction.
3630
// The _C and _NC versions are used the same way as ALU_INIT.
3631
// OP_XXX: ALU operations. XXX is the instruction name.
3632
// SETCOND_NONE: Used in multiply instructions in place of SETCOND_MUL
3633
// when the condition codes are not set. Usually empty.
3634
// SETCOND_MUL: Used in multiply instructions to set the condition codes.
3635
// ROR_IMM_MSR: Used to rotate the immediate operand for MSR.
3636
// ROR_OFFSET: Used to rotate the `offset' parameter for LDR and STR
3637
// instructions.
3638
// RRX_OFFSET: Used to rotate (RRX) the `offset' parameter for LDR and
3639
// STR instructions.
3640
3641
// C core
3642
3643
#define C_SETCOND_LOGICAL \
3644
N_FLAG = ((s32)res < 0) ? true : false; \
3645
Z_FLAG = (res == 0) ? true : false; \
3646
C_FLAG = C_OUT;
3647
#define C_SETCOND_ADD \
3648
N_FLAG = ((s32)res < 0) ? true : false; \
3649
Z_FLAG = (res == 0) ? true : false; \
3650
V_FLAG = ((NEG(lhs) & NEG(rhs) & POS(res)) | \
3651
(POS(lhs) & POS(rhs) & NEG(res))) ? true : false;\
3652
C_FLAG = ((NEG(lhs) & NEG(rhs)) | \
3653
(NEG(lhs) & POS(res)) | \
3654
(NEG(rhs) & POS(res))) ? true : false;
3655
#define C_SETCOND_SUB \
3656
N_FLAG = ((s32)res < 0) ? true : false; \
3657
Z_FLAG = (res == 0) ? true : false; \
3658
V_FLAG = ((NEG(lhs) & POS(rhs) & POS(res)) | \
3659
(POS(lhs) & NEG(rhs) & NEG(res))) ? true : false;\
3660
C_FLAG = ((NEG(lhs) & POS(rhs)) | \
3661
(NEG(lhs) & POS(res)) | \
3662
(POS(rhs) & POS(res))) ? true : false;
3663
3664
#ifndef ALU_INIT_C
3665
#define ALU_INIT_C \
3666
int dest = (opcode>>12) & 15; \
3667
bool C_OUT = C_FLAG; \
3668
u32 value;
3669
#endif
3670
// OP Rd,Rb,Rm LSL #
3671
#ifndef VALUE_LSL_IMM_C
3672
#define VALUE_LSL_IMM_C \
3673
unsigned int shift = (opcode >> 7) & 0x1F; \
3674
if (!shift) { /* LSL #0 most common? */ \
3675
value = bus.reg[opcode & 0x0F].I; \
3676
} else { \
3677
u32 v = bus.reg[opcode & 0x0F].I; \
3678
C_OUT = (v >> (32 - shift)) & 1 ? true : false; \
3679
value = v << shift; \
3680
}
3681
#endif
3682
// OP Rd,Rb,Rm LSL Rs
3683
#ifndef VALUE_LSL_REG_C
3684
#define VALUE_LSL_REG_C \
3685
unsigned int shift = bus.reg[(opcode >> 8)&15].B.B0; \
3686
if (shift) { \
3687
if (shift == 32) { \
3688
value = 0; \
3689
C_OUT = (bus.reg[opcode & 0x0F].I & 1 ? true : false);\
3690
} else if (shift < 32) { \
3691
u32 v = bus.reg[opcode & 0x0F].I; \
3692
C_OUT = (v >> (32 - shift)) & 1 ? true : false;\
3693
value = v << shift; \
3694
} else { \
3695
value = 0; \
3696
C_OUT = false; \
3697
} \
3698
} else { \
3699
value = bus.reg[opcode & 0x0F].I; \
3700
}
3701
#endif
3702
// OP Rd,Rb,Rm LSR #
3703
#ifndef VALUE_LSR_IMM_C
3704
#define VALUE_LSR_IMM_C \
3705
unsigned int shift = (opcode >> 7) & 0x1F; \
3706
if (shift) { \
3707
u32 v = bus.reg[opcode & 0x0F].I; \
3708
C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
3709
value = v >> shift; \
3710
} else { \
3711
value = 0; \
3712
C_OUT = (bus.reg[opcode & 0x0F].I & 0x80000000) ? true : false;\
3713
}
3714
#endif
3715
// OP Rd,Rb,Rm LSR Rs
3716
#ifndef VALUE_LSR_REG_C
3717
#define VALUE_LSR_REG_C \
3718
unsigned int shift = bus.reg[(opcode >> 8)&15].B.B0; \
3719
if (shift) { \
3720
if (shift == 32) { \
3721
value = 0; \
3722
C_OUT = (bus.reg[opcode & 0x0F].I & 0x80000000 ? true : false);\
3723
} else if (shift < 32) { \
3724
u32 v = bus.reg[opcode & 0x0F].I; \
3725
C_OUT = (v >> (shift - 1)) & 1 ? true : false;\
3726
value = v >> shift; \
3727
} else { \
3728
value = 0; \
3729
C_OUT = false; \
3730
} \
3731
} else { \
3732
value = bus.reg[opcode & 0x0F].I; \
3733
}
3734
#endif
3735
// OP Rd,Rb,Rm ASR #
3736
#ifndef VALUE_ASR_IMM_C
3737
#define VALUE_ASR_IMM_C \
3738
unsigned int shift = (opcode >> 7) & 0x1F; \
3739
if (shift) { \
3740
s32 v = bus.reg[opcode & 0x0F].I; \
3741
C_OUT = (v >> (int)(shift - 1)) & 1 ? true : false;\
3742
value = v >> (int)shift; \
3743
} else { \
3744
if (bus.reg[opcode & 0x0F].I & 0x80000000) { \
3745
value = 0xFFFFFFFF; \
3746
C_OUT = true; \
3747
} else { \
3748
value = 0; \
3749
C_OUT = false; \
3750
} \
3751
}
3752
#endif
3753
// OP Rd,Rb,Rm ASR Rs
3754
#ifndef VALUE_ASR_REG_C
3755
#define VALUE_ASR_REG_C \
3756
unsigned int shift = bus.reg[(opcode >> 8)&15].B.B0; \
3757
if (shift < 32) { \
3758
if (shift) { \
3759
s32 v = bus.reg[opcode & 0x0F].I; \
3760
C_OUT = (v >> (int)(shift - 1)) & 1 ? true : false;\
3761
value = v >> (int)shift; \
3762
} else { \
3763
value = bus.reg[opcode & 0x0F].I; \
3764
} \
3765
} else { \
3766
if (bus.reg[opcode & 0x0F].I & 0x80000000) { \
3767
value = 0xFFFFFFFF; \
3768
C_OUT = true; \
3769
} else { \
3770
value = 0; \
3771
C_OUT = false; \
3772
} \
3773
}
3774
#endif
3775
// OP Rd,Rb,Rm ROR #
3776
#ifndef VALUE_ROR_IMM_C
3777
#define VALUE_ROR_IMM_C \
3778
unsigned int shift = (opcode >> 7) & 0x1F; \
3779
if (shift) { \
3780
u32 v = bus.reg[opcode & 0x0F].I; \
3781
C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
3782
value = ((v << (32 - shift)) | \
3783
(v >> shift)); \
3784
} else { \
3785
u32 v = bus.reg[opcode & 0x0F].I; \
3786
C_OUT = (v & 1) ? true : false; \
3787
value = ((v >> 1) | \
3788
(C_FLAG << 31)); \
3789
}
3790
#endif
3791
// OP Rd,Rb,Rm ROR Rs
3792
#ifndef VALUE_ROR_REG_C
3793
#define VALUE_ROR_REG_C \
3794
unsigned int shift = bus.reg[(opcode >> 8)&15].B.B0; \
3795
if (shift & 0x1F) { \
3796
u32 v = bus.reg[opcode & 0x0F].I; \
3797
C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
3798
value = ((v << (32 - shift)) | \
3799
(v >> shift)); \
3800
} else { \
3801
value = bus.reg[opcode & 0x0F].I; \
3802
if (shift) \
3803
C_OUT = (value & 0x80000000 ? true : false);\
3804
}
3805
#endif
3806
// OP Rd,Rb,# ROR #
3807
#ifndef VALUE_IMM_C
3808
#define VALUE_IMM_C \
3809
int shift = (opcode & 0xF00) >> 7; \
3810
if (shift) { \
3811
u32 v = opcode & 0xFF; \
3812
C_OUT = (v >> (shift - 1)) & 1 ? true : false; \
3813
value = ((v << (32 - shift)) | \
3814
(v >> shift)); \
3815
} else { \
3816
value = opcode & 0xFF; \
3817
}
3818
#endif
3819
3820
// Make the non-carry versions default to the carry versions
3821
// (this is fine for C--the compiler will optimize the dead code out)
3822
#ifndef ALU_INIT_NC
3823
#define ALU_INIT_NC ALU_INIT_C
3824
#endif
3825
#ifndef VALUE_LSL_IMM_NC
3826
#define VALUE_LSL_IMM_NC VALUE_LSL_IMM_C
3827
#endif
3828
#ifndef VALUE_LSL_REG_NC
3829
#define VALUE_LSL_REG_NC VALUE_LSL_REG_C
3830
#endif
3831
#ifndef VALUE_LSR_IMM_NC
3832
#define VALUE_LSR_IMM_NC VALUE_LSR_IMM_C
3833
#endif
3834
#ifndef VALUE_LSR_REG_NC
3835
#define VALUE_LSR_REG_NC VALUE_LSR_REG_C
3836
#endif
3837
#ifndef VALUE_ASR_IMM_NC
3838
#define VALUE_ASR_IMM_NC VALUE_ASR_IMM_C
3839
#endif
3840
#ifndef VALUE_ASR_REG_NC
3841
#define VALUE_ASR_REG_NC VALUE_ASR_REG_C
3842
#endif
3843
#ifndef VALUE_ROR_IMM_NC
3844
#define VALUE_ROR_IMM_NC VALUE_ROR_IMM_C
3845
#endif
3846
#ifndef VALUE_ROR_REG_NC
3847
#define VALUE_ROR_REG_NC VALUE_ROR_REG_C
3848
#endif
3849
#ifndef VALUE_IMM_NC
3850
#define VALUE_IMM_NC VALUE_IMM_C
3851
#endif
3852
3853
#define C_CHECK_PC(SETCOND) if (dest != 15) { SETCOND }
3854
#ifndef OP_AND
3855
#define OP_AND \
3856
u32 res = bus.reg[(opcode>>16)&15].I & value; \
3857
bus.reg[dest].I = res;
3858
#endif
3859
#ifndef OP_ANDS
3860
#define OP_ANDS OP_AND C_CHECK_PC(C_SETCOND_LOGICAL)
3861
#endif
3862
#ifndef OP_EOR
3863
#define OP_EOR \
3864
u32 res = bus.reg[(opcode>>16)&15].I ^ value; \
3865
bus.reg[dest].I = res;
3866
#endif
3867
#ifndef OP_EORS
3868
#define OP_EORS OP_EOR C_CHECK_PC(C_SETCOND_LOGICAL)
3869
#endif
3870
#ifndef OP_SUB
3871
#define OP_SUB \
3872
u32 lhs = bus.reg[(opcode>>16)&15].I; \
3873
u32 rhs = value; \
3874
u32 res = lhs - rhs; \
3875
bus.reg[dest].I = res;
3876
#endif
3877
#ifndef OP_SUBS
3878
#define OP_SUBS OP_SUB C_CHECK_PC(C_SETCOND_SUB)
3879
#endif
3880
#ifndef OP_RSB
3881
#define OP_RSB \
3882
u32 lhs = bus.reg[(opcode>>16)&15].I; \
3883
u32 rhs = value; \
3884
u32 res = rhs - lhs; \
3885
bus.reg[dest].I = res;
3886
#endif
3887
#ifndef OP_RSBS
3888
#define OP_RSBS OP_RSB C_CHECK_PC(C_SETCOND_SUB)
3889
#endif
3890
#ifndef OP_ADD
3891
#define OP_ADD \
3892
u32 lhs = bus.reg[(opcode>>16)&15].I; \
3893
u32 rhs = value; \
3894
u32 res = lhs + rhs; \
3895
bus.reg[dest].I = res;
3896
#endif
3897
#ifndef OP_ADDS
3898
#define OP_ADDS OP_ADD C_CHECK_PC(C_SETCOND_ADD)
3899
#endif
3900
#ifndef OP_ADC
3901
#define OP_ADC \
3902
u32 lhs = bus.reg[(opcode>>16)&15].I; \
3903
u32 rhs = value; \
3904
u32 res = lhs + rhs + (u32)C_FLAG; \
3905
bus.reg[dest].I = res;
3906
#endif
3907
#ifndef OP_ADCS
3908
#define OP_ADCS OP_ADC C_CHECK_PC(C_SETCOND_ADD)
3909
#endif
3910
#ifndef OP_SBC
3911
#define OP_SBC \
3912
u32 lhs = bus.reg[(opcode>>16)&15].I; \
3913
u32 rhs = value; \
3914
u32 res = lhs - rhs - !((u32)C_FLAG); \
3915
bus.reg[dest].I = res;
3916
#endif
3917
#ifndef OP_SBCS
3918
#define OP_SBCS OP_SBC C_CHECK_PC(C_SETCOND_SUB)
3919
#endif
3920
#ifndef OP_RSC
3921
#define OP_RSC \
3922
u32 lhs = bus.reg[(opcode>>16)&15].I; \
3923
u32 rhs = value; \
3924
u32 res = rhs - lhs - !((u32)C_FLAG); \
3925
bus.reg[dest].I = res;
3926
#endif
3927
#ifndef OP_RSCS
3928
#define OP_RSCS OP_RSC C_CHECK_PC(C_SETCOND_SUB)
3929
#endif
3930
#ifndef OP_TST
3931
#define OP_TST \
3932
u32 res = bus.reg[(opcode >> 16) & 0x0F].I & value; \
3933
C_SETCOND_LOGICAL;
3934
#endif
3935
#ifndef OP_TEQ
3936
#define OP_TEQ \
3937
u32 res = bus.reg[(opcode >> 16) & 0x0F].I ^ value; \
3938
C_SETCOND_LOGICAL;
3939
#endif
3940
#ifndef OP_CMP
3941
#define OP_CMP \
3942
u32 lhs = bus.reg[(opcode>>16)&15].I; \
3943
u32 rhs = value; \
3944
u32 res = lhs - rhs; \
3945
C_SETCOND_SUB;
3946
#endif
3947
#ifndef OP_CMN
3948
#define OP_CMN \
3949
u32 lhs = bus.reg[(opcode>>16)&15].I; \
3950
u32 rhs = value; \
3951
u32 res = lhs + rhs; \
3952
C_SETCOND_ADD;
3953
#endif
3954
#ifndef OP_ORR
3955
#define OP_ORR \
3956
u32 res = bus.reg[(opcode >> 16) & 0x0F].I | value; \
3957
bus.reg[dest].I = res;
3958
#endif
3959
#ifndef OP_ORRS
3960
#define OP_ORRS OP_ORR C_CHECK_PC(C_SETCOND_LOGICAL)
3961
#endif
3962
#ifndef OP_MOV
3963
#define OP_MOV \
3964
u32 res = value; \
3965
bus.reg[dest].I = res;
3966
#endif
3967
#ifndef OP_MOVS
3968
#define OP_MOVS OP_MOV C_CHECK_PC(C_SETCOND_LOGICAL)
3969
#endif
3970
#ifndef OP_BIC
3971
#define OP_BIC \
3972
u32 res = bus.reg[(opcode >> 16) & 0x0F].I & (~value); \
3973
bus.reg[dest].I = res;
3974
#endif
3975
#ifndef OP_BICS
3976
#define OP_BICS OP_BIC C_CHECK_PC(C_SETCOND_LOGICAL)
3977
#endif
3978
#ifndef OP_MVN
3979
#define OP_MVN \
3980
u32 res = ~value; \
3981
bus.reg[dest].I = res;
3982
#endif
3983
#ifndef OP_MVNS
3984
#define OP_MVNS OP_MVN C_CHECK_PC(C_SETCOND_LOGICAL)
3985
#endif
3986
3987
#ifndef SETCOND_NONE
3988
#define SETCOND_NONE /*nothing*/
3989
#endif
3990
#ifndef SETCOND_MUL
3991
#define SETCOND_MUL \
3992
N_FLAG = ((s32)bus.reg[dest].I < 0) ? true : false; \
3993
Z_FLAG = bus.reg[dest].I ? false : true;
3994
#endif
3995
#ifndef SETCOND_MULL
3996
#define SETCOND_MULL \
3997
N_FLAG = (bus.reg[dest].I & 0x80000000) ? true : false;\
3998
Z_FLAG = bus.reg[dest].I || bus.reg[acc].I ? false : true;
3999
#endif
4000
4001
#ifndef ROR_IMM_MSR
4002
#define ROR_IMM_MSR \
4003
u32 v = opcode & 0xff; \
4004
value = ((v << (32 - shift)) | (v >> shift));
4005
#endif
4006
#ifndef ROR_OFFSET
4007
#define ROR_OFFSET \
4008
offset = ((offset << (32 - shift)) | (offset >> shift));
4009
#endif
4010
#ifndef RRX_OFFSET
4011
#define RRX_OFFSET \
4012
offset = ((offset >> 1) | ((int)C_FLAG << 31));
4013
#endif
4014
4015
// ALU ops (except multiply) //////////////////////////////////////////////
4016
4017
// ALU_INIT: init code (ALU_INIT_C or ALU_INIT_NC)
4018
// GETVALUE: load value and shift/rotate (VALUE_XXX)
4019
// OP: ALU operation (OP_XXX)
4020
// MODECHANGE: MODECHANGE_NO or MODECHANGE_YES
4021
// ISREGSHIFT: 1 for insns of the form ...,Rn LSL/etc Rs; 0 otherwise
4022
// ALU_INIT, GETVALUE and OP are concatenated in order.
4023
#define ALU_INSN(ALU_INIT, GETVALUE, OP, MODECHANGE, ISREGSHIFT) \
4024
ALU_INIT GETVALUE OP; \
4025
if ((opcode & 0x0000F000) != 0x0000F000) { \
4026
clockTicks = 1 + ISREGSHIFT \
4027
+ codeTicksAccessSeq32(bus.armNextPC); \
4028
} else { \
4029
MODECHANGE; \
4030
if (armState) { \
4031
bus.reg[15].I &= 0xFFFFFFFC; \
4032
bus.armNextPC = bus.reg[15].I; \
4033
bus.reg[15].I += 4; \
4034
ARM_PREFETCH; \
4035
} else { \
4036
bus.reg[15].I &= 0xFFFFFFFE; \
4037
bus.armNextPC = bus.reg[15].I; \
4038
bus.reg[15].I += 2; \
4039
THUMB_PREFETCH; \
4040
} \
4041
clockTicks = 3 + ISREGSHIFT \
4042
+ codeTicksAccess(bus.armNextPC, BITS_32) \
4043
+ ((codeTicksAccessSeq32(bus.armNextPC)) << 1); \
4044
}
4045
4046
#define MODECHANGE_NO /*nothing*/
4047
#define MODECHANGE_YES if(armMode != (bus.reg[17].I & 0x1f)) CPUSwitchMode(bus.reg[17].I & 0x1f, false, true);
4048
4049
#define DEFINE_ALU_INSN_C(CODE1, CODE2, OP, MODECHANGE) \
4050
void arm##CODE1##0(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSL_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
4051
void arm##CODE1##1(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSL_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
4052
void arm##CODE1##2(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
4053
void arm##CODE1##3(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_LSR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
4054
void arm##CODE1##4(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ASR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
4055
void arm##CODE1##5(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ASR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
4056
void arm##CODE1##6(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ROR_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
4057
void arm##CODE1##7(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_ROR_REG_C, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
4058
void arm##CODE2##0(u32 opcode) { ALU_INSN(ALU_INIT_C, VALUE_IMM_C, OP_##OP, MODECHANGE_##MODECHANGE, 0); }
4059
#define DEFINE_ALU_INSN_NC(CODE1, CODE2, OP, MODECHANGE) \
4060
void arm##CODE1##0(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSL_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
4061
void arm##CODE1##1(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSL_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
4062
void arm##CODE1##2(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
4063
void arm##CODE1##3(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_LSR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
4064
void arm##CODE1##4(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ASR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
4065
void arm##CODE1##5(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ASR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
4066
void arm##CODE1##6(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ROR_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }\
4067
void arm##CODE1##7(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_ROR_REG_NC, OP_##OP, MODECHANGE_##MODECHANGE, 1); }\
4068
void arm##CODE2##0(u32 opcode) { ALU_INSN(ALU_INIT_NC, VALUE_IMM_NC, OP_##OP, MODECHANGE_##MODECHANGE, 0); }
4069
4070
// AND
4071
DEFINE_ALU_INSN_NC(00, 20, AND, NO)
4072
// ANDS
4073
DEFINE_ALU_INSN_C (01, 21, ANDS, YES)
4074
4075
// EOR
4076
DEFINE_ALU_INSN_NC(02, 22, EOR, NO)
4077
// EORS
4078
DEFINE_ALU_INSN_C (03, 23, EORS, YES)
4079
4080
// SUB
4081
DEFINE_ALU_INSN_NC(04, 24, SUB, NO)
4082
// SUBS
4083
DEFINE_ALU_INSN_NC(05, 25, SUBS, YES)
4084
4085
// RSB
4086
DEFINE_ALU_INSN_NC(06, 26, RSB, NO)
4087
// RSBS
4088
DEFINE_ALU_INSN_NC(07, 27, RSBS, YES)
4089
4090
// ADD
4091
DEFINE_ALU_INSN_NC(08, 28, ADD, NO)
4092
// ADDS
4093
DEFINE_ALU_INSN_NC(09, 29, ADDS, YES)
4094
4095
// ADC
4096
DEFINE_ALU_INSN_NC(0A, 2A, ADC, NO)
4097
// ADCS
4098
DEFINE_ALU_INSN_NC(0B, 2B, ADCS, YES)
4099
4100
// SBC
4101
DEFINE_ALU_INSN_NC(0C, 2C, SBC, NO)
4102
// SBCS
4103
DEFINE_ALU_INSN_NC(0D, 2D, SBCS, YES)
4104
4105
// RSC
4106
DEFINE_ALU_INSN_NC(0E, 2E, RSC, NO)
4107
// RSCS
4108
DEFINE_ALU_INSN_NC(0F, 2F, RSCS, YES)
4109
4110
// TST
4111
DEFINE_ALU_INSN_C (11, 31, TST, NO)
4112
4113
// TEQ
4114
DEFINE_ALU_INSN_C (13, 33, TEQ, NO)
4115
4116
// CMP
4117
DEFINE_ALU_INSN_NC(15, 35, CMP, NO)
4118
4119
// CMN
4120
DEFINE_ALU_INSN_NC(17, 37, CMN, NO)
4121
4122
// ORR
4123
DEFINE_ALU_INSN_NC(18, 38, ORR, NO)
4124
// ORRS
4125
DEFINE_ALU_INSN_C (19, 39, ORRS, YES)
4126
4127
// MOV
4128
DEFINE_ALU_INSN_NC(1A, 3A, MOV, NO)
4129
// MOVS
4130
DEFINE_ALU_INSN_C (1B, 3B, MOVS, YES)
4131
4132
// BIC
4133
DEFINE_ALU_INSN_NC(1C, 3C, BIC, NO)
4134
// BICS
4135
DEFINE_ALU_INSN_C (1D, 3D, BICS, YES)
4136
4137
// MVN
4138
DEFINE_ALU_INSN_NC(1E, 3E, MVN, NO)
4139
// MVNS
4140
DEFINE_ALU_INSN_C (1F, 3F, MVNS, YES)
4141
4142
// Multiply instructions //////////////////////////////////////////////////
4143
4144
// OP: OP_MUL, OP_MLA etc.
4145
// SETCOND: SETCOND_NONE, SETCOND_MUL, or SETCOND_MULL
4146
// CYCLES: base cycle count (1, 2, or 3)
4147
#define MUL_INSN(OP, SETCOND, CYCLES) \
4148
int mult = (opcode & 0x0F); \
4149
u32 rs = bus.reg[(opcode >> 8) & 0x0F].I; \
4150
int acc = (opcode >> 12) & 0x0F; /* or destLo */ \
4151
int dest = (opcode >> 16) & 0x0F; /* or destHi */ \
4152
OP; \
4153
SETCOND; \
4154
if ((s32)rs < 0) \
4155
rs = ~rs; \
4156
if ((rs & 0xFFFF0000) == 0) \
4157
clockTicks += 1; \
4158
else if ((rs & 0xFF000000) == 0) \
4159
clockTicks += 2; \
4160
else \
4161
clockTicks += 3; \
4162
if (bus.busPrefetchCount == 0) \
4163
bus.busPrefetchCount = ((bus.busPrefetchCount+1)<<clockTicks) - 1; \
4164
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
4165
4166
#define OP_MUL \
4167
bus.reg[dest].I = bus.reg[mult].I * rs;
4168
#define OP_MLA \
4169
bus.reg[dest].I = bus.reg[mult].I * rs + bus.reg[acc].I;
4170
#define OP_MULL(SIGN) \
4171
SIGN##64 res = (SIGN##64)(SIGN##32)bus.reg[mult].I \
4172
* (SIGN##64)(SIGN##32)rs; \
4173
bus.reg[acc].I = (u32)res; \
4174
bus.reg[dest].I = (u32)(res >> 32);
4175
#define OP_MLAL(SIGN) \
4176
SIGN##64 res = ((SIGN##64)bus.reg[dest].I<<32 | bus.reg[acc].I)\
4177
+ ((SIGN##64)(SIGN##32)bus.reg[mult].I \
4178
* (SIGN##64)(SIGN##32)rs); \
4179
bus.reg[acc].I = (u32)res; \
4180
bus.reg[dest].I = (u32)(res >> 32);
4181
#define OP_UMULL OP_MULL(u)
4182
#define OP_UMLAL OP_MLAL(u)
4183
#define OP_SMULL OP_MULL(s)
4184
#define OP_SMLAL OP_MLAL(s)
4185
4186
// MUL Rd, Rm, Rs
4187
void arm009(u32 opcode) { MUL_INSN(OP_MUL, SETCOND_NONE, 1); }
4188
// MULS Rd, Rm, Rs
4189
void arm019(u32 opcode) { MUL_INSN(OP_MUL, SETCOND_MUL, 1); }
4190
4191
// MLA Rd, Rm, Rs, Rn
4192
void arm029(u32 opcode) { MUL_INSN(OP_MLA, SETCOND_NONE, 2); }
4193
// MLAS Rd, Rm, Rs, Rn
4194
void arm039(u32 opcode) { MUL_INSN(OP_MLA, SETCOND_MUL, 2); }
4195
4196
// UMULL RdLo, RdHi, Rn, Rs
4197
void arm089(u32 opcode) { MUL_INSN(OP_UMULL, SETCOND_NONE, 2); }
4198
// UMULLS RdLo, RdHi, Rn, Rs
4199
void arm099(u32 opcode) { MUL_INSN(OP_UMULL, SETCOND_MULL, 2); }
4200
4201
// UMLAL RdLo, RdHi, Rn, Rs
4202
void arm0A9(u32 opcode) { MUL_INSN(OP_UMLAL, SETCOND_NONE, 3); }
4203
// UMLALS RdLo, RdHi, Rn, Rs
4204
void arm0B9(u32 opcode) { MUL_INSN(OP_UMLAL, SETCOND_MULL, 3); }
4205
4206
// SMULL RdLo, RdHi, Rm, Rs
4207
void arm0C9(u32 opcode) { MUL_INSN(OP_SMULL, SETCOND_NONE, 2); }
4208
// SMULLS RdLo, RdHi, Rm, Rs
4209
void arm0D9(u32 opcode) { MUL_INSN(OP_SMULL, SETCOND_MULL, 2); }
4210
4211
// SMLAL RdLo, RdHi, Rm, Rs
4212
void arm0E9(u32 opcode) { MUL_INSN(OP_SMLAL, SETCOND_NONE, 3); }
4213
// SMLALS RdLo, RdHi, Rm, Rs
4214
void arm0F9(u32 opcode) { MUL_INSN(OP_SMLAL, SETCOND_MULL, 3); }
4215
4216
// Misc instructions //////////////////////////////////////////////////////
4217
4218
// SWP Rd, Rm, [Rn]
4219
void arm109(u32 opcode)
4220
{
4221
u32 address = bus.reg[(opcode >> 16) & 15].I;
4222
u32 temp = CPUReadMemory(address);
4223
CPUWriteMemory(address, bus.reg[opcode&15].I);
4224
bus.reg[(opcode >> 12) & 15].I = temp;
4225
int dataticks_value = DATATICKS_ACCESS_32BIT(address);
4226
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
4227
clockTicks = 4 + (dataticks_value << 1) + codeTicksAccess(bus.armNextPC, BITS_32);
4228
}
4229
4230
// SWPB Rd, Rm, [Rn]
4231
void arm149(u32 opcode)
4232
{
4233
u32 address = bus.reg[(opcode >> 16) & 15].I;
4234
u32 temp = CPUReadByte(address);
4235
CPUWriteByte(address, bus.reg[opcode&15].B.B0);
4236
bus.reg[(opcode>>12)&15].I = temp;
4237
u32 dataticks_value = DATATICKS_ACCESS_32BIT(address);
4238
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
4239
clockTicks = 4 + (dataticks_value << 1) + codeTicksAccess(bus.armNextPC, BITS_32);
4240
}
4241
4242
// MRS Rd, CPSR
4243
void arm100(u32 opcode)
4244
{
4245
if ((opcode & 0x0FFF0FFF) == 0x010F0000)
4246
{
4247
CPU_UPDATE_CPSR();
4248
bus.reg[(opcode >> 12) & 0x0F].I = bus.reg[16].I;
4249
}
4250
else
4251
armUnknownInsn(opcode);
4252
}
4253
4254
// MRS Rd, SPSR
4255
void arm140(u32 opcode)
4256
{
4257
if ((opcode & 0x0FFF0FFF) == 0x014F0000)
4258
bus.reg[(opcode >> 12) & 0x0F].I = bus.reg[17].I;
4259
else
4260
armUnknownInsn(opcode);
4261
}
4262
4263
// MSR CPSR_fields, Rm
4264
void arm120(u32 opcode)
4265
{
4266
if ((opcode & 0x0FF0FFF0) == 0x0120F000)
4267
{
4268
CPU_UPDATE_CPSR();
4269
u32 value = bus.reg[opcode & 15].I;
4270
u32 newValue = bus.reg[16].I;
4271
if (armMode > 0x10) {
4272
if (opcode & 0x00010000)
4273
newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
4274
if (opcode & 0x00020000)
4275
newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
4276
if (opcode & 0x00040000)
4277
newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
4278
}
4279
if (opcode & 0x00080000)
4280
newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
4281
newValue |= 0x10;
4282
if(armMode != (newValue & 0x1F))
4283
CPUSwitchMode(newValue & 0x1F, false, true);
4284
bus.reg[16].I = newValue;
4285
CPUUpdateFlags(1);
4286
if (!armState) { // this should not be allowed, but it seems to work
4287
THUMB_PREFETCH;
4288
bus.reg[15].I = bus.armNextPC + 2;
4289
}
4290
}
4291
else
4292
armUnknownInsn(opcode);
4293
}
4294
4295
// MSR SPSR_fields, Rm
4296
void arm160(u32 opcode)
4297
{
4298
if ((opcode & 0x0FF0FFF0) == 0x0160F000)
4299
{
4300
u32 value = bus.reg[opcode & 15].I;
4301
if (armMode > 0x10 && armMode < 0x1F)
4302
{
4303
if (opcode & 0x00010000)
4304
bus.reg[17].I = (bus.reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
4305
if (opcode & 0x00020000)
4306
bus.reg[17].I = (bus.reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
4307
if (opcode & 0x00040000)
4308
bus.reg[17].I = (bus.reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
4309
if (opcode & 0x00080000)
4310
bus.reg[17].I = (bus.reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
4311
}
4312
}
4313
else
4314
armUnknownInsn(opcode);
4315
}
4316
4317
// MSR CPSR_fields, #
4318
void arm320(u32 opcode)
4319
{
4320
if ((opcode & 0x0FF0F000) == 0x0320F000)
4321
{
4322
CPU_UPDATE_CPSR();
4323
u32 value = opcode & 0xFF;
4324
int shift = (opcode & 0xF00) >> 7;
4325
if (shift) {
4326
ROR_IMM_MSR;
4327
}
4328
u32 newValue = bus.reg[16].I;
4329
if (armMode > 0x10) {
4330
if (opcode & 0x00010000)
4331
newValue = (newValue & 0xFFFFFF00) | (value & 0x000000FF);
4332
if (opcode & 0x00020000)
4333
newValue = (newValue & 0xFFFF00FF) | (value & 0x0000FF00);
4334
if (opcode & 0x00040000)
4335
newValue = (newValue & 0xFF00FFFF) | (value & 0x00FF0000);
4336
}
4337
if (opcode & 0x00080000)
4338
newValue = (newValue & 0x00FFFFFF) | (value & 0xFF000000);
4339
4340
newValue |= 0x10;
4341
4342
if(armMode != (newValue & 0x1F))
4343
CPUSwitchMode(newValue & 0x1F, false, true);
4344
bus.reg[16].I = newValue;
4345
CPUUpdateFlags(1);
4346
if (!armState) { // this should not be allowed, but it seems to work
4347
THUMB_PREFETCH;
4348
bus.reg[15].I = bus.armNextPC + 2;
4349
}
4350
}
4351
else
4352
armUnknownInsn(opcode);
4353
}
4354
4355
// MSR SPSR_fields, #
4356
void arm360(u32 opcode)
4357
{
4358
if ((opcode & 0x0FF0F000) == 0x0360F000) {
4359
if (armMode > 0x10 && armMode < 0x1F) {
4360
u32 value = opcode & 0xFF;
4361
int shift = (opcode & 0xF00) >> 7;
4362
if (shift) {
4363
ROR_IMM_MSR;
4364
}
4365
if (opcode & 0x00010000)
4366
bus.reg[17].I = (bus.reg[17].I & 0xFFFFFF00) | (value & 0x000000FF);
4367
if (opcode & 0x00020000)
4368
bus.reg[17].I = (bus.reg[17].I & 0xFFFF00FF) | (value & 0x0000FF00);
4369
if (opcode & 0x00040000)
4370
bus.reg[17].I = (bus.reg[17].I & 0xFF00FFFF) | (value & 0x00FF0000);
4371
if (opcode & 0x00080000)
4372
bus.reg[17].I = (bus.reg[17].I & 0x00FFFFFF) | (value & 0xFF000000);
4373
}
4374
}
4375
else
4376
armUnknownInsn(opcode);
4377
}
4378
4379
// BX Rm
4380
void arm121(u32 opcode)
4381
{
4382
if ((opcode & 0x0FFFFFF0) == 0x012FFF10) {
4383
int base = opcode & 0x0F;
4384
bus.busPrefetchCount = 0;
4385
armState = bus.reg[base].I & 1 ? false : true;
4386
if (armState) {
4387
bus.reg[15].I = bus.reg[base].I & 0xFFFFFFFC;
4388
bus.armNextPC = bus.reg[15].I;
4389
bus.reg[15].I += 4;
4390
ARM_PREFETCH;
4391
clockTicks = 3 + (codeTicksAccessSeq32(bus.armNextPC)<<1)
4392
+ codeTicksAccess(bus.armNextPC, BITS_32);
4393
} else {
4394
bus.reg[15].I = bus.reg[base].I & 0xFFFFFFFE;
4395
bus.armNextPC = bus.reg[15].I;
4396
bus.reg[15].I += 2;
4397
THUMB_PREFETCH;
4398
clockTicks = 3 + (codeTicksAccessSeq16(bus.armNextPC)<<1)
4399
+ codeTicksAccess(bus.armNextPC, BITS_16);
4400
}
4401
}
4402
else
4403
armUnknownInsn(opcode);
4404
}
4405
4406
// Load/store /////////////////////////////////////////////////////////////
4407
4408
#define OFFSET_IMM \
4409
int offset = opcode & 0xFFF;
4410
#define OFFSET_IMM8 \
4411
int offset = ((opcode & 0x0F) | ((opcode>>4) & 0xF0));
4412
#define OFFSET_REG \
4413
int offset = bus.reg[opcode & 15].I;
4414
#define OFFSET_LSL \
4415
int offset = bus.reg[opcode & 15].I << ((opcode>>7) & 31);
4416
#define OFFSET_LSR \
4417
int shift = (opcode >> 7) & 31; \
4418
int offset = shift ? bus.reg[opcode & 15].I >> shift : 0;
4419
#define OFFSET_ASR \
4420
int shift = (opcode >> 7) & 31; \
4421
int offset; \
4422
if (shift) \
4423
offset = (int)((s32)bus.reg[opcode & 15].I >> shift);\
4424
else if (bus.reg[opcode & 15].I & 0x80000000) \
4425
offset = 0xFFFFFFFF; \
4426
else \
4427
offset = 0;
4428
#define OFFSET_ROR \
4429
int shift = (opcode >> 7) & 31; \
4430
u32 offset = bus.reg[opcode & 15].I; \
4431
if (shift) { \
4432
ROR_OFFSET; \
4433
} else { \
4434
RRX_OFFSET; \
4435
}
4436
4437
#define ADDRESS_POST (bus.reg[base].I)
4438
#define ADDRESS_PREDEC (bus.reg[base].I - offset)
4439
#define ADDRESS_PREINC (bus.reg[base].I + offset)
4440
4441
#define OP_STR CPUWriteMemory(address, bus.reg[dest].I)
4442
#define OP_STRH CPUWriteHalfWord(address, bus.reg[dest].W.W0)
4443
#define OP_STRB CPUWriteByte(address, bus.reg[dest].B.B0)
4444
#define OP_LDR bus.reg[dest].I = CPUReadMemory(address)
4445
#define OP_LDRH bus.reg[dest].I = CPUReadHalfWord(address)
4446
#define OP_LDRB bus.reg[dest].I = CPUReadByte(address)
4447
#define OP_LDRSH bus.reg[dest].I = (s16)CPUReadHalfWordSigned(address)
4448
#define OP_LDRSB bus.reg[dest].I = (s8)CPUReadByte(address)
4449
4450
#define WRITEBACK_NONE /*nothing*/
4451
#define WRITEBACK_PRE bus.reg[base].I = address
4452
#define WRITEBACK_POSTDEC bus.reg[base].I = address - offset
4453
#define WRITEBACK_POSTINC bus.reg[base].I = address + offset
4454
4455
#define LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS) \
4456
if (bus.busPrefetchCount == 0) \
4457
bus.busPrefetch = bus.busPrefetchEnable; \
4458
int dest = (opcode >> 12) & 15; \
4459
int base = (opcode >> 16) & 15; \
4460
CALC_OFFSET; \
4461
u32 address = CALC_ADDRESS;
4462
4463
#define STR(CALC_OFFSET, CALC_ADDRESS, STORE_DATA, WRITEBACK1, WRITEBACK2, SIZE) \
4464
LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS); \
4465
WRITEBACK1; \
4466
STORE_DATA; \
4467
WRITEBACK2; \
4468
int dataticks_val; \
4469
if(SIZE == 32) \
4470
dataticks_val = DATATICKS_ACCESS_32BIT(address); \
4471
else \
4472
dataticks_val = DATATICKS_ACCESS_16BIT(address); \
4473
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_val); \
4474
clockTicks = 2 + dataticks_val + codeTicksAccess(bus.armNextPC, BITS_32);
4475
4476
#define LDR(CALC_OFFSET, CALC_ADDRESS, LOAD_DATA, WRITEBACK, SIZE) \
4477
LDRSTR_INIT(CALC_OFFSET, CALC_ADDRESS); \
4478
LOAD_DATA; \
4479
if (dest != base) \
4480
{ \
4481
WRITEBACK; \
4482
} \
4483
clockTicks = 0; \
4484
int dataticks_value; \
4485
if (dest == 15) { \
4486
bus.reg[15].I &= 0xFFFFFFFC; \
4487
bus.armNextPC = bus.reg[15].I; \
4488
bus.reg[15].I += 4; \
4489
ARM_PREFETCH; \
4490
dataticks_value = DATATICKS_ACCESS_32BIT_SEQ(address); \
4491
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
4492
clockTicks += 2 + (dataticks_value << 1);\
4493
} \
4494
if(SIZE == 32) \
4495
dataticks_value = DATATICKS_ACCESS_32BIT(address); \
4496
else \
4497
dataticks_value = DATATICKS_ACCESS_16BIT(address); \
4498
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
4499
clockTicks += 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_32);
4500
#define STR_POSTDEC(CALC_OFFSET, STORE_DATA, SIZE) \
4501
STR(CALC_OFFSET, ADDRESS_POST, STORE_DATA, WRITEBACK_NONE, WRITEBACK_POSTDEC, SIZE)
4502
#define STR_POSTINC(CALC_OFFSET, STORE_DATA, SIZE) \
4503
STR(CALC_OFFSET, ADDRESS_POST, STORE_DATA, WRITEBACK_NONE, WRITEBACK_POSTINC, SIZE)
4504
#define STR_PREDEC(CALC_OFFSET, STORE_DATA, SIZE) \
4505
STR(CALC_OFFSET, ADDRESS_PREDEC, STORE_DATA, WRITEBACK_NONE, WRITEBACK_NONE, SIZE)
4506
#define STR_PREDEC_WB(CALC_OFFSET, STORE_DATA, SIZE) \
4507
STR(CALC_OFFSET, ADDRESS_PREDEC, STORE_DATA, WRITEBACK_PRE, WRITEBACK_NONE, SIZE)
4508
#define STR_PREINC(CALC_OFFSET, STORE_DATA, SIZE) \
4509
STR(CALC_OFFSET, ADDRESS_PREINC, STORE_DATA, WRITEBACK_NONE, WRITEBACK_NONE, SIZE)
4510
#define STR_PREINC_WB(CALC_OFFSET, STORE_DATA, SIZE) \
4511
STR(CALC_OFFSET, ADDRESS_PREINC, STORE_DATA, WRITEBACK_PRE, WRITEBACK_NONE, SIZE)
4512
#define LDR_POSTDEC(CALC_OFFSET, LOAD_DATA, SIZE) \
4513
LDR(CALC_OFFSET, ADDRESS_POST, LOAD_DATA, WRITEBACK_POSTDEC, SIZE)
4514
#define LDR_POSTINC(CALC_OFFSET, LOAD_DATA, SIZE) \
4515
LDR(CALC_OFFSET, ADDRESS_POST, LOAD_DATA, WRITEBACK_POSTINC, SIZE)
4516
#define LDR_PREDEC(CALC_OFFSET, LOAD_DATA, SIZE) \
4517
LDR(CALC_OFFSET, ADDRESS_PREDEC, LOAD_DATA, WRITEBACK_NONE, SIZE)
4518
#define LDR_PREDEC_WB(CALC_OFFSET, LOAD_DATA, SIZE) \
4519
LDR(CALC_OFFSET, ADDRESS_PREDEC, LOAD_DATA, WRITEBACK_PRE, SIZE)
4520
#define LDR_PREINC(CALC_OFFSET, LOAD_DATA, SIZE) \
4521
LDR(CALC_OFFSET, ADDRESS_PREINC, LOAD_DATA, WRITEBACK_NONE, SIZE)
4522
#define LDR_PREINC_WB(CALC_OFFSET, LOAD_DATA, SIZE) \
4523
LDR(CALC_OFFSET, ADDRESS_PREINC, LOAD_DATA, WRITEBACK_PRE, SIZE)
4524
4525
// STRH Rd, [Rn], -Rm
4526
void arm00B(u32 opcode) { STR_POSTDEC(OFFSET_REG, OP_STRH, 16); }
4527
// STRH Rd, [Rn], #-offset
4528
void arm04B(u32 opcode) { STR_POSTDEC(OFFSET_IMM8, OP_STRH, 16); }
4529
// STRH Rd, [Rn], Rm
4530
void arm08B(u32 opcode) { STR_POSTINC(OFFSET_REG, OP_STRH, 16); }
4531
// STRH Rd, [Rn], #offset
4532
void arm0CB(u32 opcode) { STR_POSTINC(OFFSET_IMM8, OP_STRH, 16); }
4533
// STRH Rd, [Rn, -Rm]
4534
void arm10B(u32 opcode) { STR_PREDEC(OFFSET_REG, OP_STRH, 16); }
4535
// STRH Rd, [Rn, -Rm]!
4536
void arm12B(u32 opcode) { STR_PREDEC_WB(OFFSET_REG, OP_STRH, 16); }
4537
// STRH Rd, [Rn, -#offset]
4538
void arm14B(u32 opcode) { STR_PREDEC(OFFSET_IMM8, OP_STRH, 16); }
4539
// STRH Rd, [Rn, -#offset]!
4540
void arm16B(u32 opcode) { STR_PREDEC_WB(OFFSET_IMM8, OP_STRH, 16); }
4541
// STRH Rd, [Rn, Rm]
4542
void arm18B(u32 opcode) { STR_PREINC(OFFSET_REG, OP_STRH, 16); }
4543
// STRH Rd, [Rn, Rm]!
4544
void arm1AB(u32 opcode) { STR_PREINC_WB(OFFSET_REG, OP_STRH, 16); }
4545
// STRH Rd, [Rn, #offset]
4546
void arm1CB(u32 opcode) { STR_PREINC(OFFSET_IMM8, OP_STRH, 16); }
4547
// STRH Rd, [Rn, #offset]!
4548
void arm1EB(u32 opcode) { STR_PREINC_WB(OFFSET_IMM8, OP_STRH, 16); }
4549
4550
// LDRH Rd, [Rn], -Rm
4551
void arm01B(u32 opcode) { LDR_POSTDEC(OFFSET_REG, OP_LDRH, 16); }
4552
// LDRH Rd, [Rn], #-offset
4553
void arm05B(u32 opcode) { LDR_POSTDEC(OFFSET_IMM8, OP_LDRH, 16); }
4554
// LDRH Rd, [Rn], Rm
4555
void arm09B(u32 opcode) { LDR_POSTINC(OFFSET_REG, OP_LDRH, 16); }
4556
// LDRH Rd, [Rn], #offset
4557
void arm0DB(u32 opcode) { LDR_POSTINC(OFFSET_IMM8, OP_LDRH, 16); }
4558
// LDRH Rd, [Rn, -Rm]
4559
void arm11B(u32 opcode) { LDR_PREDEC(OFFSET_REG, OP_LDRH, 16); }
4560
// LDRH Rd, [Rn, -Rm]!
4561
void arm13B(u32 opcode) { LDR_PREDEC_WB(OFFSET_REG, OP_LDRH, 16); }
4562
// LDRH Rd, [Rn, -#offset]
4563
void arm15B(u32 opcode) { LDR_PREDEC(OFFSET_IMM8, OP_LDRH, 16); }
4564
// LDRH Rd, [Rn, -#offset]!
4565
void arm17B(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM8, OP_LDRH, 16); }
4566
// LDRH Rd, [Rn, Rm]
4567
void arm19B(u32 opcode) { LDR_PREINC(OFFSET_REG, OP_LDRH, 16); }
4568
// LDRH Rd, [Rn, Rm]!
4569
void arm1BB(u32 opcode) { LDR_PREINC_WB(OFFSET_REG, OP_LDRH, 16); }
4570
// LDRH Rd, [Rn, #offset]
4571
void arm1DB(u32 opcode) { LDR_PREINC(OFFSET_IMM8, OP_LDRH, 16); }
4572
// LDRH Rd, [Rn, #offset]!
4573
void arm1FB(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM8, OP_LDRH, 16); }
4574
4575
// LDRSB Rd, [Rn], -Rm
4576
void arm01D(u32 opcode) { LDR_POSTDEC(OFFSET_REG, OP_LDRSB, 16); }
4577
// LDRSB Rd, [Rn], #-offset
4578
void arm05D(u32 opcode) { LDR_POSTDEC(OFFSET_IMM8, OP_LDRSB, 16); }
4579
// LDRSB Rd, [Rn], Rm
4580
void arm09D(u32 opcode) { LDR_POSTINC(OFFSET_REG, OP_LDRSB, 16); }
4581
// LDRSB Rd, [Rn], #offset
4582
void arm0DD(u32 opcode) { LDR_POSTINC(OFFSET_IMM8, OP_LDRSB, 16); }
4583
// LDRSB Rd, [Rn, -Rm]
4584
void arm11D(u32 opcode) { LDR_PREDEC(OFFSET_REG, OP_LDRSB, 16); }
4585
// LDRSB Rd, [Rn, -Rm]!
4586
void arm13D(u32 opcode) { LDR_PREDEC_WB(OFFSET_REG, OP_LDRSB, 16); }
4587
// LDRSB Rd, [Rn, -#offset]
4588
void arm15D(u32 opcode) { LDR_PREDEC(OFFSET_IMM8, OP_LDRSB, 16); }
4589
// LDRSB Rd, [Rn, -#offset]!
4590
void arm17D(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM8, OP_LDRSB, 16); }
4591
// LDRSB Rd, [Rn, Rm]
4592
void arm19D(u32 opcode) { LDR_PREINC(OFFSET_REG, OP_LDRSB, 16); }
4593
// LDRSB Rd, [Rn, Rm]!
4594
void arm1BD(u32 opcode) { LDR_PREINC_WB(OFFSET_REG, OP_LDRSB, 16); }
4595
// LDRSB Rd, [Rn, #offset]
4596
void arm1DD(u32 opcode) { LDR_PREINC(OFFSET_IMM8, OP_LDRSB, 16); }
4597
// LDRSB Rd, [Rn, #offset]!
4598
void arm1FD(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM8, OP_LDRSB, 16); }
4599
4600
// LDRSH Rd, [Rn], -Rm
4601
void arm01F(u32 opcode) { LDR_POSTDEC(OFFSET_REG, OP_LDRSH, 16); }
4602
// LDRSH Rd, [Rn], #-offset
4603
void arm05F(u32 opcode) { LDR_POSTDEC(OFFSET_IMM8, OP_LDRSH, 16); }
4604
// LDRSH Rd, [Rn], Rm
4605
void arm09F(u32 opcode) { LDR_POSTINC(OFFSET_REG, OP_LDRSH, 16); }
4606
// LDRSH Rd, [Rn], #offset
4607
void arm0DF(u32 opcode) { LDR_POSTINC(OFFSET_IMM8, OP_LDRSH, 16); }
4608
// LDRSH Rd, [Rn, -Rm]
4609
void arm11F(u32 opcode) { LDR_PREDEC(OFFSET_REG, OP_LDRSH, 16); }
4610
// LDRSH Rd, [Rn, -Rm]!
4611
void arm13F(u32 opcode) { LDR_PREDEC_WB(OFFSET_REG, OP_LDRSH, 16); }
4612
// LDRSH Rd, [Rn, -#offset]
4613
void arm15F(u32 opcode) { LDR_PREDEC(OFFSET_IMM8, OP_LDRSH, 16); }
4614
// LDRSH Rd, [Rn, -#offset]!
4615
void arm17F(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM8, OP_LDRSH, 16); }
4616
// LDRSH Rd, [Rn, Rm]
4617
void arm19F(u32 opcode) { LDR_PREINC(OFFSET_REG, OP_LDRSH, 16); }
4618
// LDRSH Rd, [Rn, Rm]!
4619
void arm1BF(u32 opcode) { LDR_PREINC_WB(OFFSET_REG, OP_LDRSH, 16); }
4620
// LDRSH Rd, [Rn, #offset]
4621
void arm1DF(u32 opcode) { LDR_PREINC(OFFSET_IMM8, OP_LDRSH, 16); }
4622
// LDRSH Rd, [Rn, #offset]!
4623
void arm1FF(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM8, OP_LDRSH, 16); }
4624
4625
// STR[T] Rd, [Rn], -#
4626
// Note: STR and STRT do the same thing on the GBA (likewise for LDR/LDRT etc)
4627
void arm400(u32 opcode) { STR_POSTDEC(OFFSET_IMM, OP_STR, 32); }
4628
// LDR[T] Rd, [Rn], -#
4629
void arm410(u32 opcode) { LDR_POSTDEC(OFFSET_IMM, OP_LDR, 32); }
4630
// STRB[T] Rd, [Rn], -#
4631
void arm440(u32 opcode) { STR_POSTDEC(OFFSET_IMM, OP_STRB, 16); }
4632
// LDRB[T] Rd, [Rn], -#
4633
void arm450(u32 opcode) { LDR_POSTDEC(OFFSET_IMM, OP_LDRB, 16); }
4634
// STR[T] Rd, [Rn], #
4635
void arm480(u32 opcode) { STR_POSTINC(OFFSET_IMM, OP_STR, 32); }
4636
// LDR Rd, [Rn], #
4637
void arm490(u32 opcode) { LDR_POSTINC(OFFSET_IMM, OP_LDR, 32); }
4638
// STRB[T] Rd, [Rn], #
4639
void arm4C0(u32 opcode) { STR_POSTINC(OFFSET_IMM, OP_STRB, 16); }
4640
// LDRB[T] Rd, [Rn], #
4641
void arm4D0(u32 opcode) { LDR_POSTINC(OFFSET_IMM, OP_LDRB, 16); }
4642
// STR Rd, [Rn, -#]
4643
void arm500(u32 opcode) { STR_PREDEC(OFFSET_IMM, OP_STR, 32); }
4644
// LDR Rd, [Rn, -#]
4645
void arm510(u32 opcode) { LDR_PREDEC(OFFSET_IMM, OP_LDR, 32); }
4646
// STR Rd, [Rn, -#]!
4647
void arm520(u32 opcode) { STR_PREDEC_WB(OFFSET_IMM, OP_STR, 32); }
4648
// LDR Rd, [Rn, -#]!
4649
void arm530(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM, OP_LDR, 32); }
4650
// STRB Rd, [Rn, -#]
4651
void arm540(u32 opcode) { STR_PREDEC(OFFSET_IMM, OP_STRB, 16); }
4652
// LDRB Rd, [Rn, -#]
4653
void arm550(u32 opcode) { LDR_PREDEC(OFFSET_IMM, OP_LDRB, 16); }
4654
// STRB Rd, [Rn, -#]!
4655
void arm560(u32 opcode) { STR_PREDEC_WB(OFFSET_IMM, OP_STRB, 16); }
4656
// LDRB Rd, [Rn, -#]!
4657
void arm570(u32 opcode) { LDR_PREDEC_WB(OFFSET_IMM, OP_LDRB, 16); }
4658
// STR Rd, [Rn, #]
4659
void arm580(u32 opcode) { STR_PREINC(OFFSET_IMM, OP_STR, 32); }
4660
// LDR Rd, [Rn, #]
4661
void arm590(u32 opcode) { LDR_PREINC(OFFSET_IMM, OP_LDR, 32); }
4662
// STR Rd, [Rn, #]!
4663
void arm5A0(u32 opcode) { STR_PREINC_WB(OFFSET_IMM, OP_STR, 32); }
4664
// LDR Rd, [Rn, #]!
4665
void arm5B0(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM, OP_LDR, 32); }
4666
// STRB Rd, [Rn, #]
4667
void arm5C0(u32 opcode) { STR_PREINC(OFFSET_IMM, OP_STRB, 16); }
4668
// LDRB Rd, [Rn, #]
4669
void arm5D0(u32 opcode) { LDR_PREINC(OFFSET_IMM, OP_LDRB, 16); }
4670
// STRB Rd, [Rn, #]!
4671
void arm5E0(u32 opcode) { STR_PREINC_WB(OFFSET_IMM, OP_STRB, 16); }
4672
// LDRB Rd, [Rn, #]!
4673
void arm5F0(u32 opcode) { LDR_PREINC_WB(OFFSET_IMM, OP_LDRB, 16); }
4674
4675
// STR[T] Rd, [Rn], -Rm, LSL #
4676
void arm600(u32 opcode) { STR_POSTDEC(OFFSET_LSL, OP_STR, 32); }
4677
// STR[T] Rd, [Rn], -Rm, LSR #
4678
void arm602(u32 opcode) { STR_POSTDEC(OFFSET_LSR, OP_STR, 32); }
4679
// STR[T] Rd, [Rn], -Rm, ASR #
4680
void arm604(u32 opcode) { STR_POSTDEC(OFFSET_ASR, OP_STR, 32); }
4681
// STR[T] Rd, [Rn], -Rm, ROR #
4682
void arm606(u32 opcode) { STR_POSTDEC(OFFSET_ROR, OP_STR, 32); }
4683
// LDR[T] Rd, [Rn], -Rm, LSL #
4684
void arm610(u32 opcode) { LDR_POSTDEC(OFFSET_LSL, OP_LDR, 32); }
4685
// LDR[T] Rd, [Rn], -Rm, LSR #
4686
void arm612(u32 opcode) { LDR_POSTDEC(OFFSET_LSR, OP_LDR, 32); }
4687
// LDR[T] Rd, [Rn], -Rm, ASR #
4688
void arm614(u32 opcode) { LDR_POSTDEC(OFFSET_ASR, OP_LDR, 32); }
4689
// LDR[T] Rd, [Rn], -Rm, ROR #
4690
void arm616(u32 opcode) { LDR_POSTDEC(OFFSET_ROR, OP_LDR, 32); }
4691
// STRB[T] Rd, [Rn], -Rm, LSL #
4692
void arm640(u32 opcode) { STR_POSTDEC(OFFSET_LSL, OP_STRB, 16); }
4693
// STRB[T] Rd, [Rn], -Rm, LSR #
4694
void arm642(u32 opcode) { STR_POSTDEC(OFFSET_LSR, OP_STRB, 16); }
4695
// STRB[T] Rd, [Rn], -Rm, ASR #
4696
void arm644(u32 opcode) { STR_POSTDEC(OFFSET_ASR, OP_STRB, 16); }
4697
// STRB[T] Rd, [Rn], -Rm, ROR #
4698
void arm646(u32 opcode) { STR_POSTDEC(OFFSET_ROR, OP_STRB, 16); }
4699
// LDRB[T] Rd, [Rn], -Rm, LSL #
4700
void arm650(u32 opcode) { LDR_POSTDEC(OFFSET_LSL, OP_LDRB, 16); }
4701
// LDRB[T] Rd, [Rn], -Rm, LSR #
4702
void arm652(u32 opcode) { LDR_POSTDEC(OFFSET_LSR, OP_LDRB, 16); }
4703
// LDRB[T] Rd, [Rn], -Rm, ASR #
4704
void arm654(u32 opcode) { LDR_POSTDEC(OFFSET_ASR, OP_LDRB, 16); }
4705
// LDRB Rd, [Rn], -Rm, ROR #
4706
void arm656(u32 opcode) { LDR_POSTDEC(OFFSET_ROR, OP_LDRB, 16); }
4707
// STR[T] Rd, [Rn], Rm, LSL #
4708
void arm680(u32 opcode) { STR_POSTINC(OFFSET_LSL, OP_STR, 32); }
4709
// STR[T] Rd, [Rn], Rm, LSR #
4710
void arm682(u32 opcode) { STR_POSTINC(OFFSET_LSR, OP_STR, 32); }
4711
// STR[T] Rd, [Rn], Rm, ASR #
4712
void arm684(u32 opcode) { STR_POSTINC(OFFSET_ASR, OP_STR, 32); }
4713
// STR[T] Rd, [Rn], Rm, ROR #
4714
void arm686(u32 opcode) { STR_POSTINC(OFFSET_ROR, OP_STR, 32); }
4715
// LDR[T] Rd, [Rn], Rm, LSL #
4716
void arm690(u32 opcode) { LDR_POSTINC(OFFSET_LSL, OP_LDR, 32); }
4717
// LDR[T] Rd, [Rn], Rm, LSR #
4718
void arm692(u32 opcode) { LDR_POSTINC(OFFSET_LSR, OP_LDR, 32); }
4719
// LDR[T] Rd, [Rn], Rm, ASR #
4720
void arm694(u32 opcode) { LDR_POSTINC(OFFSET_ASR, OP_LDR, 32); }
4721
// LDR[T] Rd, [Rn], Rm, ROR #
4722
void arm696(u32 opcode) { LDR_POSTINC(OFFSET_ROR, OP_LDR, 32); }
4723
// STRB[T] Rd, [Rn], Rm, LSL #
4724
void arm6C0(u32 opcode) { STR_POSTINC(OFFSET_LSL, OP_STRB, 16); }
4725
// STRB[T] Rd, [Rn], Rm, LSR #
4726
void arm6C2(u32 opcode) { STR_POSTINC(OFFSET_LSR, OP_STRB, 16); }
4727
// STRB[T] Rd, [Rn], Rm, ASR #
4728
void arm6C4(u32 opcode) { STR_POSTINC(OFFSET_ASR, OP_STRB, 16); }
4729
// STRB[T] Rd, [Rn], Rm, ROR #
4730
void arm6C6(u32 opcode) { STR_POSTINC(OFFSET_ROR, OP_STRB, 16); }
4731
// LDRB[T] Rd, [Rn], Rm, LSL #
4732
void arm6D0(u32 opcode) { LDR_POSTINC(OFFSET_LSL, OP_LDRB, 16); }
4733
// LDRB[T] Rd, [Rn], Rm, LSR #
4734
void arm6D2(u32 opcode) { LDR_POSTINC(OFFSET_LSR, OP_LDRB, 16); }
4735
// LDRB[T] Rd, [Rn], Rm, ASR #
4736
void arm6D4(u32 opcode) { LDR_POSTINC(OFFSET_ASR, OP_LDRB, 16); }
4737
// LDRB[T] Rd, [Rn], Rm, ROR #
4738
void arm6D6(u32 opcode) { LDR_POSTINC(OFFSET_ROR, OP_LDRB, 16); }
4739
// STR Rd, [Rn, -Rm, LSL #]
4740
void arm700(u32 opcode) { STR_PREDEC(OFFSET_LSL, OP_STR, 32); }
4741
// STR Rd, [Rn, -Rm, LSR #]
4742
void arm702(u32 opcode) { STR_PREDEC(OFFSET_LSR, OP_STR, 32); }
4743
// STR Rd, [Rn, -Rm, ASR #]
4744
void arm704(u32 opcode) { STR_PREDEC(OFFSET_ASR, OP_STR, 32); }
4745
// STR Rd, [Rn, -Rm, ROR #]
4746
void arm706(u32 opcode) { STR_PREDEC(OFFSET_ROR, OP_STR, 32); }
4747
// LDR Rd, [Rn, -Rm, LSL #]
4748
void arm710(u32 opcode) { LDR_PREDEC(OFFSET_LSL, OP_LDR, 32); }
4749
// LDR Rd, [Rn, -Rm, LSR #]
4750
void arm712(u32 opcode) { LDR_PREDEC(OFFSET_LSR, OP_LDR, 32); }
4751
// LDR Rd, [Rn, -Rm, ASR #]
4752
void arm714(u32 opcode) { LDR_PREDEC(OFFSET_ASR, OP_LDR, 32); }
4753
// LDR Rd, [Rn, -Rm, ROR #]
4754
void arm716(u32 opcode) { LDR_PREDEC(OFFSET_ROR, OP_LDR, 32); }
4755
// STR Rd, [Rn, -Rm, LSL #]!
4756
void arm720(u32 opcode) { STR_PREDEC_WB(OFFSET_LSL, OP_STR, 32); }
4757
// STR Rd, [Rn, -Rm, LSR #]!
4758
void arm722(u32 opcode) { STR_PREDEC_WB(OFFSET_LSR, OP_STR, 32); }
4759
// STR Rd, [Rn, -Rm, ASR #]!
4760
void arm724(u32 opcode) { STR_PREDEC_WB(OFFSET_ASR, OP_STR, 32); }
4761
// STR Rd, [Rn, -Rm, ROR #]!
4762
void arm726(u32 opcode) { STR_PREDEC_WB(OFFSET_ROR, OP_STR, 32); }
4763
// LDR Rd, [Rn, -Rm, LSL #]!
4764
void arm730(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSL, OP_LDR, 32); }
4765
// LDR Rd, [Rn, -Rm, LSR #]!
4766
void arm732(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSR, OP_LDR, 32); }
4767
// LDR Rd, [Rn, -Rm, ASR #]!
4768
void arm734(u32 opcode) { LDR_PREDEC_WB(OFFSET_ASR, OP_LDR, 32); }
4769
// LDR Rd, [Rn, -Rm, ROR #]!
4770
void arm736(u32 opcode) { LDR_PREDEC_WB(OFFSET_ROR, OP_LDR, 32); }
4771
// STRB Rd, [Rn, -Rm, LSL #]
4772
void arm740(u32 opcode) { STR_PREDEC(OFFSET_LSL, OP_STRB, 16); }
4773
// STRB Rd, [Rn, -Rm, LSR #]
4774
void arm742(u32 opcode) { STR_PREDEC(OFFSET_LSR, OP_STRB, 16); }
4775
// STRB Rd, [Rn, -Rm, ASR #]
4776
void arm744(u32 opcode) { STR_PREDEC(OFFSET_ASR, OP_STRB, 16); }
4777
// STRB Rd, [Rn, -Rm, ROR #]
4778
void arm746(u32 opcode) { STR_PREDEC(OFFSET_ROR, OP_STRB, 16); }
4779
// LDRB Rd, [Rn, -Rm, LSL #]
4780
void arm750(u32 opcode) { LDR_PREDEC(OFFSET_LSL, OP_LDRB, 16); }
4781
// LDRB Rd, [Rn, -Rm, LSR #]
4782
void arm752(u32 opcode) { LDR_PREDEC(OFFSET_LSR, OP_LDRB, 16); }
4783
// LDRB Rd, [Rn, -Rm, ASR #]
4784
void arm754(u32 opcode) { LDR_PREDEC(OFFSET_ASR, OP_LDRB, 16); }
4785
// LDRB Rd, [Rn, -Rm, ROR #]
4786
void arm756(u32 opcode) { LDR_PREDEC(OFFSET_ROR, OP_LDRB, 16); }
4787
// STRB Rd, [Rn, -Rm, LSL #]!
4788
void arm760(u32 opcode) { STR_PREDEC_WB(OFFSET_LSL, OP_STRB, 16); }
4789
// STRB Rd, [Rn, -Rm, LSR #]!
4790
void arm762(u32 opcode) { STR_PREDEC_WB(OFFSET_LSR, OP_STRB, 16); }
4791
// STRB Rd, [Rn, -Rm, ASR #]!
4792
void arm764(u32 opcode) { STR_PREDEC_WB(OFFSET_ASR, OP_STRB, 16); }
4793
// STRB Rd, [Rn, -Rm, ROR #]!
4794
void arm766(u32 opcode) { STR_PREDEC_WB(OFFSET_ROR, OP_STRB, 16); }
4795
// LDRB Rd, [Rn, -Rm, LSL #]!
4796
void arm770(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSL, OP_LDRB, 16); }
4797
// LDRB Rd, [Rn, -Rm, LSR #]!
4798
void arm772(u32 opcode) { LDR_PREDEC_WB(OFFSET_LSR, OP_LDRB, 16); }
4799
// LDRB Rd, [Rn, -Rm, ASR #]!
4800
void arm774(u32 opcode) { LDR_PREDEC_WB(OFFSET_ASR, OP_LDRB, 16); }
4801
// LDRB Rd, [Rn, -Rm, ROR #]!
4802
void arm776(u32 opcode) { LDR_PREDEC_WB(OFFSET_ROR, OP_LDRB, 16); }
4803
// STR Rd, [Rn, Rm, LSL #]
4804
void arm780(u32 opcode) { STR_PREINC(OFFSET_LSL, OP_STR, 32); }
4805
// STR Rd, [Rn, Rm, LSR #]
4806
void arm782(u32 opcode) { STR_PREINC(OFFSET_LSR, OP_STR, 32); }
4807
// STR Rd, [Rn, Rm, ASR #]
4808
void arm784(u32 opcode) { STR_PREINC(OFFSET_ASR, OP_STR, 32); }
4809
// STR Rd, [Rn, Rm, ROR #]
4810
void arm786(u32 opcode) { STR_PREINC(OFFSET_ROR, OP_STR, 32); }
4811
// LDR Rd, [Rn, Rm, LSL #]
4812
void arm790(u32 opcode) { LDR_PREINC(OFFSET_LSL, OP_LDR, 32); }
4813
// LDR Rd, [Rn, Rm, LSR #]
4814
void arm792(u32 opcode) { LDR_PREINC(OFFSET_LSR, OP_LDR, 32); }
4815
// LDR Rd, [Rn, Rm, ASR #]
4816
void arm794(u32 opcode) { LDR_PREINC(OFFSET_ASR, OP_LDR, 32); }
4817
// LDR Rd, [Rn, Rm, ROR #]
4818
void arm796(u32 opcode) { LDR_PREINC(OFFSET_ROR, OP_LDR, 32); }
4819
// STR Rd, [Rn, Rm, LSL #]!
4820
void arm7A0(u32 opcode) { STR_PREINC_WB(OFFSET_LSL, OP_STR, 32); }
4821
// STR Rd, [Rn, Rm, LSR #]!
4822
void arm7A2(u32 opcode) { STR_PREINC_WB(OFFSET_LSR, OP_STR, 32); }
4823
// STR Rd, [Rn, Rm, ASR #]!
4824
void arm7A4(u32 opcode) { STR_PREINC_WB(OFFSET_ASR, OP_STR, 32); }
4825
// STR Rd, [Rn, Rm, ROR #]!
4826
void arm7A6(u32 opcode) { STR_PREINC_WB(OFFSET_ROR, OP_STR, 32); }
4827
// LDR Rd, [Rn, Rm, LSL #]!
4828
void arm7B0(u32 opcode) { LDR_PREINC_WB(OFFSET_LSL, OP_LDR, 32); }
4829
// LDR Rd, [Rn, Rm, LSR #]!
4830
void arm7B2(u32 opcode) { LDR_PREINC_WB(OFFSET_LSR, OP_LDR, 32); }
4831
// LDR Rd, [Rn, Rm, ASR #]!
4832
void arm7B4(u32 opcode) { LDR_PREINC_WB(OFFSET_ASR, OP_LDR, 32); }
4833
// LDR Rd, [Rn, Rm, ROR #]!
4834
void arm7B6(u32 opcode) { LDR_PREINC_WB(OFFSET_ROR, OP_LDR, 32); }
4835
// STRB Rd, [Rn, Rm, LSL #]
4836
void arm7C0(u32 opcode) { STR_PREINC(OFFSET_LSL, OP_STRB, 16); }
4837
// STRB Rd, [Rn, Rm, LSR #]
4838
void arm7C2(u32 opcode) { STR_PREINC(OFFSET_LSR, OP_STRB, 16); }
4839
// STRB Rd, [Rn, Rm, ASR #]
4840
void arm7C4(u32 opcode) { STR_PREINC(OFFSET_ASR, OP_STRB, 16); }
4841
// STRB Rd, [Rn, Rm, ROR #]
4842
void arm7C6(u32 opcode) { STR_PREINC(OFFSET_ROR, OP_STRB, 16); }
4843
// LDRB Rd, [Rn, Rm, LSL #]
4844
void arm7D0(u32 opcode) { LDR_PREINC(OFFSET_LSL, OP_LDRB, 16); }
4845
// LDRB Rd, [Rn, Rm, LSR #]
4846
void arm7D2(u32 opcode) { LDR_PREINC(OFFSET_LSR, OP_LDRB, 16); }
4847
// LDRB Rd, [Rn, Rm, ASR #]
4848
void arm7D4(u32 opcode) { LDR_PREINC(OFFSET_ASR, OP_LDRB, 16); }
4849
// LDRB Rd, [Rn, Rm, ROR #]
4850
void arm7D6(u32 opcode) { LDR_PREINC(OFFSET_ROR, OP_LDRB, 16); }
4851
// STRB Rd, [Rn, Rm, LSL #]!
4852
void arm7E0(u32 opcode) { STR_PREINC_WB(OFFSET_LSL, OP_STRB, 16); }
4853
// STRB Rd, [Rn, Rm, LSR #]!
4854
void arm7E2(u32 opcode) { STR_PREINC_WB(OFFSET_LSR, OP_STRB, 16); }
4855
// STRB Rd, [Rn, Rm, ASR #]!
4856
void arm7E4(u32 opcode) { STR_PREINC_WB(OFFSET_ASR, OP_STRB, 16); }
4857
// STRB Rd, [Rn, Rm, ROR #]!
4858
void arm7E6(u32 opcode) { STR_PREINC_WB(OFFSET_ROR, OP_STRB, 16); }
4859
// LDRB Rd, [Rn, Rm, LSL #]!
4860
void arm7F0(u32 opcode) { LDR_PREINC_WB(OFFSET_LSL, OP_LDRB, 16); }
4861
// LDRB Rd, [Rn, Rm, LSR #]!
4862
void arm7F2(u32 opcode) { LDR_PREINC_WB(OFFSET_LSR, OP_LDRB, 16); }
4863
// LDRB Rd, [Rn, Rm, ASR #]!
4864
void arm7F4(u32 opcode) { LDR_PREINC_WB(OFFSET_ASR, OP_LDRB, 16); }
4865
// LDRB Rd, [Rn, Rm, ROR #]!
4866
void arm7F6(u32 opcode) { LDR_PREINC_WB(OFFSET_ROR, OP_LDRB, 16); }
4867
4868
// STM/LDM ////////////////////////////////////////////////////////////////
4869
4870
#define STM_REG(bit,num) \
4871
if (opcode & (1U<<(bit))) { \
4872
CPUWriteMemory(address, bus.reg[(num)].I); \
4873
int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
4874
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
4875
clockTicks += 1 + dataticks_value; \
4876
count++; \
4877
address += 4; \
4878
}
4879
#define STMW_REG(bit,num) \
4880
if (opcode & (1U<<(bit))) { \
4881
CPUWriteMemory(address, bus.reg[(num)].I); \
4882
int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
4883
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
4884
clockTicks += 1 + dataticks_value; \
4885
bus.reg[base].I = temp; \
4886
count++; \
4887
address += 4; \
4888
}
4889
#define LDM_REG(bit,num) \
4890
if (opcode & (1U<<(bit))) { \
4891
int dataticks_value; \
4892
bus.reg[(num)].I = CPUReadMemory(address); \
4893
dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
4894
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
4895
clockTicks += 1 + dataticks_value; \
4896
count++; \
4897
address += 4; \
4898
}
4899
#define STM_LOW(STORE_REG) \
4900
STORE_REG(0, 0); \
4901
STORE_REG(1, 1); \
4902
STORE_REG(2, 2); \
4903
STORE_REG(3, 3); \
4904
STORE_REG(4, 4); \
4905
STORE_REG(5, 5); \
4906
STORE_REG(6, 6); \
4907
STORE_REG(7, 7);
4908
#define STM_HIGH(STORE_REG) \
4909
STORE_REG(8, 8); \
4910
STORE_REG(9, 9); \
4911
STORE_REG(10, 10); \
4912
STORE_REG(11, 11); \
4913
STORE_REG(12, 12); \
4914
STORE_REG(13, 13); \
4915
STORE_REG(14, 14);
4916
#define STM_HIGH_2(STORE_REG) \
4917
if (armMode == 0x11) { \
4918
STORE_REG(8, R8_FIQ); \
4919
STORE_REG(9, R9_FIQ); \
4920
STORE_REG(10, R10_FIQ); \
4921
STORE_REG(11, R11_FIQ); \
4922
STORE_REG(12, R12_FIQ); \
4923
} else { \
4924
STORE_REG(8, 8); \
4925
STORE_REG(9, 9); \
4926
STORE_REG(10, 10); \
4927
STORE_REG(11, 11); \
4928
STORE_REG(12, 12); \
4929
} \
4930
if (armMode != 0x10 && armMode != 0x1F) { \
4931
STORE_REG(13, R13_USR); \
4932
STORE_REG(14, R14_USR); \
4933
} else { \
4934
STORE_REG(13, 13); \
4935
STORE_REG(14, 14); \
4936
}
4937
#define STM_PC \
4938
if (opcode & (1U<<15)) { \
4939
CPUWriteMemory(address, bus.reg[15].I+4); \
4940
int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
4941
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
4942
clockTicks += 1 + dataticks_value; \
4943
count++; \
4944
}
4945
#define STMW_PC \
4946
if (opcode & (1U<<15)) { \
4947
CPUWriteMemory(address, bus.reg[15].I+4); \
4948
int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
4949
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
4950
clockTicks += 1 + dataticks_value; \
4951
bus.reg[base].I = temp; \
4952
count++; \
4953
}
4954
#define LDM_LOW \
4955
LDM_REG(0, 0); \
4956
LDM_REG(1, 1); \
4957
LDM_REG(2, 2); \
4958
LDM_REG(3, 3); \
4959
LDM_REG(4, 4); \
4960
LDM_REG(5, 5); \
4961
LDM_REG(6, 6); \
4962
LDM_REG(7, 7);
4963
#define LDM_HIGH \
4964
LDM_REG(8, 8); \
4965
LDM_REG(9, 9); \
4966
LDM_REG(10, 10); \
4967
LDM_REG(11, 11); \
4968
LDM_REG(12, 12); \
4969
LDM_REG(13, 13); \
4970
LDM_REG(14, 14);
4971
#define LDM_HIGH_2 \
4972
if (armMode == 0x11) { \
4973
LDM_REG(8, R8_FIQ); \
4974
LDM_REG(9, R9_FIQ); \
4975
LDM_REG(10, R10_FIQ); \
4976
LDM_REG(11, R11_FIQ); \
4977
LDM_REG(12, R12_FIQ); \
4978
} else { \
4979
LDM_REG(8, 8); \
4980
LDM_REG(9, 9); \
4981
LDM_REG(10, 10); \
4982
LDM_REG(11, 11); \
4983
LDM_REG(12, 12); \
4984
} \
4985
if (armMode != 0x10 && armMode != 0x1F) { \
4986
LDM_REG(13, R13_USR); \
4987
LDM_REG(14, R14_USR); \
4988
} else { \
4989
LDM_REG(13, 13); \
4990
LDM_REG(14, 14); \
4991
}
4992
#define STM_ALL \
4993
STM_LOW(STM_REG); \
4994
STM_HIGH(STM_REG); \
4995
STM_PC;
4996
#define STMW_ALL \
4997
STM_LOW(STMW_REG); \
4998
STM_HIGH(STMW_REG); \
4999
STMW_PC;
5000
#define LDM_ALL \
5001
LDM_LOW; \
5002
LDM_HIGH; \
5003
if (opcode & (1U<<15)) { \
5004
bus.reg[15].I = CPUReadMemory(address); \
5005
int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
5006
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
5007
clockTicks += 1 + dataticks_value; \
5008
count++; \
5009
} \
5010
if (opcode & (1U<<15)) { \
5011
bus.armNextPC = bus.reg[15].I; \
5012
bus.reg[15].I += 4; \
5013
ARM_PREFETCH; \
5014
clockTicks += 1 + codeTicksAccessSeq32(bus.armNextPC);\
5015
}
5016
#define STM_ALL_2 \
5017
STM_LOW(STM_REG); \
5018
STM_HIGH_2(STM_REG); \
5019
STM_PC;
5020
#define STMW_ALL_2 \
5021
STM_LOW(STMW_REG); \
5022
STM_HIGH_2(STMW_REG); \
5023
STMW_PC;
5024
#define LDM_ALL_2 \
5025
LDM_LOW; \
5026
if (opcode & (1U<<15)) { \
5027
LDM_HIGH; \
5028
bus.reg[15].I = CPUReadMemory(address); \
5029
int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
5030
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
5031
clockTicks += 1 + dataticks_value; \
5032
count++; \
5033
} else { \
5034
LDM_HIGH_2; \
5035
}
5036
#define LDM_ALL_2B \
5037
if (opcode & (1U<<15)) { \
5038
if(armMode != (bus.reg[17].I & 0x1F)) \
5039
CPUSwitchMode(bus.reg[17].I & 0x1F, false, true); \
5040
if (armState) { \
5041
bus.armNextPC = bus.reg[15].I & 0xFFFFFFFC; \
5042
bus.reg[15].I = bus.armNextPC + 4; \
5043
ARM_PREFETCH; \
5044
} else { \
5045
bus.armNextPC = bus.reg[15].I & 0xFFFFFFFE; \
5046
bus.reg[15].I = bus.armNextPC + 2; \
5047
THUMB_PREFETCH; \
5048
} \
5049
clockTicks += 1 + codeTicksAccessSeq32(bus.armNextPC);\
5050
}
5051
5052
5053
// STMDA Rn, {Rlist}
5054
void arm800(u32 opcode)
5055
{
5056
if (bus.busPrefetchCount == 0)
5057
bus.busPrefetch = bus.busPrefetchEnable;
5058
int base = (opcode & 0x000F0000) >> 16;
5059
u32 temp = bus.reg[base].I -
5060
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5061
u32 address = (temp + 4) & 0xFFFFFFFC;
5062
int count = 0;
5063
STM_ALL;
5064
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5065
}
5066
5067
// LDMDA Rn, {Rlist}
5068
void arm810(u32 opcode)
5069
{
5070
if (bus.busPrefetchCount == 0)
5071
bus.busPrefetch = bus.busPrefetchEnable;
5072
int base = (opcode & 0x000F0000) >> 16;
5073
u32 temp = bus.reg[base].I -
5074
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5075
u32 address = (temp + 4) & 0xFFFFFFFC;
5076
int count = 0;
5077
LDM_ALL;
5078
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5079
}
5080
5081
// STMDA Rn!, {Rlist}
5082
void arm820(u32 opcode)
5083
{
5084
if (bus.busPrefetchCount == 0)
5085
bus.busPrefetch = bus.busPrefetchEnable;
5086
int base = (opcode & 0x000F0000) >> 16;
5087
u32 temp = bus.reg[base].I -
5088
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5089
u32 address = (temp+4) & 0xFFFFFFFC;
5090
int count = 0;
5091
STMW_ALL;
5092
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5093
}
5094
5095
// LDMDA Rn!, {Rlist}
5096
void arm830(u32 opcode)
5097
{
5098
if (bus.busPrefetchCount == 0)
5099
bus.busPrefetch = bus.busPrefetchEnable;
5100
int base = (opcode & 0x000F0000) >> 16;
5101
u32 temp = bus.reg[base].I -
5102
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5103
u32 address = (temp + 4) & 0xFFFFFFFC;
5104
int count = 0;
5105
LDM_ALL;
5106
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5107
if (!(opcode & (1U << base)))
5108
bus.reg[base].I = temp;
5109
}
5110
5111
// STMDA Rn, {Rlist}^
5112
void arm840(u32 opcode)
5113
{
5114
if (bus.busPrefetchCount == 0)
5115
bus.busPrefetch = bus.busPrefetchEnable;
5116
int base = (opcode & 0x000F0000) >> 16;
5117
u32 temp = bus.reg[base].I -
5118
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5119
u32 address = (temp+4) & 0xFFFFFFFC;
5120
int count = 0;
5121
STM_ALL_2;
5122
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5123
}
5124
5125
// LDMDA Rn, {Rlist}^
5126
void arm850(u32 opcode)
5127
{
5128
if (bus.busPrefetchCount == 0)
5129
bus.busPrefetch = bus.busPrefetchEnable;
5130
int base = (opcode & 0x000F0000) >> 16;
5131
u32 temp = bus.reg[base].I -
5132
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5133
u32 address = (temp + 4) & 0xFFFFFFFC;
5134
int count = 0;
5135
LDM_ALL_2;
5136
LDM_ALL_2B;
5137
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5138
}
5139
5140
// STMDA Rn!, {Rlist}^
5141
void arm860(u32 opcode)
5142
{
5143
if (bus.busPrefetchCount == 0)
5144
bus.busPrefetch = bus.busPrefetchEnable;
5145
int base = (opcode & 0x000F0000) >> 16;
5146
u32 temp = bus.reg[base].I -
5147
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5148
u32 address = (temp+4) & 0xFFFFFFFC;
5149
int count = 0;
5150
STMW_ALL_2;
5151
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5152
}
5153
5154
// LDMDA Rn!, {Rlist}^
5155
void arm870(u32 opcode)
5156
{
5157
if (bus.busPrefetchCount == 0)
5158
bus.busPrefetch = bus.busPrefetchEnable;
5159
int base = (opcode & 0x000F0000) >> 16;
5160
u32 temp = bus.reg[base].I -
5161
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5162
u32 address = (temp + 4) & 0xFFFFFFFC;
5163
int count = 0;
5164
LDM_ALL_2;
5165
if (!(opcode & (1U << base)))
5166
bus.reg[base].I = temp;
5167
LDM_ALL_2B;
5168
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5169
}
5170
5171
// STMIA Rn, {Rlist}
5172
void arm880(u32 opcode)
5173
{
5174
if (bus.busPrefetchCount == 0)
5175
bus.busPrefetch = bus.busPrefetchEnable;
5176
int base = (opcode & 0x000F0000) >> 16;
5177
u32 address = bus.reg[base].I & 0xFFFFFFFC;
5178
int count = 0;
5179
STM_ALL;
5180
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5181
}
5182
5183
// LDMIA Rn, {Rlist}
5184
void arm890(u32 opcode)
5185
{
5186
if (bus.busPrefetchCount == 0)
5187
bus.busPrefetch = bus.busPrefetchEnable;
5188
int base = (opcode & 0x000F0000) >> 16;
5189
u32 address = bus.reg[base].I & 0xFFFFFFFC;
5190
int count = 0;
5191
LDM_ALL;
5192
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5193
}
5194
5195
// STMIA Rn!, {Rlist}
5196
void arm8A0(u32 opcode)
5197
{
5198
if (bus.busPrefetchCount == 0)
5199
bus.busPrefetch = bus.busPrefetchEnable;
5200
int base = (opcode & 0x000F0000) >> 16;
5201
u32 address = bus.reg[base].I & 0xFFFFFFFC;
5202
int count = 0;
5203
u32 temp = bus.reg[base].I +
5204
4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
5205
STMW_ALL;
5206
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5207
}
5208
5209
// LDMIA Rn!, {Rlist}
5210
void arm8B0(u32 opcode)
5211
{
5212
if (bus.busPrefetchCount == 0)
5213
bus.busPrefetch = bus.busPrefetchEnable;
5214
int base = (opcode & 0x000F0000) >> 16;
5215
u32 temp = bus.reg[base].I +
5216
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5217
u32 address = bus.reg[base].I & 0xFFFFFFFC;
5218
int count = 0;
5219
LDM_ALL;
5220
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5221
if (!(opcode & (1U << base)))
5222
bus.reg[base].I = temp;
5223
}
5224
5225
// STMIA Rn, {Rlist}^
5226
void arm8C0(u32 opcode)
5227
{
5228
if (bus.busPrefetchCount == 0)
5229
bus.busPrefetch = bus.busPrefetchEnable;
5230
int base = (opcode & 0x000F0000) >> 16;
5231
u32 address = bus.reg[base].I & 0xFFFFFFFC;
5232
int count = 0;
5233
STM_ALL_2;
5234
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5235
}
5236
5237
// LDMIA Rn, {Rlist}^
5238
void arm8D0(u32 opcode)
5239
{
5240
if (bus.busPrefetchCount == 0)
5241
bus.busPrefetch = bus.busPrefetchEnable;
5242
int base = (opcode & 0x000F0000) >> 16;
5243
u32 address = bus.reg[base].I & 0xFFFFFFFC;
5244
int count = 0;
5245
LDM_ALL_2;
5246
LDM_ALL_2B;
5247
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5248
}
5249
5250
// STMIA Rn!, {Rlist}^
5251
void arm8E0(u32 opcode)
5252
{
5253
if (bus.busPrefetchCount == 0)
5254
bus.busPrefetch = bus.busPrefetchEnable;
5255
int base = (opcode & 0x000F0000) >> 16;
5256
u32 address = bus.reg[base].I & 0xFFFFFFFC;
5257
int count = 0;
5258
u32 temp = bus.reg[base].I +
5259
4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
5260
STMW_ALL_2;
5261
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5262
}
5263
5264
// LDMIA Rn!, {Rlist}^
5265
void arm8F0(u32 opcode)
5266
{
5267
if (bus.busPrefetchCount == 0)
5268
bus.busPrefetch = bus.busPrefetchEnable;
5269
int base = (opcode & 0x000F0000) >> 16;
5270
u32 temp = bus.reg[base].I +
5271
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5272
u32 address = bus.reg[base].I & 0xFFFFFFFC;
5273
int count = 0;
5274
LDM_ALL_2;
5275
if (!(opcode & (1U << base)))
5276
bus.reg[base].I = temp;
5277
LDM_ALL_2B;
5278
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5279
}
5280
5281
// STMDB Rn, {Rlist}
5282
void arm900(u32 opcode)
5283
{
5284
if (bus.busPrefetchCount == 0)
5285
bus.busPrefetch = bus.busPrefetchEnable;
5286
int base = (opcode & 0x000F0000) >> 16;
5287
u32 temp = bus.reg[base].I -
5288
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5289
u32 address = temp & 0xFFFFFFFC;
5290
int count = 0;
5291
STM_ALL;
5292
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5293
}
5294
5295
// LDMDB Rn, {Rlist}
5296
void arm910(u32 opcode)
5297
{
5298
if (bus.busPrefetchCount == 0)
5299
bus.busPrefetch = bus.busPrefetchEnable;
5300
int base = (opcode & 0x000F0000) >> 16;
5301
u32 temp = bus.reg[base].I -
5302
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5303
u32 address = temp & 0xFFFFFFFC;
5304
int count = 0;
5305
LDM_ALL;
5306
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5307
}
5308
5309
// STMDB Rn!, {Rlist}
5310
void arm920(u32 opcode)
5311
{
5312
if (bus.busPrefetchCount == 0)
5313
bus.busPrefetch = bus.busPrefetchEnable;
5314
int base = (opcode & 0x000F0000) >> 16;
5315
u32 temp = bus.reg[base].I -
5316
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5317
u32 address = temp & 0xFFFFFFFC;
5318
int count = 0;
5319
STMW_ALL;
5320
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5321
}
5322
5323
// LDMDB Rn!, {Rlist}
5324
void arm930(u32 opcode)
5325
{
5326
if (bus.busPrefetchCount == 0)
5327
bus.busPrefetch = bus.busPrefetchEnable;
5328
int base = (opcode & 0x000F0000) >> 16;
5329
u32 temp = bus.reg[base].I -
5330
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5331
u32 address = temp & 0xFFFFFFFC;
5332
int count = 0;
5333
LDM_ALL;
5334
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5335
if (!(opcode & (1U << base)))
5336
bus.reg[base].I = temp;
5337
}
5338
5339
// STMDB Rn, {Rlist}^
5340
void arm940(u32 opcode)
5341
{
5342
if (bus.busPrefetchCount == 0)
5343
bus.busPrefetch = bus.busPrefetchEnable;
5344
int base = (opcode & 0x000F0000) >> 16;
5345
u32 temp = bus.reg[base].I -
5346
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5347
u32 address = temp & 0xFFFFFFFC;
5348
int count = 0;
5349
STM_ALL_2;
5350
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5351
}
5352
5353
// LDMDB Rn, {Rlist}^
5354
void arm950(u32 opcode)
5355
{
5356
if (bus.busPrefetchCount == 0)
5357
bus.busPrefetch = bus.busPrefetchEnable;
5358
int base = (opcode & 0x000F0000) >> 16;
5359
u32 temp = bus.reg[base].I -
5360
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5361
u32 address = temp & 0xFFFFFFFC;
5362
int count = 0;
5363
LDM_ALL_2;
5364
LDM_ALL_2B;
5365
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5366
}
5367
5368
// STMDB Rn!, {Rlist}^
5369
void arm960(u32 opcode)
5370
{
5371
if (bus.busPrefetchCount == 0)
5372
bus.busPrefetch = bus.busPrefetchEnable;
5373
int base = (opcode & 0x000F0000) >> 16;
5374
u32 temp = bus.reg[base].I -
5375
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5376
u32 address = temp & 0xFFFFFFFC;
5377
int count = 0;
5378
STMW_ALL_2;
5379
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5380
}
5381
5382
// LDMDB Rn!, {Rlist}^
5383
void arm970(u32 opcode)
5384
{
5385
if (bus.busPrefetchCount == 0)
5386
bus.busPrefetch = bus.busPrefetchEnable;
5387
int base = (opcode & 0x000F0000) >> 16;
5388
u32 temp = bus.reg[base].I -
5389
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5390
u32 address = temp & 0xFFFFFFFC;
5391
int count = 0;
5392
LDM_ALL_2;
5393
if (!(opcode & (1U << base)))
5394
bus.reg[base].I = temp;
5395
LDM_ALL_2B;
5396
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5397
}
5398
5399
// STMIB Rn, {Rlist}
5400
void arm980(u32 opcode)
5401
{
5402
if (bus.busPrefetchCount == 0)
5403
bus.busPrefetch = bus.busPrefetchEnable;
5404
int base = (opcode & 0x000F0000) >> 16;
5405
u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
5406
int count = 0;
5407
STM_ALL;
5408
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5409
}
5410
5411
// LDMIB Rn, {Rlist}
5412
void arm990(u32 opcode)
5413
{
5414
if (bus.busPrefetchCount == 0)
5415
bus.busPrefetch = bus.busPrefetchEnable;
5416
int base = (opcode & 0x000F0000) >> 16;
5417
u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
5418
int count = 0;
5419
LDM_ALL;
5420
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5421
}
5422
5423
// STMIB Rn!, {Rlist}
5424
void arm9A0(u32 opcode)
5425
{
5426
if (bus.busPrefetchCount == 0)
5427
bus.busPrefetch = bus.busPrefetchEnable;
5428
int base = (opcode & 0x000F0000) >> 16;
5429
u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
5430
int count = 0;
5431
u32 temp = bus.reg[base].I +
5432
4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
5433
STMW_ALL;
5434
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5435
}
5436
5437
// LDMIB Rn!, {Rlist}
5438
void arm9B0(u32 opcode)
5439
{
5440
if (bus.busPrefetchCount == 0)
5441
bus.busPrefetch = bus.busPrefetchEnable;
5442
int base = (opcode & 0x000F0000) >> 16;
5443
u32 temp = bus.reg[base].I +
5444
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5445
u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
5446
int count = 0;
5447
LDM_ALL;
5448
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5449
if (!(opcode & (1U << base)))
5450
bus.reg[base].I = temp;
5451
}
5452
5453
// STMIB Rn, {Rlist}^
5454
void arm9C0(u32 opcode)
5455
{
5456
if (bus.busPrefetchCount == 0)
5457
bus.busPrefetch = bus.busPrefetchEnable;
5458
int base = (opcode & 0x000F0000) >> 16;
5459
u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
5460
int count = 0;
5461
STM_ALL_2;
5462
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5463
}
5464
5465
// LDMIB Rn, {Rlist}^
5466
void arm9D0(u32 opcode)
5467
{
5468
if (bus.busPrefetchCount == 0)
5469
bus.busPrefetch = bus.busPrefetchEnable;
5470
int base = (opcode & 0x000F0000) >> 16;
5471
u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
5472
int count = 0;
5473
LDM_ALL_2;
5474
LDM_ALL_2B;
5475
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5476
}
5477
5478
// STMIB Rn!, {Rlist}^
5479
void arm9E0(u32 opcode)
5480
{
5481
if (bus.busPrefetchCount == 0)
5482
bus.busPrefetch = bus.busPrefetchEnable;
5483
int base = (opcode & 0x000F0000) >> 16;
5484
u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
5485
int count = 0;
5486
u32 temp = bus.reg[base].I +
5487
4 * (cpuBitsSet[opcode & 0xFF] + cpuBitsSet[(opcode >> 8) & 255]);
5488
STMW_ALL_2;
5489
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_32);
5490
}
5491
5492
// LDMIB Rn!, {Rlist}^
5493
void arm9F0(u32 opcode)
5494
{
5495
if (bus.busPrefetchCount == 0)
5496
bus.busPrefetch = bus.busPrefetchEnable;
5497
int base = (opcode & 0x000F0000) >> 16;
5498
u32 temp = bus.reg[base].I +
5499
4 * (cpuBitsSet[opcode & 255] + cpuBitsSet[(opcode >> 8) & 255]);
5500
u32 address = (bus.reg[base].I+4) & 0xFFFFFFFC;
5501
int count = 0;
5502
LDM_ALL_2;
5503
if (!(opcode & (1U << base)))
5504
bus.reg[base].I = temp;
5505
LDM_ALL_2B;
5506
clockTicks += 2 + codeTicksAccess(bus.armNextPC, BITS_32);
5507
}
5508
5509
// B/BL/SWI and (unimplemented) coproc support ////////////////////////////
5510
5511
// B <offset>
5512
void armA00(u32 opcode)
5513
{
5514
int codeTicksVal = 0;
5515
int ct = 0;
5516
int offset = opcode & 0x00FFFFFF;
5517
if (offset & 0x00800000)
5518
offset |= 0xFF000000; // negative offset
5519
bus.reg[15].I += offset<<2;
5520
bus.armNextPC = bus.reg[15].I;
5521
bus.reg[15].I += 4;
5522
ARM_PREFETCH;
5523
5524
codeTicksVal = codeTicksAccessSeq32(bus.armNextPC);
5525
ct = codeTicksVal + 3;
5526
ct += 2 + codeTicksAccess(bus.armNextPC, BITS_32) + codeTicksVal;
5527
5528
bus.busPrefetchCount = 0;
5529
clockTicks = ct;
5530
}
5531
5532
// BL <offset>
5533
void armB00(u32 opcode)
5534
{
5535
int codeTicksVal = 0;
5536
int ct = 0;
5537
5538
int offset = opcode & 0x00FFFFFF;
5539
if (offset & 0x00800000)
5540
offset |= 0xFF000000; // negative offset
5541
bus.reg[14].I = bus.reg[15].I - 4;
5542
bus.reg[15].I += offset<<2;
5543
bus.armNextPC = bus.reg[15].I;
5544
bus.reg[15].I += 4;
5545
ARM_PREFETCH;
5546
5547
codeTicksVal = codeTicksAccessSeq32(bus.armNextPC);
5548
ct = codeTicksVal + 3;
5549
ct += 2 + codeTicksAccess(bus.armNextPC, BITS_32) + codeTicksVal;
5550
5551
bus.busPrefetchCount = 0;
5552
clockTicks = ct;
5553
}
5554
5555
#define armE01 armUnknownInsn
5556
5557
// SWI <comment>
5558
void armF00(u32 opcode)
5559
{
5560
int codeTicksVal = 0;
5561
int ct = 0;
5562
5563
codeTicksVal = codeTicksAccessSeq32(bus.armNextPC);
5564
ct = codeTicksVal + 3;
5565
ct += 2 + codeTicksAccess(bus.armNextPC, BITS_32) + codeTicksVal;
5566
5567
bus.busPrefetchCount = 0;
5568
5569
clockTicks = ct;
5570
CPUSoftwareInterrupt(opcode & 0x00FFFFFF);
5571
5572
}
5573
5574
// Instruction table //////////////////////////////////////////////////////
5575
5576
static void (Gigazoid::*const armInsnTable[4096])(u32 opcode);
5577
5578
// Wrapper routine (execution loop) ///////////////////////////////////////
5579
int armExecute (void)
5580
{
5581
CACHE_PREFETCH(clockTicks);
5582
5583
u32 cond1;
5584
u32 cond2;
5585
5586
int ct = 0;
5587
5588
do
5589
{
5590
5591
clockTicks = 0;
5592
5593
if ((bus.armNextPC & 0x0803FFFF) == 0x08020000)
5594
bus.busPrefetchCount = 0x100;
5595
5596
u32 opcode = cpuPrefetch[0];
5597
cpuPrefetch[0] = cpuPrefetch[1];
5598
5599
bus.busPrefetch = false;
5600
int32_t busprefetch_mask = ((bus.busPrefetchCount & 0xFFFFFE00) | -(bus.busPrefetchCount & 0xFFFFFE00)) >> 31;
5601
bus.busPrefetchCount = (0x100 | (bus.busPrefetchCount & 0xFF) & busprefetch_mask) | (bus.busPrefetchCount & ~busprefetch_mask);
5602
#if 0
5603
if (bus.busPrefetchCount & 0xFFFFFE00)
5604
bus.busPrefetchCount = 0x100 | (bus.busPrefetchCount & 0xFF);
5605
#endif
5606
5607
5608
int oldArmNextPC = bus.armNextPC;
5609
5610
bus.armNextPC = bus.reg[15].I;
5611
if (traceCallback)
5612
traceCallback(bus.armNextPC, opcode);
5613
if (fetchCallback)
5614
fetchCallback(bus.armNextPC);
5615
bus.reg[15].I += 4;
5616
ARM_PREFETCH_NEXT;
5617
5618
int cond = opcode >> 28;
5619
bool cond_res = true;
5620
if (cond != 0x0E) { // most opcodes are AL (always)
5621
switch(cond) {
5622
case 0x00: // EQ
5623
cond_res = Z_FLAG;
5624
break;
5625
case 0x01: // NE
5626
cond_res = !Z_FLAG;
5627
break;
5628
case 0x02: // CS
5629
cond_res = C_FLAG;
5630
break;
5631
case 0x03: // CC
5632
cond_res = !C_FLAG;
5633
break;
5634
case 0x04: // MI
5635
cond_res = N_FLAG;
5636
break;
5637
case 0x05: // PL
5638
cond_res = !N_FLAG;
5639
break;
5640
case 0x06: // VS
5641
cond_res = V_FLAG;
5642
break;
5643
case 0x07: // VC
5644
cond_res = !V_FLAG;
5645
break;
5646
case 0x08: // HI
5647
cond_res = C_FLAG && !Z_FLAG;
5648
break;
5649
case 0x09: // LS
5650
cond_res = !C_FLAG || Z_FLAG;
5651
break;
5652
case 0x0A: // GE
5653
cond_res = N_FLAG == V_FLAG;
5654
break;
5655
case 0x0B: // LT
5656
cond_res = N_FLAG != V_FLAG;
5657
break;
5658
case 0x0C: // GT
5659
cond_res = !Z_FLAG &&(N_FLAG == V_FLAG);
5660
break;
5661
case 0x0D: // LE
5662
cond_res = Z_FLAG || (N_FLAG != V_FLAG);
5663
break;
5664
case 0x0E: // AL (impossible, checked above)
5665
cond_res = true;
5666
break;
5667
case 0x0F:
5668
default:
5669
// ???
5670
cond_res = false;
5671
break;
5672
}
5673
}
5674
5675
if (cond_res)
5676
{
5677
cond1 = (opcode>>16)&0xFF0;
5678
cond2 = (opcode>>4)&0x0F;
5679
5680
(this->*armInsnTable[(cond1| cond2)])(opcode);
5681
5682
}
5683
ct = clockTicks;
5684
5685
if (ct < 0)
5686
return 0;
5687
5688
/// better pipelining
5689
5690
if (ct == 0)
5691
clockTicks = 1 + codeTicksAccessSeq32(oldArmNextPC);
5692
5693
cpuTotalTicks += clockTicks;
5694
5695
} while ((cpuTotalTicks < cpuNextEvent) & armState & ~holdState);
5696
return 1;
5697
}
5698
5699
5700
/*============================================================
5701
GBA THUMB CORE
5702
============================================================ */
5703
5704
void thumbUnknownInsn(u32 opcode)
5705
{
5706
u32 PC = bus.reg[15].I;
5707
bool savedArmState = armState;
5708
if(armMode != 0x1b)
5709
CPUSwitchMode(0x1b, true, false);
5710
bus.reg[14].I = PC - (savedArmState ? 4 : 2);
5711
bus.reg[15].I = 0x04;
5712
armState = true;
5713
armIrqEnable = false;
5714
bus.armNextPC = 0x04;
5715
ARM_PREFETCH;
5716
bus.reg[15].I += 4;
5717
}
5718
5719
#define NEG(i) ((i) >> 31)
5720
#define POS(i) ((~(i)) >> 31)
5721
5722
// C core
5723
#ifndef ADDCARRY
5724
#define ADDCARRY(a, b, c) \
5725
C_FLAG = ((NEG(a) & NEG(b)) |\
5726
(NEG(a) & POS(c)) |\
5727
(NEG(b) & POS(c))) ? true : false;
5728
#endif
5729
5730
#ifndef ADDOVERFLOW
5731
#define ADDOVERFLOW(a, b, c) \
5732
V_FLAG = ((NEG(a) & NEG(b) & POS(c)) |\
5733
(POS(a) & POS(b) & NEG(c))) ? true : false;
5734
#endif
5735
5736
#ifndef SUBCARRY
5737
#define SUBCARRY(a, b, c) \
5738
C_FLAG = ((NEG(a) & POS(b)) |\
5739
(NEG(a) & POS(c)) |\
5740
(POS(b) & POS(c))) ? true : false;
5741
#endif
5742
5743
#ifndef SUBOVERFLOW
5744
#define SUBOVERFLOW(a, b, c)\
5745
V_FLAG = ((NEG(a) & POS(b) & POS(c)) |\
5746
(POS(a) & NEG(b) & NEG(c))) ? true : false;
5747
#endif
5748
5749
#ifndef ADD_RD_RS_RN
5750
#define ADD_RD_RS_RN(N) \
5751
{\
5752
u32 lhs = bus.reg[source].I;\
5753
u32 rhs = bus.reg[N].I;\
5754
u32 res = lhs + rhs;\
5755
bus.reg[dest].I = res;\
5756
Z_FLAG = (res == 0) ? true : false;\
5757
N_FLAG = NEG(res) ? true : false;\
5758
ADDCARRY(lhs, rhs, res);\
5759
ADDOVERFLOW(lhs, rhs, res);\
5760
}
5761
#endif
5762
5763
#ifndef ADD_RD_RS_O3
5764
#define ADD_RD_RS_O3(N) \
5765
{\
5766
u32 lhs = bus.reg[source].I;\
5767
u32 rhs = N;\
5768
u32 res = lhs + rhs;\
5769
bus.reg[dest].I = res;\
5770
Z_FLAG = (res == 0) ? true : false;\
5771
N_FLAG = NEG(res) ? true : false;\
5772
ADDCARRY(lhs, rhs, res);\
5773
ADDOVERFLOW(lhs, rhs, res);\
5774
}
5775
#endif
5776
5777
#ifndef ADD_RD_RS_O3_0
5778
# define ADD_RD_RS_O3_0 ADD_RD_RS_O3
5779
#endif
5780
5781
#ifndef ADD_RN_O8
5782
#define ADD_RN_O8(d) \
5783
{\
5784
u32 lhs = bus.reg[(d)].I;\
5785
u32 rhs = (opcode & 255);\
5786
u32 res = lhs + rhs;\
5787
bus.reg[(d)].I = res;\
5788
Z_FLAG = (res == 0) ? true : false;\
5789
N_FLAG = NEG(res) ? true : false;\
5790
ADDCARRY(lhs, rhs, res);\
5791
ADDOVERFLOW(lhs, rhs, res);\
5792
}
5793
#endif
5794
5795
#ifndef CMN_RD_RS
5796
#define CMN_RD_RS \
5797
{\
5798
u32 lhs = bus.reg[dest].I;\
5799
u32 rhs = value;\
5800
u32 res = lhs + rhs;\
5801
Z_FLAG = (res == 0) ? true : false;\
5802
N_FLAG = NEG(res) ? true : false;\
5803
ADDCARRY(lhs, rhs, res);\
5804
ADDOVERFLOW(lhs, rhs, res);\
5805
}
5806
#endif
5807
5808
#ifndef ADC_RD_RS
5809
#define ADC_RD_RS \
5810
{\
5811
u32 lhs = bus.reg[dest].I;\
5812
u32 rhs = value;\
5813
u32 res = lhs + rhs + (u32)C_FLAG;\
5814
bus.reg[dest].I = res;\
5815
Z_FLAG = (res == 0) ? true : false;\
5816
N_FLAG = NEG(res) ? true : false;\
5817
ADDCARRY(lhs, rhs, res);\
5818
ADDOVERFLOW(lhs, rhs, res);\
5819
}
5820
#endif
5821
5822
#ifndef SUB_RD_RS_RN
5823
#define SUB_RD_RS_RN(N) \
5824
{\
5825
u32 lhs = bus.reg[source].I;\
5826
u32 rhs = bus.reg[N].I;\
5827
u32 res = lhs - rhs;\
5828
bus.reg[dest].I = res;\
5829
Z_FLAG = (res == 0) ? true : false;\
5830
N_FLAG = NEG(res) ? true : false;\
5831
SUBCARRY(lhs, rhs, res);\
5832
SUBOVERFLOW(lhs, rhs, res);\
5833
}
5834
#endif
5835
5836
#ifndef SUB_RD_RS_O3
5837
#define SUB_RD_RS_O3(N) \
5838
{\
5839
u32 lhs = bus.reg[source].I;\
5840
u32 rhs = N;\
5841
u32 res = lhs - rhs;\
5842
bus.reg[dest].I = res;\
5843
Z_FLAG = (res == 0) ? true : false;\
5844
N_FLAG = NEG(res) ? true : false;\
5845
SUBCARRY(lhs, rhs, res);\
5846
SUBOVERFLOW(lhs, rhs, res);\
5847
}
5848
#endif
5849
5850
#ifndef SUB_RD_RS_O3_0
5851
# define SUB_RD_RS_O3_0 SUB_RD_RS_O3
5852
#endif
5853
#ifndef SUB_RN_O8
5854
#define SUB_RN_O8(d) \
5855
{\
5856
u32 lhs = bus.reg[(d)].I;\
5857
u32 rhs = (opcode & 255);\
5858
u32 res = lhs - rhs;\
5859
bus.reg[(d)].I = res;\
5860
Z_FLAG = (res == 0) ? true : false;\
5861
N_FLAG = NEG(res) ? true : false;\
5862
SUBCARRY(lhs, rhs, res);\
5863
SUBOVERFLOW(lhs, rhs, res);\
5864
}
5865
#endif
5866
#ifndef MOV_RN_O8
5867
#define MOV_RN_O8(d) \
5868
{\
5869
u32 val;\
5870
val = (opcode & 255);\
5871
bus.reg[d].I = val;\
5872
N_FLAG = false;\
5873
Z_FLAG = (val ? false : true);\
5874
}
5875
#endif
5876
#ifndef CMP_RN_O8
5877
#define CMP_RN_O8(d) \
5878
{\
5879
u32 lhs = bus.reg[(d)].I;\
5880
u32 rhs = (opcode & 255);\
5881
u32 res = lhs - rhs;\
5882
Z_FLAG = (res == 0) ? true : false;\
5883
N_FLAG = NEG(res) ? true : false;\
5884
SUBCARRY(lhs, rhs, res);\
5885
SUBOVERFLOW(lhs, rhs, res);\
5886
}
5887
#endif
5888
#ifndef SBC_RD_RS
5889
#define SBC_RD_RS \
5890
{\
5891
u32 lhs = bus.reg[dest].I;\
5892
u32 rhs = value;\
5893
u32 res = lhs - rhs - !((u32)C_FLAG);\
5894
bus.reg[dest].I = res;\
5895
Z_FLAG = (res == 0) ? true : false;\
5896
N_FLAG = NEG(res) ? true : false;\
5897
SUBCARRY(lhs, rhs, res);\
5898
SUBOVERFLOW(lhs, rhs, res);\
5899
}
5900
#endif
5901
#ifndef LSL_RD_RM_I5
5902
#define LSL_RD_RM_I5 \
5903
{\
5904
C_FLAG = (bus.reg[source].I >> (32 - shift)) & 1 ? true : false;\
5905
value = bus.reg[source].I << shift;\
5906
}
5907
#endif
5908
#ifndef LSL_RD_RS
5909
#define LSL_RD_RS \
5910
{\
5911
C_FLAG = (bus.reg[dest].I >> (32 - value)) & 1 ? true : false;\
5912
value = bus.reg[dest].I << value;\
5913
}
5914
#endif
5915
#ifndef LSR_RD_RM_I5
5916
#define LSR_RD_RM_I5 \
5917
{\
5918
C_FLAG = (bus.reg[source].I >> (shift - 1)) & 1 ? true : false;\
5919
value = bus.reg[source].I >> shift;\
5920
}
5921
#endif
5922
#ifndef LSR_RD_RS
5923
#define LSR_RD_RS \
5924
{\
5925
C_FLAG = (bus.reg[dest].I >> (value - 1)) & 1 ? true : false;\
5926
value = bus.reg[dest].I >> value;\
5927
}
5928
#endif
5929
#ifndef ASR_RD_RM_I5
5930
#define ASR_RD_RM_I5 \
5931
{\
5932
C_FLAG = ((s32)bus.reg[source].I >> (int)(shift - 1)) & 1 ? true : false;\
5933
value = (s32)bus.reg[source].I >> (int)shift;\
5934
}
5935
#endif
5936
#ifndef ASR_RD_RS
5937
#define ASR_RD_RS \
5938
{\
5939
C_FLAG = ((s32)bus.reg[dest].I >> (int)(value - 1)) & 1 ? true : false;\
5940
value = (s32)bus.reg[dest].I >> (int)value;\
5941
}
5942
#endif
5943
#ifndef ROR_RD_RS
5944
#define ROR_RD_RS \
5945
{\
5946
C_FLAG = (bus.reg[dest].I >> (value - 1)) & 1 ? true : false;\
5947
value = ((bus.reg[dest].I << (32 - value)) |\
5948
(bus.reg[dest].I >> value));\
5949
}
5950
#endif
5951
#ifndef NEG_RD_RS
5952
#define NEG_RD_RS \
5953
{\
5954
u32 lhs = bus.reg[source].I;\
5955
u32 rhs = 0;\
5956
u32 res = rhs - lhs;\
5957
bus.reg[dest].I = res;\
5958
Z_FLAG = (res == 0) ? true : false;\
5959
N_FLAG = NEG(res) ? true : false;\
5960
SUBCARRY(rhs, lhs, res);\
5961
SUBOVERFLOW(rhs, lhs, res);\
5962
}
5963
#endif
5964
#ifndef CMP_RD_RS
5965
#define CMP_RD_RS \
5966
{\
5967
u32 lhs = bus.reg[dest].I;\
5968
u32 rhs = value;\
5969
u32 res = lhs - rhs;\
5970
Z_FLAG = (res == 0) ? true : false;\
5971
N_FLAG = NEG(res) ? true : false;\
5972
SUBCARRY(lhs, rhs, res);\
5973
SUBOVERFLOW(lhs, rhs, res);\
5974
}
5975
#endif
5976
#ifndef IMM5_INSN
5977
#define IMM5_INSN(OP,N) \
5978
int dest = opcode & 0x07;\
5979
int source = (opcode >> 3) & 0x07;\
5980
u32 value;\
5981
OP(N);\
5982
bus.reg[dest].I = value;\
5983
N_FLAG = (value & 0x80000000 ? true : false);\
5984
Z_FLAG = (value ? false : true);
5985
#define IMM5_INSN_0(OP) \
5986
int dest = opcode & 0x07;\
5987
int source = (opcode >> 3) & 0x07;\
5988
u32 value;\
5989
OP;\
5990
bus.reg[dest].I = value;\
5991
N_FLAG = (value & 0x80000000 ? true : false);\
5992
Z_FLAG = (value ? false : true);
5993
#define IMM5_LSL(N) \
5994
int shift = N;\
5995
LSL_RD_RM_I5;
5996
#define IMM5_LSL_0 \
5997
value = bus.reg[source].I;
5998
#define IMM5_LSR(N) \
5999
int shift = N;\
6000
LSR_RD_RM_I5;
6001
#define IMM5_LSR_0 \
6002
C_FLAG = bus.reg[source].I & 0x80000000 ? true : false;\
6003
value = 0;
6004
#define IMM5_ASR(N) \
6005
int shift = N;\
6006
ASR_RD_RM_I5;
6007
#define IMM5_ASR_0 \
6008
if(bus.reg[source].I & 0x80000000) {\
6009
value = 0xFFFFFFFF;\
6010
C_FLAG = true;\
6011
} else {\
6012
value = 0;\
6013
C_FLAG = false;\
6014
}
6015
#endif
6016
#ifndef THREEARG_INSN
6017
#define THREEARG_INSN(OP,N) \
6018
int dest = opcode & 0x07; \
6019
int source = (opcode >> 3) & 0x07; \
6020
OP(N);
6021
#endif
6022
6023
// Shift instructions /////////////////////////////////////////////////////
6024
6025
#define DEFINE_IMM5_INSN(OP,BASE) \
6026
void thumb##BASE##_00(u32 opcode) { IMM5_INSN_0(OP##_0); } \
6027
void thumb##BASE##_01(u32 opcode) { IMM5_INSN(OP, 1); } \
6028
void thumb##BASE##_02(u32 opcode) { IMM5_INSN(OP, 2); } \
6029
void thumb##BASE##_03(u32 opcode) { IMM5_INSN(OP, 3); } \
6030
void thumb##BASE##_04(u32 opcode) { IMM5_INSN(OP, 4); } \
6031
void thumb##BASE##_05(u32 opcode) { IMM5_INSN(OP, 5); } \
6032
void thumb##BASE##_06(u32 opcode) { IMM5_INSN(OP, 6); } \
6033
void thumb##BASE##_07(u32 opcode) { IMM5_INSN(OP, 7); } \
6034
void thumb##BASE##_08(u32 opcode) { IMM5_INSN(OP, 8); } \
6035
void thumb##BASE##_09(u32 opcode) { IMM5_INSN(OP, 9); } \
6036
void thumb##BASE##_0A(u32 opcode) { IMM5_INSN(OP,10); } \
6037
void thumb##BASE##_0B(u32 opcode) { IMM5_INSN(OP,11); } \
6038
void thumb##BASE##_0C(u32 opcode) { IMM5_INSN(OP,12); } \
6039
void thumb##BASE##_0D(u32 opcode) { IMM5_INSN(OP,13); } \
6040
void thumb##BASE##_0E(u32 opcode) { IMM5_INSN(OP,14); } \
6041
void thumb##BASE##_0F(u32 opcode) { IMM5_INSN(OP,15); } \
6042
void thumb##BASE##_10(u32 opcode) { IMM5_INSN(OP,16); } \
6043
void thumb##BASE##_11(u32 opcode) { IMM5_INSN(OP,17); } \
6044
void thumb##BASE##_12(u32 opcode) { IMM5_INSN(OP,18); } \
6045
void thumb##BASE##_13(u32 opcode) { IMM5_INSN(OP,19); } \
6046
void thumb##BASE##_14(u32 opcode) { IMM5_INSN(OP,20); } \
6047
void thumb##BASE##_15(u32 opcode) { IMM5_INSN(OP,21); } \
6048
void thumb##BASE##_16(u32 opcode) { IMM5_INSN(OP,22); } \
6049
void thumb##BASE##_17(u32 opcode) { IMM5_INSN(OP,23); } \
6050
void thumb##BASE##_18(u32 opcode) { IMM5_INSN(OP,24); } \
6051
void thumb##BASE##_19(u32 opcode) { IMM5_INSN(OP,25); } \
6052
void thumb##BASE##_1A(u32 opcode) { IMM5_INSN(OP,26); } \
6053
void thumb##BASE##_1B(u32 opcode) { IMM5_INSN(OP,27); } \
6054
void thumb##BASE##_1C(u32 opcode) { IMM5_INSN(OP,28); } \
6055
void thumb##BASE##_1D(u32 opcode) { IMM5_INSN(OP,29); } \
6056
void thumb##BASE##_1E(u32 opcode) { IMM5_INSN(OP,30); } \
6057
void thumb##BASE##_1F(u32 opcode) { IMM5_INSN(OP,31); }
6058
6059
// LSL Rd, Rm, #Imm 5
6060
DEFINE_IMM5_INSN(IMM5_LSL,00)
6061
// LSR Rd, Rm, #Imm 5
6062
DEFINE_IMM5_INSN(IMM5_LSR,08)
6063
// ASR Rd, Rm, #Imm 5
6064
DEFINE_IMM5_INSN(IMM5_ASR,10)
6065
6066
// 3-argument ADD/SUB /////////////////////////////////////////////////////
6067
6068
#define DEFINE_REG3_INSN(OP,BASE) \
6069
void thumb##BASE##_0(u32 opcode) { THREEARG_INSN(OP,0); } \
6070
void thumb##BASE##_1(u32 opcode) { THREEARG_INSN(OP,1); } \
6071
void thumb##BASE##_2(u32 opcode) { THREEARG_INSN(OP,2); } \
6072
void thumb##BASE##_3(u32 opcode) { THREEARG_INSN(OP,3); } \
6073
void thumb##BASE##_4(u32 opcode) { THREEARG_INSN(OP,4); } \
6074
void thumb##BASE##_5(u32 opcode) { THREEARG_INSN(OP,5); } \
6075
void thumb##BASE##_6(u32 opcode) { THREEARG_INSN(OP,6); } \
6076
void thumb##BASE##_7(u32 opcode) { THREEARG_INSN(OP,7); }
6077
6078
#define DEFINE_IMM3_INSN(OP,BASE) \
6079
void thumb##BASE##_0(u32 opcode) { THREEARG_INSN(OP##_0,0); } \
6080
void thumb##BASE##_1(u32 opcode) { THREEARG_INSN(OP,1); } \
6081
void thumb##BASE##_2(u32 opcode) { THREEARG_INSN(OP,2); } \
6082
void thumb##BASE##_3(u32 opcode) { THREEARG_INSN(OP,3); } \
6083
void thumb##BASE##_4(u32 opcode) { THREEARG_INSN(OP,4); } \
6084
void thumb##BASE##_5(u32 opcode) { THREEARG_INSN(OP,5); } \
6085
void thumb##BASE##_6(u32 opcode) { THREEARG_INSN(OP,6); } \
6086
void thumb##BASE##_7(u32 opcode) { THREEARG_INSN(OP,7); }
6087
6088
// ADD Rd, Rs, Rn
6089
DEFINE_REG3_INSN(ADD_RD_RS_RN,18)
6090
// SUB Rd, Rs, Rn
6091
DEFINE_REG3_INSN(SUB_RD_RS_RN,1A)
6092
// ADD Rd, Rs, #Offset3
6093
DEFINE_IMM3_INSN(ADD_RD_RS_O3,1C)
6094
// SUB Rd, Rs, #Offset3
6095
DEFINE_IMM3_INSN(SUB_RD_RS_O3,1E)
6096
6097
// MOV/CMP/ADD/SUB immediate //////////////////////////////////////////////
6098
6099
// MOV R0, #Offset8
6100
void thumb20(u32 opcode) { MOV_RN_O8(0); }
6101
// MOV R1, #Offset8
6102
void thumb21(u32 opcode) { MOV_RN_O8(1); }
6103
// MOV R2, #Offset8
6104
void thumb22(u32 opcode) { MOV_RN_O8(2); }
6105
// MOV R3, #Offset8
6106
void thumb23(u32 opcode) { MOV_RN_O8(3); }
6107
// MOV R4, #Offset8
6108
void thumb24(u32 opcode) { MOV_RN_O8(4); }
6109
// MOV R5, #Offset8
6110
void thumb25(u32 opcode) { MOV_RN_O8(5); }
6111
// MOV R6, #Offset8
6112
void thumb26(u32 opcode) { MOV_RN_O8(6); }
6113
// MOV R7, #Offset8
6114
void thumb27(u32 opcode) { MOV_RN_O8(7); }
6115
6116
// CMP R0, #Offset8
6117
void thumb28(u32 opcode) { CMP_RN_O8(0); }
6118
// CMP R1, #Offset8
6119
void thumb29(u32 opcode) { CMP_RN_O8(1); }
6120
// CMP R2, #Offset8
6121
void thumb2A(u32 opcode) { CMP_RN_O8(2); }
6122
// CMP R3, #Offset8
6123
void thumb2B(u32 opcode) { CMP_RN_O8(3); }
6124
// CMP R4, #Offset8
6125
void thumb2C(u32 opcode) { CMP_RN_O8(4); }
6126
// CMP R5, #Offset8
6127
void thumb2D(u32 opcode) { CMP_RN_O8(5); }
6128
// CMP R6, #Offset8
6129
void thumb2E(u32 opcode) { CMP_RN_O8(6); }
6130
// CMP R7, #Offset8
6131
void thumb2F(u32 opcode) { CMP_RN_O8(7); }
6132
6133
// ADD R0,#Offset8
6134
void thumb30(u32 opcode) { ADD_RN_O8(0); }
6135
// ADD R1,#Offset8
6136
void thumb31(u32 opcode) { ADD_RN_O8(1); }
6137
// ADD R2,#Offset8
6138
void thumb32(u32 opcode) { ADD_RN_O8(2); }
6139
// ADD R3,#Offset8
6140
void thumb33(u32 opcode) { ADD_RN_O8(3); }
6141
// ADD R4,#Offset8
6142
void thumb34(u32 opcode) { ADD_RN_O8(4); }
6143
// ADD R5,#Offset8
6144
void thumb35(u32 opcode) { ADD_RN_O8(5); }
6145
// ADD R6,#Offset8
6146
void thumb36(u32 opcode) { ADD_RN_O8(6); }
6147
// ADD R7,#Offset8
6148
void thumb37(u32 opcode) { ADD_RN_O8(7); }
6149
6150
// SUB R0,#Offset8
6151
void thumb38(u32 opcode) { SUB_RN_O8(0); }
6152
// SUB R1,#Offset8
6153
void thumb39(u32 opcode) { SUB_RN_O8(1); }
6154
// SUB R2,#Offset8
6155
void thumb3A(u32 opcode) { SUB_RN_O8(2); }
6156
// SUB R3,#Offset8
6157
void thumb3B(u32 opcode) { SUB_RN_O8(3); }
6158
// SUB R4,#Offset8
6159
void thumb3C(u32 opcode) { SUB_RN_O8(4); }
6160
// SUB R5,#Offset8
6161
void thumb3D(u32 opcode) { SUB_RN_O8(5); }
6162
// SUB R6,#Offset8
6163
void thumb3E(u32 opcode) { SUB_RN_O8(6); }
6164
// SUB R7,#Offset8
6165
void thumb3F(u32 opcode) { SUB_RN_O8(7); }
6166
6167
// ALU operations /////////////////////////////////////////////////////////
6168
6169
// AND Rd, Rs
6170
void thumb40_0(u32 opcode)
6171
{
6172
int dest = opcode & 7;
6173
u32 val = (bus.reg[dest].I & bus.reg[(opcode >> 3)&7].I);
6174
6175
//bus.reg[dest].I &= bus.reg[(opcode >> 3)&7].I;
6176
N_FLAG = val & 0x80000000 ? true : false;
6177
Z_FLAG = val ? false : true;
6178
6179
bus.reg[dest].I = val;
6180
6181
}
6182
6183
// EOR Rd, Rs
6184
void thumb40_1(u32 opcode)
6185
{
6186
int dest = opcode & 7;
6187
bus.reg[dest].I ^= bus.reg[(opcode >> 3)&7].I;
6188
N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
6189
Z_FLAG = bus.reg[dest].I ? false : true;
6190
}
6191
6192
// LSL Rd, Rs
6193
void thumb40_2(u32 opcode)
6194
{
6195
int dest = opcode & 7;
6196
u32 value = bus.reg[(opcode >> 3)&7].B.B0;
6197
u32 val = value;
6198
if(val) {
6199
if(val == 32) {
6200
value = 0;
6201
C_FLAG = (bus.reg[dest].I & 1 ? true : false);
6202
} else if(val < 32) {
6203
LSL_RD_RS;
6204
} else {
6205
value = 0;
6206
C_FLAG = false;
6207
}
6208
bus.reg[dest].I = value;
6209
}
6210
N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
6211
Z_FLAG = bus.reg[dest].I ? false : true;
6212
clockTicks = codeTicksAccess(bus.armNextPC, BITS_16)+2;
6213
}
6214
6215
// LSR Rd, Rs
6216
void thumb40_3(u32 opcode)
6217
{
6218
int dest = opcode & 7;
6219
u32 value = bus.reg[(opcode >> 3)&7].B.B0;
6220
u32 val = value;
6221
if(val) {
6222
if(val == 32) {
6223
value = 0;
6224
C_FLAG = (bus.reg[dest].I & 0x80000000 ? true : false);
6225
} else if(val < 32) {
6226
LSR_RD_RS;
6227
} else {
6228
value = 0;
6229
C_FLAG = false;
6230
}
6231
bus.reg[dest].I = value;
6232
}
6233
N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
6234
Z_FLAG = bus.reg[dest].I ? false : true;
6235
clockTicks = codeTicksAccess(bus.armNextPC, BITS_16)+2;
6236
}
6237
6238
// ASR Rd, Rs
6239
void thumb41_0(u32 opcode)
6240
{
6241
int dest = opcode & 7;
6242
u32 value = bus.reg[(opcode >> 3)&7].B.B0;
6243
6244
if(value) {
6245
if(value < 32) {
6246
ASR_RD_RS;
6247
bus.reg[dest].I = value;
6248
} else {
6249
if(bus.reg[dest].I & 0x80000000){
6250
bus.reg[dest].I = 0xFFFFFFFF;
6251
C_FLAG = true;
6252
} else {
6253
bus.reg[dest].I = 0x00000000;
6254
C_FLAG = false;
6255
}
6256
}
6257
}
6258
N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
6259
Z_FLAG = bus.reg[dest].I ? false : true;
6260
clockTicks = codeTicksAccess(bus.armNextPC, BITS_16)+2;
6261
}
6262
6263
// ADC Rd, Rs
6264
void thumb41_1(u32 opcode)
6265
{
6266
int dest = opcode & 0x07;
6267
u32 value = bus.reg[(opcode >> 3)&7].I;
6268
ADC_RD_RS;
6269
}
6270
6271
// SBC Rd, Rs
6272
void thumb41_2(u32 opcode)
6273
{
6274
int dest = opcode & 0x07;
6275
u32 value = bus.reg[(opcode >> 3)&7].I;
6276
SBC_RD_RS;
6277
}
6278
6279
// ROR Rd, Rs
6280
void thumb41_3(u32 opcode)
6281
{
6282
int dest = opcode & 7;
6283
u32 value = bus.reg[(opcode >> 3)&7].B.B0;
6284
u32 val = value;
6285
if(val) {
6286
value = value & 0x1f;
6287
if(val == 0) {
6288
C_FLAG = (bus.reg[dest].I & 0x80000000 ? true : false);
6289
} else {
6290
ROR_RD_RS;
6291
bus.reg[dest].I = value;
6292
}
6293
}
6294
clockTicks = codeTicksAccess(bus.armNextPC, BITS_16)+2;
6295
N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
6296
Z_FLAG = bus.reg[dest].I ? false : true;
6297
}
6298
6299
// TST Rd, Rs
6300
void thumb42_0(u32 opcode)
6301
{
6302
u32 value = bus.reg[opcode & 7].I & bus.reg[(opcode >> 3) & 7].I;
6303
N_FLAG = value & 0x80000000 ? true : false;
6304
Z_FLAG = value ? false : true;
6305
}
6306
6307
// NEG Rd, Rs
6308
void thumb42_1(u32 opcode)
6309
{
6310
int dest = opcode & 7;
6311
int source = (opcode >> 3) & 7;
6312
NEG_RD_RS;
6313
}
6314
6315
// CMP Rd, Rs
6316
void thumb42_2(u32 opcode)
6317
{
6318
int dest = opcode & 7;
6319
u32 value = bus.reg[(opcode >> 3)&7].I;
6320
CMP_RD_RS;
6321
}
6322
6323
// CMN Rd, Rs
6324
void thumb42_3(u32 opcode)
6325
{
6326
int dest = opcode & 7;
6327
u32 value = bus.reg[(opcode >> 3)&7].I;
6328
CMN_RD_RS;
6329
}
6330
6331
// ORR Rd, Rs
6332
void thumb43_0(u32 opcode)
6333
{
6334
int dest = opcode & 7;
6335
bus.reg[dest].I |= bus.reg[(opcode >> 3) & 7].I;
6336
Z_FLAG = bus.reg[dest].I ? false : true;
6337
N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
6338
}
6339
6340
// MUL Rd, Rs
6341
void thumb43_1(u32 opcode)
6342
{
6343
clockTicks = 1;
6344
int dest = opcode & 7;
6345
u32 rm = bus.reg[dest].I;
6346
bus.reg[dest].I = bus.reg[(opcode >> 3) & 7].I * rm;
6347
if (((s32)rm) < 0)
6348
rm = ~rm;
6349
if ((rm & 0xFFFF0000) == 0)
6350
clockTicks += 1;
6351
else if ((rm & 0xFF000000) == 0)
6352
clockTicks += 2;
6353
else
6354
clockTicks += 3;
6355
bus.busPrefetchCount = (bus.busPrefetchCount<<clockTicks) | (0xFF>>(8-clockTicks));
6356
clockTicks += codeTicksAccess(bus.armNextPC, BITS_16) + 1;
6357
Z_FLAG = bus.reg[dest].I ? false : true;
6358
N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
6359
}
6360
6361
// BIC Rd, Rs
6362
void thumb43_2(u32 opcode)
6363
{
6364
int dest = opcode & 7;
6365
bus.reg[dest].I &= (~bus.reg[(opcode >> 3) & 7].I);
6366
Z_FLAG = bus.reg[dest].I ? false : true;
6367
N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
6368
}
6369
6370
// MVN Rd, Rs
6371
void thumb43_3(u32 opcode)
6372
{
6373
int dest = opcode & 7;
6374
bus.reg[dest].I = ~bus.reg[(opcode >> 3) & 7].I;
6375
Z_FLAG = bus.reg[dest].I ? false : true;
6376
N_FLAG = bus.reg[dest].I & 0x80000000 ? true : false;
6377
}
6378
6379
// High-register instructions and BX //////////////////////////////////////
6380
6381
// ADD Rd, Hs
6382
void thumb44_1(u32 opcode)
6383
{
6384
bus.reg[opcode&7].I += bus.reg[((opcode>>3)&7)+8].I;
6385
}
6386
6387
// ADD Hd, Rs
6388
void thumb44_2(u32 opcode)
6389
{
6390
bus.reg[(opcode&7)+8].I += bus.reg[(opcode>>3)&7].I;
6391
if((opcode&7) == 7) {
6392
bus.reg[15].I &= 0xFFFFFFFE;
6393
bus.armNextPC = bus.reg[15].I;
6394
bus.reg[15].I += 2;
6395
THUMB_PREFETCH;
6396
clockTicks = codeTicksAccessSeq16(bus.armNextPC)<<1
6397
+ codeTicksAccess(bus.armNextPC, BITS_16) + 3;
6398
}
6399
}
6400
6401
// ADD Hd, Hs
6402
void thumb44_3(u32 opcode)
6403
{
6404
bus.reg[(opcode&7)+8].I += bus.reg[((opcode>>3)&7)+8].I;
6405
if((opcode&7) == 7) {
6406
bus.reg[15].I &= 0xFFFFFFFE;
6407
bus.armNextPC = bus.reg[15].I;
6408
bus.reg[15].I += 2;
6409
THUMB_PREFETCH;
6410
clockTicks = codeTicksAccessSeq16(bus.armNextPC)<<1
6411
+ codeTicksAccess(bus.armNextPC, BITS_16) + 3;
6412
}
6413
}
6414
6415
// CMP Rd, Hs
6416
void thumb45_1(u32 opcode)
6417
{
6418
int dest = opcode & 7;
6419
u32 value = bus.reg[((opcode>>3)&7)+8].I;
6420
CMP_RD_RS;
6421
}
6422
6423
// CMP Hd, Rs
6424
void thumb45_2(u32 opcode)
6425
{
6426
int dest = (opcode & 7) + 8;
6427
u32 value = bus.reg[(opcode>>3)&7].I;
6428
CMP_RD_RS;
6429
}
6430
6431
// CMP Hd, Hs
6432
void thumb45_3(u32 opcode)
6433
{
6434
int dest = (opcode & 7) + 8;
6435
u32 value = bus.reg[((opcode>>3)&7)+8].I;
6436
CMP_RD_RS;
6437
}
6438
6439
// MOV Rd, Hs
6440
void thumb46_1(u32 opcode)
6441
{
6442
bus.reg[opcode&7].I = bus.reg[((opcode>>3)&7)+8].I;
6443
}
6444
6445
// MOV Hd, Rs
6446
void thumb46_2(u32 opcode)
6447
{
6448
bus.reg[(opcode&7)+8].I = bus.reg[(opcode>>3)&7].I;
6449
if((opcode&7) == 7) {
6450
bus.reg[15].I &= 0xFFFFFFFE;
6451
bus.armNextPC = bus.reg[15].I;
6452
bus.reg[15].I += 2;
6453
THUMB_PREFETCH;
6454
clockTicks = codeTicksAccessSeq16(bus.armNextPC)<<1
6455
+ codeTicksAccess(bus.armNextPC, BITS_16) + 3;
6456
}
6457
}
6458
6459
// MOV Hd, Hs
6460
void thumb46_3(u32 opcode)
6461
{
6462
bus.reg[(opcode&7)+8].I = bus.reg[((opcode>>3)&7)+8].I;
6463
if((opcode&7) == 7) {
6464
bus.reg[15].I &= 0xFFFFFFFE;
6465
bus.armNextPC = bus.reg[15].I;
6466
bus.reg[15].I += 2;
6467
THUMB_PREFETCH;
6468
clockTicks = codeTicksAccessSeq16(bus.armNextPC)<<1
6469
+ codeTicksAccess(bus.armNextPC, BITS_16) + 3;
6470
}
6471
}
6472
6473
6474
// BX Rs
6475
void thumb47(u32 opcode)
6476
{
6477
int base = (opcode >> 3) & 15;
6478
bus.busPrefetchCount=0;
6479
bus.reg[15].I = bus.reg[base].I;
6480
if(bus.reg[base].I & 1) {
6481
armState = false;
6482
bus.reg[15].I &= 0xFFFFFFFE;
6483
bus.armNextPC = bus.reg[15].I;
6484
bus.reg[15].I += 2;
6485
THUMB_PREFETCH;
6486
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1)
6487
+ codeTicksAccess(bus.armNextPC, BITS_16) + 3;
6488
} else {
6489
armState = true;
6490
bus.reg[15].I &= 0xFFFFFFFC;
6491
bus.armNextPC = bus.reg[15].I;
6492
bus.reg[15].I += 4;
6493
ARM_PREFETCH;
6494
clockTicks = ((codeTicksAccessSeq32(bus.armNextPC)) << 1)
6495
+ codeTicksAccess(bus.armNextPC, BITS_32) + 3;
6496
}
6497
}
6498
6499
// Load/store instructions ////////////////////////////////////////////////
6500
6501
// LDR R0~R7,[PC, #Imm]
6502
void thumb48(u32 opcode)
6503
{
6504
u8 regist = (opcode >> 8) & 7;
6505
if (bus.busPrefetchCount == 0)
6506
bus.busPrefetch = bus.busPrefetchEnable;
6507
u32 address = (bus.reg[15].I & 0xFFFFFFFC) + ((opcode & 0xFF) << 2);
6508
// why quick?
6509
// bus.reg[regist].I = CPUReadMemoryQuick(address);
6510
bus.reg[regist].I = CPUReadMemory(address);
6511
bus.busPrefetchCount=0;
6512
int dataticks_value = DATATICKS_ACCESS_32BIT(address);
6513
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6514
clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
6515
}
6516
6517
// STR Rd, [Rs, Rn]
6518
void thumb50(u32 opcode)
6519
{
6520
if (bus.busPrefetchCount == 0)
6521
bus.busPrefetch = bus.busPrefetchEnable;
6522
u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I;
6523
CPUWriteMemory(address, bus.reg[opcode & 7].I);
6524
int dataticks_value = DATATICKS_ACCESS_32BIT(address);
6525
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6526
clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6527
}
6528
6529
// STRH Rd, [Rs, Rn]
6530
void thumb52(u32 opcode)
6531
{
6532
if (bus.busPrefetchCount == 0)
6533
bus.busPrefetch = bus.busPrefetchEnable;
6534
u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I;
6535
CPUWriteHalfWord(address, bus.reg[opcode&7].W.W0);
6536
int dataticks_value = DATATICKS_ACCESS_16BIT(address);
6537
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6538
clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6539
}
6540
6541
// STRB Rd, [Rs, Rn]
6542
void thumb54(u32 opcode)
6543
{
6544
if (bus.busPrefetchCount == 0)
6545
bus.busPrefetch = bus.busPrefetchEnable;
6546
u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode >>6)&7].I;
6547
CPUWriteByte(address, bus.reg[opcode & 7].B.B0);
6548
int dataticks_value = DATATICKS_ACCESS_16BIT(address);
6549
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6550
clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6551
}
6552
6553
// LDSB Rd, [Rs, Rn]
6554
void thumb56(u32 opcode)
6555
{
6556
if (bus.busPrefetchCount == 0)
6557
bus.busPrefetch = bus.busPrefetchEnable;
6558
u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I;
6559
bus.reg[opcode&7].I = (s8)CPUReadByte(address);
6560
int dataticks_value = DATATICKS_ACCESS_16BIT(address);
6561
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6562
clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
6563
}
6564
6565
// LDR Rd, [Rs, Rn]
6566
void thumb58(u32 opcode)
6567
{
6568
if (bus.busPrefetchCount == 0)
6569
bus.busPrefetch = bus.busPrefetchEnable;
6570
u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I;
6571
bus.reg[opcode&7].I = CPUReadMemory(address);
6572
int dataticks_value = DATATICKS_ACCESS_32BIT(address);
6573
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6574
clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
6575
}
6576
6577
// LDRH Rd, [Rs, Rn]
6578
void thumb5A(u32 opcode)
6579
{
6580
if (bus.busPrefetchCount == 0)
6581
bus.busPrefetch = bus.busPrefetchEnable;
6582
u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I;
6583
bus.reg[opcode&7].I = CPUReadHalfWord(address);
6584
int dataticks_value = DATATICKS_ACCESS_32BIT(address);
6585
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6586
clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
6587
}
6588
6589
// LDRB Rd, [Rs, Rn]
6590
void thumb5C(u32 opcode)
6591
{
6592
if (bus.busPrefetchCount == 0)
6593
bus.busPrefetch = bus.busPrefetchEnable;
6594
u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I;
6595
bus.reg[opcode&7].I = CPUReadByte(address);
6596
int dataticks_value = DATATICKS_ACCESS_16BIT(address);
6597
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6598
clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
6599
}
6600
6601
// LDSH Rd, [Rs, Rn]
6602
void thumb5E(u32 opcode)
6603
{
6604
if (bus.busPrefetchCount == 0)
6605
bus.busPrefetch = bus.busPrefetchEnable;
6606
u32 address = bus.reg[(opcode>>3)&7].I + bus.reg[(opcode>>6)&7].I;
6607
bus.reg[opcode&7].I = (s16)CPUReadHalfWordSigned(address);
6608
int dataticks_value = DATATICKS_ACCESS_16BIT(address);
6609
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6610
clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
6611
}
6612
6613
// STR Rd, [Rs, #Imm]
6614
void thumb60(u32 opcode)
6615
{
6616
if (bus.busPrefetchCount == 0)
6617
bus.busPrefetch = bus.busPrefetchEnable;
6618
u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2);
6619
CPUWriteMemory(address, bus.reg[opcode&7].I);
6620
int dataticks_value = DATATICKS_ACCESS_32BIT(address);
6621
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6622
clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6623
}
6624
6625
// LDR Rd, [Rs, #Imm]
6626
void thumb68(u32 opcode)
6627
{
6628
if (bus.busPrefetchCount == 0)
6629
bus.busPrefetch = bus.busPrefetchEnable;
6630
u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<2);
6631
bus.reg[opcode&7].I = CPUReadMemory(address);
6632
int dataticks_value = DATATICKS_ACCESS_32BIT(address);
6633
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6634
clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
6635
}
6636
6637
// STRB Rd, [Rs, #Imm]
6638
void thumb70(u32 opcode)
6639
{
6640
if (bus.busPrefetchCount == 0)
6641
bus.busPrefetch = bus.busPrefetchEnable;
6642
u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31));
6643
CPUWriteByte(address, bus.reg[opcode&7].B.B0);
6644
int dataticks_value = DATATICKS_ACCESS_16BIT(address);
6645
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6646
clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6647
}
6648
6649
// LDRB Rd, [Rs, #Imm]
6650
void thumb78(u32 opcode)
6651
{
6652
if (bus.busPrefetchCount == 0)
6653
bus.busPrefetch = bus.busPrefetchEnable;
6654
u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31));
6655
bus.reg[opcode&7].I = CPUReadByte(address);
6656
int dataticks_value = DATATICKS_ACCESS_16BIT(address);
6657
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6658
clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
6659
}
6660
6661
// STRH Rd, [Rs, #Imm]
6662
void thumb80(u32 opcode)
6663
{
6664
if (bus.busPrefetchCount == 0)
6665
bus.busPrefetch = bus.busPrefetchEnable;
6666
u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1);
6667
CPUWriteHalfWord(address, bus.reg[opcode&7].W.W0);
6668
int dataticks_value = DATATICKS_ACCESS_16BIT(address);
6669
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6670
clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6671
}
6672
6673
// LDRH Rd, [Rs, #Imm]
6674
void thumb88(u32 opcode)
6675
{
6676
if (bus.busPrefetchCount == 0)
6677
bus.busPrefetch = bus.busPrefetchEnable;
6678
u32 address = bus.reg[(opcode>>3)&7].I + (((opcode>>6)&31)<<1);
6679
bus.reg[opcode&7].I = CPUReadHalfWord(address);
6680
int dataticks_value = DATATICKS_ACCESS_16BIT(address);
6681
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6682
clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
6683
}
6684
6685
// STR R0~R7, [SP, #Imm]
6686
void thumb90(u32 opcode)
6687
{
6688
u8 regist = (opcode >> 8) & 7;
6689
if (bus.busPrefetchCount == 0)
6690
bus.busPrefetch = bus.busPrefetchEnable;
6691
u32 address = bus.reg[13].I + ((opcode&255)<<2);
6692
CPUWriteMemory(address, bus.reg[regist].I);
6693
int dataticks_value = DATATICKS_ACCESS_32BIT(address);
6694
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6695
clockTicks = dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16) + 2;
6696
}
6697
6698
// LDR R0~R7, [SP, #Imm]
6699
void thumb98(u32 opcode)
6700
{
6701
u8 regist = (opcode >> 8) & 7;
6702
if (bus.busPrefetchCount == 0)
6703
bus.busPrefetch = bus.busPrefetchEnable;
6704
u32 address = bus.reg[13].I + ((opcode&255)<<2);
6705
// why quick?
6706
// bus.reg[regist].I = CPUReadMemoryQuick(address);
6707
bus.reg[regist].I = CPUReadMemory(address);
6708
int dataticks_value = DATATICKS_ACCESS_32BIT(address);
6709
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6710
clockTicks = 3 + dataticks_value + codeTicksAccess(bus.armNextPC, BITS_16);
6711
}
6712
6713
// PC/stack-related ///////////////////////////////////////////////////////
6714
6715
// ADD R0~R7, PC, Imm
6716
void thumbA0(u32 opcode)
6717
{
6718
u8 regist = (opcode >> 8) & 7;
6719
bus.reg[regist].I = (bus.reg[15].I & 0xFFFFFFFC) + ((opcode&255)<<2);
6720
}
6721
6722
// ADD R0~R7, SP, Imm
6723
void thumbA8(u32 opcode)
6724
{
6725
u8 regist = (opcode >> 8) & 7;
6726
bus.reg[regist].I = bus.reg[13].I + ((opcode&255)<<2);
6727
}
6728
6729
// ADD SP, Imm
6730
void thumbB0(u32 opcode)
6731
{
6732
int offset = (opcode & 127) << 2;
6733
if(opcode & 0x80)
6734
offset = -offset;
6735
bus.reg[13].I += offset;
6736
}
6737
6738
// Push and pop ///////////////////////////////////////////////////////////
6739
6740
#define PUSH_REG(val, r) \
6741
if (opcode & (val)) { \
6742
CPUWriteMemory(address, bus.reg[(r)].I); \
6743
int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
6744
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
6745
clockTicks += 1 + dataticks_value; \
6746
count++; \
6747
address += 4; \
6748
}
6749
6750
#define POP_REG(val, r) \
6751
if (opcode & (val)) { \
6752
bus.reg[(r)].I = CPUReadMemory(address); \
6753
int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
6754
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value); \
6755
clockTicks += 1 + dataticks_value; \
6756
count++; \
6757
address += 4; \
6758
}
6759
6760
// PUSH {Rlist}
6761
void thumbB4(u32 opcode)
6762
{
6763
if (bus.busPrefetchCount == 0)
6764
bus.busPrefetch = bus.busPrefetchEnable;
6765
int count = 0;
6766
u32 temp = bus.reg[13].I - 4 * cpuBitsSet[opcode & 0xff];
6767
u32 address = temp & 0xFFFFFFFC;
6768
PUSH_REG(1, 0);
6769
PUSH_REG(2, 1);
6770
PUSH_REG(4, 2);
6771
PUSH_REG(8, 3);
6772
PUSH_REG(16, 4);
6773
PUSH_REG(32, 5);
6774
PUSH_REG(64, 6);
6775
PUSH_REG(128, 7);
6776
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_16);
6777
bus.reg[13].I = temp;
6778
}
6779
6780
// PUSH {Rlist, LR}
6781
void thumbB5(u32 opcode)
6782
{
6783
if (bus.busPrefetchCount == 0)
6784
bus.busPrefetch = bus.busPrefetchEnable;
6785
int count = 0;
6786
u32 temp = bus.reg[13].I - 4 - 4 * cpuBitsSet[opcode & 0xff];
6787
u32 address = temp & 0xFFFFFFFC;
6788
PUSH_REG(1, 0);
6789
PUSH_REG(2, 1);
6790
PUSH_REG(4, 2);
6791
PUSH_REG(8, 3);
6792
PUSH_REG(16, 4);
6793
PUSH_REG(32, 5);
6794
PUSH_REG(64, 6);
6795
PUSH_REG(128, 7);
6796
PUSH_REG(256, 14);
6797
clockTicks += 1 + codeTicksAccess(bus.armNextPC, BITS_16);
6798
bus.reg[13].I = temp;
6799
}
6800
6801
// POP {Rlist}
6802
void thumbBC(u32 opcode)
6803
{
6804
if (bus.busPrefetchCount == 0)
6805
bus.busPrefetch = bus.busPrefetchEnable;
6806
int count = 0;
6807
u32 address = bus.reg[13].I & 0xFFFFFFFC;
6808
u32 temp = bus.reg[13].I + 4*cpuBitsSet[opcode & 0xFF];
6809
POP_REG(1, 0);
6810
POP_REG(2, 1);
6811
POP_REG(4, 2);
6812
POP_REG(8, 3);
6813
POP_REG(16, 4);
6814
POP_REG(32, 5);
6815
POP_REG(64, 6);
6816
POP_REG(128, 7);
6817
bus.reg[13].I = temp;
6818
clockTicks = 2 + codeTicksAccess(bus.armNextPC, BITS_16);
6819
}
6820
6821
// POP {Rlist, PC}
6822
void thumbBD(u32 opcode)
6823
{
6824
if (bus.busPrefetchCount == 0)
6825
bus.busPrefetch = bus.busPrefetchEnable;
6826
int count = 0;
6827
u32 address = bus.reg[13].I & 0xFFFFFFFC;
6828
u32 temp = bus.reg[13].I + 4 + 4*cpuBitsSet[opcode & 0xFF];
6829
POP_REG(1, 0);
6830
POP_REG(2, 1);
6831
POP_REG(4, 2);
6832
POP_REG(8, 3);
6833
POP_REG(16, 4);
6834
POP_REG(32, 5);
6835
POP_REG(64, 6);
6836
POP_REG(128, 7);
6837
bus.reg[15].I = (CPUReadMemory(address) & 0xFFFFFFFE);
6838
int dataticks_value = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address);
6839
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_value);
6840
clockTicks += 1 + dataticks_value;
6841
count++;
6842
bus.armNextPC = bus.reg[15].I;
6843
bus.reg[15].I += 2;
6844
bus.reg[13].I = temp;
6845
THUMB_PREFETCH;
6846
bus.busPrefetchCount = 0;
6847
clockTicks += 3 + ((codeTicksAccess(bus.armNextPC, BITS_16)) << 1);
6848
}
6849
6850
// Load/store multiple ////////////////////////////////////////////////////
6851
6852
#define THUMB_STM_REG(val,r,b) \
6853
if(opcode & (val)) { \
6854
CPUWriteMemory(address, bus.reg[(r)].I); \
6855
bus.reg[(b)].I = temp; \
6856
int dataticks_val = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
6857
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_val); \
6858
clockTicks += 1 + dataticks_val; \
6859
count++; \
6860
address += 4; \
6861
}
6862
6863
#define THUMB_LDM_REG(val,r) \
6864
if(opcode & (val)) { \
6865
bus.reg[(r)].I = CPUReadMemory(address); \
6866
int dataticks_val = count ? DATATICKS_ACCESS_32BIT_SEQ(address) : DATATICKS_ACCESS_32BIT(address); \
6867
DATATICKS_ACCESS_BUS_PREFETCH(address, dataticks_val); \
6868
clockTicks += 1 + dataticks_val; \
6869
count++; \
6870
address += 4; \
6871
}
6872
6873
// STM R0~7!, {Rlist}
6874
void thumbC0(u32 opcode)
6875
{
6876
u8 regist = (opcode >> 8) & 7;
6877
if (bus.busPrefetchCount == 0)
6878
bus.busPrefetch = bus.busPrefetchEnable;
6879
u32 address = bus.reg[regist].I & 0xFFFFFFFC;
6880
u32 temp = bus.reg[regist].I + 4*cpuBitsSet[opcode & 0xff];
6881
int count = 0;
6882
// store
6883
THUMB_STM_REG(1, 0, regist);
6884
THUMB_STM_REG(2, 1, regist);
6885
THUMB_STM_REG(4, 2, regist);
6886
THUMB_STM_REG(8, 3, regist);
6887
THUMB_STM_REG(16, 4, regist);
6888
THUMB_STM_REG(32, 5, regist);
6889
THUMB_STM_REG(64, 6, regist);
6890
THUMB_STM_REG(128, 7, regist);
6891
clockTicks = 1 + codeTicksAccess(bus.armNextPC, BITS_16);
6892
}
6893
6894
// LDM R0~R7!, {Rlist}
6895
void thumbC8(u32 opcode)
6896
{
6897
u8 regist = (opcode >> 8) & 7;
6898
if (bus.busPrefetchCount == 0)
6899
bus.busPrefetch = bus.busPrefetchEnable;
6900
u32 address = bus.reg[regist].I & 0xFFFFFFFC;
6901
u32 temp = bus.reg[regist].I + 4*cpuBitsSet[opcode & 0xFF];
6902
int count = 0;
6903
// load
6904
THUMB_LDM_REG(1, 0);
6905
THUMB_LDM_REG(2, 1);
6906
THUMB_LDM_REG(4, 2);
6907
THUMB_LDM_REG(8, 3);
6908
THUMB_LDM_REG(16, 4);
6909
THUMB_LDM_REG(32, 5);
6910
THUMB_LDM_REG(64, 6);
6911
THUMB_LDM_REG(128, 7);
6912
clockTicks = 2 + codeTicksAccess(bus.armNextPC, BITS_16);
6913
if(!(opcode & (1<<regist)))
6914
bus.reg[regist].I = temp;
6915
}
6916
6917
// Conditional branches ///////////////////////////////////////////////////
6918
6919
// BEQ offset
6920
void thumbD0(u32 opcode)
6921
{
6922
if(Z_FLAG)
6923
{
6924
bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6925
bus.armNextPC = bus.reg[15].I;
6926
bus.reg[15].I += 2;
6927
THUMB_PREFETCH;
6928
#if defined (SPEEDHAX)
6929
clockTicks = 30;
6930
#else
6931
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) +
6932
codeTicksAccess(bus.armNextPC, BITS_16)+3;
6933
#endif
6934
bus.busPrefetchCount=0;
6935
}
6936
}
6937
6938
// BNE offset
6939
void thumbD1(u32 opcode)
6940
{
6941
if(!Z_FLAG) {
6942
bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6943
bus.armNextPC = bus.reg[15].I;
6944
bus.reg[15].I += 2;
6945
THUMB_PREFETCH;
6946
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) +
6947
codeTicksAccess(bus.armNextPC, BITS_16)+3;
6948
bus.busPrefetchCount=0;
6949
}
6950
}
6951
6952
// BCS offset
6953
void thumbD2(u32 opcode)
6954
{
6955
if(C_FLAG) {
6956
bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6957
bus.armNextPC = bus.reg[15].I;
6958
bus.reg[15].I += 2;
6959
THUMB_PREFETCH;
6960
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) +
6961
codeTicksAccess(bus.armNextPC, BITS_16)+3;
6962
bus.busPrefetchCount=0;
6963
}
6964
}
6965
6966
// BCC offset
6967
void thumbD3(u32 opcode)
6968
{
6969
if(!C_FLAG) {
6970
bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6971
bus.armNextPC = bus.reg[15].I;
6972
bus.reg[15].I += 2;
6973
THUMB_PREFETCH;
6974
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) +
6975
codeTicksAccess(bus.armNextPC, BITS_16)+3;
6976
bus.busPrefetchCount=0;
6977
}
6978
}
6979
6980
// BMI offset
6981
void thumbD4(u32 opcode)
6982
{
6983
if(N_FLAG) {
6984
bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6985
bus.armNextPC = bus.reg[15].I;
6986
bus.reg[15].I += 2;
6987
THUMB_PREFETCH;
6988
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) +
6989
codeTicksAccess(bus.armNextPC, BITS_16)+3;
6990
bus.busPrefetchCount=0;
6991
}
6992
}
6993
6994
// BPL offset
6995
void thumbD5(u32 opcode)
6996
{
6997
if(!N_FLAG) {
6998
bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
6999
bus.armNextPC = bus.reg[15].I;
7000
bus.reg[15].I += 2;
7001
THUMB_PREFETCH;
7002
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) +
7003
codeTicksAccess(bus.armNextPC, BITS_16)+3;
7004
bus.busPrefetchCount=0;
7005
}
7006
}
7007
7008
// BVS offset
7009
void thumbD6(u32 opcode)
7010
{
7011
if(V_FLAG) {
7012
bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
7013
bus.armNextPC = bus.reg[15].I;
7014
bus.reg[15].I += 2;
7015
THUMB_PREFETCH;
7016
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) +
7017
codeTicksAccess(bus.armNextPC, BITS_16)+3;
7018
bus.busPrefetchCount=0;
7019
}
7020
}
7021
7022
// BVC offset
7023
void thumbD7(u32 opcode)
7024
{
7025
if(!V_FLAG) {
7026
bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
7027
bus.armNextPC = bus.reg[15].I;
7028
bus.reg[15].I += 2;
7029
THUMB_PREFETCH;
7030
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) +
7031
codeTicksAccess(bus.armNextPC, BITS_16)+3;
7032
bus.busPrefetchCount=0;
7033
}
7034
}
7035
7036
// BHI offset
7037
void thumbD8(u32 opcode)
7038
{
7039
if(C_FLAG && !Z_FLAG) {
7040
bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
7041
bus.armNextPC = bus.reg[15].I;
7042
bus.reg[15].I += 2;
7043
THUMB_PREFETCH;
7044
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) +
7045
codeTicksAccess(bus.armNextPC, BITS_16)+3;
7046
bus.busPrefetchCount=0;
7047
}
7048
}
7049
7050
// BLS offset
7051
void thumbD9(u32 opcode)
7052
{
7053
if(!C_FLAG || Z_FLAG) {
7054
bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
7055
bus.armNextPC = bus.reg[15].I;
7056
bus.reg[15].I += 2;
7057
THUMB_PREFETCH;
7058
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) +
7059
codeTicksAccess(bus.armNextPC, BITS_16)+3;
7060
bus.busPrefetchCount=0;
7061
}
7062
}
7063
7064
// BGE offset
7065
void thumbDA(u32 opcode)
7066
{
7067
if(N_FLAG == V_FLAG) {
7068
bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
7069
bus.armNextPC = bus.reg[15].I;
7070
bus.reg[15].I += 2;
7071
THUMB_PREFETCH;
7072
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) +
7073
codeTicksAccess(bus.armNextPC, BITS_16)+3;
7074
bus.busPrefetchCount=0;
7075
}
7076
}
7077
7078
// BLT offset
7079
void thumbDB(u32 opcode)
7080
{
7081
if(N_FLAG != V_FLAG) {
7082
bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
7083
bus.armNextPC = bus.reg[15].I;
7084
bus.reg[15].I += 2;
7085
THUMB_PREFETCH;
7086
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) +
7087
codeTicksAccess(bus.armNextPC, BITS_16)+3;
7088
bus.busPrefetchCount=0;
7089
}
7090
}
7091
7092
// BGT offset
7093
void thumbDC(u32 opcode)
7094
{
7095
if(!Z_FLAG && (N_FLAG == V_FLAG)) {
7096
bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
7097
bus.armNextPC = bus.reg[15].I;
7098
bus.reg[15].I += 2;
7099
THUMB_PREFETCH;
7100
clockTicks = (codeTicksAccessSeq16(bus.armNextPC) << 1) +
7101
codeTicksAccess(bus.armNextPC, BITS_16)+3;
7102
bus.busPrefetchCount=0;
7103
}
7104
}
7105
7106
// BLE offset
7107
void thumbDD(u32 opcode)
7108
{
7109
if(Z_FLAG || (N_FLAG != V_FLAG)) {
7110
bus.reg[15].I += ((s8)(opcode & 0xFF)) << 1;
7111
bus.armNextPC = bus.reg[15].I;
7112
bus.reg[15].I += 2;
7113
THUMB_PREFETCH;
7114
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) +
7115
codeTicksAccess(bus.armNextPC, BITS_16)+3;
7116
bus.busPrefetchCount=0;
7117
}
7118
}
7119
7120
// SWI, B, BL /////////////////////////////////////////////////////////////
7121
7122
// SWI #comment
7123
void thumbDF(u32 opcode)
7124
{
7125
u32 address = 0;
7126
clockTicks = ((codeTicksAccessSeq16(address)) << 1) +
7127
codeTicksAccess(address, BITS_16)+3;
7128
bus.busPrefetchCount=0;
7129
CPUSoftwareInterrupt(opcode & 0xFF);
7130
}
7131
7132
// B offset
7133
void thumbE0(u32 opcode)
7134
{
7135
int offset = (opcode & 0x3FF) << 1;
7136
if(opcode & 0x0400)
7137
offset |= 0xFFFFF800;
7138
bus.reg[15].I += offset;
7139
bus.armNextPC = bus.reg[15].I;
7140
bus.reg[15].I += 2;
7141
THUMB_PREFETCH;
7142
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) +
7143
codeTicksAccess(bus.armNextPC, BITS_16) + 3;
7144
bus.busPrefetchCount=0;
7145
}
7146
7147
// BLL #offset (forward)
7148
void thumbF0(u32 opcode)
7149
{
7150
int offset = (opcode & 0x7FF);
7151
bus.reg[14].I = bus.reg[15].I + (offset << 12);
7152
clockTicks = codeTicksAccessSeq16(bus.armNextPC) + 1;
7153
}
7154
7155
// BLL #offset (backward)
7156
void thumbF4(u32 opcode)
7157
{
7158
int offset = (opcode & 0x7FF);
7159
bus.reg[14].I = bus.reg[15].I + ((offset << 12) | 0xFF800000);
7160
clockTicks = codeTicksAccessSeq16(bus.armNextPC) + 1;
7161
}
7162
7163
// BLH #offset
7164
void thumbF8(u32 opcode)
7165
{
7166
int offset = (opcode & 0x7FF);
7167
u32 temp = bus.reg[15].I-2;
7168
bus.reg[15].I = (bus.reg[14].I + (offset<<1))&0xFFFFFFFE;
7169
bus.armNextPC = bus.reg[15].I;
7170
bus.reg[15].I += 2;
7171
bus.reg[14].I = temp|1;
7172
THUMB_PREFETCH;
7173
clockTicks = ((codeTicksAccessSeq16(bus.armNextPC)) << 1) +
7174
codeTicksAccess(bus.armNextPC, BITS_16) + 3;
7175
bus.busPrefetchCount = 0;
7176
}
7177
7178
// Instruction table //////////////////////////////////////////////////////
7179
7180
static void (Gigazoid::*const thumbInsnTable[1024])(u32 opcode);
7181
7182
// Wrapper routine (execution loop) ///////////////////////////////////////
7183
7184
7185
int thumbExecute (void)
7186
{
7187
CACHE_PREFETCH(clockTicks);
7188
7189
int ct = 0;
7190
7191
do {
7192
7193
clockTicks = 0;
7194
7195
#if 0
7196
if ((bus.armNextPC & 0x0803FFFF) == 0x08020000)
7197
bus.busPrefetchCount=0x100;
7198
#endif
7199
7200
u32 opcode = cpuPrefetch[0];
7201
cpuPrefetch[0] = cpuPrefetch[1];
7202
7203
bus.busPrefetch = false;
7204
#if 0
7205
if (bus.busPrefetchCount & 0xFFFFFF00)
7206
bus.busPrefetchCount = 0x100 | (bus.busPrefetchCount & 0xFF);
7207
#endif
7208
7209
u32 oldArmNextPC = bus.armNextPC;
7210
7211
bus.armNextPC = bus.reg[15].I;
7212
if (traceCallback) // low bit of addr is set on callback to indicate thumb mode
7213
traceCallback(bus.armNextPC | 1, opcode);
7214
if (fetchCallback)
7215
fetchCallback(bus.armNextPC);
7216
7217
bus.reg[15].I += 2;
7218
THUMB_PREFETCH_NEXT;
7219
7220
(this->*thumbInsnTable[opcode>>6])(opcode);
7221
7222
ct = clockTicks;
7223
7224
if (ct < 0)
7225
return 0;
7226
7227
/// better pipelining
7228
if (ct==0)
7229
clockTicks = codeTicksAccessSeq16(oldArmNextPC) + 1;
7230
7231
cpuTotalTicks += clockTicks;
7232
7233
} while ((cpuTotalTicks < cpuNextEvent) & ~armState & ~holdState);
7234
return 1;
7235
}
7236
7237
7238
/*============================================================
7239
GBA GFX
7240
============================================================ */
7241
7242
#ifdef TILED_RENDERING
7243
#ifdef _MSC_VER
7244
union u8h
7245
{
7246
__pragma( pack(push, 1));
7247
struct
7248
#ifdef LSB_FIRST
7249
{
7250
/* 0*/ unsigned char lo:4;
7251
/* 4*/ unsigned char hi:4;
7252
#else
7253
{
7254
/* 4*/ unsigned char hi:4;
7255
/* 0*/ unsigned char lo:4;
7256
#endif
7257
}
7258
__pragma(pack(pop));
7259
u8 val;
7260
};
7261
#else
7262
union u8h
7263
{
7264
struct
7265
#ifdef LSB_FIRST
7266
{
7267
/* 0*/ unsigned char lo:4;
7268
/* 4*/ unsigned char hi:4;
7269
#else
7270
{
7271
/* 4*/ unsigned char hi:4;
7272
/* 0*/ unsigned char lo:4;
7273
#endif
7274
} __attribute__ ((packed));
7275
u8 val;
7276
};
7277
#endif
7278
7279
union TileEntry
7280
{
7281
#ifdef LSB_FIRST
7282
struct
7283
{
7284
/* 0*/ unsigned tileNum:10;
7285
/*12*/ unsigned hFlip:1;
7286
/*13*/ unsigned vFlip:1;
7287
/*14*/ unsigned palette:4;
7288
};
7289
#else
7290
struct
7291
{
7292
/*14*/ unsigned palette:4;
7293
/*13*/ unsigned vFlip:1;
7294
/*12*/ unsigned hFlip:1;
7295
/* 0*/ unsigned tileNum:10;
7296
};
7297
#endif
7298
u16 val;
7299
};
7300
7301
struct TileLine
7302
{
7303
u32 pixels[8];
7304
};
7305
7306
typedef const TileLine (*TileReader) (const u16 *, const int, const u8 *, u16 *, const u32);
7307
7308
static inline void gfxDrawPixel(u32 *dest, const u8 color, const u16 *palette, const u32 prio)
7309
{
7310
*dest = color ? (READ16LE(&palette[color]) | prio): 0x80000000;
7311
}
7312
7313
static inline const TileLine gfxReadTile(const u16 *screenSource, const int yyy, const u8 *charBase, u16 *palette, const u32 prio)
7314
{
7315
TileEntry tile;
7316
tile.val = READ16LE(screenSource);
7317
7318
int tileY = yyy & 7;
7319
if (tile.vFlip) tileY = 7 - tileY;
7320
TileLine tileLine;
7321
7322
const u8 *tileBase = &charBase[tile.tileNum * 64 + tileY * 8];
7323
7324
if (!tile.hFlip)
7325
{
7326
gfxDrawPixel(&tileLine.pixels[0], tileBase[0], palette, prio);
7327
gfxDrawPixel(&tileLine.pixels[1], tileBase[1], palette, prio);
7328
gfxDrawPixel(&tileLine.pixels[2], tileBase[2], palette, prio);
7329
gfxDrawPixel(&tileLine.pixels[3], tileBase[3], palette, prio);
7330
gfxDrawPixel(&tileLine.pixels[4], tileBase[4], palette, prio);
7331
gfxDrawPixel(&tileLine.pixels[5], tileBase[5], palette, prio);
7332
gfxDrawPixel(&tileLine.pixels[6], tileBase[6], palette, prio);
7333
gfxDrawPixel(&tileLine.pixels[7], tileBase[7], palette, prio);
7334
}
7335
else
7336
{
7337
gfxDrawPixel(&tileLine.pixels[0], tileBase[7], palette, prio);
7338
gfxDrawPixel(&tileLine.pixels[1], tileBase[6], palette, prio);
7339
gfxDrawPixel(&tileLine.pixels[2], tileBase[5], palette, prio);
7340
gfxDrawPixel(&tileLine.pixels[3], tileBase[4], palette, prio);
7341
gfxDrawPixel(&tileLine.pixels[4], tileBase[3], palette, prio);
7342
gfxDrawPixel(&tileLine.pixels[5], tileBase[2], palette, prio);
7343
gfxDrawPixel(&tileLine.pixels[6], tileBase[1], palette, prio);
7344
gfxDrawPixel(&tileLine.pixels[7], tileBase[0], palette, prio);
7345
}
7346
7347
return tileLine;
7348
}
7349
7350
static inline const TileLine gfxReadTilePal(const u16 *screenSource, const int yyy, const u8 *charBase, u16 *palette, const u32 prio)
7351
{
7352
TileEntry tile;
7353
tile.val = READ16LE(screenSource);
7354
7355
int tileY = yyy & 7;
7356
if (tile.vFlip) tileY = 7 - tileY;
7357
palette += tile.palette * 16;
7358
TileLine tileLine;
7359
7360
const u8h *tileBase = (u8h*) &charBase[tile.tileNum * 32 + tileY * 4];
7361
7362
if (!tile.hFlip)
7363
{
7364
gfxDrawPixel(&tileLine.pixels[0], tileBase[0].lo, palette, prio);
7365
gfxDrawPixel(&tileLine.pixels[1], tileBase[0].hi, palette, prio);
7366
gfxDrawPixel(&tileLine.pixels[2], tileBase[1].lo, palette, prio);
7367
gfxDrawPixel(&tileLine.pixels[3], tileBase[1].hi, palette, prio);
7368
gfxDrawPixel(&tileLine.pixels[4], tileBase[2].lo, palette, prio);
7369
gfxDrawPixel(&tileLine.pixels[5], tileBase[2].hi, palette, prio);
7370
gfxDrawPixel(&tileLine.pixels[6], tileBase[3].lo, palette, prio);
7371
gfxDrawPixel(&tileLine.pixels[7], tileBase[3].hi, palette, prio);
7372
}
7373
else
7374
{
7375
gfxDrawPixel(&tileLine.pixels[0], tileBase[3].hi, palette, prio);
7376
gfxDrawPixel(&tileLine.pixels[1], tileBase[3].lo, palette, prio);
7377
gfxDrawPixel(&tileLine.pixels[2], tileBase[2].hi, palette, prio);
7378
gfxDrawPixel(&tileLine.pixels[3], tileBase[2].lo, palette, prio);
7379
gfxDrawPixel(&tileLine.pixels[4], tileBase[1].hi, palette, prio);
7380
gfxDrawPixel(&tileLine.pixels[5], tileBase[1].lo, palette, prio);
7381
gfxDrawPixel(&tileLine.pixels[6], tileBase[0].hi, palette, prio);
7382
gfxDrawPixel(&tileLine.pixels[7], tileBase[0].lo, palette, prio);
7383
}
7384
7385
return tileLine;
7386
}
7387
7388
static inline void gfxDrawTile(const TileLine &tileLine, u32 *line)
7389
{
7390
memcpy(line, tileLine.pixels, sizeof(tileLine.pixels));
7391
}
7392
7393
static inline void gfxDrawTileClipped(const TileLine &tileLine, u32 *line, const int start, int w)
7394
{
7395
memcpy(line, tileLine.pixels + start, w * sizeof(u32));
7396
}
7397
7398
template<TileReader readTile>
7399
void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
7400
u32 *line)
7401
{
7402
u16 *palette = (u16 *)graphics.paletteRAM;
7403
u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
7404
u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800];
7405
u32 prio = ((control & 3)<<25) + 0x1000000;
7406
int sizeX = 256;
7407
int sizeY = 256;
7408
switch ((control >> 14) & 3)
7409
{
7410
case 0:
7411
break;
7412
case 1:
7413
sizeX = 512;
7414
break;
7415
case 2:
7416
sizeY = 512;
7417
break;
7418
case 3:
7419
sizeX = 512;
7420
sizeY = 512;
7421
break;
7422
}
7423
7424
int maskX = sizeX-1;
7425
int maskY = sizeY-1;
7426
7427
bool mosaicOn = (control & 0x40) ? true : false;
7428
7429
int xxx = hofs & maskX;
7430
int yyy = (vofs + io_registers[REG_VCOUNT]) & maskY;
7431
int mosaicX = (MOSAIC & 0x000F)+1;
7432
int mosaicY = ((MOSAIC & 0x00F0)>>4)+1;
7433
7434
if (mosaicOn)
7435
{
7436
if ((io_registers[REG_VCOUNT] % mosaicY) != 0)
7437
{
7438
mosaicY = io_registers[REG_VCOUNT] - (io_registers[REG_VCOUNT] % mosaicY);
7439
yyy = (vofs + mosaicY) & maskY;
7440
}
7441
}
7442
7443
if (yyy > 255 && sizeY > 256)
7444
{
7445
yyy &= 255;
7446
screenBase += 0x400;
7447
if (sizeX > 256)
7448
screenBase += 0x400;
7449
}
7450
7451
int yshift = ((yyy>>3)<<5);
7452
7453
u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift;
7454
int x = 0;
7455
const int firstTileX = xxx & 7;
7456
7457
// First tile, if clipped
7458
if (firstTileX)
7459
{
7460
gfxDrawTileClipped(readTile(screenSource, yyy, charBase, palette, prio), &line[x], firstTileX, 8 - firstTileX);
7461
screenSource++;
7462
x += 8 - firstTileX;
7463
xxx += 8 - firstTileX;
7464
7465
if (xxx == 256 && sizeX > 256)
7466
{
7467
screenSource = screenBase + 0x400 + yshift;
7468
}
7469
else if (xxx >= sizeX)
7470
{
7471
xxx = 0;
7472
screenSource = screenBase + yshift;
7473
}
7474
}
7475
7476
// Middle tiles, full
7477
while (x < 240 - firstTileX)
7478
{
7479
gfxDrawTile(readTile(screenSource, yyy, charBase, palette, prio), &line[x]);
7480
screenSource++;
7481
xxx += 8;
7482
x += 8;
7483
7484
if (xxx == 256 && sizeX > 256)
7485
{
7486
screenSource = screenBase + 0x400 + yshift;
7487
}
7488
else if (xxx >= sizeX)
7489
{
7490
xxx = 0;
7491
screenSource = screenBase + yshift;
7492
}
7493
}
7494
7495
// Last tile, if clipped
7496
if (firstTileX)
7497
{
7498
gfxDrawTileClipped(readTile(screenSource, yyy, charBase, palette, prio), &line[x], 0, firstTileX);
7499
}
7500
7501
if (mosaicOn)
7502
{
7503
if (mosaicX > 1)
7504
{
7505
int m = 1;
7506
for (int i = 0; i < 239; i++)
7507
{
7508
line[i+1] = line[i];
7509
m++;
7510
if (m == mosaicX)
7511
{
7512
m = 1;
7513
i++;
7514
}
7515
}
7516
}
7517
}
7518
}
7519
7520
void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs, u32 *line)
7521
{
7522
if (control & 0x80) // 1 pal / 256 col
7523
gfxDrawTextScreen<gfxReadTile>(control, hofs, vofs, line);
7524
else // 16 pal / 16 col
7525
gfxDrawTextScreen<gfxReadTilePal>(control, hofs, vofs, line);
7526
}
7527
#else
7528
inline void gfxDrawTextScreen(u16 control, u16 hofs, u16 vofs,
7529
u32 *line)
7530
{
7531
u16 *palette = (u16 *)graphics.paletteRAM;
7532
u8 *charBase = &vram[((control >> 2) & 0x03) * 0x4000];
7533
u16 *screenBase = (u16 *)&vram[((control >> 8) & 0x1f) * 0x800];
7534
u32 prio = ((control & 3)<<25) + 0x1000000;
7535
int sizeX = 256;
7536
int sizeY = 256;
7537
switch((control >> 14) & 3) {
7538
case 0:
7539
break;
7540
case 1:
7541
sizeX = 512;
7542
break;
7543
case 2:
7544
sizeY = 512;
7545
break;
7546
case 3:
7547
sizeX = 512;
7548
sizeY = 512;
7549
break;
7550
}
7551
7552
int maskX = sizeX-1;
7553
int maskY = sizeY-1;
7554
7555
bool mosaicOn = (control & 0x40) ? true : false;
7556
7557
int xxx = hofs & maskX;
7558
int yyy = (vofs + io_registers[REG_VCOUNT]) & maskY;
7559
int mosaicX = (MOSAIC & 0x000F)+1;
7560
int mosaicY = ((MOSAIC & 0x00F0)>>4)+1;
7561
7562
if(mosaicOn) {
7563
if((io_registers[REG_VCOUNT] % mosaicY) != 0) {
7564
mosaicY = io_registers[REG_VCOUNT] - (io_registers[REG_VCOUNT] % mosaicY);
7565
yyy = (vofs + mosaicY) & maskY;
7566
}
7567
}
7568
7569
if(yyy > 255 && sizeY > 256) {
7570
yyy &= 255;
7571
screenBase += 0x400;
7572
if(sizeX > 256)
7573
screenBase += 0x400;
7574
}
7575
7576
int yshift = ((yyy>>3)<<5);
7577
if((control) & 0x80) {
7578
u16 *screenSource = screenBase + 0x400 * (xxx>>8) + ((xxx & 255)>>3) + yshift;
7579
for(int x = 0; x < 240; x++) {
7580
u16 data = READ16LE(screenSource);
7581
7582
int tile = data & 0x3FF;
7583
int tileX = (xxx & 7);
7584
int tileY = yyy & 7;
7585
7586
if(tileX == 7)
7587
screenSource++;
7588
7589
if(data & 0x0400)
7590
tileX = 7 - tileX;
7591
if(data & 0x0800)
7592
tileY = 7 - tileY;
7593
7594
u8 color = charBase[tile * 64 + tileY * 8 + tileX];
7595
7596
line[x] = color ? (READ16LE(&palette[color]) | prio): 0x80000000;
7597
7598
xxx++;
7599
if(xxx == 256) {
7600
if(sizeX > 256)
7601
screenSource = screenBase + 0x400 + yshift;
7602
else {
7603
screenSource = screenBase + yshift;
7604
xxx = 0;
7605
}
7606
} else if(xxx >= sizeX) {
7607
xxx = 0;
7608
screenSource = screenBase + yshift;
7609
}
7610
}
7611
} else {
7612
u16 *screenSource = screenBase + 0x400*(xxx>>8)+((xxx&255)>>3) +
7613
yshift;
7614
for(int x = 0; x < 240; x++) {
7615
u16 data = READ16LE(screenSource);
7616
7617
int tile = data & 0x3FF;
7618
int tileX = (xxx & 7);
7619
int tileY = yyy & 7;
7620
7621
if(tileX == 7)
7622
screenSource++;
7623
7624
if(data & 0x0400)
7625
tileX = 7 - tileX;
7626
if(data & 0x0800)
7627
tileY = 7 - tileY;
7628
7629
u8 color = charBase[(tile<<5) + (tileY<<2) + (tileX>>1)];
7630
7631
if(tileX & 1) {
7632
color = (color >> 4);
7633
} else {
7634
color &= 0x0F;
7635
}
7636
7637
int pal = (data>>8) & 0xF0;
7638
line[x] = color ? (READ16LE(&palette[pal + color])|prio): 0x80000000;
7639
7640
xxx++;
7641
if(xxx == 256) {
7642
if(sizeX > 256)
7643
screenSource = screenBase + 0x400 + yshift;
7644
else {
7645
screenSource = screenBase + yshift;
7646
xxx = 0;
7647
}
7648
} else if(xxx >= sizeX) {
7649
xxx = 0;
7650
screenSource = screenBase + yshift;
7651
}
7652
}
7653
}
7654
if(mosaicOn) {
7655
if(mosaicX > 1) {
7656
int m = 1;
7657
for(int i = 0; i < 239; i++) {
7658
line[i+1] = line[i];
7659
m++;
7660
if(m == mosaicX) {
7661
m = 1;
7662
i++;
7663
}
7664
}
7665
}
7666
}
7667
}
7668
#endif
7669
7670
INLINE void gfxDrawRotScreen(u16 control, u16 x_l, u16 x_h, u16 y_l, u16 y_h,
7671
u16 pa, u16 pb, u16 pc, u16 pd, int& currentX, int& currentY, int changed, u32 *line)
7672
{
7673
u16 *palette = (u16 *)graphics.paletteRAM;
7674
u8 *charBase = &vram[((control >> 2) & 0x03) << 14];
7675
u8 *screenBase = (u8 *)&vram[((control >> 8) & 0x1f) << 11];
7676
int prio = ((control & 3) << 25) + 0x1000000;
7677
7678
u32 map_size = (control >> 14) & 3;
7679
u32 sizeX = map_sizes_rot[map_size];
7680
u32 sizeY = map_sizes_rot[map_size];
7681
7682
int maskX = sizeX-1;
7683
int maskY = sizeY-1;
7684
7685
int yshift = ((control >> 14) & 3)+4;
7686
7687
#ifdef BRANCHLESS_GBA_GFX
7688
int dx = pa & 0x7FFF;
7689
int dmx = pb & 0x7FFF;
7690
int dy = pc & 0x7FFF;
7691
int dmy = pd & 0x7FFF;
7692
7693
dx |= isel(-(pa & 0x8000), 0, 0xFFFF8000);
7694
7695
dmx |= isel(-(pb & 0x8000), 0, 0xFFFF8000);
7696
7697
dy |= isel(-(pc & 0x8000), 0, 0xFFFF8000);
7698
7699
dmy |= isel(-(pd & 0x8000), 0, 0xFFFF8000);
7700
#else
7701
int dx = pa & 0x7FFF;
7702
if(pa & 0x8000)
7703
dx |= 0xFFFF8000;
7704
int dmx = pb & 0x7FFF;
7705
if(pb & 0x8000)
7706
dmx |= 0xFFFF8000;
7707
int dy = pc & 0x7FFF;
7708
if(pc & 0x8000)
7709
dy |= 0xFFFF8000;
7710
int dmy = pd & 0x7FFF;
7711
if(pd & 0x8000)
7712
dmy |= 0xFFFF8000;
7713
#endif
7714
7715
if(io_registers[REG_VCOUNT] == 0)
7716
changed = 3;
7717
7718
currentX += dmx;
7719
currentY += dmy;
7720
7721
if(changed & 1)
7722
{
7723
currentX = (x_l) | ((x_h & 0x07FF)<<16);
7724
if(x_h & 0x0800)
7725
currentX |= 0xF8000000;
7726
}
7727
7728
if(changed & 2)
7729
{
7730
currentY = (y_l) | ((y_h & 0x07FF)<<16);
7731
if(y_h & 0x0800)
7732
currentY |= 0xF8000000;
7733
}
7734
7735
int realX = currentX;
7736
int realY = currentY;
7737
7738
if(control & 0x40)
7739
{
7740
int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
7741
int y = (io_registers[REG_VCOUNT] % mosaicY);
7742
realX -= y*dmx;
7743
realY -= y*dmy;
7744
}
7745
7746
memset(line, -1, 240 * sizeof(u32));
7747
if(control & 0x2000)
7748
{
7749
for(u32 x = 0; x < 240u; ++x)
7750
{
7751
int xxx = (realX >> 8) & maskX;
7752
int yyy = (realY >> 8) & maskY;
7753
7754
int tile = screenBase[(xxx>>3) + ((yyy>>3)<<yshift)];
7755
7756
int tileX = (xxx & 7);
7757
int tileY = yyy & 7;
7758
7759
u8 color = charBase[(tile<<6) + (tileY<<3) + tileX];
7760
7761
if(color)
7762
line[x] = (READ16LE(&palette[color])|prio);
7763
7764
realX += dx;
7765
realY += dy;
7766
}
7767
}
7768
else
7769
{
7770
for(u32 x = 0; x < 240u; ++x)
7771
{
7772
unsigned xxx = (realX >> 8);
7773
unsigned yyy = (realY >> 8);
7774
7775
if(xxx < sizeX && yyy < sizeY)
7776
{
7777
int tile = screenBase[(xxx>>3) + ((yyy>>3)<<yshift)];
7778
7779
int tileX = (xxx & 7);
7780
int tileY = yyy & 7;
7781
7782
u8 color = charBase[(tile<<6) + (tileY<<3) + tileX];
7783
7784
if(color)
7785
line[x] = (READ16LE(&palette[color])|prio);
7786
}
7787
7788
realX += dx;
7789
realY += dy;
7790
}
7791
}
7792
7793
if(control & 0x40)
7794
{
7795
int mosaicX = (MOSAIC & 0xF) + 1;
7796
if(mosaicX > 1)
7797
{
7798
int m = 1;
7799
for(u32 i = 0; i < 239u; ++i)
7800
{
7801
line[i+1] = line[i];
7802
if(++m == mosaicX)
7803
{
7804
m = 1;
7805
++i;
7806
}
7807
}
7808
}
7809
}
7810
}
7811
7812
INLINE void gfxDrawRotScreen16Bit( int& currentX, int& currentY, int changed)
7813
{
7814
u16 *screenBase = (u16 *)&vram[0];
7815
int prio = ((io_registers[REG_BG2CNT] & 3) << 25) + 0x1000000;
7816
7817
u32 sizeX = 240;
7818
u32 sizeY = 160;
7819
7820
int startX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16);
7821
if(BG2X_H & 0x0800)
7822
startX |= 0xF8000000;
7823
int startY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16);
7824
if(BG2Y_H & 0x0800)
7825
startY |= 0xF8000000;
7826
7827
#ifdef BRANCHLESS_GBA_GFX
7828
int dx = io_registers[REG_BG2PA] & 0x7FFF;
7829
dx |= isel(-(io_registers[REG_BG2PA] & 0x8000), 0, 0xFFFF8000);
7830
7831
int dmx = io_registers[REG_BG2PB] & 0x7FFF;
7832
dmx |= isel(-(io_registers[REG_BG2PB] & 0x8000), 0, 0xFFFF8000);
7833
7834
int dy = io_registers[REG_BG2PC] & 0x7FFF;
7835
dy |= isel(-(io_registers[REG_BG2PC] & 0x8000), 0, 0xFFFF8000);
7836
7837
int dmy = io_registers[REG_BG2PD] & 0x7FFF;
7838
dmy |= isel(-(io_registers[REG_BG2PD] & 0x8000), 0, 0xFFFF8000);
7839
#else
7840
int dx = io_registers[REG_BG2PA] & 0x7FFF;
7841
if(io_registers[REG_BG2PA] & 0x8000)
7842
dx |= 0xFFFF8000;
7843
int dmx = io_registers[REG_BG2PB] & 0x7FFF;
7844
if(io_registers[REG_BG2PB] & 0x8000)
7845
dmx |= 0xFFFF8000;
7846
int dy = io_registers[REG_BG2PC] & 0x7FFF;
7847
if(io_registers[REG_BG2PC] & 0x8000)
7848
dy |= 0xFFFF8000;
7849
int dmy = io_registers[REG_BG2PD] & 0x7FFF;
7850
if(io_registers[REG_BG2PD] & 0x8000)
7851
dmy |= 0xFFFF8000;
7852
#endif
7853
7854
if(io_registers[REG_VCOUNT] == 0)
7855
changed = 3;
7856
7857
currentX += dmx;
7858
currentY += dmy;
7859
7860
if(changed & 1)
7861
{
7862
currentX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16);
7863
if(BG2X_H & 0x0800)
7864
currentX |= 0xF8000000;
7865
}
7866
7867
if(changed & 2)
7868
{
7869
currentY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16);
7870
if(BG2Y_H & 0x0800)
7871
currentY |= 0xF8000000;
7872
}
7873
7874
int realX = currentX;
7875
int realY = currentY;
7876
7877
if(io_registers[REG_BG2CNT] & 0x40) {
7878
int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
7879
int y = (io_registers[REG_VCOUNT] % mosaicY);
7880
realX -= y*dmx;
7881
realY -= y*dmy;
7882
}
7883
7884
unsigned xxx = (realX >> 8);
7885
unsigned yyy = (realY >> 8);
7886
7887
memset(line[2], -1, 240 * sizeof(u32));
7888
for(u32 x = 0; x < 240u; ++x)
7889
{
7890
if(xxx < sizeX && yyy < sizeY)
7891
line[2][x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
7892
7893
realX += dx;
7894
realY += dy;
7895
7896
xxx = (realX >> 8);
7897
yyy = (realY >> 8);
7898
}
7899
7900
if(io_registers[REG_BG2CNT] & 0x40) {
7901
int mosaicX = (MOSAIC & 0xF) + 1;
7902
if(mosaicX > 1) {
7903
int m = 1;
7904
for(u32 i = 0; i < 239u; ++i)
7905
{
7906
line[2][i+1] = line[2][i];
7907
if(++m == mosaicX)
7908
{
7909
m = 1;
7910
++i;
7911
}
7912
}
7913
}
7914
}
7915
}
7916
7917
INLINE void gfxDrawRotScreen256(int &currentX, int& currentY, int changed)
7918
{
7919
u16 *palette = (u16 *)graphics.paletteRAM;
7920
u8 *screenBase = (io_registers[REG_DISPCNT] & 0x0010) ? &vram[0xA000] : &vram[0x0000];
7921
int prio = ((io_registers[REG_BG2CNT] & 3) << 25) + 0x1000000;
7922
u32 sizeX = 240;
7923
u32 sizeY = 160;
7924
7925
int startX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16);
7926
if(BG2X_H & 0x0800)
7927
startX |= 0xF8000000;
7928
int startY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16);
7929
if(BG2Y_H & 0x0800)
7930
startY |= 0xF8000000;
7931
7932
#ifdef BRANCHLESS_GBA_GFX
7933
int dx = io_registers[REG_BG2PA] & 0x7FFF;
7934
dx |= isel(-(io_registers[REG_BG2PA] & 0x8000), 0, 0xFFFF8000);
7935
7936
int dmx = io_registers[REG_BG2PB] & 0x7FFF;
7937
dmx |= isel(-(io_registers[REG_BG2PB] & 0x8000), 0, 0xFFFF8000);
7938
7939
int dy = io_registers[REG_BG2PC] & 0x7FFF;
7940
dy |= isel(-(io_registers[REG_BG2PC] & 0x8000), 0, 0xFFFF8000);
7941
7942
int dmy = io_registers[REG_BG2PD] & 0x7FFF;
7943
dmy |= isel(-(io_registers[REG_BG2PD] & 0x8000), 0, 0xFFFF8000);
7944
#else
7945
int dx = io_registers[REG_BG2PA] & 0x7FFF;
7946
if(io_registers[REG_BG2PA] & 0x8000)
7947
dx |= 0xFFFF8000;
7948
int dmx = io_registers[REG_BG2PB] & 0x7FFF;
7949
if(io_registers[REG_BG2PB] & 0x8000)
7950
dmx |= 0xFFFF8000;
7951
int dy = io_registers[REG_BG2PC] & 0x7FFF;
7952
if(io_registers[REG_BG2PC] & 0x8000)
7953
dy |= 0xFFFF8000;
7954
int dmy = io_registers[REG_BG2PD] & 0x7FFF;
7955
if(io_registers[REG_BG2PD] & 0x8000)
7956
dmy |= 0xFFFF8000;
7957
#endif
7958
7959
if(io_registers[REG_VCOUNT] == 0)
7960
changed = 3;
7961
7962
currentX += dmx;
7963
currentY += dmy;
7964
7965
if(changed & 1)
7966
{
7967
currentX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16);
7968
if(BG2X_H & 0x0800)
7969
currentX |= 0xF8000000;
7970
}
7971
7972
if(changed & 2)
7973
{
7974
currentY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16);
7975
if(BG2Y_H & 0x0800)
7976
currentY |= 0xF8000000;
7977
}
7978
7979
int realX = currentX;
7980
int realY = currentY;
7981
7982
if(io_registers[REG_BG2CNT] & 0x40) {
7983
int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
7984
int y = io_registers[REG_VCOUNT] - (io_registers[REG_VCOUNT] % mosaicY);
7985
realX = startX + y*dmx;
7986
realY = startY + y*dmy;
7987
}
7988
7989
int xxx = (realX >> 8);
7990
int yyy = (realY >> 8);
7991
7992
memset(line[2], -1, 240 * sizeof(u32));
7993
for(u32 x = 0; x < 240; ++x)
7994
{
7995
u8 color = screenBase[yyy * 240 + xxx];
7996
if(unsigned(xxx) < sizeX && unsigned(yyy) < sizeY && color)
7997
line[2][x] = (READ16LE(&palette[color])|prio);
7998
realX += dx;
7999
realY += dy;
8000
8001
xxx = (realX >> 8);
8002
yyy = (realY >> 8);
8003
}
8004
8005
if(io_registers[REG_BG2CNT] & 0x40)
8006
{
8007
int mosaicX = (MOSAIC & 0xF) + 1;
8008
if(mosaicX > 1)
8009
{
8010
int m = 1;
8011
for(u32 i = 0; i < 239u; ++i)
8012
{
8013
line[2][i+1] = line[2][i];
8014
if(++m == mosaicX)
8015
{
8016
m = 1;
8017
++i;
8018
}
8019
}
8020
}
8021
}
8022
}
8023
8024
INLINE void gfxDrawRotScreen16Bit160(int& currentX, int& currentY, int changed)
8025
{
8026
u16 *screenBase = (io_registers[REG_DISPCNT] & 0x0010) ? (u16 *)&vram[0xa000] :
8027
(u16 *)&vram[0];
8028
int prio = ((io_registers[REG_BG2CNT] & 3) << 25) + 0x1000000;
8029
u32 sizeX = 160;
8030
u32 sizeY = 128;
8031
8032
int startX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16);
8033
if(BG2X_H & 0x0800)
8034
startX |= 0xF8000000;
8035
int startY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16);
8036
if(BG2Y_H & 0x0800)
8037
startY |= 0xF8000000;
8038
8039
#ifdef BRANCHLESS_GBA_GFX
8040
int dx = io_registers[REG_BG2PA] & 0x7FFF;
8041
dx |= isel(-(io_registers[REG_BG2PA] & 0x8000), 0, 0xFFFF8000);
8042
8043
int dmx = io_registers[REG_BG2PB] & 0x7FFF;
8044
dmx |= isel(-(io_registers[REG_BG2PB] & 0x8000), 0, 0xFFFF8000);
8045
8046
int dy = io_registers[REG_BG2PC] & 0x7FFF;
8047
dy |= isel(-(io_registers[REG_BG2PC] & 0x8000), 0, 0xFFFF8000);
8048
8049
int dmy = io_registers[REG_BG2PD] & 0x7FFF;
8050
dmy |= isel(-(io_registers[REG_BG2PD] & 0x8000), 0, 0xFFFF8000);
8051
#else
8052
int dx = io_registers[REG_BG2PA] & 0x7FFF;
8053
if(io_registers[REG_BG2PA] & 0x8000)
8054
dx |= 0xFFFF8000;
8055
int dmx = io_registers[REG_BG2PB] & 0x7FFF;
8056
if(io_registers[REG_BG2PB] & 0x8000)
8057
dmx |= 0xFFFF8000;
8058
int dy = io_registers[REG_BG2PC] & 0x7FFF;
8059
if(io_registers[REG_BG2PC] & 0x8000)
8060
dy |= 0xFFFF8000;
8061
int dmy = io_registers[REG_BG2PD] & 0x7FFF;
8062
if(io_registers[REG_BG2PD] & 0x8000)
8063
dmy |= 0xFFFF8000;
8064
#endif
8065
8066
if(io_registers[REG_VCOUNT] == 0)
8067
changed = 3;
8068
8069
currentX += dmx;
8070
currentY += dmy;
8071
8072
if(changed & 1)
8073
{
8074
currentX = (BG2X_L) | ((BG2X_H & 0x07FF)<<16);
8075
if(BG2X_H & 0x0800)
8076
currentX |= 0xF8000000;
8077
}
8078
8079
if(changed & 2)
8080
{
8081
currentY = (BG2Y_L) | ((BG2Y_H & 0x07FF)<<16);
8082
if(BG2Y_H & 0x0800)
8083
currentY |= 0xF8000000;
8084
}
8085
8086
int realX = currentX;
8087
int realY = currentY;
8088
8089
if(io_registers[REG_BG2CNT] & 0x40) {
8090
int mosaicY = ((MOSAIC & 0xF0)>>4) + 1;
8091
int y = io_registers[REG_VCOUNT] - (io_registers[REG_VCOUNT] % mosaicY);
8092
realX = startX + y*dmx;
8093
realY = startY + y*dmy;
8094
}
8095
8096
int xxx = (realX >> 8);
8097
int yyy = (realY >> 8);
8098
8099
memset(line[2], -1, 240 * sizeof(u32));
8100
for(u32 x = 0; x < 240u; ++x)
8101
{
8102
if(unsigned(xxx) < sizeX && unsigned(yyy) < sizeY)
8103
line[2][x] = (READ16LE(&screenBase[yyy * sizeX + xxx]) | prio);
8104
8105
realX += dx;
8106
realY += dy;
8107
8108
xxx = (realX >> 8);
8109
yyy = (realY >> 8);
8110
}
8111
8112
8113
int mosaicX = (MOSAIC & 0xF) + 1;
8114
if(io_registers[REG_BG2CNT] & 0x40 && (mosaicX > 1))
8115
{
8116
int m = 1;
8117
for(u32 i = 0; i < 239u; ++i)
8118
{
8119
line[2][i+1] = line[2][i];
8120
if(++m == mosaicX)
8121
{
8122
m = 1;
8123
++i;
8124
}
8125
}
8126
}
8127
}
8128
8129
/* lineOBJpix is used to keep track of the drawn OBJs
8130
and to stop drawing them if the 'maximum number of OBJ per line'
8131
has been reached. */
8132
8133
INLINE void gfxDrawSprites (void)
8134
{
8135
unsigned lineOBJpix, m;
8136
8137
lineOBJpix = (io_registers[REG_DISPCNT] & 0x20) ? 954 : 1226;
8138
m = 0;
8139
8140
u16 *sprites = (u16 *)oam;
8141
u16 *spritePalette = &((u16 *)graphics.paletteRAM)[256];
8142
int mosaicY = ((MOSAIC & 0xF000)>>12) + 1;
8143
int mosaicX = ((MOSAIC & 0xF00)>>8) + 1;
8144
for(u32 x = 0; x < 128; x++)
8145
{
8146
u16 a0 = READ16LE(sprites++);
8147
u16 a1 = READ16LE(sprites++);
8148
u16 a2 = READ16LE(sprites++);
8149
++sprites;
8150
8151
lineOBJpixleft[x]=lineOBJpix;
8152
8153
lineOBJpix-=2;
8154
if (lineOBJpix<=0)
8155
return;
8156
8157
if ((a0 & 0x0c00) == 0x0c00)
8158
a0 &=0xF3FF;
8159
8160
u16 a0val = a0>>14;
8161
8162
if (a0val == 3)
8163
{
8164
a0 &= 0x3FFF;
8165
a1 &= 0x3FFF;
8166
}
8167
8168
u32 sizeX = 8<<(a1>>14);
8169
u32 sizeY = sizeX;
8170
8171
8172
if (a0val & 1)
8173
{
8174
#ifdef BRANCHLESS_GBA_GFX
8175
sizeX <<= isel(-(sizeX & (~31u)), 1, 0);
8176
sizeY >>= isel(-(sizeY>8), 0, 1);
8177
#else
8178
if (sizeX<32)
8179
sizeX<<=1;
8180
if (sizeY>8)
8181
sizeY>>=1;
8182
#endif
8183
}
8184
else if (a0val & 2)
8185
{
8186
#ifdef BRANCHLESS_GBA_GFX
8187
sizeX >>= isel(-(sizeX>8), 0, 1);
8188
sizeY <<= isel(-(sizeY & (~31u)), 1, 0);
8189
#else
8190
if (sizeX>8)
8191
sizeX>>=1;
8192
if (sizeY<32)
8193
sizeY<<=1;
8194
#endif
8195
8196
}
8197
8198
8199
int sy = (a0 & 255);
8200
int sx = (a1 & 0x1FF);
8201
8202
// computes ticks used by OBJ-WIN if OBJWIN is enabled
8203
if (((a0 & 0x0c00) == 0x0800) && (graphics.layerEnable & 0x8000))
8204
{
8205
if ((a0 & 0x0300) == 0x0300)
8206
{
8207
sizeX<<=1;
8208
sizeY<<=1;
8209
}
8210
8211
#ifdef BRANCHLESS_GBA_GFX
8212
sy -= isel(256 - sy - sizeY, 0, 256);
8213
sx -= isel(512 - sx - sizeX, 0, 512);
8214
#else
8215
if((sy+sizeY) > 256)
8216
sy -= 256;
8217
if ((sx+sizeX)> 512)
8218
sx -= 512;
8219
#endif
8220
8221
if (sx < 0)
8222
{
8223
sizeX+=sx;
8224
sx = 0;
8225
}
8226
else if ((sx+sizeX)>240)
8227
sizeX=240-sx;
8228
8229
if ((io_registers[REG_VCOUNT]>=sy) && (io_registers[REG_VCOUNT]<sy+sizeY) && (sx<240))
8230
{
8231
lineOBJpix -= (sizeX-2);
8232
8233
if (a0 & 0x0100)
8234
lineOBJpix -= (10+sizeX);
8235
}
8236
continue;
8237
}
8238
8239
// else ignores OBJ-WIN if OBJWIN is disabled, and ignored disabled OBJ
8240
else if(((a0 & 0x0c00) == 0x0800) || ((a0 & 0x0300) == 0x0200))
8241
continue;
8242
8243
if(a0 & 0x0100)
8244
{
8245
u32 fieldX = sizeX;
8246
u32 fieldY = sizeY;
8247
if(a0 & 0x0200)
8248
{
8249
fieldX <<= 1;
8250
fieldY <<= 1;
8251
}
8252
if((sy+fieldY) > 256)
8253
sy -= 256;
8254
int t = io_registers[REG_VCOUNT] - sy;
8255
if(unsigned(t) < fieldY)
8256
{
8257
u32 startpix = 0;
8258
if ((sx+fieldX)> 512)
8259
startpix=512-sx;
8260
8261
if (lineOBJpix && ((sx < 240) || startpix))
8262
{
8263
lineOBJpix-=8;
8264
int rot = (((a1 >> 9) & 0x1F) << 4);
8265
u16 *OAM = (u16 *)oam;
8266
int dx = READ16LE(&OAM[3 + rot]);
8267
if(dx & 0x8000)
8268
dx |= 0xFFFF8000;
8269
int dmx = READ16LE(&OAM[7 + rot]);
8270
if(dmx & 0x8000)
8271
dmx |= 0xFFFF8000;
8272
int dy = READ16LE(&OAM[11 + rot]);
8273
if(dy & 0x8000)
8274
dy |= 0xFFFF8000;
8275
int dmy = READ16LE(&OAM[15 + rot]);
8276
if(dmy & 0x8000)
8277
dmy |= 0xFFFF8000;
8278
8279
if(a0 & 0x1000)
8280
t -= (t % mosaicY);
8281
8282
int realX = ((sizeX) << 7) - (fieldX >> 1)*dx + ((t - (fieldY>>1))* dmx);
8283
int realY = ((sizeY) << 7) - (fieldX >> 1)*dy + ((t - (fieldY>>1))* dmy);
8284
8285
u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
8286
8287
int c = (a2 & 0x3FF);
8288
if((io_registers[REG_DISPCNT] & 7) > 2 && (c < 512))
8289
continue;
8290
8291
if(a0 & 0x2000)
8292
{
8293
int inc = 32;
8294
if(io_registers[REG_DISPCNT] & 0x40)
8295
inc = sizeX >> 2;
8296
else
8297
c &= 0x3FE;
8298
for(u32 x = 0; x < fieldX; x++)
8299
{
8300
if (x >= startpix)
8301
lineOBJpix-=2;
8302
unsigned xxx = realX >> 8;
8303
unsigned yyy = realY >> 8;
8304
if(xxx < sizeX && yyy < sizeY && sx < 240)
8305
{
8306
8307
u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
8308
+ ((yyy & 7)<<3) + ((xxx >> 3)<<6) + (xxx & 7))&0x7FFF)];
8309
8310
if ((color==0) && (((prio >> 25)&3) < ((line[4][sx]>>25)&3)))
8311
{
8312
line[4][sx] = (line[4][sx] & 0xF9FFFFFF) | prio;
8313
if((a0 & 0x1000) && m)
8314
line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio;
8315
}
8316
else if((color) && (prio < (line[4][sx]&0xFF000000)))
8317
{
8318
line[4][sx] = READ16LE(&spritePalette[color]) | prio;
8319
if((a0 & 0x1000) && m)
8320
line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio;
8321
}
8322
8323
if ((a0 & 0x1000) && ((m+1) == mosaicX))
8324
m = 0;
8325
}
8326
sx = (sx+1)&511;
8327
realX += dx;
8328
realY += dy;
8329
}
8330
}
8331
else
8332
{
8333
int inc = 32;
8334
if(io_registers[REG_DISPCNT] & 0x40)
8335
inc = sizeX >> 3;
8336
int palette = (a2 >> 8) & 0xF0;
8337
for(u32 x = 0; x < fieldX; ++x)
8338
{
8339
if (x >= startpix)
8340
lineOBJpix-=2;
8341
unsigned xxx = realX >> 8;
8342
unsigned yyy = realY >> 8;
8343
if(xxx < sizeX && yyy < sizeY && sx < 240)
8344
{
8345
8346
u32 color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
8347
+ ((yyy & 7)<<2) + ((xxx >> 3)<<5)
8348
+ ((xxx & 7)>>1))&0x7FFF)];
8349
if(xxx & 1)
8350
color >>= 4;
8351
else
8352
color &= 0x0F;
8353
8354
if ((color==0) && (((prio >> 25)&3) <
8355
((line[4][sx]>>25)&3)))
8356
{
8357
line[4][sx] = (line[4][sx] & 0xF9FFFFFF) | prio;
8358
if((a0 & 0x1000) && m)
8359
line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio;
8360
}
8361
else if((color) && (prio < (line[4][sx]&0xFF000000)))
8362
{
8363
line[4][sx] = READ16LE(&spritePalette[palette+color]) | prio;
8364
if((a0 & 0x1000) && m)
8365
line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio;
8366
}
8367
}
8368
if((a0 & 0x1000) && m)
8369
{
8370
if (++m==mosaicX)
8371
m=0;
8372
}
8373
8374
sx = (sx+1)&511;
8375
realX += dx;
8376
realY += dy;
8377
8378
}
8379
}
8380
}
8381
}
8382
}
8383
else
8384
{
8385
if(sy+sizeY > 256)
8386
sy -= 256;
8387
int t = io_registers[REG_VCOUNT] - sy;
8388
if(unsigned(t) < sizeY)
8389
{
8390
u32 startpix = 0;
8391
if ((sx+sizeX)> 512)
8392
startpix=512-sx;
8393
8394
if((sx < 240) || startpix)
8395
{
8396
lineOBJpix+=2;
8397
8398
if(a1 & 0x2000)
8399
t = sizeY - t - 1;
8400
8401
int c = (a2 & 0x3FF);
8402
if((io_registers[REG_DISPCNT] & 7) > 2 && (c < 512))
8403
continue;
8404
8405
int inc = 32;
8406
int xxx = 0;
8407
if(a1 & 0x1000)
8408
xxx = sizeX-1;
8409
8410
if(a0 & 0x1000)
8411
t -= (t % mosaicY);
8412
8413
if(a0 & 0x2000)
8414
{
8415
if(io_registers[REG_DISPCNT] & 0x40)
8416
inc = sizeX >> 2;
8417
else
8418
c &= 0x3FE;
8419
8420
int address = 0x10000 + ((((c+ (t>>3) * inc) << 5)
8421
+ ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7)) & 0x7FFF);
8422
8423
if(a1 & 0x1000)
8424
xxx = 7;
8425
u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
8426
8427
for(u32 xx = 0; xx < sizeX; xx++)
8428
{
8429
if (xx >= startpix)
8430
--lineOBJpix;
8431
if(sx < 240)
8432
{
8433
u8 color = vram[address];
8434
if ((color==0) && (((prio >> 25)&3) <
8435
((line[4][sx]>>25)&3)))
8436
{
8437
line[4][sx] = (line[4][sx] & 0xF9FFFFFF) | prio;
8438
if((a0 & 0x1000) && m)
8439
line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio;
8440
}
8441
else if((color) && (prio < (line[4][sx]&0xFF000000)))
8442
{
8443
line[4][sx] = READ16LE(&spritePalette[color]) | prio;
8444
if((a0 & 0x1000) && m)
8445
line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio;
8446
}
8447
8448
if ((a0 & 0x1000) && ((m+1) == mosaicX))
8449
m = 0;
8450
}
8451
8452
sx = (sx+1) & 511;
8453
if(a1 & 0x1000)
8454
{
8455
--address;
8456
if(--xxx == -1)
8457
{
8458
address -= 56;
8459
xxx = 7;
8460
}
8461
if(address < 0x10000)
8462
address += 0x8000;
8463
}
8464
else
8465
{
8466
++address;
8467
if(++xxx == 8)
8468
{
8469
address += 56;
8470
xxx = 0;
8471
}
8472
if(address > 0x17fff)
8473
address -= 0x8000;
8474
}
8475
}
8476
}
8477
else
8478
{
8479
if(io_registers[REG_DISPCNT] & 0x40)
8480
inc = sizeX >> 3;
8481
8482
int address = 0x10000 + ((((c + (t>>3) * inc)<<5)
8483
+ ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7FFF);
8484
8485
u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
8486
int palette = (a2 >> 8) & 0xF0;
8487
if(a1 & 0x1000)
8488
{
8489
xxx = 7;
8490
int xx = sizeX - 1;
8491
do
8492
{
8493
if (xx >= (int)(startpix))
8494
--lineOBJpix;
8495
//if (lineOBJpix<0)
8496
// continue;
8497
if(sx < 240)
8498
{
8499
u8 color = vram[address];
8500
if(xx & 1)
8501
color >>= 4;
8502
else
8503
color &= 0x0F;
8504
8505
if ((color==0) && (((prio >> 25)&3) <
8506
((line[4][sx]>>25)&3)))
8507
{
8508
line[4][sx] = (line[4][sx] & 0xF9FFFFFF) | prio;
8509
if((a0 & 0x1000) && m)
8510
line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio;
8511
}
8512
else if((color) && (prio < (line[4][sx]&0xFF000000)))
8513
{
8514
line[4][sx] = READ16LE(&spritePalette[palette + color]) | prio;
8515
if((a0 & 0x1000) && m)
8516
line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio;
8517
}
8518
}
8519
8520
if ((a0 & 0x1000) && ((m+1) == mosaicX))
8521
m=0;
8522
8523
sx = (sx+1) & 511;
8524
if(!(xx & 1))
8525
--address;
8526
if(--xxx == -1)
8527
{
8528
xxx = 7;
8529
address -= 28;
8530
}
8531
if(address < 0x10000)
8532
address += 0x8000;
8533
}while(--xx >= 0);
8534
}
8535
else
8536
{
8537
for(u32 xx = 0; xx < sizeX; ++xx)
8538
{
8539
if (xx >= startpix)
8540
--lineOBJpix;
8541
//if (lineOBJpix<0)
8542
// continue;
8543
if(sx < 240)
8544
{
8545
u8 color = vram[address];
8546
if(xx & 1)
8547
color >>= 4;
8548
else
8549
color &= 0x0F;
8550
8551
if ((color==0) && (((prio >> 25)&3) <
8552
((line[4][sx]>>25)&3)))
8553
{
8554
line[4][sx] = (line[4][sx] & 0xF9FFFFFF) | prio;
8555
if((a0 & 0x1000) && m)
8556
line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio;
8557
}
8558
else if((color) && (prio < (line[4][sx]&0xFF000000)))
8559
{
8560
line[4][sx] = READ16LE(&spritePalette[palette + color]) | prio;
8561
if((a0 & 0x1000) && m)
8562
line[4][sx]=(line[4][sx-1] & 0xF9FFFFFF) | prio;
8563
8564
}
8565
}
8566
if ((a0 & 0x1000) && ((m+1) == mosaicX))
8567
m=0;
8568
8569
sx = (sx+1) & 511;
8570
if(xx & 1)
8571
++address;
8572
if(++xxx == 8)
8573
{
8574
address += 28;
8575
xxx = 0;
8576
}
8577
if(address > 0x17fff)
8578
address -= 0x8000;
8579
}
8580
}
8581
}
8582
}
8583
}
8584
}
8585
}
8586
}
8587
8588
INLINE void gfxDrawOBJWin (void)
8589
{
8590
u16 *sprites = (u16 *)oam;
8591
for(int x = 0; x < 128 ; x++)
8592
{
8593
int lineOBJpix = lineOBJpixleft[x];
8594
u16 a0 = READ16LE(sprites++);
8595
u16 a1 = READ16LE(sprites++);
8596
u16 a2 = READ16LE(sprites++);
8597
sprites++;
8598
8599
if (lineOBJpix<=0)
8600
return;
8601
8602
// ignores non OBJ-WIN and disabled OBJ-WIN
8603
if(((a0 & 0x0c00) != 0x0800) || ((a0 & 0x0300) == 0x0200))
8604
continue;
8605
8606
u16 a0val = a0>>14;
8607
8608
if ((a0 & 0x0c00) == 0x0c00)
8609
a0 &=0xF3FF;
8610
8611
if (a0val == 3)
8612
{
8613
a0 &= 0x3FFF;
8614
a1 &= 0x3FFF;
8615
}
8616
8617
int sizeX = 8<<(a1>>14);
8618
int sizeY = sizeX;
8619
8620
if (a0val & 1)
8621
{
8622
#ifdef BRANCHLESS_GBA_GFX
8623
sizeX <<= isel(-(sizeX & (~31u)), 1, 0);
8624
sizeY >>= isel(-(sizeY>8), 0, 1);
8625
#else
8626
if (sizeX<32)
8627
sizeX<<=1;
8628
if (sizeY>8)
8629
sizeY>>=1;
8630
#endif
8631
}
8632
else if (a0val & 2)
8633
{
8634
#ifdef BRANCHLESS_GBA_GFX
8635
sizeX >>= isel(-(sizeX>8), 0, 1);
8636
sizeY <<= isel(-(sizeY & (~31u)), 1, 0);
8637
#else
8638
if (sizeX>8)
8639
sizeX>>=1;
8640
if (sizeY<32)
8641
sizeY<<=1;
8642
#endif
8643
8644
}
8645
8646
int sy = (a0 & 255);
8647
8648
if(a0 & 0x0100)
8649
{
8650
int fieldX = sizeX;
8651
int fieldY = sizeY;
8652
if(a0 & 0x0200)
8653
{
8654
fieldX <<= 1;
8655
fieldY <<= 1;
8656
}
8657
if((sy+fieldY) > 256)
8658
sy -= 256;
8659
int t = io_registers[REG_VCOUNT] - sy;
8660
if((t >= 0) && (t < fieldY))
8661
{
8662
int sx = (a1 & 0x1FF);
8663
int startpix = 0;
8664
if ((sx+fieldX)> 512)
8665
startpix=512-sx;
8666
8667
if((sx < 240) || startpix)
8668
{
8669
lineOBJpix-=8;
8670
// int t2 = t - (fieldY >> 1);
8671
int rot = (a1 >> 9) & 0x1F;
8672
u16 *OAM = (u16 *)oam;
8673
int dx = READ16LE(&OAM[3 + (rot << 4)]);
8674
if(dx & 0x8000)
8675
dx |= 0xFFFF8000;
8676
int dmx = READ16LE(&OAM[7 + (rot << 4)]);
8677
if(dmx & 0x8000)
8678
dmx |= 0xFFFF8000;
8679
int dy = READ16LE(&OAM[11 + (rot << 4)]);
8680
if(dy & 0x8000)
8681
dy |= 0xFFFF8000;
8682
int dmy = READ16LE(&OAM[15 + (rot << 4)]);
8683
if(dmy & 0x8000)
8684
dmy |= 0xFFFF8000;
8685
8686
int realX = ((sizeX) << 7) - (fieldX >> 1)*dx - (fieldY>>1)*dmx
8687
+ t * dmx;
8688
int realY = ((sizeY) << 7) - (fieldX >> 1)*dy - (fieldY>>1)*dmy
8689
+ t * dmy;
8690
8691
int c = (a2 & 0x3FF);
8692
if((io_registers[REG_DISPCNT] & 7) > 2 && (c < 512))
8693
continue;
8694
8695
int inc = 32;
8696
bool condition1 = a0 & 0x2000;
8697
8698
if(io_registers[REG_DISPCNT] & 0x40)
8699
inc = sizeX >> 3;
8700
8701
for(int x = 0; x < fieldX; x++)
8702
{
8703
bool cont = true;
8704
if (x >= startpix)
8705
lineOBJpix-=2;
8706
if (lineOBJpix<0)
8707
continue;
8708
int xxx = realX >> 8;
8709
int yyy = realY >> 8;
8710
8711
if(xxx < 0 || xxx >= sizeX || yyy < 0 || yyy >= sizeY || sx >= 240)
8712
cont = false;
8713
8714
if(cont)
8715
{
8716
u32 color;
8717
if(condition1)
8718
color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
8719
+ ((yyy & 7)<<3) + ((xxx >> 3)<<6) +
8720
(xxx & 7))&0x7fff)];
8721
else
8722
{
8723
color = vram[0x10000 + ((((c + (yyy>>3) * inc)<<5)
8724
+ ((yyy & 7)<<2) + ((xxx >> 3)<<5) +
8725
((xxx & 7)>>1))&0x7fff)];
8726
if(xxx & 1)
8727
color >>= 4;
8728
else
8729
color &= 0x0F;
8730
}
8731
8732
if(color)
8733
line[5][sx] = 1;
8734
}
8735
sx = (sx+1)&511;
8736
realX += dx;
8737
realY += dy;
8738
}
8739
}
8740
}
8741
}
8742
else
8743
{
8744
if((sy+sizeY) > 256)
8745
sy -= 256;
8746
int t = io_registers[REG_VCOUNT] - sy;
8747
if((t >= 0) && (t < sizeY))
8748
{
8749
int sx = (a1 & 0x1FF);
8750
int startpix = 0;
8751
if ((sx+sizeX)> 512)
8752
startpix=512-sx;
8753
8754
if((sx < 240) || startpix)
8755
{
8756
lineOBJpix+=2;
8757
if(a1 & 0x2000)
8758
t = sizeY - t - 1;
8759
int c = (a2 & 0x3FF);
8760
if((io_registers[REG_DISPCNT] & 7) > 2 && (c < 512))
8761
continue;
8762
if(a0 & 0x2000)
8763
{
8764
8765
int inc = 32;
8766
if(io_registers[REG_DISPCNT] & 0x40)
8767
inc = sizeX >> 2;
8768
else
8769
c &= 0x3FE;
8770
8771
int xxx = 0;
8772
if(a1 & 0x1000)
8773
xxx = sizeX-1;
8774
int address = 0x10000 + ((((c+ (t>>3) * inc) << 5)
8775
+ ((t & 7) << 3) + ((xxx>>3)<<6) + (xxx & 7))&0x7fff);
8776
if(a1 & 0x1000)
8777
xxx = 7;
8778
for(int xx = 0; xx < sizeX; xx++)
8779
{
8780
if (xx >= startpix)
8781
lineOBJpix--;
8782
if (lineOBJpix<0)
8783
continue;
8784
if(sx < 240)
8785
{
8786
u8 color = vram[address];
8787
if(color)
8788
line[5][sx] = 1;
8789
}
8790
8791
sx = (sx+1) & 511;
8792
if(a1 & 0x1000) {
8793
xxx--;
8794
address--;
8795
if(xxx == -1) {
8796
address -= 56;
8797
xxx = 7;
8798
}
8799
if(address < 0x10000)
8800
address += 0x8000;
8801
} else {
8802
xxx++;
8803
address++;
8804
if(xxx == 8) {
8805
address += 56;
8806
xxx = 0;
8807
}
8808
if(address > 0x17fff)
8809
address -= 0x8000;
8810
}
8811
}
8812
}
8813
else
8814
{
8815
int inc = 32;
8816
if(io_registers[REG_DISPCNT] & 0x40)
8817
inc = sizeX >> 3;
8818
int xxx = 0;
8819
if(a1 & 0x1000)
8820
xxx = sizeX - 1;
8821
int address = 0x10000 + ((((c + (t>>3) * inc)<<5)
8822
+ ((t & 7)<<2) + ((xxx>>3)<<5) + ((xxx & 7) >> 1))&0x7fff);
8823
// u32 prio = (((a2 >> 10) & 3) << 25) | ((a0 & 0x0c00)<<6);
8824
// int palette = (a2 >> 8) & 0xF0;
8825
if(a1 & 0x1000)
8826
{
8827
xxx = 7;
8828
for(int xx = sizeX - 1; xx >= 0; xx--)
8829
{
8830
if (xx >= startpix)
8831
lineOBJpix--;
8832
if (lineOBJpix<0)
8833
continue;
8834
if(sx < 240)
8835
{
8836
u8 color = vram[address];
8837
if(xx & 1)
8838
color = (color >> 4);
8839
else
8840
color &= 0x0F;
8841
8842
if(color)
8843
line[5][sx] = 1;
8844
}
8845
sx = (sx+1) & 511;
8846
xxx--;
8847
if(!(xx & 1))
8848
address--;
8849
if(xxx == -1) {
8850
xxx = 7;
8851
address -= 28;
8852
}
8853
if(address < 0x10000)
8854
address += 0x8000;
8855
}
8856
}
8857
else
8858
{
8859
for(int xx = 0; xx < sizeX; xx++)
8860
{
8861
if (xx >= startpix)
8862
lineOBJpix--;
8863
if (lineOBJpix<0)
8864
continue;
8865
if(sx < 240)
8866
{
8867
u8 color = vram[address];
8868
if(xx & 1)
8869
color = (color >> 4);
8870
else
8871
color &= 0x0F;
8872
8873
if(color)
8874
line[5][sx] = 1;
8875
}
8876
sx = (sx+1) & 511;
8877
xxx++;
8878
if(xx & 1)
8879
address++;
8880
if(xxx == 8) {
8881
address += 28;
8882
xxx = 0;
8883
}
8884
if(address > 0x17fff)
8885
address -= 0x8000;
8886
}
8887
}
8888
}
8889
}
8890
}
8891
}
8892
}
8893
}
8894
8895
INLINE u32 gfxIncreaseBrightness(u32 color, int coeff)
8896
{
8897
color = (((color & 0xffff) << 16) | (color & 0xffff)) & 0x3E07C1F;
8898
8899
color += ((((0x3E07C1F - color) * coeff) >> 4) & 0x3E07C1F);
8900
8901
return (color >> 16) | color;
8902
}
8903
8904
INLINE u32 gfxDecreaseBrightness(u32 color, int coeff)
8905
{
8906
color = (((color & 0xffff) << 16) | (color & 0xffff)) & 0x3E07C1F;
8907
8908
color -= (((color * coeff) >> 4) & 0x3E07C1F);
8909
8910
return (color >> 16) | color;
8911
}
8912
8913
#define GFX_ALPHA_BLEND(color, color2, ca, cb) \
8914
int r = AlphaClampLUT[(((color & 0x1F) * ca) >> 4) + (((color2 & 0x1F) * cb) >> 4)]; \
8915
int g = AlphaClampLUT[((((color >> 5) & 0x1F) * ca) >> 4) + ((((color2 >> 5) & 0x1F) * cb) >> 4)]; \
8916
int b = AlphaClampLUT[((((color >> 10) & 0x1F) * ca) >> 4) + ((((color2 >> 10) & 0x1F) * cb) >> 4)]; \
8917
color = (color & 0xFFFF0000) | (b << 10) | (g << 5) | r;
8918
8919
/*============================================================
8920
GBA.CPP
8921
============================================================ */
8922
static const bool useBios = true;
8923
bool skipBios;
8924
// it's a few bytes in the linkscript to make a multiboot image work in normal boot as well,
8925
// and most of the ones i've seen have done that, so this is not terribly useful
8926
static const bool cpuIsMultiBoot = false;
8927
int cpuSaveType; // used only in init() to set up function pointers and for save file determination
8928
bool mirroringEnable;
8929
8930
int cpuDmaCount;
8931
8932
uint8_t bios[0x4000];
8933
uint8_t rom[0x2000000];
8934
uint8_t internalRAM[0x8000];
8935
uint8_t workRAM[0x40000];
8936
uint8_t vram[0x20000];
8937
u16 pix[2 * PIX_BUFFER_SCREEN_WIDTH * 160];
8938
uint8_t oam[0x400];
8939
uint8_t ioMem[0x400];
8940
8941
bool cpuEEPROMEnabled; // true to process writes to EEPROM at 0dxxxxxx
8942
bool cpuEEPROMSensorEnabled; // eeprom motion sensor? code is mostly disabled
8943
8944
#ifndef LSB_FIRST
8945
bool cpuBiosSwapped = false;
8946
#endif
8947
8948
INLINE int CPUUpdateTicks (void)
8949
{
8950
int cpuLoopTicks = graphics.lcdTicks;
8951
8952
if(timer0On && (timer0Ticks < cpuLoopTicks))
8953
cpuLoopTicks = timer0Ticks;
8954
8955
if(timer1On && !(io_registers[REG_TM1CNT] & 4) && (timer1Ticks < cpuLoopTicks))
8956
cpuLoopTicks = timer1Ticks;
8957
8958
if(timer2On && !(io_registers[REG_TM2CNT] & 4) && (timer2Ticks < cpuLoopTicks))
8959
cpuLoopTicks = timer2Ticks;
8960
8961
if(timer3On && !(io_registers[REG_TM3CNT] & 4) && (timer3Ticks < cpuLoopTicks))
8962
cpuLoopTicks = timer3Ticks;
8963
8964
if (IRQTicks)
8965
{
8966
if (IRQTicks < cpuLoopTicks)
8967
cpuLoopTicks = IRQTicks;
8968
}
8969
8970
return cpuLoopTicks;
8971
}
8972
8973
#define CPUUpdateWindow0() \
8974
{ \
8975
int x00_window0 = io_registers[REG_WIN0H] >>8; \
8976
int x01_window0 = io_registers[REG_WIN0H] & 255; \
8977
int x00_lte_x01 = x00_window0 <= x01_window0; \
8978
for(int i = 0; i < 240; i++) \
8979
gfxInWin[0][i] = ((i >= x00_window0 && i < x01_window0) & x00_lte_x01) | ((i >= x00_window0 || i < x01_window0) & ~x00_lte_x01); \
8980
}
8981
8982
#define CPUUpdateWindow1() \
8983
{ \
8984
int x00_window1 = io_registers[REG_WIN1H]>>8; \
8985
int x01_window1 = io_registers[REG_WIN1H] & 255; \
8986
int x00_lte_x01 = x00_window1 <= x01_window1; \
8987
for(int i = 0; i < 240; i++) \
8988
gfxInWin[1][i] = ((i >= x00_window1 && i < x01_window1) & x00_lte_x01) | ((i >= x00_window1 || i < x01_window1) & ~x00_lte_x01); \
8989
}
8990
8991
#define CPUCompareVCOUNT() \
8992
if(io_registers[REG_VCOUNT] == (io_registers[REG_DISPSTAT] >> 8)) \
8993
{ \
8994
io_registers[REG_DISPSTAT] |= 4; \
8995
UPDATE_REG(0x04, io_registers[REG_DISPSTAT]); \
8996
if(io_registers[REG_DISPSTAT] & 0x20) \
8997
{ \
8998
io_registers[REG_IF] |= 4; \
8999
UPDATE_REG(0x202, io_registers[REG_IF]); \
9000
} \
9001
} \
9002
else \
9003
{ \
9004
io_registers[REG_DISPSTAT] &= 0xFFFB; \
9005
UPDATE_REG(0x4, io_registers[REG_DISPSTAT]); \
9006
} \
9007
if (graphics.layerEnableDelay > 0) \
9008
{ \
9009
graphics.layerEnableDelay--; \
9010
if (graphics.layerEnableDelay == 1) \
9011
graphics.layerEnable = io_registers[REG_DISPCNT]; \
9012
}
9013
9014
int CPULoadRom(const u8 *romfile, const u32 romfilelen)
9015
{
9016
if (cpuIsMultiBoot)
9017
{
9018
if (romfilelen > 0x40000)
9019
return 0;
9020
}
9021
else
9022
{
9023
if (romfilelen > 0x2000000)
9024
return 0;
9025
}
9026
9027
uint8_t *whereToLoad = cpuIsMultiBoot ? workRAM : rom;
9028
9029
memcpy(whereToLoad, romfile, romfilelen);
9030
romSize = romfilelen;
9031
9032
uint16_t *temp = (uint16_t *)(rom+((romSize+1)&~1));
9033
int i;
9034
for(i = (romSize+1)&~1; i < 0x2000000; i+=2) {
9035
WRITE16LE(temp, (i >> 1) & 0xFFFF);
9036
temp++;
9037
}
9038
9039
9040
flashInit();
9041
eepromInit();
9042
9043
memset(line[0], -1, 240 * sizeof(u32));
9044
memset(line[1], -1, 240 * sizeof(u32));
9045
memset(line[2], -1, 240 * sizeof(u32));
9046
memset(line[3], -1, 240 * sizeof(u32));
9047
9048
return romSize;
9049
}
9050
9051
void doMirroring (bool b)
9052
{
9053
uint32_t mirroredRomSize = (((romSize)>>20) & 0x3F)<<20;
9054
uint32_t mirroredRomAddress = romSize;
9055
if ((mirroredRomSize <=0x800000) && (b))
9056
{
9057
mirroredRomAddress = mirroredRomSize;
9058
if (mirroredRomSize==0)
9059
mirroredRomSize=0x100000;
9060
while (mirroredRomAddress<0x01000000)
9061
{
9062
memcpy((uint16_t *)(rom+mirroredRomAddress), (uint16_t *)(rom), mirroredRomSize);
9063
mirroredRomAddress+=mirroredRomSize;
9064
}
9065
}
9066
}
9067
9068
#define brightness_switch() \
9069
switch((BLDMOD >> 6) & 3) \
9070
{ \
9071
case 2: \
9072
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]); \
9073
break; \
9074
case 3: \
9075
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]); \
9076
break; \
9077
}
9078
9079
#define alpha_blend_brightness_switch() \
9080
if(top2 & (BLDMOD>>8)) \
9081
if(color < 0x80000000) \
9082
{ \
9083
GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]); \
9084
} \
9085
else if(BLDMOD & top) \
9086
{ \
9087
brightness_switch(); \
9088
}
9089
9090
/* we only use 16bit color depth */
9091
#define INIT_COLOR_DEPTH_LINE_MIX() uint16_t * lineMix = (pix + PIX_BUFFER_SCREEN_WIDTH * io_registers[REG_VCOUNT])
9092
9093
void mode0RenderLine (void)
9094
{
9095
#ifdef REPORT_VIDEO_MODES
9096
fprintf(stderr, "MODE 0: Render Line\n");
9097
#endif
9098
INIT_COLOR_DEPTH_LINE_MIX();
9099
9100
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
9101
9102
if(graphics.layerEnable & 0x0100) {
9103
gfxDrawTextScreen(io_registers[REG_BG0CNT], io_registers[REG_BG0HOFS], io_registers[REG_BG0VOFS], line[0]);
9104
}
9105
9106
if(graphics.layerEnable & 0x0200) {
9107
gfxDrawTextScreen(io_registers[REG_BG1CNT], io_registers[REG_BG1HOFS], io_registers[REG_BG1VOFS], line[1]);
9108
}
9109
9110
if(graphics.layerEnable & 0x0400) {
9111
gfxDrawTextScreen(io_registers[REG_BG2CNT], io_registers[REG_BG2HOFS], io_registers[REG_BG2VOFS], line[2]);
9112
}
9113
9114
if(graphics.layerEnable & 0x0800) {
9115
gfxDrawTextScreen(io_registers[REG_BG3CNT], io_registers[REG_BG3HOFS], io_registers[REG_BG3VOFS], line[3]);
9116
}
9117
9118
9119
uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000);
9120
9121
for(int x = 0; x < 240; x++)
9122
{
9123
uint32_t color = backdrop;
9124
uint8_t top = 0x20;
9125
9126
if(line[0][x] < color) {
9127
color = line[0][x];
9128
top = 0x01;
9129
}
9130
9131
if((uint8_t)(line[1][x]>>24) < (uint8_t)(color >> 24)) {
9132
color = line[1][x];
9133
top = 0x02;
9134
}
9135
9136
if((uint8_t)(line[2][x]>>24) < (uint8_t)(color >> 24)) {
9137
color = line[2][x];
9138
top = 0x04;
9139
}
9140
9141
if((uint8_t)(line[3][x]>>24) < (uint8_t)(color >> 24)) {
9142
color = line[3][x];
9143
top = 0x08;
9144
}
9145
9146
if((uint8_t)(line[4][x]>>24) < (uint8_t)(color >> 24)) {
9147
color = line[4][x];
9148
top = 0x10;
9149
9150
if(color & 0x00010000) {
9151
// semi-transparent OBJ
9152
uint32_t back = backdrop;
9153
uint8_t top2 = 0x20;
9154
9155
if((uint8_t)(line[0][x]>>24) < (uint8_t)(back >> 24)) {
9156
back = line[0][x];
9157
top2 = 0x01;
9158
}
9159
9160
if((uint8_t)(line[1][x]>>24) < (uint8_t)(back >> 24)) {
9161
back = line[1][x];
9162
top2 = 0x02;
9163
}
9164
9165
if((uint8_t)(line[2][x]>>24) < (uint8_t)(back >> 24)) {
9166
back = line[2][x];
9167
top2 = 0x04;
9168
}
9169
9170
if((uint8_t)(line[3][x]>>24) < (uint8_t)(back >> 24)) {
9171
back = line[3][x];
9172
top2 = 0x08;
9173
}
9174
9175
alpha_blend_brightness_switch();
9176
}
9177
}
9178
9179
9180
lineMix[x] = CONVERT_COLOR(color);
9181
}
9182
}
9183
9184
void mode0RenderLineNoWindow (void)
9185
{
9186
#ifdef REPORT_VIDEO_MODES
9187
fprintf(stderr, "MODE 0: Render Line No Window\n");
9188
#endif
9189
INIT_COLOR_DEPTH_LINE_MIX();
9190
9191
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
9192
uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000);
9193
9194
if(graphics.layerEnable & 0x0100) {
9195
gfxDrawTextScreen(io_registers[REG_BG0CNT], io_registers[REG_BG0HOFS], io_registers[REG_BG0VOFS], line[0]);
9196
}
9197
9198
if(graphics.layerEnable & 0x0200) {
9199
gfxDrawTextScreen(io_registers[REG_BG1CNT], io_registers[REG_BG1HOFS], io_registers[REG_BG1VOFS], line[1]);
9200
}
9201
9202
if(graphics.layerEnable & 0x0400) {
9203
gfxDrawTextScreen(io_registers[REG_BG2CNT], io_registers[REG_BG2HOFS], io_registers[REG_BG2VOFS], line[2]);
9204
}
9205
9206
if(graphics.layerEnable & 0x0800) {
9207
gfxDrawTextScreen(io_registers[REG_BG3CNT], io_registers[REG_BG3HOFS], io_registers[REG_BG3VOFS], line[3]);
9208
}
9209
9210
int effect = (BLDMOD >> 6) & 3;
9211
9212
for(int x = 0; x < 240; x++) {
9213
uint32_t color = backdrop;
9214
uint8_t top = 0x20;
9215
9216
if(line[0][x] < color) {
9217
color = line[0][x];
9218
top = 0x01;
9219
}
9220
9221
if(line[1][x] < (color & 0xFF000000)) {
9222
color = line[1][x];
9223
top = 0x02;
9224
}
9225
9226
if(line[2][x] < (color & 0xFF000000)) {
9227
color = line[2][x];
9228
top = 0x04;
9229
}
9230
9231
if(line[3][x] < (color & 0xFF000000)) {
9232
color = line[3][x];
9233
top = 0x08;
9234
}
9235
9236
if(line[4][x] < (color & 0xFF000000)) {
9237
color = line[4][x];
9238
top = 0x10;
9239
}
9240
9241
if(!(color & 0x00010000)) {
9242
switch(effect) {
9243
case 0:
9244
break;
9245
case 1:
9246
if(top & BLDMOD)
9247
{
9248
uint32_t back = backdrop;
9249
uint8_t top2 = 0x20;
9250
if((line[0][x] < back) && (top != 0x01))
9251
{
9252
back = line[0][x];
9253
top2 = 0x01;
9254
}
9255
9256
if((line[1][x] < (back & 0xFF000000)) && (top != 0x02))
9257
{
9258
back = line[1][x];
9259
top2 = 0x02;
9260
}
9261
9262
if((line[2][x] < (back & 0xFF000000)) && (top != 0x04))
9263
{
9264
back = line[2][x];
9265
top2 = 0x04;
9266
}
9267
9268
if((line[3][x] < (back & 0xFF000000)) && (top != 0x08))
9269
{
9270
back = line[3][x];
9271
top2 = 0x08;
9272
}
9273
9274
if((line[4][x] < (back & 0xFF000000)) && (top != 0x10))
9275
{
9276
back = line[4][x];
9277
top2 = 0x10;
9278
}
9279
9280
if(top2 & (BLDMOD>>8) && color < 0x80000000)
9281
{
9282
GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
9283
}
9284
9285
}
9286
break;
9287
case 2:
9288
if(BLDMOD & top)
9289
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
9290
break;
9291
case 3:
9292
if(BLDMOD & top)
9293
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
9294
break;
9295
}
9296
} else {
9297
// semi-transparent OBJ
9298
uint32_t back = backdrop;
9299
uint8_t top2 = 0x20;
9300
9301
if(line[0][x] < back) {
9302
back = line[0][x];
9303
top2 = 0x01;
9304
}
9305
9306
if(line[1][x] < (back & 0xFF000000)) {
9307
back = line[1][x];
9308
top2 = 0x02;
9309
}
9310
9311
if(line[2][x] < (back & 0xFF000000)) {
9312
back = line[2][x];
9313
top2 = 0x04;
9314
}
9315
9316
if(line[3][x] < (back & 0xFF000000)) {
9317
back = line[3][x];
9318
top2 = 0x08;
9319
}
9320
9321
alpha_blend_brightness_switch();
9322
}
9323
9324
lineMix[x] = CONVERT_COLOR(color);
9325
}
9326
}
9327
9328
void mode0RenderLineAll (void)
9329
{
9330
#ifdef REPORT_VIDEO_MODES
9331
fprintf(stderr, "MODE 0: Render Line All\n");
9332
#endif
9333
INIT_COLOR_DEPTH_LINE_MIX();
9334
9335
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
9336
9337
bool inWindow0 = false;
9338
bool inWindow1 = false;
9339
9340
if(graphics.layerEnable & 0x2000) {
9341
uint8_t v0 = io_registers[REG_WIN0V] >> 8;
9342
uint8_t v1 = io_registers[REG_WIN0V] & 255;
9343
inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
9344
if(v1 >= v0)
9345
inWindow0 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1);
9346
else
9347
inWindow0 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1);
9348
}
9349
if(graphics.layerEnable & 0x4000) {
9350
uint8_t v0 = io_registers[REG_WIN1V] >> 8;
9351
uint8_t v1 = io_registers[REG_WIN1V] & 255;
9352
inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
9353
if(v1 >= v0)
9354
inWindow1 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1);
9355
else
9356
inWindow1 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1);
9357
}
9358
9359
if((graphics.layerEnable & 0x0100)) {
9360
gfxDrawTextScreen(io_registers[REG_BG0CNT], io_registers[REG_BG0HOFS], io_registers[REG_BG0VOFS], line[0]);
9361
}
9362
9363
if((graphics.layerEnable & 0x0200)) {
9364
gfxDrawTextScreen(io_registers[REG_BG1CNT], io_registers[REG_BG1HOFS], io_registers[REG_BG1VOFS], line[1]);
9365
}
9366
9367
if((graphics.layerEnable & 0x0400)) {
9368
gfxDrawTextScreen(io_registers[REG_BG2CNT], io_registers[REG_BG2HOFS], io_registers[REG_BG2VOFS], line[2]);
9369
}
9370
9371
if((graphics.layerEnable & 0x0800)) {
9372
gfxDrawTextScreen(io_registers[REG_BG3CNT], io_registers[REG_BG3HOFS], io_registers[REG_BG3VOFS], line[3]);
9373
}
9374
9375
uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000);
9376
9377
uint8_t inWin0Mask = io_registers[REG_WININ] & 0xFF;
9378
uint8_t inWin1Mask = io_registers[REG_WININ] >> 8;
9379
uint8_t outMask = io_registers[REG_WINOUT] & 0xFF;
9380
9381
for(int x = 0; x < 240; x++) {
9382
uint32_t color = backdrop;
9383
uint8_t top = 0x20;
9384
uint8_t mask = outMask;
9385
9386
if(!(line[5][x] & 0x80000000)) {
9387
mask = io_registers[REG_WINOUT] >> 8;
9388
}
9389
9390
int32_t window1_mask = ((inWindow1 & gfxInWin[1][x]) | -(inWindow1 & gfxInWin[1][x])) >> 31;
9391
int32_t window0_mask = ((inWindow0 & gfxInWin[0][x]) | -(inWindow0 & gfxInWin[0][x])) >> 31;
9392
mask = (inWin1Mask & window1_mask) | (mask & ~window1_mask);
9393
mask = (inWin0Mask & window0_mask) | (mask & ~window0_mask);
9394
9395
if((mask & 1) && (line[0][x] < color)) {
9396
color = line[0][x];
9397
top = 0x01;
9398
}
9399
9400
if((mask & 2) && ((uint8_t)(line[1][x]>>24) < (uint8_t)(color >> 24))) {
9401
color = line[1][x];
9402
top = 0x02;
9403
}
9404
9405
if((mask & 4) && ((uint8_t)(line[2][x]>>24) < (uint8_t)(color >> 24))) {
9406
color = line[2][x];
9407
top = 0x04;
9408
}
9409
9410
if((mask & 8) && ((uint8_t)(line[3][x]>>24) < (uint8_t)(color >> 24))) {
9411
color = line[3][x];
9412
top = 0x08;
9413
}
9414
9415
if((mask & 16) && ((uint8_t)(line[4][x]>>24) < (uint8_t)(color >> 24))) {
9416
color = line[4][x];
9417
top = 0x10;
9418
}
9419
9420
if(color & 0x00010000)
9421
{
9422
// semi-transparent OBJ
9423
uint32_t back = backdrop;
9424
uint8_t top2 = 0x20;
9425
9426
if((mask & 1) && ((uint8_t)(line[0][x]>>24) < (uint8_t)(back >> 24))) {
9427
back = line[0][x];
9428
top2 = 0x01;
9429
}
9430
9431
if((mask & 2) && ((uint8_t)(line[1][x]>>24) < (uint8_t)(back >> 24))) {
9432
back = line[1][x];
9433
top2 = 0x02;
9434
}
9435
9436
if((mask & 4) && ((uint8_t)(line[2][x]>>24) < (uint8_t)(back >> 24))) {
9437
back = line[2][x];
9438
top2 = 0x04;
9439
}
9440
9441
if((mask & 8) && ((uint8_t)(line[3][x]>>24) < (uint8_t)(back >> 24))) {
9442
back = line[3][x];
9443
top2 = 0x08;
9444
}
9445
9446
alpha_blend_brightness_switch();
9447
}
9448
else if((mask & 32) && (top & BLDMOD))
9449
{
9450
// special FX on in the window
9451
switch((BLDMOD >> 6) & 3)
9452
{
9453
case 0:
9454
break;
9455
case 1:
9456
{
9457
uint32_t back = backdrop;
9458
uint8_t top2 = 0x20;
9459
if(((mask & 1) && (uint8_t)(line[0][x]>>24) < (uint8_t)(back >> 24)) && top != 0x01)
9460
{
9461
back = line[0][x];
9462
top2 = 0x01;
9463
}
9464
9465
if(((mask & 2) && (uint8_t)(line[1][x]>>24) < (uint8_t)(back >> 24)) && top != 0x02)
9466
{
9467
back = line[1][x];
9468
top2 = 0x02;
9469
}
9470
9471
if(((mask & 4) && (uint8_t)(line[2][x]>>24) < (uint8_t)(back >> 24)) && top != 0x04)
9472
{
9473
back = line[2][x];
9474
top2 = 0x04;
9475
}
9476
9477
if(((mask & 8) && (uint8_t)(line[3][x]>>24) < (uint8_t)(back >> 24)) && top != 0x08)
9478
{
9479
back = line[3][x];
9480
top2 = 0x08;
9481
}
9482
9483
if(((mask & 16) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) && top != 0x10) {
9484
back = line[4][x];
9485
top2 = 0x10;
9486
}
9487
9488
if(top2 & (BLDMOD>>8) && color < 0x80000000)
9489
{
9490
GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
9491
}
9492
}
9493
break;
9494
case 2:
9495
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
9496
break;
9497
case 3:
9498
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
9499
break;
9500
}
9501
}
9502
9503
lineMix[x] = CONVERT_COLOR(color);
9504
}
9505
}
9506
9507
/*
9508
Mode 1 is a tiled graphics mode, but with background layer 2 supporting scaling and rotation.
9509
There is no layer 3 in this mode.
9510
Layers 0 and 1 can be either 16 colours (with 16 different palettes) or 256 colours.
9511
There are 1024 tiles available.
9512
Layer 2 is 256 colours and allows only 256 tiles.
9513
9514
These routines only render a single line at a time, because of the way the GBA does events.
9515
*/
9516
9517
void mode1RenderLine (void)
9518
{
9519
#ifdef REPORT_VIDEO_MODES
9520
fprintf(stderr, "MODE 1: Render Line\n");
9521
#endif
9522
INIT_COLOR_DEPTH_LINE_MIX();
9523
9524
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
9525
9526
if(graphics.layerEnable & 0x0100) {
9527
gfxDrawTextScreen(io_registers[REG_BG0CNT], io_registers[REG_BG0HOFS], io_registers[REG_BG0VOFS], line[0]);
9528
}
9529
9530
if(graphics.layerEnable & 0x0200) {
9531
gfxDrawTextScreen(io_registers[REG_BG1CNT], io_registers[REG_BG1HOFS], io_registers[REG_BG1VOFS], line[1]);
9532
}
9533
9534
if(graphics.layerEnable & 0x0400) {
9535
int changed = gfxBG2Changed;
9536
#if 0
9537
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
9538
changed = 3;
9539
#endif
9540
gfxDrawRotScreen(io_registers[REG_BG2CNT], BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
9541
io_registers[REG_BG2PA], io_registers[REG_BG2PB], io_registers[REG_BG2PC], io_registers[REG_BG2PD],
9542
gfxBG2X, gfxBG2Y, changed, line[2]);
9543
}
9544
9545
uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000);
9546
9547
for(uint32_t x = 0; x < 240u; ++x) {
9548
uint32_t color = backdrop;
9549
uint8_t top = 0x20;
9550
9551
uint8_t li1 = (uint8_t)(line[1][x]>>24);
9552
uint8_t li2 = (uint8_t)(line[2][x]>>24);
9553
uint8_t li4 = (uint8_t)(line[4][x]>>24);
9554
9555
uint8_t r = (li2 < li1) ? (li2) : (li1);
9556
9557
if(li4 < r){
9558
r = (li4);
9559
}
9560
9561
if(line[0][x] < backdrop) {
9562
color = line[0][x];
9563
top = 0x01;
9564
}
9565
9566
if(r < (uint8_t)(color >> 24)) {
9567
if(r == li1){
9568
color = line[1][x];
9569
top = 0x02;
9570
}else if(r == li2){
9571
color = line[2][x];
9572
top = 0x04;
9573
}else if(r == li4){
9574
color = line[4][x];
9575
top = 0x10;
9576
if((color & 0x00010000))
9577
{
9578
// semi-transparent OBJ
9579
uint32_t back = backdrop;
9580
uint8_t top2 = 0x20;
9581
9582
uint8_t li0 = (uint8_t)(line[0][x]>>24);
9583
uint8_t li1 = (uint8_t)(line[1][x]>>24);
9584
uint8_t li2 = (uint8_t)(line[2][x]>>24);
9585
uint8_t r = (li1 < li0) ? (li1) : (li0);
9586
9587
if(li2 < r) {
9588
r = (li2);
9589
}
9590
9591
if(r < (uint8_t)(back >> 24)) {
9592
if(r == li0){
9593
back = line[0][x];
9594
top2 = 0x01;
9595
}else if(r == li1){
9596
back = line[1][x];
9597
top2 = 0x02;
9598
}else if(r == li2){
9599
back = line[2][x];
9600
top2 = 0x04;
9601
}
9602
}
9603
9604
alpha_blend_brightness_switch();
9605
}
9606
}
9607
}
9608
9609
9610
lineMix[x] = CONVERT_COLOR(color);
9611
}
9612
gfxBG2Changed = 0;
9613
//gfxLastVCOUNT = io_registers[REG_VCOUNT];
9614
}
9615
9616
void mode1RenderLineNoWindow (void)
9617
{
9618
#ifdef REPORT_VIDEO_MODES
9619
fprintf(stderr, "MODE 1: Render Line No Window\n");
9620
#endif
9621
INIT_COLOR_DEPTH_LINE_MIX();
9622
9623
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
9624
9625
if(graphics.layerEnable & 0x0100) {
9626
gfxDrawTextScreen(io_registers[REG_BG0CNT], io_registers[REG_BG0HOFS], io_registers[REG_BG0VOFS], line[0]);
9627
}
9628
9629
9630
if(graphics.layerEnable & 0x0200) {
9631
gfxDrawTextScreen(io_registers[REG_BG1CNT], io_registers[REG_BG1HOFS], io_registers[REG_BG1VOFS], line[1]);
9632
}
9633
9634
if(graphics.layerEnable & 0x0400) {
9635
int changed = gfxBG2Changed;
9636
#if 0
9637
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
9638
changed = 3;
9639
#endif
9640
gfxDrawRotScreen(io_registers[REG_BG2CNT], BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
9641
io_registers[REG_BG2PA], io_registers[REG_BG2PB], io_registers[REG_BG2PC], io_registers[REG_BG2PD],
9642
gfxBG2X, gfxBG2Y, changed, line[2]);
9643
}
9644
9645
uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000);
9646
9647
for(int x = 0; x < 240; ++x) {
9648
uint32_t color = backdrop;
9649
uint8_t top = 0x20;
9650
9651
uint8_t li1 = (uint8_t)(line[1][x]>>24);
9652
uint8_t li2 = (uint8_t)(line[2][x]>>24);
9653
uint8_t li4 = (uint8_t)(line[4][x]>>24);
9654
9655
uint8_t r = (li2 < li1) ? (li2) : (li1);
9656
9657
if(li4 < r){
9658
r = (li4);
9659
}
9660
9661
if(line[0][x] < backdrop) {
9662
color = line[0][x];
9663
top = 0x01;
9664
}
9665
9666
if(r < (uint8_t)(color >> 24)) {
9667
if(r == li1){
9668
color = line[1][x];
9669
top = 0x02;
9670
}else if(r == li2){
9671
color = line[2][x];
9672
top = 0x04;
9673
}else if(r == li4){
9674
color = line[4][x];
9675
top = 0x10;
9676
}
9677
}
9678
9679
if(!(color & 0x00010000)) {
9680
switch((BLDMOD >> 6) & 3) {
9681
case 0:
9682
break;
9683
case 1:
9684
if(top & BLDMOD)
9685
{
9686
uint32_t back = backdrop;
9687
uint8_t top2 = 0x20;
9688
9689
if((top != 0x01) && (uint8_t)(line[0][x]>>24) < (uint8_t)(back >> 24)) {
9690
back = line[0][x];
9691
top2 = 0x01;
9692
}
9693
9694
if((top != 0x02) && (uint8_t)(line[1][x]>>24) < (uint8_t)(back >> 24)) {
9695
back = line[1][x];
9696
top2 = 0x02;
9697
}
9698
9699
if((top != 0x04) && (uint8_t)(line[2][x]>>24) < (uint8_t)(back >> 24)) {
9700
back = line[2][x];
9701
top2 = 0x04;
9702
}
9703
9704
if((top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) {
9705
back = line[4][x];
9706
top2 = 0x10;
9707
}
9708
9709
if(top2 & (BLDMOD>>8) && color < 0x80000000)
9710
{
9711
GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
9712
}
9713
}
9714
break;
9715
case 2:
9716
if(BLDMOD & top)
9717
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
9718
break;
9719
case 3:
9720
if(BLDMOD & top)
9721
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
9722
break;
9723
}
9724
} else {
9725
// semi-transparent OBJ
9726
uint32_t back = backdrop;
9727
uint8_t top2 = 0x20;
9728
9729
uint8_t li0 = (uint8_t)(line[0][x]>>24);
9730
uint8_t li1 = (uint8_t)(line[1][x]>>24);
9731
uint8_t li2 = (uint8_t)(line[2][x]>>24);
9732
9733
uint8_t r = (li1 < li0) ? (li1) : (li0);
9734
9735
if(li2 < r) {
9736
r = (li2);
9737
}
9738
9739
if(r < (uint8_t)(back >> 24))
9740
{
9741
if(r == li0)
9742
{
9743
back = line[0][x];
9744
top2 = 0x01;
9745
}
9746
else if(r == li1)
9747
{
9748
back = line[1][x];
9749
top2 = 0x02;
9750
}
9751
else if(r == li2)
9752
{
9753
back = line[2][x];
9754
top2 = 0x04;
9755
}
9756
}
9757
9758
alpha_blend_brightness_switch();
9759
}
9760
9761
lineMix[x] = CONVERT_COLOR(color);
9762
}
9763
gfxBG2Changed = 0;
9764
//gfxLastVCOUNT = io_registers[REG_VCOUNT];
9765
}
9766
9767
void mode1RenderLineAll (void)
9768
{
9769
#ifdef REPORT_VIDEO_MODES
9770
fprintf(stderr, "MODE 1: Render Line All\n");
9771
#endif
9772
INIT_COLOR_DEPTH_LINE_MIX();
9773
9774
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
9775
9776
bool inWindow0 = false;
9777
bool inWindow1 = false;
9778
9779
if(graphics.layerEnable & 0x2000)
9780
{
9781
uint8_t v0 = io_registers[REG_WIN0V] >> 8;
9782
uint8_t v1 = io_registers[REG_WIN0V] & 255;
9783
inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
9784
#ifndef ORIGINAL_BRANCHES
9785
uint32_t condition = v1 >= v0;
9786
int32_t condition_mask = ((condition) | -(condition)) >> 31;
9787
inWindow0 = (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask))));
9788
#else
9789
if(v1 >= v0)
9790
inWindow0 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1);
9791
else
9792
inWindow0 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1);
9793
#endif
9794
}
9795
if(graphics.layerEnable & 0x4000)
9796
{
9797
uint8_t v0 = io_registers[REG_WIN1V] >> 8;
9798
uint8_t v1 = io_registers[REG_WIN1V] & 255;
9799
inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
9800
#ifndef ORIGINAL_BRANCHES
9801
uint32_t condition = v1 >= v0;
9802
int32_t condition_mask = ((condition) | -(condition)) >> 31;
9803
inWindow1 = (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask))));
9804
#else
9805
if(v1 >= v0)
9806
inWindow1 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1);
9807
else
9808
inWindow1 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1);
9809
#endif
9810
}
9811
9812
if(graphics.layerEnable & 0x0100) {
9813
gfxDrawTextScreen(io_registers[REG_BG0CNT], io_registers[REG_BG0HOFS], io_registers[REG_BG0VOFS], line[0]);
9814
}
9815
9816
if(graphics.layerEnable & 0x0200) {
9817
gfxDrawTextScreen(io_registers[REG_BG1CNT], io_registers[REG_BG1HOFS], io_registers[REG_BG1VOFS], line[1]);
9818
}
9819
9820
if(graphics.layerEnable & 0x0400) {
9821
int changed = gfxBG2Changed;
9822
#if 0
9823
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
9824
changed = 3;
9825
#endif
9826
gfxDrawRotScreen(io_registers[REG_BG2CNT], BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
9827
io_registers[REG_BG2PA], io_registers[REG_BG2PB], io_registers[REG_BG2PC], io_registers[REG_BG2PD],
9828
gfxBG2X, gfxBG2Y, changed, line[2]);
9829
}
9830
9831
uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000);
9832
9833
uint8_t inWin0Mask = io_registers[REG_WININ] & 0xFF;
9834
uint8_t inWin1Mask = io_registers[REG_WININ] >> 8;
9835
uint8_t outMask = io_registers[REG_WINOUT] & 0xFF;
9836
9837
for(int x = 0; x < 240; ++x) {
9838
uint32_t color = backdrop;
9839
uint8_t top = 0x20;
9840
uint8_t mask = outMask;
9841
9842
if(!(line[5][x] & 0x80000000)) {
9843
mask = io_registers[REG_WINOUT] >> 8;
9844
}
9845
9846
int32_t window1_mask = ((inWindow1 & gfxInWin[1][x]) | -(inWindow1 & gfxInWin[1][x])) >> 31;
9847
int32_t window0_mask = ((inWindow0 & gfxInWin[0][x]) | -(inWindow0 & gfxInWin[0][x])) >> 31;
9848
mask = (inWin1Mask & window1_mask) | (mask & ~window1_mask);
9849
mask = (inWin0Mask & window0_mask) | (mask & ~window0_mask);
9850
9851
// At the very least, move the inexpensive 'mask' operation up front
9852
if((mask & 1) && line[0][x] < backdrop) {
9853
color = line[0][x];
9854
top = 0x01;
9855
}
9856
9857
if((mask & 2) && (uint8_t)(line[1][x]>>24) < (uint8_t)(color >> 24)) {
9858
color = line[1][x];
9859
top = 0x02;
9860
}
9861
9862
if((mask & 4) && (uint8_t)(line[2][x]>>24) < (uint8_t)(color >> 24)) {
9863
color = line[2][x];
9864
top = 0x04;
9865
}
9866
9867
if((mask & 16) && (uint8_t)(line[4][x]>>24) < (uint8_t)(color >> 24)) {
9868
color = line[4][x];
9869
top = 0x10;
9870
}
9871
9872
if(color & 0x00010000) {
9873
// semi-transparent OBJ
9874
uint32_t back = backdrop;
9875
uint8_t top2 = 0x20;
9876
9877
if((mask & 1) && (uint8_t)(line[0][x]>>24) < (uint8_t)(backdrop >> 24)) {
9878
back = line[0][x];
9879
top2 = 0x01;
9880
}
9881
9882
if((mask & 2) && (uint8_t)(line[1][x]>>24) < (uint8_t)(back >> 24)) {
9883
back = line[1][x];
9884
top2 = 0x02;
9885
}
9886
9887
if((mask & 4) && (uint8_t)(line[2][x]>>24) < (uint8_t)(back >> 24)) {
9888
back = line[2][x];
9889
top2 = 0x04;
9890
}
9891
9892
alpha_blend_brightness_switch();
9893
} else if(mask & 32) {
9894
// special FX on the window
9895
switch((BLDMOD >> 6) & 3) {
9896
case 0:
9897
break;
9898
case 1:
9899
if(top & BLDMOD)
9900
{
9901
uint32_t back = backdrop;
9902
uint8_t top2 = 0x20;
9903
9904
if((mask & 1) && (top != 0x01) && (uint8_t)(line[0][x]>>24) < (uint8_t)(backdrop >> 24)) {
9905
back = line[0][x];
9906
top2 = 0x01;
9907
}
9908
9909
if((mask & 2) && (top != 0x02) && (uint8_t)(line[1][x]>>24) < (uint8_t)(back >> 24)) {
9910
back = line[1][x];
9911
top2 = 0x02;
9912
}
9913
9914
if((mask & 4) && (top != 0x04) && (uint8_t)(line[2][x]>>24) < (uint8_t)(back >> 24)) {
9915
back = line[2][x];
9916
top2 = 0x04;
9917
}
9918
9919
if((mask & 16) && (top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) {
9920
back = line[4][x];
9921
top2 = 0x10;
9922
}
9923
9924
if(top2 & (BLDMOD>>8) && color < 0x80000000)
9925
{
9926
GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
9927
}
9928
}
9929
break;
9930
case 2:
9931
if(BLDMOD & top)
9932
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
9933
break;
9934
case 3:
9935
if(BLDMOD & top)
9936
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
9937
break;
9938
}
9939
}
9940
9941
lineMix[x] = CONVERT_COLOR(color);
9942
}
9943
gfxBG2Changed = 0;
9944
//gfxLastVCOUNT = io_registers[REG_VCOUNT];
9945
}
9946
9947
/*
9948
Mode 2 is a 256 colour tiled graphics mode which supports scaling and rotation.
9949
There is no background layer 0 or 1 in this mode. Only background layers 2 and 3.
9950
There are 256 tiles available.
9951
It does not support flipping.
9952
9953
These routines only render a single line at a time, because of the way the GBA does events.
9954
*/
9955
9956
void mode2RenderLine (void)
9957
{
9958
#ifdef REPORT_VIDEO_MODES
9959
fprintf(stderr, "MODE 2: Render Line\n");
9960
#endif
9961
INIT_COLOR_DEPTH_LINE_MIX();
9962
9963
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
9964
9965
if(graphics.layerEnable & 0x0400) {
9966
int changed = gfxBG2Changed;
9967
#if 0
9968
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
9969
changed = 3;
9970
#endif
9971
9972
gfxDrawRotScreen(io_registers[REG_BG2CNT], BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
9973
io_registers[REG_BG2PA], io_registers[REG_BG2PB], io_registers[REG_BG2PC], io_registers[REG_BG2PD], gfxBG2X, gfxBG2Y,
9974
changed, line[2]);
9975
}
9976
9977
if(graphics.layerEnable & 0x0800) {
9978
int changed = gfxBG3Changed;
9979
#if 0
9980
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
9981
changed = 3;
9982
#endif
9983
9984
gfxDrawRotScreen(io_registers[REG_BG3CNT], BG3X_L, BG3X_H, BG3Y_L, BG3Y_H,
9985
io_registers[REG_BG3PA], io_registers[REG_BG3PB], io_registers[REG_BG3PC], io_registers[REG_BG3PD], gfxBG3X, gfxBG3Y,
9986
changed, line[3]);
9987
}
9988
9989
uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000);
9990
9991
for(int x = 0; x < 240; ++x) {
9992
uint32_t color = backdrop;
9993
uint8_t top = 0x20;
9994
9995
uint8_t li2 = (uint8_t)(line[2][x]>>24);
9996
uint8_t li3 = (uint8_t)(line[3][x]>>24);
9997
uint8_t li4 = (uint8_t)(line[4][x]>>24);
9998
9999
uint8_t r = (li3 < li2) ? (li3) : (li2);
10000
10001
if(li4 < r){
10002
r = (li4);
10003
}
10004
10005
if(r < (uint8_t)(color >> 24)) {
10006
if(r == li2){
10007
color = line[2][x];
10008
top = 0x04;
10009
}else if(r == li3){
10010
color = line[3][x];
10011
top = 0x08;
10012
}else if(r == li4){
10013
color = line[4][x];
10014
top = 0x10;
10015
10016
if(color & 0x00010000) {
10017
// semi-transparent OBJ
10018
uint32_t back = backdrop;
10019
uint8_t top2 = 0x20;
10020
10021
uint8_t li2 = (uint8_t)(line[2][x]>>24);
10022
uint8_t li3 = (uint8_t)(line[3][x]>>24);
10023
uint8_t r = (li3 < li2) ? (li3) : (li2);
10024
10025
if(r < (uint8_t)(back >> 24)) {
10026
if(r == li2){
10027
back = line[2][x];
10028
top2 = 0x04;
10029
}else if(r == li3){
10030
back = line[3][x];
10031
top2 = 0x08;
10032
}
10033
}
10034
10035
alpha_blend_brightness_switch();
10036
}
10037
}
10038
}
10039
10040
10041
lineMix[x] = CONVERT_COLOR(color);
10042
}
10043
gfxBG2Changed = 0;
10044
gfxBG3Changed = 0;
10045
//gfxLastVCOUNT = io_registers[REG_VCOUNT];
10046
}
10047
10048
void mode2RenderLineNoWindow (void)
10049
{
10050
#ifdef REPORT_VIDEO_MODES
10051
fprintf(stderr, "MODE 2: Render Line No Window\n");
10052
#endif
10053
INIT_COLOR_DEPTH_LINE_MIX();
10054
10055
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
10056
10057
if(graphics.layerEnable & 0x0400) {
10058
int changed = gfxBG2Changed;
10059
#if 0
10060
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
10061
changed = 3;
10062
#endif
10063
10064
gfxDrawRotScreen(io_registers[REG_BG2CNT], BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
10065
io_registers[REG_BG2PA], io_registers[REG_BG2PB], io_registers[REG_BG2PC], io_registers[REG_BG2PD], gfxBG2X, gfxBG2Y,
10066
changed, line[2]);
10067
}
10068
10069
if(graphics.layerEnable & 0x0800) {
10070
int changed = gfxBG3Changed;
10071
#if 0
10072
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
10073
changed = 3;
10074
#endif
10075
10076
gfxDrawRotScreen(io_registers[REG_BG3CNT], BG3X_L, BG3X_H, BG3Y_L, BG3Y_H,
10077
io_registers[REG_BG3PA], io_registers[REG_BG3PB], io_registers[REG_BG3PC], io_registers[REG_BG3PD], gfxBG3X, gfxBG3Y,
10078
changed, line[3]);
10079
}
10080
10081
uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000);
10082
10083
for(int x = 0; x < 240; ++x) {
10084
uint32_t color = backdrop;
10085
uint8_t top = 0x20;
10086
10087
uint8_t li2 = (uint8_t)(line[2][x]>>24);
10088
uint8_t li3 = (uint8_t)(line[3][x]>>24);
10089
uint8_t li4 = (uint8_t)(line[4][x]>>24);
10090
10091
uint8_t r = (li3 < li2) ? (li3) : (li2);
10092
10093
if(li4 < r){
10094
r = (li4);
10095
}
10096
10097
if(r < (uint8_t)(color >> 24)) {
10098
if(r == li2){
10099
color = line[2][x];
10100
top = 0x04;
10101
}else if(r == li3){
10102
color = line[3][x];
10103
top = 0x08;
10104
}else if(r == li4){
10105
color = line[4][x];
10106
top = 0x10;
10107
}
10108
}
10109
10110
if(!(color & 0x00010000)) {
10111
switch((BLDMOD >> 6) & 3) {
10112
case 0:
10113
break;
10114
case 1:
10115
if(top & BLDMOD)
10116
{
10117
uint32_t back = backdrop;
10118
uint8_t top2 = 0x20;
10119
10120
if((top != 0x04) && (uint8_t)(line[2][x]>>24) < (uint8_t)(back >> 24)) {
10121
back = line[2][x];
10122
top2 = 0x04;
10123
}
10124
10125
if((top != 0x08) && (uint8_t)(line[3][x]>>24) < (uint8_t)(back >> 24)) {
10126
back = line[3][x];
10127
top2 = 0x08;
10128
}
10129
10130
if((top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) {
10131
back = line[4][x];
10132
top2 = 0x10;
10133
}
10134
10135
if(top2 & (BLDMOD>>8) && color < 0x80000000)
10136
{
10137
GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
10138
}
10139
}
10140
break;
10141
case 2:
10142
if(BLDMOD & top)
10143
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
10144
break;
10145
case 3:
10146
if(BLDMOD & top)
10147
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
10148
break;
10149
}
10150
} else {
10151
// semi-transparent OBJ
10152
uint32_t back = backdrop;
10153
uint8_t top2 = 0x20;
10154
10155
uint8_t li2 = (uint8_t)(line[2][x]>>24);
10156
uint8_t li3 = (uint8_t)(line[3][x]>>24);
10157
uint8_t r = (li3 < li2) ? (li3) : (li2);
10158
10159
if(r < (uint8_t)(back >> 24)) {
10160
if(r == li2){
10161
back = line[2][x];
10162
top2 = 0x04;
10163
}else if(r == li3){
10164
back = line[3][x];
10165
top2 = 0x08;
10166
}
10167
}
10168
10169
alpha_blend_brightness_switch();
10170
}
10171
10172
lineMix[x] = CONVERT_COLOR(color);
10173
}
10174
gfxBG2Changed = 0;
10175
gfxBG3Changed = 0;
10176
//gfxLastVCOUNT = io_registers[REG_VCOUNT];
10177
}
10178
10179
void mode2RenderLineAll (void)
10180
{
10181
#ifdef REPORT_VIDEO_MODES
10182
fprintf(stderr, "MODE 2: Render Line All\n");
10183
#endif
10184
INIT_COLOR_DEPTH_LINE_MIX();
10185
10186
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
10187
10188
bool inWindow0 = false;
10189
bool inWindow1 = false;
10190
10191
if(graphics.layerEnable & 0x2000)
10192
{
10193
uint8_t v0 = io_registers[REG_WIN0V] >> 8;
10194
uint8_t v1 = io_registers[REG_WIN0V] & 255;
10195
inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
10196
#ifndef ORIGINAL_BRANCHES
10197
uint32_t condition = v1 >= v0;
10198
int32_t condition_mask = ((condition) | -(condition)) >> 31;
10199
inWindow0 = (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask))));
10200
#else
10201
if(v1 >= v0)
10202
inWindow0 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1);
10203
else
10204
inWindow0 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1);
10205
#endif
10206
}
10207
if(graphics.layerEnable & 0x4000)
10208
{
10209
uint8_t v0 = io_registers[REG_WIN1V] >> 8;
10210
uint8_t v1 = io_registers[REG_WIN1V] & 255;
10211
inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
10212
#ifndef ORIGINAL_BRANCHES
10213
uint32_t condition = v1 >= v0;
10214
int32_t condition_mask = ((condition) | -(condition)) >> 31;
10215
inWindow1 = (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask))));
10216
#else
10217
if(v1 >= v0)
10218
inWindow1 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1);
10219
else
10220
inWindow1 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1);
10221
#endif
10222
}
10223
10224
if(graphics.layerEnable & 0x0400) {
10225
int changed = gfxBG2Changed;
10226
#if 0
10227
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
10228
changed = 3;
10229
#endif
10230
10231
gfxDrawRotScreen(io_registers[REG_BG2CNT], BG2X_L, BG2X_H, BG2Y_L, BG2Y_H,
10232
io_registers[REG_BG2PA], io_registers[REG_BG2PB], io_registers[REG_BG2PC], io_registers[REG_BG2PD], gfxBG2X, gfxBG2Y,
10233
changed, line[2]);
10234
}
10235
10236
if(graphics.layerEnable & 0x0800) {
10237
int changed = gfxBG3Changed;
10238
#if 0
10239
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
10240
changed = 3;
10241
#endif
10242
10243
gfxDrawRotScreen(io_registers[REG_BG3CNT], BG3X_L, BG3X_H, BG3Y_L, BG3Y_H,
10244
io_registers[REG_BG3PA], io_registers[REG_BG3PB], io_registers[REG_BG3PC], io_registers[REG_BG3PD], gfxBG3X, gfxBG3Y,
10245
changed, line[3]);
10246
}
10247
10248
uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000);
10249
10250
uint8_t inWin0Mask = io_registers[REG_WININ] & 0xFF;
10251
uint8_t inWin1Mask = io_registers[REG_WININ] >> 8;
10252
uint8_t outMask = io_registers[REG_WINOUT] & 0xFF;
10253
10254
for(int x = 0; x < 240; x++) {
10255
uint32_t color = backdrop;
10256
uint8_t top = 0x20;
10257
uint8_t mask = outMask;
10258
10259
if(!(line[5][x] & 0x80000000)) {
10260
mask = io_registers[REG_WINOUT] >> 8;
10261
}
10262
10263
int32_t window1_mask = ((inWindow1 & gfxInWin[1][x]) | -(inWindow1 & gfxInWin[1][x])) >> 31;
10264
int32_t window0_mask = ((inWindow0 & gfxInWin[0][x]) | -(inWindow0 & gfxInWin[0][x])) >> 31;
10265
mask = (inWin1Mask & window1_mask) | (mask & ~window1_mask);
10266
mask = (inWin0Mask & window0_mask) | (mask & ~window0_mask);
10267
10268
if((mask & 4) && line[2][x] < color) {
10269
color = line[2][x];
10270
top = 0x04;
10271
}
10272
10273
if((mask & 8) && (uint8_t)(line[3][x]>>24) < (uint8_t)(color >> 24)) {
10274
color = line[3][x];
10275
top = 0x08;
10276
}
10277
10278
if((mask & 16) && (uint8_t)(line[4][x]>>24) < (uint8_t)(color >> 24)) {
10279
color = line[4][x];
10280
top = 0x10;
10281
}
10282
10283
if(color & 0x00010000) {
10284
// semi-transparent OBJ
10285
uint32_t back = backdrop;
10286
uint8_t top2 = 0x20;
10287
10288
if((mask & 4) && line[2][x] < back) {
10289
back = line[2][x];
10290
top2 = 0x04;
10291
}
10292
10293
if((mask & 8) && (uint8_t)(line[3][x]>>24) < (uint8_t)(back >> 24)) {
10294
back = line[3][x];
10295
top2 = 0x08;
10296
}
10297
10298
alpha_blend_brightness_switch();
10299
} else if(mask & 32) {
10300
// special FX on the window
10301
switch((BLDMOD >> 6) & 3) {
10302
case 0:
10303
break;
10304
case 1:
10305
if(top & BLDMOD)
10306
{
10307
uint32_t back = backdrop;
10308
uint8_t top2 = 0x20;
10309
10310
if((mask & 4) && (top != 0x04) && line[2][x] < back) {
10311
back = line[2][x];
10312
top2 = 0x04;
10313
}
10314
10315
if((mask & 8) && (top != 0x08) && (uint8_t)(line[3][x]>>24) < (uint8_t)(back >> 24)) {
10316
back = line[3][x];
10317
top2 = 0x08;
10318
}
10319
10320
if((mask & 16) && (top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) {
10321
back = line[4][x];
10322
top2 = 0x10;
10323
}
10324
10325
if(top2 & (BLDMOD>>8) && color < 0x80000000)
10326
{
10327
GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
10328
}
10329
}
10330
break;
10331
case 2:
10332
if(BLDMOD & top)
10333
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
10334
break;
10335
case 3:
10336
if(BLDMOD & top)
10337
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
10338
break;
10339
}
10340
}
10341
10342
lineMix[x] = CONVERT_COLOR(color);
10343
}
10344
gfxBG2Changed = 0;
10345
gfxBG3Changed = 0;
10346
//gfxLastVCOUNT = io_registers[REG_VCOUNT];
10347
}
10348
10349
/*
10350
Mode 3 is a 15-bit (32768) colour bitmap graphics mode.
10351
It has a single layer, background layer 2, the same size as the screen.
10352
It doesn't support paging, scrolling, flipping, rotation or tiles.
10353
10354
These routines only render a single line at a time, because of the way the GBA does events.
10355
*/
10356
10357
void mode3RenderLine (void)
10358
{
10359
#ifdef REPORT_VIDEO_MODES
10360
fprintf(stderr, "MODE 3: Render Line\n");
10361
#endif
10362
INIT_COLOR_DEPTH_LINE_MIX();
10363
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
10364
10365
if(graphics.layerEnable & 0x0400) {
10366
int changed = gfxBG2Changed;
10367
10368
#if 0
10369
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
10370
changed = 3;
10371
#endif
10372
10373
gfxDrawRotScreen16Bit(gfxBG2X, gfxBG2Y, changed);
10374
}
10375
10376
uint32_t background = (READ16LE(&palette[0]) | 0x30000000);
10377
10378
for(int x = 0; x < 240; ++x) {
10379
uint32_t color = background;
10380
uint8_t top = 0x20;
10381
10382
if(line[2][x] < color) {
10383
color = line[2][x];
10384
top = 0x04;
10385
}
10386
10387
if((uint8_t)(line[4][x]>>24) < (uint8_t)(color >>24)) {
10388
color = line[4][x];
10389
top = 0x10;
10390
10391
if(color & 0x00010000) {
10392
// semi-transparent OBJ
10393
uint32_t back = background;
10394
uint8_t top2 = 0x20;
10395
10396
if(line[2][x] < background) {
10397
back = line[2][x];
10398
top2 = 0x04;
10399
}
10400
10401
alpha_blend_brightness_switch();
10402
}
10403
}
10404
10405
10406
lineMix[x] = CONVERT_COLOR(color);
10407
}
10408
gfxBG2Changed = 0;
10409
//gfxLastVCOUNT = io_registers[REG_VCOUNT];
10410
}
10411
10412
void mode3RenderLineNoWindow (void)
10413
{
10414
#ifdef REPORT_VIDEO_MODES
10415
fprintf(stderr, "MODE 3: Render Line No Window\n");
10416
#endif
10417
INIT_COLOR_DEPTH_LINE_MIX();
10418
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
10419
10420
if(graphics.layerEnable & 0x0400) {
10421
int changed = gfxBG2Changed;
10422
10423
#if 0
10424
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
10425
changed = 3;
10426
#endif
10427
10428
gfxDrawRotScreen16Bit(gfxBG2X, gfxBG2Y, changed);
10429
}
10430
10431
uint32_t background = (READ16LE(&palette[0]) | 0x30000000);
10432
10433
for(int x = 0; x < 240; ++x) {
10434
uint32_t color = background;
10435
uint8_t top = 0x20;
10436
10437
if(line[2][x] < background) {
10438
color = line[2][x];
10439
top = 0x04;
10440
}
10441
10442
if((uint8_t)(line[4][x]>>24) < (uint8_t)(color >>24)) {
10443
color = line[4][x];
10444
top = 0x10;
10445
}
10446
10447
if(!(color & 0x00010000)) {
10448
switch((BLDMOD >> 6) & 3) {
10449
case 0:
10450
break;
10451
case 1:
10452
if(top & BLDMOD)
10453
{
10454
uint32_t back = background;
10455
uint8_t top2 = 0x20;
10456
10457
if(top != 0x04 && (line[2][x] < background) ) {
10458
back = line[2][x];
10459
top2 = 0x04;
10460
}
10461
10462
if(top != 0x10 && ((uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24))) {
10463
back = line[4][x];
10464
top2 = 0x10;
10465
}
10466
10467
if(top2 & (BLDMOD>>8) && color < 0x80000000)
10468
{
10469
GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
10470
}
10471
10472
}
10473
break;
10474
case 2:
10475
if(BLDMOD & top)
10476
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
10477
break;
10478
case 3:
10479
if(BLDMOD & top)
10480
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
10481
break;
10482
}
10483
} else {
10484
// semi-transparent OBJ
10485
uint32_t back = background;
10486
uint8_t top2 = 0x20;
10487
10488
if(line[2][x] < background) {
10489
back = line[2][x];
10490
top2 = 0x04;
10491
}
10492
10493
alpha_blend_brightness_switch();
10494
}
10495
10496
lineMix[x] = CONVERT_COLOR(color);
10497
}
10498
gfxBG2Changed = 0;
10499
//gfxLastVCOUNT = io_registers[REG_VCOUNT];
10500
}
10501
10502
void mode3RenderLineAll (void)
10503
{
10504
#ifdef REPORT_VIDEO_MODES
10505
fprintf(stderr, "MODE 3: Render Line All\n");
10506
#endif
10507
INIT_COLOR_DEPTH_LINE_MIX();
10508
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
10509
10510
bool inWindow0 = false;
10511
bool inWindow1 = false;
10512
10513
if(graphics.layerEnable & 0x2000)
10514
{
10515
uint8_t v0 = io_registers[REG_WIN0V] >> 8;
10516
uint8_t v1 = io_registers[REG_WIN0V] & 255;
10517
inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
10518
#ifndef ORIGINAL_BRANCHES
10519
uint32_t condition = v1 >= v0;
10520
int32_t condition_mask = ((condition) | -(condition)) >> 31;
10521
inWindow0 = (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask))));
10522
#else
10523
if(v1 >= v0)
10524
inWindow0 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1);
10525
else
10526
inWindow0 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1);
10527
#endif
10528
}
10529
10530
if(graphics.layerEnable & 0x4000)
10531
{
10532
uint8_t v0 = io_registers[REG_WIN1V] >> 8;
10533
uint8_t v1 = io_registers[REG_WIN1V] & 255;
10534
inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
10535
#ifndef ORIGINAL_BRANCHES
10536
uint32_t condition = v1 >= v0;
10537
int32_t condition_mask = ((condition) | -(condition)) >> 31;
10538
inWindow1 = (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask))));
10539
#else
10540
if(v1 >= v0)
10541
inWindow1 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1);
10542
else
10543
inWindow1 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1);
10544
#endif
10545
}
10546
10547
if(graphics.layerEnable & 0x0400) {
10548
int changed = gfxBG2Changed;
10549
10550
#if 0
10551
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
10552
changed = 3;
10553
#endif
10554
10555
gfxDrawRotScreen16Bit(gfxBG2X, gfxBG2Y, changed);
10556
}
10557
10558
uint8_t inWin0Mask = io_registers[REG_WININ] & 0xFF;
10559
uint8_t inWin1Mask = io_registers[REG_WININ] >> 8;
10560
uint8_t outMask = io_registers[REG_WINOUT] & 0xFF;
10561
10562
uint32_t background = (READ16LE(&palette[0]) | 0x30000000);
10563
10564
for(int x = 0; x < 240; ++x) {
10565
uint32_t color = background;
10566
uint8_t top = 0x20;
10567
uint8_t mask = outMask;
10568
10569
if(!(line[5][x] & 0x80000000)) {
10570
mask = io_registers[REG_WINOUT] >> 8;
10571
}
10572
10573
int32_t window1_mask = ((inWindow1 & gfxInWin[1][x]) | -(inWindow1 & gfxInWin[1][x])) >> 31;
10574
int32_t window0_mask = ((inWindow0 & gfxInWin[0][x]) | -(inWindow0 & gfxInWin[0][x])) >> 31;
10575
mask = (inWin1Mask & window1_mask) | (mask & ~window1_mask);
10576
mask = (inWin0Mask & window0_mask) | (mask & ~window0_mask);
10577
10578
if((mask & 4) && line[2][x] < background) {
10579
color = line[2][x];
10580
top = 0x04;
10581
}
10582
10583
if((mask & 16) && ((uint8_t)(line[4][x]>>24) < (uint8_t)(color >>24))) {
10584
color = line[4][x];
10585
top = 0x10;
10586
}
10587
10588
if(color & 0x00010000) {
10589
// semi-transparent OBJ
10590
uint32_t back = background;
10591
uint8_t top2 = 0x20;
10592
10593
if((mask & 4) && line[2][x] < background) {
10594
back = line[2][x];
10595
top2 = 0x04;
10596
}
10597
10598
alpha_blend_brightness_switch();
10599
} else if(mask & 32) {
10600
switch((BLDMOD >> 6) & 3) {
10601
case 0:
10602
break;
10603
case 1:
10604
if(top & BLDMOD)
10605
{
10606
uint32_t back = background;
10607
uint8_t top2 = 0x20;
10608
10609
if((mask & 4) && (top != 0x04) && line[2][x] < back) {
10610
back = line[2][x];
10611
top2 = 0x04;
10612
}
10613
10614
if((mask & 16) && (top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) {
10615
back = line[4][x];
10616
top2 = 0x10;
10617
}
10618
10619
if(top2 & (BLDMOD>>8) && color < 0x80000000)
10620
{
10621
GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
10622
}
10623
}
10624
break;
10625
case 2:
10626
if(BLDMOD & top)
10627
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
10628
break;
10629
case 3:
10630
if(BLDMOD & top)
10631
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
10632
break;
10633
}
10634
}
10635
10636
lineMix[x] = CONVERT_COLOR(color);
10637
}
10638
gfxBG2Changed = 0;
10639
//gfxLastVCOUNT = io_registers[REG_VCOUNT];
10640
}
10641
10642
/*
10643
Mode 4 is a 256 colour bitmap graphics mode with 2 swappable pages.
10644
It has a single layer, background layer 2, the same size as the screen.
10645
It doesn't support scrolling, flipping, rotation or tiles.
10646
10647
These routines only render a single line at a time, because of the way the GBA does events.
10648
*/
10649
10650
void mode4RenderLine (void)
10651
{
10652
#ifdef REPORT_VIDEO_MODES
10653
fprintf(stderr, "MODE 4: Render Line\n");
10654
#endif
10655
INIT_COLOR_DEPTH_LINE_MIX();
10656
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
10657
10658
if(graphics.layerEnable & 0x400)
10659
{
10660
int changed = gfxBG2Changed;
10661
10662
#if 0
10663
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
10664
changed = 3;
10665
#endif
10666
10667
gfxDrawRotScreen256(gfxBG2X, gfxBG2Y, changed);
10668
}
10669
10670
uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000);
10671
10672
for(int x = 0; x < 240; ++x)
10673
{
10674
uint32_t color = backdrop;
10675
uint8_t top = 0x20;
10676
10677
if(line[2][x] < backdrop) {
10678
color = line[2][x];
10679
top = 0x04;
10680
}
10681
10682
if((uint8_t)(line[4][x]>>24) < (uint8_t)(color >> 24)) {
10683
color = line[4][x];
10684
top = 0x10;
10685
10686
if(color & 0x00010000) {
10687
// semi-transparent OBJ
10688
uint32_t back = backdrop;
10689
uint8_t top2 = 0x20;
10690
10691
if(line[2][x] < backdrop) {
10692
back = line[2][x];
10693
top2 = 0x04;
10694
}
10695
10696
alpha_blend_brightness_switch();
10697
}
10698
}
10699
10700
10701
lineMix[x] = CONVERT_COLOR(color);
10702
}
10703
gfxBG2Changed = 0;
10704
//gfxLastVCOUNT = io_registers[REG_VCOUNT];
10705
}
10706
10707
void mode4RenderLineNoWindow (void)
10708
{
10709
#ifdef REPORT_VIDEO_MODES
10710
fprintf(stderr, "MODE 4: Render Line No Window\n");
10711
#endif
10712
INIT_COLOR_DEPTH_LINE_MIX();
10713
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
10714
10715
if(graphics.layerEnable & 0x400)
10716
{
10717
int changed = gfxBG2Changed;
10718
10719
#if 0
10720
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
10721
changed = 3;
10722
#endif
10723
10724
gfxDrawRotScreen256(gfxBG2X, gfxBG2Y, changed);
10725
}
10726
10727
uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000);
10728
10729
for(int x = 0; x < 240; ++x)
10730
{
10731
uint32_t color = backdrop;
10732
uint8_t top = 0x20;
10733
10734
if(line[2][x] < backdrop) {
10735
color = line[2][x];
10736
top = 0x04;
10737
}
10738
10739
if((uint8_t)(line[4][x]>>24) < (uint8_t)(color >> 24)) {
10740
color = line[4][x];
10741
top = 0x10;
10742
}
10743
10744
if(!(color & 0x00010000)) {
10745
switch((BLDMOD >> 6) & 3) {
10746
case 0:
10747
break;
10748
case 1:
10749
if(top & BLDMOD)
10750
{
10751
uint32_t back = backdrop;
10752
uint8_t top2 = 0x20;
10753
10754
if((top != 0x04) && line[2][x] < backdrop) {
10755
back = line[2][x];
10756
top2 = 0x04;
10757
}
10758
10759
if((top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) {
10760
back = line[4][x];
10761
top2 = 0x10;
10762
}
10763
10764
if(top2 & (BLDMOD>>8) && color < 0x80000000)
10765
{
10766
GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
10767
}
10768
}
10769
break;
10770
case 2:
10771
if(BLDMOD & top)
10772
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
10773
break;
10774
case 3:
10775
if(BLDMOD & top)
10776
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
10777
break;
10778
}
10779
} else {
10780
// semi-transparent OBJ
10781
uint32_t back = backdrop;
10782
uint8_t top2 = 0x20;
10783
10784
if(line[2][x] < back) {
10785
back = line[2][x];
10786
top2 = 0x04;
10787
}
10788
10789
alpha_blend_brightness_switch();
10790
}
10791
10792
lineMix[x] = CONVERT_COLOR(color);
10793
}
10794
gfxBG2Changed = 0;
10795
//gfxLastVCOUNT = io_registers[REG_VCOUNT];
10796
}
10797
10798
void mode4RenderLineAll (void)
10799
{
10800
#ifdef REPORT_VIDEO_MODES
10801
fprintf(stderr, "MODE 4: Render Line All\n");
10802
#endif
10803
INIT_COLOR_DEPTH_LINE_MIX();
10804
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
10805
10806
bool inWindow0 = false;
10807
bool inWindow1 = false;
10808
10809
if(graphics.layerEnable & 0x2000)
10810
{
10811
uint8_t v0 = io_registers[REG_WIN0V] >> 8;
10812
uint8_t v1 = io_registers[REG_WIN0V] & 255;
10813
inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
10814
#ifndef ORIGINAL_BRANCHES
10815
uint32_t condition = v1 >= v0;
10816
int32_t condition_mask = ((condition) | -(condition)) >> 31;
10817
inWindow0 = (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask))));
10818
#else
10819
if(v1 >= v0)
10820
inWindow0 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1);
10821
else
10822
inWindow0 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1);
10823
#endif
10824
}
10825
10826
if(graphics.layerEnable & 0x4000)
10827
{
10828
uint8_t v0 = io_registers[REG_WIN1V] >> 8;
10829
uint8_t v1 = io_registers[REG_WIN1V] & 255;
10830
inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
10831
#ifndef ORIGINAL_BRANCHES
10832
uint32_t condition = v1 >= v0;
10833
int32_t condition_mask = ((condition) | -(condition)) >> 31;
10834
inWindow1 = (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask))));
10835
#else
10836
if(v1 >= v0)
10837
inWindow1 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1);
10838
else
10839
inWindow1 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1);
10840
#endif
10841
}
10842
10843
if(graphics.layerEnable & 0x400)
10844
{
10845
int changed = gfxBG2Changed;
10846
10847
#if 0
10848
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
10849
changed = 3;
10850
#endif
10851
10852
gfxDrawRotScreen256(gfxBG2X, gfxBG2Y, changed);
10853
}
10854
10855
uint32_t backdrop = (READ16LE(&palette[0]) | 0x30000000);
10856
10857
uint8_t inWin0Mask = io_registers[REG_WININ] & 0xFF;
10858
uint8_t inWin1Mask = io_registers[REG_WININ] >> 8;
10859
uint8_t outMask = io_registers[REG_WINOUT] & 0xFF;
10860
10861
for(int x = 0; x < 240; ++x) {
10862
uint32_t color = backdrop;
10863
uint8_t top = 0x20;
10864
uint8_t mask = outMask;
10865
10866
if(!(line[5][x] & 0x80000000))
10867
mask = io_registers[REG_WINOUT] >> 8;
10868
10869
int32_t window1_mask = ((inWindow1 & gfxInWin[1][x]) | -(inWindow1 & gfxInWin[1][x])) >> 31;
10870
int32_t window0_mask = ((inWindow0 & gfxInWin[0][x]) | -(inWindow0 & gfxInWin[0][x])) >> 31;
10871
mask = (inWin1Mask & window1_mask) | (mask & ~window1_mask);
10872
mask = (inWin0Mask & window0_mask) | (mask & ~window0_mask);
10873
10874
if((mask & 4) && (line[2][x] < backdrop))
10875
{
10876
color = line[2][x];
10877
top = 0x04;
10878
}
10879
10880
if((mask & 16) && ((uint8_t)(line[4][x]>>24) < (uint8_t)(color >>24)))
10881
{
10882
color = line[4][x];
10883
top = 0x10;
10884
}
10885
10886
if(color & 0x00010000) {
10887
// semi-transparent OBJ
10888
uint32_t back = backdrop;
10889
uint8_t top2 = 0x20;
10890
10891
if((mask & 4) && line[2][x] < back) {
10892
back = line[2][x];
10893
top2 = 0x04;
10894
}
10895
10896
alpha_blend_brightness_switch();
10897
} else if(mask & 32) {
10898
switch((BLDMOD >> 6) & 3) {
10899
case 0:
10900
break;
10901
case 1:
10902
if(top & BLDMOD)
10903
{
10904
uint32_t back = backdrop;
10905
uint8_t top2 = 0x20;
10906
10907
if((mask & 4) && (top != 0x04) && (line[2][x] < backdrop)) {
10908
back = line[2][x];
10909
top2 = 0x04;
10910
}
10911
10912
if((mask & 16) && (top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) {
10913
back = line[4][x];
10914
top2 = 0x10;
10915
}
10916
10917
if(top2 & (BLDMOD>>8) && color < 0x80000000)
10918
{
10919
GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
10920
}
10921
}
10922
break;
10923
case 2:
10924
if(BLDMOD & top)
10925
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
10926
break;
10927
case 3:
10928
if(BLDMOD & top)
10929
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
10930
break;
10931
}
10932
}
10933
10934
lineMix[x] = CONVERT_COLOR(color);
10935
}
10936
gfxBG2Changed = 0;
10937
//gfxLastVCOUNT = io_registers[REG_VCOUNT];
10938
}
10939
10940
/*
10941
Mode 5 is a low resolution (160x128) 15-bit colour bitmap graphics mode
10942
with 2 swappable pages!
10943
It has a single layer, background layer 2, lower resolution than the screen.
10944
It doesn't support scrolling, flipping, rotation or tiles.
10945
10946
These routines only render a single line at a time, because of the way the GBA does events.
10947
*/
10948
10949
void mode5RenderLine (void)
10950
{
10951
#ifdef REPORT_VIDEO_MODES
10952
fprintf(stderr, "MODE 5: Render Line\n");
10953
#endif
10954
INIT_COLOR_DEPTH_LINE_MIX();
10955
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
10956
10957
if(graphics.layerEnable & 0x0400) {
10958
int changed = gfxBG2Changed;
10959
10960
#if 0
10961
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
10962
changed = 3;
10963
#endif
10964
10965
gfxDrawRotScreen16Bit160(gfxBG2X, gfxBG2Y, changed);
10966
}
10967
10968
uint32_t background;
10969
background = (READ16LE(&palette[0]) | 0x30000000);
10970
10971
for(int x = 0; x < 240; ++x) {
10972
uint32_t color = background;
10973
uint8_t top = 0x20;
10974
10975
if(line[2][x] < background) {
10976
color = line[2][x];
10977
top = 0x04;
10978
}
10979
10980
if((uint8_t)(line[4][x]>>24) < (uint8_t)(color >>24)) {
10981
color = line[4][x];
10982
top = 0x10;
10983
10984
if(color & 0x00010000) {
10985
// semi-transparent OBJ
10986
uint32_t back = background;
10987
uint8_t top2 = 0x20;
10988
10989
if(line[2][x] < back) {
10990
back = line[2][x];
10991
top2 = 0x04;
10992
}
10993
10994
alpha_blend_brightness_switch();
10995
}
10996
}
10997
10998
10999
lineMix[x] = CONVERT_COLOR(color);
11000
}
11001
gfxBG2Changed = 0;
11002
//gfxLastVCOUNT = io_registers[REG_VCOUNT];
11003
}
11004
11005
void mode5RenderLineNoWindow (void)
11006
{
11007
#ifdef REPORT_VIDEO_MODES
11008
fprintf(stderr, "MODE 5: Render Line No Window\n");
11009
#endif
11010
INIT_COLOR_DEPTH_LINE_MIX();
11011
11012
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
11013
11014
if(graphics.layerEnable & 0x0400) {
11015
int changed = gfxBG2Changed;
11016
11017
#if 0
11018
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
11019
changed = 3;
11020
#endif
11021
11022
gfxDrawRotScreen16Bit160(gfxBG2X, gfxBG2Y, changed);
11023
}
11024
11025
uint32_t background;
11026
background = (READ16LE(&palette[0]) | 0x30000000);
11027
11028
for(int x = 0; x < 240; ++x) {
11029
uint32_t color = background;
11030
uint8_t top = 0x20;
11031
11032
if(line[2][x] < background) {
11033
color = line[2][x];
11034
top = 0x04;
11035
}
11036
11037
if((uint8_t)(line[4][x]>>24) < (uint8_t)(color >>24)) {
11038
color = line[4][x];
11039
top = 0x10;
11040
}
11041
11042
if(!(color & 0x00010000)) {
11043
switch((BLDMOD >> 6) & 3) {
11044
case 0:
11045
break;
11046
case 1:
11047
if(top & BLDMOD)
11048
{
11049
uint32_t back = background;
11050
uint8_t top2 = 0x20;
11051
11052
if((top != 0x04) && line[2][x] < background) {
11053
back = line[2][x];
11054
top2 = 0x04;
11055
}
11056
11057
if((top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) {
11058
back = line[4][x];
11059
top2 = 0x10;
11060
}
11061
11062
if(top2 & (BLDMOD>>8) && color < 0x80000000)
11063
{
11064
GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
11065
}
11066
11067
}
11068
break;
11069
case 2:
11070
if(BLDMOD & top)
11071
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
11072
break;
11073
case 3:
11074
if(BLDMOD & top)
11075
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
11076
break;
11077
}
11078
} else {
11079
// semi-transparent OBJ
11080
uint32_t back = background;
11081
uint8_t top2 = 0x20;
11082
11083
if(line[2][x] < back) {
11084
back = line[2][x];
11085
top2 = 0x04;
11086
}
11087
11088
alpha_blend_brightness_switch();
11089
}
11090
11091
lineMix[x] = CONVERT_COLOR(color);
11092
}
11093
gfxBG2Changed = 0;
11094
//gfxLastVCOUNT = io_registers[REG_VCOUNT];
11095
}
11096
11097
void mode5RenderLineAll (void)
11098
{
11099
#ifdef REPORT_VIDEO_MODES
11100
fprintf(stderr, "MODE 5: Render Line All\n");
11101
#endif
11102
INIT_COLOR_DEPTH_LINE_MIX();
11103
11104
uint16_t *palette = (uint16_t *)graphics.paletteRAM;
11105
11106
if(graphics.layerEnable & 0x0400)
11107
{
11108
int changed = gfxBG2Changed;
11109
11110
#if 0
11111
if(gfxLastVCOUNT > io_registers[REG_VCOUNT])
11112
changed = 3;
11113
#endif
11114
11115
gfxDrawRotScreen16Bit160(gfxBG2X, gfxBG2Y, changed);
11116
}
11117
11118
11119
11120
bool inWindow0 = false;
11121
bool inWindow1 = false;
11122
11123
if(graphics.layerEnable & 0x2000)
11124
{
11125
uint8_t v0 = io_registers[REG_WIN0V] >> 8;
11126
uint8_t v1 = io_registers[REG_WIN0V] & 255;
11127
inWindow0 = ((v0 == v1) && (v0 >= 0xe8));
11128
#ifndef ORIGINAL_BRANCHES
11129
uint32_t condition = v1 >= v0;
11130
int32_t condition_mask = ((condition) | -(condition)) >> 31;
11131
inWindow0 = (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow0 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask))));
11132
#else
11133
if(v1 >= v0)
11134
inWindow0 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1);
11135
else
11136
inWindow0 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1);
11137
#endif
11138
}
11139
11140
if(graphics.layerEnable & 0x4000)
11141
{
11142
uint8_t v0 = io_registers[REG_WIN1V] >> 8;
11143
uint8_t v1 = io_registers[REG_WIN1V] & 255;
11144
inWindow1 = ((v0 == v1) && (v0 >= 0xe8));
11145
#ifndef ORIGINAL_BRANCHES
11146
uint32_t condition = v1 >= v0;
11147
int32_t condition_mask = ((condition) | -(condition)) >> 31;
11148
inWindow1 = (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1)) & condition_mask) | (((inWindow1 | (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1)) & ~(condition_mask))));
11149
#else
11150
if(v1 >= v0)
11151
inWindow1 |= (io_registers[REG_VCOUNT] >= v0 && io_registers[REG_VCOUNT] < v1);
11152
else
11153
inWindow1 |= (io_registers[REG_VCOUNT] >= v0 || io_registers[REG_VCOUNT] < v1);
11154
#endif
11155
}
11156
11157
uint8_t inWin0Mask = io_registers[REG_WININ] & 0xFF;
11158
uint8_t inWin1Mask = io_registers[REG_WININ] >> 8;
11159
uint8_t outMask = io_registers[REG_WINOUT] & 0xFF;
11160
11161
uint32_t background;
11162
background = (READ16LE(&palette[0]) | 0x30000000);
11163
11164
for(int x = 0; x < 240; ++x) {
11165
uint32_t color = background;
11166
uint8_t top = 0x20;
11167
uint8_t mask = outMask;
11168
11169
if(!(line[5][x] & 0x80000000)) {
11170
mask = io_registers[REG_WINOUT] >> 8;
11171
}
11172
11173
int32_t window1_mask = ((inWindow1 & gfxInWin[1][x]) | -(inWindow1 & gfxInWin[1][x])) >> 31;
11174
int32_t window0_mask = ((inWindow0 & gfxInWin[0][x]) | -(inWindow0 & gfxInWin[0][x])) >> 31;
11175
mask = (inWin1Mask & window1_mask) | (mask & ~window1_mask);
11176
mask = (inWin0Mask & window0_mask) | (mask & ~window0_mask);
11177
11178
if((mask & 4) && (line[2][x] < background)) {
11179
color = line[2][x];
11180
top = 0x04;
11181
}
11182
11183
if((mask & 16) && ((uint8_t)(line[4][x]>>24) < (uint8_t)(color >>24))) {
11184
color = line[4][x];
11185
top = 0x10;
11186
}
11187
11188
if(color & 0x00010000) {
11189
// semi-transparent OBJ
11190
uint32_t back = background;
11191
uint8_t top2 = 0x20;
11192
11193
if((mask & 4) && line[2][x] < back) {
11194
back = line[2][x];
11195
top2 = 0x04;
11196
}
11197
11198
alpha_blend_brightness_switch();
11199
} else if(mask & 32) {
11200
switch((BLDMOD >> 6) & 3) {
11201
case 0:
11202
break;
11203
case 1:
11204
if(top & BLDMOD)
11205
{
11206
uint32_t back = background;
11207
uint8_t top2 = 0x20;
11208
11209
if((mask & 4) && (top != 0x04) && (line[2][x] < background)) {
11210
back = line[2][x];
11211
top2 = 0x04;
11212
}
11213
11214
if((mask & 16) && (top != 0x10) && (uint8_t)(line[4][x]>>24) < (uint8_t)(back >> 24)) {
11215
back = line[4][x];
11216
top2 = 0x10;
11217
}
11218
11219
if(top2 & (BLDMOD>>8) && color < 0x80000000)
11220
{
11221
GFX_ALPHA_BLEND(color, back, coeff[COLEV & 0x1F], coeff[(COLEV >> 8) & 0x1F]);
11222
}
11223
}
11224
break;
11225
case 2:
11226
if(BLDMOD & top)
11227
color = gfxIncreaseBrightness(color, coeff[COLY & 0x1F]);
11228
break;
11229
case 3:
11230
if(BLDMOD & top)
11231
color = gfxDecreaseBrightness(color, coeff[COLY & 0x1F]);
11232
break;
11233
}
11234
}
11235
11236
lineMix[x] = CONVERT_COLOR(color);
11237
}
11238
gfxBG2Changed = 0;
11239
//gfxLastVCOUNT = io_registers[REG_VCOUNT];
11240
}
11241
11242
void (Gigazoid::*renderLine)(void);
11243
bool render_line_all_enabled;
11244
11245
#define CPUUpdateRender() \
11246
render_line_all_enabled = false; \
11247
switch(io_registers[REG_DISPCNT] & 7) { \
11248
case 0: \
11249
if((!fxOn && !windowOn && !(graphics.layerEnable & 0x8000))) \
11250
renderLine = &Gigazoid::mode0RenderLine; \
11251
else if(fxOn && !windowOn && !(graphics.layerEnable & 0x8000)) \
11252
renderLine = &Gigazoid::mode0RenderLineNoWindow; \
11253
else { \
11254
renderLine = &Gigazoid::mode0RenderLineAll; \
11255
render_line_all_enabled = true; \
11256
} \
11257
break; \
11258
case 1: \
11259
if((!fxOn && !windowOn && !(graphics.layerEnable & 0x8000))) \
11260
renderLine = &Gigazoid::mode1RenderLine; \
11261
else if(fxOn && !windowOn && !(graphics.layerEnable & 0x8000)) \
11262
renderLine = &Gigazoid::mode1RenderLineNoWindow; \
11263
else { \
11264
renderLine = &Gigazoid::mode1RenderLineAll; \
11265
render_line_all_enabled = true; \
11266
} \
11267
break; \
11268
case 2: \
11269
if((!fxOn && !windowOn && !(graphics.layerEnable & 0x8000))) \
11270
renderLine = &Gigazoid::mode2RenderLine; \
11271
else if(fxOn && !windowOn && !(graphics.layerEnable & 0x8000)) \
11272
renderLine = &Gigazoid::mode2RenderLineNoWindow; \
11273
else { \
11274
renderLine = &Gigazoid::mode2RenderLineAll; \
11275
render_line_all_enabled = true; \
11276
} \
11277
break; \
11278
case 3: \
11279
if((!fxOn && !windowOn && !(graphics.layerEnable & 0x8000))) \
11280
renderLine = &Gigazoid::mode3RenderLine; \
11281
else if(fxOn && !windowOn && !(graphics.layerEnable & 0x8000)) \
11282
renderLine = &Gigazoid::mode3RenderLineNoWindow; \
11283
else { \
11284
renderLine = &Gigazoid::mode3RenderLineAll; \
11285
render_line_all_enabled = true; \
11286
} \
11287
break; \
11288
case 4: \
11289
if((!fxOn && !windowOn && !(graphics.layerEnable & 0x8000))) \
11290
renderLine = &Gigazoid::mode4RenderLine; \
11291
else if(fxOn && !windowOn && !(graphics.layerEnable & 0x8000)) \
11292
renderLine = &Gigazoid::mode4RenderLineNoWindow; \
11293
else { \
11294
renderLine = &Gigazoid::mode4RenderLineAll; \
11295
render_line_all_enabled = true; \
11296
} \
11297
break; \
11298
case 5: \
11299
if((!fxOn && !windowOn && !(graphics.layerEnable & 0x8000))) \
11300
renderLine = &Gigazoid::mode5RenderLine; \
11301
else if(fxOn && !windowOn && !(graphics.layerEnable & 0x8000)) \
11302
renderLine = &Gigazoid::mode5RenderLineNoWindow; \
11303
else { \
11304
renderLine = &Gigazoid::mode5RenderLineAll; \
11305
render_line_all_enabled = true; \
11306
} \
11307
}
11308
11309
#define CPUSwap(a, b) \
11310
a ^= b; \
11311
b ^= a; \
11312
a ^= b;
11313
11314
void CPUSwitchMode(int mode, bool saveState, bool breakLoop)
11315
{
11316
CPU_UPDATE_CPSR();
11317
11318
switch(armMode) {
11319
case 0x10:
11320
case 0x1F:
11321
bus.reg[R13_USR].I = bus.reg[13].I;
11322
bus.reg[R14_USR].I = bus.reg[14].I;
11323
bus.reg[17].I = bus.reg[16].I;
11324
break;
11325
case 0x11:
11326
CPUSwap(bus.reg[R8_FIQ].I, bus.reg[8].I);
11327
CPUSwap(bus.reg[R9_FIQ].I, bus.reg[9].I);
11328
CPUSwap(bus.reg[R10_FIQ].I, bus.reg[10].I);
11329
CPUSwap(bus.reg[R11_FIQ].I, bus.reg[11].I);
11330
CPUSwap(bus.reg[R12_FIQ].I, bus.reg[12].I);
11331
bus.reg[R13_FIQ].I = bus.reg[13].I;
11332
bus.reg[R14_FIQ].I = bus.reg[14].I;
11333
bus.reg[SPSR_FIQ].I = bus.reg[17].I;
11334
break;
11335
case 0x12:
11336
bus.reg[R13_IRQ].I = bus.reg[13].I;
11337
bus.reg[R14_IRQ].I = bus.reg[14].I;
11338
bus.reg[SPSR_IRQ].I = bus.reg[17].I;
11339
break;
11340
case 0x13:
11341
bus.reg[R13_SVC].I = bus.reg[13].I;
11342
bus.reg[R14_SVC].I = bus.reg[14].I;
11343
bus.reg[SPSR_SVC].I = bus.reg[17].I;
11344
break;
11345
case 0x17:
11346
bus.reg[R13_ABT].I = bus.reg[13].I;
11347
bus.reg[R14_ABT].I = bus.reg[14].I;
11348
bus.reg[SPSR_ABT].I = bus.reg[17].I;
11349
break;
11350
case 0x1b:
11351
bus.reg[R13_UND].I = bus.reg[13].I;
11352
bus.reg[R14_UND].I = bus.reg[14].I;
11353
bus.reg[SPSR_UND].I = bus.reg[17].I;
11354
break;
11355
}
11356
11357
uint32_t CPSR = bus.reg[16].I;
11358
uint32_t SPSR = bus.reg[17].I;
11359
11360
switch(mode) {
11361
case 0x10:
11362
case 0x1F:
11363
bus.reg[13].I = bus.reg[R13_USR].I;
11364
bus.reg[14].I = bus.reg[R14_USR].I;
11365
bus.reg[16].I = SPSR;
11366
break;
11367
case 0x11:
11368
CPUSwap(bus.reg[8].I, bus.reg[R8_FIQ].I);
11369
CPUSwap(bus.reg[9].I, bus.reg[R9_FIQ].I);
11370
CPUSwap(bus.reg[10].I, bus.reg[R10_FIQ].I);
11371
CPUSwap(bus.reg[11].I, bus.reg[R11_FIQ].I);
11372
CPUSwap(bus.reg[12].I, bus.reg[R12_FIQ].I);
11373
bus.reg[13].I = bus.reg[R13_FIQ].I;
11374
bus.reg[14].I = bus.reg[R14_FIQ].I;
11375
if(saveState)
11376
bus.reg[17].I = CPSR; else
11377
bus.reg[17].I = bus.reg[SPSR_FIQ].I;
11378
break;
11379
case 0x12:
11380
bus.reg[13].I = bus.reg[R13_IRQ].I;
11381
bus.reg[14].I = bus.reg[R14_IRQ].I;
11382
bus.reg[16].I = SPSR;
11383
if(saveState)
11384
bus.reg[17].I = CPSR;
11385
else
11386
bus.reg[17].I = bus.reg[SPSR_IRQ].I;
11387
break;
11388
case 0x13:
11389
bus.reg[13].I = bus.reg[R13_SVC].I;
11390
bus.reg[14].I = bus.reg[R14_SVC].I;
11391
bus.reg[16].I = SPSR;
11392
if(saveState)
11393
bus.reg[17].I = CPSR;
11394
else
11395
bus.reg[17].I = bus.reg[SPSR_SVC].I;
11396
break;
11397
case 0x17:
11398
bus.reg[13].I = bus.reg[R13_ABT].I;
11399
bus.reg[14].I = bus.reg[R14_ABT].I;
11400
bus.reg[16].I = SPSR;
11401
if(saveState)
11402
bus.reg[17].I = CPSR;
11403
else
11404
bus.reg[17].I = bus.reg[SPSR_ABT].I;
11405
break;
11406
case 0x1b:
11407
bus.reg[13].I = bus.reg[R13_UND].I;
11408
bus.reg[14].I = bus.reg[R14_UND].I;
11409
bus.reg[16].I = SPSR;
11410
if(saveState)
11411
bus.reg[17].I = CPSR;
11412
else
11413
bus.reg[17].I = bus.reg[SPSR_UND].I;
11414
break;
11415
default:
11416
break;
11417
}
11418
armMode = mode;
11419
CPUUpdateFlags(breakLoop);
11420
CPU_UPDATE_CPSR();
11421
}
11422
11423
11424
11425
void doDMA(uint32_t &s, uint32_t &d, uint32_t si, uint32_t di, uint32_t c, int transfer32)
11426
{
11427
int sm = s >> 24;
11428
int dm = d >> 24;
11429
int sw = 0;
11430
int dw = 0;
11431
int sc = c;
11432
11433
cpuDmaCount = c;
11434
// This is done to get the correct waitstates.
11435
int32_t sm_gt_15_mask = ((sm>15) | -(sm>15)) >> 31;
11436
int32_t dm_gt_15_mask = ((dm>15) | -(dm>15)) >> 31;
11437
sm = ((((15) & sm_gt_15_mask) | ((((sm) & ~(sm_gt_15_mask))))));
11438
dm = ((((15) & dm_gt_15_mask) | ((((dm) & ~(dm_gt_15_mask))))));
11439
11440
//if ((sm>=0x05) && (sm<=0x07) || (dm>=0x05) && (dm <=0x07))
11441
// blank = (((io_registers[REG_DISPSTAT] | ((io_registers[REG_DISPSTAT] >> 1)&1))==1) ? true : false);
11442
11443
if(transfer32)
11444
{
11445
s &= 0xFFFFFFFC;
11446
if(s < 0x02000000 && (bus.reg[15].I >> 24))
11447
{
11448
do
11449
{
11450
CPUWriteMemory(d, 0);
11451
d += di;
11452
c--;
11453
}while(c != 0);
11454
}
11455
else
11456
{
11457
do {
11458
CPUWriteMemory(d, CPUReadMemory(s));
11459
d += di;
11460
s += si;
11461
c--;
11462
}while(c != 0);
11463
}
11464
}
11465
else
11466
{
11467
s &= 0xFFFFFFFE;
11468
si = (int)si >> 1;
11469
di = (int)di >> 1;
11470
if(s < 0x02000000 && (bus.reg[15].I >> 24))
11471
{
11472
do {
11473
CPUWriteHalfWord(d, 0);
11474
d += di;
11475
c--;
11476
}while(c != 0);
11477
}
11478
else
11479
{
11480
do{
11481
CPUWriteHalfWord(d, CPUReadHalfWord(s));
11482
d += di;
11483
s += si;
11484
c--;
11485
}while(c != 0);
11486
}
11487
}
11488
11489
cpuDmaCount = 0;
11490
11491
if(transfer32)
11492
{
11493
sw = 1+memoryWaitSeq32[sm & 15];
11494
dw = 1+memoryWaitSeq32[dm & 15];
11495
cpuDmaTicksToUpdate += (sw+dw)*(sc-1) + 6 + memoryWait32[sm & 15] + memoryWaitSeq32[dm & 15];
11496
}
11497
else
11498
{
11499
sw = 1+memoryWaitSeq[sm & 15];
11500
dw = 1+memoryWaitSeq[dm & 15];
11501
cpuDmaTicksToUpdate += (sw+dw)*(sc-1) + 6 + memoryWait[sm & 15] + memoryWaitSeq[dm & 15];
11502
}
11503
}
11504
11505
11506
void CPUCheckDMA(int reason, int dmamask)
11507
{
11508
uint32_t arrayval[] = {4, (uint32_t)-4, 0, 4};
11509
// DMA 0
11510
if((DM0CNT_H & 0x8000) && (dmamask & 1))
11511
{
11512
if(((DM0CNT_H >> 12) & 3) == reason)
11513
{
11514
uint32_t sourceIncrement, destIncrement;
11515
uint32_t condition1 = ((DM0CNT_H >> 7) & 3);
11516
uint32_t condition2 = ((DM0CNT_H >> 5) & 3);
11517
sourceIncrement = arrayval[condition1];
11518
destIncrement = arrayval[condition2];
11519
doDMA(dma0Source, dma0Dest, sourceIncrement, destIncrement,
11520
DM0CNT_L ? DM0CNT_L : 0x4000,
11521
DM0CNT_H & 0x0400);
11522
11523
if(DM0CNT_H & 0x4000)
11524
{
11525
io_registers[REG_IF] |= 0x0100;
11526
UPDATE_REG(0x202, io_registers[REG_IF]);
11527
cpuNextEvent = cpuTotalTicks;
11528
}
11529
11530
if(((DM0CNT_H >> 5) & 3) == 3) {
11531
dma0Dest = DM0DAD_L | (DM0DAD_H << 16);
11532
}
11533
11534
if(!(DM0CNT_H & 0x0200) || (reason == 0)) {
11535
DM0CNT_H &= 0x7FFF;
11536
UPDATE_REG(0xBA, DM0CNT_H);
11537
}
11538
}
11539
}
11540
11541
// DMA 1
11542
if((DM1CNT_H & 0x8000) && (dmamask & 2)) {
11543
if(((DM1CNT_H >> 12) & 3) == reason) {
11544
uint32_t sourceIncrement, destIncrement;
11545
uint32_t condition1 = ((DM1CNT_H >> 7) & 3);
11546
uint32_t condition2 = ((DM1CNT_H >> 5) & 3);
11547
sourceIncrement = arrayval[condition1];
11548
destIncrement = arrayval[condition2];
11549
uint32_t di_value, c_value, transfer_value;
11550
if(reason == 3)
11551
{
11552
di_value = 0;
11553
c_value = 4;
11554
transfer_value = 0x0400;
11555
}
11556
else
11557
{
11558
di_value = destIncrement;
11559
c_value = DM1CNT_L ? DM1CNT_L : 0x4000;
11560
transfer_value = DM1CNT_H & 0x0400;
11561
}
11562
doDMA(dma1Source, dma1Dest, sourceIncrement, di_value, c_value, transfer_value);
11563
11564
if(DM1CNT_H & 0x4000) {
11565
io_registers[REG_IF] |= 0x0200;
11566
UPDATE_REG(0x202, io_registers[REG_IF]);
11567
cpuNextEvent = cpuTotalTicks;
11568
}
11569
11570
if(((DM1CNT_H >> 5) & 3) == 3) {
11571
dma1Dest = DM1DAD_L | (DM1DAD_H << 16);
11572
}
11573
11574
if(!(DM1CNT_H & 0x0200) || (reason == 0)) {
11575
DM1CNT_H &= 0x7FFF;
11576
UPDATE_REG(0xC6, DM1CNT_H);
11577
}
11578
}
11579
}
11580
11581
// DMA 2
11582
if((DM2CNT_H & 0x8000) && (dmamask & 4)) {
11583
if(((DM2CNT_H >> 12) & 3) == reason) {
11584
uint32_t sourceIncrement, destIncrement;
11585
uint32_t condition1 = ((DM2CNT_H >> 7) & 3);
11586
uint32_t condition2 = ((DM2CNT_H >> 5) & 3);
11587
sourceIncrement = arrayval[condition1];
11588
destIncrement = arrayval[condition2];
11589
uint32_t di_value, c_value, transfer_value;
11590
if(reason == 3)
11591
{
11592
di_value = 0;
11593
c_value = 4;
11594
transfer_value = 0x0400;
11595
}
11596
else
11597
{
11598
di_value = destIncrement;
11599
c_value = DM2CNT_L ? DM2CNT_L : 0x4000;
11600
transfer_value = DM2CNT_H & 0x0400;
11601
}
11602
doDMA(dma2Source, dma2Dest, sourceIncrement, di_value, c_value, transfer_value);
11603
11604
if(DM2CNT_H & 0x4000) {
11605
io_registers[REG_IF] |= 0x0400;
11606
UPDATE_REG(0x202, io_registers[REG_IF]);
11607
cpuNextEvent = cpuTotalTicks;
11608
}
11609
11610
if(((DM2CNT_H >> 5) & 3) == 3) {
11611
dma2Dest = DM2DAD_L | (DM2DAD_H << 16);
11612
}
11613
11614
if(!(DM2CNT_H & 0x0200) || (reason == 0)) {
11615
DM2CNT_H &= 0x7FFF;
11616
UPDATE_REG(0xD2, DM2CNT_H);
11617
}
11618
}
11619
}
11620
11621
// DMA 3
11622
if((DM3CNT_H & 0x8000) && (dmamask & 8))
11623
{
11624
if(((DM3CNT_H >> 12) & 3) == reason)
11625
{
11626
uint32_t sourceIncrement, destIncrement;
11627
uint32_t condition1 = ((DM3CNT_H >> 7) & 3);
11628
uint32_t condition2 = ((DM3CNT_H >> 5) & 3);
11629
sourceIncrement = arrayval[condition1];
11630
destIncrement = arrayval[condition2];
11631
doDMA(dma3Source, dma3Dest, sourceIncrement, destIncrement,
11632
DM3CNT_L ? DM3CNT_L : 0x10000,
11633
DM3CNT_H & 0x0400);
11634
if(DM3CNT_H & 0x4000) {
11635
io_registers[REG_IF] |= 0x0800;
11636
UPDATE_REG(0x202, io_registers[REG_IF]);
11637
cpuNextEvent = cpuTotalTicks;
11638
}
11639
11640
if(((DM3CNT_H >> 5) & 3) == 3) {
11641
dma3Dest = DM3DAD_L | (DM3DAD_H << 16);
11642
}
11643
11644
if(!(DM3CNT_H & 0x0200) || (reason == 0)) {
11645
DM3CNT_H &= 0x7FFF;
11646
UPDATE_REG(0xDE, DM3CNT_H);
11647
}
11648
}
11649
}
11650
}
11651
11652
uint16_t *address_lut[0x300];
11653
11654
void CPUUpdateRegister(uint32_t address, uint16_t value)
11655
{
11656
switch(address)
11657
{
11658
case 0x00:
11659
{
11660
if((value & 7) > 5) // display modes above 0-5 are prohibited
11661
io_registers[REG_DISPCNT] = (value & 7);
11662
11663
bool change = (0 != ((io_registers[REG_DISPCNT] ^ value) & 0x80));
11664
bool changeBG = (0 != ((io_registers[REG_DISPCNT] ^ value) & 0x0F00));
11665
uint16_t changeBGon = ((~io_registers[REG_DISPCNT]) & value) & 0x0F00; // these layers are being activated
11666
11667
io_registers[REG_DISPCNT] = (value & 0xFFF7); // bit 3 can only be accessed by the BIOS to enable GBC mode
11668
UPDATE_REG(0x00, io_registers[REG_DISPCNT]);
11669
11670
graphics.layerEnable = value;
11671
11672
if(changeBGon)
11673
{
11674
graphics.layerEnableDelay = 4;
11675
graphics.layerEnable &= ~changeBGon;
11676
}
11677
11678
windowOn = (graphics.layerEnable & 0x6000) ? true : false;
11679
if(change && !((value & 0x80)))
11680
{
11681
if(!(io_registers[REG_DISPSTAT] & 1))
11682
{
11683
graphics.lcdTicks = 1008;
11684
io_registers[REG_DISPSTAT] &= 0xFFFC;
11685
UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
11686
CPUCompareVCOUNT();
11687
}
11688
}
11689
CPUUpdateRender();
11690
// we only care about changes in BG0-BG3
11691
if(changeBG)
11692
{
11693
if(!(graphics.layerEnable & 0x0100))
11694
memset(line[0], -1, 240 * sizeof(u32));
11695
if(!(graphics.layerEnable & 0x0200))
11696
memset(line[1], -1, 240 * sizeof(u32));
11697
if(!(graphics.layerEnable & 0x0400))
11698
memset(line[2], -1, 240 * sizeof(u32));
11699
if(!(graphics.layerEnable & 0x0800))
11700
memset(line[3], -1, 240 * sizeof(u32));
11701
}
11702
break;
11703
}
11704
case 0x04:
11705
io_registers[REG_DISPSTAT] = (value & 0xFF38) | (io_registers[REG_DISPSTAT] & 7);
11706
UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
11707
break;
11708
case 0x06:
11709
// not writable
11710
break;
11711
case 0x08: /* BG0CNT */
11712
case 0x0A: /* BG1CNT */
11713
*address_lut[address] = (value & 0xDFCF);
11714
UPDATE_REG(address, *address_lut[address]);
11715
break;
11716
case 0x0C: /* BG2CNT */
11717
case 0x0E: /* BG3CNT */
11718
*address_lut[address] = (value & 0xFFCF);
11719
UPDATE_REG(address, *address_lut[address]);
11720
break;
11721
case 0x10: /* BG0HOFS */
11722
case 0x12: /* BG0VOFS */
11723
case 0x14: /* BG1HOFS */
11724
case 0x16: /* BG1VOFS */
11725
case 0x18: /* BG2HOFS */
11726
case 0x1A: /* BG2VOFS */
11727
case 0x1C: /* BG3HOFS */
11728
case 0x1E: /* BG3VOFS */
11729
*address_lut[address] = value & 511;
11730
UPDATE_REG(address, *address_lut[address]);
11731
break;
11732
case 0x20: /* BG2PA */
11733
case 0x22: /* BG2PB */
11734
case 0x24: /* BG2PC */
11735
case 0x26: /* BG2PD */
11736
*address_lut[address] = value;
11737
UPDATE_REG(address, *address_lut[address]);
11738
break;
11739
case 0x28:
11740
BG2X_L = value;
11741
UPDATE_REG(0x28, BG2X_L);
11742
gfxBG2Changed |= 1;
11743
break;
11744
case 0x2A:
11745
BG2X_H = (value & 0xFFF);
11746
UPDATE_REG(0x2A, BG2X_H);
11747
gfxBG2Changed |= 1;
11748
break;
11749
case 0x2C:
11750
BG2Y_L = value;
11751
UPDATE_REG(0x2C, BG2Y_L);
11752
gfxBG2Changed |= 2;
11753
break;
11754
case 0x2E:
11755
BG2Y_H = value & 0xFFF;
11756
UPDATE_REG(0x2E, BG2Y_H);
11757
gfxBG2Changed |= 2;
11758
break;
11759
case 0x30: /* BG3PA */
11760
case 0x32: /* BG3PB */
11761
case 0x34: /* BG3PC */
11762
case 0x36: /* BG3PD */
11763
*address_lut[address] = value;
11764
UPDATE_REG(address, *address_lut[address]);
11765
break;
11766
case 0x38:
11767
BG3X_L = value;
11768
UPDATE_REG(0x38, BG3X_L);
11769
gfxBG3Changed |= 1;
11770
break;
11771
case 0x3A:
11772
BG3X_H = value & 0xFFF;
11773
UPDATE_REG(0x3A, BG3X_H);
11774
gfxBG3Changed |= 1;
11775
break;
11776
case 0x3C:
11777
BG3Y_L = value;
11778
UPDATE_REG(0x3C, BG3Y_L);
11779
gfxBG3Changed |= 2;
11780
break;
11781
case 0x3E:
11782
BG3Y_H = value & 0xFFF;
11783
UPDATE_REG(0x3E, BG3Y_H);
11784
gfxBG3Changed |= 2;
11785
break;
11786
case 0x40:
11787
io_registers[REG_WIN0H] = value;
11788
UPDATE_REG(0x40, io_registers[REG_WIN0H]);
11789
CPUUpdateWindow0();
11790
break;
11791
case 0x42:
11792
io_registers[REG_WIN1H] = value;
11793
UPDATE_REG(0x42, io_registers[REG_WIN1H]);
11794
CPUUpdateWindow1();
11795
break;
11796
case 0x44:
11797
case 0x46:
11798
*address_lut[address] = value;
11799
UPDATE_REG(address, *address_lut[address]);
11800
break;
11801
case 0x48: /* WININ */
11802
case 0x4A: /* WINOUT */
11803
*address_lut[address] = value & 0x3F3F;
11804
UPDATE_REG(address, *address_lut[address]);
11805
break;
11806
case 0x4C:
11807
MOSAIC = value;
11808
UPDATE_REG(0x4C, MOSAIC);
11809
break;
11810
case 0x50:
11811
BLDMOD = value & 0x3FFF;
11812
UPDATE_REG(0x50, BLDMOD);
11813
fxOn = ((BLDMOD>>6)&3) != 0;
11814
CPUUpdateRender();
11815
break;
11816
case 0x52:
11817
COLEV = value & 0x1F1F;
11818
UPDATE_REG(0x52, COLEV);
11819
break;
11820
case 0x54:
11821
COLY = value & 0x1F;
11822
UPDATE_REG(0x54, COLY);
11823
break;
11824
case 0x60:
11825
case 0x62:
11826
case 0x64:
11827
case 0x68:
11828
case 0x6c:
11829
case 0x70:
11830
case 0x72:
11831
case 0x74:
11832
case 0x78:
11833
case 0x7c:
11834
case 0x80:
11835
case 0x84:
11836
{
11837
int gb_addr[2] = {address & 0xFF, (address & 0xFF) + 1};
11838
uint32_t address_array[2] = {address & 0xFF, (address&0xFF)+1};
11839
uint8_t data_array[2] = {(uint8_t)(value & 0xFF), (uint8_t)(value>>8)};
11840
gb_addr[0] = table[gb_addr[0] - 0x60];
11841
gb_addr[1] = table[gb_addr[1] - 0x60];
11842
soundEvent_u8_parallel(gb_addr, address_array, data_array);
11843
break;
11844
}
11845
case 0x82:
11846
case 0x88:
11847
case 0xa0:
11848
case 0xa2:
11849
case 0xa4:
11850
case 0xa6:
11851
case 0x90:
11852
case 0x92:
11853
case 0x94:
11854
case 0x96:
11855
case 0x98:
11856
case 0x9a:
11857
case 0x9c:
11858
case 0x9e:
11859
soundEvent_u16(address&0xFF, value);
11860
break;
11861
case 0xB0:
11862
DM0SAD_L = value;
11863
UPDATE_REG(0xB0, DM0SAD_L);
11864
break;
11865
case 0xB2:
11866
DM0SAD_H = value & 0x07FF;
11867
UPDATE_REG(0xB2, DM0SAD_H);
11868
break;
11869
case 0xB4:
11870
DM0DAD_L = value;
11871
UPDATE_REG(0xB4, DM0DAD_L);
11872
break;
11873
case 0xB6:
11874
DM0DAD_H = value & 0x07FF;
11875
UPDATE_REG(0xB6, DM0DAD_H);
11876
break;
11877
case 0xB8:
11878
DM0CNT_L = value & 0x3FFF;
11879
UPDATE_REG(0xB8, 0);
11880
break;
11881
case 0xBA:
11882
{
11883
bool start = ((DM0CNT_H ^ value) & 0x8000) ? true : false;
11884
value &= 0xF7E0;
11885
11886
DM0CNT_H = value;
11887
UPDATE_REG(0xBA, DM0CNT_H);
11888
11889
if(start && (value & 0x8000))
11890
{
11891
dma0Source = DM0SAD_L | (DM0SAD_H << 16);
11892
dma0Dest = DM0DAD_L | (DM0DAD_H << 16);
11893
CPUCheckDMA(0, 1);
11894
}
11895
}
11896
break;
11897
case 0xBC:
11898
DM1SAD_L = value;
11899
UPDATE_REG(0xBC, DM1SAD_L);
11900
break;
11901
case 0xBE:
11902
DM1SAD_H = value & 0x0FFF;
11903
UPDATE_REG(0xBE, DM1SAD_H);
11904
break;
11905
case 0xC0:
11906
DM1DAD_L = value;
11907
UPDATE_REG(0xC0, DM1DAD_L);
11908
break;
11909
case 0xC2:
11910
DM1DAD_H = value & 0x07FF;
11911
UPDATE_REG(0xC2, DM1DAD_H);
11912
break;
11913
case 0xC4:
11914
DM1CNT_L = value & 0x3FFF;
11915
UPDATE_REG(0xC4, 0);
11916
break;
11917
case 0xC6:
11918
{
11919
bool start = ((DM1CNT_H ^ value) & 0x8000) ? true : false;
11920
value &= 0xF7E0;
11921
11922
DM1CNT_H = value;
11923
UPDATE_REG(0xC6, DM1CNT_H);
11924
11925
if(start && (value & 0x8000))
11926
{
11927
dma1Source = DM1SAD_L | (DM1SAD_H << 16);
11928
dma1Dest = DM1DAD_L | (DM1DAD_H << 16);
11929
CPUCheckDMA(0, 2);
11930
}
11931
}
11932
break;
11933
case 0xC8:
11934
DM2SAD_L = value;
11935
UPDATE_REG(0xC8, DM2SAD_L);
11936
break;
11937
case 0xCA:
11938
DM2SAD_H = value & 0x0FFF;
11939
UPDATE_REG(0xCA, DM2SAD_H);
11940
break;
11941
case 0xCC:
11942
DM2DAD_L = value;
11943
UPDATE_REG(0xCC, DM2DAD_L);
11944
break;
11945
case 0xCE:
11946
DM2DAD_H = value & 0x07FF;
11947
UPDATE_REG(0xCE, DM2DAD_H);
11948
break;
11949
case 0xD0:
11950
DM2CNT_L = value & 0x3FFF;
11951
UPDATE_REG(0xD0, 0);
11952
break;
11953
case 0xD2:
11954
{
11955
bool start = ((DM2CNT_H ^ value) & 0x8000) ? true : false;
11956
11957
value &= 0xF7E0;
11958
11959
DM2CNT_H = value;
11960
UPDATE_REG(0xD2, DM2CNT_H);
11961
11962
if(start && (value & 0x8000)) {
11963
dma2Source = DM2SAD_L | (DM2SAD_H << 16);
11964
dma2Dest = DM2DAD_L | (DM2DAD_H << 16);
11965
11966
CPUCheckDMA(0, 4);
11967
}
11968
}
11969
break;
11970
case 0xD4:
11971
DM3SAD_L = value;
11972
UPDATE_REG(0xD4, DM3SAD_L);
11973
break;
11974
case 0xD6:
11975
DM3SAD_H = value & 0x0FFF;
11976
UPDATE_REG(0xD6, DM3SAD_H);
11977
break;
11978
case 0xD8:
11979
DM3DAD_L = value;
11980
UPDATE_REG(0xD8, DM3DAD_L);
11981
break;
11982
case 0xDA:
11983
DM3DAD_H = value & 0x0FFF;
11984
UPDATE_REG(0xDA, DM3DAD_H);
11985
break;
11986
case 0xDC:
11987
DM3CNT_L = value;
11988
UPDATE_REG(0xDC, 0);
11989
break;
11990
case 0xDE:
11991
{
11992
bool start = ((DM3CNT_H ^ value) & 0x8000) ? true : false;
11993
11994
value &= 0xFFE0;
11995
11996
DM3CNT_H = value;
11997
UPDATE_REG(0xDE, DM3CNT_H);
11998
11999
if(start && (value & 0x8000)) {
12000
dma3Source = DM3SAD_L | (DM3SAD_H << 16);
12001
dma3Dest = DM3DAD_L | (DM3DAD_H << 16);
12002
CPUCheckDMA(0,8);
12003
}
12004
}
12005
break;
12006
case 0x100:
12007
timer0Reload = value;
12008
break;
12009
case 0x102:
12010
timer0Value = value;
12011
timerOnOffDelay|=1;
12012
cpuNextEvent = cpuTotalTicks;
12013
break;
12014
case 0x104:
12015
timer1Reload = value;
12016
break;
12017
case 0x106:
12018
timer1Value = value;
12019
timerOnOffDelay|=2;
12020
cpuNextEvent = cpuTotalTicks;
12021
break;
12022
case 0x108:
12023
timer2Reload = value;
12024
break;
12025
case 0x10A:
12026
timer2Value = value;
12027
timerOnOffDelay|=4;
12028
cpuNextEvent = cpuTotalTicks;
12029
break;
12030
case 0x10C:
12031
timer3Reload = value;
12032
break;
12033
case 0x10E:
12034
timer3Value = value;
12035
timerOnOffDelay|=8;
12036
cpuNextEvent = cpuTotalTicks;
12037
break;
12038
case 0x130:
12039
io_registers[REG_P1] |= (value & 0x3FF);
12040
UPDATE_REG(0x130, io_registers[REG_P1]);
12041
break;
12042
case 0x132:
12043
UPDATE_REG(0x132, value & 0xC3FF);
12044
break;
12045
12046
12047
case 0x200:
12048
io_registers[REG_IE] = value & 0x3FFF;
12049
UPDATE_REG(0x200, io_registers[REG_IE]);
12050
if ((io_registers[REG_IME] & 1) && (io_registers[REG_IF] & io_registers[REG_IE]) && armIrqEnable)
12051
cpuNextEvent = cpuTotalTicks;
12052
break;
12053
case 0x202:
12054
io_registers[REG_IF] ^= (value & io_registers[REG_IF]);
12055
UPDATE_REG(0x202, io_registers[REG_IF]);
12056
break;
12057
case 0x204:
12058
{
12059
memoryWait[0x0e] = memoryWaitSeq[0x0e] = gamepakRamWaitState[value & 3];
12060
12061
memoryWait[0x08] = memoryWait[0x09] = 3;
12062
memoryWaitSeq[0x08] = memoryWaitSeq[0x09] = 1;
12063
12064
memoryWait[0x0a] = memoryWait[0x0b] = 3;
12065
memoryWaitSeq[0x0a] = memoryWaitSeq[0x0b] = 1;
12066
12067
memoryWait[0x0c] = memoryWait[0x0d] = 3;
12068
memoryWaitSeq[0x0c] = memoryWaitSeq[0x0d] = 1;
12069
12070
memoryWait32[8] = memoryWait[8] + memoryWaitSeq[8] + 1;
12071
memoryWaitSeq32[8] = memoryWaitSeq[8]*2 + 1;
12072
12073
memoryWait32[9] = memoryWait[9] + memoryWaitSeq[9] + 1;
12074
memoryWaitSeq32[9] = memoryWaitSeq[9]*2 + 1;
12075
12076
memoryWait32[10] = memoryWait[10] + memoryWaitSeq[10] + 1;
12077
memoryWaitSeq32[10] = memoryWaitSeq[10]*2 + 1;
12078
12079
memoryWait32[11] = memoryWait[11] + memoryWaitSeq[11] + 1;
12080
memoryWaitSeq32[11] = memoryWaitSeq[11]*2 + 1;
12081
12082
memoryWait32[12] = memoryWait[12] + memoryWaitSeq[12] + 1;
12083
memoryWaitSeq32[12] = memoryWaitSeq[12]*2 + 1;
12084
12085
memoryWait32[13] = memoryWait[13] + memoryWaitSeq[13] + 1;
12086
memoryWaitSeq32[13] = memoryWaitSeq[13]*2 + 1;
12087
12088
memoryWait32[14] = memoryWait[14] + memoryWaitSeq[14] + 1;
12089
memoryWaitSeq32[14] = memoryWaitSeq[14]*2 + 1;
12090
12091
if((value & 0x4000) == 0x4000)
12092
bus.busPrefetchEnable = true;
12093
else
12094
bus.busPrefetchEnable = false;
12095
12096
bus.busPrefetch = false;
12097
bus.busPrefetchCount = 0;
12098
12099
UPDATE_REG(0x204, value & 0x7FFF);
12100
12101
}
12102
break;
12103
case 0x208:
12104
io_registers[REG_IME] = value & 1;
12105
UPDATE_REG(0x208, io_registers[REG_IME]);
12106
if ((io_registers[REG_IME] & 1) && (io_registers[REG_IF] & io_registers[REG_IE]) && armIrqEnable)
12107
cpuNextEvent = cpuTotalTicks;
12108
break;
12109
case 0x300:
12110
if(value != 0)
12111
value &= 0xFFFE;
12112
UPDATE_REG(0x300, value);
12113
break;
12114
default:
12115
UPDATE_REG(address&0x3FE, value);
12116
break;
12117
}
12118
}
12119
12120
12121
void CPUInit(const u8 *biosfile, const u32 biosfilelen)
12122
{
12123
eepromInUse = false;
12124
switch(cpuSaveType)
12125
{
12126
case 0: // automatic
12127
default:
12128
cpuEEPROMEnabled = true;
12129
cpuEEPROMSensorEnabled = false;
12130
cpuSaveGameFunc = &Gigazoid::flashSaveDecide; // EEPROM usage is automatically detected
12131
break;
12132
case 1: // EEPROM
12133
cpuEEPROMEnabled = true;
12134
cpuEEPROMSensorEnabled = false;
12135
cpuSaveGameFunc = &Gigazoid::dummyWrite; // EEPROM usage is automatically detected
12136
break;
12137
case 2: // SRAM
12138
cpuEEPROMEnabled = false;
12139
cpuEEPROMSensorEnabled = false;
12140
cpuSaveGameFunc = &Gigazoid::sramWrite;
12141
break;
12142
case 3: // FLASH
12143
cpuEEPROMEnabled = false;
12144
cpuEEPROMSensorEnabled = false;
12145
cpuSaveGameFunc = &Gigazoid::flashWrite;
12146
break;
12147
case 4: // EEPROM+Sensor
12148
cpuEEPROMEnabled = true;
12149
cpuEEPROMSensorEnabled = true;
12150
cpuSaveGameFunc = &Gigazoid::dummyWrite; // EEPROM usage is automatically detected
12151
break;
12152
case 5: // NONE
12153
cpuEEPROMEnabled = false;
12154
cpuEEPROMSensorEnabled = false;
12155
cpuSaveGameFunc = &Gigazoid::dummyWrite;
12156
break;
12157
}
12158
12159
memcpy(bios, biosfile, 16384);
12160
12161
int i = 0;
12162
12163
biosProtected[0] = 0x00;
12164
biosProtected[1] = 0xf0;
12165
biosProtected[2] = 0x29;
12166
biosProtected[3] = 0xe1;
12167
12168
for(i = 0; i < 256; i++)
12169
{
12170
int count = 0;
12171
int j;
12172
for(j = 0; j < 8; j++)
12173
if(i & (1 << j))
12174
count++;
12175
cpuBitsSet[i] = count;
12176
12177
for(j = 0; j < 8; j++)
12178
if(i & (1 << j))
12179
break;
12180
}
12181
12182
for(i = 0; i < 0x400; i++)
12183
ioReadable[i] = true;
12184
for(i = 0x10; i < 0x48; i++)
12185
ioReadable[i] = false;
12186
for(i = 0x4c; i < 0x50; i++)
12187
ioReadable[i] = false;
12188
for(i = 0x54; i < 0x60; i++)
12189
ioReadable[i] = false;
12190
for(i = 0x8c; i < 0x90; i++)
12191
ioReadable[i] = false;
12192
for(i = 0xa0; i < 0xb8; i++)
12193
ioReadable[i] = false;
12194
for(i = 0xbc; i < 0xc4; i++)
12195
ioReadable[i] = false;
12196
for(i = 0xc8; i < 0xd0; i++)
12197
ioReadable[i] = false;
12198
for(i = 0xd4; i < 0xdc; i++)
12199
ioReadable[i] = false;
12200
for(i = 0xe0; i < 0x100; i++)
12201
ioReadable[i] = false;
12202
for(i = 0x110; i < 0x120; i++)
12203
ioReadable[i] = false;
12204
for(i = 0x12c; i < 0x130; i++)
12205
ioReadable[i] = false;
12206
for(i = 0x138; i < 0x140; i++)
12207
ioReadable[i] = false;
12208
for(i = 0x144; i < 0x150; i++)
12209
ioReadable[i] = false;
12210
for(i = 0x15c; i < 0x200; i++)
12211
ioReadable[i] = false;
12212
for(i = 0x20c; i < 0x300; i++)
12213
ioReadable[i] = false;
12214
for(i = 0x304; i < 0x400; i++)
12215
ioReadable[i] = false;
12216
12217
// what is this?
12218
if(romSize < 0x1fe2000) {
12219
*((uint16_t *)&rom[0x1fe209c]) = 0xdffa; // SWI 0xFA
12220
*((uint16_t *)&rom[0x1fe209e]) = 0x4770; // BX LR
12221
}
12222
12223
graphics.layerEnable = 0xff00;
12224
graphics.layerEnableDelay = 1;
12225
io_registers[REG_DISPCNT] = 0x0080;
12226
io_registers[REG_DISPSTAT] = 0;
12227
graphics.lcdTicks = (useBios && !skipBios) ? 1008 : 208;
12228
12229
/* address lut for use in CPUUpdateRegister */
12230
address_lut[0x08] = &io_registers[REG_BG0CNT];
12231
address_lut[0x0A] = &io_registers[REG_BG1CNT];
12232
address_lut[0x0C] = &io_registers[REG_BG2CNT];
12233
address_lut[0x0E] = &io_registers[REG_BG3CNT];
12234
address_lut[0x10] = &io_registers[REG_BG0HOFS];
12235
address_lut[0x12] = &io_registers[REG_BG0VOFS];
12236
address_lut[0x14] = &io_registers[REG_BG1HOFS];
12237
address_lut[0x16] = &io_registers[REG_BG1VOFS];
12238
address_lut[0x18] = &io_registers[REG_BG2HOFS];
12239
address_lut[0x1A] = &io_registers[REG_BG2VOFS];
12240
address_lut[0x1C] = &io_registers[REG_BG3HOFS];
12241
address_lut[0x1E] = &io_registers[REG_BG3VOFS];
12242
address_lut[0x20] = &io_registers[REG_BG2PA];
12243
address_lut[0x22] = &io_registers[REG_BG2PB];
12244
address_lut[0x24] = &io_registers[REG_BG2PC];
12245
address_lut[0x26] = &io_registers[REG_BG2PD];
12246
address_lut[0x48] = &io_registers[REG_WININ];
12247
address_lut[0x4A] = &io_registers[REG_WINOUT];
12248
address_lut[0x30] = &io_registers[REG_BG3PA];
12249
address_lut[0x32] = &io_registers[REG_BG3PB];
12250
address_lut[0x34] = &io_registers[REG_BG3PC];
12251
address_lut[0x36] = &io_registers[REG_BG3PD];
12252
address_lut[0x40] = &io_registers[REG_WIN0H];
12253
address_lut[0x42] = &io_registers[REG_WIN1H];
12254
address_lut[0x44] = &io_registers[REG_WIN0V];
12255
address_lut[0x46] = &io_registers[REG_WIN1V];
12256
}
12257
12258
void CPUReset (void)
12259
{
12260
rtcReset();
12261
memset(&bus.reg[0], 0, sizeof(bus.reg)); // clean registers
12262
memset(oam, 0, 0x400); // clean OAM
12263
memset(graphics.paletteRAM, 0, 0x400); // clean palette
12264
memset(pix, 0, 4 * 160 * 240); // clean picture
12265
memset(vram, 0, 0x20000); // clean vram
12266
memset(ioMem, 0, 0x400); // clean io memory
12267
12268
io_registers[REG_DISPCNT] = 0x0080;
12269
io_registers[REG_DISPSTAT] = 0x0000;
12270
io_registers[REG_VCOUNT] = (useBios && !skipBios) ? 0 :0x007E;
12271
io_registers[REG_BG0CNT] = 0x0000;
12272
io_registers[REG_BG1CNT] = 0x0000;
12273
io_registers[REG_BG2CNT] = 0x0000;
12274
io_registers[REG_BG3CNT] = 0x0000;
12275
io_registers[REG_BG0HOFS] = 0x0000;
12276
io_registers[REG_BG0VOFS] = 0x0000;
12277
io_registers[REG_BG1HOFS] = 0x0000;
12278
io_registers[REG_BG1VOFS] = 0x0000;
12279
io_registers[REG_BG2HOFS] = 0x0000;
12280
io_registers[REG_BG2VOFS] = 0x0000;
12281
io_registers[REG_BG3HOFS] = 0x0000;
12282
io_registers[REG_BG3VOFS] = 0x0000;
12283
io_registers[REG_BG2PA] = 0x0100;
12284
io_registers[REG_BG2PB] = 0x0000;
12285
io_registers[REG_BG2PC] = 0x0000;
12286
io_registers[REG_BG2PD] = 0x0100;
12287
BG2X_L = 0x0000;
12288
BG2X_H = 0x0000;
12289
BG2Y_L = 0x0000;
12290
BG2Y_H = 0x0000;
12291
io_registers[REG_BG3PA] = 0x0100;
12292
io_registers[REG_BG3PB] = 0x0000;
12293
io_registers[REG_BG3PC] = 0x0000;
12294
io_registers[REG_BG3PD] = 0x0100;
12295
BG3X_L = 0x0000;
12296
BG3X_H = 0x0000;
12297
BG3Y_L = 0x0000;
12298
BG3Y_H = 0x0000;
12299
io_registers[REG_WIN0H] = 0x0000;
12300
io_registers[REG_WIN1H] = 0x0000;
12301
io_registers[REG_WIN0V] = 0x0000;
12302
io_registers[REG_WIN1V] = 0x0000;
12303
io_registers[REG_WININ] = 0x0000;
12304
io_registers[REG_WINOUT] = 0x0000;
12305
MOSAIC = 0x0000;
12306
BLDMOD = 0x0000;
12307
COLEV = 0x0000;
12308
COLY = 0x0000;
12309
DM0SAD_L = 0x0000;
12310
DM0SAD_H = 0x0000;
12311
DM0DAD_L = 0x0000;
12312
DM0DAD_H = 0x0000;
12313
DM0CNT_L = 0x0000;
12314
DM0CNT_H = 0x0000;
12315
DM1SAD_L = 0x0000;
12316
DM1SAD_H = 0x0000;
12317
DM1DAD_L = 0x0000;
12318
DM1DAD_H = 0x0000;
12319
DM1CNT_L = 0x0000;
12320
DM1CNT_H = 0x0000;
12321
DM2SAD_L = 0x0000;
12322
DM2SAD_H = 0x0000;
12323
DM2DAD_L = 0x0000;
12324
DM2DAD_H = 0x0000;
12325
DM2CNT_L = 0x0000;
12326
DM2CNT_H = 0x0000;
12327
DM3SAD_L = 0x0000;
12328
DM3SAD_H = 0x0000;
12329
DM3DAD_L = 0x0000;
12330
DM3DAD_H = 0x0000;
12331
DM3CNT_L = 0x0000;
12332
DM3CNT_H = 0x0000;
12333
io_registers[REG_TM0D] = 0x0000;
12334
io_registers[REG_TM0CNT] = 0x0000;
12335
io_registers[REG_TM1D] = 0x0000;
12336
io_registers[REG_TM1CNT] = 0x0000;
12337
io_registers[REG_TM2D] = 0x0000;
12338
io_registers[REG_TM2CNT] = 0x0000;
12339
io_registers[REG_TM3D] = 0x0000;
12340
io_registers[REG_TM3CNT] = 0x0000;
12341
io_registers[REG_P1] = 0x03FF;
12342
io_registers[REG_IE] = 0x0000;
12343
io_registers[REG_IF] = 0x0000;
12344
io_registers[REG_IME] = 0x0000;
12345
12346
armMode = 0x1F;
12347
12348
if(cpuIsMultiBoot) {
12349
bus.reg[13].I = 0x03007F00;
12350
bus.reg[15].I = 0x02000000;
12351
bus.reg[16].I = 0x00000000;
12352
bus.reg[R13_IRQ].I = 0x03007FA0;
12353
bus.reg[R13_SVC].I = 0x03007FE0;
12354
armIrqEnable = true;
12355
} else {
12356
#ifdef HAVE_HLE_BIOS
12357
if(useBios && !skipBios)
12358
{
12359
bus.reg[15].I = 0x00000000;
12360
armMode = 0x13;
12361
armIrqEnable = false;
12362
}
12363
else
12364
{
12365
#endif
12366
bus.reg[13].I = 0x03007F00;
12367
bus.reg[15].I = 0x08000000;
12368
bus.reg[16].I = 0x00000000;
12369
bus.reg[R13_IRQ].I = 0x03007FA0;
12370
bus.reg[R13_SVC].I = 0x03007FE0;
12371
armIrqEnable = true;
12372
#ifdef HAVE_HLE_BIOS
12373
}
12374
#endif
12375
}
12376
armState = true;
12377
C_FLAG = V_FLAG = N_FLAG = Z_FLAG = false;
12378
UPDATE_REG(0x00, io_registers[REG_DISPCNT]);
12379
UPDATE_REG(0x06, io_registers[REG_VCOUNT]);
12380
UPDATE_REG(0x20, io_registers[REG_BG2PA]);
12381
UPDATE_REG(0x26, io_registers[REG_BG2PD]);
12382
UPDATE_REG(0x30, io_registers[REG_BG3PA]);
12383
UPDATE_REG(0x36, io_registers[REG_BG3PD]);
12384
UPDATE_REG(0x130, io_registers[REG_P1]);
12385
UPDATE_REG(0x88, 0x200);
12386
12387
// disable FIQ
12388
bus.reg[16].I |= 0x40;
12389
12390
CPU_UPDATE_CPSR();
12391
12392
bus.armNextPC = bus.reg[15].I;
12393
bus.reg[15].I += 4;
12394
12395
// reset internal state
12396
holdState = false;
12397
12398
biosProtected[0] = 0x00;
12399
biosProtected[1] = 0xf0;
12400
biosProtected[2] = 0x29;
12401
biosProtected[3] = 0xe1;
12402
12403
graphics.lcdTicks = (useBios && !skipBios) ? 1008 : 208;
12404
timer0On = false;
12405
timer0Ticks = 0;
12406
timer0Reload = 0;
12407
timer0ClockReload = 0;
12408
timer1On = false;
12409
timer1Ticks = 0;
12410
timer1Reload = 0;
12411
timer1ClockReload = 0;
12412
timer2On = false;
12413
timer2Ticks = 0;
12414
timer2Reload = 0;
12415
timer2ClockReload = 0;
12416
timer3On = false;
12417
timer3Ticks = 0;
12418
timer3Reload = 0;
12419
timer3ClockReload = 0;
12420
dma0Source = 0;
12421
dma0Dest = 0;
12422
dma1Source = 0;
12423
dma1Dest = 0;
12424
dma2Source = 0;
12425
dma2Dest = 0;
12426
dma3Source = 0;
12427
dma3Dest = 0;
12428
renderLine = &Gigazoid::mode0RenderLine;
12429
fxOn = false;
12430
windowOn = false;
12431
graphics.layerEnable = io_registers[REG_DISPCNT];
12432
12433
memset(line[0], -1, 240 * sizeof(u32));
12434
memset(line[1], -1, 240 * sizeof(u32));
12435
memset(line[2], -1, 240 * sizeof(u32));
12436
memset(line[3], -1, 240 * sizeof(u32));
12437
12438
for(int i = 0; i < 256; i++) {
12439
map[i].address = 0;
12440
map[i].mask = 0;
12441
}
12442
12443
map[0].address = bios;
12444
map[0].mask = 0x3FFF;
12445
map[2].address = workRAM;
12446
map[2].mask = 0x3FFFF;
12447
map[3].address = internalRAM;
12448
map[3].mask = 0x7FFF;
12449
map[4].address = ioMem;
12450
map[4].mask = 0x3FF;
12451
map[5].address = graphics.paletteRAM;
12452
map[5].mask = 0x3FF;
12453
map[6].address = vram;
12454
map[6].mask = 0x1FFFF;
12455
map[7].address = oam;
12456
map[7].mask = 0x3FF;
12457
map[8].address = rom;
12458
map[8].mask = 0x1FFFFFF;
12459
map[9].address = rom;
12460
map[9].mask = 0x1FFFFFF;
12461
map[10].address = rom;
12462
map[10].mask = 0x1FFFFFF;
12463
map[12].address = rom;
12464
map[12].mask = 0x1FFFFFF;
12465
map[14].address = flashSaveMemory;
12466
map[14].mask = 0xFFFF;
12467
12468
eepromReset();
12469
flashReset();
12470
12471
soundReset();
12472
12473
CPUUpdateWindow0();
12474
CPUUpdateWindow1();
12475
12476
// make sure registers are correctly initialized if not using BIOS
12477
if(cpuIsMultiBoot)
12478
BIOS_RegisterRamReset(0xfe);
12479
else if(!useBios && !cpuIsMultiBoot)
12480
BIOS_RegisterRamReset(0xff);
12481
else if (skipBios)
12482
BIOS_RegisterRamReset(0xff); // ??
12483
12484
ARM_PREFETCH;
12485
}
12486
12487
void CPUInterrupt(void)
12488
{
12489
uint32_t PC = bus.reg[15].I;
12490
bool savedState = armState;
12491
12492
if(armMode != 0x12 )
12493
CPUSwitchMode(0x12, true, false);
12494
12495
bus.reg[14].I = PC;
12496
if(!savedState)
12497
bus.reg[14].I += 2;
12498
bus.reg[15].I = 0x18;
12499
armState = true;
12500
armIrqEnable = false;
12501
12502
bus.armNextPC = bus.reg[15].I;
12503
bus.reg[15].I += 4;
12504
ARM_PREFETCH;
12505
12506
// if(!holdState)
12507
biosProtected[0] = 0x02;
12508
biosProtected[1] = 0xc0;
12509
biosProtected[2] = 0x5e;
12510
biosProtected[3] = 0xe5;
12511
}
12512
12513
void CPULoop (void)
12514
{
12515
bus.busPrefetchCount = 0;
12516
int ticks = 300000;
12517
int timerOverflow = 0;
12518
// variable used by the CPU core
12519
cpuTotalTicks = 0;
12520
12521
cpuNextEvent = CPUUpdateTicks();
12522
if(cpuNextEvent > ticks)
12523
cpuNextEvent = ticks;
12524
12525
bool framedone = false;
12526
12527
do
12528
{
12529
if(!holdState)
12530
{
12531
if(armState)
12532
{
12533
if (!armExecute())
12534
return;
12535
}
12536
else
12537
{
12538
if (!thumbExecute())
12539
return;
12540
}
12541
clockTicks = 0;
12542
}
12543
else
12544
clockTicks = CPUUpdateTicks();
12545
12546
cpuTotalTicks += clockTicks;
12547
12548
12549
if(cpuTotalTicks >= cpuNextEvent) {
12550
int remainingTicks = cpuTotalTicks - cpuNextEvent;
12551
12552
clockTicks = cpuNextEvent;
12553
cpuTotalTicks = 0;
12554
12555
updateLoop:
12556
12557
if (IRQTicks)
12558
{
12559
IRQTicks -= clockTicks;
12560
if (IRQTicks<0)
12561
IRQTicks = 0;
12562
}
12563
12564
graphics.lcdTicks -= clockTicks;
12565
12566
soundTicksUp += clockTicks;
12567
12568
AdvanceRTC(clockTicks);
12569
12570
if(graphics.lcdTicks <= 0)
12571
{
12572
if(io_registers[REG_DISPSTAT] & 1)
12573
{ // V-BLANK
12574
// if in V-Blank mode, keep computing...
12575
if(io_registers[REG_DISPSTAT] & 2)
12576
{
12577
graphics.lcdTicks += 1008;
12578
io_registers[REG_VCOUNT] += 1;
12579
UPDATE_REG(0x06, io_registers[REG_VCOUNT]);
12580
io_registers[REG_DISPSTAT] &= 0xFFFD;
12581
UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
12582
CPUCompareVCOUNT();
12583
}
12584
else
12585
{
12586
graphics.lcdTicks += 224;
12587
io_registers[REG_DISPSTAT] |= 2;
12588
UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
12589
if(io_registers[REG_DISPSTAT] & 16)
12590
{
12591
io_registers[REG_IF] |= 2;
12592
UPDATE_REG(0x202, io_registers[REG_IF]);
12593
}
12594
if (scanlineCallback && scanlineCallbackLine == io_registers[REG_VCOUNT])
12595
scanlineCallback();
12596
}
12597
12598
if(io_registers[REG_VCOUNT] >= 228)
12599
{
12600
//Reaching last line
12601
io_registers[REG_DISPSTAT] &= 0xFFFC;
12602
UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
12603
io_registers[REG_VCOUNT] = 0;
12604
UPDATE_REG(0x06, io_registers[REG_VCOUNT]);
12605
CPUCompareVCOUNT();
12606
}
12607
}
12608
else if(io_registers[REG_DISPSTAT] & 2)
12609
{
12610
// if in H-Blank, leave it and move to drawing mode
12611
io_registers[REG_VCOUNT] += 1;
12612
UPDATE_REG(0x06, io_registers[REG_VCOUNT]);
12613
graphics.lcdTicks += 1008;
12614
io_registers[REG_DISPSTAT] &= 0xFFFD;
12615
if(io_registers[REG_VCOUNT] == 160)
12616
{
12617
// moved to start of emulated frame
12618
//UpdateJoypad();
12619
12620
io_registers[REG_DISPSTAT] |= 1;
12621
io_registers[REG_DISPSTAT] &= 0xFFFD;
12622
UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
12623
if(io_registers[REG_DISPSTAT] & 0x0008)
12624
{
12625
io_registers[REG_IF] |= 1;
12626
UPDATE_REG(0x202, io_registers[REG_IF]);
12627
}
12628
CPUCheckDMA(1, 0x0f);
12629
systemDrawScreen();
12630
12631
process_sound_tick_fn();
12632
framedone = true;
12633
}
12634
12635
UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
12636
CPUCompareVCOUNT();
12637
}
12638
else
12639
{
12640
bool draw_objwin = (graphics.layerEnable & 0x9000) == 0x9000;
12641
bool draw_sprites = graphics.layerEnable & 0x1000;
12642
memset(line[4], -1, 240 * sizeof(u32)); // erase all sprites
12643
12644
if(draw_sprites)
12645
gfxDrawSprites();
12646
12647
if(render_line_all_enabled)
12648
{
12649
memset(line[5], -1, 240 * sizeof(u32)); // erase all OBJ Win
12650
if(draw_objwin)
12651
gfxDrawOBJWin();
12652
}
12653
12654
(this->*renderLine)();
12655
12656
// entering H-Blank
12657
io_registers[REG_DISPSTAT] |= 2;
12658
UPDATE_REG(0x04, io_registers[REG_DISPSTAT]);
12659
graphics.lcdTicks += 224;
12660
CPUCheckDMA(2, 0x0f);
12661
if(io_registers[REG_DISPSTAT] & 16)
12662
{
12663
io_registers[REG_IF] |= 2;
12664
UPDATE_REG(0x202, io_registers[REG_IF]);
12665
}
12666
if (scanlineCallback && scanlineCallbackLine == io_registers[REG_VCOUNT])
12667
scanlineCallback();
12668
}
12669
}
12670
12671
// we shouldn't be doing sound in stop state, but we lose synchronization
12672
// if sound is disabled, so in stop state, soundTick will just produce
12673
// mute sound
12674
12675
// moving this may have consequences; we'll see
12676
//soundTicksUp += clockTicks;
12677
12678
if(!stopState) {
12679
if(timer0On) {
12680
timer0Ticks -= clockTicks;
12681
if(timer0Ticks <= 0) {
12682
timer0Ticks += (0x10000 - timer0Reload) << timer0ClockReload;
12683
timerOverflow |= 1;
12684
soundTimerOverflow(0);
12685
if(io_registers[REG_TM0CNT] & 0x40) {
12686
io_registers[REG_IF] |= 0x08;
12687
UPDATE_REG(0x202, io_registers[REG_IF]);
12688
}
12689
}
12690
io_registers[REG_TM0D] = 0xFFFF - (timer0Ticks >> timer0ClockReload);
12691
UPDATE_REG(0x100, io_registers[REG_TM0D]);
12692
}
12693
12694
if(timer1On) {
12695
if(io_registers[REG_TM1CNT] & 4) {
12696
if(timerOverflow & 1) {
12697
io_registers[REG_TM1D]++;
12698
if(io_registers[REG_TM1D] == 0) {
12699
io_registers[REG_TM1D] += timer1Reload;
12700
timerOverflow |= 2;
12701
soundTimerOverflow(1);
12702
if(io_registers[REG_TM1CNT] & 0x40) {
12703
io_registers[REG_IF] |= 0x10;
12704
UPDATE_REG(0x202, io_registers[REG_IF]);
12705
}
12706
}
12707
UPDATE_REG(0x104, io_registers[REG_TM1D]);
12708
}
12709
} else {
12710
timer1Ticks -= clockTicks;
12711
if(timer1Ticks <= 0) {
12712
timer1Ticks += (0x10000 - timer1Reload) << timer1ClockReload;
12713
timerOverflow |= 2;
12714
soundTimerOverflow(1);
12715
if(io_registers[REG_TM1CNT] & 0x40) {
12716
io_registers[REG_IF] |= 0x10;
12717
UPDATE_REG(0x202, io_registers[REG_IF]);
12718
}
12719
}
12720
io_registers[REG_TM1D] = 0xFFFF - (timer1Ticks >> timer1ClockReload);
12721
UPDATE_REG(0x104, io_registers[REG_TM1D]);
12722
}
12723
}
12724
12725
if(timer2On) {
12726
if(io_registers[REG_TM2CNT] & 4) {
12727
if(timerOverflow & 2) {
12728
io_registers[REG_TM2D]++;
12729
if(io_registers[REG_TM2D] == 0) {
12730
io_registers[REG_TM2D] += timer2Reload;
12731
timerOverflow |= 4;
12732
if(io_registers[REG_TM2CNT] & 0x40) {
12733
io_registers[REG_IF] |= 0x20;
12734
UPDATE_REG(0x202, io_registers[REG_IF]);
12735
}
12736
}
12737
UPDATE_REG(0x108, io_registers[REG_TM2D]);
12738
}
12739
} else {
12740
timer2Ticks -= clockTicks;
12741
if(timer2Ticks <= 0) {
12742
timer2Ticks += (0x10000 - timer2Reload) << timer2ClockReload;
12743
timerOverflow |= 4;
12744
if(io_registers[REG_TM2CNT] & 0x40) {
12745
io_registers[REG_IF] |= 0x20;
12746
UPDATE_REG(0x202, io_registers[REG_IF]);
12747
}
12748
}
12749
io_registers[REG_TM2D] = 0xFFFF - (timer2Ticks >> timer2ClockReload);
12750
UPDATE_REG(0x108, io_registers[REG_TM2D]);
12751
}
12752
}
12753
12754
if(timer3On) {
12755
if(io_registers[REG_TM3CNT] & 4) {
12756
if(timerOverflow & 4) {
12757
io_registers[REG_TM3D]++;
12758
if(io_registers[REG_TM3D] == 0) {
12759
io_registers[REG_TM3D] += timer3Reload;
12760
if(io_registers[REG_TM3CNT] & 0x40) {
12761
io_registers[REG_IF] |= 0x40;
12762
UPDATE_REG(0x202, io_registers[REG_IF]);
12763
}
12764
}
12765
UPDATE_REG(0x10C, io_registers[REG_TM3D]);
12766
}
12767
} else {
12768
timer3Ticks -= clockTicks;
12769
if(timer3Ticks <= 0) {
12770
timer3Ticks += (0x10000 - timer3Reload) << timer3ClockReload;
12771
if(io_registers[REG_TM3CNT] & 0x40) {
12772
io_registers[REG_IF] |= 0x40;
12773
UPDATE_REG(0x202, io_registers[REG_IF]);
12774
}
12775
}
12776
io_registers[REG_TM3D] = 0xFFFF - (timer3Ticks >> timer3ClockReload);
12777
UPDATE_REG(0x10C, io_registers[REG_TM3D]);
12778
}
12779
}
12780
}
12781
12782
timerOverflow = 0;
12783
ticks -= clockTicks;
12784
cpuNextEvent = CPUUpdateTicks();
12785
12786
if(cpuDmaTicksToUpdate > 0)
12787
{
12788
if(cpuDmaTicksToUpdate > cpuNextEvent)
12789
clockTicks = cpuNextEvent;
12790
else
12791
clockTicks = cpuDmaTicksToUpdate;
12792
cpuDmaTicksToUpdate -= clockTicks;
12793
if(cpuDmaTicksToUpdate < 0)
12794
cpuDmaTicksToUpdate = 0;
12795
goto skipIRQ;
12796
}
12797
12798
if(io_registers[REG_IF] && (io_registers[REG_IME] & 1) && armIrqEnable)
12799
{
12800
int res = io_registers[REG_IF] & io_registers[REG_IE];
12801
if(stopState)
12802
res &= 0x3080;
12803
if(res)
12804
{
12805
if (intState)
12806
{
12807
if (!IRQTicks)
12808
{
12809
CPUInterrupt();
12810
intState = false;
12811
holdState = false;
12812
stopState = false;
12813
}
12814
}
12815
else
12816
{
12817
if (!holdState)
12818
{
12819
intState = true;
12820
IRQTicks=7;
12821
if (cpuNextEvent> IRQTicks)
12822
cpuNextEvent = IRQTicks;
12823
}
12824
else
12825
{
12826
CPUInterrupt();
12827
holdState = false;
12828
stopState = false;
12829
}
12830
}
12831
}
12832
}
12833
12834
skipIRQ:
12835
12836
if(remainingTicks > 0) {
12837
if(remainingTicks > cpuNextEvent)
12838
clockTicks = cpuNextEvent;
12839
else
12840
clockTicks = remainingTicks;
12841
remainingTicks -= clockTicks;
12842
if(remainingTicks < 0)
12843
remainingTicks = 0;
12844
goto updateLoop;
12845
}
12846
12847
if (timerOnOffDelay)
12848
{
12849
// Apply Timer
12850
if (timerOnOffDelay & 1)
12851
{
12852
timer0ClockReload = TIMER_TICKS[timer0Value & 3];
12853
if(!timer0On && (timer0Value & 0x80)) {
12854
// reload the counter
12855
io_registers[REG_TM0D] = timer0Reload;
12856
timer0Ticks = (0x10000 - io_registers[REG_TM0D]) << timer0ClockReload;
12857
UPDATE_REG(0x100, io_registers[REG_TM0D]);
12858
}
12859
timer0On = timer0Value & 0x80 ? true : false;
12860
io_registers[REG_TM0CNT] = timer0Value & 0xC7;
12861
UPDATE_REG(0x102, io_registers[REG_TM0CNT]);
12862
}
12863
if (timerOnOffDelay & 2)
12864
{
12865
timer1ClockReload = TIMER_TICKS[timer1Value & 3];
12866
if(!timer1On && (timer1Value & 0x80)) {
12867
// reload the counter
12868
io_registers[REG_TM1D] = timer1Reload;
12869
timer1Ticks = (0x10000 - io_registers[REG_TM1D]) << timer1ClockReload;
12870
UPDATE_REG(0x104, io_registers[REG_TM1D]);
12871
}
12872
timer1On = timer1Value & 0x80 ? true : false;
12873
io_registers[REG_TM1CNT] = timer1Value & 0xC7;
12874
UPDATE_REG(0x106, io_registers[REG_TM1CNT]);
12875
}
12876
if (timerOnOffDelay & 4)
12877
{
12878
timer2ClockReload = TIMER_TICKS[timer2Value & 3];
12879
if(!timer2On && (timer2Value & 0x80)) {
12880
// reload the counter
12881
io_registers[REG_TM2D] = timer2Reload;
12882
timer2Ticks = (0x10000 - io_registers[REG_TM2D]) << timer2ClockReload;
12883
UPDATE_REG(0x108, io_registers[REG_TM2D]);
12884
}
12885
timer2On = timer2Value & 0x80 ? true : false;
12886
io_registers[REG_TM2CNT] = timer2Value & 0xC7;
12887
UPDATE_REG(0x10A, io_registers[REG_TM2CNT]);
12888
}
12889
if (timerOnOffDelay & 8)
12890
{
12891
timer3ClockReload = TIMER_TICKS[timer3Value & 3];
12892
if(!timer3On && (timer3Value & 0x80)) {
12893
// reload the counter
12894
io_registers[REG_TM3D] = timer3Reload;
12895
timer3Ticks = (0x10000 - io_registers[REG_TM3D]) << timer3ClockReload;
12896
UPDATE_REG(0x10C, io_registers[REG_TM3D]);
12897
}
12898
timer3On = timer3Value & 0x80 ? true : false;
12899
io_registers[REG_TM3CNT] = timer3Value & 0xC7;
12900
UPDATE_REG(0x10E, io_registers[REG_TM3CNT]);
12901
}
12902
cpuNextEvent = CPUUpdateTicks();
12903
timerOnOffDelay = 0;
12904
// End of Apply Timer
12905
}
12906
12907
if(cpuNextEvent > ticks)
12908
cpuNextEvent = ticks;
12909
12910
if(ticks <= 0 || framedone)
12911
break;
12912
12913
}
12914
}while(1);
12915
}
12916
12917
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
12918
// END GBA.CPP
12919
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
12920
12921
void Gigazoid_Init()
12922
{
12923
// one time constructor stuff
12924
12925
flashState = FLASH_READ_ARRAY;
12926
flashReadState = FLASH_READ_ARRAY;
12927
flashSize = 0x10000;
12928
flashDeviceID = 0x1b;
12929
flashManufacturerID = 0x32;
12930
flashBank = 0;
12931
12932
eepromMode = EEPROM_IDLE;
12933
12934
eepromInUse = false;
12935
eepromSize = 512;
12936
12937
// this is constant now
12938
// soundSampleRate = 22050;
12939
12940
soundEnableFlag = 0x3ff; /* emulator channels enabled*/
12941
12942
armState = true;
12943
armIrqEnable = true;
12944
armMode = 0x1f;
12945
12946
renderLine = &Gigazoid::mode0RenderLine;
12947
12948
#define ARRAYINIT(n) memcpy((n), (n##_init), sizeof(n))
12949
ARRAYINIT(memoryWait);
12950
ARRAYINIT(memoryWaitSeq);
12951
ARRAYINIT(memoryWait32);
12952
ARRAYINIT(memoryWaitSeq32);
12953
#undef ARRAYINIT
12954
}
12955
12956
u32 *systemVideoFrameDest;
12957
u32 *systemVideoFramePalette;
12958
s16 *systemAudioFrameDest;
12959
int *systemAudioFrameSamp;
12960
bool lagged;
12961
12962
void (*scanlineCallback)();
12963
int scanlineCallbackLine;
12964
12965
void (*fetchCallback)(u32 addr);
12966
void (*writeCallback)(u32 addr);
12967
void (*readCallback)(u32 addr);
12968
void (*traceCallback)(u32 addr, u32 opcode);
12969
12970
void (*padCallback)();
12971
12972
void systemDrawScreen (void)
12973
{
12974
// upconvert 555->888 (TODO: BETTER)
12975
for (int i = 0; i < 240 * 160; i++)
12976
{
12977
u32 input = pix[i];
12978
/*
12979
u32 output = 0xff000000 |
12980
input << 9 & 0xf80000 |
12981
input << 6 & 0xf800 |
12982
input << 3 & 0xf8;
12983
*/
12984
u32 output = systemVideoFramePalette[input];
12985
systemVideoFrameDest[i] = output;
12986
}
12987
systemVideoFrameDest = nullptr;
12988
systemVideoFramePalette = nullptr;
12989
}
12990
12991
// called at regular intervals on sound clock
12992
void systemOnWriteDataToSoundBuffer(int16_t * finalWave, int length)
12993
{
12994
memcpy(systemAudioFrameDest, finalWave, length * 2);
12995
systemAudioFrameDest = nullptr;
12996
*systemAudioFrameSamp = length / 2;
12997
systemAudioFrameSamp = nullptr;
12998
}
12999
13000
void UpdateJoypad()
13001
{
13002
/* update joystick information */
13003
io_registers[REG_P1] = 0x03FF ^ (joy & 0x3FF);
13004
#if 0
13005
if(cpuEEPROMSensorEnabled)
13006
systemUpdateMotionSensor();
13007
#endif
13008
UPDATE_REG(0x130, io_registers[REG_P1]);
13009
io_registers[REG_P1CNT] = READ16LE(((uint16_t *)&ioMem[0x132]));
13010
13011
// this seems wrong, but there are cases where the game
13012
// can enter the stop state without requesting an IRQ from
13013
// the joypad.
13014
if((io_registers[REG_P1CNT] & 0x4000) || stopState) {
13015
uint16_t p1 = (0x3FF ^ io_registers[REG_P1CNT]) & 0x3FF;
13016
if(io_registers[REG_P1CNT] & 0x8000) {
13017
if(p1 == (io_registers[REG_P1CNT] & 0x3FF)) {
13018
io_registers[REG_IF] |= 0x1000;
13019
UPDATE_REG(0x202, io_registers[REG_IF]);
13020
}
13021
} else {
13022
if(p1 & io_registers[REG_P1CNT]) {
13023
io_registers[REG_IF] |= 0x1000;
13024
UPDATE_REG(0x202, io_registers[REG_IF]);
13025
}
13026
}
13027
}
13028
}
13029
13030
public:
13031
13032
template<bool isReader>void SyncState(NewState *ns)
13033
{
13034
NSS(flashSaveMemory);
13035
NSS(flashState);
13036
NSS(flashReadState);
13037
NSS(flashSize);
13038
NSS(flashDeviceID);
13039
NSS(flashManufacturerID);
13040
NSS(flashBank);
13041
13042
NSS(eepromMode);
13043
NSS(eepromByte);
13044
NSS(eepromBits);
13045
NSS(eepromAddress);
13046
NSS(eepromData);
13047
NSS(eepromBuffer);
13048
NSS(eepromInUse);
13049
NSS(eepromSize);
13050
13051
NSS(rtcClockData);
13052
NSS(rtcEnabled);
13053
SSS(rtcInternalTime);
13054
NSS(RTCTicks);
13055
NSS(RTCUseRealTime);
13056
13057
NSS(soundTicksUp);
13058
NSS(soundEnableFlag);
13059
SSS_HACKY(pcm[0], this);
13060
SSS_HACKY(pcm[1], this);
13061
SSS(pcm_synth);
13062
13063
SSS(bufs_buffer[0]);
13064
SSS(bufs_buffer[1]);
13065
SSS(bufs_buffer[2]);
13066
NSS(mixer_samples_read);
13067
13068
SSS(gb_apu);
13069
13070
NSS(cpuNextEvent);
13071
NSS(holdState);
13072
NSS(cpuPrefetch);
13073
NSS(cpuTotalTicks);
13074
NSS(memoryWait);
13075
NSS(memoryWaitSeq);
13076
NSS(memoryWait32);
13077
NSS(memoryWaitSeq32);
13078
NSS(biosProtected);
13079
NSS(cpuBitsSet);
13080
13081
NSS(N_FLAG);
13082
NSS(C_FLAG);
13083
NSS(Z_FLAG);
13084
NSS(V_FLAG);
13085
NSS(armState);
13086
NSS(armIrqEnable);
13087
NSS(armMode);
13088
13089
NSS(io_registers);
13090
13091
NSS(MOSAIC);
13092
13093
NSS(BG2X_L);
13094
NSS(BG2X_H);
13095
NSS(BG2Y_L);
13096
NSS(BG2Y_H);
13097
NSS(BG3X_L);
13098
NSS(BG3X_H);
13099
NSS(BG3Y_L);
13100
NSS(BG3Y_H);
13101
NSS(BLDMOD);
13102
NSS(COLEV);
13103
NSS(COLY);
13104
NSS(DM0SAD_L);
13105
NSS(DM0SAD_H);
13106
NSS(DM0DAD_L);
13107
NSS(DM0DAD_H);
13108
NSS(DM0CNT_L);
13109
NSS(DM0CNT_H);
13110
NSS(DM1SAD_L);
13111
NSS(DM1SAD_H);
13112
NSS(DM1DAD_L);
13113
NSS(DM1DAD_H);
13114
NSS(DM1CNT_L);
13115
NSS(DM1CNT_H);
13116
NSS(DM2SAD_L);
13117
NSS(DM2SAD_H);
13118
NSS(DM2DAD_L);
13119
NSS(DM2DAD_H);
13120
NSS(DM2CNT_L);
13121
NSS(DM2CNT_H);
13122
NSS(DM3SAD_L);
13123
NSS(DM3SAD_H);
13124
NSS(DM3DAD_L);
13125
NSS(DM3DAD_H);
13126
NSS(DM3CNT_L);
13127
NSS(DM3CNT_H);
13128
13129
NSS(timerOnOffDelay);
13130
NSS(timer0Value);
13131
NSS(dma0Source);
13132
NSS(dma0Dest);
13133
NSS(dma1Source);
13134
NSS(dma1Dest);
13135
NSS(dma2Source);
13136
NSS(dma2Dest);
13137
NSS(dma3Source);
13138
NSS(dma3Dest);
13139
13140
EBS(cpuSaveGameFunc, 0);
13141
EVS(cpuSaveGameFunc, &Gigazoid::flashWrite, 1);
13142
EVS(cpuSaveGameFunc, &Gigazoid::sramWrite, 2);
13143
EVS(cpuSaveGameFunc, &Gigazoid::flashSaveDecide, 3);
13144
EVS(cpuSaveGameFunc, &Gigazoid::dummyWrite, 4);
13145
EES(cpuSaveGameFunc, nullptr);
13146
13147
NSS(fxOn);
13148
NSS(windowOn);
13149
NSS(cpuDmaTicksToUpdate);
13150
NSS(IRQTicks);
13151
NSS(intState);
13152
13153
NSS(bus);
13154
NSS(graphics);
13155
13156
// map; // values never change
13157
13158
NSS(clockTicks);
13159
13160
NSS(romSize);
13161
NSS(line);
13162
NSS(gfxInWin);
13163
NSS(lineOBJpixleft);
13164
NSS(joy);
13165
13166
NSS(gfxBG2Changed);
13167
NSS(gfxBG3Changed);
13168
13169
NSS(gfxBG2X);
13170
NSS(gfxBG2Y);
13171
NSS(gfxBG3X);
13172
NSS(gfxBG3Y);
13173
13174
NSS(ioReadable);
13175
13176
NSS(stopState);
13177
13178
NSS(timer0On);
13179
NSS(timer0Ticks);
13180
NSS(timer0Reload);
13181
NSS(timer0ClockReload);
13182
NSS(timer1Value);
13183
NSS(timer1On);
13184
NSS(timer1Ticks);
13185
NSS(timer1Reload);
13186
NSS(timer1ClockReload);
13187
NSS(timer2Value);
13188
NSS(timer2On);
13189
NSS(timer2Ticks);
13190
NSS(timer2Reload);
13191
NSS(timer2ClockReload);
13192
NSS(timer3Value);
13193
NSS(timer3On);
13194
NSS(timer3Ticks);
13195
NSS(timer3Reload);
13196
NSS(timer3ClockReload);
13197
13198
NSS(skipBios);
13199
NSS(cpuSaveType);
13200
NSS(mirroringEnable);
13201
13202
NSS(cpuDmaCount);
13203
13204
NSS(internalRAM);
13205
NSS(workRAM);
13206
NSS(vram);
13207
NSS(pix);
13208
NSS(oam);
13209
NSS(ioMem);
13210
13211
NSS(cpuEEPROMEnabled);
13212
NSS(cpuEEPROMSensorEnabled);
13213
13214
EBS(renderLine, 0);
13215
EVS(renderLine, &Gigazoid::mode0RenderLine, 0x01);
13216
EVS(renderLine, &Gigazoid::mode0RenderLineNoWindow, 0x02);
13217
EVS(renderLine, &Gigazoid::mode0RenderLineAll, 0x03);
13218
EVS(renderLine, &Gigazoid::mode1RenderLine, 0x11);
13219
EVS(renderLine, &Gigazoid::mode1RenderLineNoWindow, 0x12);
13220
EVS(renderLine, &Gigazoid::mode1RenderLineAll, 0x13);
13221
EVS(renderLine, &Gigazoid::mode2RenderLine, 0x21);
13222
EVS(renderLine, &Gigazoid::mode2RenderLineNoWindow, 0x22);
13223
EVS(renderLine, &Gigazoid::mode2RenderLineAll, 0x23);
13224
EVS(renderLine, &Gigazoid::mode3RenderLine, 0x31);
13225
EVS(renderLine, &Gigazoid::mode3RenderLineNoWindow, 0x32);
13226
EVS(renderLine, &Gigazoid::mode3RenderLineAll, 0x33);
13227
EVS(renderLine, &Gigazoid::mode4RenderLine, 0x41);
13228
EVS(renderLine, &Gigazoid::mode4RenderLineNoWindow, 0x42);
13229
EVS(renderLine, &Gigazoid::mode4RenderLineAll, 0x43);
13230
EVS(renderLine, &Gigazoid::mode5RenderLine, 0x51);
13231
EVS(renderLine, &Gigazoid::mode5RenderLineNoWindow, 0x52);
13232
EVS(renderLine, &Gigazoid::mode5RenderLineAll, 0x53);
13233
EES(renderLine, nullptr);
13234
13235
NSS(render_line_all_enabled);
13236
13237
// address_lut; // values never change
13238
13239
NSS(lagged);
13240
}
13241
13242
// load a legacy battery ram file to a place where it might work, who knows
13243
void LoadLegacyBatteryRam(const char *data, int len)
13244
{
13245
std::memcpy(eepromData, data, std::min<int>(len, sizeof(eepromData)));
13246
std::memcpy(flashSaveMemory, data, std::min<int>(len, sizeof(flashSaveMemory)));
13247
if (len <= 0x10000)
13248
{
13249
// can salvage broken pokeymans saves in some cases
13250
std::memcpy(flashSaveMemory + 0x10000, data, std::min<int>(len, 0x10000));
13251
}
13252
}
13253
13254
bool HasBatteryRam()
13255
{
13256
return cpuSaveType != 5;
13257
}
13258
13259
int BatteryRamSize()
13260
{
13261
switch (cpuSaveType)
13262
{
13263
default:
13264
case 0: // auto
13265
return 0x10000;
13266
case 1:
13267
case 4: // eeprom
13268
return eepromSize;
13269
case 2: // sram
13270
// should only be 32K, but vba uses 64K as a stand-in for both SRAM (guess no game ever checks mirroring?),
13271
// and for 64K flash where the program never issues any flash commands
13272
return 0x10000;
13273
case 3: // flash
13274
return flashSize;
13275
case 5: // none
13276
return 0;
13277
}
13278
}
13279
13280
void SaveLegacyBatteryRam(char *dest)
13281
{
13282
switch (cpuSaveType)
13283
{
13284
default:
13285
case 0: // auto
13286
std::memcpy(dest, flashSaveMemory, 0x10000);
13287
return;
13288
case 1:
13289
case 4: // eeprom
13290
std::memcpy(dest, eepromData, eepromSize);
13291
return;
13292
case 2: // sram
13293
// should only be 32K, but vba uses 64K as a stand-in for both SRAM (guess no game ever checks mirroring?),
13294
// and for 64K flash where the program never issues any flash commands
13295
std::memcpy(dest, flashSaveMemory, 0x10000);
13296
return;
13297
case 3: // flash
13298
std::memcpy(dest, flashSaveMemory, flashSize);
13299
return;
13300
case 5: // none
13301
return;
13302
}
13303
}
13304
13305
template<bool isReader>bool SyncBatteryRam(NewState *ns)
13306
{
13307
// if we were given a positive ID from the gamedb, we can choose to save/load only that type
13308
// else, we save\load everything -- even if we used our knowledge of the current state to
13309
// save only what was needed, we'd have to save that metadata as well for load
13310
13311
// file id detection
13312
char batteryramid[8];
13313
std::memcpy(batteryramid, "GBABATT\0", 8);
13314
NSS(batteryramid);
13315
if (std::memcmp(batteryramid, "GBABATT\0", 8) != 0)
13316
return false;
13317
13318
int flashFileSize;
13319
int eepromFileSize;
13320
13321
// when writing, try to figure out the sizes as smartly as we can
13322
switch (cpuSaveType)
13323
{
13324
default:
13325
case 0: // auto
13326
flashFileSize = 0x20000;
13327
eepromFileSize = 0x2000;
13328
break;
13329
case 1:
13330
case 4: // eeprom
13331
flashFileSize = 0;
13332
eepromFileSize = eepromSize;
13333
break;
13334
case 2: // sram
13335
// should only be 32K, but vba uses 64K as a stand-in for both SRAM (guess no game ever checks mirroring?),
13336
// and for 64K flash where the program never issues any flash commands
13337
flashFileSize = 0x10000;
13338
eepromFileSize = 0;
13339
break;
13340
case 3: // flash
13341
flashFileSize = flashSize;
13342
eepromFileSize = 0;
13343
break;
13344
case 5: // none
13345
flashFileSize = 0;
13346
eepromFileSize = 0;
13347
break;
13348
}
13349
NSS(flashFileSize);
13350
NSS(eepromFileSize);
13351
// when reading, cap to allowable limits. any save file with numbers larger than this is not legal.
13352
flashFileSize = std::min<int>(flashFileSize, sizeof(flashSaveMemory));
13353
eepromFileSize = std::min<int>(eepromFileSize, sizeof(eepromData));
13354
13355
PSS(flashSaveMemory, flashFileSize);
13356
PSS(eepromData, eepromFileSize);
13357
13358
return true;
13359
}
13360
13361
Gigazoid()
13362
{
13363
Gigazoid_Init();
13364
}
13365
13366
~Gigazoid()
13367
{
13368
}
13369
13370
bool LoadRom(const u8 *romfile, const u32 romfilelen, const u8 *biosfile, const u32 biosfilelen, const FrontEndSettings &settings)
13371
{
13372
if (biosfilelen != 16384)
13373
return false;
13374
13375
if (!CPULoadRom(romfile, romfilelen))
13376
return false;
13377
13378
cpuSaveType = settings.cpuSaveType;
13379
flashSize = settings.flashSize;
13380
rtcEnabled = settings.enableRtc;
13381
mirroringEnable = settings.mirroringEnable;
13382
skipBios = settings.skipBios;
13383
13384
RTCUseRealTime = settings.RTCuseRealTime;
13385
rtcInternalTime.hour = settings.RTChour;
13386
rtcInternalTime.mday = settings.RTCmday;
13387
rtcInternalTime.min = settings.RTCmin;
13388
rtcInternalTime.month = settings.RTCmonth;
13389
rtcInternalTime.sec = settings.RTCsec;
13390
rtcInternalTime.wday = settings.RTCwday;
13391
rtcInternalTime.year = settings.RTCyear;
13392
13393
if(flashSize == 0x10000)
13394
{
13395
flashDeviceID = 0x1b;
13396
flashManufacturerID = 0x32;
13397
}
13398
else
13399
{
13400
flashDeviceID = 0x13; //0x09;
13401
flashManufacturerID = 0x62; //0xc2;
13402
}
13403
13404
doMirroring(mirroringEnable);
13405
13406
CPUInit(biosfile, biosfilelen);
13407
CPUReset();
13408
13409
// CPUReset already calls this, but if that were to change
13410
// soundReset();
13411
13412
return true;
13413
}
13414
13415
void Reset()
13416
{
13417
CPUReset();
13418
}
13419
13420
bool FrameAdvance(int input, u32 *videobuffer, s16 *audiobuffer, int *numsamp, u32 *videopalette)
13421
{
13422
joy = input;
13423
systemVideoFrameDest = videobuffer;
13424
systemVideoFramePalette = videopalette;
13425
systemAudioFrameDest = audiobuffer;
13426
systemAudioFrameSamp = numsamp;
13427
lagged = true;
13428
UpdateJoypad();
13429
do
13430
{
13431
CPULoop();
13432
} while (systemVideoFrameDest);
13433
return lagged;
13434
}
13435
13436
void FillMemoryAreas(MemoryAreas &mem)
13437
{
13438
mem.bios = bios;
13439
mem.iwram = internalRAM;
13440
mem.ewram = workRAM;
13441
mem.palram = graphics.paletteRAM;
13442
mem.mmio = ioMem;
13443
mem.rom = rom;
13444
mem.vram = vram;
13445
mem.oam = oam;
13446
switch (cpuSaveType)
13447
{
13448
default:
13449
case 0: // auto
13450
mem.sram = flashSaveMemory;
13451
mem.sram_size = 0x10000;;
13452
return;
13453
case 1:
13454
case 4: // eeprom
13455
mem.sram = eepromData;
13456
mem.sram_size = eepromSize;
13457
return;
13458
case 2: // sram
13459
mem.sram = flashSaveMemory;
13460
mem.sram_size = 0x10000;
13461
return;
13462
case 3: // flash
13463
mem.sram = flashSaveMemory;
13464
mem.sram_size = flashSize;
13465
return;
13466
case 5: // none
13467
return;
13468
}
13469
}
13470
13471
void BusWrite(u32 addr, u8 val)
13472
{
13473
CPUWriteByte(addr, val);
13474
}
13475
u8 BusRead(u32 addr)
13476
{
13477
return CPUReadByte(addr);
13478
}
13479
13480
void SetScanlineCallback(void (*cb)(), int scanline)
13481
{
13482
// the sequence of calls in a frame will be:
13483
// 160,161,...,227,0,1,...,160
13484
// calls coincide with entering hblank, or something like that
13485
if (scanline < 0 || scanline > 227)
13486
cb = nullptr;
13487
scanlineCallback = cb;
13488
scanlineCallbackLine = scanline;
13489
}
13490
13491
uint32_t *GetRegisters()
13492
{
13493
return &bus.reg[0].I;
13494
}
13495
13496
void SetPadCallback(void (*cb)())
13497
{
13498
// before each read of the pad regs
13499
padCallback = cb;
13500
}
13501
13502
void SetFetchCallback(void (*cb)(u32 addr))
13503
{
13504
// before each opcode fetch
13505
fetchCallback = cb;
13506
}
13507
13508
void SetReadCallback(void (*cb)(u32 addr))
13509
{
13510
// before each read, not including opcodes, including pad regs
13511
readCallback = cb;
13512
}
13513
13514
void SetWriteCallback(void (*cb)(u32 addr))
13515
{
13516
// before each write
13517
writeCallback = cb;
13518
}
13519
13520
void SetTraceCallback(void (*cb)(u32 addr, u32 opcode))
13521
{
13522
// before each opcode fetch
13523
traceCallback = cb;
13524
}
13525
13526
}; // class Gigazoid
13527
13528
// zeroing mem operators: these are very important
13529
void *operator new(std::size_t n)
13530
{
13531
void *p = std::malloc(n);
13532
std::memset(p, 0, n);
13533
return p;
13534
}
13535
void operator delete(void *p)
13536
{
13537
std::free(p);
13538
}
13539
13540
#define EXPORT extern "C" __declspec(dllexport)
13541
13542
// public interface follows
13543
EXPORT Gigazoid *Create()
13544
{
13545
return new Gigazoid();
13546
}
13547
13548
EXPORT void Destroy(Gigazoid *g)
13549
{
13550
delete g;
13551
}
13552
13553
EXPORT int LoadRom(Gigazoid *g, const u8 *romfile, const u32 romfilelen, const u8 *biosfile, const u32 biosfilelen, const FrontEndSettings *settings)
13554
{
13555
return g->LoadRom(romfile, romfilelen, biosfile, biosfilelen, *settings);
13556
}
13557
13558
EXPORT void Reset(Gigazoid *g)
13559
{
13560
// TODO: this calls a soundreset that seems to remake some buffers. that seems like it should be fixed?
13561
g->Reset();
13562
}
13563
13564
EXPORT int FrameAdvance(Gigazoid *g, int input, u32 *videobuffer, s16 *audiobuffer, int *numsamp, u32 *videopalette)
13565
{
13566
return g->FrameAdvance(input, videobuffer, audiobuffer, numsamp, videopalette);
13567
}
13568
13569
EXPORT int SaveRamSize(Gigazoid *g)
13570
{
13571
/*
13572
if (g->HasBatteryRam())
13573
{
13574
NewStateDummy dummy;
13575
g->SyncBatteryRam<false>(&dummy);
13576
return dummy.GetLength();
13577
}
13578
else
13579
{
13580
return 0;
13581
}*/
13582
return g->BatteryRamSize();
13583
}
13584
13585
EXPORT int SaveRamSave(Gigazoid *g, char *data, int length)
13586
{
13587
/*
13588
if (g->HasBatteryRam())
13589
{
13590
NewStateExternalBuffer saver(data, length);
13591
g->SyncBatteryRam<false>(&saver);
13592
return !saver.Overflow() && saver.GetLength() == length;
13593
}
13594
else
13595
{
13596
return false;
13597
}*/
13598
if (!g->HasBatteryRam() || length != g->BatteryRamSize())
13599
return false;
13600
g->SaveLegacyBatteryRam(data);
13601
return true;
13602
}
13603
13604
EXPORT int SaveRamLoad(Gigazoid *g, const char *data, int length)
13605
{
13606
if (g->HasBatteryRam())
13607
{
13608
NewStateExternalBuffer loader(const_cast<char *>(data), length);
13609
if (g->SyncBatteryRam<true>(&loader))
13610
{
13611
return !loader.Overflow() && loader.GetLength() == length;
13612
}
13613
else
13614
{
13615
// couldn't find the magic signature at the top, so try a salvage load
13616
g->LoadLegacyBatteryRam(data, length);
13617
return true;
13618
}
13619
}
13620
else
13621
{
13622
return false;
13623
}
13624
}
13625
13626
EXPORT int BinStateSize(Gigazoid *g)
13627
{
13628
NewStateDummy dummy;
13629
g->SyncState<false>(&dummy);
13630
return dummy.GetLength();
13631
}
13632
13633
EXPORT int BinStateSave(Gigazoid *g, char *data, int length)
13634
{
13635
NewStateExternalBuffer saver(data, length);
13636
g->SyncState<false>(&saver);
13637
return !saver.Overflow() && saver.GetLength() == length;
13638
}
13639
13640
EXPORT int BinStateLoad(Gigazoid *g, const char *data, int length)
13641
{
13642
NewStateExternalBuffer loader(const_cast<char *>(data), length);
13643
g->SyncState<true>(&loader);
13644
return !loader.Overflow() && loader.GetLength() == length;
13645
}
13646
13647
EXPORT void TxtStateSave(Gigazoid *g, FPtrs *ff)
13648
{
13649
NewStateExternalFunctions saver(ff);
13650
g->SyncState<false>(&saver);
13651
}
13652
13653
EXPORT void TxtStateLoad(Gigazoid *g, FPtrs *ff)
13654
{
13655
NewStateExternalFunctions loader(ff);
13656
g->SyncState<true>(&loader);
13657
}
13658
13659
EXPORT void GetMemoryAreas(Gigazoid *g, MemoryAreas *mem)
13660
{
13661
g->FillMemoryAreas(*mem);
13662
}
13663
13664
EXPORT void SystemBusWrite(Gigazoid *g, u32 addr, u8 val)
13665
{
13666
g->BusWrite(addr, val);
13667
}
13668
13669
EXPORT u8 SystemBusRead(Gigazoid *g, u32 addr)
13670
{
13671
return g->BusRead(addr);
13672
}
13673
13674
EXPORT void SetScanlineCallback(Gigazoid *g, void (*cb)(), int scanline)
13675
{
13676
g->SetScanlineCallback(cb, scanline);
13677
}
13678
13679
EXPORT void SetTraceCallback(Gigazoid *g, void (*cb)(u32 addr, u32 opcode))
13680
{
13681
g->SetTraceCallback(cb);
13682
}
13683
13684
EXPORT u32 *GetRegisters(Gigazoid *g)
13685
{
13686
return g->GetRegisters();
13687
}
13688
13689
EXPORT void SetPadCallback(Gigazoid *g, void (*cb)()) { g->SetPadCallback(cb); }
13690
EXPORT void SetFetchCallback(Gigazoid *g, void (*cb)(u32 addr)) { g->SetFetchCallback(cb); }
13691
EXPORT void SetReadCallback(Gigazoid *g, void (*cb)(u32 addr)) { g->SetReadCallback(cb); }
13692
EXPORT void SetWriteCallback(Gigazoid *g, void (*cb)(u32 addr)) { g->SetWriteCallback(cb); }
13693
13694
13695
#include "optable.inc"
13696
13697