@@ -41,6 +41,7 @@ public class ExROM : NES.NESBoardBase
41
41
IntBuffer b_banks_1k = new IntBuffer ( 8 ) ;
42
42
IntBuffer prg_banks_8k = new IntBuffer ( 4 ) ;
43
43
byte product_low , product_high ;
44
+ int last_nt_read ;
44
45
45
46
public override void SyncState ( Serializer ser )
46
47
{
@@ -54,14 +55,15 @@ public override void SyncState(Serializer ser)
54
55
ser . Sync ( "chr_mode" , ref chr_mode ) ;
55
56
ser . Sync ( "prg_mode" , ref prg_mode ) ;
56
57
ser . Sync ( "chr_reg_high" , ref chr_reg_high ) ;
57
- ser . Sync ( "ab_mode" , ref chr_reg_high ) ;
58
+ ser . Sync ( "ab_mode" , ref ab_mode ) ;
58
59
ser . Sync ( "regs_a" , ref regs_a ) ;
59
60
ser . Sync ( "regs_b" , ref regs_b ) ;
60
61
ser . Sync ( "regs_prg" , ref regs_prg ) ;
61
62
ser . Sync ( "nt_modes" , ref nt_modes ) ;
62
63
ser . Sync ( "nt_fill_tile" , ref nt_fill_tile ) ;
63
64
ser . Sync ( "nt_fill_attrib" , ref nt_fill_attrib ) ;
64
65
ser . Sync ( "wram_bank" , ref wram_bank ) ;
66
+ ser . Sync ( "last_nt_read" , ref last_nt_read ) ;
65
67
ser . Sync ( "EXRAM" , ref EXRAM , false ) ;
66
68
67
69
if ( ser . IsReader )
@@ -91,6 +93,9 @@ public override bool Configure(NES.EDetectionOrigin origin)
91
93
case "NES-ELROM" : //Castlevania 3 - Dracula's Curse (U)
92
94
AssertPrg ( 128 , 256 ) ; AssertChr ( 128 ) ;
93
95
break ;
96
+ case "NES-EKROM" : //Gemfire (U)
97
+ AssertPrg ( 256 ) ; AssertChr ( 256 ) ;
98
+ break ;
94
99
case "MAPPER5" :
95
100
break ;
96
101
default :
@@ -139,12 +144,40 @@ int MapPRG(int addr, out bool ram)
139
144
return ( bank_8k << 13 ) | ofs ;
140
145
}
141
146
147
+ //this could be handy, but probably not. I did it on accident.
148
+ //TileCoord ComputeTXTYFromPPUTiming(int visible_scanline, int cycle)
149
+ //{
150
+ // int py = visible_scanline;
151
+ // int px = cycle;
152
+ // if (cycle > 260)
153
+ // {
154
+ // py++;
155
+ // px -= 322;
156
+ // }
157
+ // else px += 16;
158
+ // int tx = px / 8;
159
+ // int ty = py / 8;
160
+ // return new TileCoord(tx, ty);
161
+ //}
162
+
142
163
int MapCHR ( int addr )
143
164
{
144
165
int bank_1k = addr >> 10 ;
145
166
int ofs = addr & ( ( 1 << 10 ) - 1 ) ;
146
167
168
+ if ( exram_mode == 1 && NES . ppu . ppuphase == Nintendo . NES . PPU . PPUPHASE . BG )
169
+ {
170
+ int exram_addr = last_nt_read ;
171
+ int bank_4k = EXRAM [ exram_addr ] & 0x3F ;
172
+
173
+ bank_1k = bank_4k * 4 ;
174
+ bank_1k += chr_reg_high << 2 ;
175
+ ofs = addr & ( 4 * 1024 - 1 ) ;
176
+ goto MAPPED ;
177
+ }
178
+
147
179
//wish this logic could be smaller..
180
+ //how does this KNOW that its in 8x16 sprites? the pattern of reads... emulate it that way..
148
181
if ( NES . ppu . reg_2000 . obj_size_16 )
149
182
{
150
183
if ( NES . ppu . ppuphase == NES . PPU . PPUPHASE . OBJ )
@@ -157,11 +190,8 @@ int MapCHR(int addr)
157
190
bank_1k = a_banks_1k [ bank_1k ] ;
158
191
else
159
192
bank_1k = b_banks_1k [ bank_1k ] ;
160
-
161
- //something like this..?
162
- //bool special_sel = NES.ppu.reg_2000.obj_size_16 && NES.ppu.ppuphase == NES.PPU.PPUPHASE.OBJ;
163
- //bool a_sel = special_sel || (!a_sel && ab_mode == 0);
164
-
193
+
194
+ MAPPED :
165
195
bank_1k &= chr_bank_mask_1k ;
166
196
addr = ( bank_1k << 10 ) | ofs ;
167
197
return addr ;
@@ -177,6 +207,33 @@ public override byte ReadPPU(int addr)
177
207
else
178
208
{
179
209
addr -= 0x2000 ;
210
+ int nt_entry = addr & 0x3FF ;
211
+ if ( nt_entry < 0x3C0 )
212
+ {
213
+ //track the last nametable entry read so that subsequent pattern and attribute reads will know which exram address to use
214
+ last_nt_read = nt_entry ;
215
+ }
216
+ else
217
+ {
218
+ //attribute table
219
+ if ( exram_mode == 1 )
220
+ {
221
+ //attribute will be in the top 2 bits of the exram byte
222
+ int exram_addr = last_nt_read ;
223
+ int attribute = EXRAM [ exram_addr ] >> 6 ;
224
+ //calculate tile address by getting x/y from last nametable
225
+ int tx = last_nt_read & 0x1F ;
226
+ int ty = last_nt_read / 32 ;
227
+ //attribute table address is just these coords shifted
228
+ int atx = tx >> 1 ;
229
+ int aty = ty >> 1 ;
230
+ //figure out how we need to shift the attribute to fake out the ppu
231
+ int at_shift = ( ( aty & 1 ) << 1 ) + ( atx & 1 ) ;
232
+ at_shift <<= 1 ;
233
+ attribute <<= at_shift ;
234
+ return ( byte ) attribute ;
235
+ }
236
+ }
180
237
int nt = addr >> 10 ;
181
238
int offset = addr & ( ( 1 << 10 ) - 1 ) ;
182
239
nt = nt_modes [ nt ] ;
@@ -473,24 +530,28 @@ void SyncCHRBanks()
473
530
//MASTER LOGIC: something like this this might be enough to work, but i'll play with it later
474
531
//bank_1k >> (3 - chr_mode) << chr_mode | bank_1k & ( etc.etc.
475
532
533
+ //TODO - do these need to have the last arguments multiplied by 8,4,2 to map to the right banks?
476
534
switch ( chr_mode )
477
535
{
478
536
case 0 :
479
- SetBank ( a_banks_1k , 0 , 8 , regs_a [ 7 ] ) ;
480
- SetBank ( b_banks_1k , 0 , 8 , regs_a [ 7 ] ) ;
537
+ SetBank ( a_banks_1k , 0 , 8 , regs_a [ 7 ] * 8 ) ;
538
+ SetBank ( b_banks_1k , 0 , 8 , regs_b [ 3 ] * 8 ) ;
481
539
break ;
482
540
case 1 :
483
- SetBank ( a_banks_1k , 0 , 4 , regs_a [ 3 ] ) ;
484
- SetBank ( a_banks_1k , 4 , 4 , regs_a [ 7 ] ) ;
485
- SetBank ( b_banks_1k , 0 , 4 , regs_b [ 3 ] ) ;
541
+ SetBank ( a_banks_1k , 0 , 4 , regs_a [ 3 ] * 4 ) ;
542
+ SetBank ( a_banks_1k , 4 , 4 , regs_a [ 7 ] * 4 ) ;
543
+ SetBank ( b_banks_1k , 0 , 4 , regs_b [ 3 ] * 4 ) ;
544
+ SetBank ( b_banks_1k , 4 , 4 , regs_b [ 3 ] * 4 ) ;
486
545
break ;
487
546
case 2 :
488
- SetBank ( a_banks_1k , 0 , 2 , regs_a [ 1 ] ) ;
489
- SetBank ( a_banks_1k , 2 , 2 , regs_a [ 3 ] ) ;
490
- SetBank ( a_banks_1k , 4 , 2 , regs_a [ 5 ] ) ;
491
- SetBank ( a_banks_1k , 6 , 2 , regs_a [ 7 ] ) ;
492
- SetBank ( b_banks_1k , 0 , 2 , regs_b [ 1 ] ) ;
493
- SetBank ( b_banks_1k , 2 , 2 , regs_b [ 3 ] ) ;
547
+ SetBank ( a_banks_1k , 0 , 2 , regs_a [ 1 ] * 2 ) ;
548
+ SetBank ( a_banks_1k , 2 , 2 , regs_a [ 3 ] * 2 ) ;
549
+ SetBank ( a_banks_1k , 4 , 2 , regs_a [ 5 ] * 2 ) ;
550
+ SetBank ( a_banks_1k , 6 , 2 , regs_a [ 7 ] * 2 ) ;
551
+ SetBank ( b_banks_1k , 0 , 2 , regs_b [ 1 ] * 2 ) ;
552
+ SetBank ( b_banks_1k , 2 , 2 , regs_b [ 3 ] * 2 ) ;
553
+ SetBank ( b_banks_1k , 4 , 2 , regs_b [ 1 ] * 2 ) ;
554
+ SetBank ( b_banks_1k , 6 , 2 , regs_b [ 3 ] * 2 ) ;
494
555
break ;
495
556
case 3 :
496
557
SetBank ( a_banks_1k , 0 , 1 , regs_a [ 0 ] ) ;
@@ -505,12 +566,13 @@ void SyncCHRBanks()
505
566
SetBank ( b_banks_1k , 1 , 1 , regs_b [ 1 ] ) ;
506
567
SetBank ( b_banks_1k , 2 , 1 , regs_b [ 2 ] ) ;
507
568
SetBank ( b_banks_1k , 3 , 1 , regs_b [ 3 ] ) ;
569
+ SetBank ( b_banks_1k , 4 , 1 , regs_b [ 0 ] ) ;
570
+ SetBank ( b_banks_1k , 5 , 1 , regs_b [ 1 ] ) ;
571
+ SetBank ( b_banks_1k , 6 , 1 , regs_b [ 2 ] ) ;
572
+ SetBank ( b_banks_1k , 7 , 1 , regs_b [ 3 ] ) ;
508
573
break ;
509
574
}
510
- b_banks_1k [ 4 ] = b_banks_1k [ 0 ] ;
511
- b_banks_1k [ 5 ] = b_banks_1k [ 1 ] ;
512
- b_banks_1k [ 6 ] = b_banks_1k [ 2 ] ;
513
- b_banks_1k [ 7 ] = b_banks_1k [ 3 ] ;
575
+
514
576
515
577
}
516
578
0 commit comments