1
/* FCE Ultra - NES/Famicom Emulator
3
* Copyright notice for this file:
4
* Copyright (C) 2002 Xodnizel
5
* Copyright (C) 2005 CaH4e3
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
12
* This program is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
* GNU General Public License for more details.
17
* You should have received a copy of the GNU General Public License
18
* along with this program; if not, write to the Free Software
19
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
// Mapper 090 is simpliest mapper hardware and have not extended nametable control and latched chr banks in 4k mode
26
// Mapper 209 much compicated hardware with decribed above features disabled by default and switchable by command
27
// Mapper 211 the same mapper 209 but with forced nametable control
32
static uint8 IRQMode; // from $c001
33
static uint8 IRQPre; // from $c004
34
static uint8 IRQPreSize; // from $c007
35
static uint8 IRQCount; // from $c005
36
static uint8 IRQXOR; // Loaded from $C006
37
static uint8 IRQa; // $c002, $c003, and $c000
42
static uint8 tkcom[4];
44
static uint8 chrlow[8];
45
static uint8 chrhigh[8];
49
static uint16 names[4];
52
static SFORMAT Tek_StateRegs[]={
53
{&IRQMode, 1, "IRQMODE"},
54
{&IRQPre, 1, "IRQPRE"},
55
{&IRQPreSize, 1, "IRQPRESIZE"},
56
{&IRQCount, 1, "IRQC"},
57
{&IRQXOR, 1, "IRQXOR"},
66
{&names[0], 2|FCEUSTATE_RLSB, "NMS0"},
67
{&names[1], 2|FCEUSTATE_RLSB, "NMS1"},
68
{&names[2], 2|FCEUSTATE_RLSB, "NMS2"},
69
{&names[3], 2|FCEUSTATE_RLSB, "NMS3"},
74
static void mira(void)
76
if((tkcom[0]&0x20&&is209)||is211)
79
if(tkcom[0]&0x40) // Name tables are ROM-only
82
setntamem(CHRptr[0]+(((names[x])&CHRmask1[0])<<10),0,x);
84
else // Name tables can be RAM or ROM.
88
if((tkcom[1]&0x80)==(names[x]&0x80)) // RAM selected.
89
setntamem(NTARAM+((names[x]&0x1)<<10),1,x);
91
setntamem(CHRptr[0]+(((names[x])&CHRmask1[0])<<10),0,x);
99
case 0: setmirror(MI_V); break;
100
case 1: setmirror(MI_H); break;
101
case 2: setmirror(MI_0); break;
102
case 3: setmirror(MI_1); break;
107
static void tekprom(void)
109
uint32 bankmode=((tkcom[3]&6)<<5);
112
case 00: if(tkcom[0]&0x80)
113
setprg8(0x6000,(((prgb[3]<<2)+3)&0x3F)|bankmode);
114
setprg32(0x8000,0x0F|((tkcom[3]&6)<<3));
116
case 01: if(tkcom[0]&0x80)
117
setprg8(0x6000,(((prgb[3]<<1)+1)&0x3F)|bankmode);
118
setprg16(0x8000,(prgb[1]&0x1F)|((tkcom[3]&6)<<4));
119
setprg16(0xC000,0x1F|((tkcom[3]&6)<<4));
121
case 03: // bit reversion
122
case 02: if(tkcom[0]&0x80)
123
setprg8(0x6000,(prgb[3]&0x3F)|bankmode);
124
setprg8(0x8000,(prgb[0]&0x3F)|bankmode);
125
setprg8(0xa000,(prgb[1]&0x3F)|bankmode);
126
setprg8(0xc000,(prgb[2]&0x3F)|bankmode);
127
setprg8(0xe000,0x3F|bankmode);
129
case 04: if(tkcom[0]&0x80)
130
setprg8(0x6000,(((prgb[3]<<2)+3)&0x3F)|bankmode);
131
setprg32(0x8000,(prgb[3]&0x0F)|((tkcom[3]&6)<<3));
133
case 05: if(tkcom[0]&0x80)
134
setprg8(0x6000,(((prgb[3]<<1)+1)&0x3F)|bankmode);
135
setprg16(0x8000,(prgb[1]&0x1F)|((tkcom[3]&6)<<4));
136
setprg16(0xC000,(prgb[3]&0x1F)|((tkcom[3]&6)<<4));
138
case 07: // bit reversion
139
case 06: if(tkcom[0]&0x80)
140
setprg8(0x6000,(prgb[3]&0x3F)|bankmode);
141
setprg8(0x8000,(prgb[0]&0x3F)|bankmode);
142
setprg8(0xa000,(prgb[1]&0x3F)|bankmode);
143
setprg8(0xc000,(prgb[2]&0x3F)|bankmode);
144
setprg8(0xe000,(prgb[3]&0x3F)|bankmode);
149
static void tekvrom(void)
151
int x, bank=0, mask=0xFFFF;
154
bank=(tkcom[3]&1)|((tkcom[3]&0x18)>>2);
155
switch (tkcom[0]&0x18)
157
case 0x00: bank<<=5; mask=0x1F; break;
158
case 0x08: bank<<=6; mask=0x3F; break;
159
case 0x10: bank<<=7; mask=0x7F; break;
160
case 0x18: bank<<=8; mask=0xFF; break;
163
switch(tkcom[0]&0x18)
166
setchr8(((chrlow[0]|(chrhigh[0]<<8))&mask)|bank);
170
// setchr4(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank);
171
setchr4(0x0000,((chrlow[chr[0]]|(chrhigh[chr[0]]<<8))&mask)|bank);
172
setchr4(0x1000,((chrlow[chr[1]]|(chrhigh[chr[1]]<<8))&mask)|bank);
176
setchr2(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank);
180
setchr1(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank);
185
static DECLFW(M90TekWrite)
189
case 0x5800: mul[0]=V; break;
190
case 0x5801: mul[1]=V; break;
191
case 0x5803: regie=V; break;
195
static DECLFR(M90TekRead)
199
case 0x5800: return (mul[0]*mul[1]);
200
case 0x5801: return((mul[0]*mul[1])>>8);
201
case 0x5803: return (regie);
202
default: return tekker;
207
static DECLFW(M90PRGWrite)
209
// FCEU_printf("bs %04x %02x\n",A,V);
214
static DECLFW(M90CHRlowWrite)
216
// FCEU_printf("bs %04x %02x\n",A,V);
221
static DECLFW(M90CHRhiWrite)
223
// FCEU_printf("bs %04x %02x\n",A,V);
228
static DECLFW(M90NTWrite)
230
// FCEU_printf("bs %04x %02x\n",A,V);
244
static DECLFW(M90IRQWrite)
246
// FCEU_printf("bs %04x %02x\n",A,V);
249
case 00: //FCEU_printf("%s IRQ (C000)\n",V&1?"Enable":"Disable");
250
IRQa=V&1;if(!(V&1)) X6502_IRQEnd(FCEU_IQEXT);break;
251
case 02: //FCEU_printf("Disable IRQ (C002) scanline=%d\n", scanline);
252
IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break;
253
case 03: //FCEU_printf("Enable IRQ (C003) scanline=%d\n", scanline);
256
// FCEU_printf("IRQ Count method: ");
257
// switch (IRQMode&3)
259
// case 00: FCEU_printf("M2 cycles\n");break;
260
// case 01: FCEU_printf("PPU A12 toggles\n");break;
261
// case 02: FCEU_printf("PPU reads\n");break;
262
// case 03: FCEU_printf("Writes to CPU space\n");break;
264
// FCEU_printf("Counter prescaler size: %s\n",(IRQMode&4)?"3 bits":"8 bits");
265
// FCEU_printf("Counter prescaler size adjust: %s\n",(IRQMode&8)?"Used C007":"Normal Operation");
266
// if((IRQMode>>6)==2) FCEU_printf("Counter Down\n");
267
// else if((IRQMode>>6)==1) FCEU_printf("Counter Up\n");
268
// else FCEU_printf("Counter Stopped\n");
270
case 04: //FCEU_printf("Pre Counter Loaded and Xored wiht C006: %d\n",V^IRQXOR);
271
IRQPre=V^IRQXOR;break;
272
case 05: //FCEU_printf("Main Counter Loaded and Xored wiht C006: %d\n",V^IRQXOR);
273
IRQCount=V^IRQXOR;break;
274
case 06: //FCEU_printf("Xor Value: %d\n",V);
276
case 07: //if(!(IRQMode&8)) FCEU_printf("C001 is clear, no effect applied\n");
277
// else if(V==0xFF) FCEU_printf("Prescaler is changed for 12bits\n");
278
// else FCEU_printf("Counter Stopped\n");
283
static DECLFW(M90ModeWrite)
285
// FCEU_printf("bs %04x %02x\n",A,V);
294
case 00: FCEU_printf("Main Control Register:\n");
295
FCEU_printf(" PGR Banking mode: %d\n",V&7);
296
FCEU_printf(" CHR Banking mode: %d\n",(V>>3)&3);
297
FCEU_printf(" 6000-7FFF addresses mapping: %s\n",(V&0x80)?"Yes":"No");
298
FCEU_printf(" Nametable control: %s\n",(V&0x20)?"Enabled":"Disabled");
300
FCEU_printf(" Nametable can be: %s\n",(V&0x40)?"ROM Only":"RAM or ROM");
302
case 01: FCEU_printf("Mirroring mode: ");
305
case 0: FCEU_printf("Vertical\n");break;
306
case 1: FCEU_printf("Horizontal\n");break;
307
case 2: FCEU_printf("Nametable 0 only\n");break;
308
case 3: FCEU_printf("Nametable 1 only\n");break;
310
FCEU_printf("Mirroring flag: %s\n",(V&0x80)?"On":"Off");
312
case 02: if((((tkcom[0])>>5)&3)==1)
313
FCEU_printf("Nametable ROM/RAM select mode: %d\n",V>>7);
316
FCEU_printf("CHR Banking mode: %s\n",(V&0x20)?"Entire CHR ROM":"256Kb Switching mode");
317
if(!(V&0x20)) FCEU_printf("256K CHR bank number: %02x\n",(V&1)|((V&0x18)>>2));
318
FCEU_printf("512K PRG bank number: %d\n",(V&6)>>1);
319
FCEU_printf("CHR Bank mirroring: %s\n",(V&0x80)?"Swapped":"Normal operate");
324
static DECLFW(M90DummyWrite)
326
// FCEU_printf("bs %04x %02x\n",A,V);
329
static void CCL(void)
331
if((IRQMode>>6) == 1) // Count Up
334
if((IRQCount == 0) && IRQa)
336
X6502_IRQBegin(FCEU_IQEXT);
339
else if((IRQMode>>6) == 2) // Count down
342
if((IRQCount == 0xFF) && IRQa)
344
X6502_IRQBegin(FCEU_IQEXT);
349
static void ClockCounter(void)
357
if((IRQMode>>6) == 1) // Count up
360
if((IRQPre & premask) == 0) CCL();
362
else if((IRQMode>>6) == 2) // Count down
365
if((IRQPre & premask) == premask) CCL();
372
if((IRQMode&3)==0) for(x=0;x<a;x++) ClockCounter();
375
static void SLWrap(void)
378
if((IRQMode&3)==1) for(x=0;x<8;x++) ClockCounter();
381
static uint32 lastread;
382
static void M90PPU(uint32 A)
398
if(h<0x20&&((h&0x0F)==0xF))
403
chr[(h&0x10)>>4]=((h&0x10)>>2);
408
chr[(h&0x10)>>4]=((h&0x10)>>2)|2;
420
static void togglie()
424
FCEU_printf("tekker=%02x\n",tekker);
425
memset(tkcom,0x00,sizeof(tkcom));
426
memset(prgb,0xff,sizeof(prgb));
431
static void M90Restore(int version)
438
static void M90Power(void)
440
SetWriteHandler(0x5000,0x5fff,M90TekWrite);
441
SetWriteHandler(0x8000,0x8ff0,M90PRGWrite);
442
SetWriteHandler(0x9000,0x9fff,M90CHRlowWrite);
443
SetWriteHandler(0xA000,0xAfff,M90CHRhiWrite);
444
SetWriteHandler(0xB000,0xBfff,M90NTWrite);
445
SetWriteHandler(0xC000,0xCfff,M90IRQWrite);
446
SetWriteHandler(0xD000,0xD5ff,M90ModeWrite);
447
SetWriteHandler(0xE000,0xFfff,M90DummyWrite);
450
SetReadHandler(0x5000,0x5fff,M90TekRead);
451
SetReadHandler(0x6000,0xffff,CartBR);
453
mul[0]=mul[1]=regie=0xFF;
455
memset(tkcom,0x00,sizeof(tkcom));
456
memset(prgb,0xff,sizeof(prgb));
457
memset(chrlow,0xff,sizeof(chrlow));
458
memset(chrhigh,0xff,sizeof(chrhigh));
459
memset(names,0x00,sizeof(names));
471
void Mapper90_Init(CartInfo *info)
476
info->Power=M90Power;
479
GameHBIRQHook2=SLWrap;
480
GameStateRestore=M90Restore;
481
AddExState(Tek_StateRegs, ~0, 0, 0);
484
void Mapper209_Init(CartInfo *info)
489
info->Power=M90Power;
492
GameHBIRQHook2=SLWrap;
493
GameStateRestore=M90Restore;
494
AddExState(Tek_StateRegs, ~0, 0, 0);
497
void Mapper211_Init(CartInfo *info)
501
info->Power=M90Power;
504
GameHBIRQHook2=SLWrap;
505
GameStateRestore=M90Restore;
506
AddExState(Tek_StateRegs, ~0, 0, 0);