initial checkin of tasbuild
[[Split portion of a mixed commit.]]
This commit is contained in:
commit
dfd763c100
|
@ -0,0 +1,17 @@
|
|||
# A simulation of Subversion default ignores, generated by reposurgeon.
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
*.al
|
||||
*.libs
|
||||
*.so
|
||||
*.so.[0-9]*
|
||||
*.a
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.rej
|
||||
*~
|
||||
*.#*
|
||||
.*.swp
|
||||
.DS_store
|
||||
# Simulated Subversion default ignores end here
|
|
@ -0,0 +1,90 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 reg[8];
|
||||
static uint8 mirror, cmd;
|
||||
static uint8 *WRAM=NULL;
|
||||
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{&cmd, 1, "CMD"},
|
||||
{&mirror, 1, "MIRR"},
|
||||
{reg, 8, "REGS"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
setmirror(mirror^1);
|
||||
setprg8(0x8000,reg[0]);
|
||||
setprg8(0xA000,reg[1]);
|
||||
setchr2(0x0000,reg[2]>>1);
|
||||
setchr2(0x0800,reg[3]>>1);
|
||||
setchr1(0x1000,reg[4]);
|
||||
setchr1(0x1400,reg[5]);
|
||||
setchr1(0x1800,reg[6]);
|
||||
setchr1(0x1C00,reg[7]);
|
||||
}
|
||||
|
||||
static DECLFW(M112Write)
|
||||
{
|
||||
switch(A)
|
||||
{
|
||||
case 0xe000: mirror=V&1; Sync(); ;break;
|
||||
case 0x8000: cmd=V&7; break;
|
||||
case 0xa000: reg[cmd]=V; Sync(); break;
|
||||
}
|
||||
FCEU_printf("%04x:%04x %d\n",A,V,scanline);
|
||||
}
|
||||
|
||||
static void M112Close(void)
|
||||
{
|
||||
if(WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM = NULL;
|
||||
}
|
||||
|
||||
static void M112Power(void)
|
||||
{
|
||||
setprg16(0xC000,~0);
|
||||
setprg8r(0x10,0x6000,0);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xFFFF,M112Write);
|
||||
SetReadHandler(0x6000,0x7FFF,CartBR);
|
||||
SetWriteHandler(0x6000,0x7FFF,CartBW);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper112_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=M112Power;
|
||||
info->Close=M112Close;
|
||||
GameStateRestore=StateRestore;
|
||||
WRAM=(uint8*)FCEU_gmalloc(8192);
|
||||
SetupCartPRGMapping(0x10,WRAM,8192,1);
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 prgreg[4], chrreg[8];
|
||||
static uint8 IRQa, IRQCount, IRQLatch;
|
||||
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{&IRQa, 1, "IRQA"},
|
||||
{&IRQCount, 1, "IRQC"},
|
||||
{&IRQLatch, 1, "IRQL"},
|
||||
{prgreg, 4, "PREGS"},
|
||||
{chrreg, 8, "CREGS"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
setprg8(0x8000,prgreg[0]);
|
||||
setprg8(0xa000,prgreg[1]);
|
||||
setprg8(0xc000,prgreg[2]);
|
||||
setprg8(0xe000,prgreg[3]);
|
||||
int i;
|
||||
for(i=0; i<8; i++)
|
||||
setchr1(i<<10,chrreg[i]);
|
||||
}
|
||||
|
||||
static DECLFW(M117Write)
|
||||
{
|
||||
if(A<0x8004)
|
||||
{
|
||||
prgreg[A&3]=V;
|
||||
Sync();
|
||||
}
|
||||
else if((A>=0xA000)&&(A<=0xA007))
|
||||
{
|
||||
chrreg[A&7]=V;
|
||||
Sync();
|
||||
}
|
||||
else switch(A)
|
||||
{
|
||||
case 0xc001: IRQLatch=V; break;
|
||||
case 0xc003: IRQCount=IRQLatch; IRQa|=2; break;
|
||||
case 0xe000: IRQa&=~1; IRQa|=V&1; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
case 0xc002: X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void M117Power(void)
|
||||
{
|
||||
prgreg[0]=~3; prgreg[1]=~2; prgreg[2]=~1; prgreg[3]=~0;
|
||||
Sync();
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xFFFF,M117Write);
|
||||
}
|
||||
|
||||
static void M117IRQHook(void)
|
||||
{
|
||||
if(IRQa==3&&IRQCount)
|
||||
{
|
||||
IRQCount--;
|
||||
if(!IRQCount)
|
||||
{
|
||||
IRQa&=1;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper117_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=M117Power;
|
||||
GameHBIRQHook=M117IRQHook;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 cmd;
|
||||
static uint8 DRegs[8];
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{&cmd, 1, "CMD"},
|
||||
{DRegs, 8, "DREG"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
setprg32(0x8000,(DRegs[0]<<4)|(DRegs[1]&0xF));
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFW(Write)
|
||||
{
|
||||
switch (A&0x7300)
|
||||
{
|
||||
case 0x5100: DRegs[0]=V; Sync(); break;
|
||||
case 0x5000: DRegs[1]=V; Sync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(Write2)
|
||||
{
|
||||
switch (A&0x7300)
|
||||
{
|
||||
case 0x5200: DRegs[0]=V; Sync(); break;
|
||||
case 0x5000: DRegs[1]=V; Sync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8 WRAM[8192];
|
||||
static DECLFR(AWRAM)
|
||||
{
|
||||
return(WRAM[A-0x6000]);
|
||||
}
|
||||
|
||||
static DECLFW(BWRAM)
|
||||
{
|
||||
WRAM[A-0x6000]=V;
|
||||
}
|
||||
|
||||
static void Power(void)
|
||||
{
|
||||
memset(DRegs,0,8);
|
||||
DRegs[1]=0xFF;
|
||||
cmd=0;
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x4020,0xFFFF,Write);
|
||||
SetReadHandler(0x6000,0x7FFF,AWRAM);
|
||||
SetWriteHandler(0x6000,0x7FFF,BWRAM);
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M163HB(void)
|
||||
{
|
||||
if(scanline==127&&DRegs[1]&0x80)
|
||||
setchr4(0x0000,1);
|
||||
}
|
||||
|
||||
|
||||
static void Power2(void)
|
||||
{
|
||||
memset(DRegs,0,8);
|
||||
DRegs[1]=0xFF;
|
||||
cmd=0;
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x4020,0xFFFF,Write2);
|
||||
SetReadHandler(0x6000,0x7FFF,AWRAM);
|
||||
SetWriteHandler(0x6000,0x7FFF,BWRAM);
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper164_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=Power;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void Mapper163_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=Power2;
|
||||
GameHBIRQHook=M163HB;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Gimmick Bootleg
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 prg[4];
|
||||
static uint8 chr[8];
|
||||
static uint8 IRQCount;
|
||||
static uint8 IRQPre;
|
||||
static uint8 IRQa;
|
||||
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{prg, 4, "PRG"},
|
||||
{chr, 8, "CHR"},
|
||||
{&IRQCount, 1, "IRQCOUNT"},
|
||||
{&IRQPre, 1, "IRQPRE"},
|
||||
{&IRQa, 1, "IRQA"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void SyncPrg(void)
|
||||
{
|
||||
setprg8(0x6000,0);
|
||||
setprg8(0x8000,prg[0]);
|
||||
setprg8(0xA000,prg[1]);
|
||||
setprg8(0xC000,prg[2]);
|
||||
setprg8(0xE000,~0);
|
||||
}
|
||||
|
||||
static void SyncChr(void)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<8; i++)
|
||||
setchr1(i<<10,chr[i]);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
SyncPrg();
|
||||
SyncChr();
|
||||
}
|
||||
|
||||
static DECLFW(M183Write)
|
||||
{
|
||||
if(((A&0xF80C)>=0xB000)&&((A&0xF80C)<=0xE00C))
|
||||
{
|
||||
uint8 index=(((A&0x7000)>>11)-6)|((A&8)>>3);
|
||||
chr[index]=(chr[index]&(0xF0>>(A&4)))|((V&0x0F)<<(A&4));
|
||||
SyncChr();
|
||||
}
|
||||
else switch (A&0xF80C)
|
||||
{
|
||||
case 0x8800: prg[0]=V; SyncPrg(); break;
|
||||
case 0xA800: prg[1]=V; SyncPrg(); break;
|
||||
case 0xA000: prg[2]=V; SyncPrg(); break;
|
||||
case 0x9800: switch (V&3)
|
||||
{
|
||||
case 0: setmirror(MI_V); break;
|
||||
case 1: setmirror(MI_H); break;
|
||||
case 2: setmirror(MI_0); break;
|
||||
case 3: setmirror(MI_1); break;
|
||||
}
|
||||
break;
|
||||
case 0xF000: IRQCount=((IRQCount&0xF0)|(V&0xF)); break;
|
||||
case 0xF004: IRQCount=((IRQCount&0x0F)|((V&0xF)<<4)); break;
|
||||
case 0xF008: IRQa=V; if(!V)IRQPre=0; X6502_IRQEnd(FCEU_IQEXT); break;
|
||||
case 0xF00C: IRQPre=16; break;
|
||||
}
|
||||
}
|
||||
|
||||
static void M183IRQCounter(void)
|
||||
{
|
||||
if(IRQa)
|
||||
{
|
||||
IRQCount++;
|
||||
if((IRQCount-IRQPre)==238)
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
|
||||
static void M183Power(void)
|
||||
{
|
||||
IRQPre=IRQCount=IRQa=0;
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xFFFF,M183Write);
|
||||
SetReadHandler(0x6000,0x7FFF,CartBR);
|
||||
SyncPrg();
|
||||
SyncChr();
|
||||
}
|
||||
|
||||
void Mapper183_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=M183Power;
|
||||
GameHBIRQHook=M183IRQCounter;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Family Study Box by Fukutake Shoten
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 *DummyCHR=NULL;
|
||||
static uint8 datareg;
|
||||
static void(*Sync)(void);
|
||||
|
||||
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{&datareg, 1, "DREG"},
|
||||
{0}
|
||||
};
|
||||
|
||||
// on off
|
||||
//1 0x0F, 0xF0 - Bird Week
|
||||
//2 0x33, 0x00 - B-Wings
|
||||
//3 0x11, 0x00 - Mighty Bomb Jack
|
||||
//4 0x22, 0x20 - Sansuu 1 Nen, Sansuu 2 Nen
|
||||
//5 0xFF, 0x00 - Sansuu 3 Nen
|
||||
//6 0x21, 0x13 - Spy vs Spy
|
||||
//7 0x20, 0x21 - Seicross
|
||||
|
||||
static void Sync185(void)
|
||||
{
|
||||
// little dirty eh? ;_)
|
||||
if((datareg&3)&&(datareg!=0x13)) // 1, 2, 3, 4, 5, 6
|
||||
setchr8(0);
|
||||
else
|
||||
setchr8r(0x10,0);
|
||||
}
|
||||
|
||||
static void Sync181(void)
|
||||
{
|
||||
if(!(datareg&1)) // 7
|
||||
setchr8(0);
|
||||
else
|
||||
setchr8r(0x10,0);
|
||||
}
|
||||
|
||||
static DECLFW(MWrite)
|
||||
{
|
||||
datareg=V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void MPower(void)
|
||||
{
|
||||
datareg=0;
|
||||
Sync();
|
||||
setprg16(0x8000,0);
|
||||
setprg16(0xC000,~0);
|
||||
SetWriteHandler(0x8000,0xFFFF,MWrite);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
}
|
||||
|
||||
static void MClose(void)
|
||||
{
|
||||
if(DummyCHR)
|
||||
FCEU_gfree(DummyCHR);
|
||||
DummyCHR=NULL;
|
||||
}
|
||||
|
||||
static void MRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper185_Init(CartInfo *info)
|
||||
{
|
||||
Sync=Sync185;
|
||||
info->Power=MPower;
|
||||
info->Close=MClose;
|
||||
GameStateRestore=MRestore;
|
||||
DummyCHR=(uint8*)FCEU_gmalloc(8192);
|
||||
int x;
|
||||
for(x=0;x<8192;x++)
|
||||
DummyCHR[x]=0xff;
|
||||
SetupCartCHRMapping(0x10,DummyCHR,8192,0);
|
||||
AddExState(StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void Mapper181_Init(CartInfo *info)
|
||||
{
|
||||
Sync=Sync181;
|
||||
info->Power=MPower;
|
||||
info->Close=MClose;
|
||||
GameStateRestore=MRestore;
|
||||
DummyCHR=(uint8*)FCEU_gmalloc(8192);
|
||||
int x;
|
||||
for(x=0;x<8192;x++)
|
||||
DummyCHR[x]=0xff;
|
||||
SetupCartCHRMapping(0x10,DummyCHR,8192,0);
|
||||
AddExState(StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* Family Study Box by Fukutake Shoten
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 SWRAM[2816];
|
||||
static uint8 *WRAM=NULL;
|
||||
static uint8 regs[4];
|
||||
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{regs, 4, "DREG"},
|
||||
{SWRAM, 2816, "SWRAM"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
setprg8r(0x10,0x6000,regs[0]>>6);
|
||||
setprg16(0x8000,regs[1]);
|
||||
setprg16(0xc000,0);
|
||||
}
|
||||
|
||||
static DECLFW(M186Write)
|
||||
{
|
||||
if(A&0x4203) regs[A&3]=V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFR(M186Read)
|
||||
{
|
||||
switch(A)
|
||||
{
|
||||
case 0x4200: return 0x00; break;
|
||||
case 0x4201: return 0x00; break;
|
||||
case 0x4202: return 0x40; break;
|
||||
case 0x4203: return 0x00; break;
|
||||
}
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
static DECLFR(ASWRAM)
|
||||
{
|
||||
return(SWRAM[A-0x4400]);
|
||||
}
|
||||
static DECLFW(BSWRAM)
|
||||
{
|
||||
SWRAM[A-0x4400]=V;
|
||||
}
|
||||
|
||||
static void M186Power(void)
|
||||
{
|
||||
setchr8(0);
|
||||
SetReadHandler(0x6000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x6000,0xFFFF,CartBW);
|
||||
SetReadHandler(0x4200,0x43FF,M186Read);
|
||||
SetWriteHandler(0x4200,0x43FF,M186Write);
|
||||
SetReadHandler(0x4400,0x4EFF,ASWRAM);
|
||||
SetWriteHandler(0x4400,0x4EFF,BSWRAM);
|
||||
regs[0]=regs[1]=regs[2]=regs[3];
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M186Close(void)
|
||||
{
|
||||
if(WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
WRAM=NULL;
|
||||
}
|
||||
|
||||
static void M186Restore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper186_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=M186Power;
|
||||
info->Close=M186Close;
|
||||
GameStateRestore=M186Restore;
|
||||
WRAM=(uint8*)FCEU_gmalloc(32384);
|
||||
SetupCartPRGMapping(0x10,WRAM,32384,1);
|
||||
AddExState(WRAM, 32384, 0, "WRAM");
|
||||
AddExState(StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void M187CW(uint32 A, uint8 V)
|
||||
{
|
||||
if((A&0x1000)==((MMC3_cmd&0x80)<<5))
|
||||
setchr1(A,V|0x100);
|
||||
else
|
||||
setchr1(A,V);
|
||||
}
|
||||
|
||||
static void M187PW(uint32 A, uint8 V)
|
||||
{
|
||||
if(EXPREGS[0]&0x80)
|
||||
{
|
||||
uint8 bank=EXPREGS[0]&0x1F;
|
||||
if(EXPREGS[0]&0x20)
|
||||
setprg32(0x8000,bank>>2);
|
||||
else
|
||||
{
|
||||
setprg16(0x8000,bank);
|
||||
setprg16(0xC000,bank);
|
||||
}
|
||||
}
|
||||
else
|
||||
setprg8(A,V&0x3F);
|
||||
}
|
||||
|
||||
static DECLFW(M187Write8000)
|
||||
{
|
||||
EXPREGS[2]=1;
|
||||
MMC3_CMDWrite(A,V);
|
||||
}
|
||||
|
||||
static DECLFW(M187Write8001)
|
||||
{
|
||||
if(EXPREGS[2])
|
||||
MMC3_CMDWrite(A,V);
|
||||
}
|
||||
|
||||
static DECLFW(M187Write8003)
|
||||
{
|
||||
EXPREGS[2]=0;
|
||||
if(V==0x28)setprg8(0xC000,0x17);
|
||||
else if(V==0x2A)setprg8(0xA000,0x0F);
|
||||
}
|
||||
|
||||
|
||||
static DECLFW(M187WriteLo)
|
||||
{
|
||||
EXPREGS[1]=V;
|
||||
if(A==0x5000)
|
||||
{
|
||||
EXPREGS[0]=V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8 prot_data[4] = { 0x83, 0x83, 0x42, 0x00 };
|
||||
static DECLFR(M187Read)
|
||||
{
|
||||
return prot_data[EXPREGS[1]&3];
|
||||
}
|
||||
|
||||
static void M187Power(void)
|
||||
{
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=0;
|
||||
GenMMC3Power();
|
||||
Write_IRQFM(0x4017,0x40);
|
||||
SetReadHandler(0x5000,0x5FFF,M187Read);
|
||||
SetWriteHandler(0x5000,0x5FFF,M187WriteLo);
|
||||
SetWriteHandler(0x8000,0x8000,M187Write8000);
|
||||
SetWriteHandler(0x8001,0x8001,M187Write8001);
|
||||
SetWriteHandler(0x8003,0x8003,M187Write8003);
|
||||
}
|
||||
|
||||
void Mapper187_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC3_Init(info, 256, 256, 0, 0);
|
||||
pwrap=M187PW;
|
||||
cwrap=M187CW;
|
||||
info->Power=M187Power;
|
||||
AddExState(EXPREGS, 3, 0, "EXPR");
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static void M189PW(uint32 A, uint8 V)
|
||||
{
|
||||
setprg32(0x8000,EXPREGS[0]&3);
|
||||
}
|
||||
|
||||
static DECLFW(M189Write)
|
||||
{
|
||||
EXPREGS[0]=V|(V>>4); //actually, there is a two versions of 189 mapper with hi or lo bits bankswitching.
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void M189Power(void)
|
||||
{
|
||||
EXPREGS[0]=EXPREGS[1]=0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x4120,0x7FFF,M189Write);
|
||||
}
|
||||
|
||||
void Mapper189_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC3_Init(info, 256, 256, 0, 0);
|
||||
pwrap=M189PW;
|
||||
info->Power=M189Power;
|
||||
AddExState(EXPREGS, 2, 0, "EXPR");
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 lut[256]={
|
||||
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x59, 0x49, 0x19, 0x09, 0x59, 0x49, 0x19, 0x09,
|
||||
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x51, 0x41, 0x11, 0x01, 0x51, 0x41, 0x11, 0x01,
|
||||
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x59, 0x49, 0x19, 0x09, 0x59, 0x49, 0x19, 0x09,
|
||||
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x51, 0x41, 0x11, 0x01, 0x51, 0x41, 0x11, 0x01,
|
||||
0x00, 0x10, 0x40, 0x50, 0x00, 0x10, 0x40, 0x50,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x08, 0x18, 0x48, 0x58, 0x08, 0x18, 0x48, 0x58,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x10, 0x40, 0x50, 0x00, 0x10, 0x40, 0x50,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x08, 0x18, 0x48, 0x58, 0x08, 0x18, 0x48, 0x58,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x58, 0x48, 0x18, 0x08, 0x58, 0x48, 0x18, 0x08,
|
||||
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x50, 0x40, 0x10, 0x00, 0x50, 0x40, 0x10, 0x00,
|
||||
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x58, 0x48, 0x18, 0x08, 0x58, 0x48, 0x18, 0x08,
|
||||
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x50, 0x40, 0x10, 0x00, 0x50, 0x40, 0x10, 0x00,
|
||||
0x01, 0x11, 0x41, 0x51, 0x01, 0x11, 0x41, 0x51,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x09, 0x19, 0x49, 0x59, 0x09, 0x19, 0x49, 0x59,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x11, 0x41, 0x51, 0x01, 0x11, 0x41, 0x51,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x09, 0x19, 0x49, 0x59, 0x09, 0x19, 0x49, 0x59,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static void M208PW(uint32 A, uint8 V)
|
||||
{
|
||||
setprg32(0x8000,EXPREGS[5]);
|
||||
}
|
||||
|
||||
static DECLFW(M208Write)
|
||||
{
|
||||
EXPREGS[5]=(V&0x1)|((V>>3)&0x2);
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
|
||||
static DECLFW(M208ProtWrite)
|
||||
{
|
||||
if(A<=0x57FF)
|
||||
EXPREGS[4]=V;
|
||||
else
|
||||
EXPREGS[(A&0x03)]=V^lut[EXPREGS[4]];
|
||||
}
|
||||
|
||||
static DECLFR(M208ProtRead)
|
||||
{
|
||||
return(EXPREGS[(A&0x3)]);
|
||||
}
|
||||
|
||||
static void M208Power(void)
|
||||
{
|
||||
EXPREGS[5]=3;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x4800,0x4FFF,M208Write);
|
||||
SetWriteHandler(0x5000,0x5fff,M208ProtWrite);
|
||||
SetReadHandler(0x5800,0x5FFF,M208ProtRead);
|
||||
SetReadHandler(0x8000,0xffff,CartBR);
|
||||
}
|
||||
|
||||
void Mapper208_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC3_Init(info, 128, 256, 0, 0);
|
||||
pwrap=M208PW;
|
||||
info->Power=M208Power;
|
||||
AddExState(EXPREGS, 6, 0, "EXPR");
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint16 IRQCount;
|
||||
static uint8 IRQa;
|
||||
static uint8 prg_reg[2];
|
||||
static uint8 chr_reg[8];
|
||||
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{&IRQCount, 2, "IRQC"},
|
||||
{&IRQa, 2, "IRQA"},
|
||||
{prg_reg, 2, "PRG"},
|
||||
{chr_reg, 8, "CHR"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void M222IRQ(void)
|
||||
{
|
||||
if(IRQa)
|
||||
{
|
||||
IRQCount++;
|
||||
if(IRQCount>=240)
|
||||
{
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
IRQa=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
setprg8(0x8000,prg_reg[0]);
|
||||
setprg8(0xA000,prg_reg[1]);
|
||||
int i;
|
||||
for(i=0; i<8; i++)
|
||||
setchr1(i<<10,chr_reg[i]);
|
||||
}
|
||||
|
||||
static DECLFW(M222Write)
|
||||
{
|
||||
switch(A&0xF003)
|
||||
{
|
||||
case 0x8000: prg_reg[0]=V; break;
|
||||
case 0xA000: prg_reg[1]=V; break;
|
||||
case 0xB000: chr_reg[0]=V; break;
|
||||
case 0xB002: chr_reg[1]=V; break;
|
||||
case 0xC000: chr_reg[2]=V; break;
|
||||
case 0xC002: chr_reg[3]=V; break;
|
||||
case 0xD000: chr_reg[4]=V; break;
|
||||
case 0xD002: chr_reg[5]=V; break;
|
||||
case 0xE000: chr_reg[6]=V; break;
|
||||
case 0xE002: chr_reg[7]=V; break;
|
||||
case 0xF000: IRQCount=IRQa=V;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
}
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M222Power(void)
|
||||
{
|
||||
setprg16(0xC000,~0);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xFFFF,M222Write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper222_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=M222Power;
|
||||
GameHBIRQHook=M222IRQ;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint16 cmdreg;
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{&cmdreg, 2, "CMDREG"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
if(cmdreg&0x400)
|
||||
setmirror(MI_0);
|
||||
else
|
||||
setmirror(((cmdreg>>13)&1)^1);
|
||||
if(cmdreg&0x800)
|
||||
{
|
||||
setprg16(0x8000,((cmdreg&0x300)>>3)|((cmdreg&0x1F)<<1)|((cmdreg>>12)&1));
|
||||
setprg16(0xC000,((cmdreg&0x300)>>3)|((cmdreg&0x1F)<<1)|((cmdreg>>12)&1));
|
||||
}
|
||||
else
|
||||
setprg32(0x8000,((cmdreg&0x300)>>4)|(cmdreg&0x1F));
|
||||
}
|
||||
|
||||
static DECLFW(M235Write)
|
||||
{
|
||||
cmdreg=A;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M235Power(void)
|
||||
{
|
||||
setchr8(0);
|
||||
SetWriteHandler(0x8000,0xFFFF,M235Write);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
cmdreg=0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M235Restore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper235_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=M235Power;
|
||||
GameStateRestore=M235Restore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 prg_reg;
|
||||
static uint8 chr_reg;
|
||||
static uint8 hrd_flag;
|
||||
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{&prg_reg, 1, "PRG"},
|
||||
{&chr_reg, 1, "CHR"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
if(prg_reg&0x80)
|
||||
setprg32(0x8000,prg_reg>>6);
|
||||
else
|
||||
{
|
||||
setprg16(0x8000,(prg_reg>>5)&3);
|
||||
setprg16(0xC000,(prg_reg>>5)&3);
|
||||
}
|
||||
setmirror((prg_reg&8)>>3);
|
||||
setchr8((chr_reg&3)|(prg_reg&7)|((prg_reg&0x10)>>1));
|
||||
}
|
||||
|
||||
static DECLFR(M57Read)
|
||||
{
|
||||
return hrd_flag;
|
||||
}
|
||||
|
||||
static DECLFW(M57Write)
|
||||
{
|
||||
if((A&0x8800)==0x8800)
|
||||
prg_reg=V;
|
||||
else
|
||||
chr_reg=V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M57Power(void)
|
||||
{
|
||||
prg_reg=0;
|
||||
chr_reg=0;
|
||||
hrd_flag=0;
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xFFFF,M57Write);
|
||||
SetReadHandler(0x6000,0x6000,M57Read);
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M57Reset()
|
||||
{
|
||||
if(hrd_flag==3)
|
||||
hrd_flag=0;
|
||||
else
|
||||
hrd_flag++;
|
||||
FCEU_printf("Select Register = %02x\n",hrd_flag);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper57_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=M57Power;
|
||||
info->Reset=M57Reset;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint16 cmdreg;
|
||||
static uint8 invalid_data;
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{&cmdreg, 2, "CMDREG"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
setprg16r((cmdreg&0x060)>>5,0x8000,(cmdreg&0x01C)>>2);
|
||||
setprg16r((cmdreg&0x060)>>5,0xC000,(cmdreg&0x200)?(~0):0);
|
||||
setmirror(((cmdreg&2)>>1)^1);
|
||||
}
|
||||
|
||||
static DECLFR(UNL8157Read)
|
||||
{
|
||||
if(invalid_data&&cmdreg&0x100)
|
||||
return 0xFF;
|
||||
else
|
||||
return CartBR(A);
|
||||
}
|
||||
|
||||
static DECLFW(UNL8157Write)
|
||||
{
|
||||
cmdreg=A;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void UNL8157Power(void)
|
||||
{
|
||||
setchr8(0);
|
||||
SetWriteHandler(0x8000,0xFFFF,UNL8157Write);
|
||||
SetReadHandler(0x8000,0xFFFF,UNL8157Read);
|
||||
cmdreg=0x200;
|
||||
invalid_data=1;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void UNL8157Reset(void)
|
||||
{
|
||||
cmdreg=0;
|
||||
invalid_data^=1;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void UNL8157Restore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void UNL8157_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=UNL8157Power;
|
||||
info->Reset=UNL8157Reset;
|
||||
GameStateRestore=UNL8157Restore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 cmdin;
|
||||
static uint8 UNL8237_perm[8] = {0, 2, 6, 1, 7, 3, 4, 5};
|
||||
|
||||
static void UNL8237CW(uint32 A, uint8 V)
|
||||
{
|
||||
setchr1(A,((EXPREGS[1]&4)<<6)|V);
|
||||
}
|
||||
|
||||
static void UNL8237PW(uint32 A, uint8 V)
|
||||
{
|
||||
if(EXPREGS[0]&0x80)
|
||||
{
|
||||
if(EXPREGS[0]&0x20)
|
||||
setprg32(0x8000,(EXPREGS[0]&0xF)>>1);
|
||||
else
|
||||
{
|
||||
setprg16(0x8000,(EXPREGS[0]&0x1F));
|
||||
setprg16(0xC000,(EXPREGS[0]&0x1F));
|
||||
}
|
||||
}
|
||||
else
|
||||
setprg8(A,V&0x3F);
|
||||
}
|
||||
|
||||
static DECLFW(UNL8237Write)
|
||||
{
|
||||
if((A&0xF000)==0xF000)
|
||||
IRQCount=V;
|
||||
else if((A&0xF000)==0xE000)
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
else switch(A&0xE001)
|
||||
{
|
||||
case 0x8000: setmirror(((V|(V>>7))&1)^1); break;
|
||||
case 0xA000: MMC3_CMDWrite(0x8000,(V&0xC0)|(UNL8237_perm[V&7])); cmdin=1; break;
|
||||
case 0xC000: if(cmdin)
|
||||
{
|
||||
MMC3_CMDWrite(0x8001,V);
|
||||
cmdin=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(UNL8237ExWrite)
|
||||
{
|
||||
switch(A)
|
||||
{
|
||||
case 0x5000: EXPREGS[0]=V; FixMMC3PRG(MMC3_cmd); break;
|
||||
case 0x5001: EXPREGS[1]=V; FixMMC3CHR(MMC3_cmd); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void UNL8237Power(void)
|
||||
{
|
||||
IRQa=1;
|
||||
EXPREGS[0]=EXPREGS[1]=0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x8000,0xFFFF,UNL8237Write);
|
||||
SetWriteHandler(0x5000,0x7FFF,UNL8237ExWrite);
|
||||
}
|
||||
|
||||
void UNL8237_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC3_Init(info, 256, 256, 0, 0);
|
||||
cwrap=UNL8237CW;
|
||||
pwrap=UNL8237PW;
|
||||
info->Power=UNL8237Power;
|
||||
AddExState(EXPREGS, 3, 0, "EXPR");
|
||||
AddExState(&cmdin, 1, 0, "CMDIN");
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 reg[8];
|
||||
static uint8 mirror, cmd, is154;
|
||||
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{&cmd, 1, "CMD"},
|
||||
{&mirror, 1, "MIRR"},
|
||||
{reg, 8, "REGS"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
setchr2(0x0000,reg[0]>>1);
|
||||
setchr2(0x0800,reg[1]>>1);
|
||||
setchr1(0x1000,reg[2]|0x40);
|
||||
setchr1(0x1400,reg[3]|0x40);
|
||||
setchr1(0x1800,reg[4]|0x40);
|
||||
setchr1(0x1C00,reg[5]|0x40);
|
||||
setprg8(0x8000,reg[6]);
|
||||
setprg8(0xA000,reg[7]);
|
||||
}
|
||||
|
||||
static void MSync(void)
|
||||
{
|
||||
if(is154)setmirror(MI_0+(mirror&1));
|
||||
}
|
||||
|
||||
static DECLFW(M88Write)
|
||||
{
|
||||
switch(A&0x8001)
|
||||
{
|
||||
case 0x8000: cmd=V&7; mirror=V>>6; MSync(); break;
|
||||
case 0x8001: reg[cmd]=V; Sync(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static void M88Power(void)
|
||||
{
|
||||
setprg16(0xC000,~0);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xFFFF,M88Write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
MSync();
|
||||
}
|
||||
|
||||
void Mapper88_Init(CartInfo *info)
|
||||
{
|
||||
is154=0;
|
||||
info->Power=M88Power;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void Mapper154_Init(CartInfo *info)
|
||||
{
|
||||
is154=1;
|
||||
info->Power=M88Power;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,466 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
//#define DEBUG90
|
||||
|
||||
static int is209;
|
||||
static int is211;
|
||||
|
||||
static uint8 IRQMode; // from $c001
|
||||
static uint8 IRQPre; // from $c004
|
||||
static uint8 IRQPreSize; // from $c007
|
||||
static uint8 IRQCount; // from $c005
|
||||
static uint8 IRQXOR; // Loaded from $C006
|
||||
static uint8 IRQa; // $c002, $c003, and $c000
|
||||
|
||||
static uint8 mul[2];
|
||||
static uint8 regie;
|
||||
|
||||
static uint8 tkcom[4];
|
||||
static uint8 prgb[4];
|
||||
static uint8 chrlow[8];
|
||||
static uint8 chrhigh[8];
|
||||
|
||||
static uint16 names[4];
|
||||
static uint8 tekker;
|
||||
|
||||
static SFORMAT Tek_StateRegs[]={
|
||||
{&IRQMode, 1, "IRQMODE"},
|
||||
{&IRQPre, 1, "IRQPRE"},
|
||||
{&IRQPreSize, 1, "IRQPRESIZE"},
|
||||
{&IRQCount, 1, "IRQC"},
|
||||
{&IRQXOR, 1, "IRQXOR"},
|
||||
{&IRQa, 1, "IRQa"},
|
||||
{mul, 2, "MUL"},
|
||||
{®ie, 1, "REGI"},
|
||||
{tkcom, 4, "TKCO"},
|
||||
{prgb, 4, "PRGB"},
|
||||
{chrlow, 4, "CHRL"},
|
||||
{chrhigh, 8, "CHRH"},
|
||||
{&names[0], 2|FCEUSTATE_RLSB, "NMS0"},
|
||||
{&names[1], 2|FCEUSTATE_RLSB, "NMS1"},
|
||||
{&names[2], 2|FCEUSTATE_RLSB, "NMS2"},
|
||||
{&names[3], 2|FCEUSTATE_RLSB, "NMS3"},
|
||||
{&tekker, 1, "TEKR"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void mira(void)
|
||||
{
|
||||
if((tkcom[0]&0x20&&is209)||is211)
|
||||
{
|
||||
int x;
|
||||
if(tkcom[0]&0x40) // Name tables are ROM-only
|
||||
{
|
||||
for(x=0;x<4;x++)
|
||||
setntamem(CHRptr[0]+(((names[x])&CHRmask1[0])<<10),0,x);
|
||||
}
|
||||
else // Name tables can be RAM or ROM.
|
||||
{
|
||||
for(x=0;x<4;x++)
|
||||
{
|
||||
if((tkcom[1]&0x80)==(names[x]&0x80)) // RAM selected.
|
||||
setntamem(NTARAM+((names[x]&0x1)<<10),1,x);
|
||||
else
|
||||
setntamem(CHRptr[0]+(((names[x])&CHRmask1[0])<<10),0,x);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(tkcom[1]&3)
|
||||
{
|
||||
case 0: setmirror(MI_V); break;
|
||||
case 1: setmirror(MI_H); break;
|
||||
case 2: setmirror(MI_0); break;
|
||||
case 3: setmirror(MI_1); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void tekprom(void)
|
||||
{
|
||||
uint32 bankmode=((tkcom[3]&6)<<5);
|
||||
switch(tkcom[0]&7)
|
||||
{
|
||||
case 00: if(tkcom[0]&0x80)
|
||||
setprg8(0x6000,(((prgb[3]<<2)+3)&0x3F)|bankmode);
|
||||
setprg32(0x8000,0x0F|((tkcom[3]&6)<<3));
|
||||
break;
|
||||
case 01: if(tkcom[0]&0x80)
|
||||
setprg8(0x6000,(((prgb[3]<<1)+1)&0x3F)|bankmode);
|
||||
setprg16(0x8000,(prgb[1]&0x1F)|((tkcom[3]&6)<<4));
|
||||
setprg16(0xC000,0x1F|((tkcom[3]&6)<<4));
|
||||
break;
|
||||
case 03: // bit reversion
|
||||
case 02: if(tkcom[0]&0x80)
|
||||
setprg8(0x6000,(prgb[3]&0x3F)|bankmode);
|
||||
setprg8(0x8000,(prgb[0]&0x3F)|bankmode);
|
||||
setprg8(0xa000,(prgb[1]&0x3F)|bankmode);
|
||||
setprg8(0xc000,(prgb[2]&0x3F)|bankmode);
|
||||
setprg8(0xe000,0x3F|bankmode);
|
||||
break;
|
||||
case 04: if(tkcom[0]&0x80)
|
||||
setprg8(0x6000,(((prgb[3]<<2)+3)&0x3F)|bankmode);
|
||||
setprg32(0x8000,(prgb[3]&0x0F)|((tkcom[3]&6)<<3));
|
||||
break;
|
||||
case 05: if(tkcom[0]&0x80)
|
||||
setprg8(0x6000,(((prgb[3]<<1)+1)&0x3F)|bankmode);
|
||||
setprg16(0x8000,(prgb[1]&0x1F)|((tkcom[3]&6)<<4));
|
||||
setprg16(0xC000,(prgb[3]&0x1F)|((tkcom[3]&6)<<4));
|
||||
break;
|
||||
case 07: // bit reversion
|
||||
case 06: if(tkcom[0]&0x80)
|
||||
setprg8(0x6000,(prgb[3]&0x3F)|bankmode);
|
||||
setprg8(0x8000,(prgb[0]&0x3F)|bankmode);
|
||||
setprg8(0xa000,(prgb[1]&0x3F)|bankmode);
|
||||
setprg8(0xc000,(prgb[2]&0x3F)|bankmode);
|
||||
setprg8(0xe000,(prgb[3]&0x3F)|bankmode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void tekvrom(void)
|
||||
{
|
||||
int x, bank=0, mask=0xFFFF;
|
||||
if(!(tkcom[3]&0x20))
|
||||
{
|
||||
bank=(tkcom[3]&1)|((tkcom[3]&0x18)>>2);
|
||||
switch (tkcom[0]&0x18)
|
||||
{
|
||||
case 0x00: bank<<=5; mask=0x1F; break;
|
||||
case 0x08: bank<<=6; mask=0x3F; break;
|
||||
case 0x10: bank<<=7; mask=0x7F; break;
|
||||
case 0x18: bank<<=8; mask=0xFF; break;
|
||||
}
|
||||
}
|
||||
switch(tkcom[0]&0x18)
|
||||
{
|
||||
case 0x00: // 8KB
|
||||
setchr8(((chrlow[0]|(chrhigh[0]<<8))&mask)|bank);
|
||||
break;
|
||||
case 0x08: // 4KB
|
||||
for(x=0;x<8;x+=4)
|
||||
setchr4(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank);
|
||||
break;
|
||||
case 0x10: // 2KB
|
||||
for(x=0;x<8;x+=2)
|
||||
setchr2(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank);
|
||||
break;
|
||||
case 0x18: // 1KB
|
||||
for(x=0;x<8;x++)
|
||||
setchr1(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(M90TekWrite)
|
||||
{
|
||||
switch(A)
|
||||
{
|
||||
case 0x5800: mul[0]=V; break;
|
||||
case 0x5801: mul[1]=V; break;
|
||||
case 0x5803: regie=V; break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(M90TekRead)
|
||||
{
|
||||
switch(A)
|
||||
{
|
||||
case 0x5800: return (mul[0]*mul[1]);
|
||||
case 0x5801: return((mul[0]*mul[1])>>8);
|
||||
case 0x5803: return (regie);
|
||||
}
|
||||
return(tekker);
|
||||
}
|
||||
|
||||
static DECLFW(M90PRGWrite)
|
||||
{
|
||||
prgb[A&3]=V;
|
||||
tekprom();
|
||||
}
|
||||
|
||||
static DECLFW(M90CHRlowWrite)
|
||||
{
|
||||
chrlow[A&7]=V;
|
||||
tekvrom();
|
||||
}
|
||||
|
||||
static DECLFW(M90CHRhiWrite)
|
||||
{
|
||||
chrhigh[A&7]=V;
|
||||
tekvrom();
|
||||
}
|
||||
|
||||
static DECLFW(M90NTWrite)
|
||||
{
|
||||
if(A&4)
|
||||
{
|
||||
names[A&3]&=0x00FF;
|
||||
names[A&3]|=V<<8;
|
||||
}
|
||||
else
|
||||
{
|
||||
names[A&3]&=0xFF00;
|
||||
names[A&3]|=V;
|
||||
}
|
||||
mira();
|
||||
}
|
||||
|
||||
static DECLFW(M90IRQWrite)
|
||||
{
|
||||
switch(A&7)
|
||||
{
|
||||
case 00: //FCEU_printf("%s IRQ (C000)\n",V&1?"Enable":"Disable");
|
||||
IRQa=V&1;if(!(V&1)) X6502_IRQEnd(FCEU_IQEXT);break;
|
||||
case 02: //FCEU_printf("Disable IRQ (C002) scanline=%d\n", scanline);
|
||||
IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break;
|
||||
case 03: //FCEU_printf("Enable IRQ (C003) scanline=%d\n", scanline);
|
||||
IRQa=1;break;
|
||||
case 01: IRQMode=V;
|
||||
/* FCEU_printf("IRQ Count method: ");
|
||||
switch (IRQMode&3)
|
||||
{
|
||||
case 00: FCEU_printf("M2 cycles\n");break;
|
||||
case 01: FCEU_printf("PPU A12 toggles\n");break;
|
||||
case 02: FCEU_printf("PPU reads\n");break;
|
||||
case 03: FCEU_printf("Writes to CPU space\n");break;
|
||||
}
|
||||
FCEU_printf("Counter prescaler size: %s\n",(IRQMode&4)?"3 bits":"8 bits");
|
||||
FCEU_printf("Counter prescaler size adjust: %s\n",(IRQMode&8)?"Used C007":"Normal Operation");
|
||||
if((IRQMode>>6)==2) FCEU_printf("Counter Down\n");
|
||||
else if((IRQMode>>6)==1) FCEU_printf("Counter Up\n");
|
||||
else FCEU_printf("Counter Stopped\n");
|
||||
*/ break;
|
||||
case 04: //FCEU_printf("Pre Counter Loaded and Xored wiht C006: %d\n",V^IRQXOR);
|
||||
IRQPre=V^IRQXOR;break;
|
||||
case 05: //FCEU_printf("Main Counter Loaded and Xored wiht C006: %d\n",V^IRQXOR);
|
||||
IRQCount=V^IRQXOR;break;
|
||||
case 06: //FCEU_printf("Xor Value: %d\n",V);
|
||||
IRQXOR=V;break;
|
||||
case 07: //if(!(IRQMode&8)) FCEU_printf("C001 is clear, no effect applied\n");
|
||||
// else if(V==0xFF) FCEU_printf("Prescaler is changed for 12bits\n");
|
||||
// else FCEU_printf("Counter Stopped\n");
|
||||
IRQPreSize=V;break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(M90ModeWrite)
|
||||
{
|
||||
tkcom[A&3]=V;
|
||||
tekprom();
|
||||
tekvrom();
|
||||
mira();
|
||||
|
||||
#ifdef DEBUG90
|
||||
switch (A&3)
|
||||
{
|
||||
case 00: FCEU_printf("Main Control Register:\n");
|
||||
FCEU_printf(" PGR Banking mode: %d\n",V&7);
|
||||
FCEU_printf(" CHR Banking mode: %d\n",(V>>3)&3);
|
||||
FCEU_printf(" 6000-7FFF addresses mapping: %s\n",(V&0x80)?"Yes":"No");
|
||||
FCEU_printf(" Nametable control: %s\n",(V&0x20)?"Enabled":"Disabled");
|
||||
if(V&0x20)
|
||||
FCEU_printf(" Nametable can be: %s\n",(V&0x40)?"ROM Only":"RAM or ROM");
|
||||
break;
|
||||
case 01: FCEU_printf("Mirroring mode: ");
|
||||
switch (V&3)
|
||||
{
|
||||
case 0: FCEU_printf("Vertical\n");break;
|
||||
case 1: FCEU_printf("Horizontal\n");break;
|
||||
case 2: FCEU_printf("Nametable 0 only\n");break;
|
||||
case 3: FCEU_printf("Nametable 1 only\n");break;
|
||||
}
|
||||
FCEU_printf("Mirroring flag: %s\n",(V&0x80)?"On":"Off");
|
||||
break;
|
||||
case 02: if((((tkcom[0])>>5)&3)==1)
|
||||
FCEU_printf("Nametable ROM/RAM select mode: %d\n",V>>7);
|
||||
break;
|
||||
case 03:
|
||||
FCEU_printf("CHR Banking mode: %s\n",(V&0x20)?"Entire CHR ROM":"256Kb Switching mode");
|
||||
if(!(V&0x20)) FCEU_printf("256K CHR bank number: %02x\n",(V&1)|((V&0x18)>>2));
|
||||
FCEU_printf("512K PRG bank number: %d\n",(V&6)>>1);
|
||||
FCEU_printf("CHR Bank mirroring: %s\n",(V&0x80)?"Swapped":"Normal operate");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void CCL(void)
|
||||
{
|
||||
if((IRQMode>>6) == 1) // Count Up
|
||||
{
|
||||
IRQCount++;
|
||||
if((IRQCount == 0) && IRQa)
|
||||
{
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
else if((IRQMode>>6) == 2) // Count down
|
||||
{
|
||||
IRQCount--;
|
||||
if((IRQCount == 0xFF) && IRQa)
|
||||
{
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ClockCounter(void)
|
||||
{
|
||||
uint8 premask;
|
||||
|
||||
if(IRQMode & 0x4)
|
||||
premask = 0x7;
|
||||
else
|
||||
premask = 0xFF;
|
||||
if((IRQMode>>6) == 1) // Count up
|
||||
{
|
||||
IRQPre++;
|
||||
if((IRQPre & premask) == 0) CCL();
|
||||
}
|
||||
else if((IRQMode>>6) == 2) // Count down
|
||||
{
|
||||
IRQPre--;
|
||||
if((IRQPre & premask) == premask) CCL();
|
||||
}
|
||||
}
|
||||
|
||||
void FP_FASTAPASS(1) CPUWrap(int a)
|
||||
{
|
||||
int x;
|
||||
if((IRQMode&3)==0) for(x=0;x<a;x++) ClockCounter();
|
||||
}
|
||||
|
||||
static void SLWrap(void)
|
||||
{
|
||||
int x;
|
||||
if((IRQMode&3)==1) for(x=0;x<8;x++) ClockCounter();
|
||||
}
|
||||
|
||||
static uint32 lastread;
|
||||
static void FP_FASTAPASS(1) M90PPU(uint32 A)
|
||||
{
|
||||
if((IRQMode&3)==2)
|
||||
{
|
||||
if(lastread!=A)
|
||||
{
|
||||
ClockCounter();
|
||||
ClockCounter();
|
||||
}
|
||||
lastread=A;
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// if((!lastread)&&(A&0x1000))
|
||||
// ClockCounter();
|
||||
// lastread=A&0x1000;
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
static void togglie()
|
||||
{
|
||||
tekker>>=6;
|
||||
if(tekker>3)
|
||||
tekker=0;
|
||||
else
|
||||
tekker++;
|
||||
tekker<<=6;
|
||||
FCEU_printf("tekker=%04x\n",tekker);
|
||||
memset(tkcom,0x00,sizeof(tkcom));
|
||||
memset(prgb,0xff,sizeof(prgb));
|
||||
tekprom();
|
||||
tekvrom();
|
||||
}
|
||||
|
||||
static void M90Restore(int version)
|
||||
{
|
||||
tekprom();
|
||||
tekvrom();
|
||||
mira();
|
||||
}
|
||||
|
||||
static void M90Power(void)
|
||||
{
|
||||
SetWriteHandler(0x5000,0x5fff,M90TekWrite);
|
||||
SetWriteHandler(0x8000,0x8fff,M90PRGWrite);
|
||||
SetWriteHandler(0x9000,0x9fff,M90CHRlowWrite);
|
||||
SetWriteHandler(0xA000,0xAfff,M90CHRhiWrite);
|
||||
SetWriteHandler(0xB000,0xBfff,M90NTWrite);
|
||||
SetWriteHandler(0xC000,0xCfff,M90IRQWrite);
|
||||
SetWriteHandler(0xD000,0xDfff,M90ModeWrite);
|
||||
|
||||
SetReadHandler(0x5000,0x5fff,M90TekRead);
|
||||
SetReadHandler(0x6000,0xffff,CartBR);
|
||||
|
||||
mul[0]=mul[1]=regie=0xFF;
|
||||
|
||||
memset(tkcom,0x00,sizeof(tkcom));
|
||||
memset(prgb,0xff,sizeof(prgb));
|
||||
memset(chrlow,0xff,sizeof(chrlow));
|
||||
memset(chrhigh,0xff,sizeof(chrhigh));
|
||||
memset(names,0x00,sizeof(names));
|
||||
|
||||
if(is211)
|
||||
tekker=0xC0;
|
||||
else
|
||||
tekker=0x00;
|
||||
|
||||
tekprom();
|
||||
tekvrom();
|
||||
}
|
||||
|
||||
|
||||
void Mapper90_Init(CartInfo *info)
|
||||
{
|
||||
is211=0;
|
||||
is209=0;
|
||||
info->Reset=togglie;
|
||||
info->Power=M90Power;
|
||||
PPU_hook=M90PPU;
|
||||
GameHBIRQHook2=SLWrap;
|
||||
MapIRQHook=CPUWrap;
|
||||
GameStateRestore=M90Restore;
|
||||
AddExState(Tek_StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void Mapper209_Init(CartInfo *info)
|
||||
{
|
||||
is211=0;
|
||||
is209=1;
|
||||
info->Reset=togglie;
|
||||
info->Power=M90Power;
|
||||
GameHBIRQHook2=SLWrap;
|
||||
GameStateRestore=M90Restore;
|
||||
AddExState(Tek_StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void Mapper211_Init(CartInfo *info)
|
||||
{
|
||||
is211=1;
|
||||
info->Reset=togglie;
|
||||
info->Power=M90Power;
|
||||
GameHBIRQHook2=SLWrap;
|
||||
GameStateRestore=M90Restore;
|
||||
AddExState(Tek_StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 lastA;
|
||||
static uint8 DRegs[8];
|
||||
static uint8 cmd;
|
||||
static uint8 MirCache[8];
|
||||
|
||||
static SFORMAT DB_StateRegs[]={
|
||||
{DRegs, 8, "DREG"},
|
||||
{&cmd, 1, "CMD"},
|
||||
{&lastA, 1, "LAST"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void toot(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
MirCache[0]=MirCache[1]=(DRegs[0]>>4)&1;
|
||||
MirCache[2]=MirCache[3]=(DRegs[1]>>4)&1;
|
||||
|
||||
for(x=0;x<4;x++)
|
||||
MirCache[4+x]=(DRegs[2+x]>>5)&1;
|
||||
onemir(MirCache[lastA]);
|
||||
}
|
||||
|
||||
static void Sync()
|
||||
{
|
||||
setchr2(0x0000,DRegs[0]&0x1F);
|
||||
setchr2(0x0800,DRegs[1]&0x1F);
|
||||
setchr1(0x1000,DRegs[2]&0x1F);
|
||||
setchr1(0x1400,DRegs[3]&0x1F);
|
||||
setchr1(0x1800,DRegs[4]&0x1F);
|
||||
setchr1(0x1C00,DRegs[5]&0x1F);
|
||||
setprg8(0x8000,DRegs[6]&0x1F);
|
||||
setprg8(0xa000,DRegs[7]&0x1F);
|
||||
toot();
|
||||
}
|
||||
|
||||
static DECLFW(Mapper95_write)
|
||||
{
|
||||
switch(A&0xF001)
|
||||
{
|
||||
case 0x8000: cmd = V; break;
|
||||
case 0x8001:
|
||||
switch(cmd&0x07)
|
||||
{
|
||||
case 0: DRegs[0]=(V&0x3F)>>1; break;
|
||||
case 1: DRegs[1]=(V&0x3F)>>1; break;
|
||||
case 2: DRegs[2]=V&0x3F; break;
|
||||
case 3: DRegs[3]=V&0x3F; break;
|
||||
case 4: DRegs[4]=V&0x3F; break;
|
||||
case 5: DRegs[5]=V&0x3F; break;
|
||||
case 6: DRegs[6]=V&0x3F; break;
|
||||
case 7: DRegs[7]=V&0x3F; break;
|
||||
}
|
||||
Sync();
|
||||
}
|
||||
}
|
||||
|
||||
static void FP_FASTAPASS(1) dragonbust_ppu(uint32 A)
|
||||
{
|
||||
static int last=-1;
|
||||
static uint8 z;
|
||||
|
||||
if(A>=0x2000) return;
|
||||
|
||||
A>>=10;
|
||||
lastA=A;
|
||||
z=MirCache[A];
|
||||
if(z!=last)
|
||||
{
|
||||
onemir(z);
|
||||
last=z;
|
||||
}
|
||||
}
|
||||
|
||||
static void DBPower(void)
|
||||
{
|
||||
memset(DRegs,0x3F,8);
|
||||
DRegs[0]=DRegs[1]=0x1F;
|
||||
|
||||
Sync();
|
||||
|
||||
setprg8(0xc000,0x3E);
|
||||
setprg8(0xe000,0x3F);
|
||||
|
||||
SetReadHandler(0x8000,0xffff,CartBR);
|
||||
SetWriteHandler(0x8000,0xffff,Mapper95_write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper95_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=DBPower;
|
||||
AddExState(DB_StateRegs, ~0, 0, 0);
|
||||
PPU_hook=dragonbust_ppu;
|
||||
GameStateRestore=StateRestore;
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
fceu_SOURCES += boards/112.c boards/117.c boards/164.c boards/183.c boards/185.c boards/186.c boards/187.c boards/189.c boards/208.c boards/222.c boards/235.c boards/57.c boards/8157.c boards/8237.c boards/88.c boards/90.c boards/95.c boards/bmc13in1jy110.c boards/bmc42in1r.c boards/bmc64in1nr.c boards/bmc70in1.c boards/bmcgk192.c boards/bonza.c boards/cc21.c boards/datalatch.c boards/deirom.c boards/dream.c boards/fk23c.c boards/h2288.c boards/karaoke.c boards/kof97.c boards/konami-qtai.c boards/malee.c boards/mmc1.c boards/mmc3.c boards/mmc5.c boards/n106.c boards/novel.c boards/sachen.c boards/sheroes.c boards/sl1632.c boards/sonic5.c boards/subor.c boards/super24.c boards/supervision.c boards/t-262.c boards/tengen.c boards/__dummy_mapper.c
|
|
@ -0,0 +1,96 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2006 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 reg[8];
|
||||
/*
|
||||
static uint8 *WRAM=NULL;
|
||||
static uint32 WRAMSIZE;
|
||||
static uint8 *CHRRAM=NULL;
|
||||
static uint32 CHRRAMSIZE;
|
||||
*/
|
||||
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{reg, 8, "REGS"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
}
|
||||
|
||||
static DECLFW(MNNNWrite)
|
||||
{
|
||||
}
|
||||
|
||||
static void MNNNPower(void)
|
||||
{
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xFFFF,MNNNWrite);
|
||||
}
|
||||
|
||||
static void MNNNReset(void)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
static void MNNNClose(void)
|
||||
{
|
||||
if(WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
if(CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
WRAM=CHRRAM=NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
static void MNNNIRQHook(void)
|
||||
{
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void MapperNNN_Init(CartInfo *info)
|
||||
{
|
||||
info->Reset=MNNNReset;
|
||||
info->Power=MNNNPower;
|
||||
// info->Close=MNNNClose;
|
||||
GameHBIRQHook=MNNNIRQHook;
|
||||
GameStateRestore=StateRestore;
|
||||
/*
|
||||
CHRRAMSIZE=8192;
|
||||
CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSIZE);
|
||||
SetupCartPRGMapping(0x10,CHRRAM,CHRRAMSIZE,1);
|
||||
AddExState(CHRRAM, CHRRAMSIZE, 0, "WRAM");
|
||||
*/
|
||||
/*
|
||||
WRAMSIZE=8192;
|
||||
WRAM=(uint8*)FCEU_gmalloc(WRAMSIZE);
|
||||
SetupCartPRGMapping(0x10,WRAM,WRAMSIZE,1);
|
||||
AddExState(WRAM, WRAMSIZE, 0, "WRAM");
|
||||
*/
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* BMC 42-in-1 reset switch
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 bank_mode;
|
||||
static uint8 bank_value;
|
||||
static uint8 prgb[4];
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
FCEU_printf("%02x: %02x %02x\n", bank_mode, bank_value, prgb[0]);
|
||||
switch(bank_mode&7)
|
||||
{
|
||||
case 0:
|
||||
setprg32(0x8000,bank_value&7); break;
|
||||
case 1:
|
||||
setprg16(0x8000,((8+(bank_value&7))>>1)+prgb[1]);
|
||||
setprg16(0xC000,(bank_value&7)>>1);
|
||||
case 4:
|
||||
setprg32(0x8000,8+(bank_value&7)); break;
|
||||
case 5:
|
||||
setprg16(0x8000,((8+(bank_value&7))>>1)+prgb[1]);
|
||||
setprg16(0xC000,((8+(bank_value&7))>>1)+prgb[3]);
|
||||
case 2:
|
||||
setprg8(0x8000,prgb[0]>>2);
|
||||
setprg8(0xa000,prgb[1]);
|
||||
setprg8(0xc000,prgb[2]);
|
||||
setprg8(0xe000,~0);
|
||||
break;
|
||||
case 3:
|
||||
setprg8(0x8000,prgb[0]);
|
||||
setprg8(0xa000,prgb[1]);
|
||||
setprg8(0xc000,prgb[2]);
|
||||
setprg8(0xe000,prgb[3]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(BMC13in1JY110Write)
|
||||
{
|
||||
FCEU_printf("%04x:%04x\n",A,V);
|
||||
switch(A)
|
||||
{
|
||||
case 0x8000:
|
||||
case 0x8001:
|
||||
case 0x8002:
|
||||
case 0x8003: prgb[A&3]=V; break;
|
||||
case 0xD000: bank_mode=V; break;
|
||||
case 0xD001: setmirror(V&3);
|
||||
case 0xD002: break;
|
||||
case 0xD003: bank_value=V; break;
|
||||
}
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void BMC13in1JY110Power(void)
|
||||
{
|
||||
prgb[0]=prgb[1]=prgb[2]=prgb[3]=0;
|
||||
bank_mode=0;
|
||||
bank_value=0;
|
||||
setprg32(0x8000,0);
|
||||
setchr8(0);
|
||||
SetWriteHandler(0x8000,0xFFFF,BMC13in1JY110Write);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void BMC13in1JY110_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=BMC13in1JY110Power;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
GameStateRestore=StateRestore;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* BMC 42-in-1 reset switch
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 hrd_sw;
|
||||
static uint8 latche;
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{&latche, 1, "LATCHE"},
|
||||
{&hrd_sw, 1, "HRDSW"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
if(!(latche&0x20))
|
||||
setprg32r(hrd_sw,0x8000,(latche>>1)&0x0f);
|
||||
else
|
||||
{
|
||||
setprg16r(hrd_sw,0x8000,latche&0x1f);
|
||||
setprg16r(hrd_sw,0xC000,latche&0x1f);
|
||||
}
|
||||
switch((latche>>6)&3)
|
||||
{
|
||||
case 0: setmirrorw(0,0,0,1); break;
|
||||
case 1: setmirror(MI_V); break;
|
||||
case 2: setmirror(MI_H); break;
|
||||
case 3: setmirror(MI_1); break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(BMC42in1rWrite)
|
||||
{
|
||||
latche=V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void BMC42in1rReset(void)
|
||||
{
|
||||
hrd_sw^=1;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void BMC42in1rPower(void)
|
||||
{
|
||||
latche=0x00;
|
||||
hrd_sw=0;
|
||||
setchr8(0);
|
||||
Sync();
|
||||
SetWriteHandler(0x8000,0xFFFF,BMC42in1rWrite);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void BMC42in1r_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=BMC42in1rPower;
|
||||
info->Reset=BMC42in1rReset;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
GameStateRestore=StateRestore;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* BMC 42-in-1 reset switch
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 regs[4];
|
||||
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{regs, 4, "REGS"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
if(regs[0]&0x80)
|
||||
{
|
||||
if(regs[1]&0x80)
|
||||
setprg32(0x8000,regs[1]&0x1F);
|
||||
else
|
||||
{
|
||||
int bank=((regs[1]&0x1f)<<1)|((regs[1]>>6)&1);
|
||||
setprg16(0x8000,bank);
|
||||
setprg16(0xC000,bank);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int bank=((regs[1]&0x1f)<<1)|((regs[1]>>6)&1);
|
||||
setprg16(0xC000,bank);
|
||||
}
|
||||
if(regs[0]&0x20)
|
||||
setmirror(MI_H);
|
||||
else
|
||||
setmirror(MI_V);
|
||||
setchr8((regs[2]<<2)|((regs[0]>>1)&3));
|
||||
}
|
||||
|
||||
static DECLFW(BMC64in1nrWriteLo)
|
||||
{
|
||||
regs[A&3]=V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFW(BMC64in1nrWriteHi)
|
||||
{
|
||||
regs[3]=V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void BMC64in1nrPower(void)
|
||||
{
|
||||
regs[0]=0x80;
|
||||
regs[1]=0x43;
|
||||
regs[2]=regs[3]=0;
|
||||
Sync();
|
||||
SetWriteHandler(0x5000,0x5003,BMC64in1nrWriteLo);
|
||||
SetWriteHandler(0x8000,0xFFFF,BMC64in1nrWriteHi);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void BMC64in1nr_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=BMC64in1nrPower;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
GameStateRestore=StateRestore;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,116 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 is_large_banks;
|
||||
static uint8 large_bank;
|
||||
static uint8 prg_bank;
|
||||
static uint8 chr_bank;
|
||||
static uint8 bank_mode;
|
||||
static uint8 mirroring;
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{&large_bank, 1, "LB"},
|
||||
{&prg_bank, 1, "PRG"},
|
||||
{&chr_bank, 1, "CHR"},
|
||||
{&bank_mode, 1, "BM"},
|
||||
{&mirroring, 1, "MIRR"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
switch (bank_mode)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x10: setprg16(0x8000,large_bank|prg_bank);
|
||||
setprg16(0xC000,large_bank|7);
|
||||
break;
|
||||
case 0x20: setprg32(0x8000,(large_bank|prg_bank)>>1);
|
||||
break;
|
||||
case 0x30: setprg16(0x8000,large_bank|prg_bank);
|
||||
setprg16(0xC000,large_bank|prg_bank);
|
||||
break;
|
||||
}
|
||||
setmirror(mirroring);
|
||||
if(!is_large_banks)
|
||||
setchr8(chr_bank);
|
||||
}
|
||||
|
||||
static DECLFR(BMC70in1Read)
|
||||
{
|
||||
if(bank_mode==0x10)
|
||||
if(is_large_banks)
|
||||
return CartBR((A&0xFFF0)|0x06);
|
||||
else
|
||||
return CartBR((A&0xFFF0)|0x0d);
|
||||
else
|
||||
return CartBR(A);
|
||||
}
|
||||
|
||||
static DECLFW(BMC70in1Write)
|
||||
{
|
||||
if(A&0x4000)
|
||||
{
|
||||
bank_mode=A&0x30;
|
||||
prg_bank=A&7;
|
||||
}
|
||||
else
|
||||
{
|
||||
mirroring=((A&0x20)>>5)^1;
|
||||
if(is_large_banks)
|
||||
large_bank=(A&3)<<3;
|
||||
else
|
||||
chr_bank=A&7;
|
||||
}
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void BMC70in1Power(void)
|
||||
{
|
||||
setchr8(0);
|
||||
bank_mode=0;
|
||||
large_bank=0;
|
||||
Sync();
|
||||
SetReadHandler(0x8000,0xFFFF,BMC70in1Read);
|
||||
SetWriteHandler(0x8000,0xffff,BMC70in1Write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void BMC70in1_Init(CartInfo *info)
|
||||
{
|
||||
is_large_banks=0;
|
||||
info->Power=BMC70in1Power;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void BMC70in1B_Init(CartInfo *info)
|
||||
{
|
||||
is_large_banks=1;
|
||||
info->Power=BMC70in1Power;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint16 addrlatche;
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
if(addrlatche&0x40)
|
||||
{
|
||||
setprg16(0x8000,addrlatche&7);
|
||||
setprg16(0xC000,addrlatche&7);
|
||||
}
|
||||
else
|
||||
setprg32(0x8000,(addrlatche>>1)&3);
|
||||
setchr8((addrlatche>>3)&7);
|
||||
setmirror(((addrlatche&0x80)>>7)^1);
|
||||
}
|
||||
|
||||
static DECLFW(BMCGK192Write)
|
||||
{
|
||||
addrlatche=A;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void BMCGK192Reset(void)
|
||||
{
|
||||
setprg32(0x8000,0);
|
||||
}
|
||||
|
||||
static void BMCGK192Power(void)
|
||||
{
|
||||
setprg32(0x8000,0);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xffff,BMCGK192Write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper58_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=BMCGK192Power;
|
||||
info->Reset=BMCGK192Reset;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&addrlatche, 2, 0, "ALATC");
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 prg_reg;
|
||||
static uint8 chr_reg;
|
||||
|
||||
static uint8 sim0reg, sim0bit, sim0byte, sim0parity, sim0bcnt;
|
||||
static uint16 sim0data;
|
||||
static uint8 sim0array[128] =
|
||||
{
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xAA,
|
||||
};
|
||||
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{&prg_reg, 1, "PREG"},
|
||||
{&chr_reg, 1, "CREG"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
setprg32(0x8000, prg_reg);
|
||||
setchr8(chr_reg);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFW(M216WriteHi)
|
||||
{
|
||||
// FCEU_printf("%04x:%04x\n",A,V);
|
||||
prg_reg=A&1;
|
||||
chr_reg=(A&0x0E)>>1;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFW(M216Write5000)
|
||||
{
|
||||
// FCEU_printf("WRITE: %04x:%04x\n",A,V);
|
||||
sim0reg=V;
|
||||
if(!sim0reg)
|
||||
{
|
||||
sim0bit=sim0byte=sim0parity=0;
|
||||
sim0data=sim0array[0];
|
||||
sim0bcnt=0x80;
|
||||
}
|
||||
else if(sim0reg&0x20)
|
||||
{
|
||||
sim0bcnt=0x20;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(M216Read5000)
|
||||
{
|
||||
if(sim0reg&0x60)
|
||||
{
|
||||
sim0reg=(sim0reg^(sim0reg<<1))&0x40;
|
||||
return sim0reg;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8 sim0out=0;
|
||||
if(sim0bit<8)
|
||||
{
|
||||
// sim0data=((sim0array[sim0byte]<<(sim0bit))&0x80)>>1;
|
||||
sim0out=(sim0data&1)<<6;
|
||||
sim0data>>=1;
|
||||
sim0bit++;
|
||||
sim0parity+=sim0data;
|
||||
}
|
||||
else if(sim0bit==8)
|
||||
{
|
||||
sim0bit++;
|
||||
sim0out=sim0parity&1;
|
||||
}
|
||||
else if(sim0bit==9)
|
||||
{
|
||||
if(sim0byte==sim0bcnt)
|
||||
sim0out=0x60;
|
||||
else
|
||||
{
|
||||
sim0bit=0;
|
||||
sim0byte++;
|
||||
sim0data=sim0array[sim0byte];
|
||||
sim0out=0;
|
||||
}
|
||||
}
|
||||
// FCEU_printf("READ: %04x (%04x-%02x,%04x)\n",A,X.PC,sim0out,sim0byte);
|
||||
return sim0out;
|
||||
}
|
||||
}
|
||||
|
||||
static void Power(void)
|
||||
{
|
||||
prg_reg = 0;
|
||||
chr_reg = 0;
|
||||
Sync();
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xFFFF,M216WriteHi);
|
||||
SetWriteHandler(0x5000,0x5000,M216Write5000);
|
||||
SetReadHandler(0x5000,0x5000,M216Read5000);
|
||||
}
|
||||
|
||||
|
||||
void Mapper216_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=Power;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint16 addrlatche;
|
||||
|
||||
//------------------ UNLCC21 ---------------------------
|
||||
|
||||
static void UNLCC21Sync(void)
|
||||
{
|
||||
setchr8(addrlatche&1);
|
||||
setmirror(MI_0+((addrlatche&2)>>1));
|
||||
}
|
||||
|
||||
static DECLFW(UNLCC21Write)
|
||||
{
|
||||
addrlatche=A;
|
||||
UNLCC21Sync();
|
||||
}
|
||||
|
||||
static void UNLCC21Power(void)
|
||||
{
|
||||
setprg32(0x8000,0);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xffff,UNLCC21Write);
|
||||
}
|
||||
|
||||
static void UNLCC21Restore(int version)
|
||||
{
|
||||
UNLCC21Sync();
|
||||
}
|
||||
|
||||
void UNLCC21_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=UNLCC21Power;
|
||||
GameStateRestore=UNLCC21Restore;
|
||||
AddExState(&addrlatche, 2, 0, "ALATC");
|
||||
}
|
|
@ -0,0 +1,272 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 latche, latcheinit;
|
||||
static uint16 addrreg0, addrreg1;
|
||||
static void(*WSync)(void);
|
||||
|
||||
static DECLFW(LatchWrite)
|
||||
{
|
||||
latche=V;
|
||||
WSync();
|
||||
}
|
||||
|
||||
static void LatchPower(void)
|
||||
{
|
||||
latche=latcheinit;
|
||||
WSync();
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(addrreg0,addrreg1,LatchWrite);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
WSync();
|
||||
}
|
||||
|
||||
void Latch_Init(CartInfo *info, void (*proc)(void), uint8 init, uint16 adr0, uint16 adr1)
|
||||
{
|
||||
latcheinit=init;
|
||||
addrreg0=adr0;
|
||||
addrreg1=adr1;
|
||||
WSync=proc;
|
||||
info->Power=LatchPower;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&latche, 1, 0, "LATC");
|
||||
}
|
||||
|
||||
//------------------ CPROM ---------------------------
|
||||
|
||||
static void CPROMSync(void)
|
||||
{
|
||||
setchr4(0x0000,0);
|
||||
setchr4(0x1000,latche&3);
|
||||
setprg16(0x8000,0);
|
||||
setprg16(0xC000,1);
|
||||
}
|
||||
|
||||
void CPROM_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, CPROMSync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ CNROM ---------------------------
|
||||
|
||||
static void CNROMSync(void)
|
||||
{
|
||||
setchr8(latche&3);
|
||||
setprg16(0x8000,0);
|
||||
setprg16(0xC000,1);
|
||||
}
|
||||
|
||||
void CNROM_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, CNROMSync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ ANROM ---------------------------
|
||||
|
||||
static void ANROMSync()
|
||||
{
|
||||
setprg32(0x8000,latche&0xf);
|
||||
setmirror(MI_0+((latche>>4)&1));
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
void ANROM_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, ANROMSync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 70 ---------------------------
|
||||
|
||||
static void M70Sync()
|
||||
{
|
||||
setprg16(0x8000,latche>>4);
|
||||
setprg16(0xc000,~0);
|
||||
setchr8(latche&0xf);
|
||||
}
|
||||
|
||||
void Mapper70_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M70Sync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 152 ---------------------------
|
||||
|
||||
static void M152Sync()
|
||||
{
|
||||
setprg16(0x8000,(latche>>4)&7);
|
||||
setprg16(0xc000,~0);
|
||||
setchr8(latche&0xf);
|
||||
setmirror(MI_0+((latche>>7)&1)); /* Saint Seiya...hmm. */
|
||||
}
|
||||
|
||||
void Mapper152_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M152Sync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 78 ---------------------------
|
||||
/* Should be two separate emulation functions for this "mapper". Sigh. URGE TO KILL RISING. */
|
||||
static void M78Sync()
|
||||
{
|
||||
setprg16(0x8000,(latche&7));
|
||||
setprg16(0xc000,~0);
|
||||
setchr8(latche>>4);
|
||||
setmirror(MI_0+((latche>>3)&1));
|
||||
}
|
||||
|
||||
void Mapper78_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M78Sync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ MHROM ---------------------------
|
||||
|
||||
static void MHROMSync(void)
|
||||
{
|
||||
setprg32(0x8000,latche>>4);
|
||||
setchr8(latche&0xf);
|
||||
}
|
||||
|
||||
void MHROM_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, MHROMSync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
void Mapper140_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, MHROMSync, 0, 0x6000, 0x7FFF);
|
||||
}
|
||||
|
||||
//------------------ Map 87 ---------------------------
|
||||
|
||||
static void M87Sync(void)
|
||||
{
|
||||
setprg16(0x8000,0);
|
||||
setprg16(0xC000,1);
|
||||
setchr8(latche>>1);
|
||||
}
|
||||
|
||||
void Mapper87_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M87Sync, ~0, 0x6000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 11 ---------------------------
|
||||
|
||||
static void M11Sync(void)
|
||||
{
|
||||
setprg32(0x8000,latche&0xf);
|
||||
setchr8(latche>>4);
|
||||
}
|
||||
|
||||
void Mapper11_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M11Sync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
void Mapper144_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M11Sync, 0, 0x8001, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ UNROM ---------------------------
|
||||
|
||||
static void UNROMSync(void)
|
||||
{
|
||||
setprg16(0x8000,latche);
|
||||
setprg16(0xc000,~0);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
void UNROM_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, UNROMSync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 93 ---------------------------
|
||||
|
||||
static void SSUNROMSync(void)
|
||||
{
|
||||
setprg16(0x8000,latche>>4);
|
||||
setprg16(0xc000,~0);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
void SUNSOFT_UNROM_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, SSUNROMSync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 94 ---------------------------
|
||||
|
||||
static void M94Sync(void)
|
||||
{
|
||||
setprg16(0x8000,latche>>2);
|
||||
setprg16(0xc000,~0);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
void Mapper94_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M94Sync, 0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ Map 107 ---------------------------
|
||||
|
||||
static void M107Sync(void)
|
||||
{
|
||||
setprg32(0x8000,(latche>>1)&3);
|
||||
setchr8(latche&7);
|
||||
}
|
||||
|
||||
void Mapper107_Init(CartInfo *info)
|
||||
{
|
||||
Latch_Init(info, M107Sync, ~0, 0x8000, 0xFFFF);
|
||||
}
|
||||
|
||||
//------------------ NROM ---------------------------
|
||||
|
||||
#ifdef DEBUG_MAPPER
|
||||
static DECLFW(WriteHandler)
|
||||
{
|
||||
FCEU_printf("$%04x:$%02x\n",A,V);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void NROMPower(void)
|
||||
{
|
||||
setprg16(0x8000,0);
|
||||
setprg16(0xC000,~0);
|
||||
setchr8(0);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
#ifdef DEBUG_MAPPER
|
||||
SetWriteHandler(0x4020,0xFFFF,WriteHandler);
|
||||
#endif
|
||||
}
|
||||
|
||||
void NROM_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=NROMPower;
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 cmd;
|
||||
static uint8 DRegs[8];
|
||||
|
||||
static SFORMAT DEI_StateRegs[]=
|
||||
{
|
||||
{&cmd, 1, "CMD"},
|
||||
{DRegs, 8, "DREG"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
setchr2(0x0000,DRegs[0]);
|
||||
setchr2(0x0800,DRegs[1]);
|
||||
int x;
|
||||
for(x=0;x<4;x++)
|
||||
setchr1(0x1000+(x<<10),DRegs[2+x]);
|
||||
setprg8(0x8000,DRegs[6]);
|
||||
setprg8(0xa000,DRegs[7]);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFW(DEIWrite)
|
||||
{
|
||||
switch(A&0x8001)
|
||||
{
|
||||
case 0x8000: cmd=V&0x07; break;
|
||||
case 0x8001: if(cmd<=0x05)
|
||||
V&=0x3F;
|
||||
else
|
||||
V&=0x0F;
|
||||
if(cmd<=0x01) V>>=1;
|
||||
DRegs[cmd&0x07]=V;
|
||||
Sync();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void DEIPower(void)
|
||||
{
|
||||
setprg8(0xc000,0xE);
|
||||
setprg8(0xe000,0xF);
|
||||
cmd=0;
|
||||
memset(DRegs,0,8);
|
||||
Sync();
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xFFFF,DEIWrite);
|
||||
}
|
||||
|
||||
|
||||
void DEIROM_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=DEIPower;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&DEI_StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 latche;
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
setprg16(0x8000,latche);
|
||||
setprg16(0xC000,8);
|
||||
}
|
||||
|
||||
static DECLFW(DREAMWrite)
|
||||
{
|
||||
latche=V&7;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void DREAMPower(void)
|
||||
{
|
||||
latche=0;
|
||||
Sync();
|
||||
setchr8(0);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x5020,0x5020,DREAMWrite);
|
||||
}
|
||||
|
||||
static void Restore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void DreamTech01_Init(CartInfo *info)
|
||||
{
|
||||
GameStateRestore=Restore;
|
||||
info->Power=DREAMPower;
|
||||
AddExState(&latche, 1, 0, "LATCH");
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 unromchr;
|
||||
|
||||
static void BMCFK23CCW(uint32 A, uint8 V)
|
||||
{
|
||||
if(EXPREGS[0]&0x40)
|
||||
setchr8((EXPREGS[2]&0xFC)|unromchr);
|
||||
else
|
||||
{
|
||||
uint16 base=(EXPREGS[2]&0x7F)<<3;
|
||||
setchr1(A,V|base);
|
||||
if(EXPREGS[3]&2)
|
||||
{
|
||||
setchr1(0x0400,EXPREGS[6]|base);
|
||||
setchr1(0x0C00,EXPREGS[7]|base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void BMCFK23CPW(uint32 A, uint8 V)
|
||||
{
|
||||
if(EXPREGS[0]&4)
|
||||
setprg32(0x8000,EXPREGS[1]>>1);
|
||||
else
|
||||
{
|
||||
if(EXPREGS[0]&2)
|
||||
setprg8(A,(V&(0x3F>>(EXPREGS[0]&3)))|(EXPREGS[1]<<1));
|
||||
else
|
||||
setprg8(A,V);
|
||||
if(EXPREGS[3]&2)
|
||||
{
|
||||
setprg8(0xC000,EXPREGS[4]);
|
||||
setprg8(0xE000,EXPREGS[5]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(BMCFK23C8003Write)
|
||||
{
|
||||
if(EXPREGS[0]&0x40)
|
||||
{
|
||||
unromchr=V&3;
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
if((A==0x8001)&&(EXPREGS[3]&2&&MMC3_cmd&8))
|
||||
{
|
||||
EXPREGS[4|(MMC3_cmd&3)]=V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
else
|
||||
MMC3_CMDWrite(A,V);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(BMCFK23CWrite)
|
||||
{
|
||||
EXPREGS[A&3]=V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void BMCFK23CReset(void)
|
||||
{
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void BMCFK23CPower(void)
|
||||
{
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
|
||||
EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x5ff0,0x5fff,BMCFK23CWrite);
|
||||
SetWriteHandler(0x8000,0x8003,BMCFK23C8003Write);
|
||||
}
|
||||
|
||||
void BMCFK23C_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC3_Init(info, 512, 256, 8, 0);
|
||||
cwrap=BMCFK23CCW;
|
||||
pwrap=BMCFK23CPW;
|
||||
info->Power=BMCFK23CPower;
|
||||
info->Reset=BMCFK23CReset;
|
||||
AddExState(EXPREGS, 8, 0, "EXPR");
|
||||
AddExState(&unromchr, 1, 0, "UNCHR");
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
extern uint8 m114_perm[8];
|
||||
|
||||
static void H2288PW(uint32 A, uint8 V)
|
||||
{
|
||||
if(EXPREGS[0]&0x40)
|
||||
{
|
||||
uint8 bank=(EXPREGS[0]&5)|((EXPREGS[0]&8)>>2)|((EXPREGS[0]&0x20)>>2);
|
||||
if(EXPREGS[0]&2)
|
||||
setprg32(0x8000,bank>>1);
|
||||
else
|
||||
{
|
||||
setprg16(0x8000,bank);
|
||||
setprg16(0xC000,bank);
|
||||
}
|
||||
}
|
||||
else
|
||||
setprg8(A,V&0x3F);
|
||||
}
|
||||
|
||||
static DECLFW(H2288WriteHi)
|
||||
{
|
||||
switch (A&0x8001)
|
||||
{
|
||||
case 0x8000: MMC3_CMDWrite(0x8000,(V&0xC0)|(m114_perm[V&7])); break;
|
||||
case 0x8001: MMC3_CMDWrite(0x8001,V); break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(H2288WriteLo)
|
||||
{
|
||||
if(A&0x800)
|
||||
{
|
||||
if(A&1)
|
||||
EXPREGS[1]=V;
|
||||
else
|
||||
EXPREGS[0]=V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(H2288Read)
|
||||
{
|
||||
int bit;
|
||||
bit=(A&1)^1;
|
||||
bit&=((A>>8)&1);
|
||||
bit^=1;
|
||||
return((X.DB&0xFE)|bit);
|
||||
}
|
||||
|
||||
static void H2288Power(void)
|
||||
{
|
||||
EXPREGS[0]=EXPREGS[1]=0;
|
||||
GenMMC3Power();
|
||||
SetReadHandler(0x5000,0x5FFF,H2288Read);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x5000,0x5FFF,H2288WriteLo);
|
||||
SetWriteHandler(0x8000,0x8FFF,H2288WriteHi);
|
||||
}
|
||||
|
||||
void UNLH2288_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC3_Init(info, 256, 256, 0, 0);
|
||||
pwrap=H2288PW;
|
||||
info->Power=H2288Power;
|
||||
AddExState(EXPREGS, 2, 0, "EXPR");
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
extern uint32 ROM_size;
|
||||
static uint8 latche;
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
if(latche)
|
||||
{
|
||||
if(latche&0x10)
|
||||
setprg16(0x8000,(latche&7));
|
||||
else
|
||||
setprg16(0x8000,(latche&7)|8);
|
||||
}
|
||||
else
|
||||
setprg16(0x8000,7+(ROM_size>>4));
|
||||
}
|
||||
|
||||
static DECLFW(M188Write)
|
||||
{
|
||||
latche=V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFR(ExtDev)
|
||||
{
|
||||
return(3);
|
||||
}
|
||||
|
||||
static void Power(void)
|
||||
{
|
||||
latche=0;
|
||||
Sync();
|
||||
setchr8(0);
|
||||
setprg16(0xc000,0x7);
|
||||
SetReadHandler(0x6000,0x7FFF,ExtDev);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xFFFF,M188Write);
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper188_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=Power;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&latche, 1, 0, "LATCH");
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static DECLFW(UNLKOF97CMDWrite)
|
||||
{
|
||||
V=(V&0xD8)|((V&0x20)>>4)|((V&4)<<3)|((V&2)>>1)|((V&1)<<2); //76143502
|
||||
if(A==0x9000) A=0x8001;
|
||||
MMC3_CMDWrite(A,V);
|
||||
}
|
||||
|
||||
static DECLFW(UNLKOF97IRQWrite)
|
||||
{
|
||||
V=(V&0xD8)|((V&0x20)>>4)|((V&4)<<3)|((V&2)>>1)|((V&1)<<2);
|
||||
if(A==0xD000) A=0xC001;
|
||||
else if(A==0xF000) A=0xE001;
|
||||
MMC3_IRQWrite(A,V);
|
||||
}
|
||||
|
||||
static void UNLKOF97Power(void)
|
||||
{
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x8000,0xA000,UNLKOF97CMDWrite);
|
||||
SetWriteHandler(0xC000,0xF000,UNLKOF97IRQWrite);
|
||||
}
|
||||
|
||||
void UNLKOF97_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC3_Init(info, 128, 256, 0, 0);
|
||||
info->Power=UNLKOF97Power;
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*
|
||||
* CAI Shogakko no Sansu
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 *CHRRAM=NULL;
|
||||
static uint8 SWRAM[4096];
|
||||
|
||||
static uint8 regs[16];
|
||||
static uint8 WRAM[4096];
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{®s, 16, "REGS"},
|
||||
{WRAM, 4096, "WRAM"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
if(regs[5]&0x40)
|
||||
{
|
||||
setchr4r(0,0x1000,regs[5]&0x3F);
|
||||
}
|
||||
else
|
||||
{
|
||||
setchr4r(0x10,0x0000,regs[5]);
|
||||
setchr4r(0x10,0x1000,regs[5]^1);
|
||||
}
|
||||
setprg8r((regs[2]>>6)&1,0x8000,(regs[2]&0x3F));
|
||||
setprg8r((regs[3]>>6)&1,0xA000,(regs[3]&0x3F));
|
||||
setprg8r((regs[4]>>6)&1,0xC000,(regs[4]&0x3F));
|
||||
setprg8r(1,0xE000,~0);
|
||||
setmirror((regs[0xA]&3));
|
||||
}
|
||||
|
||||
static DECLFW(M190Write)
|
||||
{
|
||||
// FCEU_printf("write %04x:%04x %d, %d\n",A,V,scanline,timestamp);
|
||||
regs[(A&0x0F00)>>8]=V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static DECLFR(M190Read)
|
||||
{
|
||||
// FCEU_printf("read %04x:%04x %d, %d\n",A,regs[(A&0x0F00)>>8],scanline,timestamp);
|
||||
return regs[(A&0x0F00)>>8];
|
||||
}
|
||||
|
||||
static DECLFR(AWRAM)
|
||||
{
|
||||
return(WRAM[A-0x7000]);
|
||||
}
|
||||
static DECLFW(BWRAM)
|
||||
{
|
||||
WRAM[A-0x7000]=V;
|
||||
}
|
||||
|
||||
static DECLFR(ASWRAM)
|
||||
{
|
||||
return(SWRAM[A-0x6000]);
|
||||
}
|
||||
static DECLFW(BSWRAM)
|
||||
{
|
||||
SWRAM[A-0x6000]=V;
|
||||
}
|
||||
|
||||
static void M190Power(void)
|
||||
{
|
||||
setvram8(CHRRAM);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xFFFF,M190Write);
|
||||
// SetReadHandler(0xDA00,0xDA00,M190Read);
|
||||
// SetReadHandler(0xDB00,0xDB00,M190Read);
|
||||
SetReadHandler(0xDC00,0xDC00,M190Read);
|
||||
SetReadHandler(0xDD00,0xDD00,M190Read);
|
||||
SetReadHandler(0x7000,0x7FFF,AWRAM);
|
||||
SetWriteHandler(0x7000,0x7FFF,BWRAM);
|
||||
SetReadHandler(0x6000,0x6FFF,ASWRAM);
|
||||
SetWriteHandler(0x6000,0x6FFF,BSWRAM);
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void M190Close(void)
|
||||
{
|
||||
if(CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM=NULL;
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper190_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=M190Power;
|
||||
info->Close=M190Close;
|
||||
if(info->battery)
|
||||
{
|
||||
info->SaveGame[0]=SWRAM;
|
||||
info->SaveGameLen[0]=4096;
|
||||
}
|
||||
GameStateRestore=StateRestore;
|
||||
CHRRAM=(uint8*)FCEU_gmalloc(8192);
|
||||
SetupCartCHRMapping(0x10,CHRRAM,8192,1);
|
||||
AddExState(CHRRAM, 8192, 0, "CHRRAM");
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 WRAM[2048];
|
||||
|
||||
static void MALEEReset(void)
|
||||
{
|
||||
setprg2r(0x10,0x7000,0);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetReadHandler(0x6000,0x67FF,CartBR);
|
||||
SetReadHandler(0x7000,0x77FF,CartBR);
|
||||
setprg2r(1,0x6000,0);
|
||||
setprg32(0x8000,0);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
void MALEE_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=MALEEReset;
|
||||
SetupCartPRGMapping(0x10, WRAM, 2048, 1);
|
||||
AddExState(WRAM, 2048, 0,"RAM");
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
#include "../types.h"
|
||||
#include "../x6502.h"
|
||||
#include "../fceu.h"
|
||||
#include "../ppu.h"
|
||||
#include "../memory.h"
|
||||
#include "../sound.h"
|
||||
#include "../state.h"
|
||||
#include "../cart.h"
|
||||
#include "../cheat.h"
|
||||
#include "../unif.h"
|
||||
#include <string.h>
|
|
@ -0,0 +1,423 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 1998 BERO
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static void GenMMC1Power(void);
|
||||
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery);
|
||||
|
||||
static uint8 DRegs[4];
|
||||
static uint8 Buffer,BufferShift;
|
||||
|
||||
static int mmc1opts;
|
||||
|
||||
static void (*MMC1CHRHook4)(uint32 A, uint8 V);
|
||||
static void (*MMC1PRGHook16)(uint32 A, uint8 V);
|
||||
|
||||
static uint8 *WRAM=NULL;
|
||||
static uint8 *CHRRAM=NULL;
|
||||
static int is155;
|
||||
|
||||
static DECLFW(MBWRAM)
|
||||
{
|
||||
if(!(DRegs[3]&0x10)||is155)
|
||||
Page[A>>11][A]=V; // WRAM is enabled.
|
||||
}
|
||||
|
||||
static DECLFR(MAWRAM)
|
||||
{
|
||||
if((DRegs[3]&0x10)&&!is155)
|
||||
return X.DB; // WRAM is disabled
|
||||
return(Page[A>>11][A]);
|
||||
}
|
||||
|
||||
static void MMC1CHR(void)
|
||||
{
|
||||
if(mmc1opts&4)
|
||||
{
|
||||
if(DRegs[0]&0x10)
|
||||
setprg8r(0x10,0x6000,(DRegs[1]>>4)&1);
|
||||
else
|
||||
setprg8r(0x10,0x6000,(DRegs[1]>>3)&1);
|
||||
}
|
||||
if(MMC1CHRHook4)
|
||||
{
|
||||
if(DRegs[0]&0x10)
|
||||
{
|
||||
MMC1CHRHook4(0x0000,DRegs[1]);
|
||||
MMC1CHRHook4(0x1000,DRegs[2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
MMC1CHRHook4(0x0000,(DRegs[1]&0xFE));
|
||||
MMC1CHRHook4(0x1000,DRegs[1]|1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DRegs[0]&0x10)
|
||||
{
|
||||
setchr4(0x0000,DRegs[1]);
|
||||
setchr4(0x1000,DRegs[2]);
|
||||
}
|
||||
else
|
||||
setchr8(DRegs[1]>>1);
|
||||
}
|
||||
}
|
||||
|
||||
static void MMC1PRG(void)
|
||||
{
|
||||
uint8 offs=DRegs[1]&0x10;
|
||||
if(MMC1PRGHook16)
|
||||
{
|
||||
switch(DRegs[0]&0xC)
|
||||
{
|
||||
case 0xC: MMC1PRGHook16(0x8000,(DRegs[3]+offs));
|
||||
MMC1PRGHook16(0xC000,0xF+offs);
|
||||
break;
|
||||
case 0x8: MMC1PRGHook16(0xC000,(DRegs[3]+offs));
|
||||
MMC1PRGHook16(0x8000,offs);
|
||||
break;
|
||||
case 0x0:
|
||||
case 0x4:
|
||||
MMC1PRGHook16(0x8000,((DRegs[3]&~1)+offs));
|
||||
MMC1PRGHook16(0xc000,((DRegs[3]&~1)+offs+1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
else switch(DRegs[0]&0xC)
|
||||
{
|
||||
case 0xC: setprg16(0x8000,(DRegs[3]+offs));
|
||||
setprg16(0xC000,0xF+offs);
|
||||
break;
|
||||
case 0x8: setprg16(0xC000,(DRegs[3]+offs));
|
||||
setprg16(0x8000,offs);
|
||||
break;
|
||||
case 0x0:
|
||||
case 0x4:
|
||||
setprg16(0x8000,((DRegs[3]&~1)+offs));
|
||||
setprg16(0xc000,((DRegs[3]&~1)+offs+1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void MMC1MIRROR(void)
|
||||
{
|
||||
switch(DRegs[0]&3)
|
||||
{
|
||||
case 2: setmirror(MI_V); break;
|
||||
case 3: setmirror(MI_H); break;
|
||||
case 0: setmirror(MI_0); break;
|
||||
case 1: setmirror(MI_1); break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64 lreset;
|
||||
static DECLFW(MMC1_write)
|
||||
{
|
||||
int n=(A>>13)-4;
|
||||
//FCEU_DispMessage("%016x",timestampbase+timestamp);
|
||||
//printf("$%04x:$%02x, $%04x\n",A,V,X.PC);
|
||||
//DumpMem("out",0xe000,0xffff);
|
||||
|
||||
/* The MMC1 is busy so ignore the write. */
|
||||
/* As of version FCE Ultra 0.81, the timestamp is only
|
||||
increased before each instruction is executed(in other words
|
||||
precision isn't that great), but this should still work to
|
||||
deal with 2 writes in a row from a single RMW instruction. */
|
||||
if((timestampbase+timestamp)<(lreset+2)) return;
|
||||
if(V&0x80)
|
||||
{
|
||||
DRegs[0]|=0xC;
|
||||
BufferShift=Buffer=0;
|
||||
MMC1PRG();
|
||||
lreset=timestampbase+timestamp;
|
||||
return;
|
||||
}
|
||||
Buffer|=(V&1)<<(BufferShift++);
|
||||
if(BufferShift==5)
|
||||
{
|
||||
DRegs[n] = Buffer;
|
||||
BufferShift = Buffer = 0;
|
||||
switch(n)
|
||||
{
|
||||
case 0: MMC1MIRROR(); MMC1CHR(); MMC1PRG(); break;
|
||||
case 1: MMC1CHR(); MMC1PRG(); break;
|
||||
case 2: MMC1CHR(); break;
|
||||
case 3: MMC1PRG(); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void MMC1_Restore(int version)
|
||||
{
|
||||
MMC1MIRROR();
|
||||
MMC1CHR();
|
||||
MMC1PRG();
|
||||
lreset=0; /* timestamp(base) is not stored in save states. */
|
||||
}
|
||||
|
||||
static void MMC1CMReset(void)
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<4;i++)
|
||||
DRegs[i]=0;
|
||||
Buffer = BufferShift = 0;
|
||||
DRegs[0]=0x1F;
|
||||
DRegs[1]=0;
|
||||
DRegs[2]=0; // Should this be something other than 0?
|
||||
DRegs[3]=0;
|
||||
|
||||
MMC1MIRROR();
|
||||
MMC1CHR();
|
||||
MMC1PRG();
|
||||
}
|
||||
|
||||
static int DetectMMC1WRAMSize(uint32 crc32)
|
||||
{
|
||||
switch(crc32)
|
||||
{
|
||||
case 0xc6182024: /* Romance of the 3 Kingdoms */
|
||||
case 0x2225c20f: /* Genghis Khan */
|
||||
case 0x4642dda6: /* Nobunaga's Ambition */
|
||||
case 0x29449ba9: /* "" "" (J) */
|
||||
case 0x2b11e0b0: /* "" "" (J) */
|
||||
case 0xb8747abf: /* Best Play Pro Yakyuu Special (J) */
|
||||
case 0xc9556b36: /* Final Fantasy I & II (J) [!] */
|
||||
FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n");
|
||||
return(16);
|
||||
break;
|
||||
default:return(8);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32 NWCIRQCount;
|
||||
static uint8 NWCRec;
|
||||
#define NWCDIP 0xE
|
||||
|
||||
static void FP_FASTAPASS(1) NWCIRQHook(int a)
|
||||
{
|
||||
if(!(NWCRec&0x10))
|
||||
{
|
||||
NWCIRQCount+=a;
|
||||
if((NWCIRQCount|(NWCDIP<<25))>=0x3e000000)
|
||||
{
|
||||
NWCIRQCount=0;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void NWCCHRHook(uint32 A, uint8 V)
|
||||
{
|
||||
if((V&0x10)) // && !(NWCRec&0x10))
|
||||
{
|
||||
NWCIRQCount=0;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
}
|
||||
NWCRec=V;
|
||||
if(V&0x08)
|
||||
MMC1PRG();
|
||||
else
|
||||
setprg32(0x8000,(V>>1)&3);
|
||||
}
|
||||
|
||||
static void NWCPRGHook(uint32 A, uint8 V)
|
||||
{
|
||||
if(NWCRec&0x8)
|
||||
setprg16(A,8|(V&0x7));
|
||||
else
|
||||
setprg32(0x8000,(NWCRec>>1)&3);
|
||||
}
|
||||
|
||||
static void NWCPower(void)
|
||||
{
|
||||
GenMMC1Power();
|
||||
setchr8r(0,0);
|
||||
}
|
||||
|
||||
void Mapper105_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC1Init(info, 256, 256, 8, 0);
|
||||
MMC1CHRHook4=NWCCHRHook;
|
||||
MMC1PRGHook16=NWCPRGHook;
|
||||
MapIRQHook=NWCIRQHook;
|
||||
info->Power=NWCPower;
|
||||
}
|
||||
|
||||
static void GenMMC1Power(void)
|
||||
{
|
||||
lreset=0;
|
||||
if(mmc1opts&1)
|
||||
{
|
||||
FCEU_CheatAddRAM(8,0x6000,WRAM);
|
||||
if(mmc1opts&4)
|
||||
FCEU_dwmemset(WRAM,0,8192)
|
||||
else if(!(mmc1opts&2))
|
||||
FCEU_dwmemset(WRAM,0,8192);
|
||||
}
|
||||
SetWriteHandler(0x8000,0xFFFF,MMC1_write);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
|
||||
if(mmc1opts&1)
|
||||
{
|
||||
SetReadHandler(0x6000,0x7FFF,MAWRAM);
|
||||
SetWriteHandler(0x6000,0x7FFF,MBWRAM);
|
||||
setprg8r(0x10,0x6000,0);
|
||||
}
|
||||
|
||||
MMC1CMReset();
|
||||
}
|
||||
|
||||
static void GenMMC1Close(void)
|
||||
{
|
||||
if(CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
if(WRAM)
|
||||
FCEU_gfree(WRAM);
|
||||
CHRRAM=WRAM=NULL;
|
||||
}
|
||||
|
||||
static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery)
|
||||
{
|
||||
is155=0;
|
||||
|
||||
info->Close=GenMMC1Close;
|
||||
MMC1PRGHook16=MMC1CHRHook4=0;
|
||||
mmc1opts=0;
|
||||
PRGmask16[0]&=(prg>>14)-1;
|
||||
CHRmask4[0]&=(chr>>12)-1;
|
||||
CHRmask8[0]&=(chr>>13)-1;
|
||||
|
||||
if(wram)
|
||||
{
|
||||
WRAM=(uint8*)FCEU_gmalloc(wram*1024);
|
||||
mmc1opts|=1;
|
||||
if(wram>8) mmc1opts|=4;
|
||||
SetupCartPRGMapping(0x10,WRAM,wram*1024,1);
|
||||
AddExState(WRAM, wram*1024, 0, "WRAM");
|
||||
if(battery)
|
||||
{
|
||||
mmc1opts|=2;
|
||||
info->SaveGame[0]=WRAM+((mmc1opts&4)?8192:0);
|
||||
info->SaveGameLen[0]=8192;
|
||||
}
|
||||
}
|
||||
if(!chr)
|
||||
{
|
||||
CHRRAM=(uint8*)FCEU_gmalloc(8192);
|
||||
SetupCartCHRMapping(0, CHRRAM, 8192, 1);
|
||||
AddExState(CHRRAM, 8192, 0, "CHRR");
|
||||
}
|
||||
AddExState(DRegs, 4, 0, "DREG");
|
||||
|
||||
info->Power=GenMMC1Power;
|
||||
GameStateRestore=MMC1_Restore;
|
||||
AddExState(&lreset, 8, 1, "LRST");
|
||||
}
|
||||
|
||||
void Mapper1_Init(CartInfo *info)
|
||||
{
|
||||
int ws=DetectMMC1WRAMSize(info->CRC32);
|
||||
GenMMC1Init(info, 512, 256, ws, info->battery);
|
||||
}
|
||||
|
||||
/* Same as mapper 1, without respect for WRAM enable bit. */
|
||||
void Mapper155_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC1Init(info,512,256,8,info->battery);
|
||||
is155=1;
|
||||
}
|
||||
|
||||
void SAROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC1Init(info, 128, 64, 8, info->battery);
|
||||
}
|
||||
|
||||
void SBROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC1Init(info, 128, 64, 0, 0);
|
||||
}
|
||||
|
||||
void SCROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC1Init(info, 128, 128, 0, 0);
|
||||
}
|
||||
|
||||
void SEROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC1Init(info, 32, 64, 0, 0);
|
||||
}
|
||||
|
||||
void SGROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC1Init(info, 256, 0, 0, 0);
|
||||
}
|
||||
|
||||
void SKROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC1Init(info, 256, 64, 8, info->battery);
|
||||
}
|
||||
|
||||
void SLROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC1Init(info, 256, 128, 0, 0);
|
||||
}
|
||||
|
||||
void SL1ROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC1Init(info, 128, 128, 0, 0);
|
||||
}
|
||||
|
||||
/* Begin unknown - may be wrong - perhaps they use different MMC1s from the
|
||||
similarly functioning boards?
|
||||
*/
|
||||
|
||||
void SL2ROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC1Init(info, 256, 256, 0, 0);
|
||||
}
|
||||
|
||||
void SFROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC1Init(info, 256, 256, 0, 0);
|
||||
}
|
||||
|
||||
void SHROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC1Init(info, 256, 256, 0, 0);
|
||||
}
|
||||
|
||||
/* End unknown */
|
||||
/* */
|
||||
/* */
|
||||
|
||||
void SNROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC1Init(info, 256, 0, 8, info->battery);
|
||||
}
|
||||
|
||||
void SOROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC1Init(info, 256, 0, 16, info->battery);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,23 @@
|
|||
extern uint8 MMC3_cmd;
|
||||
extern uint8 *WRAM;
|
||||
extern uint8 *CHRRAM;
|
||||
extern uint8 EXPREGS[8];
|
||||
#undef IRQCount
|
||||
#undef IRQLatch
|
||||
#undef IRQa
|
||||
extern uint8 IRQCount,IRQLatch,IRQa;
|
||||
extern uint8 IRQReload;
|
||||
|
||||
extern void (*pwrap)(uint32 A, uint8 V);
|
||||
extern void (*cwrap)(uint32 A, uint8 V);
|
||||
extern void (*mwrap)(uint8 V);
|
||||
|
||||
void GenMMC3Power(void);
|
||||
void GenMMC3Restore(int version);
|
||||
void MMC3RegReset(void);
|
||||
void FixMMC3PRG(int V);
|
||||
void FixMMC3CHR(int V);
|
||||
DECLFW(MMC3_CMDWrite);
|
||||
DECLFW(MMC3_IRQWrite);
|
||||
|
||||
void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery);
|
|
@ -0,0 +1,834 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* None of this code should use any of the iNES bank switching wrappers. */
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static void (*sfun)(int P);
|
||||
static void (*psfun)(void);
|
||||
|
||||
void MMC5RunSound(int Count);
|
||||
void MMC5RunSoundHQ(void);
|
||||
|
||||
static INLINE void MMC5SPRVROM_BANK1(uint32 A,uint32 V)
|
||||
{
|
||||
if(CHRptr[0])
|
||||
{
|
||||
V&=CHRmask1[0];
|
||||
MMC5SPRVPage[(A)>>10]=&CHRptr[0][(V)<<10]-(A);
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void MMC5BGVROM_BANK1(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask1[0];MMC5BGVPage[(A)>>10]=&CHRptr[0][(V)<<10]-(A);}}
|
||||
|
||||
static INLINE void MMC5SPRVROM_BANK2(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask2[0];MMC5SPRVPage[(A)>>10]=MMC5SPRVPage[((A)>>10)+1]=&CHRptr[0][(V)<<11]-(A);}}
|
||||
static INLINE void MMC5BGVROM_BANK2(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask2[0];MMC5BGVPage[(A)>>10]=MMC5BGVPage[((A)>>10)+1]=&CHRptr[0][(V)<<11]-(A);}}
|
||||
|
||||
static INLINE void MMC5SPRVROM_BANK4(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask4[0];MMC5SPRVPage[(A)>>10]=MMC5SPRVPage[((A)>>10)+1]= MMC5SPRVPage[((A)>>10)+2]=MMC5SPRVPage[((A)>>10)+3]=&CHRptr[0][(V)<<12]-(A);}}
|
||||
static INLINE void MMC5BGVROM_BANK4(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask4[0];MMC5BGVPage[(A)>>10]=MMC5BGVPage[((A)>>10)+1]=MMC5BGVPage[((A)>>10)+2]=MMC5BGVPage[((A)>>10)+3]=&CHRptr[0][(V)<<12]-(A);}}
|
||||
|
||||
static INLINE void MMC5SPRVROM_BANK8(uint32 V) {if(CHRptr[0]){V&=CHRmask8[0];MMC5SPRVPage[0]=MMC5SPRVPage[1]=MMC5SPRVPage[2]=MMC5SPRVPage[3]=MMC5SPRVPage[4]=MMC5SPRVPage[5]=MMC5SPRVPage[6]=MMC5SPRVPage[7]=&CHRptr[0][(V)<<13];}}
|
||||
static INLINE void MMC5BGVROM_BANK8(uint32 V) {if(CHRptr[0]){V&=CHRmask8[0];MMC5BGVPage[0]=MMC5BGVPage[1]=MMC5BGVPage[2]=MMC5BGVPage[3]=MMC5BGVPage[4]=MMC5BGVPage[5]=MMC5BGVPage[6]=MMC5BGVPage[7]=&CHRptr[0][(V)<<13];}}
|
||||
|
||||
static uint8 PRGBanks[4];
|
||||
static uint8 WRAMPage;
|
||||
static uint8 CHRBanksA[8], CHRBanksB[4];
|
||||
static uint8 WRAMMaskEnable[2];
|
||||
static uint8 ABMode; /* A=0, B=1 */
|
||||
|
||||
static uint8 IRQScanline,IRQEnable;
|
||||
static uint8 CHRMode, NTAMirroring, NTFill, ATFill;
|
||||
|
||||
static uint8 MMC5IRQR;
|
||||
static uint8 MMC5LineCounter;
|
||||
static uint8 mmc5psize, mmc5vsize;
|
||||
static uint8 mul[2];
|
||||
|
||||
static uint8 *WRAM=NULL;
|
||||
static uint8 *MMC5fill=NULL;
|
||||
static uint8 *ExRAM=NULL;
|
||||
|
||||
static uint8 MMC5WRAMsize;
|
||||
static uint8 MMC5WRAMIndex[8];
|
||||
|
||||
static uint8 MMC5ROMWrProtect[4];
|
||||
static uint8 MMC5MemIn[5];
|
||||
|
||||
static void MMC5CHRA(void);
|
||||
static void MMC5CHRB(void);
|
||||
|
||||
typedef struct __cartdata {
|
||||
uint32 crc32;
|
||||
uint8 size;
|
||||
} cartdata;
|
||||
|
||||
|
||||
// ETROM seems to have 16KB of WRAM, ELROM seems to have 8KB
|
||||
// EWROM seems to have 32KB of WRAM
|
||||
|
||||
#define MMC5_NOCARTS 14
|
||||
cartdata MMC5CartList[MMC5_NOCARTS]=
|
||||
{
|
||||
{0x9c18762b,2}, /* L'Empereur */
|
||||
{0x26533405,2},
|
||||
{0x6396b988,2},
|
||||
|
||||
{0xaca15643,2}, /* Uncharted Waters */
|
||||
{0xfe3488d1,2}, /* Dai Koukai Jidai */
|
||||
|
||||
{0x15fe6d0f,2}, /* BKAC */
|
||||
{0x39f2ce4b,2}, /* Suikoden */
|
||||
|
||||
{0x8ce478db,2}, /* Nobunaga's Ambition 2 */
|
||||
{0xeee9a682,2},
|
||||
|
||||
{0x1ced086f,2}, /* Ishin no Arashi */
|
||||
|
||||
{0xf540677b,4}, /* Nobunaga...Bushou Fuuun Roku */
|
||||
|
||||
{0x6f4e4312,4}, /* Aoki Ookami..Genchou */
|
||||
|
||||
{0xf011e490,4}, /* Romance of the 3 Kingdoms 2 */
|
||||
{0x184c2124,4}, /* Sangokushi 2 */
|
||||
};
|
||||
|
||||
|
||||
int DetectMMC5WRAMSize(uint32 crc32)
|
||||
{
|
||||
int x;
|
||||
for(x=0;x<MMC5_NOCARTS;x++)
|
||||
if(crc32==MMC5CartList[x].crc32)
|
||||
{
|
||||
FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n");
|
||||
return(MMC5CartList[x].size*8);
|
||||
}
|
||||
return(8);
|
||||
}
|
||||
|
||||
static void BuildWRAMSizeTable(void)
|
||||
{
|
||||
int x;
|
||||
for(x=0;x<8;x++)
|
||||
{
|
||||
switch(MMC5WRAMsize)
|
||||
{
|
||||
case 0: MMC5WRAMIndex[x]=255; break;
|
||||
case 1: MMC5WRAMIndex[x]=(x>3)?255:0; break;
|
||||
case 2: MMC5WRAMIndex[x]=(x&4)>>2; break;
|
||||
case 4: MMC5WRAMIndex[x]=(x>3)?255:(x&3); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void MMC5CHRA(void)
|
||||
{
|
||||
int x;
|
||||
switch(mmc5vsize&3)
|
||||
{
|
||||
case 0: setchr8(CHRBanksA[7]);
|
||||
MMC5SPRVROM_BANK8(CHRBanksA[7]);
|
||||
break;
|
||||
case 1: setchr4(0x0000,CHRBanksA[3]);
|
||||
setchr4(0x1000,CHRBanksA[7]);
|
||||
MMC5SPRVROM_BANK4(0x0000,CHRBanksA[3]);
|
||||
MMC5SPRVROM_BANK4(0x1000,CHRBanksA[7]);
|
||||
break;
|
||||
case 2: setchr2(0x0000,CHRBanksA[1]);
|
||||
setchr2(0x0800,CHRBanksA[3]);
|
||||
setchr2(0x1000,CHRBanksA[5]);
|
||||
setchr2(0x1800,CHRBanksA[7]);
|
||||
MMC5SPRVROM_BANK2(0x0000,CHRBanksA[1]);
|
||||
MMC5SPRVROM_BANK2(0x0800,CHRBanksA[3]);
|
||||
MMC5SPRVROM_BANK2(0x1000,CHRBanksA[5]);
|
||||
MMC5SPRVROM_BANK2(0x1800,CHRBanksA[7]);
|
||||
break;
|
||||
case 3: for(x=0;x<8;x++)
|
||||
{
|
||||
setchr1(x<<10,CHRBanksA[x]);
|
||||
MMC5SPRVROM_BANK1(x<<10,CHRBanksA[x]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void MMC5CHRB(void)
|
||||
{
|
||||
int x;
|
||||
switch(mmc5vsize&3)
|
||||
{
|
||||
case 0: setchr8(CHRBanksB[3]);
|
||||
MMC5BGVROM_BANK8(CHRBanksB[3]);
|
||||
break;
|
||||
case 1: setchr4(0x0000,CHRBanksB[3]);
|
||||
setchr4(0x1000,CHRBanksB[3]);
|
||||
MMC5BGVROM_BANK4(0x0000,CHRBanksB[3]);
|
||||
MMC5BGVROM_BANK4(0x1000,CHRBanksB[3]);
|
||||
break;
|
||||
case 2: setchr2(0x0000,CHRBanksB[1]);
|
||||
setchr2(0x0800,CHRBanksB[3]);
|
||||
setchr2(0x1000,CHRBanksB[1]);
|
||||
setchr2(0x1800,CHRBanksB[3]);
|
||||
MMC5BGVROM_BANK2(0x0000,CHRBanksB[1]);
|
||||
MMC5BGVROM_BANK2(0x0800,CHRBanksB[3]);
|
||||
MMC5BGVROM_BANK2(0x1000,CHRBanksB[1]);
|
||||
MMC5BGVROM_BANK2(0x1800,CHRBanksB[3]);
|
||||
break;
|
||||
case 3: for(x=0;x<8;x++)
|
||||
{
|
||||
setchr1(x<<10,CHRBanksB[x&3]);
|
||||
MMC5BGVROM_BANK1(x<<10,CHRBanksB[x&3]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void FASTAPASS(2) MMC5WRAM(uint32 A, uint32 V)
|
||||
{
|
||||
//printf("%02x\n",V);
|
||||
V=MMC5WRAMIndex[V&7];
|
||||
if(V!=255)
|
||||
{
|
||||
setprg8r(0x10,A,V);
|
||||
MMC5MemIn[(A-0x6000)>>13]=1;
|
||||
}
|
||||
else
|
||||
MMC5MemIn[(A-0x6000)>>13]=0;
|
||||
}
|
||||
|
||||
static void MMC5PRG(void)
|
||||
{
|
||||
int x;
|
||||
switch(mmc5psize&3)
|
||||
{
|
||||
case 0: MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=
|
||||
MMC5ROMWrProtect[2]=MMC5ROMWrProtect[3]=1;
|
||||
setprg32(0x8000,((PRGBanks[1]&0x7F)>>2));
|
||||
for(x=0;x<4;x++)
|
||||
MMC5MemIn[1+x]=1;
|
||||
break;
|
||||
case 1: if(PRGBanks[1]&0x80)
|
||||
{
|
||||
MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=1;
|
||||
setprg16(0x8000,(PRGBanks[1]>>1));
|
||||
MMC5MemIn[1]=MMC5MemIn[2]=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=0;
|
||||
MMC5WRAM(0x8000,PRGBanks[1]&7&0xFE);
|
||||
MMC5WRAM(0xA000,(PRGBanks[1]&7&0xFE)+1);
|
||||
}
|
||||
MMC5MemIn[3]=MMC5MemIn[4]=1;
|
||||
MMC5ROMWrProtect[2]=MMC5ROMWrProtect[3]=1;
|
||||
setprg16(0xC000,(PRGBanks[3]&0x7F)>>1);
|
||||
break;
|
||||
case 2: if(PRGBanks[1]&0x80)
|
||||
{
|
||||
MMC5MemIn[1]=MMC5MemIn[2]=1;
|
||||
MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=1;
|
||||
setprg16(0x8000,(PRGBanks[1]&0x7F)>>1);
|
||||
}
|
||||
else
|
||||
{
|
||||
MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=0;
|
||||
MMC5WRAM(0x8000,PRGBanks[1]&7&0xFE);
|
||||
MMC5WRAM(0xA000,(PRGBanks[1]&7&0xFE)+1);
|
||||
}
|
||||
if(PRGBanks[2]&0x80)
|
||||
{
|
||||
MMC5ROMWrProtect[2]=1;
|
||||
MMC5MemIn[3]=1;
|
||||
setprg8(0xC000,PRGBanks[2]&0x7F);
|
||||
}
|
||||
else
|
||||
{
|
||||
MMC5ROMWrProtect[2]=0;
|
||||
MMC5WRAM(0xC000,PRGBanks[2]&7);
|
||||
}
|
||||
MMC5MemIn[4]=1;
|
||||
MMC5ROMWrProtect[3]=1;
|
||||
setprg8(0xE000,PRGBanks[3]&0x7F);
|
||||
break;
|
||||
case 3: for(x=0;x<3;x++)
|
||||
if(PRGBanks[x]&0x80)
|
||||
{
|
||||
MMC5ROMWrProtect[x]=1;
|
||||
setprg8(0x8000+(x<<13),PRGBanks[x]&0x7F);
|
||||
MMC5MemIn[1+x]=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
MMC5ROMWrProtect[x]=0;
|
||||
MMC5WRAM(0x8000+(x<<13),PRGBanks[x]&7);
|
||||
}
|
||||
MMC5MemIn[4]=1;
|
||||
MMC5ROMWrProtect[3]=1;
|
||||
setprg8(0xE000,PRGBanks[3]&0x7F);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(Mapper5_write)
|
||||
{
|
||||
if(A>=0x5120&&A<=0x5127)
|
||||
{
|
||||
ABMode = 0;
|
||||
CHRBanksA[A&7]=V;
|
||||
MMC5CHRA();
|
||||
}
|
||||
else switch(A)
|
||||
{
|
||||
case 0x5105: {
|
||||
int x;
|
||||
for(x=0;x<4;x++)
|
||||
{
|
||||
switch((V>>(x<<1))&3)
|
||||
{
|
||||
case 0:PPUNTARAM|=1<<x;vnapage[x]=NTARAM;break;
|
||||
case 1:PPUNTARAM|=1<<x;vnapage[x]=NTARAM+0x400;break;
|
||||
case 2:PPUNTARAM|=1<<x;vnapage[x]=ExRAM;break;
|
||||
case 3:PPUNTARAM&=~(1<<x);vnapage[x]=MMC5fill;break;
|
||||
}
|
||||
}
|
||||
}
|
||||
NTAMirroring=V;
|
||||
break;
|
||||
case 0x5113: WRAMPage=V;MMC5WRAM(0x6000,V&7);break;
|
||||
case 0x5100: mmc5psize=V;MMC5PRG();break;
|
||||
case 0x5101: mmc5vsize=V;
|
||||
if(!ABMode)
|
||||
{ MMC5CHRB();MMC5CHRA();}
|
||||
else
|
||||
{ MMC5CHRA();MMC5CHRB();}
|
||||
break;
|
||||
case 0x5114:
|
||||
case 0x5115:
|
||||
case 0x5116:
|
||||
case 0x5117: PRGBanks[A&3]=V;MMC5PRG();break;
|
||||
case 0x5128:
|
||||
case 0x5129:
|
||||
case 0x512a:
|
||||
case 0x512b: ABMode=1;
|
||||
CHRBanksB[A&3]=V;
|
||||
MMC5CHRB();
|
||||
break;
|
||||
case 0x5102: WRAMMaskEnable[0]=V;break;
|
||||
case 0x5103: WRAMMaskEnable[1]=V;break;
|
||||
case 0x5104: CHRMode=V;MMC5HackCHRMode=V&3;break;
|
||||
case 0x5106: if(V!=NTFill)
|
||||
{
|
||||
uint32 t;
|
||||
t=V|(V<<8)|(V<<16)|(V<<24);
|
||||
FCEU_dwmemset(MMC5fill,t,0x3c0);
|
||||
}
|
||||
NTFill=V;
|
||||
break;
|
||||
case 0x5107: if(V!=ATFill)
|
||||
{
|
||||
unsigned char moop;
|
||||
uint32 t;
|
||||
moop=V|(V<<2)|(V<<4)|(V<<6);
|
||||
t=moop|(moop<<8)|(moop<<16)|(moop<<24);
|
||||
FCEU_dwmemset(MMC5fill+0x3c0,t,0x40);
|
||||
}
|
||||
ATFill=V;
|
||||
break;
|
||||
case 0x5200: MMC5HackSPMode=V;break;
|
||||
case 0x5201: MMC5HackSPScroll=(V>>3)&0x1F;break;
|
||||
case 0x5202: MMC5HackSPPage=V&0x3F;break;
|
||||
case 0x5203: X6502_IRQEnd(FCEU_IQEXT);IRQScanline=V;break;
|
||||
case 0x5204: X6502_IRQEnd(FCEU_IQEXT);IRQEnable=V&0x80;break;
|
||||
case 0x5205: mul[0]=V;break;
|
||||
case 0x5206: mul[1]=V;break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(MMC5_ReadROMRAM)
|
||||
{
|
||||
if(MMC5MemIn[(A-0x6000)>>13])
|
||||
return Page[A>>11][A];
|
||||
else
|
||||
return X.DB;
|
||||
}
|
||||
|
||||
static DECLFW(MMC5_WriteROMRAM)
|
||||
{
|
||||
if(A>=0x8000)
|
||||
if(MMC5ROMWrProtect[(A-0x8000)>>13]) return;
|
||||
if(MMC5MemIn[(A-0x6000)>>13])
|
||||
if(((WRAMMaskEnable[0]&3)|((WRAMMaskEnable[1]&3)<<2)) == 6) Page[A>>11][A]=V;
|
||||
}
|
||||
|
||||
static DECLFW(MMC5_ExRAMWr)
|
||||
{
|
||||
if(MMC5HackCHRMode!=3)
|
||||
ExRAM[A&0x3ff]=V;
|
||||
}
|
||||
|
||||
static DECLFR(MMC5_ExRAMRd)
|
||||
{
|
||||
/* Not sure if this is correct, so I'll comment it out for now. */
|
||||
//if(MMC5HackCHRMode>=2)
|
||||
return ExRAM[A&0x3ff];
|
||||
//else
|
||||
// return(X.DB);
|
||||
}
|
||||
|
||||
static DECLFR(MMC5_read)
|
||||
{
|
||||
switch(A)
|
||||
{
|
||||
case 0x5204: X6502_IRQEnd(FCEU_IQEXT);
|
||||
{
|
||||
uint8 x;
|
||||
x=MMC5IRQR;
|
||||
if(!fceuindbg)
|
||||
MMC5IRQR&=0x40;
|
||||
return x;
|
||||
}
|
||||
case 0x5205: return (mul[0]*mul[1]);
|
||||
case 0x5206: return ((mul[0]*mul[1])>>8);
|
||||
}
|
||||
return(X.DB);
|
||||
}
|
||||
|
||||
void MMC5Synco(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
MMC5PRG();
|
||||
for(x=0;x<4;x++)
|
||||
{
|
||||
switch((NTAMirroring>>(x<<1))&3)
|
||||
{
|
||||
case 0:PPUNTARAM|=1<<x;vnapage[x]=NTARAM;break;
|
||||
case 1:PPUNTARAM|=1<<x;vnapage[x]=NTARAM+0x400;break;
|
||||
case 2:PPUNTARAM|=1<<x;vnapage[x]=ExRAM;break;
|
||||
case 3:PPUNTARAM&=~(1<<x);vnapage[x]=MMC5fill;break;
|
||||
}
|
||||
}
|
||||
MMC5WRAM(0x6000,WRAMPage&7);
|
||||
if(!ABMode)
|
||||
{
|
||||
MMC5CHRB();
|
||||
MMC5CHRA();
|
||||
}
|
||||
else
|
||||
{
|
||||
MMC5CHRA();
|
||||
MMC5CHRB();
|
||||
}
|
||||
{
|
||||
uint32 t;
|
||||
t=NTFill|(NTFill<<8)|(NTFill<<16)|(NTFill<<24);
|
||||
FCEU_dwmemset(MMC5fill,t,0x3c0);
|
||||
}
|
||||
{
|
||||
unsigned char moop;
|
||||
uint32 t;
|
||||
moop=ATFill|(ATFill<<2)|(ATFill<<4)|(ATFill<<6);
|
||||
t=moop|(moop<<8)|(moop<<16)|(moop<<24);
|
||||
FCEU_dwmemset(MMC5fill+0x3c0,t,0x40);
|
||||
}
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
MMC5HackCHRMode=CHRMode&3;
|
||||
}
|
||||
|
||||
void MMC5_hb(int scanline)
|
||||
{
|
||||
if(scanline==240)
|
||||
{
|
||||
MMC5LineCounter=0;
|
||||
MMC5IRQR=0x40;
|
||||
return;
|
||||
}
|
||||
if(MMC5LineCounter<240)
|
||||
{
|
||||
if(MMC5LineCounter==IRQScanline)
|
||||
{
|
||||
MMC5IRQR|=0x80;
|
||||
if(IRQEnable&0x80)
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
MMC5LineCounter++;
|
||||
}
|
||||
if(MMC5LineCounter==240)
|
||||
MMC5IRQR=0;
|
||||
}
|
||||
|
||||
void MMC5_StateRestore(int version)
|
||||
{
|
||||
MMC5Synco();
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint16 wl[2];
|
||||
uint8 env[2];
|
||||
uint8 enable;
|
||||
uint8 running;
|
||||
uint8 raw;
|
||||
uint8 rawcontrol;
|
||||
int32 dcount[2];
|
||||
int32 BC[3];
|
||||
int32 vcount[2];
|
||||
} MMC5APU;
|
||||
|
||||
static MMC5APU MMC5Sound;
|
||||
|
||||
|
||||
static void Do5PCM()
|
||||
{
|
||||
int32 V;
|
||||
int32 start,end;
|
||||
|
||||
start=MMC5Sound.BC[2];
|
||||
end=(SOUNDTS<<16)/soundtsinc;
|
||||
if(end<=start) return;
|
||||
MMC5Sound.BC[2]=end;
|
||||
|
||||
if(!(MMC5Sound.rawcontrol&0x40) && MMC5Sound.raw)
|
||||
for(V=start;V<end;V++)
|
||||
Wave[V>>4]+=MMC5Sound.raw<<1;
|
||||
}
|
||||
|
||||
static void Do5PCMHQ()
|
||||
{
|
||||
int32 V;
|
||||
if(!(MMC5Sound.rawcontrol&0x40) && MMC5Sound.raw)
|
||||
for(V=MMC5Sound.BC[2];V<SOUNDTS;V++)
|
||||
WaveHi[V]+=MMC5Sound.raw<<5;
|
||||
MMC5Sound.BC[2]=SOUNDTS;
|
||||
}
|
||||
|
||||
|
||||
static DECLFW(Mapper5_SW)
|
||||
{
|
||||
A&=0x1F;
|
||||
|
||||
GameExpSound.Fill=MMC5RunSound;
|
||||
GameExpSound.HiFill=MMC5RunSoundHQ;
|
||||
|
||||
switch(A)
|
||||
{
|
||||
case 0x10:if(psfun) psfun();MMC5Sound.rawcontrol=V;break;
|
||||
case 0x11:if(psfun) psfun();MMC5Sound.raw=V;break;
|
||||
|
||||
case 0x0:
|
||||
case 0x4://printf("%04x:$%02x\n",A,V&0x30);
|
||||
if(sfun) sfun(A>>2);
|
||||
MMC5Sound.env[A>>2]=V;
|
||||
break;
|
||||
case 0x2:
|
||||
case 0x6: if(sfun) sfun(A>>2);
|
||||
MMC5Sound.wl[A>>2]&=~0x00FF;
|
||||
MMC5Sound.wl[A>>2]|=V&0xFF;
|
||||
break;
|
||||
case 0x3:
|
||||
case 0x7://printf("%04x:$%02x\n",A,V>>3);
|
||||
MMC5Sound.wl[A>>2]&=~0x0700;
|
||||
MMC5Sound.wl[A>>2]|=(V&0x07)<<8;
|
||||
MMC5Sound.running|=1<<(A>>2);
|
||||
break;
|
||||
case 0x15:if(sfun)
|
||||
{
|
||||
sfun(0);
|
||||
sfun(1);
|
||||
}
|
||||
MMC5Sound.running&=V;
|
||||
MMC5Sound.enable=V;
|
||||
//printf("%02x\n",V);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Do5SQ(int P)
|
||||
{
|
||||
static int tal[4]={1,2,4,6};
|
||||
int32 V,amp,rthresh,wl;
|
||||
int32 start,end;
|
||||
|
||||
start=MMC5Sound.BC[P];
|
||||
end=(SOUNDTS<<16)/soundtsinc;
|
||||
if(end<=start) return;
|
||||
MMC5Sound.BC[P]=end;
|
||||
|
||||
wl=MMC5Sound.wl[P]+1;
|
||||
amp=(MMC5Sound.env[P]&0xF)<<4;
|
||||
rthresh=tal[(MMC5Sound.env[P]&0xC0)>>6];
|
||||
|
||||
if(wl>=8 && (MMC5Sound.running&(P+1)))
|
||||
{
|
||||
int dc,vc;
|
||||
|
||||
wl<<=18;
|
||||
dc=MMC5Sound.dcount[P];
|
||||
vc=MMC5Sound.vcount[P];
|
||||
|
||||
for(V=start;V<end;V++)
|
||||
{
|
||||
if(dc<rthresh)
|
||||
Wave[V>>4]+=amp;
|
||||
vc-=nesincsize;
|
||||
while(vc<=0)
|
||||
{
|
||||
vc+=wl;
|
||||
dc=(dc+1)&7;
|
||||
}
|
||||
}
|
||||
MMC5Sound.dcount[P]=dc;
|
||||
MMC5Sound.vcount[P]=vc;
|
||||
}
|
||||
}
|
||||
|
||||
static void Do5SQHQ(int P)
|
||||
{
|
||||
static int tal[4]={1,2,4,6};
|
||||
int32 V,amp,rthresh,wl;
|
||||
|
||||
wl=MMC5Sound.wl[P]+1;
|
||||
amp=((MMC5Sound.env[P]&0xF)<<8);
|
||||
rthresh=tal[(MMC5Sound.env[P]&0xC0)>>6];
|
||||
|
||||
if(wl>=8 && (MMC5Sound.running&(P+1)))
|
||||
{
|
||||
int dc,vc;
|
||||
|
||||
wl<<=1;
|
||||
|
||||
dc=MMC5Sound.dcount[P];
|
||||
vc=MMC5Sound.vcount[P];
|
||||
for(V=MMC5Sound.BC[P];V<SOUNDTS;V++)
|
||||
{
|
||||
if(dc<rthresh)
|
||||
WaveHi[V]+=amp;
|
||||
vc--;
|
||||
if(vc<=0) /* Less than zero when first started. */
|
||||
{
|
||||
vc=wl;
|
||||
dc=(dc+1)&7;
|
||||
}
|
||||
}
|
||||
MMC5Sound.dcount[P]=dc;
|
||||
MMC5Sound.vcount[P]=vc;
|
||||
}
|
||||
MMC5Sound.BC[P]=SOUNDTS;
|
||||
}
|
||||
|
||||
void MMC5RunSoundHQ(void)
|
||||
{
|
||||
Do5SQHQ(0);
|
||||
Do5SQHQ(1);
|
||||
Do5PCMHQ();
|
||||
}
|
||||
|
||||
void MMC5HiSync(int32 ts)
|
||||
{
|
||||
int x;
|
||||
for(x=0;x<3;x++) MMC5Sound.BC[x]=ts;
|
||||
}
|
||||
|
||||
void MMC5RunSound(int Count)
|
||||
{
|
||||
int x;
|
||||
Do5SQ(0);
|
||||
Do5SQ(1);
|
||||
Do5PCM();
|
||||
for(x=0;x<3;x++)
|
||||
MMC5Sound.BC[x]=Count;
|
||||
}
|
||||
|
||||
void Mapper5_ESI(void)
|
||||
{
|
||||
GameExpSound.RChange=Mapper5_ESI;
|
||||
if(FSettings.SndRate)
|
||||
{
|
||||
if(FSettings.soundq>=1)
|
||||
{
|
||||
sfun=Do5SQHQ;
|
||||
psfun=Do5PCMHQ;
|
||||
}
|
||||
else
|
||||
{
|
||||
sfun=Do5SQ;
|
||||
psfun=Do5PCM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sfun=0;
|
||||
psfun=0;
|
||||
}
|
||||
memset(MMC5Sound.BC,0,sizeof(MMC5Sound.BC));
|
||||
memset(MMC5Sound.vcount,0,sizeof(MMC5Sound.vcount));
|
||||
GameExpSound.HiSync=MMC5HiSync;
|
||||
}
|
||||
|
||||
void NSFMMC5_Init(void)
|
||||
{
|
||||
memset(&MMC5Sound,0,sizeof(MMC5Sound));
|
||||
mul[0]=mul[1]=0;
|
||||
ExRAM=(uint8*)FCEU_gmalloc(1024);
|
||||
Mapper5_ESI();
|
||||
SetWriteHandler(0x5c00,0x5fef,MMC5_ExRAMWr);
|
||||
SetReadHandler(0x5c00,0x5fef,MMC5_ExRAMRd);
|
||||
MMC5HackCHRMode=2;
|
||||
SetWriteHandler(0x5000,0x5015,Mapper5_SW);
|
||||
SetWriteHandler(0x5205,0x5206,Mapper5_write);
|
||||
SetReadHandler(0x5205,0x5206,MMC5_read);
|
||||
}
|
||||
|
||||
void NSFMMC5_Close(void)
|
||||
{
|
||||
FCEU_gfree(ExRAM);
|
||||
ExRAM=0;
|
||||
}
|
||||
|
||||
static void GenMMC5Reset(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=0;x<4;x++) PRGBanks[x]=~0;
|
||||
for(x=0;x<8;x++) CHRBanksA[x]=~0;
|
||||
for(x=0;x<4;x++) CHRBanksB[x]=~0;
|
||||
WRAMMaskEnable[0]=WRAMMaskEnable[1]=~0;
|
||||
|
||||
mmc5psize=mmc5vsize=3;
|
||||
CHRMode=0;
|
||||
|
||||
NTAMirroring=NTFill=ATFill=0xFF;
|
||||
|
||||
MMC5Synco();
|
||||
|
||||
SetWriteHandler(0x4020,0x5bff,Mapper5_write);
|
||||
SetReadHandler(0x4020,0x5bff,MMC5_read);
|
||||
|
||||
SetWriteHandler(0x5c00,0x5fff,MMC5_ExRAMWr);
|
||||
SetReadHandler(0x5c00,0x5fff,MMC5_ExRAMRd);
|
||||
|
||||
SetWriteHandler(0x6000,0xFFFF,MMC5_WriteROMRAM);
|
||||
SetReadHandler(0x6000,0xFFFF,MMC5_ReadROMRAM);
|
||||
|
||||
SetWriteHandler(0x5000,0x5015,Mapper5_SW);
|
||||
SetWriteHandler(0x5205,0x5206,Mapper5_write);
|
||||
SetReadHandler(0x5205,0x5206,MMC5_read);
|
||||
|
||||
//GameHBIRQHook=MMC5_hb;
|
||||
FCEU_CheatAddRAM(8,0x6000,WRAM);
|
||||
FCEU_CheatAddRAM(1,0x5c00,ExRAM);
|
||||
}
|
||||
|
||||
static SFORMAT MMC5_StateRegs[]={
|
||||
{ PRGBanks, 4, "PRGB"},
|
||||
{ CHRBanksA, 8, "CHRA"},
|
||||
{ CHRBanksB, 4, "CHRB"},
|
||||
{ &WRAMPage, 1, "WRMP"},
|
||||
{ WRAMMaskEnable, 2, "WRME"},
|
||||
{ &ABMode, 1, "ABMD"},
|
||||
{ &IRQScanline, 1, "IRQS"},
|
||||
{ &IRQEnable, 1, "IRQE"},
|
||||
{ &CHRMode, 1, "CHRM"},
|
||||
{ &NTAMirroring, 1, "NTAM"},
|
||||
{ &NTFill, 1, "NTFL"},
|
||||
{ &ATFill, 1, "ATFL"},
|
||||
|
||||
{ &MMC5Sound.wl[0], 2|FCEUSTATE_RLSB, "SDW0"},
|
||||
{ &MMC5Sound.wl[1], 2|FCEUSTATE_RLSB, "SDW1"},
|
||||
{ MMC5Sound.env, 2, "SDEV"},
|
||||
{ &MMC5Sound.enable, 1, "SDEN"},
|
||||
{ &MMC5Sound.running, 1, "SDRU"},
|
||||
{ &MMC5Sound.raw, 1, "SDRW"},
|
||||
{ &MMC5Sound.rawcontrol, 1, "SDRC"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void GenMMC5_Init(CartInfo *info, int wsize, int battery)
|
||||
{
|
||||
if(wsize)
|
||||
{
|
||||
WRAM=(uint8*)FCEU_gmalloc(wsize*1024);
|
||||
SetupCartPRGMapping(0x10,WRAM,wsize*1024,1);
|
||||
AddExState(WRAM, wsize*1024, 0, "WRAM");
|
||||
}
|
||||
|
||||
MMC5fill=(uint8*)FCEU_gmalloc(1024);
|
||||
ExRAM=(uint8*)FCEU_gmalloc(1024);
|
||||
|
||||
AddExState(MMC5_StateRegs, ~0, 0, 0);
|
||||
AddExState(WRAM, wsize*1024, 0, "WRAM");
|
||||
AddExState(ExRAM, 1024, 0, "ERAM");
|
||||
AddExState(&MMC5HackSPMode, 1, 0, "SPLM");
|
||||
AddExState(&MMC5HackSPScroll, 1, 0, "SPLS");
|
||||
AddExState(&MMC5HackSPPage, 1, 0, "SPLP");
|
||||
|
||||
MMC5WRAMsize=wsize/8;
|
||||
BuildWRAMSizeTable();
|
||||
GameStateRestore=MMC5_StateRestore;
|
||||
info->Power=GenMMC5Reset;
|
||||
|
||||
if(battery)
|
||||
{
|
||||
info->SaveGame[0]=WRAM;
|
||||
if(wsize<=16)
|
||||
info->SaveGameLen[0]=8192;
|
||||
else
|
||||
info->SaveGameLen[0]=32768;
|
||||
}
|
||||
|
||||
MMC5HackVROMMask=CHRmask4[0];
|
||||
MMC5HackExNTARAMPtr=ExRAM;
|
||||
MMC5Hack=1;
|
||||
MMC5HackVROMPTR=CHRptr[0];
|
||||
MMC5HackCHRMode=0;
|
||||
MMC5HackSPMode=MMC5HackSPScroll=MMC5HackSPPage=0;
|
||||
Mapper5_ESI();
|
||||
}
|
||||
|
||||
void Mapper5_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC5_Init(info, DetectMMC5WRAMSize(info->CRC32), info->battery);
|
||||
}
|
||||
|
||||
// ELROM seems to have 0KB of WRAM
|
||||
// EKROM seems to have 8KB of WRAM
|
||||
// ETROM seems to have 16KB of WRAM
|
||||
// EWROM seems to have 32KB of WRAM
|
||||
|
||||
// ETROM and EWROM are battery-backed, EKROM isn't.
|
||||
|
||||
void ETROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC5_Init(info, 16,info->battery);
|
||||
}
|
||||
|
||||
void ELROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC5_Init(info,0,0);
|
||||
}
|
||||
|
||||
void EWROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC5_Init(info,32,info->battery);
|
||||
}
|
||||
|
||||
void EKROM_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC5_Init(info,8,info->battery);
|
||||
}
|
|
@ -0,0 +1,469 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint16 IRQCount;
|
||||
static uint8 IRQa;
|
||||
|
||||
static uint8 WRAM[8192];
|
||||
static uint8 IRAM[128];
|
||||
|
||||
static DECLFR(AWRAM)
|
||||
{
|
||||
return(WRAM[A-0x6000]);
|
||||
}
|
||||
|
||||
static DECLFW(BWRAM)
|
||||
{
|
||||
WRAM[A-0x6000]=V;
|
||||
}
|
||||
|
||||
void Mapper19_ESI(void);
|
||||
|
||||
static uint8 NTAPage[4];
|
||||
|
||||
static uint8 dopol;
|
||||
static uint8 gorfus;
|
||||
static uint8 gorko;
|
||||
|
||||
static void NamcoSound(int Count);
|
||||
static void NamcoSoundHack(void);
|
||||
static void DoNamcoSound(int32 *Wave, int Count);
|
||||
static void DoNamcoSoundHQ(void);
|
||||
static void SyncHQ(int32 ts);
|
||||
|
||||
static int is210; /* Lesser mapper. */
|
||||
|
||||
static uint8 PRG[3];
|
||||
static uint8 CHR[8];
|
||||
|
||||
static SFORMAT N106_StateRegs[]={
|
||||
{PRG,3,"PRG"},
|
||||
{CHR,8,"CHR"},
|
||||
{NTAPage,4,"NTA"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void SyncPRG(void)
|
||||
{
|
||||
setprg8(0x8000,PRG[0]);
|
||||
setprg8(0xa000,PRG[1]);
|
||||
setprg8(0xc000,PRG[2]);
|
||||
setprg8(0xe000,0x3F);
|
||||
}
|
||||
|
||||
static void FP_FASTAPASS(1) NamcoIRQHook(int a)
|
||||
{
|
||||
if(IRQa)
|
||||
{
|
||||
IRQCount+=a;
|
||||
if(IRQCount>=0x7FFF)
|
||||
{
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
IRQa=0;
|
||||
IRQCount=0x7FFF; //7FFF;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(Namco_Read4800)
|
||||
{
|
||||
uint8 ret=IRAM[dopol&0x7f];
|
||||
/* Maybe I should call NamcoSoundHack() here? */
|
||||
if(!fceuindbg)
|
||||
if(dopol&0x80)
|
||||
dopol=(dopol&0x80)|((dopol+1)&0x7f);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static DECLFR(Namco_Read5000)
|
||||
{
|
||||
return(IRQCount);
|
||||
}
|
||||
|
||||
static DECLFR(Namco_Read5800)
|
||||
{
|
||||
return(IRQCount>>8);
|
||||
}
|
||||
|
||||
static void FASTAPASS(2) DoNTARAMROM(int w, uint8 V)
|
||||
{
|
||||
NTAPage[w]=V;
|
||||
if(V>=0xE0)
|
||||
setntamem(NTARAM+((V&1)<<10), 1, w);
|
||||
else
|
||||
{
|
||||
V&=CHRmask1[0];
|
||||
setntamem(CHRptr[0]+(V<<10), 0, w);
|
||||
}
|
||||
}
|
||||
|
||||
static void FixNTAR(void)
|
||||
{
|
||||
int x;
|
||||
for(x=0;x<4;x++)
|
||||
DoNTARAMROM(x,NTAPage[x]);
|
||||
}
|
||||
|
||||
static void FASTAPASS(2) DoCHRRAMROM(int x, uint8 V)
|
||||
{
|
||||
CHR[x]=V;
|
||||
if(!is210 && !((gorfus>>((x>>2)+6))&1) && (V>=0xE0))
|
||||
{
|
||||
// printf("BLAHAHA: %d, %02x\n",x,V);
|
||||
//setchr1r(0x10,x<<10,V&7);
|
||||
}
|
||||
else
|
||||
setchr1(x<<10,V);
|
||||
}
|
||||
|
||||
static void FixCRR(void)
|
||||
{
|
||||
int x;
|
||||
for(x=0;x<8;x++)
|
||||
DoCHRRAMROM(x,CHR[x]);
|
||||
}
|
||||
|
||||
static DECLFW(Mapper19C0D8_write)
|
||||
{
|
||||
DoNTARAMROM((A-0xC000)>>11,V);
|
||||
}
|
||||
|
||||
static uint32 FreqCache[8];
|
||||
static uint32 EnvCache[8];
|
||||
static uint32 LengthCache[8];
|
||||
|
||||
static void FixCache(int a,int V)
|
||||
{
|
||||
int w=(a>>3)&0x7;
|
||||
switch(a&0x07)
|
||||
{
|
||||
case 0x00:FreqCache[w]&=~0x000000FF;FreqCache[w]|=V;break;
|
||||
case 0x02:FreqCache[w]&=~0x0000FF00;FreqCache[w]|=V<<8;break;
|
||||
case 0x04:FreqCache[w]&=~0x00030000;FreqCache[w]|=(V&3)<<16;
|
||||
LengthCache[w]=(8-((V>>2)&7))<<2;
|
||||
break;
|
||||
case 0x07:EnvCache[w]=(double)(V&0xF)*576716;break;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(Mapper19_write)
|
||||
{
|
||||
A&=0xF800;
|
||||
if(A>=0x8000 && A<=0xb800)
|
||||
DoCHRRAMROM((A-0x8000)>>11,V);
|
||||
else switch(A)
|
||||
{
|
||||
case 0x4800:
|
||||
if(dopol&0x40)
|
||||
{
|
||||
if(FSettings.SndRate)
|
||||
{
|
||||
NamcoSoundHack();
|
||||
GameExpSound.Fill=NamcoSound;
|
||||
GameExpSound.HiFill=DoNamcoSoundHQ;
|
||||
GameExpSound.HiSync=SyncHQ;
|
||||
}
|
||||
FixCache(dopol,V);
|
||||
}
|
||||
IRAM[dopol&0x7f]=V;
|
||||
if(dopol&0x80)
|
||||
dopol=(dopol&0x80)|((dopol+1)&0x7f);
|
||||
break;
|
||||
case 0xf800:
|
||||
dopol=V;break;
|
||||
case 0x5000:
|
||||
IRQCount&=0xFF00;IRQCount|=V;X6502_IRQEnd(FCEU_IQEXT);break;
|
||||
case 0x5800:
|
||||
IRQCount&=0x00ff;IRQCount|=(V&0x7F)<<8;
|
||||
IRQa=V&0x80;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
break;
|
||||
case 0xE000:
|
||||
gorko=V&0xC0;
|
||||
PRG[0]=V&0x3F;
|
||||
SyncPRG();
|
||||
break;
|
||||
case 0xE800:
|
||||
gorfus=V&0xC0;
|
||||
FixCRR();
|
||||
PRG[1]=V&0x3F;
|
||||
SyncPRG();
|
||||
break;
|
||||
case 0xF000:
|
||||
PRG[2]=V&0x3F;
|
||||
SyncPRG();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int dwave=0;
|
||||
|
||||
static void NamcoSoundHack(void)
|
||||
{
|
||||
int32 z,a;
|
||||
if(FSettings.soundq>=1)
|
||||
{
|
||||
DoNamcoSoundHQ();
|
||||
return;
|
||||
}
|
||||
z=((SOUNDTS<<16)/soundtsinc)>>4;
|
||||
a=z-dwave;
|
||||
if(a) DoNamcoSound(&Wave[dwave], a);
|
||||
dwave+=a;
|
||||
}
|
||||
|
||||
static void NamcoSound(int Count)
|
||||
{
|
||||
int32 z,a;
|
||||
z=((SOUNDTS<<16)/soundtsinc)>>4;
|
||||
a=z-dwave;
|
||||
if(a) DoNamcoSound(&Wave[dwave], a);
|
||||
dwave=0;
|
||||
}
|
||||
|
||||
static uint32 PlayIndex[8];
|
||||
static int32 vcount[8];
|
||||
static int32 CVBC;
|
||||
|
||||
#define TOINDEX (16+1)
|
||||
|
||||
// 16:15
|
||||
static void SyncHQ(int32 ts)
|
||||
{
|
||||
CVBC=ts;
|
||||
}
|
||||
|
||||
|
||||
/* Things to do:
|
||||
1 Read freq low
|
||||
2 Read freq mid
|
||||
3 Read freq high
|
||||
4 Read envelope
|
||||
...?
|
||||
*/
|
||||
|
||||
static INLINE uint32 FetchDuff(uint32 P, uint32 envelope)
|
||||
{
|
||||
uint32 duff;
|
||||
duff=IRAM[((IRAM[0x46+(P<<3)]+(PlayIndex[P]>>TOINDEX))&0xFF)>>1];
|
||||
if((IRAM[0x46+(P<<3)]+(PlayIndex[P]>>TOINDEX))&1)
|
||||
duff>>=4;
|
||||
duff&=0xF;
|
||||
duff=(duff*envelope)>>16;
|
||||
return(duff);
|
||||
}
|
||||
|
||||
static void DoNamcoSoundHQ(void)
|
||||
{
|
||||
int32 P,V;
|
||||
int32 cyclesuck=(((IRAM[0x7F]>>4)&7)+1)*15;
|
||||
|
||||
for(P=7;P>=(7-((IRAM[0x7F]>>4)&7));P--)
|
||||
{
|
||||
if((IRAM[0x44+(P<<3)]&0xE0) && (IRAM[0x47+(P<<3)]&0xF))
|
||||
{
|
||||
uint32 freq;
|
||||
int32 vco;
|
||||
uint32 duff2,lengo,envelope;
|
||||
|
||||
vco=vcount[P];
|
||||
freq=FreqCache[P];
|
||||
envelope=EnvCache[P];
|
||||
lengo=LengthCache[P];
|
||||
|
||||
duff2=FetchDuff(P,envelope);
|
||||
for(V=CVBC<<1;V<SOUNDTS<<1;V++)
|
||||
{
|
||||
WaveHi[V>>1]+=duff2;
|
||||
if(!vco)
|
||||
{
|
||||
PlayIndex[P]+=freq;
|
||||
while((PlayIndex[P]>>TOINDEX)>=lengo) PlayIndex[P]-=lengo<<TOINDEX;
|
||||
duff2=FetchDuff(P,envelope);
|
||||
vco=cyclesuck;
|
||||
}
|
||||
vco--;
|
||||
}
|
||||
vcount[P]=vco;
|
||||
}
|
||||
}
|
||||
CVBC=SOUNDTS;
|
||||
}
|
||||
|
||||
|
||||
static void DoNamcoSound(int32 *Wave, int Count)
|
||||
{
|
||||
int P,V;
|
||||
for(P=7;P>=7-((IRAM[0x7F]>>4)&7);P--)
|
||||
{
|
||||
if((IRAM[0x44+(P<<3)]&0xE0) && (IRAM[0x47+(P<<3)]&0xF))
|
||||
{
|
||||
int32 inc;
|
||||
uint32 freq;
|
||||
int32 vco;
|
||||
uint32 duff,duff2,lengo,envelope;
|
||||
|
||||
vco=vcount[P];
|
||||
freq=FreqCache[P];
|
||||
envelope=EnvCache[P];
|
||||
lengo=LengthCache[P];
|
||||
|
||||
if(!freq) {/*printf("Ack");*/ continue;}
|
||||
|
||||
{
|
||||
int c=((IRAM[0x7F]>>4)&7)+1;
|
||||
inc=(long double)(FSettings.SndRate<<15)/((long double)freq*21477272/((long double)0x400000*c*45));
|
||||
}
|
||||
|
||||
duff=IRAM[(((IRAM[0x46+(P<<3)]+PlayIndex[P])&0xFF)>>1)];
|
||||
if((IRAM[0x46+(P<<3)]+PlayIndex[P])&1)
|
||||
duff>>=4;
|
||||
duff&=0xF;
|
||||
duff2=(duff*envelope)>>19;
|
||||
for(V=0;V<Count*16;V++)
|
||||
{
|
||||
if(vco>=inc)
|
||||
{
|
||||
PlayIndex[P]++;
|
||||
if(PlayIndex[P]>=lengo)
|
||||
PlayIndex[P]=0;
|
||||
vco-=inc;
|
||||
duff=IRAM[(((IRAM[0x46+(P<<3)]+PlayIndex[P])&0xFF)>>1)];
|
||||
if((IRAM[0x46+(P<<3)]+PlayIndex[P])&1)
|
||||
duff>>=4;
|
||||
duff&=0xF;
|
||||
duff2=(duff*envelope)>>19;
|
||||
}
|
||||
Wave[V>>4]+=duff2;
|
||||
vco+=0x8000;
|
||||
}
|
||||
vcount[P]=vco;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Mapper19_StateRestore(int version)
|
||||
{
|
||||
SyncPRG();
|
||||
FixNTAR();
|
||||
FixCRR();
|
||||
int x;
|
||||
for(x=0x40;x<0x80;x++)
|
||||
FixCache(x,IRAM[x]);
|
||||
}
|
||||
|
||||
static void M19SC(void)
|
||||
{
|
||||
if(FSettings.SndRate)
|
||||
Mapper19_ESI();
|
||||
}
|
||||
|
||||
void Mapper19_ESI(void)
|
||||
{
|
||||
GameExpSound.RChange=M19SC;
|
||||
memset(vcount,0,sizeof(vcount));
|
||||
memset(PlayIndex,0,sizeof(PlayIndex));
|
||||
CVBC=0;
|
||||
}
|
||||
|
||||
void NSFN106_Init(void)
|
||||
{
|
||||
SetWriteHandler(0xf800,0xffff,Mapper19_write);
|
||||
SetWriteHandler(0x4800,0x4fff,Mapper19_write);
|
||||
SetReadHandler(0x4800,0x4fff,Namco_Read4800);
|
||||
Mapper19_ESI();
|
||||
}
|
||||
|
||||
static int battery=0;
|
||||
|
||||
static void N106_Power(void)
|
||||
{
|
||||
int x;
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xffff,Mapper19_write);
|
||||
SetWriteHandler(0x4020,0x5fff,Mapper19_write);
|
||||
if(!is210)
|
||||
{
|
||||
SetWriteHandler(0xc000,0xdfff,Mapper19C0D8_write);
|
||||
SetReadHandler(0x4800,0x4fff,Namco_Read4800);
|
||||
SetReadHandler(0x5000,0x57ff,Namco_Read5000);
|
||||
SetReadHandler(0x5800,0x5fff,Namco_Read5800);
|
||||
NTAPage[0]=NTAPage[1]=NTAPage[2]=NTAPage[3]=0xFF;
|
||||
FixNTAR();
|
||||
}
|
||||
|
||||
SetReadHandler(0x6000,0x7FFF,AWRAM);
|
||||
SetWriteHandler(0x6000,0x7FFF,BWRAM);
|
||||
FCEU_CheatAddRAM(8,0x6000,WRAM);
|
||||
|
||||
gorfus=0xFF;
|
||||
SyncPRG();
|
||||
FixCRR();
|
||||
|
||||
if(!battery)
|
||||
{
|
||||
FCEU_dwmemset(WRAM,0,8192);
|
||||
FCEU_dwmemset(IRAM,0,128);
|
||||
}
|
||||
for(x=0x40;x<0x80;x++)
|
||||
FixCache(x,IRAM[x]);
|
||||
}
|
||||
|
||||
void Mapper19_Init(CartInfo *info)
|
||||
{
|
||||
is210=0;
|
||||
battery=info->battery;
|
||||
info->Power=N106_Power;
|
||||
|
||||
MapIRQHook=NamcoIRQHook;
|
||||
GameStateRestore=Mapper19_StateRestore;
|
||||
GameExpSound.RChange=M19SC;
|
||||
|
||||
if(FSettings.SndRate)
|
||||
Mapper19_ESI();
|
||||
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
AddExState(IRAM, 128, 0, "WRAM");
|
||||
AddExState(N106_StateRegs, ~0, 0, 0);
|
||||
|
||||
if(info->battery)
|
||||
{
|
||||
info->SaveGame[0]=WRAM;
|
||||
info->SaveGameLen[0]=8192;
|
||||
info->SaveGame[1]=IRAM;
|
||||
info->SaveGameLen[1]=128;
|
||||
}
|
||||
}
|
||||
|
||||
static void Mapper210_StateRestore(int version)
|
||||
{
|
||||
SyncPRG();
|
||||
FixCRR();
|
||||
}
|
||||
|
||||
void Mapper210_Init(CartInfo *info)
|
||||
{
|
||||
is210=1;
|
||||
GameStateRestore=Mapper210_StateRestore;
|
||||
info->Power=N106_Power;
|
||||
AddExState(WRAM, 8192, 0, "WRAM");
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 latch;
|
||||
|
||||
static void DoNovel(void)
|
||||
{
|
||||
setprg32(0x8000,latch&3);
|
||||
setchr8(latch&7);
|
||||
}
|
||||
|
||||
static DECLFW(NovelWrite)
|
||||
{
|
||||
latch=A&0xFF;
|
||||
DoNovel();
|
||||
}
|
||||
|
||||
static void NovelReset(void)
|
||||
{
|
||||
SetWriteHandler(0x8000,0xFFFF,NovelWrite);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
setprg32(0x8000,0);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static void NovelRestore(int version)
|
||||
{
|
||||
DoNovel();
|
||||
}
|
||||
|
||||
void Novel_Init(CartInfo *info)
|
||||
{
|
||||
AddExState(&latch, 1, 0,"L1");
|
||||
info->Power=NovelReset;
|
||||
GameStateRestore=NovelRestore;
|
||||
}
|
|
@ -0,0 +1,398 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 cmd;
|
||||
static uint8 latch[8];
|
||||
|
||||
static void S74LS374MSync(uint8 mirr)
|
||||
{
|
||||
switch(mirr&3)
|
||||
{
|
||||
case 0:setmirror(MI_V);break;
|
||||
case 1:setmirror(MI_H);break;
|
||||
case 2:setmirrorw(0,1,1,1);break;
|
||||
case 3:setmirror(MI_0);break;
|
||||
}
|
||||
}
|
||||
|
||||
static void S74LS374NSynco(void)
|
||||
{
|
||||
setprg32(0x8000,latch[0]);
|
||||
setchr8(latch[1]|latch[3]|latch[4]);
|
||||
S74LS374MSync(latch[2]);
|
||||
}
|
||||
|
||||
static DECLFW(S74LS374NWrite)
|
||||
{
|
||||
A&=0x4101;
|
||||
if(A==0x4100)
|
||||
cmd=V&7;
|
||||
else
|
||||
{
|
||||
switch(cmd)
|
||||
{
|
||||
case 2:latch[0]=V&1; latch[3]=(V&1)<<3;break;
|
||||
case 4:latch[4]=(V&1)<<2;break;
|
||||
case 5:latch[0]=V&7;break;
|
||||
case 6:latch[1]=V&3;break;
|
||||
case 7:latch[2]=V>>1;break;
|
||||
}
|
||||
S74LS374NSynco();
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(S74LS374NRead)
|
||||
{
|
||||
uint8 ret;
|
||||
if((A&0x4100)==0x4100)
|
||||
ret=(X.DB&0xC0)|((~cmd)&0x3F);
|
||||
else
|
||||
ret=X.DB;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void S74LS374NPower(void)
|
||||
{
|
||||
latch[0]=latch[1]=latch[2]=latch[3]=latch[4]=0;
|
||||
S74LS374NSynco();
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x4100,0x7FFF,S74LS374NWrite);
|
||||
SetReadHandler(0x4100,0x5fff,S74LS374NRead);
|
||||
}
|
||||
|
||||
static void S74LS374NRestore(int version)
|
||||
{
|
||||
S74LS374NSynco();
|
||||
}
|
||||
|
||||
void S74LS374N_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=S74LS374NPower;
|
||||
GameStateRestore=S74LS374NRestore;
|
||||
AddExState(latch, 5, 0, "LATC");
|
||||
AddExState(&cmd, 1, 0, "CMD");
|
||||
}
|
||||
|
||||
static void S74LS374NASynco(void)
|
||||
{
|
||||
setprg32(0x8000,latch[0]);
|
||||
setchr8(latch[1]);
|
||||
S74LS374MSync(latch[2]);
|
||||
}
|
||||
|
||||
static DECLFW(S74LS374NAWrite)
|
||||
{
|
||||
A&=0x4101;
|
||||
if(A==0x4100)
|
||||
cmd=V&7;
|
||||
else
|
||||
{
|
||||
switch(cmd)
|
||||
{
|
||||
case 0:latch[0]=0;latch[1]=3;break;
|
||||
case 2:latch[3]=(V&1)<<3;break;
|
||||
case 4:latch[1]=(latch[1]&6)|(V&3);break;
|
||||
case 5:latch[0]=V&1;break;
|
||||
case 6:latch[1]=(latch[1]&1)|latch[3]|((V&3)<<1);break;
|
||||
case 7:latch[2]=V&1;break;
|
||||
}
|
||||
S74LS374NASynco();
|
||||
}
|
||||
}
|
||||
|
||||
static void S74LS374NAPower(void)
|
||||
{
|
||||
latch[0]=latch[2]=latch[3]=latch[4]=0;
|
||||
latch[1]=3;
|
||||
S74LS374NASynco();
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x4100,0x7FFF,S74LS374NAWrite);
|
||||
}
|
||||
|
||||
void S74LS374NA_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=S74LS374NAPower;
|
||||
GameStateRestore=S74LS374NRestore;
|
||||
AddExState(latch, 5, 0, "LATC");
|
||||
AddExState(&cmd, 1, 0, "CMD");
|
||||
}
|
||||
|
||||
static int type;
|
||||
static void S8259Synco(void)
|
||||
{
|
||||
int x;
|
||||
setprg32(0x8000,latch[5]&7);
|
||||
|
||||
if(!UNIFchrrama) // No CHR RAM? Then BS'ing is ok.
|
||||
{
|
||||
for(x=0;x<4;x++)
|
||||
{
|
||||
int bank;
|
||||
if(latch[7]&1)
|
||||
bank=(latch[0]&0x7)|((latch[4]&7)<<3);
|
||||
else
|
||||
bank=(latch[x]&0x7)|((latch[4]&7)<<3);
|
||||
switch (type)
|
||||
{
|
||||
case 00: bank=(bank<<1)|(x&1); setchr2(0x800*x,bank); break;
|
||||
case 01: setchr2(0x800*x,bank); break;
|
||||
case 02: bank=(bank<<2)|(x&3); setchr2(0x800*x,bank); break;
|
||||
case 03: bank=latch[x]&7;
|
||||
switch (x&3)
|
||||
{
|
||||
case 01: bank|=(latch[4]&1)<<4;break;
|
||||
case 02: bank|=(latch[4]&2)<<3;break;
|
||||
case 03: bank|=((latch[4]&4)<<2)|((latch[6]&1)<<3);break;
|
||||
}
|
||||
setchr1(0x400*x,bank);
|
||||
setchr4(0x1000,~0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!(latch[7]&1))
|
||||
S74LS374MSync(latch[7]>>1);
|
||||
else
|
||||
setmirror(MI_V);
|
||||
}
|
||||
|
||||
static DECLFW(S8259Write)
|
||||
{
|
||||
A&=0x4101;
|
||||
if(A==0x4100)
|
||||
cmd=V;
|
||||
else
|
||||
{
|
||||
latch[cmd&7]=V;
|
||||
S8259Synco();
|
||||
}
|
||||
}
|
||||
|
||||
static void S8259Reset(void)
|
||||
{
|
||||
int x;
|
||||
cmd=0;
|
||||
|
||||
for(x=0;x<8;x++) latch[x]=0;
|
||||
setchr8(0);
|
||||
|
||||
S8259Synco();
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x4100,0x7FFF,S8259Write);
|
||||
}
|
||||
|
||||
static void S8259Restore(int version)
|
||||
{
|
||||
S8259Synco();
|
||||
}
|
||||
|
||||
void S8259A_Init(CartInfo *info) // Kevin's Horton 141 mapper
|
||||
{
|
||||
info->Power=S8259Reset;
|
||||
GameStateRestore=S8259Restore;
|
||||
AddExState(latch, 8, 0, "LATC");
|
||||
AddExState(&cmd, 1, 0, "CMD");
|
||||
type=0;
|
||||
}
|
||||
|
||||
void S8259B_Init(CartInfo *info) // Kevin's Horton 138 mapper
|
||||
{
|
||||
info->Power=S8259Reset;
|
||||
GameStateRestore=S8259Restore;
|
||||
AddExState(latch, 8, 0, "LATC");
|
||||
AddExState(&cmd, 1, 0, "CMD");
|
||||
type=1;
|
||||
}
|
||||
|
||||
void S8259C_Init(CartInfo *info) // Kevin's Horton 139 mapper
|
||||
{
|
||||
info->Power=S8259Reset;
|
||||
GameStateRestore=S8259Restore;
|
||||
AddExState(latch, 8, 0, "LATC");
|
||||
AddExState(&cmd, 1, 0, "CMD");
|
||||
type=2;
|
||||
}
|
||||
|
||||
void S8259D_Init(CartInfo *info) // Kevin's Horton 137 mapper
|
||||
{
|
||||
info->Power=S8259Reset;
|
||||
GameStateRestore=S8259Restore;
|
||||
AddExState(latch, 8, 0, "LATC");
|
||||
AddExState(&cmd, 1, 0, "CMD");
|
||||
type=3;
|
||||
}
|
||||
|
||||
static void(*WSync)(void);
|
||||
|
||||
static DECLFW(SAWrite)
|
||||
{
|
||||
if(A&0x100)
|
||||
{
|
||||
latch[0]=V;
|
||||
WSync();
|
||||
}
|
||||
}
|
||||
|
||||
static void SAPower(void)
|
||||
{
|
||||
latch[0]=0;
|
||||
WSync();
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x4100,0x5FFF,SAWrite);
|
||||
}
|
||||
|
||||
static void SARestore(int version)
|
||||
{
|
||||
WSync();
|
||||
}
|
||||
|
||||
static DECLFW(SADWrite)
|
||||
{
|
||||
latch[0]=V;
|
||||
WSync();
|
||||
}
|
||||
|
||||
static void SADPower(void)
|
||||
{
|
||||
latch[0]=0;
|
||||
WSync();
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xFFFF,SADWrite);
|
||||
}
|
||||
|
||||
static void SA0161MSynco()
|
||||
{
|
||||
setprg32(0x8000,(latch[0]>>3)&1);
|
||||
setchr8(latch[0]&7);
|
||||
}
|
||||
|
||||
static void SA72007Synco()
|
||||
{
|
||||
setprg32(0x8000,0);
|
||||
setchr8(latch[0]>>7);
|
||||
}
|
||||
|
||||
static void SA72008Synco()
|
||||
{
|
||||
setprg32(0x8000,(latch[0]>>2)&1);
|
||||
setchr8(latch[0]&3);
|
||||
}
|
||||
|
||||
void SA0161M_Init(CartInfo *info)
|
||||
{
|
||||
WSync=SA0161MSynco;
|
||||
GameStateRestore=SARestore;
|
||||
info->Power=SAPower;
|
||||
AddExState(&latch[0], 1, 0, "LATC");
|
||||
}
|
||||
|
||||
void SA72007_Init(CartInfo *info)
|
||||
{
|
||||
WSync=SA72007Synco;
|
||||
GameStateRestore=SARestore;
|
||||
info->Power=SAPower;
|
||||
AddExState(&latch[0], 1, 0, "LATC");
|
||||
}
|
||||
|
||||
void SA72008_Init(CartInfo *info)
|
||||
{
|
||||
WSync=SA72008Synco;
|
||||
GameStateRestore=SARestore;
|
||||
info->Power=SAPower;
|
||||
AddExState(&latch[0], 1, 0, "LATC");
|
||||
}
|
||||
|
||||
void SA0036_Init(CartInfo *info)
|
||||
{
|
||||
WSync=SA72007Synco;
|
||||
GameStateRestore=SARestore;
|
||||
info->Power=SADPower;
|
||||
AddExState(&latch[0], 1, 0, "LATC");
|
||||
}
|
||||
|
||||
void SA0037_Init(CartInfo *info)
|
||||
{
|
||||
WSync=SA0161MSynco;
|
||||
GameStateRestore=SARestore;
|
||||
info->Power=SADPower;
|
||||
AddExState(&latch[0], 1, 0, "LATC");
|
||||
}
|
||||
|
||||
static void TCU01Synco()
|
||||
{
|
||||
setprg32(0x8000,(latch[0]>>2)&1);
|
||||
setchr8((latch[0]>>3)&0xF);
|
||||
}
|
||||
|
||||
static DECLFW(TCWrite)
|
||||
{
|
||||
if((A&0x103)==0x102)
|
||||
{
|
||||
latch[0]=V;
|
||||
TCU01Synco();
|
||||
}
|
||||
}
|
||||
|
||||
static void TCU01Reset(void)
|
||||
{
|
||||
latch[0]=0;
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x4100,0xFFFF,TCWrite);
|
||||
TCU01Synco();
|
||||
}
|
||||
|
||||
static void TCU01Restore(int version)
|
||||
{
|
||||
TCU01Synco();
|
||||
}
|
||||
|
||||
void TCU01_Init(CartInfo *info)
|
||||
{
|
||||
GameStateRestore=TCU01Restore;
|
||||
info->Power=TCU01Reset;
|
||||
AddExState(&latch[0], 1, 0, "LATC");
|
||||
}
|
||||
|
||||
static DECLFR(TCA01Read)
|
||||
{
|
||||
uint8 ret;
|
||||
if((A&0x4100)==0x4100)
|
||||
ret=(X.DB&0xC0)|((~A)&0x3F);
|
||||
else
|
||||
ret=X.DB;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void TCA01Reset(void)
|
||||
{
|
||||
setprg16(0x8000,0);
|
||||
setprg16(0xC000,1);
|
||||
setchr8(0);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetReadHandler(0x4100,0x5FFF,TCA01Read);
|
||||
}
|
||||
|
||||
void TCA01_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=TCA01Reset;
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2006 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 *CHRRAM;
|
||||
static uint8 tekker;
|
||||
|
||||
static void MSHCW(uint32 A, uint8 V)
|
||||
{
|
||||
if(EXPREGS[0]&0x40)
|
||||
setchr8r(0x10,0);
|
||||
else
|
||||
{
|
||||
if(A<0x800)
|
||||
setchr1(A,V|((EXPREGS[0]&8)<<5));
|
||||
else if(A<0x1000)
|
||||
setchr1(A,V|((EXPREGS[0]&4)<<6));
|
||||
else if(A<0x1800)
|
||||
setchr1(A,V|((EXPREGS[0]&1)<<8));
|
||||
else
|
||||
setchr1(A,V|((EXPREGS[0]&2)<<7));
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(MSHWrite)
|
||||
{
|
||||
EXPREGS[0]=V;
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
}
|
||||
|
||||
static DECLFR(MSHRead)
|
||||
{
|
||||
return(tekker);
|
||||
}
|
||||
|
||||
static void MSHReset(void)
|
||||
{
|
||||
MMC3RegReset();
|
||||
tekker^=0xFF;
|
||||
}
|
||||
|
||||
static void MSHPower(void)
|
||||
{
|
||||
tekker=0x00;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x4100,0x4100,MSHWrite);
|
||||
SetReadHandler(0x4100,0x4100,MSHRead);
|
||||
}
|
||||
|
||||
static void MSHClose(void)
|
||||
{
|
||||
if(CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM=NULL;
|
||||
}
|
||||
|
||||
void UNLSHeroes_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC3_Init(info, 256, 512, 0, 0);
|
||||
cwrap=MSHCW;
|
||||
info->Power=MSHPower;
|
||||
info->Reset=MSHReset;
|
||||
info->Close=MSHClose;
|
||||
CHRRAM = (uint8*)FCEU_gmalloc(8192);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, 8192, 1);
|
||||
AddExState(EXPREGS, 4, 0, "EXPR");
|
||||
}
|
|
@ -0,0 +1,159 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 chrcmd[8], prg0, prg1, brk, mirr;
|
||||
static uint8 reg[8], cmd;
|
||||
static uint8 IRQCount,IRQLatch,IRQa;
|
||||
static uint8 IRQReload;
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{reg, 8, "MMCREG"},
|
||||
{&cmd, 1, "MMCCMD"},
|
||||
{chrcmd, 8, "CHRCMD"},
|
||||
{&prg0, 1, "PRG0"},
|
||||
{&prg1, 1, "PRG1"},
|
||||
{&brk, 1, "BRK"},
|
||||
{&mirr, 1, "MIRR"},
|
||||
{&IRQReload, 1, "IRQR"},
|
||||
{&IRQCount, 1, "IRQC"},
|
||||
{&IRQLatch, 1, "IRQL"},
|
||||
{&IRQa, 1, "IRQA"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
// if(brk&2)
|
||||
// {
|
||||
// setprg16(0x8000,~0);
|
||||
// setprg16(0xC000,~0);
|
||||
// }
|
||||
// else
|
||||
{
|
||||
setprg8(0x8000,prg0);
|
||||
setprg8(0xA000,prg1);
|
||||
}
|
||||
int i;
|
||||
for(i=0; i<8; i++)
|
||||
setchr1(i<<10,chrcmd[i]);
|
||||
setmirror(mirr^1);
|
||||
}
|
||||
|
||||
static void Sync2(void)
|
||||
{
|
||||
setprg8(0x8000,reg[6]&0x3F);
|
||||
setprg8(0xA000,reg[7]&0x3F);
|
||||
setchr2(0x0000,reg[0]>>1);
|
||||
setchr2(0x8000,reg[1]>>1);
|
||||
setchr1(0x1000,reg[2]);
|
||||
setchr1(0x1400,reg[3]);
|
||||
setchr1(0x1800,reg[4]);
|
||||
setchr1(0x1C00,reg[5]);
|
||||
setmirror(mirr^1);
|
||||
}
|
||||
|
||||
static DECLFW(UNLSL1632CMDWrite)
|
||||
{
|
||||
FCEU_printf("bs %04x %02x\n",A,V);
|
||||
// if((A&0xA131)==0xA131) brk=V;
|
||||
if((A&0xA131)==0xA131) brk=V;
|
||||
if(brk==2)
|
||||
{
|
||||
switch(A&0xE001)
|
||||
{
|
||||
case 0x8000: cmd=V&7; break;
|
||||
case 0x8001: reg[cmd]=V; Sync(); break;
|
||||
case 0xA000: mirr=V&1; break;
|
||||
case 0xC000: IRQLatch=V; break;
|
||||
case 0xC001: IRQReload=1; break;
|
||||
case 0xE000: X6502_IRQEnd(FCEU_IQEXT); IRQa=0; break;
|
||||
case 0xE001: IRQa=1; break;
|
||||
}
|
||||
Sync2();
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(A&0xF003)
|
||||
{
|
||||
case 0x8000: prg0=V; break;
|
||||
case 0xA000: prg1=V; break;
|
||||
case 0x9000: mirr=V&1; break;
|
||||
case 0xB000: chrcmd[0]=(chrcmd[0]&0xF0)|(V&0x0F); break;
|
||||
case 0xB001: chrcmd[0]=(chrcmd[0]&0x0F)|(V<<4); break;
|
||||
case 0xB002: chrcmd[1]=(chrcmd[1]&0xF0)|(V&0x0F); break;
|
||||
case 0xB003: chrcmd[1]=(chrcmd[1]&0x0F)|(V<<4); break;
|
||||
case 0xC000: chrcmd[2]=(chrcmd[2]&0xF0)|(V&0x0F); break;
|
||||
case 0xC001: chrcmd[2]=(chrcmd[2]&0x0F)|(V<<4); break;
|
||||
case 0xC002: chrcmd[3]=(chrcmd[3]&0xF0)|(V&0x0F); break;
|
||||
case 0xC003: chrcmd[3]=(chrcmd[3]&0x0F)|(V<<4); break;
|
||||
case 0xD000: chrcmd[4]=(chrcmd[4]&0xF0)|(V&0x0F); break;
|
||||
case 0xD001: chrcmd[4]=(chrcmd[4]&0x0F)|(V<<4); break;
|
||||
case 0xD002: chrcmd[5]=(chrcmd[5]&0xF0)|(V&0x0F); break;
|
||||
case 0xD003: chrcmd[5]=(chrcmd[5]&0x0F)|(V<<4); break;
|
||||
case 0xE000: chrcmd[6]=(chrcmd[6]&0xF0)|(V&0x0F); break;
|
||||
case 0xE001: chrcmd[6]=(chrcmd[6]&0x0F)|(V<<4); break;
|
||||
case 0xE002: chrcmd[7]=(chrcmd[7]&0xF0)|(V&0x0F); break;
|
||||
case 0xE003: chrcmd[7]=(chrcmd[7]&0x0F)|(V<<4); break;
|
||||
}
|
||||
Sync();
|
||||
}
|
||||
}
|
||||
|
||||
static void UNLSL1632IRQHook(void)
|
||||
{
|
||||
int count = IRQCount;
|
||||
if((scanline==128)&&IRQa)X6502_IRQBegin(FCEU_IQEXT);
|
||||
if(!count || IRQReload)
|
||||
{
|
||||
IRQCount = IRQLatch;
|
||||
IRQReload = 0;
|
||||
}
|
||||
else
|
||||
IRQCount--;
|
||||
if(!IRQCount)
|
||||
{
|
||||
if(IRQa)
|
||||
{
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void UNLSL1632Power(void)
|
||||
{
|
||||
setprg16(0xC000,~0);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
SetWriteHandler(0x8000,0xFFFF,UNLSL1632CMDWrite);
|
||||
}
|
||||
|
||||
void UNLSL1632_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=UNLSL1632Power;
|
||||
GameHBIRQHook2=UNLSL1632IRQHook;
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 m_perm[8] = {0, 1, 0, 3, 0, 5, 6, 7};
|
||||
|
||||
static void UNLSonicPW(uint32 A, uint8 V)
|
||||
{
|
||||
if(EXPREGS[0]&0x80)
|
||||
{
|
||||
uint8 bank=EXPREGS[0]&0x1F;
|
||||
if(EXPREGS[0]&0x20)
|
||||
setprg32(0x8000,bank>>2);
|
||||
else
|
||||
{
|
||||
setprg16(0x8000,bank);
|
||||
setprg16(0xC000,bank);
|
||||
}
|
||||
}
|
||||
else
|
||||
setprg8(A,V&0x3F);
|
||||
}
|
||||
|
||||
static DECLFW(UNLSonicWrite8000)
|
||||
{
|
||||
if(V&0x80)
|
||||
MMC3_CMDWrite(A,V);
|
||||
else
|
||||
MMC3_CMDWrite(A,m_perm[V&7]);
|
||||
}
|
||||
|
||||
static DECLFW(UNLSonicWriteLo)
|
||||
{
|
||||
EXPREGS[0]=V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
}
|
||||
|
||||
static void UNLSonicPower(void)
|
||||
{
|
||||
EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x5000,0x5FFF,UNLSonicWriteLo);
|
||||
// SetWriteHandler(0x8000,0x8000,UNLSonicWrite8000);
|
||||
}
|
||||
|
||||
void UNLSonic_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC3_Init(info, 256, 256, 0, 0);
|
||||
pwrap=UNLSonicPW;
|
||||
info->Power=UNLSonicPower;
|
||||
AddExState(EXPREGS, 3, 0, "EXPR");
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
#include "mapinc.h"
|
||||
|
||||
static uint8 mode;
|
||||
static uint8 DRegs[4];
|
||||
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{DRegs, 4, "DREG"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
int base, bank;
|
||||
base = ((DRegs[0]^DRegs[1])&0x10)<<1;
|
||||
bank = (DRegs[2]^DRegs[3])&0x1f;
|
||||
|
||||
if(DRegs[1]&0x08)
|
||||
{
|
||||
bank &= 0xfe;
|
||||
if(mode==0)
|
||||
{
|
||||
setprg16(0x8000,base+bank+1);
|
||||
setprg16(0xC000,base+bank+0);
|
||||
}
|
||||
else
|
||||
{
|
||||
setprg16(0x8000,base+bank+0);
|
||||
setprg16(0xC000,base+bank+1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(DRegs[1]&0x04)
|
||||
{
|
||||
setprg16(0x8000,0x1f);
|
||||
setprg16(0xC000,base+bank);
|
||||
}
|
||||
else
|
||||
{
|
||||
setprg16(0x8000,base+bank);
|
||||
if(mode==0)
|
||||
setprg16(0xC000,0x20);
|
||||
else
|
||||
setprg16(0xC000,0x07);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(Mapper167_write)
|
||||
{
|
||||
DRegs[(A>>13)&0x03]=V;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void StateRestore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void Mapper166_init(void)
|
||||
{
|
||||
mode=1;
|
||||
DRegs[0]=DRegs[1]=DRegs[2]=DRegs[3]=0;
|
||||
Sync();
|
||||
SetWriteHandler(0x8000,0xFFFF,Mapper167_write);
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
void Mapper167_init(void)
|
||||
{
|
||||
mode=0;
|
||||
DRegs[0]=DRegs[1]=DRegs[2]=DRegs[3]=0;
|
||||
Sync();
|
||||
SetWriteHandler(0x8000,0xFFFF,Mapper167_write);
|
||||
GameStateRestore=StateRestore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
#include "mmc3.h"
|
||||
|
||||
static uint8 *CHRRAM = NULL;
|
||||
static int masko8[8]={63,31,15,1,3,0,0,0};
|
||||
|
||||
static void Super24PW(uint32 A, uint8 V)
|
||||
{
|
||||
uint32 NV=V&masko8[EXPREGS[0]&7];
|
||||
NV|=(EXPREGS[1]<<1);
|
||||
setprg8r((NV>>6)&0xF,A,NV);
|
||||
}
|
||||
|
||||
static void Super24CW(uint32 A, uint8 V)
|
||||
{
|
||||
if(EXPREGS[0]&0x20)
|
||||
setchr1r(0x10,A,V);
|
||||
else
|
||||
{
|
||||
uint32 NV=V|(EXPREGS[2]<<3);
|
||||
setchr1r((NV>>9)&0xF,A,NV);
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(Super24Write)
|
||||
{
|
||||
switch(A)
|
||||
{
|
||||
case 0x5FF0: EXPREGS[0]=V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
break;
|
||||
case 0x5FF1: EXPREGS[1]=V;
|
||||
FixMMC3PRG(MMC3_cmd);
|
||||
break;
|
||||
case 0x5FF2: EXPREGS[2]=V;
|
||||
FixMMC3CHR(MMC3_cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Super24Power(void)
|
||||
{
|
||||
EXPREGS[0]=0x24;
|
||||
EXPREGS[1]=159;
|
||||
EXPREGS[2]=0;
|
||||
GenMMC3Power();
|
||||
SetWriteHandler(0x5000,0x7FFF,Super24Write);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
}
|
||||
|
||||
static void Super24Reset(void)
|
||||
{
|
||||
EXPREGS[0]=0x24;
|
||||
EXPREGS[1]=159;
|
||||
EXPREGS[2]=0;
|
||||
MMC3RegReset();
|
||||
}
|
||||
|
||||
static void Super24Close(void)
|
||||
{
|
||||
if(CHRRAM)
|
||||
FCEU_gfree(CHRRAM);
|
||||
CHRRAM = NULL;
|
||||
}
|
||||
|
||||
void Super24_Init(CartInfo *info)
|
||||
{
|
||||
GenMMC3_Init(info, 128, 256, 0, 0);
|
||||
info->Power=Super24Power;
|
||||
info->Reset=Super24Reset;
|
||||
info->Close=Super24Close;
|
||||
cwrap=Super24CW;
|
||||
pwrap=Super24PW;
|
||||
CHRRAM=(uint8*)FCEU_gmalloc(8192);
|
||||
SetupCartCHRMapping(0x10, CHRRAM, 8192, 1);
|
||||
AddExState(CHRRAM, 8192, 0, "CHRR");
|
||||
AddExState(EXPREGS, 3, 0, "BIG2");
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 cmd0, cmd1;
|
||||
|
||||
static void DoSuper(void)
|
||||
{
|
||||
setprg8r((cmd0&0xC)>>2,0x6000,((cmd0&0x3)<<4)|0xF);
|
||||
if(cmd0&0x10)
|
||||
{
|
||||
setprg16r((cmd0&0xC)>>2,0x8000,((cmd0&0x3)<<3)|(cmd1&7));
|
||||
setprg16r((cmd0&0xC)>>2,0xc000,((cmd0&0x3)<<3)|7);
|
||||
}
|
||||
else
|
||||
setprg32r(4,0x8000,0);
|
||||
setmirror(((cmd0&0x20)>>5)^1);
|
||||
}
|
||||
|
||||
static DECLFW(SuperWrite)
|
||||
{
|
||||
if(!(cmd0&0x10))
|
||||
{
|
||||
cmd0=V;
|
||||
DoSuper();
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFW(SuperHi)
|
||||
{
|
||||
cmd1=V;
|
||||
DoSuper();
|
||||
}
|
||||
|
||||
static void SuperReset(void)
|
||||
{
|
||||
SetWriteHandler(0x6000,0x7FFF,SuperWrite);
|
||||
SetWriteHandler(0x8000,0xFFFF,SuperHi);
|
||||
SetReadHandler(0x6000,0xFFFF,CartBR);
|
||||
cmd0=cmd1=0;
|
||||
setprg32r(4,0x8000,0);
|
||||
setchr8(0);
|
||||
}
|
||||
|
||||
static void SuperRestore(int version)
|
||||
{
|
||||
DoSuper();
|
||||
}
|
||||
|
||||
void Supervision16_Init(CartInfo *info)
|
||||
{
|
||||
AddExState(&cmd0, 1, 0,"L1");
|
||||
AddExState(&cmd1, 1, 0,"L2");
|
||||
info->Power=SuperReset;
|
||||
GameStateRestore=SuperRestore;
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2005 CaH4e3
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint16 addrreg;
|
||||
static uint8 datareg;
|
||||
static uint8 busy;
|
||||
static SFORMAT StateRegs[]=
|
||||
{
|
||||
{&addrreg, 2, "ADDRREG"},
|
||||
{&datareg, 1, "DATAREG"},
|
||||
{&busy, 1, "BUSY"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
setprg16(0x8000,(datareg&7)|((addrreg&0x60)>>2)|((addrreg&0x100)>>3));
|
||||
setprg16(0xC000,7|((addrreg&0x60)>>2)|((addrreg&0x100)>>3));
|
||||
setmirror(((addrreg&2)>>1)^1);
|
||||
}
|
||||
|
||||
static DECLFW(BMCT262Write)
|
||||
{
|
||||
if(busy||(A==0x8000))
|
||||
datareg=V;
|
||||
else
|
||||
{
|
||||
addrreg=A;
|
||||
busy=1;
|
||||
}
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void BMCT262Power(void)
|
||||
{
|
||||
setchr8(0);
|
||||
SetWriteHandler(0x8000,0xFFFF,BMCT262Write);
|
||||
SetReadHandler(0x8000,0xFFFF,CartBR);
|
||||
busy=0;
|
||||
addrreg=0;
|
||||
datareg=0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void BMCT262Reset(void)
|
||||
{
|
||||
busy=0;
|
||||
addrreg=0;
|
||||
datareg=0;
|
||||
Sync();
|
||||
}
|
||||
|
||||
static void BMCT262Restore(int version)
|
||||
{
|
||||
Sync();
|
||||
}
|
||||
|
||||
void BMCT262_Init(CartInfo *info)
|
||||
{
|
||||
info->Power=BMCT262Power;
|
||||
info->Reset=BMCT262Reset;
|
||||
GameStateRestore=BMCT262Restore;
|
||||
AddExState(&StateRegs, ~0, 0, 0);
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "mapinc.h"
|
||||
|
||||
static uint8 cmd,mir,rmode,IRQmode;
|
||||
static uint8 DRegs[11];
|
||||
static uint8 IRQCount,IRQa,IRQLatch;
|
||||
|
||||
static SFORMAT Rambo_StateRegs[]={
|
||||
{&cmd, 1, "CMD"},
|
||||
{&mir, 1, "MIR"},
|
||||
{&rmode, 1, "RMOD"},
|
||||
{&IRQmode, 1, "IRQM"},
|
||||
{&IRQCount, 1, "IRQC"},
|
||||
{&IRQa, 1, "IRQA"},
|
||||
{&IRQLatch, 1, "IRQL"},
|
||||
{DRegs, 11, "DREG"},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void FP_FASTAPASS(2) (*setchr1wrap)(unsigned int A, unsigned int V);
|
||||
static int nomirror;
|
||||
|
||||
static void FP_FASTAPASS(1) RAMBO1_IRQHook(int a)
|
||||
{
|
||||
static int smallcount;
|
||||
if(!IRQmode) return;
|
||||
|
||||
smallcount+=a;
|
||||
while(smallcount>=4)
|
||||
{
|
||||
smallcount-=4;
|
||||
IRQCount--;
|
||||
if(IRQCount==0xFF)
|
||||
if(IRQa) X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
|
||||
static void RAMBO1_hb(void)
|
||||
{
|
||||
if(IRQmode) return;
|
||||
if(scanline==240) return; /* hmm. Maybe that should be an mmc3-only call in fce.c. */
|
||||
rmode=0;
|
||||
IRQCount--;
|
||||
if(IRQCount==0xFF)
|
||||
{
|
||||
if(IRQa)
|
||||
{
|
||||
rmode = 1;
|
||||
X6502_IRQBegin(FCEU_IQEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Synco(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
if(cmd&0x20)
|
||||
{
|
||||
setchr1wrap(0x0000,DRegs[0]);
|
||||
setchr1wrap(0x0800,DRegs[1]);
|
||||
setchr1wrap(0x0400,DRegs[8]);
|
||||
setchr1wrap(0x0c00,DRegs[9]);
|
||||
}
|
||||
else
|
||||
{
|
||||
setchr1wrap(0x0000,(DRegs[0]&0xFE));
|
||||
setchr1wrap(0x0400,(DRegs[0]&0xFE)|1);
|
||||
setchr1wrap(0x0800,(DRegs[1]&0xFE));
|
||||
setchr1wrap(0x0C00,(DRegs[1]&0xFE)|1);
|
||||
}
|
||||
|
||||
for(x=0;x<4;x++)
|
||||
setchr1wrap(0x1000+x*0x400,DRegs[2+x]);
|
||||
|
||||
setprg8(0x8000,DRegs[6]);
|
||||
setprg8(0xA000,DRegs[7]);
|
||||
|
||||
setprg8(0xC000,DRegs[10]);
|
||||
}
|
||||
|
||||
|
||||
static DECLFW(RAMBO1_write)
|
||||
{
|
||||
switch(A&0xF001)
|
||||
{
|
||||
case 0xa000: mir=V&1;
|
||||
if(!nomirror)
|
||||
setmirror(mir^1);
|
||||
break;
|
||||
case 0x8000: cmd = V;
|
||||
break;
|
||||
case 0x8001: if((cmd&0xF)<10)
|
||||
DRegs[cmd&0xF]=V;
|
||||
else if((cmd&0xF)==0xF)
|
||||
DRegs[10]=V;
|
||||
Synco();
|
||||
break;
|
||||
case 0xc000: IRQLatch=V;
|
||||
if(rmode==1)
|
||||
IRQCount=IRQLatch;
|
||||
break;
|
||||
case 0xc001: rmode=1;
|
||||
IRQCount=IRQLatch;
|
||||
IRQmode=V&1;
|
||||
break;
|
||||
case 0xE000: IRQa=0;
|
||||
X6502_IRQEnd(FCEU_IQEXT);
|
||||
if(rmode==1)
|
||||
IRQCount=IRQLatch;
|
||||
break;
|
||||
case 0xE001: IRQa=1;
|
||||
if(rmode==1)
|
||||
IRQCount=IRQLatch;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void RAMBO1_Restore(int version)
|
||||
{
|
||||
Synco();
|
||||
if(!nomirror)
|
||||
setmirror(mir^1);
|
||||
}
|
||||
|
||||
static void RAMBO1_init(void)
|
||||
{
|
||||
int x;
|
||||
for(x=0;x<11;x++)
|
||||
DRegs[x]=~0;
|
||||
cmd=mir=0;
|
||||
if(!nomirror)
|
||||
setmirror(1);
|
||||
Synco();
|
||||
GameHBIRQHook=RAMBO1_hb;
|
||||
MapIRQHook=RAMBO1_IRQHook;
|
||||
GameStateRestore=RAMBO1_Restore;
|
||||
SetWriteHandler(0x8000,0xffff,RAMBO1_write);
|
||||
AddExState(Rambo_StateRegs, ~0, 0, 0);
|
||||
}
|
||||
|
||||
static void FP_FASTAPASS(2) CHRWrap(unsigned int A, unsigned int V)
|
||||
{
|
||||
setchr1(A,V);
|
||||
}
|
||||
|
||||
void Mapper64_init(void)
|
||||
{
|
||||
setchr1wrap=CHRWrap;
|
||||
nomirror=0;
|
||||
RAMBO1_init();
|
||||
}
|
||||
|
||||
static int MirCache[8];
|
||||
static unsigned int PPUCHRBus;
|
||||
|
||||
static void FP_FASTAPASS(2) MirWrap(unsigned int A, unsigned int V)
|
||||
{
|
||||
MirCache[A>>10]=(V>>7)&1;
|
||||
if(PPUCHRBus==(A>>10))
|
||||
setmirror(MI_0+((V>>7)&1));
|
||||
setchr1(A,V);
|
||||
}
|
||||
|
||||
static void FP_FASTAPASS(1) MirrorFear(uint32 A)
|
||||
{
|
||||
A&=0x1FFF;
|
||||
A>>=10;
|
||||
PPUCHRBus=A;
|
||||
setmirror(MI_0+MirCache[A]);
|
||||
}
|
||||
|
||||
void Mapper158_init(void)
|
||||
{
|
||||
setchr1wrap=MirWrap;
|
||||
PPU_hook=MirrorFear;
|
||||
nomirror=1;
|
||||
RAMBO1_init();
|
||||
}
|
|
@ -0,0 +1,685 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "fceu.h"
|
||||
#include "ppu.h"
|
||||
|
||||
#include "cart.h"
|
||||
#include "memory.h"
|
||||
#include "x6502.h"
|
||||
|
||||
#include "general.h"
|
||||
|
||||
/*
|
||||
This file contains all code for coordinating the mapping in of the
|
||||
address space external to the NES.
|
||||
It's also (ab)used by the NSF code.
|
||||
*/
|
||||
|
||||
uint8 *Page[32],*VPage[8];
|
||||
uint8 **VPageR=VPage;
|
||||
uint8 *VPageG[8];
|
||||
uint8 *MMC5SPRVPage[8];
|
||||
uint8 *MMC5BGVPage[8];
|
||||
|
||||
static uint8 PRGIsRAM[32]; /* This page is/is not PRG RAM. */
|
||||
|
||||
/* 16 are (sort of) reserved for UNIF/iNES and 16 to map other stuff. */
|
||||
static int CHRram[32];
|
||||
static int PRGram[32];
|
||||
|
||||
uint8 *PRGptr[32];
|
||||
uint8 *CHRptr[32];
|
||||
|
||||
uint32 PRGsize[32];
|
||||
uint32 CHRsize[32];
|
||||
|
||||
uint32 PRGmask2[32];
|
||||
uint32 PRGmask4[32];
|
||||
uint32 PRGmask8[32];
|
||||
uint32 PRGmask16[32];
|
||||
uint32 PRGmask32[32];
|
||||
|
||||
uint32 CHRmask1[32];
|
||||
uint32 CHRmask2[32];
|
||||
uint32 CHRmask4[32];
|
||||
uint32 CHRmask8[32];
|
||||
|
||||
int geniestage=0;
|
||||
|
||||
int modcon;
|
||||
|
||||
uint8 genieval[3];
|
||||
uint8 geniech[3];
|
||||
|
||||
uint32 genieaddr[3];
|
||||
|
||||
static INLINE void setpageptr(int s, uint32 A, uint8 *p, int ram)
|
||||
{
|
||||
uint32 AB=A>>11;
|
||||
int x;
|
||||
|
||||
if(p)
|
||||
for(x=(s>>1)-1;x>=0;x--)
|
||||
{
|
||||
PRGIsRAM[AB+x]=ram;
|
||||
Page[AB+x]=p-A;
|
||||
}
|
||||
else
|
||||
for(x=(s>>1)-1;x>=0;x--)
|
||||
{
|
||||
PRGIsRAM[AB+x]=0;
|
||||
Page[AB+x]=0;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8 nothing[8192];
|
||||
void ResetCartMapping(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=0;x<32;x++)
|
||||
{
|
||||
Page[x]=nothing-x*2048;
|
||||
PRGptr[x]=CHRptr[x]=0;
|
||||
PRGsize[x]=CHRsize[x]=0;
|
||||
}
|
||||
for(x=0;x<8;x++)
|
||||
{
|
||||
MMC5SPRVPage[x]=MMC5BGVPage[x]=VPageR[x]=nothing-0x400*x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SetupCartPRGMapping(int chip, uint8 *p, uint32 size, int ram)
|
||||
{
|
||||
PRGptr[chip]=p;
|
||||
PRGsize[chip]=size;
|
||||
|
||||
PRGmask2[chip]=(size>>11)-1;
|
||||
PRGmask4[chip]=(size>>12)-1;
|
||||
PRGmask8[chip]=(size>>13)-1;
|
||||
PRGmask16[chip]=(size>>14)-1;
|
||||
PRGmask32[chip]=(size>>15)-1;
|
||||
|
||||
PRGram[chip]=ram?1:0;
|
||||
}
|
||||
|
||||
void SetupCartCHRMapping(int chip, uint8 *p, uint32 size, int ram)
|
||||
{
|
||||
CHRptr[chip]=p;
|
||||
CHRsize[chip]=size;
|
||||
|
||||
CHRmask1[chip]=(size>>10)-1;
|
||||
CHRmask2[chip]=(size>>11)-1;
|
||||
CHRmask4[chip]=(size>>12)-1;
|
||||
CHRmask8[chip]=(size>>13)-1;
|
||||
|
||||
CHRram[chip]=ram;
|
||||
}
|
||||
|
||||
DECLFR(CartBR)
|
||||
{
|
||||
return Page[A>>11][A];
|
||||
}
|
||||
|
||||
DECLFW(CartBW)
|
||||
{
|
||||
//printf("Ok: %04x:%02x, %d\n",A,V,PRGIsRAM[A>>11]);
|
||||
if(PRGIsRAM[A>>11] && Page[A>>11])
|
||||
Page[A>>11][A]=V;
|
||||
}
|
||||
|
||||
DECLFR(CartBROB)
|
||||
{
|
||||
if(!Page[A>>11]) return(X.DB);
|
||||
return Page[A>>11][A];
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setprg2r(int r, unsigned int A, unsigned int V)
|
||||
{
|
||||
V&=PRGmask2[r];
|
||||
setpageptr(2,A,PRGptr[r]?(&PRGptr[r][V<<11]):0,PRGram[r]);
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setprg2(uint32 A, uint32 V)
|
||||
{
|
||||
setprg2r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setprg4r(int r, unsigned int A, unsigned int V)
|
||||
{
|
||||
V&=PRGmask4[r];
|
||||
setpageptr(4,A,PRGptr[r]?(&PRGptr[r][V<<12]):0,PRGram[r]);
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setprg4(uint32 A, uint32 V)
|
||||
{
|
||||
setprg4r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setprg8r(int r, unsigned int A, unsigned int V)
|
||||
{
|
||||
if(PRGsize[r]>=8192)
|
||||
{
|
||||
V&=PRGmask8[r];
|
||||
setpageptr(8,A,PRGptr[r]?(&PRGptr[r][V<<13]):0,PRGram[r]);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 VA=V<<2;
|
||||
int x;
|
||||
for(x=0;x<4;x++)
|
||||
setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
|
||||
}
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setprg8(uint32 A, uint32 V)
|
||||
{
|
||||
setprg8r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setprg16r(int r, unsigned int A, unsigned int V)
|
||||
{
|
||||
if(PRGsize[r]>=16384)
|
||||
{
|
||||
V&=PRGmask16[r];
|
||||
setpageptr(16,A,PRGptr[r]?(&PRGptr[r][V<<14]):0,PRGram[r]);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 VA=V<<3;
|
||||
int x;
|
||||
|
||||
for(x=0;x<8;x++)
|
||||
setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
|
||||
}
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setprg16(uint32 A, uint32 V)
|
||||
{
|
||||
setprg16r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setprg32r(int r,unsigned int A, unsigned int V)
|
||||
{
|
||||
if(PRGsize[r]>=32768)
|
||||
{
|
||||
V&=PRGmask32[r];
|
||||
setpageptr(32,A,PRGptr[r]?(&PRGptr[r][V<<15]):0,PRGram[r]);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 VA=V<<4;
|
||||
int x;
|
||||
|
||||
for(x=0;x<16;x++)
|
||||
setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
|
||||
}
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setprg32(uint32 A, uint32 V)
|
||||
{
|
||||
setprg32r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setchr1r(int r, unsigned int A, unsigned int V)
|
||||
{
|
||||
if(!CHRptr[r]) return;
|
||||
FCEUPPU_LineUpdate();
|
||||
V&=CHRmask1[r];
|
||||
if(CHRram[r])
|
||||
PPUCHRRAM|=(1<<(A>>10));
|
||||
else
|
||||
PPUCHRRAM&=~(1<<(A>>10));
|
||||
VPageR[(A)>>10]=&CHRptr[r][(V)<<10]-(A);
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setchr2r(int r, unsigned int A, unsigned int V)
|
||||
{
|
||||
if(!CHRptr[r]) return;
|
||||
FCEUPPU_LineUpdate();
|
||||
V&=CHRmask2[r];
|
||||
VPageR[(A)>>10]=VPageR[((A)>>10)+1]=&CHRptr[r][(V)<<11]-(A);
|
||||
if(CHRram[r])
|
||||
PPUCHRRAM|=(3<<(A>>10));
|
||||
else
|
||||
PPUCHRRAM&=~(3<<(A>>10));
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setchr4r(int r, unsigned int A, unsigned int V)
|
||||
{
|
||||
if(!CHRptr[r]) return;
|
||||
FCEUPPU_LineUpdate();
|
||||
V&=CHRmask4[r];
|
||||
VPageR[(A)>>10]=VPageR[((A)>>10)+1]=
|
||||
VPageR[((A)>>10)+2]=VPageR[((A)>>10)+3]=&CHRptr[r][(V)<<12]-(A);
|
||||
if(CHRram[r])
|
||||
PPUCHRRAM|=(15<<(A>>10));
|
||||
else
|
||||
PPUCHRRAM&=~(15<<(A>>10));
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setchr8r(int r, unsigned int V)
|
||||
{
|
||||
int x;
|
||||
|
||||
if(!CHRptr[r]) return;
|
||||
FCEUPPU_LineUpdate();
|
||||
V&=CHRmask8[r];
|
||||
for(x=7;x>=0;x--)
|
||||
VPageR[x]=&CHRptr[r][V<<13];
|
||||
if(CHRram[r])
|
||||
PPUCHRRAM|=(255);
|
||||
else
|
||||
PPUCHRRAM&=~(255);
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setchr1(unsigned int A, unsigned int V)
|
||||
{
|
||||
setchr1r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setchr2(unsigned int A, unsigned int V)
|
||||
{
|
||||
setchr2r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setchr4(unsigned int A, unsigned int V)
|
||||
{
|
||||
setchr4r(0,A,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(1) setchr8(unsigned int V)
|
||||
{
|
||||
setchr8r(0,V);
|
||||
}
|
||||
|
||||
void FASTAPASS(1) setvram8(uint8 *p)
|
||||
{
|
||||
int x;
|
||||
for(x=7;x>=0;x--)
|
||||
VPageR[x]=p;
|
||||
PPUCHRRAM|=255;
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setvram4(uint32 A, uint8 *p)
|
||||
{
|
||||
int x;
|
||||
for(x=3;x>=0;x--)
|
||||
VPageR[(A>>10)+x]=p-A;
|
||||
PPUCHRRAM|=(15<<(A>>10));
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setvramb1(uint8 *p, uint32 A, uint32 b)
|
||||
{
|
||||
FCEUPPU_LineUpdate();
|
||||
VPageR[A>>10]=p-A+(b<<10);
|
||||
PPUCHRRAM|=(1<<(A>>10));
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setvramb2(uint8 *p, uint32 A, uint32 b)
|
||||
{
|
||||
FCEUPPU_LineUpdate();
|
||||
VPageR[(A>>10)]=VPageR[(A>>10)+1]=p-A+(b<<11);
|
||||
PPUCHRRAM|=(3<<(A>>10));
|
||||
}
|
||||
|
||||
void FASTAPASS(3) setvramb4(uint8 *p, uint32 A, uint32 b)
|
||||
{
|
||||
int x;
|
||||
|
||||
FCEUPPU_LineUpdate();
|
||||
for(x=3;x>=0;x--)
|
||||
VPageR[(A>>10)+x]=p-A+(b<<12);
|
||||
PPUCHRRAM|=(15<<(A>>10));
|
||||
}
|
||||
|
||||
void FASTAPASS(2) setvramb8(uint8 *p, uint32 b)
|
||||
{
|
||||
int x;
|
||||
|
||||
FCEUPPU_LineUpdate();
|
||||
for(x=7;x>=0;x--)
|
||||
VPageR[x]=p+(b<<13);
|
||||
PPUCHRRAM|=255;
|
||||
}
|
||||
|
||||
/* This function can be called without calling SetupCartMirroring(). */
|
||||
|
||||
void FASTAPASS(3) setntamem(uint8 *p, int ram, uint32 b)
|
||||
{
|
||||
FCEUPPU_LineUpdate();
|
||||
vnapage[b]=p;
|
||||
PPUNTARAM&=~(1<<b);
|
||||
if(ram)
|
||||
PPUNTARAM|=1<<b;
|
||||
}
|
||||
|
||||
static int mirrorhard=0;
|
||||
void setmirrorw(int a, int b, int c, int d)
|
||||
{
|
||||
FCEUPPU_LineUpdate();
|
||||
vnapage[0]=NTARAM+a*0x400;
|
||||
vnapage[1]=NTARAM+b*0x400;
|
||||
vnapage[2]=NTARAM+c*0x400;
|
||||
vnapage[3]=NTARAM+d*0x400;
|
||||
}
|
||||
|
||||
void FASTAPASS(1) setmirror(int t)
|
||||
{
|
||||
FCEUPPU_LineUpdate();
|
||||
if(!mirrorhard)
|
||||
{
|
||||
switch(t)
|
||||
{
|
||||
case MI_H:
|
||||
vnapage[0]=vnapage[1]=NTARAM;vnapage[2]=vnapage[3]=NTARAM+0x400;
|
||||
break;
|
||||
case MI_V:
|
||||
vnapage[0]=vnapage[2]=NTARAM;vnapage[1]=vnapage[3]=NTARAM+0x400;
|
||||
break;
|
||||
case MI_0:
|
||||
vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=NTARAM;
|
||||
break;
|
||||
case MI_1:
|
||||
vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=NTARAM+0x400;
|
||||
break;
|
||||
}
|
||||
PPUNTARAM=0xF;
|
||||
}
|
||||
}
|
||||
|
||||
void SetupCartMirroring(int m, int hard, uint8 *extra)
|
||||
{
|
||||
if(m<4)
|
||||
{
|
||||
mirrorhard = 0;
|
||||
setmirror(m);
|
||||
}
|
||||
else
|
||||
{
|
||||
vnapage[0]=NTARAM;
|
||||
vnapage[1]=NTARAM+0x400;
|
||||
vnapage[2]=extra;
|
||||
vnapage[3]=extra+0x400;
|
||||
PPUNTARAM=0xF;
|
||||
}
|
||||
mirrorhard=hard;
|
||||
}
|
||||
|
||||
static uint8 *GENIEROM=0;
|
||||
|
||||
void FixGenieMap(void);
|
||||
|
||||
/* Called when a game(file) is opened successfully. */
|
||||
void OpenGenie(void)
|
||||
{
|
||||
FILE *fp;
|
||||
int x;
|
||||
|
||||
if(!GENIEROM)
|
||||
{
|
||||
char *fn;
|
||||
|
||||
if(!(GENIEROM=(uint8 *)FCEU_malloc(4096+1024))) return;
|
||||
|
||||
fn=FCEU_MakeFName(FCEUMKF_GGROM,0,0);
|
||||
fp=FCEUD_UTF8fopen(fn,"rb");
|
||||
if(!fp)
|
||||
{
|
||||
FCEU_PrintError("Error opening Game Genie ROM image!");
|
||||
free(GENIEROM);
|
||||
GENIEROM=0;
|
||||
return;
|
||||
}
|
||||
if(fread(GENIEROM,1,16,fp)!=16)
|
||||
{
|
||||
grerr:
|
||||
FCEU_PrintError("Error reading from Game Genie ROM image!");
|
||||
free(GENIEROM);
|
||||
GENIEROM=0;
|
||||
fclose(fp);
|
||||
return;
|
||||
}
|
||||
if(GENIEROM[0]==0x4E) /* iNES ROM image */
|
||||
{
|
||||
if(fread(GENIEROM,1,4096,fp)!=4096)
|
||||
goto grerr;
|
||||
if(fseek(fp,16384-4096,SEEK_CUR))
|
||||
goto grerr;
|
||||
if(fread(GENIEROM+4096,1,256,fp)!=256)
|
||||
goto grerr;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(fread(GENIEROM+16,1,4352-16,fp)!=(4352-16))
|
||||
goto grerr;
|
||||
}
|
||||
fclose(fp);
|
||||
|
||||
/* Workaround for the FCE Ultra CHR page size only being 1KB */
|
||||
for(x=0;x<4;x++)
|
||||
memcpy(GENIEROM+4096+(x<<8),GENIEROM+4096,256);
|
||||
}
|
||||
|
||||
geniestage=1;
|
||||
}
|
||||
|
||||
/* Called when a game is closed. */
|
||||
void CloseGenie(void)
|
||||
{
|
||||
/* No good reason to free() the Game Genie ROM image data. */
|
||||
geniestage=0;
|
||||
FlushGenieRW();
|
||||
VPageR=VPage;
|
||||
}
|
||||
|
||||
void FCEU_KillGenie(void)
|
||||
{
|
||||
if(GENIEROM)
|
||||
{
|
||||
free(GENIEROM);
|
||||
GENIEROM=0;
|
||||
}
|
||||
}
|
||||
|
||||
static DECLFR(GenieRead)
|
||||
{
|
||||
return GENIEROM[A&4095];
|
||||
}
|
||||
|
||||
static DECLFW(GenieWrite)
|
||||
{
|
||||
switch(A)
|
||||
{
|
||||
case 0x800c:
|
||||
case 0x8008:
|
||||
case 0x8004:genieval[((A-4)&0xF)>>2]=V;break;
|
||||
|
||||
case 0x800b:
|
||||
case 0x8007:
|
||||
case 0x8003:geniech[((A-3)&0xF)>>2]=V;break;
|
||||
|
||||
case 0x800a:
|
||||
case 0x8006:
|
||||
case 0x8002:genieaddr[((A-2)&0xF)>>2]&=0xFF00;genieaddr[((A-2)&0xF)>>2]|=V;break;
|
||||
|
||||
case 0x8009:
|
||||
case 0x8005:
|
||||
case 0x8001:genieaddr[((A-1)&0xF)>>2]&=0xFF;genieaddr[((A-1)&0xF)>>2]|=(V|0x80)<<8;break;
|
||||
|
||||
case 0x8000:if(!V)
|
||||
FixGenieMap();
|
||||
else
|
||||
{
|
||||
modcon=V^0xFF;
|
||||
if(V==0x71)
|
||||
modcon=0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static readfunc GenieBackup[3];
|
||||
|
||||
static DECLFR(GenieFix1)
|
||||
{
|
||||
uint8 r=GenieBackup[0](A);
|
||||
|
||||
if((modcon>>1)&1) // No check
|
||||
return genieval[0];
|
||||
else if(r==geniech[0])
|
||||
return genieval[0];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static DECLFR(GenieFix2)
|
||||
{
|
||||
uint8 r=GenieBackup[1](A);
|
||||
|
||||
if((modcon>>2)&1) // No check
|
||||
return genieval[1];
|
||||
else if(r==geniech[1])
|
||||
return genieval[1];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static DECLFR(GenieFix3)
|
||||
{
|
||||
uint8 r=GenieBackup[2](A);
|
||||
|
||||
if((modcon>>3)&1) // No check
|
||||
return genieval[2];
|
||||
else if(r==geniech[2])
|
||||
return genieval[2];
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
void FixGenieMap(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
geniestage=2;
|
||||
|
||||
for(x=0;x<8;x++)
|
||||
VPage[x]=VPageG[x];
|
||||
|
||||
VPageR=VPage;
|
||||
FlushGenieRW();
|
||||
//printf("Rightyo\n");
|
||||
for(x=0;x<3;x++)
|
||||
if((modcon>>(4+x))&1)
|
||||
{
|
||||
readfunc tmp[3]={GenieFix1,GenieFix2,GenieFix3};
|
||||
GenieBackup[x]=GetReadHandler(genieaddr[x]);
|
||||
SetReadHandler(genieaddr[x],genieaddr[x],tmp[x]);
|
||||
}
|
||||
}
|
||||
|
||||
void GeniePower(void)
|
||||
{
|
||||
uint32 x;
|
||||
|
||||
if(!geniestage)
|
||||
return;
|
||||
|
||||
geniestage=1;
|
||||
for(x=0;x<3;x++)
|
||||
{
|
||||
genieval[x]=0xFF;
|
||||
geniech[x]=0xFF;
|
||||
genieaddr[x]=0xFFFF;
|
||||
}
|
||||
modcon=0;
|
||||
|
||||
SetWriteHandler(0x8000,0xFFFF,GenieWrite);
|
||||
SetReadHandler(0x8000,0xFFFF,GenieRead);
|
||||
|
||||
for(x=0;x<8;x++)
|
||||
VPage[x]=GENIEROM+4096-0x400*x;
|
||||
|
||||
if(AllocGenieRW())
|
||||
VPageR=VPageG;
|
||||
else
|
||||
geniestage=2;
|
||||
}
|
||||
|
||||
|
||||
void FCEU_SaveGameSave(CartInfo *LocalHWInfo)
|
||||
{
|
||||
if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0])
|
||||
{
|
||||
FILE *sp;
|
||||
char *soot;
|
||||
|
||||
soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
|
||||
if((sp=FCEUD_UTF8fopen(soot,"wb"))==NULL)
|
||||
{
|
||||
FCEU_PrintError("WRAM file \"%s\" cannot be written to.\n",soot);
|
||||
}
|
||||
else
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=0;x<4;x++)
|
||||
if(LocalHWInfo->SaveGame[x])
|
||||
{
|
||||
fwrite(LocalHWInfo->SaveGame[x],1,
|
||||
LocalHWInfo->SaveGameLen[x],sp);
|
||||
}
|
||||
}
|
||||
free(soot);
|
||||
}
|
||||
}
|
||||
|
||||
// hack, movie.c has to communicate with this function somehow
|
||||
int disableBatteryLoading=0;
|
||||
|
||||
void FCEU_LoadGameSave(CartInfo *LocalHWInfo)
|
||||
{
|
||||
if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0] && !disableBatteryLoading)
|
||||
{
|
||||
FILE *sp;
|
||||
char *soot;
|
||||
|
||||
soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
|
||||
sp=FCEUD_UTF8fopen(soot,"rb");
|
||||
if(sp!=NULL)
|
||||
{
|
||||
int x;
|
||||
for(x=0;x<4;x++)
|
||||
if(LocalHWInfo->SaveGame[x])
|
||||
fread(LocalHWInfo->SaveGame[x],1,LocalHWInfo->SaveGameLen[x],sp);
|
||||
}
|
||||
free(soot);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
typedef struct {
|
||||
/* Set by mapper/board code: */
|
||||
void (*Power)(void);
|
||||
void (*Reset)(void);
|
||||
void (*Close)(void);
|
||||
uint8 *SaveGame[4]; /* Pointers to memory to save/load. */
|
||||
uint32 SaveGameLen[4]; /* How much memory to save/load. */
|
||||
|
||||
/* Set by iNES/UNIF loading code. */
|
||||
int mirror; /* As set in the header or chunk.
|
||||
iNES/UNIF specific. Intended
|
||||
to help support games like "Karnov"
|
||||
that are not really MMC3 but are
|
||||
set to mapper 4.
|
||||
*/
|
||||
int battery; /* Presence of an actual battery. */
|
||||
uint8 MD5[16];
|
||||
uint32 CRC32; /* Should be set by the iNES/UNIF loading
|
||||
code, used by mapper/board code, maybe
|
||||
other code in the future.
|
||||
*/
|
||||
} CartInfo;
|
||||
|
||||
void FCEU_SaveGameSave(CartInfo *LocalHWInfo);
|
||||
void FCEU_LoadGameSave(CartInfo *LocalHWInfo);
|
||||
|
||||
extern uint8 *Page[32],*VPage[8],*MMC5SPRVPage[8],*MMC5BGVPage[8];
|
||||
|
||||
void ResetCartMapping(void);
|
||||
void SetupCartPRGMapping(int chip, uint8 *p, uint32 size, int ram);
|
||||
void SetupCartCHRMapping(int chip, uint8 *p, uint32 size, int ram);
|
||||
void SetupCartMirroring(int m, int hard, uint8 *extra);
|
||||
|
||||
DECLFR(CartBROB);
|
||||
DECLFR(CartBR);
|
||||
DECLFW(CartBW);
|
||||
|
||||
extern uint8 *PRGptr[32];
|
||||
extern uint8 *CHRptr[32];
|
||||
|
||||
extern uint32 PRGsize[32];
|
||||
extern uint32 CHRsize[32];
|
||||
|
||||
extern uint32 PRGmask2[32];
|
||||
extern uint32 PRGmask4[32];
|
||||
extern uint32 PRGmask8[32];
|
||||
extern uint32 PRGmask16[32];
|
||||
extern uint32 PRGmask32[32];
|
||||
|
||||
extern uint32 CHRmask1[32];
|
||||
extern uint32 CHRmask2[32];
|
||||
extern uint32 CHRmask4[32];
|
||||
extern uint32 CHRmask8[32];
|
||||
|
||||
void FASTAPASS(2) setprg2(uint32 A, uint32 V);
|
||||
void FASTAPASS(2) setprg4(uint32 A, uint32 V);
|
||||
void FASTAPASS(2) setprg8(uint32 A, uint32 V);
|
||||
void FASTAPASS(2) setprg16(uint32 A, uint32 V);
|
||||
void FASTAPASS(2) setprg32(uint32 A, uint32 V);
|
||||
|
||||
void FASTAPASS(3) setprg2r(int r, unsigned int A, unsigned int V);
|
||||
void FASTAPASS(3) setprg4r(int r, unsigned int A, unsigned int V);
|
||||
void FASTAPASS(3) setprg8r(int r, unsigned int A, unsigned int V);
|
||||
void FASTAPASS(3) setprg16r(int r, unsigned int A, unsigned int V);
|
||||
void FASTAPASS(3) setprg32r(int r, unsigned int A, unsigned int V);
|
||||
|
||||
void FASTAPASS(3) setchr1r(int r, unsigned int A, unsigned int V);
|
||||
void FASTAPASS(3) setchr2r(int r, unsigned int A, unsigned int V);
|
||||
void FASTAPASS(3) setchr4r(int r, unsigned int A, unsigned int V);
|
||||
void FASTAPASS(2) setchr8r(int r, unsigned int V);
|
||||
|
||||
void FASTAPASS(2) setchr1(unsigned int A, unsigned int V);
|
||||
void FASTAPASS(2) setchr2(unsigned int A, unsigned int V);
|
||||
void FASTAPASS(2) setchr4(unsigned int A, unsigned int V);
|
||||
void FASTAPASS(1) setchr8(unsigned int V);
|
||||
|
||||
void FASTAPASS(2) setvram4(uint32 A, uint8 *p);
|
||||
void FASTAPASS(1) setvram8(uint8 *p);
|
||||
|
||||
void FASTAPASS(3) setvramb1(uint8 *p, uint32 A, uint32 b);
|
||||
void FASTAPASS(3) setvramb2(uint8 *p, uint32 A, uint32 b);
|
||||
void FASTAPASS(3) setvramb4(uint8 *p, uint32 A, uint32 b);
|
||||
void FASTAPASS(2) setvramb8(uint8 *p, uint32 b);
|
||||
|
||||
void FASTAPASS(1) setmirror(int t);
|
||||
void setmirrorw(int a, int b, int c, int d);
|
||||
void FASTAPASS(3) setntamem(uint8 *p, int ram, uint32 b);
|
||||
|
||||
#define MI_H 0
|
||||
#define MI_V 1
|
||||
#define MI_0 2
|
||||
#define MI_1 3
|
||||
|
||||
extern int geniestage;
|
||||
|
||||
void GeniePower(void);
|
||||
|
||||
void OpenGenie(void);
|
||||
void CloseGenie(void);
|
||||
void FCEU_KillGenie(void);
|
|
@ -0,0 +1,855 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "x6502.h"
|
||||
#include "cheat.h"
|
||||
#include "fceu.h"
|
||||
#include "general.h"
|
||||
#include "cart.h"
|
||||
#include "memory.h"
|
||||
|
||||
static uint8 *CheatRPtrs[64];
|
||||
|
||||
void FCEU_CheatResetRAM(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=0;x<64;x++)
|
||||
CheatRPtrs[x]=0;
|
||||
}
|
||||
|
||||
void FCEU_CheatAddRAM(int s, uint32 A, uint8 *p)
|
||||
{
|
||||
uint32 AB=A>>10;
|
||||
int x;
|
||||
|
||||
for(x=s-1;x>=0;x--)
|
||||
CheatRPtrs[AB+x]=p-A;
|
||||
}
|
||||
|
||||
|
||||
struct CHEATF {
|
||||
struct CHEATF *next;
|
||||
char *name;
|
||||
uint16 addr;
|
||||
uint8 val;
|
||||
int compare; /* -1 for no compare. */
|
||||
int type; /* 0 for replace, 1 for substitute(GG). */
|
||||
int status;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint16 addr;
|
||||
uint8 val;
|
||||
int compare;
|
||||
readfunc PrevRead;
|
||||
} CHEATF_SUBFAST;
|
||||
|
||||
|
||||
static CHEATF_SUBFAST SubCheats[256];
|
||||
static int numsubcheats=0;
|
||||
struct CHEATF *cheats=0,*cheatsl=0;
|
||||
|
||||
|
||||
#define CHEATC_NONE 0x8000
|
||||
#define CHEATC_EXCLUDED 0x4000
|
||||
#define CHEATC_NOSHOW 0xC000
|
||||
|
||||
static uint16 *CheatComp=0;
|
||||
static int savecheats;
|
||||
|
||||
static DECLFR(SubCheatsRead)
|
||||
{
|
||||
CHEATF_SUBFAST *s=SubCheats;
|
||||
int x=numsubcheats;
|
||||
|
||||
do
|
||||
{
|
||||
if(s->addr==A)
|
||||
{
|
||||
if(s->compare>=0)
|
||||
{
|
||||
uint8 pv=s->PrevRead(A);
|
||||
|
||||
if(pv==s->compare)
|
||||
return(s->val);
|
||||
else return(pv);
|
||||
}
|
||||
else return(s->val);
|
||||
}
|
||||
s++;
|
||||
} while(--x);
|
||||
return(0); /* We should never get here. */
|
||||
}
|
||||
|
||||
void RebuildSubCheats(void)
|
||||
{
|
||||
int x;
|
||||
struct CHEATF *c=cheats;
|
||||
|
||||
for(x=0;x<numsubcheats;x++)
|
||||
SetReadHandler(SubCheats[x].addr,SubCheats[x].addr,SubCheats[x].PrevRead);
|
||||
|
||||
numsubcheats=0;
|
||||
while(c)
|
||||
{
|
||||
if(c->type==1 && c->status)
|
||||
{
|
||||
if(GetReadHandler(c->addr)==SubCheatsRead)
|
||||
{
|
||||
/* Prevent a catastrophe by this check. */
|
||||
//FCEU_DispMessage("oops");
|
||||
}
|
||||
else
|
||||
{
|
||||
SubCheats[numsubcheats].PrevRead=GetReadHandler(c->addr);
|
||||
SubCheats[numsubcheats].addr=c->addr;
|
||||
SubCheats[numsubcheats].val=c->val;
|
||||
SubCheats[numsubcheats].compare=c->compare;
|
||||
SetReadHandler(c->addr,c->addr,SubCheatsRead);
|
||||
numsubcheats++;
|
||||
}
|
||||
}
|
||||
c=c->next;
|
||||
}
|
||||
}
|
||||
|
||||
void FCEU_PowerCheats()
|
||||
{
|
||||
numsubcheats=0; /* Quick hack to prevent setting of ancient read addresses. */
|
||||
RebuildSubCheats();
|
||||
}
|
||||
|
||||
static int AddCheatEntry(char *name, uint32 addr, uint8 val, int compare, int status, int type);
|
||||
static void CheatMemErr(void)
|
||||
{
|
||||
FCEUD_PrintError("Error allocating memory for cheat data.");
|
||||
}
|
||||
|
||||
/* This function doesn't allocate any memory for "name" */
|
||||
static int AddCheatEntry(char *name, uint32 addr, uint8 val, int compare, int status, int type)
|
||||
{
|
||||
struct CHEATF *temp;
|
||||
if(!(temp=(struct CHEATF *)malloc(sizeof(struct CHEATF))))
|
||||
{
|
||||
CheatMemErr();
|
||||
return(0);
|
||||
}
|
||||
temp->name=name;
|
||||
temp->addr=addr;
|
||||
temp->val=val;
|
||||
temp->status=status;
|
||||
temp->compare=compare;
|
||||
temp->type=type;
|
||||
temp->next=0;
|
||||
|
||||
if(cheats)
|
||||
{
|
||||
cheatsl->next=temp;
|
||||
cheatsl=temp;
|
||||
}
|
||||
else
|
||||
cheats=cheatsl=temp;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
void FCEU_LoadGameCheats(FILE *override)
|
||||
{
|
||||
FILE *fp;
|
||||
unsigned int addr;
|
||||
unsigned int val;
|
||||
unsigned int status;
|
||||
unsigned int type;
|
||||
unsigned int compare;
|
||||
int x;
|
||||
|
||||
char linebuf[2048];
|
||||
char *namebuf;
|
||||
int tc=0;
|
||||
char *fn;
|
||||
|
||||
numsubcheats=savecheats=0;
|
||||
|
||||
if(override)
|
||||
fp = override;
|
||||
else
|
||||
{
|
||||
fn=FCEU_MakeFName(FCEUMKF_CHEAT,0,0);
|
||||
fp=FCEUD_UTF8fopen(fn,"rb");
|
||||
free(fn);
|
||||
if(!fp) return;
|
||||
}
|
||||
|
||||
while(fgets(linebuf,2048,fp)>0)
|
||||
{
|
||||
char *tbuf=linebuf;
|
||||
int doc=0;
|
||||
|
||||
addr=val=compare=status=type=0;
|
||||
|
||||
if(tbuf[0]=='S')
|
||||
{
|
||||
tbuf++;
|
||||
type=1;
|
||||
}
|
||||
else type=0;
|
||||
|
||||
if(tbuf[0]=='C')
|
||||
{
|
||||
tbuf++;
|
||||
doc=1;
|
||||
}
|
||||
|
||||
if(tbuf[0]==':')
|
||||
{
|
||||
tbuf++;
|
||||
status=0;
|
||||
}
|
||||
else status=1;
|
||||
|
||||
if(doc)
|
||||
{
|
||||
char *neo=&tbuf[4+2+2+1+1+1];
|
||||
if(sscanf(tbuf,"%04x%*[:]%02x%*[:]%02x",&addr,&val,&compare)!=3)
|
||||
continue;
|
||||
namebuf=malloc(strlen(neo)+1);
|
||||
strcpy(namebuf,neo);
|
||||
}
|
||||
else
|
||||
{
|
||||
char *neo=&tbuf[4+2+1+1];
|
||||
if(sscanf(tbuf,"%04x%*[:]%02x",&addr,&val)!=2)
|
||||
continue;
|
||||
namebuf=malloc(strlen(neo)+1);
|
||||
strcpy(namebuf,neo);
|
||||
}
|
||||
|
||||
for(x=0;x<strlen(namebuf);x++)
|
||||
{
|
||||
if(namebuf[x]==10 || namebuf[x]==13)
|
||||
{
|
||||
namebuf[x]=0;
|
||||
break;
|
||||
}
|
||||
else if(namebuf[x]<0x20) namebuf[x]=' ';
|
||||
}
|
||||
|
||||
AddCheatEntry(namebuf,addr,val,doc?compare:-1,status,type);
|
||||
tc++;
|
||||
}
|
||||
RebuildSubCheats();
|
||||
if(!override)
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
void FCEU_FlushGameCheats(FILE *override, int nosave)
|
||||
{
|
||||
if(CheatComp)
|
||||
{
|
||||
free(CheatComp);
|
||||
CheatComp=0;
|
||||
}
|
||||
if((!savecheats || nosave) && !override) /* Always save cheats if we're being overridden. */
|
||||
{
|
||||
if(cheats)
|
||||
{
|
||||
struct CHEATF *next=cheats;
|
||||
for(;;)
|
||||
{
|
||||
struct CHEATF *last=next;
|
||||
next=next->next;
|
||||
free(last->name);
|
||||
free(last);
|
||||
if(!next) break;
|
||||
}
|
||||
cheats=cheatsl=0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char *fn = 0;
|
||||
|
||||
if(!override)
|
||||
fn = FCEU_MakeFName(FCEUMKF_CHEAT,0,0);
|
||||
|
||||
if(cheats)
|
||||
{
|
||||
struct CHEATF *next=cheats;
|
||||
FILE *fp;
|
||||
|
||||
if(override)
|
||||
fp = override;
|
||||
else
|
||||
fp=FCEUD_UTF8fopen(fn,"wb");
|
||||
|
||||
if(fp)
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
struct CHEATF *t;
|
||||
if(next->type)
|
||||
fputc('S',fp);
|
||||
if(next->compare>=0)
|
||||
fputc('C',fp);
|
||||
|
||||
if(!next->status)
|
||||
fputc(':',fp);
|
||||
|
||||
if(next->compare>=0)
|
||||
fprintf(fp,"%04x:%02x:%02x:%s\n",next->addr,next->val,next->compare,next->name);
|
||||
else
|
||||
fprintf(fp,"%04x:%02x:%s\n",next->addr,next->val,next->name);
|
||||
|
||||
free(next->name);
|
||||
t=next;
|
||||
next=next->next;
|
||||
free(t);
|
||||
if(!next) break;
|
||||
}
|
||||
if(!override)
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
FCEUD_PrintError("Error saving cheats.");
|
||||
cheats=cheatsl=0;
|
||||
}
|
||||
else if(!override)
|
||||
remove(fn);
|
||||
if(!override)
|
||||
free(fn);
|
||||
}
|
||||
|
||||
RebuildSubCheats(); /* Remove memory handlers. */
|
||||
|
||||
}
|
||||
|
||||
|
||||
int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type)
|
||||
{
|
||||
char *t;
|
||||
|
||||
if(!(t=(char *)malloc(strlen(name)+1)))
|
||||
{
|
||||
CheatMemErr();
|
||||
return(0);
|
||||
}
|
||||
strcpy(t,name);
|
||||
if(!AddCheatEntry(t,addr,val,compare,1,type))
|
||||
{
|
||||
free(t);
|
||||
return(0);
|
||||
}
|
||||
savecheats=1;
|
||||
RebuildSubCheats();
|
||||
return(1);
|
||||
}
|
||||
|
||||
int FCEUI_DelCheat(uint32 which)
|
||||
{
|
||||
struct CHEATF *prev;
|
||||
struct CHEATF *cur;
|
||||
uint32 x=0;
|
||||
|
||||
for(prev=0,cur=cheats;;)
|
||||
{
|
||||
if(x==which) // Remove this cheat.
|
||||
{
|
||||
if(prev) // Update pointer to this cheat.
|
||||
{
|
||||
if(cur->next) // More cheats.
|
||||
prev->next=cur->next;
|
||||
else // No more.
|
||||
{
|
||||
prev->next=0;
|
||||
cheatsl=prev; // Set the previous cheat as the last cheat.
|
||||
}
|
||||
}
|
||||
else // This is the first cheat.
|
||||
{
|
||||
if(cur->next) // More cheats
|
||||
cheats=cur->next;
|
||||
else
|
||||
cheats=cheatsl=0; // No (more) cheats.
|
||||
}
|
||||
free(cur->name); // Now that all references to this cheat are removed,
|
||||
free(cur); // free the memory.
|
||||
break;
|
||||
} // *END REMOVE THIS CHEAT*
|
||||
|
||||
|
||||
if(!cur->next) // No more cheats to go through(this shouldn't ever happen...)
|
||||
return(0);
|
||||
prev=cur;
|
||||
cur=prev->next;
|
||||
x++;
|
||||
}
|
||||
|
||||
savecheats=1;
|
||||
RebuildSubCheats();
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
void FCEU_ApplyPeriodicCheats(void)
|
||||
{
|
||||
struct CHEATF *cur=cheats;
|
||||
if(!cur) return;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
if(cur->status && !(cur->type))
|
||||
if(CheatRPtrs[cur->addr>>10])
|
||||
CheatRPtrs[cur->addr>>10][cur->addr]=cur->val;
|
||||
if(cur->next)
|
||||
cur=cur->next;
|
||||
else
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FCEUI_ListCheats(int (*callb)(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data), void *data)
|
||||
{
|
||||
struct CHEATF *next=cheats;
|
||||
|
||||
while(next)
|
||||
{
|
||||
if(!callb(next->name,next->addr,next->val,next->compare,next->status,next->type,data)) break;
|
||||
next=next->next;
|
||||
}
|
||||
}
|
||||
|
||||
int FCEUI_GetCheat(uint32 which, char **name, uint32 *a, uint8 *v, int *compare, int *s, int *type)
|
||||
{
|
||||
struct CHEATF *next=cheats;
|
||||
uint32 x=0;
|
||||
|
||||
while(next)
|
||||
{
|
||||
if(x==which)
|
||||
{
|
||||
if(name)
|
||||
*name=next->name;
|
||||
if(a)
|
||||
*a=next->addr;
|
||||
if(v)
|
||||
*v=next->val;
|
||||
if(s)
|
||||
*s=next->status;
|
||||
if(compare)
|
||||
*compare=next->compare;
|
||||
if(type)
|
||||
*type=next->type;
|
||||
return(1);
|
||||
}
|
||||
next=next->next;
|
||||
x++;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int GGtobin(char c)
|
||||
{
|
||||
static char lets[16]={'A','P','Z','L','G','I','T','Y','E','O','X','U','K','S','V','N'};
|
||||
int x;
|
||||
|
||||
for(x=0;x<16;x++)
|
||||
if(lets[x] == toupper(c)) return(x);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Returns 1 on success, 0 on failure. Sets *a,*v,*c. */
|
||||
int FCEUI_DecodeGG(const char *str, uint16 *a, uint8 *v, int *c)
|
||||
{
|
||||
uint16 A;
|
||||
uint8 V,C;
|
||||
uint8 t;
|
||||
int s;
|
||||
|
||||
A=0x8000;
|
||||
V=0;
|
||||
C=0;
|
||||
|
||||
s=strlen(str);
|
||||
if(s!=6 && s!=8) return(0);
|
||||
|
||||
t=GGtobin(*str++);
|
||||
V|=(t&0x07);
|
||||
V|=(t&0x08)<<4;
|
||||
|
||||
t=GGtobin(*str++);
|
||||
V|=(t&0x07)<<4;
|
||||
A|=(t&0x08)<<4;
|
||||
|
||||
t=GGtobin(*str++);
|
||||
A|=(t&0x07)<<4;
|
||||
//if(t&0x08) return(0); /* 8-character code?! */
|
||||
|
||||
t=GGtobin(*str++);
|
||||
A|=(t&0x07)<<12;
|
||||
A|=(t&0x08);
|
||||
|
||||
t=GGtobin(*str++);
|
||||
A|=(t&0x07);
|
||||
A|=(t&0x08)<<8;
|
||||
|
||||
if(s==6)
|
||||
{
|
||||
t=GGtobin(*str++);
|
||||
A|=(t&0x07)<<8;
|
||||
V|=(t&0x08);
|
||||
|
||||
*a=A;
|
||||
*v=V;
|
||||
*c=-1;
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
t=GGtobin(*str++);
|
||||
A|=(t&0x07)<<8;
|
||||
C|=(t&0x08);
|
||||
|
||||
t=GGtobin(*str++);
|
||||
C|=(t&0x07);
|
||||
C|=(t&0x08)<<4;
|
||||
|
||||
t=GGtobin(*str++);
|
||||
C|=(t&0x07)<<4;
|
||||
V|=(t&0x08);
|
||||
*a=A;
|
||||
*v=V;
|
||||
*c=C;
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int FCEUI_DecodePAR(const char *str, uint16 *a, uint8 *v, int *c, int *type)
|
||||
{
|
||||
int boo[4];
|
||||
if(strlen(str)!=8) return(0);
|
||||
|
||||
sscanf(str,"%02x%02x%02x%02x",boo,boo+1,boo+2,boo+3);
|
||||
|
||||
*c=-1;
|
||||
|
||||
if(1)
|
||||
{
|
||||
*a=(boo[3]<<8)|(boo[2]+0x7F);
|
||||
*v=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*v=boo[3];
|
||||
*a=boo[2]|(boo[1]<<8);
|
||||
}
|
||||
/* Zero-page addressing modes don't go through the normal read/write handlers in FCEU, so
|
||||
we must do the old hacky method of RAM cheats.
|
||||
*/
|
||||
if(*a<0x0100)
|
||||
*type=0;
|
||||
else
|
||||
*type=1;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* name can be NULL if the name isn't going to be changed. */
|
||||
/* same goes for a, v, and s(except the values of each one must be <0) */
|
||||
|
||||
int FCEUI_SetCheat(uint32 which, const char *name, int32 a, int32 v, int compare,int s, int type)
|
||||
{
|
||||
struct CHEATF *next=cheats;
|
||||
uint32 x=0;
|
||||
|
||||
while(next)
|
||||
{
|
||||
if(x==which)
|
||||
{
|
||||
if(name)
|
||||
{
|
||||
char *t;
|
||||
|
||||
if((t=(char *)realloc(next->name,strlen(name+1))))
|
||||
{
|
||||
next->name=t;
|
||||
strcpy(next->name,name);
|
||||
}
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
if(a>=0)
|
||||
next->addr=a;
|
||||
if(v>=0)
|
||||
next->val=v;
|
||||
if(s>=0)
|
||||
next->status=s;
|
||||
next->compare=compare;
|
||||
next->type=type;
|
||||
|
||||
savecheats=1;
|
||||
RebuildSubCheats();
|
||||
|
||||
return(1);
|
||||
}
|
||||
next=next->next;
|
||||
x++;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Convenience function. */
|
||||
int FCEUI_ToggleCheat(uint32 which)
|
||||
{
|
||||
struct CHEATF *next=cheats;
|
||||
uint32 x=0;
|
||||
|
||||
while(next)
|
||||
{
|
||||
if(x==which)
|
||||
{
|
||||
next->status=!next->status;
|
||||
savecheats=1;
|
||||
RebuildSubCheats();
|
||||
return(next->status);
|
||||
}
|
||||
next=next->next;
|
||||
x++;
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static int InitCheatComp(void)
|
||||
{
|
||||
uint32 x;
|
||||
|
||||
CheatComp=(uint16*)malloc(65536*sizeof(uint16));
|
||||
if(!CheatComp)
|
||||
{
|
||||
CheatMemErr();
|
||||
return(0);
|
||||
}
|
||||
for(x=0;x<65536;x++)
|
||||
CheatComp[x]=CHEATC_NONE;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
void FCEUI_CheatSearchSetCurrentAsOriginal(void)
|
||||
{
|
||||
uint32 x;
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatRPtrs[x>>10])
|
||||
CheatComp[x]=CheatRPtrs[x>>10][x];
|
||||
else
|
||||
CheatComp[x]|=CHEATC_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
void FCEUI_CheatSearchShowExcluded(void)
|
||||
{
|
||||
uint32 x;
|
||||
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
CheatComp[x]&=~CHEATC_EXCLUDED;
|
||||
}
|
||||
|
||||
|
||||
int32 FCEUI_CheatSearchGetCount(void)
|
||||
{
|
||||
uint32 x,c=0;
|
||||
|
||||
if(CheatComp)
|
||||
{
|
||||
for(x=0x0000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
|
||||
c++;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
/* This function will give the initial value of the search and the current value at a location. */
|
||||
|
||||
void FCEUI_CheatSearchGet(int (*callb)(uint32 a, uint8 last, uint8 current, void *data),void *data)
|
||||
{
|
||||
uint32 x;
|
||||
|
||||
if(!CheatComp)
|
||||
{
|
||||
if(!InitCheatComp())
|
||||
CheatMemErr();
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
|
||||
if(!callb(x,CheatComp[x],CheatRPtrs[x>>10][x],data))
|
||||
break;
|
||||
}
|
||||
|
||||
void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a, uint8 last, uint8 current))
|
||||
{
|
||||
uint32 x;
|
||||
uint32 in=0;
|
||||
|
||||
if(!CheatComp)
|
||||
{
|
||||
if(!InitCheatComp())
|
||||
CheatMemErr();
|
||||
return;
|
||||
}
|
||||
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
|
||||
{
|
||||
if(in>=first)
|
||||
if(!callb(x,CheatComp[x],CheatRPtrs[x>>10][x]))
|
||||
break;
|
||||
in++;
|
||||
if(in>last) return;
|
||||
}
|
||||
}
|
||||
|
||||
void FCEUI_CheatSearchBegin(void)
|
||||
{
|
||||
uint32 x;
|
||||
|
||||
if(!CheatComp)
|
||||
{
|
||||
if(!InitCheatComp())
|
||||
{
|
||||
CheatMemErr();
|
||||
return;
|
||||
}
|
||||
}
|
||||
for(x=0;x<0x10000;x++)
|
||||
{
|
||||
if(CheatRPtrs[x>>10])
|
||||
CheatComp[x]=CheatRPtrs[x>>10][x];
|
||||
else
|
||||
CheatComp[x]=CHEATC_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int INLINE CAbs(int x)
|
||||
{
|
||||
if(x<0)
|
||||
return(0-x);
|
||||
return x;
|
||||
}
|
||||
|
||||
void FCEUI_CheatSearchEnd(int type, uint8 v1, uint8 v2)
|
||||
{
|
||||
uint32 x;
|
||||
|
||||
if(!CheatComp)
|
||||
{
|
||||
if(!InitCheatComp())
|
||||
{
|
||||
CheatMemErr();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!type) // Change to a specific value.
|
||||
{
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]==v1 && CheatRPtrs[x>>10][x]==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
else if(type==1) // Search for relative change(between values).
|
||||
{
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]==v1 && CAbs(CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
else if(type==2) // Purely relative change.
|
||||
{
|
||||
for(x=0x000;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CAbs(CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
else if(type==3) // Any change.
|
||||
{
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(CheatComp[x]!=CheatRPtrs[x>>10][x])
|
||||
{
|
||||
|
||||
}
|
||||
else
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
else if(type==4) // Value decreased.
|
||||
{
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(!(CheatRPtrs[x>>10][x]<CheatComp[x]))
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
else if(type==5) // Value increased.
|
||||
{
|
||||
for(x=0;x<0x10000;x++)
|
||||
if(!(CheatComp[x]&CHEATC_NOSHOW))
|
||||
{
|
||||
if(!(CheatRPtrs[x>>10][x]>CheatComp[x]))
|
||||
CheatComp[x]|=CHEATC_EXCLUDED;
|
||||
}
|
||||
}
|
||||
if(type>4)
|
||||
FCEUI_CheatSearchSetCurrentAsOriginal();
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
void FCEU_CheatResetRAM(void);
|
||||
void FCEU_CheatAddRAM(int s, uint32 A, uint8 *p);
|
||||
|
||||
void FCEU_LoadGameCheats(FILE *override);
|
||||
void FCEU_FlushGameCheats(FILE *override, int nosave);
|
||||
void FCEU_ApplyPeriodicCheats(void);
|
||||
void FCEU_PowerCheats(void);
|
|
@ -0,0 +1,33 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "types.h"
|
||||
#include "crc32.h"
|
||||
|
||||
#include <zlib.h>
|
||||
uint32 CalcCRC32(uint32 crc, uint8 *buf, uint32 len)
|
||||
{
|
||||
return(crc32(crc,buf,len));
|
||||
}
|
||||
|
||||
uint32 FCEUI_CRC32(uint32 crc, uint8 *buf, uint32 len)
|
||||
{
|
||||
return(CalcCRC32(crc,buf,len));
|
||||
}
|
|
@ -0,0 +1,535 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2003 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "x6502.h"
|
||||
#include "fceu.h"
|
||||
#include "debug.h"
|
||||
#include "cart.h"
|
||||
|
||||
|
||||
void FCEUI_DumpVid(const char *fname, uint32 start, uint32 end)
|
||||
{
|
||||
FILE *fp=FCEUD_UTF8fopen(fname,"wb");
|
||||
fceuindbg=1;
|
||||
start&=0x1FFF;
|
||||
end&=0x1FFF;
|
||||
for(;start<=end;start++)
|
||||
fputc(VPage[start>>10][start],fp);
|
||||
fclose(fp);
|
||||
fceuindbg=0;
|
||||
}
|
||||
|
||||
void FCEUI_DumpMem(const char *fname, uint32 start, uint32 end)
|
||||
{
|
||||
FILE *fp=FCEUD_UTF8fopen(fname,"wb");
|
||||
fceuindbg=1;
|
||||
for(;start<=end;start++)
|
||||
fputc(ARead[start](start),fp);
|
||||
fclose(fp);
|
||||
fceuindbg=0;
|
||||
}
|
||||
|
||||
void FCEUI_LoadMem(const char *fname, uint32 start, int hl)
|
||||
{
|
||||
int t;
|
||||
|
||||
FILE *fp=FCEUD_UTF8fopen(fname,"rb");
|
||||
while((t=fgetc(fp))>=0)
|
||||
{
|
||||
if(start>0xFFFF) break;
|
||||
if(hl)
|
||||
{
|
||||
extern uint8 *Page[32];
|
||||
if(Page[start/2048])
|
||||
Page[start/2048][start]=t;
|
||||
}
|
||||
else
|
||||
BWrite[start](start,t);
|
||||
start++;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
#ifdef FCEUDEF_DEBUGGER
|
||||
|
||||
static char *fstrings[12]=
|
||||
{
|
||||
"#$%02X", // immediate
|
||||
"$%04X", // RELATIVE(jump)
|
||||
"$%02X", // Z
|
||||
"$%02X,X", // Z,x
|
||||
"$%02X,Y", // Z,y
|
||||
"$%04X", //ABS
|
||||
"$%04X,X", // ABS,x
|
||||
"$%04X,Y", // ABS,y
|
||||
"($%04X)", // IND
|
||||
"($%02X,X)", // INX
|
||||
"($%02X),Y", // INY
|
||||
""
|
||||
};
|
||||
static int flengths[12]={1,1,1,1,1,2,2,2,2,1,1,0};
|
||||
|
||||
#define IMD(x) ((0<<16)|x)
|
||||
#define REL(x) ((1<<16)|x)
|
||||
#define ZP(x) ((2<<16)|x)
|
||||
#define ZPX(x) ((3<<16)|x)
|
||||
#define ZPY(x) ((4<<16)|x)
|
||||
#define ABS(x) ((5<<16)|x)
|
||||
#define ABX(x) ((6<<16)|x)
|
||||
#define ABY(x) ((7<<16)|x)
|
||||
#define IND(x) ((8<<16)|x)
|
||||
#define INX(x) ((9<<16)|x)
|
||||
#define INY(x) ((10<<16)|x)
|
||||
#define IMP(x) ((11<<16)|x)
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
int type; /* 1 for read, 2 for write, 3 for r then write. */
|
||||
int32 modes[10];
|
||||
} OPS;
|
||||
#define NUMOPS 56
|
||||
static OPS optable[NUMOPS]=
|
||||
{
|
||||
{"BRK",0,{IMP(0x00),-1}},
|
||||
{"RTI",0,{IMP(0x40),-1}},
|
||||
{"RTS",0,{IMP(0x60),-1}},
|
||||
{"PHA",2,{IMP(0x48),-1}},
|
||||
{"PHP",2,{IMP(0x08),-1}},
|
||||
{"PLA",1,{IMP(0x68),-1}},
|
||||
{"PLP",1,{IMP(0x28),-1}},
|
||||
{"JMP",0,{ABS(0x4C),IND(0x6C),-1}},
|
||||
{"JSR",0,{ABS(0x20),-1}},
|
||||
{"TAX",0,{IMP(0xAA),-1}},
|
||||
{"TXA",0,{IMP(0x8A),-1}},
|
||||
{"TAY",0,{IMP(0xA8),-1}},
|
||||
{"TYA",0,{IMP(0x98),-1}},
|
||||
{"TSX",0,{IMP(0xBA),-1}},
|
||||
{"TXS",0,{IMP(0x9A),-1}},
|
||||
{"DEX",0,{IMP(0xCA),-1}},
|
||||
{"DEY",0,{IMP(0x88),-1}},
|
||||
{"INX",0,{IMP(0xE8),-1}},
|
||||
{"INY",0,{IMP(0xC8),-1}},
|
||||
{"CLC",0,{IMP(0x18),-1}},
|
||||
{"CLD",0,{IMP(0xD8),-1}},
|
||||
{"CLI",0,{IMP(0x58),-1}},
|
||||
{"CLV",0,{IMP(0xB8),-1}},
|
||||
{"SEC",0,{IMP(0x38),-1}},
|
||||
{"SED",0,{IMP(0xF8),-1}},
|
||||
{"SEI",0,{IMP(0x78),-1}},
|
||||
{"NOP",0,{IMP(0xEA),-1}},
|
||||
{"ASL",1,{IMP(0x0a),ZP(0x06),ZPX(0x16),ABS(0x0E),ABX(0x1E),-1}},
|
||||
{"DEC",3,{ZP(0xc6),ZPX(0xd6),ABS(0xcE),ABX(0xdE),-1}},
|
||||
{"INC",3,{ZP(0xe6),ZPX(0xf6),ABS(0xeE),ABX(0xfE),-1}},
|
||||
{"LSR",3,{IMP(0x4a),ZP(0x46),ZPX(0x56),ABS(0x4E),ABX(0x5E),-1}},
|
||||
{"ROL",3,{IMP(0x2a),ZP(0x26),ZPX(0x36),ABS(0x2E),ABX(0x3E),-1}},
|
||||
{"ROR",3,{IMP(0x6a),ZP(0x66),ZPX(0x76),ABS(0x6E),ABX(0x7E),-1}},
|
||||
{"ADC",1,{IMD(0x69),ZP(0x65),ZPX(0x75),ABS(0x6D),ABX(0x7d),ABY(0x79),
|
||||
INX(0x61),INY(0x71),-1}},
|
||||
{"AND",1,{IMD(0x29),ZP(0x25),ZPX(0x35),ABS(0x2D),ABX(0x3d),ABY(0x39),
|
||||
INX(0x21),INY(0x31),-1}},
|
||||
{"BIT",1,{ZP(0x24),ABS(0x2c),-1}},
|
||||
{"CMP",1,{IMD(0xc9),ZP(0xc5),ZPX(0xd5),ABS(0xcD),ABX(0xdd),ABY(0xd9),
|
||||
INX(0xc1),INY(0xd1),-1}},
|
||||
{"CPX",1,{IMD(0xe0),ZP(0xe4),ABS(0xec),-1}},
|
||||
{"CPY",1,{IMD(0xc0),ZP(0xc4),ABS(0xcc),-1}},
|
||||
{"EOR",1,{IMD(0x49),ZP(0x45),ZPX(0x55),ABS(0x4D),ABX(0x5d),ABY(0x59),
|
||||
INX(0x41),INY(0x51),-1}},
|
||||
{"LDA",1,{IMD(0xa9),ZP(0xa5),ZPX(0xb5),ABS(0xaD),ABX(0xbd),ABY(0xb9),
|
||||
INX(0xa1),INY(0xb1),-1}},
|
||||
{"LDX",1,{IMD(0xa2),ZP(0xa6),ZPY(0xB6),ABS(0xae),ABY(0xbe),-1}},
|
||||
{"LDY",1,{IMD(0xa0),ZP(0xa4),ZPX(0xB4),ABS(0xac),ABX(0xbc),-1}},
|
||||
{"ORA",1,{IMD(0x09),ZP(0x05),ZPX(0x15),ABS(0x0D),ABX(0x1d),ABY(0x19),
|
||||
INX(0x01),INY(0x11),-1}},
|
||||
{"SBC",1,{IMD(0xEB),IMD(0xe9),ZP(0xe5),ZPX(0xf5),ABS(0xeD),ABX(0xfd),ABY(0xf9),
|
||||
INX(0xe1),INY(0xf1),-1}},
|
||||
{"STA",2,{ZP(0x85),ZPX(0x95),ABS(0x8D),ABX(0x9d),ABY(0x99),
|
||||
INX(0x81),INY(0x91),-1}},
|
||||
{"STX",2,{ZP(0x86),ZPY(0x96),ABS(0x8E),-1}},
|
||||
{"STY",2,{ZP(0x84),ZPX(0x94),ABS(0x8C),-1}},
|
||||
{"BCC",1,{REL(0x90),-1}},
|
||||
{"BCS",1,{REL(0xb0),-1}},
|
||||
{"BEQ",1,{REL(0xf0),-1}},
|
||||
{"BNE",1,{REL(0xd0),-1}},
|
||||
{"BMI",1,{REL(0x30),-1}},
|
||||
{"BPL",1,{REL(0x10),-1}},
|
||||
{"BVC",1,{REL(0x50),-1}},
|
||||
{"BVS",1,{REL(0x70),-1}},
|
||||
};
|
||||
|
||||
uint16 FCEUI_Disassemble(void *XA, uint16 a, char *stringo)
|
||||
{
|
||||
X6502 *X=XA;
|
||||
uint8 buf;
|
||||
unsigned int arg;
|
||||
int32 info;
|
||||
int x;
|
||||
int y;
|
||||
|
||||
info=-1;
|
||||
fceuindbg=1;
|
||||
|
||||
buf=ARead[a](a);
|
||||
a++;
|
||||
|
||||
for(x=0;x<NUMOPS;x++)
|
||||
{
|
||||
y=0;
|
||||
while(optable[x].modes[y]>=0)
|
||||
{
|
||||
if((optable[x].modes[y]&0xFF)==buf)
|
||||
{
|
||||
info=optable[x].modes[y];
|
||||
goto endy;
|
||||
}
|
||||
y++;
|
||||
}
|
||||
}
|
||||
|
||||
endy:
|
||||
sprintf(stringo,"%02X ",buf);
|
||||
if(info>=0)
|
||||
{
|
||||
int z=flengths[(info>>16)];
|
||||
|
||||
if(z)
|
||||
{
|
||||
arg=ARead[a](a);
|
||||
sprintf(stringo+strlen(stringo),"%02X ",arg);
|
||||
a++;
|
||||
if(z==2) {arg|=ARead[a](a)<<8;sprintf(stringo+strlen(stringo),"%02X ",arg>>8);a++;}
|
||||
else
|
||||
strcat(stringo," ");
|
||||
|
||||
if((info>>16)==1) /* Relative branch */
|
||||
arg=a+(char)arg;
|
||||
sprintf(stringo+strlen(stringo),"%s ",optable[x].name);
|
||||
sprintf(stringo+strlen(stringo),fstrings[info>>16],arg);
|
||||
/*
|
||||
0 "#$%02X", // immediate
|
||||
1 "$%04X", // RELATIVE(jump)
|
||||
2 "$%02X", // Z
|
||||
3 "$%02X,X", // Z,x
|
||||
4 "$%02X,Y", // Z,y
|
||||
5 "$%04X", //ABS
|
||||
6 "$%04X,X", // ABS,x
|
||||
7 "$%04X,Y", // ABS,y
|
||||
8 "($%04X)", // IND
|
||||
9 "($%02X,X)", // INX
|
||||
10 "($%02X),Y", // INY
|
||||
11 #define IMP(x) ((11<<16)|x)
|
||||
*/
|
||||
{
|
||||
unsigned int tmp;
|
||||
switch(info>>16)
|
||||
{
|
||||
case 2:tmp=arg;
|
||||
if(optable[x].type&1)
|
||||
{
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
}
|
||||
break;
|
||||
case 3:tmp=(arg+X->X)&0xff;
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
if(optable[x].type&1)
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
break;
|
||||
case 4:tmp=(arg+X->Y)&0xff;
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
if(optable[x].type&1)
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
break;
|
||||
case 5:tmp=arg;
|
||||
if(optable[x].type&1)
|
||||
{
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
}
|
||||
break;
|
||||
case 6:tmp=(arg+X->X)&0xffff;
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
if(optable[x].type&1)
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
break;
|
||||
case 7:tmp=(arg+X->Y)&0xffff;
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
if(optable[x].type&1)
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
break;
|
||||
case 8:tmp=ARead[arg](arg)|(ARead[(arg+1)&0xffff]((arg+1)&0xffff)<<8);
|
||||
sprintf(stringo+strlen(stringo)," $%04X",tmp);
|
||||
break;
|
||||
case 9:tmp=(arg+X->X)&0xFF;
|
||||
tmp=ARead[tmp](tmp) | (ARead[(tmp+1)&0xFF]((tmp+1)&0xFF)<<8);
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
if(optable[x].type&1)
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
break;
|
||||
case 10:tmp=ARead[arg](arg) | (ARead[(arg+1)&0xFF]((arg+1)&0xFF)<<8);
|
||||
tmp=(tmp+X->Y)&0xFFFF;
|
||||
sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
|
||||
if(optable[x].type&1)
|
||||
sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
strcat(stringo," ");
|
||||
strcat(stringo,optable[x].name);
|
||||
}
|
||||
}
|
||||
else
|
||||
sprintf(stringo+strlen(stringo)," .db $%02X",buf);
|
||||
fceuindbg=0;
|
||||
return(a);
|
||||
}
|
||||
|
||||
void FCEUI_MemDump(uint16 a, int32 len, void (*callb)(uint16 a, uint8 v))
|
||||
{
|
||||
fceuindbg=1;
|
||||
while(len)
|
||||
{
|
||||
callb(a,ARead[a](a));
|
||||
a++;
|
||||
len--;
|
||||
}
|
||||
fceuindbg=0;
|
||||
}
|
||||
|
||||
uint8 FCEUI_MemSafePeek(uint16 A)
|
||||
{
|
||||
uint8 ret;
|
||||
|
||||
fceuindbg=1;
|
||||
ret=ARead[A](A);
|
||||
fceuindbg=0;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
void FCEUI_MemPoke(uint16 a, uint8 v, int hl)
|
||||
{
|
||||
extern uint8 *Page[32];
|
||||
if(hl)
|
||||
{
|
||||
if(Page[a/2048])
|
||||
Page[a/2048][a]=v;
|
||||
}
|
||||
else
|
||||
BWrite[a](a,v);
|
||||
}
|
||||
|
||||
typedef struct __BPOINT {
|
||||
struct __BPOINT *next;
|
||||
void (*Handler)(X6502 *X, int type, unsigned int A);
|
||||
unsigned int A[2];
|
||||
int type;
|
||||
} BPOINT;
|
||||
|
||||
static BPOINT *BreakPoints=NULL;
|
||||
static BPOINT *LastBP=NULL;
|
||||
|
||||
static void (*CPUHook)(X6502 *)=NULL;
|
||||
|
||||
static int FindBPoint(X6502 *X, int who, unsigned int A)
|
||||
{
|
||||
BPOINT *tmp;
|
||||
|
||||
tmp=BreakPoints;
|
||||
while(tmp)
|
||||
{
|
||||
if(tmp->type&who)
|
||||
{
|
||||
if(tmp->type&BPOINT_PC)
|
||||
if(X->PC!=A) goto don; /* Doesn't match, so go on. */
|
||||
|
||||
if((A>=tmp->A[0]) && (A<=tmp->A[1])) /* Whee, match. */
|
||||
{
|
||||
tmp->Handler(X,tmp->type,A);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
don:
|
||||
tmp=tmp->next;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static uint8 ReadHandler(X6502 *X, unsigned int A)
|
||||
{
|
||||
extern X6502 XSave;
|
||||
|
||||
if(X->preexec)
|
||||
FindBPoint(&XSave,BPOINT_READ,A);
|
||||
return(ARead[A](A));
|
||||
}
|
||||
|
||||
static void WriteHandler(X6502 *X, unsigned int A, uint8 V)
|
||||
{
|
||||
extern X6502 XSave;
|
||||
|
||||
if(X->preexec)
|
||||
FindBPoint(&XSave,BPOINT_WRITE,A);
|
||||
else
|
||||
BWrite[A](A,V);
|
||||
}
|
||||
|
||||
int FCEUI_AddBreakPoint(int type, unsigned int A1, unsigned int A2,
|
||||
void (*Handler)(X6502 *, int type, unsigned int A))
|
||||
{
|
||||
BPOINT *tmp;
|
||||
|
||||
tmp=(BPOINT *)malloc(sizeof(BPOINT));
|
||||
|
||||
tmp->A[0]=A1;
|
||||
tmp->A[1]=A2;
|
||||
tmp->Handler=Handler;
|
||||
tmp->type=type;
|
||||
tmp->next=0;
|
||||
|
||||
if(BreakPoints==NULL)
|
||||
BreakPoints=tmp;
|
||||
else
|
||||
LastBP->next=tmp;
|
||||
|
||||
LastBP=tmp;
|
||||
|
||||
X6502_Debug(CPUHook,ReadHandler,WriteHandler);
|
||||
return(1);
|
||||
}
|
||||
|
||||
int FCEUI_SetBreakPoint(uint32 w, int type, unsigned int A1, unsigned int A2,
|
||||
void (*Handler)(X6502 *, int type, unsigned int A))
|
||||
{
|
||||
uint32 x=0;
|
||||
BPOINT *tmp;
|
||||
|
||||
tmp=BreakPoints;
|
||||
|
||||
while(tmp)
|
||||
{
|
||||
if(w==x)
|
||||
{
|
||||
tmp->type=type;
|
||||
tmp->A[0]=A1;
|
||||
tmp->A[1]=A2;
|
||||
tmp->Handler=Handler;
|
||||
return(1);
|
||||
}
|
||||
x++;
|
||||
tmp=tmp->next;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int FCEUI_GetBreakPoint(uint32 w, int *type, unsigned int *A1, unsigned int *A2,
|
||||
void (**Handler)(X6502 *, int type, unsigned int A))
|
||||
{
|
||||
uint32 x=0;
|
||||
BPOINT *tmp;
|
||||
|
||||
tmp=BreakPoints;
|
||||
|
||||
while(tmp)
|
||||
{
|
||||
if(w==x)
|
||||
{
|
||||
*type=tmp->type;
|
||||
*A1=tmp->A[0];
|
||||
*A2=tmp->A[1];
|
||||
*Handler=tmp->Handler;
|
||||
return(1);
|
||||
}
|
||||
x++;
|
||||
tmp=tmp->next;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int FCEUI_ListBreakPoints(int (*callb)(int type, unsigned int A1, unsigned int A2,
|
||||
void (*Handler)(X6502 *, int type, unsigned int A) ))
|
||||
{
|
||||
BPOINT *tmp;
|
||||
tmp=BreakPoints;
|
||||
while(tmp)
|
||||
{
|
||||
callb(tmp->type,tmp->A[0],tmp->A[1],tmp->Handler);
|
||||
tmp=tmp->next;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
int FCEUI_DeleteBreakPoint(uint32 w)
|
||||
{
|
||||
BPOINT *tmp,*prev=NULL;
|
||||
uint32 x=0;
|
||||
|
||||
tmp=BreakPoints;
|
||||
|
||||
while(tmp)
|
||||
{
|
||||
if(w==x)
|
||||
{
|
||||
if(prev) /* Not the first breakpoint. */
|
||||
{
|
||||
if(tmp->next) /* More breakpoints. */
|
||||
prev->next=tmp->next;
|
||||
else /* This is the last breakpoint. */
|
||||
{
|
||||
prev->next=0;
|
||||
LastBP=prev;
|
||||
}
|
||||
}
|
||||
else /* The first breakpoint. */
|
||||
{
|
||||
if(tmp->next) /* More breakpoints. */
|
||||
BreakPoints=tmp->next;
|
||||
else
|
||||
{
|
||||
BreakPoints=LastBP=0; /* No more breakpoints. */
|
||||
/* Update the CPU hooks. */
|
||||
X6502_Debug(CPUHook,BreakPoints?ReadHandler:0,BreakPoints?WriteHandler:0);
|
||||
}
|
||||
}
|
||||
free(tmp);
|
||||
return(1);
|
||||
}
|
||||
prev=tmp;
|
||||
tmp=tmp->next;
|
||||
x++;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void FCEUI_SetCPUCallback(void (*callb)(X6502 *X))
|
||||
{
|
||||
CPUHook=callb;
|
||||
X6502_Debug(CPUHook,BreakPoints?ReadHandler:0,BreakPoints?WriteHandler:0);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
void FCEUI_DumpMem(const char *fname, uint32 start, uint32 end);
|
||||
void FCEUI_DumpVid(const char *fname, uint32 start, uint32 end);
|
||||
void FCEUI_LoadMem(const char *fname, uint32 start, int hl);
|
||||
|
||||
#ifdef FCEUDEF_DEBUGGER
|
||||
|
||||
/* Type attributes, you can OR them together. */
|
||||
#define BPOINT_READ 1
|
||||
#define BPOINT_WRITE 2
|
||||
#define BPOINT_PC 4
|
||||
|
||||
#include "x6502struct.h"
|
||||
|
||||
void FCEUI_SetCPUCallback(void (*callb)(X6502 *X));
|
||||
int FCEUI_DeleteBreakPoint(uint32 w);
|
||||
int FCEUI_ListBreakPoints(int (*callb)(int type, unsigned int A1, unsigned int A2,
|
||||
void (*Handler)(X6502 *, int type, unsigned int A) ));
|
||||
int FCEUI_GetBreakPoint(uint32 w, int *type, unsigned int *A1, unsigned int *A2,
|
||||
void (**Handler)(X6502 *, int type, unsigned int A));
|
||||
int FCEUI_SetBreakPoint(uint32 w, int type, unsigned int A1, unsigned int A2,
|
||||
void (*Handler)(X6502 *, int type, unsigned int A));
|
||||
int FCEUI_AddBreakPoint(int type, unsigned int A1, unsigned int A2,
|
||||
void (*Handler)(X6502 *, int type, unsigned int A));
|
||||
#endif
|
|
@ -0,0 +1,228 @@
|
|||
void DrawTextLineBG(uint8 *dest)
|
||||
{
|
||||
int x,y;
|
||||
static int otable[7]={81,49,30,17,8,3,0};
|
||||
//100,40,15,10,7,5,2};
|
||||
for(y=0;y<14;y++)
|
||||
{
|
||||
int offs;
|
||||
|
||||
if(y>=7) offs=otable[13-y];
|
||||
else offs=otable[y];
|
||||
|
||||
for(x=offs;x<(256-offs);x++)
|
||||
dest[y*256+x]=(dest[y*256+x]&0x0f)|0xC0;//&=0xe0; //0x80;
|
||||
}
|
||||
}
|
||||
|
||||
static void DrawMessage(void)
|
||||
{
|
||||
if(howlong)
|
||||
{
|
||||
uint8 *t;
|
||||
howlong--;
|
||||
t=XBuf+(FSettings.LastSLine-20)*256;
|
||||
if(t>=XBuf)
|
||||
{
|
||||
DrawTextLineBG(t);
|
||||
DrawTextTrans(t+256*3+(128-strlen(errmsg)*4),256,(uint8 *)errmsg,4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8 fontdata2[2048] =
|
||||
{
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x81,0xa5,0x81,0xbd,0x99,0x81,0x7e,0x7e,0xff,0xdb,0xff,0xc3,0xe7,0xff,0x7e,0x36,0x7f,0x7f,0x7f,0x3e,0x1c,0x08,0x00,0x08,0x1c,0x3e,0x7f,0x3e,0x1c,0x08,0x00,0x1c,0x3e,0x1c,0x7f,0x7f,0x3e,0x1c,0x3e,0x08,0x08,0x1c,0x3e,0x7f,0x3e,0x1c,0x3e,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xf0,0xe0,0xf0,0xbe,0x33,0x33,0x33,0x1e,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0xfc,0xcc,0xfc,0x0c,0x0c,0x0e,0x0f,0x07,0xfe,0xc6,0xfe,0xc6,0xc6,0xe6,0x67,0x03,0x99,0x5a,0x3c,0xe7,0xe7,0x3c,0x5a,0x99,0x01,0x07,0x1f,0x7f,0x1f,0x07,0x01,0x00,0x40,0x70,0x7c,0x7f,0x7c,0x70,0x40,0x00,0x18,0x3c,0x7e,0x18,0x18,0x7e,0x3c,0x18,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x00,0xfe,0xdb,0xdb,0xde,0xd8,0xd8,0xd8,0x00,0x7c,0xc6,0x1c,0x36,0x36,0x1c,0x33,0x1e,0x00,0x00,0x00,0x00,0x7e,0x7e,0x7e,0x00,0x18,0x3c,0x7e,0x18,0x7e,0x3c,0x18,0xff,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x18,0x30,0x7f,0x30,0x18,0x00,0x00,0x00,0x0c,0x06,0x7f,0x06,0x0c,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x7f,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0x7e,0x3c,0x18,0x00,0x00,
|
||||
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x1e,0x0c,0x0c,0x00,0x0c,0x00,0x36,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x36,0x36,0x7f,0x36,0x7f,0x36,0x36,0x00,0x0c,0x3e,0x03,0x1e,0x30,0x1f,0x0c,0x00,0x00,0x63,0x33,0x18,0x0c,0x66,0x63,0x00,0x1c,0x36,0x1c,0x6e,0x3b,0x33,0x6e,0x00,0x06,0x06,0x03,0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0x06,0x06,0x06,0x0c,0x18,0x00,0x06,0x0c,0x18,0x18,0x18,0x0c,0x06,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x0c,0x0c,0x3f,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0c,0x06,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0c,0x00,0x60,0x30,0x18,0x0c,0x06,0x03,0x01,0x00,0x3e,0x63,0x73,0x7b,0x6f,0x67,0x3e,0x00,0x0c,0x0e,0x0c,0x0c,0x0c,0x0c,0x3f,0x00,0x1e,0x33,0x30,0x1c,0x06,0x33,0x3f,0x00,0x1e,0x33,0x30,0x1c,0x30,0x33,0x1e,0x00,0x38,0x3c,0x36,0x33,0x7f,0x30,0x78,0x00,0x3f,0x03,0x1f,0x30,0x30,0x33,0x1e,0x00,0x1c,0x06,0x03,0x1f,0x33,0x33,0x1e,0x00,0x3f,0x33,0x30,0x18,0x0c,0x0c,0x0c,0x00,0x1e,0x33,0x33,0x1e,0x33,0x33,0x1e,0x00,0x1e,0x33,0x33,0x3e,0x30,0x18,0x0e,0x00,0x00,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x06,0x18,0x0c,0x06,0x03,0x06,0x0c,0x18,0x00,0x00,0x00,0x3f,0x00,0x00,0x3f,0x00,0x00,0x06,0x0c,0x18,0x30,0x18,0x0c,0x06,0x00,0x1e,0x33,0x30,0x18,0x0c,0x00,0x0c,0x00,
|
||||
0x3e,0x63,0x7b,0x7b,0x7b,0x03,0x1e,0x00,0x0c,0x1e,0x33,0x33,0x3f,0x33,0x33,0x00,0x3f,0x66,0x66,0x3e,0x66,0x66,0x3f,0x00,0x3c,0x66,0x03,0x03,0x03,0x66,0x3c,0x00,0x1f,0x36,0x66,0x66,0x66,0x36,0x1f,0x00,0x7f,0x46,0x16,0x1e,0x16,0x46,0x7f,0x00,0x7f,0x46,0x16,0x1e,0x16,0x06,0x0f,0x00,0x3c,0x66,0x03,0x03,0x73,0x66,0x7c,0x00,0x33,0x33,0x33,0x3f,0x33,0x33,0x33,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x78,0x30,0x30,0x30,0x33,0x33,0x1e,0x00,0x67,0x66,0x36,0x1e,0x36,0x66,0x67,0x00,0x0f,0x06,0x06,0x06,0x46,0x66,0x7f,0x00,0x63,0x77,0x7f,0x7f,0x6b,0x63,0x63,0x00,0x63,0x67,0x6f,0x7b,0x73,0x63,0x63,0x00,0x1c,0x36,0x63,0x63,0x63,0x36,0x1c,0x00,0x3f,0x66,0x66,0x3e,0x06,0x06,0x0f,0x00,0x1e,0x33,0x33,0x33,0x3b,0x1e,0x38,0x00,0x3f,0x66,0x66,0x3e,0x36,0x66,0x67,0x00,0x1e,0x33,0x07,0x0e,0x38,0x33,0x1e,0x00,0x3f,0x2d,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x33,0x33,0x33,0x33,0x33,0x33,0x3f,0x00,0x33,0x33,0x33,0x33,0x33,0x1e,0x0c,0x00,0x63,0x63,0x63,0x6b,0x7f,0x77,0x63,0x00,0x63,0x63,0x36,0x1c,0x1c,0x36,0x63,0x00,0x33,0x33,0x33,0x1e,0x0c,0x0c,0x1e,0x00,0x7f,0x63,0x31,0x18,0x4c,0x66,0x7f,0x00,0x1e,0x06,0x06,0x06,0x06,0x06,0x1e,0x00,0x03,0x06,0x0c,0x18,0x30,0x60,0x40,0x00,0x1e,0x18,0x18,0x18,0x18,0x18,0x1e,0x00,0x08,0x1c,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
|
||||
0x0c,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x30,0x3e,0x33,0x6e,0x00,0x07,0x06,0x06,0x3e,0x66,0x66,0x3b,0x00,0x00,0x00,0x1e,0x33,0x03,0x33,0x1e,0x00,0x38,0x30,0x30,0x3e,0x33,0x33,0x6e,0x00,0x00,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x1c,0x36,0x06,0x0f,0x06,0x06,0x0f,0x00,0x00,0x00,0x6e,0x33,0x33,0x3e,0x30,0x1f,0x07,0x06,0x36,0x6e,0x66,0x66,0x67,0x00,0x0c,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x30,0x00,0x30,0x30,0x30,0x33,0x33,0x1e,0x07,0x06,0x66,0x36,0x1e,0x36,0x67,0x00,0x0e,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x33,0x7f,0x7f,0x6b,0x63,0x00,0x00,0x00,0x1f,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x1e,0x33,0x33,0x33,0x1e,0x00,0x00,0x00,0x3b,0x66,0x66,0x3e,0x06,0x0f,0x00,0x00,0x6e,0x33,0x33,0x3e,0x30,0x78,0x00,0x00,0x3b,0x6e,0x66,0x06,0x0f,0x00,0x00,0x00,0x3e,0x03,0x1e,0x30,0x1f,0x00,0x08,0x0c,0x3e,0x0c,0x0c,0x2c,0x18,0x00,0x00,0x00,0x33,0x33,0x33,0x33,0x6e,0x00,0x00,0x00,0x33,0x33,0x33,0x1e,0x0c,0x00,0x00,0x00,0x63,0x6b,0x7f,0x7f,0x36,0x00,0x00,0x00,0x63,0x36,0x1c,0x36,0x63,0x00,0x00,0x00,0x33,0x33,0x33,0x3e,0x30,0x1f,0x00,0x00,0x3f,0x19,0x0c,0x26,0x3f,0x00,0x38,0x0c,0x0c,0x07,0x0c,0x0c,0x38,0x00,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00,0x07,0x0c,0x0c,0x38,0x0c,0x0c,0x07,0x00,0x6e,0x3b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1c,0x36,0x63,0x63,0x7f,0x00,
|
||||
0x1e,0x33,0x03,0x33,0x1e,0x18,0x30,0x1e,0x00,0x33,0x00,0x33,0x33,0x33,0x7e,0x00,0x38,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x7e,0xc3,0x3c,0x60,0x7c,0x66,0xfc,0x00,0x33,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x07,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x0c,0x0c,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x00,0x00,0x1e,0x03,0x03,0x1e,0x30,0x1c,0x7e,0xc3,0x3c,0x66,0x7e,0x06,0x3c,0x00,0x33,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x07,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x33,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x3e,0x63,0x1c,0x18,0x18,0x18,0x3c,0x00,0x07,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x63,0x1c,0x36,0x63,0x7f,0x63,0x63,0x00,0x0c,0x0c,0x00,0x1e,0x33,0x3f,0x33,0x00,0x38,0x00,0x3f,0x06,0x1e,0x06,0x3f,0x00,0x00,0x00,0xfe,0x30,0xfe,0x33,0xfe,0x00,0x7c,0x36,0x33,0x7f,0x33,0x33,0x73,0x00,0x1e,0x33,0x00,0x1e,0x33,0x33,0x1e,0x00,0x00,0x33,0x00,0x1e,0x33,0x33,0x1e,0x00,0x00,0x07,0x00,0x1e,0x33,0x33,0x1e,0x00,0x1e,0x33,0x00,0x33,0x33,0x33,0x7e,0x00,0x00,0x07,0x00,0x33,0x33,0x33,0x7e,0x00,0x00,0x33,0x00,0x33,0x33,0x3e,0x30,0x1f,0xc3,0x18,0x3c,0x66,0x66,0x3c,0x18,0x00,0x33,0x00,0x33,0x33,0x33,0x33,0x1e,0x00,0x18,0x18,0x7e,0x03,0x03,0x7e,0x18,0x18,0x1c,0x36,0x26,0x0f,0x06,0x67,0x3f,0x00,0x33,0x33,0x1e,0x3f,0x0c,0x3f,0x0c,0x0c,0x1f,0x33,0x33,0x5f,0x63,0xf3,0x63,0xe3,0x70,0xd8,0x18,0x3c,0x18,0x18,0x1b,0x0e,
|
||||
0x38,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x1c,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x38,0x00,0x1e,0x33,0x33,0x1e,0x00,0x00,0x38,0x00,0x33,0x33,0x33,0x7e,0x00,0x00,0x1f,0x00,0x1f,0x33,0x33,0x33,0x00,0x3f,0x00,0x33,0x37,0x3f,0x3b,0x33,0x00,0x3c,0x36,0x36,0x7c,0x00,0x7e,0x00,0x00,0x1c,0x36,0x36,0x1c,0x00,0x3e,0x00,0x00,0x0c,0x00,0x0c,0x06,0x03,0x33,0x1e,0x00,0x00,0x00,0x00,0x3f,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x30,0x00,0x00,0xc3,0x63,0x33,0x7b,0xcc,0x66,0x33,0xf0,0xc3,0x63,0x33,0xdb,0xec,0xf6,0xf3,0xc0,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x00,0x00,0xcc,0x66,0x33,0x66,0xcc,0x00,0x00,0x00,0x33,0x66,0xcc,0x66,0x33,0x00,0x00,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xdb,0xee,0xdb,0x77,0xdb,0xee,0xdb,0x77,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x6c,0x6c,0x6c,0x6c,0x6f,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x7f,0x6c,0x6c,0x6c,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x6c,0x6c,0x6f,0x60,0x6f,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x7f,0x60,0x6f,0x6c,0x6c,0x6c,0x6c,0x6c,0x6f,0x60,0x7f,0x00,0x00,0x00,0x6c,0x6c,0x6c,0x6c,0x7f,0x00,0x00,0x00,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,
|
||||
0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x6c,0x6c,0x6c,0x6c,0xec,0x6c,0x6c,0x6c,0x6c,0x6c,0xec,0x0c,0xfc,0x00,0x00,0x00,0x00,0x00,0xfc,0x0c,0xec,0x6c,0x6c,0x6c,0x6c,0x6c,0xef,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xef,0x6c,0x6c,0x6c,0x6c,0x6c,0xec,0x0c,0xec,0x6c,0x6c,0x6c,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x6c,0x6c,0xef,0x00,0xef,0x6c,0x6c,0x6c,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x6c,0x6c,0x6c,0x6c,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xff,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0xfc,0x00,0x00,0x00,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xfc,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0xff,0x6c,0x6c,0x6c,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
|
||||
0x00,0x00,0x6e,0x3b,0x13,0x3b,0x6e,0x00,0x00,0x1e,0x33,0x1f,0x33,0x1f,0x03,0x03,0x00,0x3f,0x33,0x03,0x03,0x03,0x03,0x00,0x00,0x7f,0x36,0x36,0x36,0x36,0x36,0x00,0x3f,0x33,0x06,0x0c,0x06,0x33,0x3f,0x00,0x00,0x00,0x7e,0x1b,0x1b,0x1b,0x0e,0x00,0x00,0x66,0x66,0x66,0x66,0x3e,0x06,0x03,0x00,0x6e,0x3b,0x18,0x18,0x18,0x18,0x00,0x3f,0x0c,0x1e,0x33,0x33,0x1e,0x0c,0x3f,0x1c,0x36,0x63,0x7f,0x63,0x36,0x1c,0x00,0x1c,0x36,0x63,0x63,0x36,0x36,0x77,0x00,0x38,0x0c,0x18,0x3e,0x33,0x33,0x1e,0x00,0x00,0x00,0x7e,0xdb,0xdb,0x7e,0x00,0x00,0x60,0x30,0x7e,0xdb,0xdb,0x7e,0x06,0x03,0x1c,0x06,0x03,0x1f,0x03,0x06,0x1c,0x00,0x1e,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x3f,0x00,0x3f,0x00,0x3f,0x00,0x00,0x0c,0x0c,0x3f,0x0c,0x0c,0x00,0x3f,0x00,0x06,0x0c,0x18,0x0c,0x06,0x00,0x3f,0x00,0x18,0x0c,0x06,0x0c,0x18,0x00,0x3f,0x00,0x70,0xd8,0xd8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x0e,0x0c,0x0c,0x00,0x3f,0x00,0x0c,0x0c,0x00,0x00,0x6e,0x3b,0x00,0x6e,0x3b,0x00,0x00,0x1c,0x36,0x36,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0xf0,0x30,0x30,0x30,0x37,0x36,0x3c,0x38,0x1e,0x36,0x36,0x36,0x36,0x00,0x00,0x00,0x0e,0x18,0x0c,0x06,0x1e,0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x3c,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||
};
|
||||
|
||||
void DrawTextTrans(uint8 *dest, uint32 width, uint8 *textmsg, uint8 fgcolor)
|
||||
{
|
||||
uint8 length=strlen((char *)textmsg);
|
||||
uint8 x;
|
||||
uint8 y;
|
||||
uint8 z;
|
||||
|
||||
for(x=0;x<length;x++)
|
||||
for(y=0;y<8;y++)
|
||||
for(z=0;z<8;z++)
|
||||
if((fontdata2[(textmsg[x]<<3)+y]>>z)&1) dest[y*width+(x<<3)+z]=fgcolor;
|
||||
}
|
||||
|
||||
static uint8 sstat[2541] =
|
||||
{
|
||||
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
|
||||
0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,
|
||||
0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x83,0x83,0x83,
|
||||
0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x80,0x83,
|
||||
0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,
|
||||
0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,
|
||||
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
|
||||
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
|
||||
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x81,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
|
||||
0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
|
||||
0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,
|
||||
0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,
|
||||
0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,
|
||||
0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,
|
||||
0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
|
||||
};
|
||||
|
||||
void FCEU_DrawNumberRow(uint8 *XBuf, int *nstatus, int cur)
|
||||
{
|
||||
uint8 *XBaf;
|
||||
int z,x,y;
|
||||
|
||||
XBaf=XBuf - 4 + (FSettings.LastSLine-34)*256;
|
||||
if(XBaf>=XBuf)
|
||||
for(z=1;z<11;z++)
|
||||
{
|
||||
if(nstatus[z%10])
|
||||
{
|
||||
for(y=0;y<13;y++)
|
||||
for(x=0;x<21;x++)
|
||||
XBaf[y*256+x+z*21+z]=sstat[y*21+x+(z-1)*21*12]^0x80;
|
||||
} else {
|
||||
for(y=0;y<13;y++)
|
||||
for(x=0;x<21;x++)
|
||||
if(sstat[y*21+x+(z-1)*21*12]!=0x83)
|
||||
XBaf[y*256+x+z*21+z]=sstat[y*21+x+(z-1)*21*12]^0x80;
|
||||
|
||||
else
|
||||
XBaf[y*256+x+z*21+z]=(XBaf[y*256+x+z*21+z]&0xF)|0xC0;
|
||||
}
|
||||
if(cur==z%10)
|
||||
{
|
||||
for(x=0;x<21;x++)
|
||||
XBaf[x+z*21+z*1]=4;
|
||||
for(x=1;x<12;x++)
|
||||
{
|
||||
XBaf[256*x+z*21+z*1]=
|
||||
XBaf[256*x+z*21+z*1+20]=4;
|
||||
}
|
||||
for(x=0;x<21;x++)
|
||||
XBaf[12*256+x+z*21+z*1]=4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint8 play_slines[]=
|
||||
{
|
||||
0, 0, 1,
|
||||
1, 0, 2,
|
||||
2, 0, 3,
|
||||
3, 0, 4,
|
||||
4, 0, 5,
|
||||
5, 0, 6,
|
||||
6, 0, 7,
|
||||
7, 0, 8,
|
||||
8, 0, 7,
|
||||
9, 0, 6,
|
||||
10, 0, 5,
|
||||
11, 0, 4,
|
||||
12, 0, 3,
|
||||
13, 0, 2,
|
||||
14, 0, 1,
|
||||
99,
|
||||
};
|
||||
|
||||
static uint8 record_slines[]=
|
||||
{
|
||||
0, 5, 9,
|
||||
1, 3, 11,
|
||||
2, 2, 12,
|
||||
3, 1, 13,
|
||||
4, 1, 13,
|
||||
5, 0, 14,
|
||||
6, 0, 14,
|
||||
7, 0, 14,
|
||||
8, 0, 14,
|
||||
9, 0, 14,
|
||||
10, 1, 13,
|
||||
11, 1, 13,
|
||||
12, 2, 12,
|
||||
13, 3, 11,
|
||||
14, 5, 9,
|
||||
99,
|
||||
};
|
||||
|
||||
static uint8 pause_slines[]=
|
||||
{
|
||||
0, 2, 6,
|
||||
1, 2, 6,
|
||||
2, 2, 6,
|
||||
3, 2, 6,
|
||||
4, 2, 6,
|
||||
5, 2, 6,
|
||||
6, 2, 6,
|
||||
7, 2, 6,
|
||||
8, 2, 6,
|
||||
9, 2, 6,
|
||||
10, 2, 6,
|
||||
11, 2, 6,
|
||||
12, 2, 6,
|
||||
13, 2, 6,
|
||||
14, 2, 6,
|
||||
|
||||
0, 9, 13,
|
||||
1, 9, 13,
|
||||
2, 9, 13,
|
||||
3, 9, 13,
|
||||
4, 9, 13,
|
||||
5, 9, 13,
|
||||
6, 9, 13,
|
||||
7, 9, 13,
|
||||
8, 9, 13,
|
||||
9, 9, 13,
|
||||
10, 9, 13,
|
||||
11, 9, 13,
|
||||
12, 9, 13,
|
||||
13, 9, 13,
|
||||
14, 9, 13,
|
||||
99,
|
||||
};
|
||||
|
||||
static uint8 no_slines[]=
|
||||
{
|
||||
99
|
||||
};
|
||||
|
||||
static uint8* sline_icons[4]=
|
||||
{
|
||||
no_slines,
|
||||
play_slines,
|
||||
record_slines,
|
||||
pause_slines
|
||||
};
|
||||
|
||||
void FCEU_DrawRecordingStatusN(uint8* XBuf, int n)
|
||||
{
|
||||
uint8* slines=sline_icons[n];
|
||||
int i;
|
||||
|
||||
XBuf += (FSettings.LastSLine-28)*256 + 240 + 255;
|
||||
for(i=0; slines[i]!=99; i+=3)
|
||||
{
|
||||
int y=slines[i];
|
||||
uint8* dest=XBuf+(y*256);
|
||||
int x;
|
||||
for(x=slines[i+1]; x!=slines[i+2]; ++x)
|
||||
dest[x]=0;
|
||||
}
|
||||
|
||||
XBuf -= 255;
|
||||
for(i=0; slines[i]!=99; i+=3)
|
||||
{
|
||||
int y=slines[i];
|
||||
uint8* dest=XBuf+(y*256);
|
||||
int x;
|
||||
for(x=slines[i+1]; x!=slines[i+2]; ++x)
|
||||
dest[x]=4;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,317 @@
|
|||
#ifndef __DRIVER_H_
|
||||
#define __DRIVER_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "types.h"
|
||||
#include "git.h"
|
||||
#include "debug.h"
|
||||
|
||||
FILE *FCEUD_UTF8fopen(const char *fn, const char *mode);
|
||||
|
||||
/* This makes me feel dirty for some reason. */
|
||||
void FCEU_printf(char *format, ...);
|
||||
#define FCEUI_printf FCEU_printf
|
||||
|
||||
/* Video interface */
|
||||
void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b);
|
||||
void FCEUD_GetPalette(uint8 i,uint8 *r, uint8 *g, uint8 *b);
|
||||
|
||||
/* Displays an error. Can block or not. */
|
||||
void FCEUD_PrintError(char *s);
|
||||
void FCEUD_Message(char *s);
|
||||
|
||||
#ifdef NETWORK
|
||||
/* Network interface */
|
||||
|
||||
/* Call only when a game is loaded. */
|
||||
int FCEUI_NetplayStart(int nlocal, int divisor);
|
||||
|
||||
/* Call when network play needs to stop. */
|
||||
void FCEUI_NetplayStop(void);
|
||||
|
||||
/* Note: YOU MUST NOT CALL ANY FCEUI_* FUNCTIONS WHILE IN FCEUD_SendData() or
|
||||
FCEUD_RecvData().
|
||||
*/
|
||||
|
||||
/* Return 0 on failure, 1 on success. */
|
||||
int FCEUD_SendData(void *data, uint32 len);
|
||||
int FCEUD_RecvData(void *data, uint32 len);
|
||||
|
||||
/* Display text received over the network. */
|
||||
void FCEUD_NetplayText(uint8 *text);
|
||||
|
||||
/* Encode and send text over the network. */
|
||||
void FCEUI_NetplayText(uint8 *text);
|
||||
|
||||
/* Called when a fatal error occurred and network play can't continue. This function
|
||||
should call FCEUI_NetplayStop() after it has deinitialized the network on the driver
|
||||
side.
|
||||
*/
|
||||
void FCEUD_NetworkClose(void);
|
||||
#endif
|
||||
|
||||
int FCEUI_BeginWaveRecord(char *fn);
|
||||
int FCEUI_EndWaveRecord(void);
|
||||
|
||||
void FCEUI_ResetNES(void);
|
||||
void FCEUI_PowerNES(void);
|
||||
|
||||
void FCEUI_NTSCSELHUE(void);
|
||||
void FCEUI_NTSCSELTINT(void);
|
||||
void FCEUI_NTSCDEC(void);
|
||||
void FCEUI_NTSCINC(void);
|
||||
void FCEUI_GetNTSCTH(int *tint, int *hue);
|
||||
void FCEUI_SetNTSCTH(int n, int tint, int hue);
|
||||
|
||||
void FCEUI_SetInput(int port, int type, void *ptr, int attrib);
|
||||
void FCEUI_SetInputFC(int type, void *ptr, int attrib);
|
||||
void FCEUI_DisableFourScore(int s);
|
||||
|
||||
#define SI_NONE 0
|
||||
#define SI_GAMEPAD 1
|
||||
#define SI_ZAPPER 2
|
||||
#define SI_POWERPADA 3
|
||||
#define SI_POWERPADB 4
|
||||
#define SI_ARKANOID 5
|
||||
|
||||
#define SIFC_NONE 0
|
||||
#define SIFC_ARKANOID 1
|
||||
#define SIFC_SHADOW 2
|
||||
#define SIFC_4PLAYER 3
|
||||
#define SIFC_FKB 4
|
||||
#define SIFC_SUBORKB 5
|
||||
#define SIFC_HYPERSHOT 6
|
||||
#define SIFC_MAHJONG 7
|
||||
#define SIFC_QUIZKING 8
|
||||
#define SIFC_FTRAINERA 9
|
||||
#define SIFC_FTRAINERB 10
|
||||
#define SIFC_OEKAKIDS 11
|
||||
#define SIFC_BWORLD 12
|
||||
#define SIFC_TOPRIDER 13
|
||||
|
||||
#define SIS_NONE 0
|
||||
#define SIS_DATACH 1
|
||||
#define SIS_NWC 2
|
||||
#define SIS_VSUNISYSTEM 3
|
||||
#define SIS_NSF 4
|
||||
|
||||
/* New interface functions */
|
||||
|
||||
/* 0 to order screen snapshots numerically(0.png), 1 to order them file base-numerically(smb3-0.png). */
|
||||
void FCEUI_SetSnapName(int a);
|
||||
|
||||
/* 0 to keep 8-sprites limitation, 1 to remove it */
|
||||
void FCEUI_DisableSpriteLimitation(int a);
|
||||
|
||||
/* -1 = no change, 0 = show, 1 = hide, 2 = internal toggle */
|
||||
void FCEUI_SetRenderDisable(int sprites, int bg);
|
||||
|
||||
/* name=path and file to load. returns 0 on failure, 1 on success */
|
||||
FCEUGI *FCEUI_LoadGame(const char *name, int OverwriteVidMode);
|
||||
|
||||
/* allocates memory. 0 on failure, 1 on success. */
|
||||
int FCEUI_Initialize(void);
|
||||
|
||||
/* Emulates a frame. */
|
||||
void FCEUI_Emulate(uint8 **, int32 **, int32 *, int);
|
||||
|
||||
/* Closes currently loaded game */
|
||||
void FCEUI_CloseGame(void);
|
||||
|
||||
/* Deallocates all allocated memory. Call after FCEUI_Emulate() returns. */
|
||||
void FCEUI_Kill(void);
|
||||
|
||||
/* Enable/Disable game genie. a=0 disable, a=1 enable */
|
||||
void FCEUI_SetGameGenie(int a);
|
||||
|
||||
/* Set video system a=0 NTSC, a=1 PAL */
|
||||
void FCEUI_SetVidSystem(int a);
|
||||
|
||||
/* Convenience function; returns currently emulated video system(0=NTSC, 1=PAL). */
|
||||
int FCEUI_GetCurrentVidSystem(int *slstart, int *slend);
|
||||
|
||||
#ifdef FRAMESKIP
|
||||
/* Should be called from FCEUD_BlitScreen(). Specifies how many frames
|
||||
to skip until FCEUD_BlitScreen() is called. FCEUD_BlitScreenDummy()
|
||||
will be called instead of FCEUD_BlitScreen() when when a frame is skipped.
|
||||
*/
|
||||
void FCEUI_FrameSkip(int x);
|
||||
#endif
|
||||
|
||||
/* First and last scanlines to render, for ntsc and pal emulation. */
|
||||
void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall);
|
||||
|
||||
/* Sets the base directory(save states, snapshots, etc. are saved in directories
|
||||
below this directory. */
|
||||
void FCEUI_SetBaseDirectory(char *dir);
|
||||
|
||||
/* Tells FCE Ultra to copy the palette data pointed to by pal and use it.
|
||||
Data pointed to by pal needs to be 64*3 bytes in length.
|
||||
*/
|
||||
void FCEUI_SetPaletteArray(uint8 *pal);
|
||||
|
||||
/* Sets up sound code to render sound at the specified rate, in samples
|
||||
per second. Only sample rates of 44100, 48000, and 96000 are currently
|
||||
supported.
|
||||
If "Rate" equals 0, sound is disabled.
|
||||
*/
|
||||
void FCEUI_Sound(int Rate);
|
||||
void FCEUI_SetSoundVolume(uint32 volume);
|
||||
void FCEUI_SetSoundQuality(int quality);
|
||||
|
||||
void FCEUD_SoundToggle(void);
|
||||
void FCEUD_SoundVolumeAdjust(int);
|
||||
|
||||
int FCEUI_SelectState(int, int);
|
||||
|
||||
/* "fname" overrides the default save state filename code if non-NULL. */
|
||||
void FCEUI_SaveState(char *fname);
|
||||
void FCEUI_LoadState(char *fname);
|
||||
|
||||
void FCEUD_SaveStateAs(void);
|
||||
void FCEUD_LoadStateFrom(void);
|
||||
|
||||
#define MOVIE_FLAG_FROM_RESET (1<<1)
|
||||
#define MOVIE_FLAG_PAL (1<<2)
|
||||
#define MOVIE_FLAG_FROM_POWERON (1<<3) // value is temporary onle, gets converted to reset
|
||||
#define MOVIE_MAX_METADATA 512
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int movie_version; // version of the movie format in the file
|
||||
uint32 num_frames;
|
||||
uint32 rerecord_count;
|
||||
uint8 flags;
|
||||
int read_only;
|
||||
uint32 emu_version_used; // 9813 = 0.98.13
|
||||
char* metadata; // caller-supplied buffer to store metadata. can be NULL.
|
||||
int metadata_size; // size of the buffer pointed to by metadata
|
||||
uint8 md5_of_rom_used[16];
|
||||
int md5_of_rom_used_present; // v1 movies don't have md5 info available
|
||||
char* name_of_rom_used; // caller-supplied buffer to store metadata. can be NULL.
|
||||
int name_of_rom_used_size; // size of the buffer pointer to by name_of_rom_used
|
||||
} MOVIE_INFO;
|
||||
|
||||
int FCEUI_SelectMovie(int, int);
|
||||
void FCEUI_SaveMovie(char *fname, uint8 flags, const char* metadata);
|
||||
void FCEUI_LoadMovie(char *fname, int read_only, int _stopframe);
|
||||
void FCEUI_StopMovie(void);
|
||||
int FCEUI_IsMovieActive(void);
|
||||
int FCEUI_MovieGetInfo(const char* fname, MOVIE_INFO* /* [in, out] */ info);
|
||||
char* FCEUI_MovieGetCurrentName(int addSlotNumber);
|
||||
void FCEUI_MovieToggleReadOnly(void);
|
||||
void FCEUI_MovieToggleFrameDisplay(void);
|
||||
void FCEUI_ToggleInputDisplay(void);
|
||||
|
||||
void FCEUD_MovieRecordTo(void);
|
||||
void FCEUD_MovieReplayFrom(void);
|
||||
|
||||
int32 FCEUI_GetDesiredFPS(void);
|
||||
void FCEUI_SaveSnapshot(void);
|
||||
void FCEU_DispMessage(char *format, ...);
|
||||
#define FCEUI_DispMessage FCEU_DispMessage
|
||||
|
||||
int FCEUI_DecodePAR(const char *code, uint16 *a, uint8 *v, int *c, int *type);
|
||||
int FCEUI_DecodeGG(const char *str, uint16 *a, uint8 *v, int *c);
|
||||
int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type);
|
||||
int FCEUI_DelCheat(uint32 which);
|
||||
int FCEUI_ToggleCheat(uint32 which);
|
||||
|
||||
int32 FCEUI_CheatSearchGetCount(void);
|
||||
void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a, uint8 last, uint8 current));
|
||||
void FCEUI_CheatSearchGet(int (*callb)(uint32 a, uint8 last, uint8 current, void *data), void *data);
|
||||
void FCEUI_CheatSearchBegin(void);
|
||||
void FCEUI_CheatSearchEnd(int type, uint8 v1, uint8 v2);
|
||||
void FCEUI_ListCheats(int (*callb)(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data), void *data);
|
||||
|
||||
int FCEUI_GetCheat(uint32 which, char **name, uint32 *a, uint8 *v, int *compare, int *s, int *type);
|
||||
int FCEUI_SetCheat(uint32 which, const char *name, int32 a, int32 v, int compare,int s, int type);
|
||||
|
||||
void FCEUI_CheatSearchShowExcluded(void);
|
||||
void FCEUI_CheatSearchSetCurrentAsOriginal(void);
|
||||
|
||||
#define FCEUIOD_STATE 0
|
||||
#define FCEUIOD_SNAPS 1
|
||||
#define FCEUIOD_NV 2
|
||||
#define FCEUIOD_CHEATS 3
|
||||
#define FCEUIOD_MISC 4
|
||||
|
||||
#define FCEUIOD__COUNT 5
|
||||
|
||||
void FCEUI_SetDirOverride(int which, char *n);
|
||||
|
||||
void FCEUI_MemDump(uint16 a, int32 len, void (*callb)(uint16 a, uint8 v));
|
||||
uint8 FCEUI_MemSafePeek(uint16 A);
|
||||
void FCEUI_MemPoke(uint16 a, uint8 v, int hl);
|
||||
void FCEUI_NMI(void);
|
||||
void FCEUI_IRQ(void);
|
||||
uint16 FCEUI_Disassemble(void *XA, uint16 a, char *stringo);
|
||||
void FCEUI_GetIVectors(uint16 *reset, uint16 *irq, uint16 *nmi);
|
||||
|
||||
uint32 FCEUI_CRC32(uint32 crc, uint8 *buf, uint32 len);
|
||||
|
||||
void FCEUI_ToggleTileView(void);
|
||||
void FCEUI_SetLowPass(int q);
|
||||
|
||||
void FCEUI_NSFSetVis(int mode);
|
||||
int FCEUI_NSFChange(int amount);
|
||||
int FCEUI_NSFGetInfo(uint8 *name, uint8 *artist, uint8 *copyright, int maxlen);
|
||||
|
||||
void FCEUI_VSUniToggleDIPView(void);
|
||||
void FCEUI_VSUniToggleDIP(int w);
|
||||
uint8 FCEUI_VSUniGetDIPs(void);
|
||||
void FCEUI_VSUniSetDIP(int w, int state);
|
||||
void FCEUI_VSUniCoin(void);
|
||||
|
||||
int FCEUI_FDSInsert(void);
|
||||
//int FCEUI_FDSEject(void);
|
||||
void FCEUI_FDSSelect(void);
|
||||
|
||||
int FCEUI_DatachSet(const uint8 *rcode);
|
||||
|
||||
int FCEUI_EmulationPaused(void);
|
||||
void FCEUI_ToggleEmulationPause(void);
|
||||
void FCEUI_FrameAdvance(void);
|
||||
|
||||
/* AVI Output */
|
||||
int FCEUI_AviBegin(const char* fname);
|
||||
void FCEUI_AviEnd(void);
|
||||
void FCEUI_AviVideoUpdate(const unsigned char* buffer);
|
||||
void FCEUI_AviSoundUpdate(void* soundData, int soundLen);
|
||||
int FCEUI_AviIsRecording(void);
|
||||
|
||||
void FCEUD_AviRecordTo(void);
|
||||
void FCEUD_AviStop(void);
|
||||
|
||||
/* Command input mapping */
|
||||
typedef int TestCommandState(int cmd);
|
||||
void FCEUI_HandleEmuCommands(TestCommandState* testfn);
|
||||
void FCEUD_CmdOpen(void);
|
||||
|
||||
/* Emulation speed */
|
||||
enum EMUSPEED_SET
|
||||
{
|
||||
EMUSPEED_SLOWEST=0,
|
||||
EMUSPEED_SLOWER,
|
||||
EMUSPEED_NORMAL,
|
||||
EMUSPEED_FASTER,
|
||||
EMUSPEED_FASTEST
|
||||
};
|
||||
void FCEUD_SetEmulationSpeed(int cmd);
|
||||
void FCEUD_TurboOn(void);
|
||||
void FCEUD_TurboOff(void);
|
||||
|
||||
int FCEUD_ShowStatusIcon(void);
|
||||
void FCEUD_ToggleStatusIcon(void);
|
||||
void FCEUD_HideMenuToggle(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __DRIVER_H_ */
|
|
@ -0,0 +1 @@
|
|||
fceu_SOURCES += drivers/common/args.c drivers/common/cheat.c drivers/common/config.c drivers/common/vidblit.c drivers/common/hq2x.c drivers/common/hq3x.c drivers/common/scale2x.c drivers/common/scale3x.c drivers/common/scalebit.c
|
|
@ -0,0 +1,98 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/****************************************************************/
|
||||
/* FCE Ultra */
|
||||
/* */
|
||||
/* This file contains code for parsing command-line */
|
||||
/* options. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "args.h"
|
||||
|
||||
void ParseEA(int x, int argc, char *argv[], ARGPSTRUCT *argsps)
|
||||
{
|
||||
int y=0;
|
||||
|
||||
do
|
||||
{
|
||||
if(!argsps[y].name)
|
||||
{
|
||||
ParseEA(x,argc,argv,(ARGPSTRUCT*)argsps[y].var);
|
||||
y++;
|
||||
continue;
|
||||
}
|
||||
if(!strcmp(argv[x],argsps[y].name)) // A match.
|
||||
{
|
||||
if(argsps[y].subs)
|
||||
{
|
||||
if((x+1)>=argc)
|
||||
break;
|
||||
if(argsps[y].substype&0x2000)
|
||||
{
|
||||
((void (*)(char *))argsps[y].subs)(argv[x+1]);
|
||||
}
|
||||
else if(argsps[y].substype&0x8000)
|
||||
{
|
||||
*(int *)argsps[y].subs&=~(argsps[y].substype&(~0x8000));
|
||||
*(int *)argsps[y].subs|=atoi(argv[x+1])?(argsps[y].substype&(~0x8000)):0;
|
||||
}
|
||||
else
|
||||
switch(argsps[y].substype&(~0x4000))
|
||||
{
|
||||
case 0: // Integer
|
||||
*(int *)argsps[y].subs=atoi(argv[x+1]);
|
||||
break;
|
||||
case 2: // Double float
|
||||
*(double *)argsps[y].subs=atof(argv[x+1]);
|
||||
break;
|
||||
case 1: // String
|
||||
if(argsps[y].substype&0x4000)
|
||||
{
|
||||
if(*(char **)argsps[y].subs)
|
||||
free(*(char **)argsps[y].subs);
|
||||
if(!( *(char **)argsps[y].subs=(char*)malloc(strlen(argv[x+1])+1) ))
|
||||
break;
|
||||
}
|
||||
strcpy(*(char **)argsps[y].subs,argv[x+1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(argsps[y].var)
|
||||
*argsps[y].var=1;
|
||||
}
|
||||
y++;
|
||||
} while(argsps[y].var || argsps[y].subs);
|
||||
}
|
||||
|
||||
void ParseArguments(int argc, char *argv[], ARGPSTRUCT *argsps)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=0;x<argc;x++)
|
||||
ParseEA(x,argc,argv,argsps);
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#ifndef _DRIVERS_ARGH
|
||||
typedef struct {
|
||||
char *name;
|
||||
int *var;
|
||||
|
||||
void *subs;
|
||||
int substype;
|
||||
} ARGPSTRUCT;
|
||||
|
||||
void ParseArguments(int argc, char *argv[], ARGPSTRUCT *argsps);
|
||||
#define _DRIVERS_ARGH
|
||||
#endif
|
|
@ -0,0 +1,523 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "../../driver.h"
|
||||
|
||||
static void GetString(char *s, int max)
|
||||
{
|
||||
int x;
|
||||
fgets(s,max,stdin);
|
||||
|
||||
for(x=0;x<max;x++)
|
||||
if(s[x]=='\n')
|
||||
{
|
||||
s[x]=0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get unsigned 16-bit integer from stdin in hex. */
|
||||
static uint32 GetH16(unsigned int def)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
fgets(buf,32,stdin);
|
||||
if(buf[0]=='\n')
|
||||
return(def);
|
||||
if(buf[0]=='$')
|
||||
sscanf(buf+1,"%04x",&def);
|
||||
else
|
||||
sscanf(buf,"%04x",&def);
|
||||
return def;
|
||||
}
|
||||
|
||||
/* Get unsigned 8-bit integer from stdin in decimal. */
|
||||
static uint8 Get8(unsigned int def)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
fgets(buf,32,stdin);
|
||||
if(buf[0]=='\n')
|
||||
return(def);
|
||||
sscanf(buf,"%u",&def);
|
||||
return def;
|
||||
}
|
||||
|
||||
static int GetI(int def)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
fgets(buf,32,stdin);
|
||||
if(buf[0]=='\n')
|
||||
return(def);
|
||||
sscanf(buf,"%d",&def);
|
||||
return def;
|
||||
}
|
||||
|
||||
static int GetYN(int def)
|
||||
{
|
||||
char buf[32];
|
||||
printf("(Y/N)[%s]: ",def?"Y":"N");
|
||||
fgets(buf,32,stdin);
|
||||
if(buf[0]=='y' || buf[0]=='Y')
|
||||
return(1);
|
||||
if(buf[0]=='n' || buf[0]=='N')
|
||||
return(0);
|
||||
return(def);
|
||||
}
|
||||
|
||||
/*
|
||||
** Begin list code.
|
||||
**
|
||||
*/
|
||||
static int listcount;
|
||||
static int listids[16];
|
||||
static int listsel;
|
||||
static int mordoe;
|
||||
|
||||
void BeginListShow(void)
|
||||
{
|
||||
listcount=0;
|
||||
listsel=-1;
|
||||
mordoe=0;
|
||||
}
|
||||
|
||||
/* Hmm =0 for in list choices, hmm=1 for end of list choices. */
|
||||
/* Return equals 0 to continue, -1 to stop, otherwise a number. */
|
||||
int ListChoice(int hmm)
|
||||
{
|
||||
char buf[32];
|
||||
|
||||
if(!hmm)
|
||||
{
|
||||
int num=0;
|
||||
|
||||
tryagain:
|
||||
printf(" <'Enter' to continue, (S)top, or enter a number.> ");
|
||||
fgets(buf,32,stdin);
|
||||
if(buf[0]=='s' || buf[0]=='S') return(-1);
|
||||
if(buf[0]=='\n') return(0);
|
||||
if(!sscanf(buf,"%d",&num))
|
||||
return(0);
|
||||
if(num<1) goto tryagain;
|
||||
return(num);
|
||||
}
|
||||
else
|
||||
{
|
||||
int num=0;
|
||||
|
||||
tryagain2:
|
||||
printf(" <'Enter' to make no selection or enter a number.> ");
|
||||
fgets(buf,32,stdin);
|
||||
if(buf[0]=='\n') return(0);
|
||||
if(!sscanf(buf,"%d",&num))
|
||||
return(0);
|
||||
if(num<1) goto tryagain2;
|
||||
return(num);
|
||||
}
|
||||
}
|
||||
|
||||
int EndListShow(void)
|
||||
{
|
||||
if(mordoe)
|
||||
{
|
||||
int r=ListChoice(1);
|
||||
if(r>0 && r<=listcount)
|
||||
listsel=listids[r-1];
|
||||
}
|
||||
return(listsel);
|
||||
}
|
||||
|
||||
/* Returns 0 to stop listing, 1 to continue. */
|
||||
int AddToList(char *text, uint32 id)
|
||||
{
|
||||
if(listcount==16)
|
||||
{
|
||||
int t=ListChoice(0);
|
||||
mordoe=0;
|
||||
if(t==-1) return(0); // Stop listing.
|
||||
else if(t>0 && t<17)
|
||||
{
|
||||
listsel=listids[t-1];
|
||||
return(0);
|
||||
}
|
||||
listcount=0;
|
||||
}
|
||||
mordoe=1;
|
||||
listids[listcount]=id;
|
||||
printf("%2d) %s\n",listcount+1,text);
|
||||
listcount++;
|
||||
return(1);
|
||||
}
|
||||
|
||||
/*
|
||||
**
|
||||
** End list code.
|
||||
**/
|
||||
|
||||
typedef struct MENU {
|
||||
char *text;
|
||||
void *action;
|
||||
int type; // 0 for menu, 1 for function.
|
||||
} MENU;
|
||||
|
||||
static void SetOC(void)
|
||||
{
|
||||
FCEUI_CheatSearchSetCurrentAsOriginal();
|
||||
}
|
||||
|
||||
static void UnhideEx(void)
|
||||
{
|
||||
FCEUI_CheatSearchShowExcluded();
|
||||
}
|
||||
|
||||
static void ToggleCheat(int num)
|
||||
{
|
||||
printf("Cheat %d %sabled.\n",1+num,
|
||||
FCEUI_ToggleCheat(num)?"en":"dis");
|
||||
}
|
||||
|
||||
static void ModifyCheat(int num)
|
||||
{
|
||||
char *name;
|
||||
char buf[256];
|
||||
uint32 A;
|
||||
uint8 V;
|
||||
int compare;
|
||||
int type;
|
||||
|
||||
int s;
|
||||
int t;
|
||||
|
||||
FCEUI_GetCheat(num, &name, &A, &V, &compare, &s, &type);
|
||||
|
||||
printf("Name [%s]: ",name);
|
||||
GetString(buf,256);
|
||||
|
||||
/* This obviously doesn't allow for cheats with no names. Bah. Who wants
|
||||
nameless cheats anyway...
|
||||
*/
|
||||
|
||||
if(buf[0])
|
||||
name=buf; // Change name when FCEUI_SetCheat() is called.
|
||||
else
|
||||
name=0; // Don't change name when FCEUI_SetCheat() is called.
|
||||
|
||||
printf("Address [$%04x]: ",(unsigned int)A);
|
||||
A=GetH16(A);
|
||||
|
||||
printf("Value [%03d]: ",(unsigned int)V);
|
||||
V=Get8(V);
|
||||
|
||||
printf("Compare [%3d]: ",compare);
|
||||
compare=GetI(compare);
|
||||
|
||||
printf("Type(0=Old Style, 1=Read Substitute) [%1d]: ",type);
|
||||
type=GetI(type)?1:0;
|
||||
|
||||
printf("Enable [%s]: ",s?"Y":"N");
|
||||
t=getchar();
|
||||
if(t=='Y' || t=='y') s=1;
|
||||
else if(t=='N' || t=='n') s=0;
|
||||
|
||||
FCEUI_SetCheat(num,name,A,V,compare,s,type);
|
||||
}
|
||||
|
||||
|
||||
static void AddCheatGGPAR(int which)
|
||||
{
|
||||
uint16 A;
|
||||
uint8 V;
|
||||
int C;
|
||||
int type;
|
||||
char name[256],code[256];
|
||||
|
||||
printf("Name: ");
|
||||
GetString(name,256);
|
||||
|
||||
printf("Code: ");
|
||||
GetString(code,256);
|
||||
|
||||
printf("Add cheat \"%s\" for code \"%s\"?",name,code);
|
||||
if(GetYN(0))
|
||||
{
|
||||
if(which)
|
||||
{
|
||||
if(!FCEUI_DecodePAR(code,&A,&V,&C,&type))
|
||||
{
|
||||
puts("Invalid Game Genie code.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!FCEUI_DecodeGG(code,&A,&V,&C))
|
||||
{
|
||||
puts("Invalid Game Genie code.");
|
||||
return;
|
||||
}
|
||||
type=1;
|
||||
}
|
||||
|
||||
if(FCEUI_AddCheat(name,A,V,C,type))
|
||||
puts("Cheat added.");
|
||||
else
|
||||
puts("Error adding cheat.");
|
||||
}
|
||||
}
|
||||
|
||||
static void AddCheatGG(void)
|
||||
{
|
||||
AddCheatGGPAR(0);
|
||||
}
|
||||
|
||||
static void AddCheatPAR(void)
|
||||
{
|
||||
AddCheatGGPAR(1);
|
||||
}
|
||||
|
||||
static void AddCheatParam(uint32 A, uint8 V)
|
||||
{
|
||||
char name[256];
|
||||
|
||||
printf("Name: ");
|
||||
GetString(name,256);
|
||||
printf("Address [$%04x]: ",(unsigned int)A);
|
||||
A=GetH16(A);
|
||||
printf("Value [%03d]: ",(unsigned int)V);
|
||||
V=Get8(V);
|
||||
printf("Add cheat \"%s\" for address $%04x with value %03d?",name,(unsigned int)A,(unsigned int)V);
|
||||
if(GetYN(0))
|
||||
{
|
||||
if(FCEUI_AddCheat(name,A,V,-1,0))
|
||||
puts("Cheat added.");
|
||||
else
|
||||
puts("Error adding cheat.");
|
||||
}
|
||||
}
|
||||
|
||||
static void AddCheat(void)
|
||||
{
|
||||
AddCheatParam(0,0);
|
||||
}
|
||||
|
||||
static int lid;
|
||||
static int clistcallb(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data)
|
||||
{
|
||||
char tmp[512];
|
||||
int ret;
|
||||
|
||||
if(compare>=0)
|
||||
sprintf(tmp,"%s $%04x:%03d:%03d - %s",s?"*":" ",(unsigned int)a,(unsigned int)v,compare,name);
|
||||
else
|
||||
sprintf(tmp,"%s $%04x:%03d - %s",s?"*":" ",(unsigned int)a,(unsigned int)v,name);
|
||||
if(type==1)
|
||||
tmp[2]='S';
|
||||
ret=AddToList(tmp,lid);
|
||||
lid++;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static void ListCheats(void)
|
||||
{
|
||||
int which;
|
||||
lid=0;
|
||||
|
||||
BeginListShow();
|
||||
FCEUI_ListCheats(clistcallb,0);
|
||||
which=EndListShow();
|
||||
if(which>=0)
|
||||
{
|
||||
char tmp[32];
|
||||
printf(" <(T)oggle status, (M)odify, or (D)elete this cheat.> ");
|
||||
fgets(tmp,32,stdin);
|
||||
switch(tolower(tmp[0]))
|
||||
{
|
||||
case 't':ToggleCheat(which);
|
||||
break;
|
||||
case 'd':if(!FCEUI_DelCheat(which))
|
||||
puts("Error deleting cheat!");
|
||||
else
|
||||
puts("Cheat has been deleted.");
|
||||
break;
|
||||
case 'm':ModifyCheat(which);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ResetSearch(void)
|
||||
{
|
||||
FCEUI_CheatSearchBegin();
|
||||
puts("Done.");
|
||||
}
|
||||
|
||||
static int srescallb(uint32 a, uint8 last, uint8 current, void *data)
|
||||
{
|
||||
char tmp[13];
|
||||
sprintf(tmp, "$%04x:%03d:%03d",(unsigned int)a,(unsigned int)last,(unsigned int)current);
|
||||
return(AddToList(tmp,a));
|
||||
}
|
||||
|
||||
static void ShowRes(void)
|
||||
{
|
||||
int n=FCEUI_CheatSearchGetCount();
|
||||
printf(" %d results:\n",n);
|
||||
if(n)
|
||||
{
|
||||
int which;
|
||||
BeginListShow();
|
||||
FCEUI_CheatSearchGet(srescallb,0);
|
||||
which=EndListShow();
|
||||
if(which>=0)
|
||||
AddCheatParam(which,0);
|
||||
}
|
||||
}
|
||||
|
||||
static int ShowShortList(char *moe[], int n, int def)
|
||||
{
|
||||
int x,c;
|
||||
unsigned int baa;
|
||||
char tmp[16];
|
||||
|
||||
red:
|
||||
for(x=0;x<n;x++)
|
||||
printf("%d) %s\n",x+1,moe[x]);
|
||||
puts("D) Display List");
|
||||
clo:
|
||||
|
||||
printf("\nSelection [%d]> ",def+1);
|
||||
fgets(tmp,256,stdin);
|
||||
if(tmp[0]=='\n')
|
||||
return def;
|
||||
c=tolower(tmp[0]);
|
||||
baa=c-'1';
|
||||
|
||||
if(baa<n)
|
||||
return baa;
|
||||
else if(c=='d')
|
||||
goto red;
|
||||
else
|
||||
{
|
||||
puts("Invalid selection.");
|
||||
goto clo;
|
||||
}
|
||||
}
|
||||
|
||||
static void DoSearch(void)
|
||||
{
|
||||
static int v1=0,v2=0;
|
||||
static int method=0;
|
||||
char *m[6]={"O==V1 && C==V2","O==V1 && |O-C|==V2","|O-C|==V2","O!=C","Value decreased","Value increased"};
|
||||
printf("\nSearch Filter:\n");
|
||||
|
||||
method=ShowShortList(m,6,method);
|
||||
if(method<=1)
|
||||
{
|
||||
printf("V1 [%03d]: ",v1);
|
||||
v1=Get8(v1);
|
||||
}
|
||||
if(method<=2)
|
||||
{
|
||||
printf("V2 [%03d]: ",v2);
|
||||
v2=Get8(v2);
|
||||
}
|
||||
FCEUI_CheatSearchEnd(method,v1,v2);
|
||||
puts("Search completed.\n");
|
||||
}
|
||||
|
||||
|
||||
static MENU NewCheatsMenu[]={
|
||||
{"Add Cheat",(void *)AddCheat,1},
|
||||
{"Reset Search",(void *)ResetSearch,1},
|
||||
{"Do Search",(void *)DoSearch,1},
|
||||
{"Set Original to Current",(void *)SetOC,1},
|
||||
{"Unhide Excluded",(void *)UnhideEx,1},
|
||||
{"Show Results",(void *)ShowRes,1},
|
||||
{"Add Game Genie Cheat",(void *)AddCheatGG,1},
|
||||
{"Add PAR Cheat",(void *)AddCheatPAR,1},
|
||||
{0}
|
||||
};
|
||||
|
||||
static MENU MainMenu[]={
|
||||
{"List Cheats",(void *)ListCheats,1},
|
||||
{"New Cheats...",(void *)NewCheatsMenu,0},
|
||||
{0}
|
||||
};
|
||||
|
||||
static void DoMenu(MENU *men)
|
||||
{
|
||||
int x=0;
|
||||
|
||||
redisplay:
|
||||
x=0;
|
||||
puts("");
|
||||
while(men[x].text)
|
||||
{
|
||||
printf("%d) %s\n",x+1,men[x].text);
|
||||
x++;
|
||||
}
|
||||
puts("D) Display Menu\nX) Return to Previous\n");
|
||||
{
|
||||
char buf[32];
|
||||
int c;
|
||||
|
||||
recommand:
|
||||
printf("Command> ");
|
||||
fgets(buf,32,stdin);
|
||||
c=tolower(buf[0]);
|
||||
if(c=='\n')
|
||||
goto recommand;
|
||||
else if(c=='d')
|
||||
goto redisplay;
|
||||
else if(c=='x')
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if(sscanf(buf,"%d",&c))
|
||||
{
|
||||
if(c>x) goto invalid;
|
||||
if(men[c-1].type)
|
||||
{
|
||||
void (*func)(void)=(void(*)())men[c-1].action;
|
||||
func();
|
||||
}
|
||||
else
|
||||
DoMenu((MENU*)men[c-1].action); /* Mmm...recursivey goodness. */
|
||||
goto redisplay;
|
||||
}
|
||||
else
|
||||
{
|
||||
invalid:
|
||||
puts("Invalid command.\n");
|
||||
goto recommand;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void DoConsoleCheatConfig(void)
|
||||
{
|
||||
MENU *curmenu=MainMenu;
|
||||
|
||||
DoMenu(curmenu);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
void DoConsoleCheatConfig(void);
|
|
@ -0,0 +1,152 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/****************************************************************/
|
||||
/* FCE Ultra */
|
||||
/* */
|
||||
/* This file contains routines for reading/writing the */
|
||||
/* configuration file. */
|
||||
/* */
|
||||
/****************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../types.h"
|
||||
#include "config.h"
|
||||
|
||||
static int FReadString(FILE *fp, char *str, int n)
|
||||
{
|
||||
int x=0,z;
|
||||
for(;;)
|
||||
{
|
||||
z=fgetc(fp);
|
||||
str[x]=z;
|
||||
x++;
|
||||
if(z<=0) break;
|
||||
if(x>=n) return 0;
|
||||
}
|
||||
if(z<0) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void GetValueR(FILE *fp, char *str, void *v, int c)
|
||||
{
|
||||
char buf[256];
|
||||
int s;
|
||||
|
||||
while(FReadString(fp,buf,256))
|
||||
{
|
||||
fread(&s,1,4,fp);
|
||||
if(!strcmp(str, buf))
|
||||
{
|
||||
if(!c) // String, allocate some memory.
|
||||
{
|
||||
if(!(*(char **)v=(char*)malloc(s)))
|
||||
goto gogl;
|
||||
fread(*(char **)v,1,s,fp);
|
||||
continue;
|
||||
}
|
||||
else if(s>c || s<c)
|
||||
{
|
||||
gogl:
|
||||
fseek(fp,s,SEEK_CUR);
|
||||
continue;
|
||||
}
|
||||
fread((uint8*)v,1,c,fp);
|
||||
}
|
||||
else
|
||||
fseek(fp,s,SEEK_CUR);
|
||||
}
|
||||
fseek(fp,4,SEEK_SET);
|
||||
}
|
||||
|
||||
static void SetValueR(FILE *fp, char *str, void *v, int c)
|
||||
{
|
||||
fwrite(str,1,strlen(str)+1,fp);
|
||||
fwrite((uint8*)&c,1,4,fp);
|
||||
fwrite((uint8*)v,1,c,fp);
|
||||
}
|
||||
|
||||
static void SaveParse(CFGSTRUCT *cfgst, FILE *fp)
|
||||
{
|
||||
int x=0;
|
||||
|
||||
while(cfgst[x].ptr)
|
||||
{
|
||||
if(!cfgst[x].name) // Link to new config structure
|
||||
{
|
||||
SaveParse((CFGSTRUCT*)cfgst[x].ptr,fp); // Recursion is sexy. I could
|
||||
// save a little stack space if I made
|
||||
// the file pointer a non-local
|
||||
// variable...
|
||||
x++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(cfgst[x].len) // Plain data
|
||||
SetValueR(fp,cfgst[x].name,cfgst[x].ptr,cfgst[x].len);
|
||||
else // String
|
||||
if(*(char **)cfgst[x].ptr) // Only save it if there IS a string.
|
||||
SetValueR(fp,cfgst[x].name,*(char **)cfgst[x].ptr,
|
||||
strlen(*(char **)cfgst[x].ptr)+1);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
void SaveFCEUConfig(char *filename, CFGSTRUCT *cfgst)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp=fopen(filename,"wb");
|
||||
if(fp==NULL) return;
|
||||
|
||||
SaveParse(cfgst,fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static void LoadParse(CFGSTRUCT *cfgst, FILE *fp)
|
||||
{
|
||||
int x=0;
|
||||
|
||||
while(cfgst[x].ptr)
|
||||
{
|
||||
if(!cfgst[x].name) // Link to new config structure
|
||||
{
|
||||
LoadParse((CFGSTRUCT*)cfgst[x].ptr,fp);
|
||||
x++;
|
||||
continue;
|
||||
}
|
||||
GetValueR(fp,cfgst[x].name,cfgst[x].ptr,cfgst[x].len);
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
void LoadFCEUConfig(char *filename, CFGSTRUCT *cfgst)
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
fp=fopen(filename,"rb");
|
||||
if(fp==NULL) return;
|
||||
LoadParse(cfgst,fp);
|
||||
fclose(fp);
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
#ifndef _DRIVERS_CONFIGH
|
||||
typedef struct {
|
||||
char *name;
|
||||
void *ptr;
|
||||
int len;
|
||||
} CFGSTRUCT;
|
||||
|
||||
void SaveFCEUConfig(char *filename, CFGSTRUCT *cfgst);
|
||||
void LoadFCEUConfig(char *filename, CFGSTRUCT *cfgst);
|
||||
|
||||
/* Macros for building CFGSTRUCT structures. */
|
||||
|
||||
/* CFGSTRUCT structures must always end with ENDCFGSTRUCT */
|
||||
#define ENDCFGSTRUCT { 0,0,0 }
|
||||
|
||||
/* When this macro is used, the config loading/saving code will parse
|
||||
the new config structure until the end of it is detected, then it
|
||||
will continue parsing the original config structure.
|
||||
*/
|
||||
#define ADDCFGSTRUCT(x) { 0,&x,0 }
|
||||
|
||||
/* Oops. The NAC* macros shouldn't have the # in front of the w, but
|
||||
fixing this would break configuration files of previous versions and it
|
||||
isn't really hurting much.
|
||||
*/
|
||||
|
||||
/* Single piece of data(integer). */
|
||||
#define AC(x) { #x,&x,sizeof(x)}
|
||||
#define NAC(w,x) { #w,&x,sizeof(x)}
|
||||
|
||||
/* Array. */
|
||||
#define ACA(x) {#x,x,sizeof(x)}
|
||||
#define NACA(w,x) {#w,x,sizeof(x)}
|
||||
|
||||
/* String(pointer) with automatic memory allocation. */
|
||||
#define ACS(x) {#x,&x,0}
|
||||
#define NACS(w,x) {#w,&x,0}
|
||||
|
||||
#define _DRIVERS_CONFIGH
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,4 @@
|
|||
void hq2x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL);
|
||||
int hq2x_InitLUTs(void);
|
||||
void hq2x_Kill(void);
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,4 @@
|
|||
void hq3x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL);
|
||||
int hq3x_InitLUTs(void);
|
||||
void hq3x_Kill(void);
|
||||
|
|
@ -0,0 +1,923 @@
|
|||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains a C and MMX implementation of the Scale2x effect.
|
||||
*
|
||||
* You can find an high level description of the effect at :
|
||||
*
|
||||
* http://scale2x.sourceforge.net/
|
||||
*
|
||||
* Alternatively at the previous license terms, you are allowed to use this
|
||||
* code in your program with these conditions:
|
||||
* - the program is not used in commercial activities.
|
||||
* - the whole source code of the program is released with the binary.
|
||||
* - derivative works of the program are allowed.
|
||||
*/
|
||||
|
||||
#include "scale2x.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/***************************************************************************/
|
||||
/* Scale2x C implementation */
|
||||
|
||||
static inline void scale2x_8_def_single(scale2x_uint8* __restrict__ dst, const scale2x_uint8* __restrict__ src0, const scale2x_uint8* __restrict__ src1, const scale2x_uint8* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[1] = src0[0];
|
||||
else
|
||||
dst[1] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
|
||||
dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale2x_16_def_single(scale2x_uint16* __restrict__ dst, const scale2x_uint16* __restrict__ src0, const scale2x_uint16* __restrict__ src1, const scale2x_uint16* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[1] = src0[0];
|
||||
else
|
||||
dst[1] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
|
||||
dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale2x_32_def_single(scale2x_uint32* __restrict__ dst, const scale2x_uint32* __restrict__ src0, const scale2x_uint32* __restrict__ src1, const scale2x_uint32* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[1] = src0[0];
|
||||
else
|
||||
dst[1] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
|
||||
dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 2;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 8 bits.
|
||||
* The function is implemented in C.
|
||||
* The pixels over the left and right borders are assumed of the same color of
|
||||
* the pixels on the border.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
scale2x_8_def_single(dst0, src0, src1, src2, count);
|
||||
scale2x_8_def_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 16 bits.
|
||||
* This function operates like scale2x_8_def() but for 16 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
scale2x_16_def_single(dst0, src0, src1, src2, count);
|
||||
scale2x_16_def_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 32 bits.
|
||||
* This function operates like scale2x_8_def() but for 32 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
scale2x_32_def_single(dst0, src0, src1, src2, count);
|
||||
scale2x_32_def_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/* Scale2x MMX implementation */
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
|
||||
/*
|
||||
* Apply the Scale2x effect at a single row.
|
||||
* This function must be called only by the other scale2x functions.
|
||||
*
|
||||
* Considering the pixel map :
|
||||
*
|
||||
* ABC (src0)
|
||||
* DEF (src1)
|
||||
* GHI (src2)
|
||||
*
|
||||
* this functions compute 2 new pixels in substitution of the source pixel E
|
||||
* like this map :
|
||||
*
|
||||
* ab (dst)
|
||||
*
|
||||
* with these variables :
|
||||
*
|
||||
* ¤t -> E
|
||||
* ¤t_left -> D
|
||||
* ¤t_right -> F
|
||||
* ¤t_upper -> B
|
||||
* ¤t_lower -> H
|
||||
*
|
||||
* %0 -> current_upper
|
||||
* %1 -> current
|
||||
* %2 -> current_lower
|
||||
* %3 -> dst
|
||||
* %4 -> counter
|
||||
*
|
||||
* %mm0 -> *current_left
|
||||
* %mm1 -> *current_next
|
||||
* %mm2 -> tmp0
|
||||
* %mm3 -> tmp1
|
||||
* %mm4 -> tmp2
|
||||
* %mm5 -> tmp3
|
||||
* %mm6 -> *current_upper
|
||||
* %mm7 -> *current
|
||||
*/
|
||||
static inline void scale2x_8_mmx_single(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 16);
|
||||
assert(count % 8 == 0);
|
||||
|
||||
/* always do the first and last run */
|
||||
count -= 2*8;
|
||||
|
||||
__asm__ __volatile__(
|
||||
/* first run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq 0(%1), %%mm0\n"
|
||||
"movq 0(%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psllq $56, %%mm0\n"
|
||||
"psllq $56, %%mm1\n"
|
||||
"psrlq $56, %%mm0\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $8, %%mm2\n"
|
||||
"psrlq $8, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqb %%mm6, %%mm2\n"
|
||||
"pcmpeqb %%mm6, %%mm4\n"
|
||||
"pcmpeqb (%2), %%mm3\n"
|
||||
"pcmpeqb (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqb %%mm1, %%mm2\n"
|
||||
"pcmpeqb %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklbw %%mm4, %%mm2\n"
|
||||
"punpckhbw %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
/* central runs */
|
||||
"shrl $3, %4\n"
|
||||
"jz 1f\n"
|
||||
|
||||
"0:\n"
|
||||
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psrlq $56, %%mm0\n"
|
||||
"psllq $56, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $8, %%mm2\n"
|
||||
"psrlq $8, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqb %%mm6, %%mm2\n"
|
||||
"pcmpeqb %%mm6, %%mm4\n"
|
||||
"pcmpeqb (%2), %%mm3\n"
|
||||
"pcmpeqb (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqb %%mm1, %%mm2\n"
|
||||
"pcmpeqb %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklbw %%mm4, %%mm2\n"
|
||||
"punpckhbw %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
"decl %4\n"
|
||||
"jnz 0b\n"
|
||||
"1:\n"
|
||||
|
||||
/* final run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq (%1), %%mm1\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"psrlq $56, %%mm1\n"
|
||||
"psrlq $56, %%mm0\n"
|
||||
"psllq $56, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $8, %%mm2\n"
|
||||
"psrlq $8, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqb %%mm6, %%mm2\n"
|
||||
"pcmpeqb %%mm6, %%mm4\n"
|
||||
"pcmpeqb (%2), %%mm3\n"
|
||||
"pcmpeqb (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqb %%mm1, %%mm2\n"
|
||||
"pcmpeqb %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklbw %%mm4, %%mm2\n"
|
||||
"punpckhbw %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
: "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
|
||||
:
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
||||
static inline void scale2x_16_mmx_single(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 8);
|
||||
assert(count % 4 == 0);
|
||||
|
||||
/* always do the first and last run */
|
||||
count -= 2*4;
|
||||
|
||||
__asm__ __volatile__(
|
||||
/* first run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq 0(%1), %%mm0\n"
|
||||
"movq 0(%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psllq $48, %%mm0\n"
|
||||
"psllq $48, %%mm1\n"
|
||||
"psrlq $48, %%mm0\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $16, %%mm2\n"
|
||||
"psrlq $16, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqw %%mm6, %%mm2\n"
|
||||
"pcmpeqw %%mm6, %%mm4\n"
|
||||
"pcmpeqw (%2), %%mm3\n"
|
||||
"pcmpeqw (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqw %%mm1, %%mm2\n"
|
||||
"pcmpeqw %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklwd %%mm4, %%mm2\n"
|
||||
"punpckhwd %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
/* central runs */
|
||||
"shrl $2, %4\n"
|
||||
"jz 1f\n"
|
||||
|
||||
"0:\n"
|
||||
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psrlq $48, %%mm0\n"
|
||||
"psllq $48, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $16, %%mm2\n"
|
||||
"psrlq $16, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqw %%mm6, %%mm2\n"
|
||||
"pcmpeqw %%mm6, %%mm4\n"
|
||||
"pcmpeqw (%2), %%mm3\n"
|
||||
"pcmpeqw (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqw %%mm1, %%mm2\n"
|
||||
"pcmpeqw %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklwd %%mm4, %%mm2\n"
|
||||
"punpckhwd %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
"decl %4\n"
|
||||
"jnz 0b\n"
|
||||
"1:\n"
|
||||
|
||||
/* final run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq (%1), %%mm1\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"psrlq $48, %%mm1\n"
|
||||
"psrlq $48, %%mm0\n"
|
||||
"psllq $48, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $16, %%mm2\n"
|
||||
"psrlq $16, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqw %%mm6, %%mm2\n"
|
||||
"pcmpeqw %%mm6, %%mm4\n"
|
||||
"pcmpeqw (%2), %%mm3\n"
|
||||
"pcmpeqw (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqw %%mm1, %%mm2\n"
|
||||
"pcmpeqw %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpcklwd %%mm4, %%mm2\n"
|
||||
"punpckhwd %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
: "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
|
||||
:
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
||||
static inline void scale2x_32_mmx_single(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 4);
|
||||
assert(count % 2 == 0);
|
||||
|
||||
/* always do the first and last run */
|
||||
count -= 2*2;
|
||||
|
||||
__asm__ __volatile__(
|
||||
/* first run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq 0(%1), %%mm0\n"
|
||||
"movq 0(%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psllq $32, %%mm0\n"
|
||||
"psllq $32, %%mm1\n"
|
||||
"psrlq $32, %%mm0\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $32, %%mm2\n"
|
||||
"psrlq $32, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqd %%mm6, %%mm2\n"
|
||||
"pcmpeqd %%mm6, %%mm4\n"
|
||||
"pcmpeqd (%2), %%mm3\n"
|
||||
"pcmpeqd (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqd %%mm1, %%mm2\n"
|
||||
"pcmpeqd %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpckldq %%mm4, %%mm2\n"
|
||||
"punpckhdq %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
/* central runs */
|
||||
"shrl $1, %4\n"
|
||||
"jz 1f\n"
|
||||
|
||||
"0:\n"
|
||||
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq 8(%1), %%mm1\n"
|
||||
"psrlq $32, %%mm0\n"
|
||||
"psllq $32, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $32, %%mm2\n"
|
||||
"psrlq $32, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqd %%mm6, %%mm2\n"
|
||||
"pcmpeqd %%mm6, %%mm4\n"
|
||||
"pcmpeqd (%2), %%mm3\n"
|
||||
"pcmpeqd (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqd %%mm1, %%mm2\n"
|
||||
"pcmpeqd %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpckldq %%mm4, %%mm2\n"
|
||||
"punpckhdq %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
/* next */
|
||||
"addl $8, %0\n"
|
||||
"addl $8, %1\n"
|
||||
"addl $8, %2\n"
|
||||
"addl $16, %3\n"
|
||||
|
||||
"decl %4\n"
|
||||
"jnz 0b\n"
|
||||
"1:\n"
|
||||
|
||||
/* final run */
|
||||
/* set the current, current_pre, current_next registers */
|
||||
"movq (%1), %%mm1\n"
|
||||
"movq (%1), %%mm7\n"
|
||||
"movq -8(%1), %%mm0\n"
|
||||
"psrlq $32, %%mm1\n"
|
||||
"psrlq $32, %%mm0\n"
|
||||
"psllq $32, %%mm1\n"
|
||||
"movq %%mm7, %%mm2\n"
|
||||
"movq %%mm7, %%mm3\n"
|
||||
"psllq $32, %%mm2\n"
|
||||
"psrlq $32, %%mm3\n"
|
||||
"por %%mm2, %%mm0\n"
|
||||
"por %%mm3, %%mm1\n"
|
||||
|
||||
/* current_upper */
|
||||
"movq (%0), %%mm6\n"
|
||||
|
||||
/* compute the upper-left pixel for dst on %%mm2 */
|
||||
/* compute the upper-right pixel for dst on %%mm4 */
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"movq %%mm0, %%mm3\n"
|
||||
"movq %%mm1, %%mm5\n"
|
||||
"pcmpeqd %%mm6, %%mm2\n"
|
||||
"pcmpeqd %%mm6, %%mm4\n"
|
||||
"pcmpeqd (%2), %%mm3\n"
|
||||
"pcmpeqd (%2), %%mm5\n"
|
||||
"pandn %%mm2, %%mm3\n"
|
||||
"pandn %%mm4, %%mm5\n"
|
||||
"movq %%mm0, %%mm2\n"
|
||||
"movq %%mm1, %%mm4\n"
|
||||
"pcmpeqd %%mm1, %%mm2\n"
|
||||
"pcmpeqd %%mm0, %%mm4\n"
|
||||
"pandn %%mm3, %%mm2\n"
|
||||
"pandn %%mm5, %%mm4\n"
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"movq %%mm4, %%mm5\n"
|
||||
"pand %%mm6, %%mm2\n"
|
||||
"pand %%mm6, %%mm4\n"
|
||||
"pandn %%mm7, %%mm3\n"
|
||||
"pandn %%mm7, %%mm5\n"
|
||||
"por %%mm3, %%mm2\n"
|
||||
"por %%mm5, %%mm4\n"
|
||||
|
||||
/* set *dst */
|
||||
"movq %%mm2, %%mm3\n"
|
||||
"punpckldq %%mm4, %%mm2\n"
|
||||
"punpckhdq %%mm4, %%mm3\n"
|
||||
"movq %%mm2, (%3)\n"
|
||||
"movq %%mm3, 8(%3)\n"
|
||||
|
||||
: "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
|
||||
:
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 8 bits.
|
||||
* This is a very fast MMX implementation.
|
||||
* The implementation uses a combination of cmp/and/not operations to
|
||||
* completly remove the need of conditional jumps. This trick give the
|
||||
* major speed improvement.
|
||||
* Also, using the 8 bytes MMX registers more than one pixel are computed
|
||||
* at the same time.
|
||||
* Before calling this function you must ensure that the currenct CPU supports
|
||||
* the MMX instruction set. After calling it you must be sure to call the EMMS
|
||||
* instruction before any floating-point operation.
|
||||
* The pixels over the left and right borders are assumed of the same color of
|
||||
* the pixels on the border.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows. It must
|
||||
* be at least 16 and a multiple of 8.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)
|
||||
{
|
||||
if (count % 8 != 0 || count < 16) {
|
||||
scale2x_8_def(dst0, dst1, src0, src1, src2, count);
|
||||
} else {
|
||||
assert(count >= 16);
|
||||
assert(count % 8 == 0);
|
||||
|
||||
scale2x_8_mmx_single(dst0, src0, src1, src2, count);
|
||||
scale2x_8_mmx_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 16 bits.
|
||||
* This function operates like scale2x_8_mmx() but for 16 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows. It must
|
||||
* be at least 8 and a multiple of 4.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)
|
||||
{
|
||||
if (count % 4 != 0 || count < 8) {
|
||||
scale2x_16_def(dst0, dst1, src0, src1, src2, count);
|
||||
} else {
|
||||
assert(count >= 8);
|
||||
assert(count % 4 == 0);
|
||||
|
||||
scale2x_16_mmx_single(dst0, src0, src1, src2, count);
|
||||
scale2x_16_mmx_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 2 a row of pixels of 32 bits.
|
||||
* This function operates like scale2x_8_mmx() but for 32 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows. It must
|
||||
* be at least 4 and a multiple of 2.
|
||||
* \param dst0 First destination row, double length in pixels.
|
||||
* \param dst1 Second destination row, double length in pixels.
|
||||
*/
|
||||
void scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)
|
||||
{
|
||||
if (count % 2 != 0 || count < 4) {
|
||||
scale2x_32_def(dst0, dst1, src0, src1, src2, count);
|
||||
} else {
|
||||
assert(count >= 4);
|
||||
assert(count % 2 == 0);
|
||||
|
||||
scale2x_32_mmx_single(dst0, src0, src1, src2, count);
|
||||
scale2x_32_mmx_single(dst1, src2, src1, src0, count);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SCALE2X_H
|
||||
#define __SCALE2X_H
|
||||
|
||||
typedef unsigned char scale2x_uint8;
|
||||
typedef unsigned short scale2x_uint16;
|
||||
typedef unsigned scale2x_uint32;
|
||||
|
||||
void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);
|
||||
void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);
|
||||
void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
|
||||
void scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);
|
||||
void scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);
|
||||
void scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);
|
||||
|
||||
/**
|
||||
* End the use of the MMX instructions.
|
||||
* This function must be called before using any floating-point operations.
|
||||
*/
|
||||
static inline void scale2x_mmx_emms(void)
|
||||
{
|
||||
__asm__ __volatile__ (
|
||||
"emms"
|
||||
);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,382 @@
|
|||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains a C and MMX implementation of the Scale2x effect.
|
||||
*
|
||||
* You can find an high level description of the effect at :
|
||||
*
|
||||
* http://scale2x.sourceforge.net/
|
||||
*
|
||||
* Alternatively at the previous license terms, you are allowed to use this
|
||||
* code in your program with these conditions:
|
||||
* - the program is not used in commercial activities.
|
||||
* - the whole source code of the program is released with the binary.
|
||||
* - derivative works of the program are allowed.
|
||||
*/
|
||||
|
||||
#include "scale3x.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/***************************************************************************/
|
||||
/* Scale3x C implementation */
|
||||
|
||||
static inline void scale3x_8_def_border(scale3x_uint8* __restrict__ dst, const scale3x_uint8* __restrict__ src0, const scale3x_uint8* __restrict__ src1, const scale3x_uint8* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[2] = src0[0];
|
||||
else
|
||||
dst[2] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
|
||||
dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
|
||||
dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale3x_8_def_center(scale3x_uint8* __restrict__ dst, const scale3x_uint8* __restrict__ src0, const scale3x_uint8* __restrict__ src1, const scale3x_uint8* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
}
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale3x_16_def_border(scale3x_uint16* __restrict__ dst, const scale3x_uint16* __restrict__ src0, const scale3x_uint16* __restrict__ src1, const scale3x_uint16* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[2] = src0[0];
|
||||
else
|
||||
dst[2] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
|
||||
dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
|
||||
dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale3x_16_def_center(scale3x_uint16* __restrict__ dst, const scale3x_uint16* __restrict__ src0, const scale3x_uint16* __restrict__ src1, const scale3x_uint16* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
}
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale3x_32_def_border(scale3x_uint32* __restrict__ dst, const scale3x_uint32* __restrict__ src0, const scale3x_uint32* __restrict__ src1, const scale3x_uint32* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src1[1] == src0[0] && src2[0] != src0[0])
|
||||
dst[2] = src0[0];
|
||||
else
|
||||
dst[2] = src1[0];
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
|
||||
dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
|
||||
dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src1[-1] == src0[0] && src2[0] != src0[0])
|
||||
dst[0] = src0[0];
|
||||
else
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
static inline void scale3x_32_def_center(scale3x_uint32* __restrict__ dst, const scale3x_uint32* __restrict__ src0, const scale3x_uint32* __restrict__ src1, const scale3x_uint32* __restrict__ src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
/* first pixel */
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
|
||||
/* central pixels */
|
||||
count -= 2;
|
||||
while (count) {
|
||||
if (src0[0] != src2[0] && src1[-1] != src1[1]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
++src0;
|
||||
++src1;
|
||||
++src2;
|
||||
dst += 3;
|
||||
--count;
|
||||
}
|
||||
|
||||
/* last pixel */
|
||||
if (src0[0] != src2[0]) {
|
||||
dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
|
||||
} else {
|
||||
dst[0] = src1[0];
|
||||
}
|
||||
dst[1] = src1[0];
|
||||
dst[2] = src1[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 3 a row of pixels of 8 bits.
|
||||
* The function is implemented in C.
|
||||
* The pixels over the left and right borders are assumed of the same color of
|
||||
* the pixels on the border.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, triple length in pixels.
|
||||
* \param dst1 Second destination row, triple length in pixels.
|
||||
* \param dst2 Third destination row, triple length in pixels.
|
||||
*/
|
||||
void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
scale3x_8_def_border(dst0, src0, src1, src2, count);
|
||||
scale3x_8_def_center(dst1, src0, src1, src2, count);
|
||||
scale3x_8_def_border(dst2, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 3 a row of pixels of 16 bits.
|
||||
* This function operates like scale3x_8_def() but for 16 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, triple length in pixels.
|
||||
* \param dst1 Second destination row, triple length in pixels.
|
||||
* \param dst2 Third destination row, triple length in pixels.
|
||||
*/
|
||||
void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
scale3x_16_def_border(dst0, src0, src1, src2, count);
|
||||
scale3x_16_def_center(dst1, src0, src1, src2, count);
|
||||
scale3x_16_def_border(dst2, src2, src1, src0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scale by a factor of 3 a row of pixels of 32 bits.
|
||||
* This function operates like scale3x_8_def() but for 32 bits pixels.
|
||||
* \param src0 Pointer at the first pixel of the previous row.
|
||||
* \param src1 Pointer at the first pixel of the current row.
|
||||
* \param src2 Pointer at the first pixel of the next row.
|
||||
* \param count Length in pixels of the src0, src1 and src2 rows.
|
||||
* It must be at least 2.
|
||||
* \param dst0 First destination row, triple length in pixels.
|
||||
* \param dst1 Second destination row, triple length in pixels.
|
||||
* \param dst2 Third destination row, triple length in pixels.
|
||||
*/
|
||||
void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count)
|
||||
{
|
||||
assert(count >= 2);
|
||||
|
||||
scale3x_32_def_border(dst0, src0, src1, src2, count);
|
||||
scale3x_32_def_center(dst1, src0, src1, src2, count);
|
||||
scale3x_32_def_border(dst2, src2, src1, src0, count);
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __SCALE3X_H
|
||||
#define __SCALE3X_H
|
||||
|
||||
typedef unsigned char scale3x_uint8;
|
||||
typedef unsigned short scale3x_uint16;
|
||||
typedef unsigned scale3x_uint32;
|
||||
|
||||
void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count);
|
||||
void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count);
|
||||
void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2003 Andrea Mazzoleni
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains an example implementation of the Scale effect
|
||||
* applyed to a generic bitmap.
|
||||
*
|
||||
* You can find an high level description of the effect at :
|
||||
*
|
||||
* http://scale2x.sourceforge.net/
|
||||
*
|
||||
* Alternatively at the previous license terms, you are allowed to use this
|
||||
* code in your program with these conditions:
|
||||
* - the program is not used in commercial activities.
|
||||
* - the whole source code of the program is released with the binary.
|
||||
* - derivative works of the program are allowed.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "scale2x.h"
|
||||
#include "scale3x.h"
|
||||
|
||||
#if HAVE_ALLOCA_H
|
||||
#include <alloca.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/**
|
||||
* Apply the Scale2x effect on a group of rows. Used internally.
|
||||
*/
|
||||
static inline void stage_scale2x(void* dst0, void* dst1, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)
|
||||
{
|
||||
switch (pixel) {
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
case 1 : scale2x_8_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
case 2 : scale2x_16_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
case 4 : scale2x_32_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
#else
|
||||
case 1 : scale2x_8_def(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
case 2 : scale2x_16_def(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
case 4 : scale2x_32_def(dst0, dst1, src0, src1, src2, pixel_per_row); break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale3x effect on a group of rows. Used internally.
|
||||
*/
|
||||
static inline void stage_scale3x(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)
|
||||
{
|
||||
switch (pixel) {
|
||||
case 1 : scale3x_8_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break;
|
||||
case 2 : scale3x_16_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break;
|
||||
case 4 : scale3x_32_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale4x effect on a group of rows. Used internally.
|
||||
*/
|
||||
static inline void stage_scale4x(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, const void* src3, unsigned pixel, unsigned pixel_per_row)
|
||||
{
|
||||
stage_scale2x(dst0, dst1, src0, src1, src2, pixel, 2 * pixel_per_row);
|
||||
stage_scale2x(dst2, dst3, src1, src2, src3, pixel, 2 * pixel_per_row);
|
||||
}
|
||||
|
||||
#define SCDST(i) (dst+(i)*dst_slice)
|
||||
#define SCSRC(i) (src+(i)*src_slice)
|
||||
#define SCMID(i) (mid[(i)])
|
||||
|
||||
/**
|
||||
* Apply the Scale2x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 2x2 times the size of the source bitmap.
|
||||
* \param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* \param dst_slice Size in bytes of a destination bitmap row.
|
||||
* \param void_src Pointer at the first pixel of the source bitmap.
|
||||
* \param src_slice Size in bytes of a source bitmap row.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
|
||||
{
|
||||
unsigned char* dst = (unsigned char*)void_dst;
|
||||
const unsigned char* src = (unsigned char*)void_src;
|
||||
unsigned count;
|
||||
|
||||
assert(height >= 2);
|
||||
|
||||
count = height;
|
||||
|
||||
stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
|
||||
|
||||
dst = SCDST(2);
|
||||
|
||||
count -= 2;
|
||||
while (count) {
|
||||
stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
|
||||
|
||||
dst = SCDST(2);
|
||||
src = SCSRC(1);
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
stage_scale2x(SCDST(0), SCDST(1), SCSRC(1-1), SCSRC(2-1), SCSRC(2-1), pixel, width);
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
scale2x_mmx_emms();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale32x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 3x3 times the size of the source bitmap.
|
||||
* \param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* \param dst_slice Size in bytes of a destination bitmap row.
|
||||
* \param void_src Pointer at the first pixel of the source bitmap.
|
||||
* \param src_slice Size in bytes of a source bitmap row.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale3x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
|
||||
{
|
||||
unsigned char* dst = (unsigned char*)void_dst;
|
||||
const unsigned char* src = (unsigned char*)void_src;
|
||||
unsigned count;
|
||||
|
||||
assert(height >= 2);
|
||||
|
||||
count = height;
|
||||
|
||||
stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
|
||||
|
||||
dst = SCDST(3);
|
||||
|
||||
count -= 2;
|
||||
while (count) {
|
||||
stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
|
||||
|
||||
dst = SCDST(3);
|
||||
src = SCSRC(1);
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(1-1), SCSRC(2-1), SCSRC(2-1), pixel, width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale4x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 4x4 times the size of the source bitmap.
|
||||
* \note This function requires also a small buffer bitmap used internally to store
|
||||
* intermediate results. This bitmap must have at least an horizontal size in bytes of 2*width*pixel,
|
||||
* and a vertical size of 6 rows. The memory of this buffer must not be allocated
|
||||
* in video memory because it's also read and not only written. Generally
|
||||
* a heap (malloc) or a stack (alloca) buffer is the best choices.
|
||||
* \param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* \param dst_slice Size in bytes of a destination bitmap row.
|
||||
* \param void_mid Pointer at the first pixel of the buffer bitmap.
|
||||
* \param mid_slice Size in bytes of a buffer bitmap row.
|
||||
* \param void_src Pointer at the first pixel of the source bitmap.
|
||||
* \param src_slice Size in bytes of a source bitmap row.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale4x_buf(void* void_dst, unsigned dst_slice, void* void_mid, unsigned mid_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
|
||||
{
|
||||
unsigned char* dst = (unsigned char*)void_dst;
|
||||
const unsigned char* src = (unsigned char*)void_src;
|
||||
unsigned count;
|
||||
unsigned char* mid[6];
|
||||
|
||||
assert(height >= 4);
|
||||
|
||||
count = height;
|
||||
|
||||
/* set the 6 buffer pointers */
|
||||
mid[0] = (unsigned char*)void_mid;
|
||||
mid[1] = mid[0] + mid_slice;
|
||||
mid[2] = mid[1] + mid_slice;
|
||||
mid[3] = mid[2] + mid_slice;
|
||||
mid[4] = mid[3] + mid_slice;
|
||||
mid[5] = mid[4] + mid_slice;
|
||||
|
||||
stage_scale2x(SCMID(-2+6), SCMID(-1+6), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
|
||||
stage_scale2x(SCMID(0), SCMID(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
|
||||
stage_scale2x(SCMID(2), SCMID(3), SCSRC(1), SCSRC(2), SCSRC(3), pixel, width);
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-2+6), SCMID(-2+6), SCMID(-1+6), SCMID(0), pixel, width);
|
||||
|
||||
dst = SCDST(4);
|
||||
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-1+6), SCMID(0), SCMID(1), SCMID(2), pixel, width);
|
||||
|
||||
dst = SCDST(4);
|
||||
|
||||
count -= 4;
|
||||
while (count) {
|
||||
unsigned char* tmp;
|
||||
|
||||
stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(4), pixel, width);
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);
|
||||
|
||||
dst = SCDST(4);
|
||||
src = SCSRC(1);
|
||||
|
||||
tmp = SCMID(0); /* shift by 2 position */
|
||||
SCMID(0) = SCMID(2);
|
||||
SCMID(2) = SCMID(4);
|
||||
SCMID(4) = tmp;
|
||||
tmp = SCMID(1);
|
||||
SCMID(1) = SCMID(3);
|
||||
SCMID(3) = SCMID(5);
|
||||
SCMID(5) = tmp;
|
||||
|
||||
--count;
|
||||
}
|
||||
|
||||
stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(3), pixel, width);
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);
|
||||
|
||||
dst = SCDST(4);
|
||||
|
||||
stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(3), SCMID(4), SCMID(5), SCMID(5), pixel, width);
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
scale2x_mmx_emms();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale4x effect on a bitmap.
|
||||
* The destination bitmap is filled with the scaled version of the source bitmap.
|
||||
* The source bitmap isn't modified.
|
||||
* The destination bitmap must be manually allocated before calling the function,
|
||||
* note that the resulting size is exactly 4x4 times the size of the source bitmap.
|
||||
* \note This function operates like ::scale4x_buf() but the intermediate buffer is
|
||||
* automatically allocated in the stack.
|
||||
* \param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* \param dst_slice Size in bytes of a destination bitmap row.
|
||||
* \param void_src Pointer at the first pixel of the source bitmap.
|
||||
* \param src_slice Size in bytes of a source bitmap row.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
static void scale4x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
|
||||
{
|
||||
unsigned mid_slice;
|
||||
void* mid;
|
||||
|
||||
mid_slice = 2 * pixel * width; /* required space for 1 row buffer */
|
||||
|
||||
mid_slice = (mid_slice + 0x7) & ~0x7; /* align to 8 bytes */
|
||||
|
||||
#if HAVE_ALLOCA
|
||||
mid = alloca(6 * mid_slice); /* allocate space for 6 row buffers */
|
||||
|
||||
assert(mid != 0); /* alloca should never fails */
|
||||
#else
|
||||
mid = malloc(6 * mid_slice); /* allocate space for 6 row buffers */
|
||||
|
||||
if (!mid)
|
||||
return;
|
||||
#endif
|
||||
|
||||
scale4x_buf(void_dst, dst_slice, mid, mid_slice, void_src, src_slice, pixel, width, height);
|
||||
|
||||
#if !HAVE_ALLOCA
|
||||
free(mid);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the scale implementation is applicable at the given arguments.
|
||||
* \param scale Scale factor. 2, 3 or 4.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
* \return
|
||||
* - -1 on precondition violated.
|
||||
* - 0 on success.
|
||||
*/
|
||||
int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height)
|
||||
{
|
||||
if (scale != 2 && scale != 3 && scale != 4)
|
||||
return -1;
|
||||
|
||||
if (pixel != 1 && pixel != 2 && pixel != 4)
|
||||
return -1;
|
||||
|
||||
switch (scale) {
|
||||
case 2 :
|
||||
case 3 :
|
||||
if (height < 2)
|
||||
return -1;
|
||||
break;
|
||||
case 4 :
|
||||
if (height < 4)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
switch (scale) {
|
||||
case 2 :
|
||||
case 4 :
|
||||
if (width < (16 / pixel))
|
||||
return -1;
|
||||
if (width % (8 / pixel) != 0)
|
||||
return -1;
|
||||
break;
|
||||
case 3 :
|
||||
if (width < 2)
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if (width < 2)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the Scale effect on a bitmap.
|
||||
* This function is simply a common interface for ::scale2x(), ::scale3x() and ::scale4x().
|
||||
* \param scale Scale factor. 2, 3 or 4.
|
||||
* \param void_dst Pointer at the first pixel of the destination bitmap.
|
||||
* \param dst_slice Size in bytes of a destination bitmap row.
|
||||
* \param void_src Pointer at the first pixel of the source bitmap.
|
||||
* \param src_slice Size in bytes of a source bitmap row.
|
||||
* \param pixel Bytes per pixel of the source and destination bitmap.
|
||||
* \param width Horizontal size in pixels of the source bitmap.
|
||||
* \param height Vertical size in pixels of the source bitmap.
|
||||
*/
|
||||
void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
|
||||
{
|
||||
switch (scale) {
|
||||
case 2 :
|
||||
scale2x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
|
||||
break;
|
||||
case 3 :
|
||||
scale3x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
|
||||
break;
|
||||
case 4 :
|
||||
scale4x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* This file is part of the Scale2x project.
|
||||
*
|
||||
* Copyright (C) 2003 Andrea Mazzoleni
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains an example implementation of the Scale effect
|
||||
* applyed to a generic bitmap.
|
||||
*
|
||||
* You can find an high level description of the effect at :
|
||||
*
|
||||
* http://scale2x.sourceforge.net/
|
||||
*
|
||||
* Alternatively at the previous license terms, you are allowed to use this
|
||||
* code in your program with these conditions:
|
||||
* - the program is not used in commercial activities.
|
||||
* - the whole source code of the program is released with the binary.
|
||||
* - derivative works of the program are allowed.
|
||||
*/
|
||||
|
||||
#ifndef __SCALEBIT_H
|
||||
#define __SCALEBIT_H
|
||||
|
||||
int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height);
|
||||
void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,843 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "scalebit.h"
|
||||
#include "hq2x.h"
|
||||
#include "hq3x.h"
|
||||
|
||||
#include "../../types.h"
|
||||
|
||||
static uint32 CBM[3];
|
||||
static uint32 *palettetranslate=0;
|
||||
|
||||
static uint16 *specbuf=NULL; // 8bpp -> 16bpp, pre hq2x/hq3x
|
||||
static uint32 *specbuf32bpp = NULL; // Buffer to hold output
|
||||
// of hq2x/hq3x when converting
|
||||
// to 16bpp and 24bpp
|
||||
static int backBpp, backshiftr[3], backshiftl[3];
|
||||
//static uint32 backmask[3];
|
||||
|
||||
static uint8 *specbuf8bpp = NULL; // For 2xscale, 3xscale.
|
||||
|
||||
|
||||
static int silt;
|
||||
|
||||
static int Bpp; // BYTES per pixel
|
||||
static int highefx;
|
||||
|
||||
#define BLUR_RED 20
|
||||
#define BLUR_GREEN 20
|
||||
#define BLUR_BLUE 10
|
||||
|
||||
#define FVB_SCANLINES 1
|
||||
|
||||
/* The blur effect is only available for bpp>=16. It could be easily modified
|
||||
to look like what happens on the real NES and TV, but lack of decent
|
||||
synchronization to the vertical retrace period makes it look rather
|
||||
blah.
|
||||
*/
|
||||
#define FVB_BLUR 2
|
||||
|
||||
static void CalculateShift(uint32 *CBM, int *cshiftr, int *cshiftl)
|
||||
{
|
||||
int a,x,z,y;
|
||||
cshiftl[0]=cshiftl[1]=cshiftl[2]=-1;
|
||||
for(a=0;a<3;a++)
|
||||
{
|
||||
for(x=0,y=-1,z=0;x<32;x++)
|
||||
{
|
||||
if(CBM[a]&(1<<x))
|
||||
{
|
||||
if(cshiftl[a]==-1) cshiftl[a]=x;
|
||||
z++;
|
||||
}
|
||||
}
|
||||
cshiftr[a]=(8-z);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int efx, int specfilt)
|
||||
{
|
||||
if(specfilt == 2 || specfilt == 4) // scale2x and scale3x
|
||||
{
|
||||
int multi;
|
||||
|
||||
if(specfilt == 2) multi = 2 * 2;
|
||||
else if(specfilt == 4) multi = 3 * 3;
|
||||
|
||||
specbuf8bpp = malloc(256*240*multi);
|
||||
|
||||
}
|
||||
else if(specfilt == 1 || specfilt == 3) // hq2x and hq3x
|
||||
{
|
||||
if(b == 1)
|
||||
return(0);
|
||||
|
||||
if(b == 2 || b == 3) // 8->16->(hq2x)->32-> 24 or 16. YARGH.
|
||||
{
|
||||
uint32 tmpCBM[3];
|
||||
backBpp = b;
|
||||
tmpCBM[0]=rmask;
|
||||
tmpCBM[1]=gmask;
|
||||
tmpCBM[2]=bmask;
|
||||
|
||||
CalculateShift(tmpCBM, backshiftr, backshiftl);
|
||||
|
||||
if(b == 2)
|
||||
{
|
||||
// ark
|
||||
backshiftr[0] += 16;
|
||||
backshiftr[1] += 8;
|
||||
backshiftr[2] += 0;
|
||||
|
||||
// Begin iffy code(requires 16bpp and 32bpp to have same RGB order)
|
||||
//backmask[0] = (rmask>>backshiftl[0]) << (backshiftr[0]);
|
||||
//backmask[1] = (gmask>>backshiftl[1]) << (backshiftr[1]);
|
||||
//backmask[2] = (bmask>>backshiftl[2]) << (backshiftr[2]);
|
||||
|
||||
//int x;
|
||||
//for(x=0;x<3;x++)
|
||||
// backshiftr[x] -= backshiftl[x];
|
||||
// End iffy code
|
||||
}
|
||||
if(specfilt == 1) specbuf32bpp = malloc(256*240*4*sizeof(uint32));
|
||||
else if(specfilt == 3) specbuf32bpp = malloc(256*240*9*sizeof(uint32));
|
||||
}
|
||||
|
||||
efx=0;
|
||||
b=2;
|
||||
rmask=0x1F<<11;
|
||||
gmask=0x3F<<5;
|
||||
bmask=0x1F;
|
||||
|
||||
if(specfilt == 3)
|
||||
hq3x_InitLUTs();
|
||||
else
|
||||
hq2x_InitLUTs();
|
||||
|
||||
specbuf=malloc(256*240*sizeof(uint16));
|
||||
}
|
||||
|
||||
silt = specfilt;
|
||||
|
||||
Bpp=b;
|
||||
|
||||
highefx=efx;
|
||||
|
||||
if(Bpp<=1 || Bpp>4)
|
||||
return(0);
|
||||
|
||||
if(efx&FVB_BLUR)
|
||||
{
|
||||
if(Bpp==2)
|
||||
palettetranslate=(uint32 *)malloc(65536*4);
|
||||
else if(Bpp>=3)
|
||||
palettetranslate=(uint32 *)malloc(65536*4);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(Bpp==2)
|
||||
palettetranslate=(uint32*)malloc(65536*4);
|
||||
else if(Bpp>=3)
|
||||
palettetranslate=(uint32*)malloc(256*4);
|
||||
}
|
||||
|
||||
if(!palettetranslate)
|
||||
return(0);
|
||||
|
||||
|
||||
CBM[0]=rmask;
|
||||
CBM[1]=gmask;
|
||||
CBM[2]=bmask;
|
||||
return(1);
|
||||
}
|
||||
|
||||
void KillBlitToHigh(void)
|
||||
{
|
||||
if(palettetranslate)
|
||||
{
|
||||
free(palettetranslate);
|
||||
palettetranslate=NULL;
|
||||
}
|
||||
|
||||
if(specbuf8bpp)
|
||||
{
|
||||
free(specbuf8bpp);
|
||||
specbuf8bpp = NULL;
|
||||
}
|
||||
if(specbuf32bpp)
|
||||
{
|
||||
free(specbuf32bpp);
|
||||
specbuf32bpp = NULL;
|
||||
}
|
||||
if(specbuf)
|
||||
{
|
||||
if(silt == 3)
|
||||
hq3x_Kill();
|
||||
else
|
||||
hq2x_Kill();
|
||||
specbuf=NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SetPaletteBlitToHigh(uint8 *src)
|
||||
{
|
||||
int cshiftr[3];
|
||||
int cshiftl[3];
|
||||
int x,y;
|
||||
|
||||
CalculateShift(CBM, cshiftr, cshiftl);
|
||||
|
||||
switch(Bpp)
|
||||
{
|
||||
case 2:
|
||||
if(highefx&FVB_BLUR)
|
||||
{
|
||||
for(x=0;x<256;x++)
|
||||
{
|
||||
uint32 r,g,b;
|
||||
for(y=0;y<256;y++)
|
||||
{
|
||||
r=src[x<<2]*(100-BLUR_RED);
|
||||
g=src[(x<<2)+1]*(100-BLUR_GREEN);
|
||||
b=src[(x<<2)+2]*(100-BLUR_BLUE);
|
||||
|
||||
r+=src[y<<2]*BLUR_RED;
|
||||
g+=src[(y<<2)+1]*BLUR_GREEN;
|
||||
b+=src[(y<<2)+2]*BLUR_BLUE;
|
||||
r/=100;
|
||||
g/=100;
|
||||
b/=100;
|
||||
|
||||
if(r>255) r=255; if(g>255) g=255; if(b>255) b=255;
|
||||
palettetranslate[x|(y<<8)]=((r>>cshiftr[0])<<cshiftl[0])|
|
||||
((g>>cshiftr[1])<<cshiftl[1])|
|
||||
((b>>cshiftr[2])<<cshiftl[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
for(x=0;x<65536;x++)
|
||||
{
|
||||
uint16 lower,upper;
|
||||
|
||||
lower=(src[((x&255)<<2)]>>cshiftr[0])<<cshiftl[0];
|
||||
lower|=(src[((x&255)<<2)+1]>>cshiftr[1])<<cshiftl[1];
|
||||
lower|=(src[((x&255)<<2)+2]>>cshiftr[2])<<cshiftl[2];
|
||||
upper=(src[((x>>8)<<2)]>>cshiftr[0])<<cshiftl[0];
|
||||
upper|=(src[((x>>8)<<2)+1]>>cshiftr[1])<<cshiftl[1];
|
||||
upper|=(src[((x>>8)<<2)+2]>>cshiftr[2])<<cshiftl[2];
|
||||
|
||||
palettetranslate[x]=lower|(upper<<16);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
for(x=0;x<256;x++)
|
||||
{
|
||||
uint32 r,g,b;
|
||||
|
||||
if(!(highefx&FVB_BLUR))
|
||||
{
|
||||
r=src[x<<2];
|
||||
g=src[(x<<2)+1];
|
||||
b=src[(x<<2)+2];
|
||||
palettetranslate[x]=(r<<cshiftl[0])|(g<<cshiftl[1])|(b<<cshiftl[2]);
|
||||
}
|
||||
else
|
||||
for(y=0;y<256;y++)
|
||||
{
|
||||
r=src[x<<2]*(100-BLUR_RED);
|
||||
g=src[(x<<2)+1]*(100-BLUR_GREEN);
|
||||
b=src[(x<<2)+2]*(100-BLUR_BLUE);
|
||||
|
||||
r+=src[y<<2]*BLUR_RED;
|
||||
g+=src[(y<<2)+1]*BLUR_GREEN;
|
||||
b+=src[(y<<2)+2]*BLUR_BLUE;
|
||||
|
||||
r/=100;
|
||||
g/=100;
|
||||
b/=100;
|
||||
if(r>255) r=255; if(g>255) g=255; if(b>255) b=255;
|
||||
|
||||
palettetranslate[x|(y<<8)]=(r<<cshiftl[0])|(g<<cshiftl[1])|(b<<cshiftl[2]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void Blit32to24(uint32 *src, uint8 *dest, int xr, int yr, int dpitch)
|
||||
{
|
||||
int x,y;
|
||||
|
||||
for(y=yr;y;y--)
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
uint32 tmp = *src;
|
||||
*dest = tmp;
|
||||
dest++;
|
||||
*dest = tmp>>8;
|
||||
dest++;
|
||||
*dest = tmp>>16;
|
||||
dest++;
|
||||
src++;
|
||||
}
|
||||
dest += dpitch / 3 - xr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Blit32to16(uint32 *src, uint16 *dest, int xr, int yr, int dpitch,
|
||||
int shiftr[3], int shiftl[3])
|
||||
{
|
||||
int x,y;
|
||||
//printf("%d\n",shiftl[1]);
|
||||
for(y=yr;y;y--)
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
uint32 tmp = *src;
|
||||
uint16 dtmp;
|
||||
|
||||
// Begin iffy code
|
||||
//dtmp = (tmp & backmask[2]) >> shiftr[2];
|
||||
//dtmp |= (tmp & backmask[1]) >> shiftr[1];
|
||||
//dtmp |= (tmp & backmask[0]) >> shiftr[0];
|
||||
// End iffy code
|
||||
|
||||
// Begin non-iffy code
|
||||
dtmp = ((tmp&0x0000FF) >> shiftr[2]) << shiftl[2];
|
||||
dtmp |= ((tmp&0x00FF00) >> shiftr[1]) << shiftl[1];
|
||||
dtmp |= ((tmp&0xFF0000) >> shiftr[0]) << shiftl[0];
|
||||
// End non-iffy code
|
||||
|
||||
//dtmp = ((tmp&0x0000FF) >> 3);
|
||||
//dtmp |= ((tmp&0x00FC00) >>5);
|
||||
//dtmp |= ((tmp&0xF80000) >>8);
|
||||
|
||||
*dest = dtmp;
|
||||
src++;
|
||||
dest++;
|
||||
}
|
||||
dest += dpitch / 2 - xr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Blit8To8(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale, int efx, int special)
|
||||
{
|
||||
int x,y;
|
||||
int pinc;
|
||||
|
||||
if(special==2)
|
||||
{
|
||||
if(xscale!=2 || yscale!=2) return;
|
||||
|
||||
scale(2,dest,pitch,src,256,1,xr,yr);
|
||||
return;
|
||||
}
|
||||
|
||||
if(special==4)
|
||||
{
|
||||
if(xscale!=3 || yscale!=3) return;
|
||||
scale(3,dest,pitch,src,256,1,xr,yr);
|
||||
return;
|
||||
}
|
||||
|
||||
pinc=pitch-(xr*xscale);
|
||||
if(xscale!=1 || yscale!=1)
|
||||
{
|
||||
if(efx&FVB_SCANLINES)
|
||||
{
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale-(yscale>>1);
|
||||
do
|
||||
{
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
*(uint8 *)dest=*(uint8 *)src;
|
||||
dest++;
|
||||
} while(--too);
|
||||
}
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
//src-=xr*(yscale-(yscale>>1));
|
||||
dest+=pitch*(yscale>>1);
|
||||
|
||||
src+=xr;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale;
|
||||
do
|
||||
{
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
*(uint8 *)dest=*(uint8 *)src;
|
||||
dest++;
|
||||
} while(--too);
|
||||
}
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
src+=xr;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
for(y=yr;y;y--,dest+=pinc,src+=256-xr)
|
||||
for(x=xr;x;x-=4,dest+=4,src+=4)
|
||||
*(uint32 *)dest=*(uint32 *)src;
|
||||
}
|
||||
}
|
||||
|
||||
/* Todo: Make sure 24bpp code works right with big-endian cpus */
|
||||
|
||||
void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch,
|
||||
int xscale, int yscale)
|
||||
{
|
||||
int x,y;
|
||||
int pinc;
|
||||
uint8 *destbackup = NULL; /* For hq2x */
|
||||
int pitchbackup = 0;
|
||||
|
||||
//static int google=0;
|
||||
//google^=1;
|
||||
|
||||
if(specbuf8bpp) // 2xscale/3xscale
|
||||
{
|
||||
int mult;
|
||||
int base;
|
||||
|
||||
if(silt == 2) mult = 2;
|
||||
else mult = 3;
|
||||
|
||||
Blit8To8(src, specbuf8bpp, xr, yr, 256*mult, xscale, yscale, 0, silt);
|
||||
|
||||
xr *= mult;
|
||||
yr *= mult;
|
||||
xscale=yscale=1;
|
||||
src = specbuf8bpp;
|
||||
base = 256*mult;
|
||||
|
||||
switch(Bpp)
|
||||
{
|
||||
case 4:
|
||||
pinc=pitch-(xr<<2);
|
||||
for(y=yr;y;y--,src+=base-xr)
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[(uint32)*src];
|
||||
dest+=4;
|
||||
src++;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
pinc=pitch-(xr+xr+xr);
|
||||
for(y=yr;y;y--,src+=base-xr)
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
uint32 tmp=palettetranslate[(uint32)*src];
|
||||
*(uint8 *)dest=tmp;
|
||||
*((uint8 *)dest+1)=tmp>>8;
|
||||
*((uint8 *)dest+2)=tmp>>16;
|
||||
dest+=3;
|
||||
src++;
|
||||
src++;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
pinc=pitch-(xr<<1);
|
||||
|
||||
for(y=yr;y;y--,src+=base-xr)
|
||||
{
|
||||
for(x=xr>>1;x;x--)
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[*(uint16 *)src];
|
||||
dest+=4;
|
||||
src+=2;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if(specbuf)
|
||||
{
|
||||
destbackup=dest;
|
||||
dest=(uint8 *)specbuf;
|
||||
pitchbackup=pitch;
|
||||
|
||||
pitch=xr*sizeof(uint16);
|
||||
xscale=1;
|
||||
yscale=1;
|
||||
}
|
||||
|
||||
if(highefx&FVB_BLUR) // DONE
|
||||
{
|
||||
if(xscale!=1 || yscale!=1 || (highefx&FVB_SCANLINES)) // DONE
|
||||
{
|
||||
switch(Bpp)
|
||||
{
|
||||
case 4:
|
||||
pinc=pitch-((xr*xscale)<<2);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale;
|
||||
|
||||
if(highefx&FVB_SCANLINES)
|
||||
doo-=yscale>>1;
|
||||
do
|
||||
{
|
||||
uint8 last=0x00;
|
||||
|
||||
//if(doo == 1 && google) dest+=4;
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[*src|(last<<8)];
|
||||
dest+=4;
|
||||
} while(--too);
|
||||
last=*src;
|
||||
}
|
||||
//if(doo == 1 && google) dest-=4;
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
src+=xr;
|
||||
if(highefx&FVB_SCANLINES)
|
||||
dest+=pitch*(yscale>>1);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
pinc=pitch-((xr*xscale)*3);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale;
|
||||
|
||||
if(highefx&FVB_SCANLINES)
|
||||
doo-=yscale>>1;
|
||||
do
|
||||
{
|
||||
uint8 last=0x00;
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[*src|(last<<8)];
|
||||
dest+=3;
|
||||
} while(--too);
|
||||
last=*src;
|
||||
}
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
src+=xr;
|
||||
if(highefx&FVB_SCANLINES)
|
||||
dest+=pitch*(yscale>>1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
pinc=pitch-((xr*xscale)<<1);
|
||||
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale;
|
||||
|
||||
if(highefx& FVB_SCANLINES)
|
||||
doo-=yscale>>1;
|
||||
do
|
||||
{
|
||||
uint8 last=0x00;
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
*(uint16 *)dest=palettetranslate[*src|(last<<8)];
|
||||
dest+=2;
|
||||
} while(--too);
|
||||
last=*src;
|
||||
}
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
src+=xr;
|
||||
if(highefx&FVB_SCANLINES)
|
||||
dest+=pitch*(yscale>>1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // No scaling, no scanlines, just blurring. - DONE
|
||||
switch(Bpp)
|
||||
{
|
||||
case 4:
|
||||
pinc=pitch-(xr<<2);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
uint8 last=0x00;
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[*src|(last<<8)];
|
||||
last=*src;
|
||||
dest+=4;
|
||||
src++;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
pinc=pitch-(xr+xr+xr);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
uint8 last=0x00;
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
uint32 tmp=palettetranslate[*src|(last<<8)];
|
||||
last=*src;
|
||||
*(uint8 *)dest=tmp;
|
||||
*((uint8 *)dest+1)=tmp>>8;
|
||||
*((uint8 *)dest+2)=tmp>>16;
|
||||
dest+=3;
|
||||
src++;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
pinc=pitch-(xr<<1);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
uint8 last=0x00;
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
*(uint16 *)dest=palettetranslate[*src|(last<<8)];
|
||||
last=*src;
|
||||
dest+=2;
|
||||
src++;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else // No blur effects.
|
||||
{
|
||||
if(xscale!=1 || yscale!=1 || (highefx&FVB_SCANLINES))
|
||||
{
|
||||
switch(Bpp)
|
||||
{
|
||||
case 4:
|
||||
pinc=pitch-((xr*xscale)<<2);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale;
|
||||
|
||||
if(highefx& FVB_SCANLINES)
|
||||
doo-=yscale>>1;
|
||||
do
|
||||
{
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[*src];
|
||||
dest+=4;
|
||||
} while(--too);
|
||||
}
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
src+=xr;
|
||||
if(highefx&FVB_SCANLINES)
|
||||
dest+=pitch*(yscale>>1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
pinc=pitch-((xr*xscale)*3);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale;
|
||||
|
||||
if(highefx& FVB_SCANLINES)
|
||||
doo-=yscale>>1;
|
||||
do
|
||||
{
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
uint32 tmp=palettetranslate[(uint32)*src];
|
||||
*(uint8 *)dest=tmp;
|
||||
*((uint8 *)dest+1)=tmp>>8;
|
||||
*((uint8 *)dest+2)=tmp>>16;
|
||||
dest+=3;
|
||||
|
||||
//*(uint32 *)dest=palettetranslate[*src];
|
||||
//dest+=4;
|
||||
} while(--too);
|
||||
}
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
src+=xr;
|
||||
if(highefx&FVB_SCANLINES)
|
||||
dest+=pitch*(yscale>>1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
pinc=pitch-((xr*xscale)<<1);
|
||||
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
int doo=yscale;
|
||||
|
||||
if(highefx& FVB_SCANLINES)
|
||||
doo-=yscale>>1;
|
||||
do
|
||||
{
|
||||
for(x=xr;x;x--,src++)
|
||||
{
|
||||
int too=xscale;
|
||||
do
|
||||
{
|
||||
*(uint16 *)dest=palettetranslate[*src];
|
||||
dest+=2;
|
||||
} while(--too);
|
||||
}
|
||||
src-=xr;
|
||||
dest+=pinc;
|
||||
} while(--doo);
|
||||
src+=xr;
|
||||
if(highefx&FVB_SCANLINES)
|
||||
dest+=pitch*(yscale>>1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
switch(Bpp)
|
||||
{
|
||||
case 4:
|
||||
pinc=pitch-(xr<<2);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[(uint32)*src];
|
||||
dest+=4;
|
||||
src++;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
pinc=pitch-(xr+xr+xr);
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
for(x=xr;x;x--)
|
||||
{
|
||||
uint32 tmp=palettetranslate[(uint32)*src];
|
||||
*(uint8 *)dest=tmp;
|
||||
*((uint8 *)dest+1)=tmp>>8;
|
||||
*((uint8 *)dest+2)=tmp>>16;
|
||||
dest+=3;
|
||||
src++;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
pinc=pitch-(xr<<1);
|
||||
|
||||
for(y=yr;y;y--,src+=256-xr)
|
||||
{
|
||||
for(x=xr>>1;x;x--)
|
||||
{
|
||||
*(uint32 *)dest=palettetranslate[*(uint16 *)src];
|
||||
dest+=4;
|
||||
src+=2;
|
||||
}
|
||||
dest+=pinc;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(specbuf)
|
||||
{
|
||||
if(specbuf32bpp)
|
||||
{
|
||||
int mult = (silt == 3)?3:2;
|
||||
|
||||
if(silt == 3)
|
||||
hq3x_32((uint8 *)specbuf,(uint8*)specbuf32bpp,xr,yr,xr*3*sizeof(uint32));
|
||||
else
|
||||
hq2x_32((uint8 *)specbuf,(uint8*)specbuf32bpp,xr,yr,xr*2*sizeof(uint32));
|
||||
|
||||
if(backBpp == 2)
|
||||
Blit32to16(specbuf32bpp, (uint16*)destbackup, xr*mult, yr*mult, pitchbackup, backshiftr,backshiftl);
|
||||
else // == 3
|
||||
Blit32to24(specbuf32bpp, (uint8*)destbackup, xr*mult, yr*mult, pitchbackup);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(silt == 3)
|
||||
hq3x_32((uint8 *)specbuf,destbackup,xr,yr,pitchbackup);
|
||||
else
|
||||
hq2x_32((uint8 *)specbuf,destbackup,xr,yr,pitchbackup);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int eefx, int specfilt);
|
||||
void SetPaletteBlitToHigh(uint8 *src);
|
||||
void KillBlitToHigh(void);
|
||||
void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale);
|
||||
void Blit8To8(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale, int efx, int special);
|
|
@ -0,0 +1,72 @@
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "../common/args.h"
|
||||
#include "../common/config.h"
|
||||
|
||||
#include "input.h"
|
||||
|
||||
extern FCEUGI *CurGame;
|
||||
|
||||
extern CFGSTRUCT DriverConfig[];
|
||||
extern ARGPSTRUCT DriverArgs[];
|
||||
extern char *DriverUsage;
|
||||
|
||||
void DoDriverArgs(void);
|
||||
uint8 *GetBaseDirectory(void);
|
||||
|
||||
int InitSound(FCEUGI *gi);
|
||||
void WriteSound(int32 *Buffer, int Count);
|
||||
int KillSound(void);
|
||||
uint32 GetMaxSound(void);
|
||||
uint32 GetWriteSound(void);
|
||||
|
||||
void SilenceSound(int s); /* DOS and SDL */
|
||||
|
||||
|
||||
int InitMouse(void);
|
||||
void KillMouse(void);
|
||||
void GetMouseData(uint32 *MouseData);
|
||||
|
||||
int InitJoysticks(void);
|
||||
int KillJoysticks(void);
|
||||
uint32 *GetJSOr(void);
|
||||
|
||||
int InitKeyboard(void);
|
||||
int UpdateKeyboard(void);
|
||||
char *GetKeyboard(void);
|
||||
void KillKeyboard(void);
|
||||
|
||||
int InitVideo(FCEUGI *gi);
|
||||
int KillVideo(void);
|
||||
void BlitScreen(uint8 *XBuf);
|
||||
void LockConsole(void);
|
||||
void UnlockConsole(void);
|
||||
void ToggleFS(); /* SDL */
|
||||
|
||||
int LoadGame(const char *path);
|
||||
int CloseGame(void);
|
||||
int GUI_Init(int argc, char **argv, int (*dofunc)(void));
|
||||
int GUI_Idle(void);
|
||||
int GUI_Update(void);
|
||||
void GUI_Hide(int);
|
||||
void GUI_RequestExit(void);
|
||||
int GUI_SetVideo(int fullscreen, int width, int height);
|
||||
char *GUI_GetKeyboard(void);
|
||||
void GUI_GetMouseState(uint32 *b, int *x, int *y);
|
||||
|
||||
void UpdatePhysicalInput(void);
|
||||
int DTestButton(ButtConfig *bc);
|
||||
int DWaitButton(const uint8 *text, ButtConfig *bc, int wb);
|
||||
int ButtonConfigBegin(void);
|
||||
void ButtonConfigEnd(void);
|
||||
|
||||
void Giggles(int);
|
||||
void DoFun(void);
|
||||
|
||||
int FCEUD_NetworkConnect(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,200 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <dpmi.h>
|
||||
#include <sys/farptr.h>
|
||||
#include <go32.h>
|
||||
#include <pc.h>
|
||||
|
||||
#include "dos.h"
|
||||
#include "dos-joystick.h"
|
||||
|
||||
#define JOY_A 1
|
||||
#define JOY_B 2
|
||||
#define JOY_SELECT 4
|
||||
#define JOY_START 8
|
||||
#define JOY_UP 0x10
|
||||
#define JOY_DOWN 0x20
|
||||
#define JOY_LEFT 0x40
|
||||
#define JOY_RIGHT 0x80
|
||||
|
||||
int joy=0;
|
||||
int joyBMap[6];
|
||||
|
||||
static int32 joybuttons=0;
|
||||
static uint32 joyx=0;
|
||||
static uint32 joyy=0;
|
||||
static uint32 joyxcenter;
|
||||
static uint32 joyycenter;
|
||||
|
||||
static void ConfigJoystick(void);
|
||||
volatile int soundjoyer=0;
|
||||
volatile int soundjoyeron=0;
|
||||
|
||||
/* Crude method to detect joystick. */
|
||||
static int DetectJoystick(void)
|
||||
{
|
||||
uint8 b;
|
||||
|
||||
outportb(0x201,0);
|
||||
b=inportb(0x201);
|
||||
sleep(1);
|
||||
if((inportb(0x201)&3)==(b&3))
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
void UpdateJoyData(void)
|
||||
{
|
||||
uint32 xc,yc;
|
||||
|
||||
|
||||
joybuttons=((inportb(0x201)&0xF0)^0xF0)>>4;
|
||||
|
||||
xc=yc=0;
|
||||
|
||||
{
|
||||
outportb(0x201,0);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
uint8 b;
|
||||
|
||||
b=inportb(0x201);
|
||||
if(!(b&3))
|
||||
break;
|
||||
if(b&1) xc++;
|
||||
if(b&2) yc++;
|
||||
}
|
||||
}
|
||||
|
||||
joyx=xc;
|
||||
joyy=yc;
|
||||
}
|
||||
|
||||
uint32 GetJSOr(void)
|
||||
{
|
||||
int y;
|
||||
unsigned long ret;
|
||||
static int rtoggle=0;
|
||||
ret=0;
|
||||
|
||||
rtoggle^=1;
|
||||
if(!soundo)
|
||||
UpdateJoyData();
|
||||
for(y=0;y<6;y++)
|
||||
if((y>=4 && rtoggle) || y<4)
|
||||
if(joybuttons&joyBMap[y]) ret|=(1<<y&3)<<((joy-1)<<3);
|
||||
|
||||
if(joyx<=joyxcenter*.25) ret|=JOY_LEFT<<((joy-1)<<3);
|
||||
else if(joyx>=joyxcenter*1.75) ret|=JOY_RIGHT<<((joy-1)<<3);
|
||||
if(joyy<=joyycenter*.25) ret|=JOY_UP<<((joy-1)<<3);
|
||||
else if(joyy>=joyycenter*1.75) ret|=JOY_DOWN<<((joy-1)<<3);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int InitJoysticks(void)
|
||||
{
|
||||
if(!joy) return(0);
|
||||
if(!DetectJoystick())
|
||||
{
|
||||
printf("Joystick not detected!\n");
|
||||
joy=0;
|
||||
return 0;
|
||||
}
|
||||
if(soundo)
|
||||
{
|
||||
soundjoyeron=1;
|
||||
while(!soundjoyer);
|
||||
}
|
||||
else
|
||||
UpdateJoyData();
|
||||
|
||||
joyxcenter=joyx;
|
||||
joyycenter=joyy;
|
||||
|
||||
if(!(joyBMap[0]|joyBMap[1]|joyBMap[2]|joyBMap[3]))
|
||||
ConfigJoystick();
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void BConfig(int b)
|
||||
{
|
||||
int c=0;
|
||||
uint32 st=time(0);
|
||||
|
||||
while(time(0)< (st+4) )
|
||||
{
|
||||
if(!soundo)
|
||||
UpdateJoyData();
|
||||
if(joybuttons) c=joybuttons;
|
||||
else if(c && !joybuttons)
|
||||
{
|
||||
joyBMap[b]=c;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void KillJoysticks(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void ConfigJoystick(void)
|
||||
{
|
||||
static char *genb="** Press button for ";
|
||||
|
||||
printf("\n\n Joystick button configuration:\n\n");
|
||||
printf(" Push and release the button to map to the virtual joystick.\n");
|
||||
printf(" If you do not wish to assign a button, wait a few seconds\n");
|
||||
printf(" and the configuration will continue.\n\n");
|
||||
printf(" Press enter to continue...\n");
|
||||
getchar();
|
||||
|
||||
printf("%s\"Select\".\n",genb);
|
||||
BConfig(2);
|
||||
|
||||
printf("%s\"Start\".\n",genb);
|
||||
BConfig(3);
|
||||
|
||||
printf("%s\"B\".\n",genb);
|
||||
BConfig(1);
|
||||
|
||||
printf("%s\"A\".\n",genb);
|
||||
BConfig(0);
|
||||
|
||||
printf("%s\"Rapid fire B\".\n",genb);
|
||||
BConfig(5);
|
||||
|
||||
printf("%s\"Rapid fire A\".\n",genb);
|
||||
BConfig(4);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
void UpdateJoyData(void);
|
||||
uint32 GetJSOr(void);
|
||||
int InitJoysticks(void);
|
||||
|
||||
/* Variables to save in config file. */
|
||||
extern int joy;
|
||||
extern int joyBMap[6];
|
|
@ -0,0 +1,131 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <pc.h>
|
||||
#include <dpmi.h>
|
||||
#include <go32.h>
|
||||
#include "keyscan.h"
|
||||
|
||||
static unsigned char lastsc;
|
||||
static char keybuf[256];
|
||||
int newk;
|
||||
|
||||
/* Read scan code from port $60 */
|
||||
/* Acknowledge interrupt( output $20 to port $20) */
|
||||
|
||||
static void ihandler(_go32_dpmi_registers *r)
|
||||
{
|
||||
unsigned char scode=inp(0x60); /* Get scan code. */
|
||||
|
||||
|
||||
if(scode!=0xE0)
|
||||
{
|
||||
int offs=0;
|
||||
|
||||
/* I'm only interested in preserving the independent status of the
|
||||
right ALT and CONTROL keys.
|
||||
*/
|
||||
if(lastsc==0xE0)
|
||||
if((scode&0x7F)==SCAN_LEFTALT || (scode&0x7F)==SCAN_LEFTCONTROL)
|
||||
offs=0x80;
|
||||
|
||||
|
||||
keybuf[(scode&0x7f)|offs]=((scode&0x80)^0x80);
|
||||
newk++;
|
||||
}
|
||||
lastsc=scode;
|
||||
|
||||
outp(0x20,0x20); /* Acknowledge interrupt. */
|
||||
}
|
||||
|
||||
static _go32_dpmi_seginfo KBIBack,KBIBackRM;
|
||||
static _go32_dpmi_seginfo KBI,KBIRM;
|
||||
static _go32_dpmi_registers KBIRMRegs;
|
||||
static int initdone=0;
|
||||
|
||||
int InitKeyboard(void)
|
||||
{
|
||||
/* I'll assume that the keyboard is in the correct scancode mode(translated
|
||||
mode 2, I think).
|
||||
*/
|
||||
newk=0;
|
||||
memset(keybuf,0,sizeof(keybuf));
|
||||
KBIRM.pm_offset=KBI.pm_offset=(int)ihandler;
|
||||
KBIRM.pm_selector=KBI.pm_selector=_my_cs();
|
||||
|
||||
_go32_dpmi_get_real_mode_interrupt_vector(9,&KBIBackRM);
|
||||
_go32_dpmi_allocate_real_mode_callback_iret(&KBIRM, &KBIRMRegs);
|
||||
_go32_dpmi_set_real_mode_interrupt_vector(9,&KBIRM);
|
||||
|
||||
_go32_dpmi_get_protected_mode_interrupt_vector(9,&KBIBack);
|
||||
_go32_dpmi_allocate_iret_wrapper(&KBI);
|
||||
_go32_dpmi_set_protected_mode_interrupt_vector(9,&KBI);
|
||||
lastsc=0;
|
||||
initdone=1;
|
||||
return(1);
|
||||
}
|
||||
|
||||
void KillKeyboard(void)
|
||||
{
|
||||
if(initdone)
|
||||
{
|
||||
_go32_dpmi_set_protected_mode_interrupt_vector(9,&KBIBack);
|
||||
_go32_dpmi_free_iret_wrapper(&KBI);
|
||||
|
||||
_go32_dpmi_set_real_mode_interrupt_vector(9,&KBIBackRM);
|
||||
_go32_dpmi_free_real_mode_callback(&KBIRM);
|
||||
initdone=0;
|
||||
}
|
||||
}
|
||||
|
||||
/* In FCE Ultra, it doesn't matter if the key states change
|
||||
in the middle of the keyboard handling code. If you want
|
||||
to use this code elsewhere, you may want to memcpy() keybuf
|
||||
to another buffer and return that when GetKeyboard() is
|
||||
called.
|
||||
*/
|
||||
|
||||
char *GetKeyboard(void)
|
||||
{
|
||||
return keybuf;
|
||||
}
|
||||
|
||||
/* Returns 1 on new scan codes generated, 0 on no new scan codes. */
|
||||
int UpdateKeyboard(void)
|
||||
{
|
||||
int t=newk;
|
||||
|
||||
if(t)
|
||||
{
|
||||
asm volatile(
|
||||
"subl %%eax,_newk\n\t"
|
||||
:
|
||||
: "a" (t)
|
||||
);
|
||||
|
||||
if(keybuf[SCAN_LEFTCONTROL] && keybuf[SCAN_C])
|
||||
raise(SIGINT);
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <dpmi.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dos.h"
|
||||
|
||||
int InitMouse(void)
|
||||
{
|
||||
__dpmi_regs regs;
|
||||
|
||||
memset(®s,0,sizeof(regs));
|
||||
regs.x.ax=0;
|
||||
__dpmi_int(0x33,®s);
|
||||
if(regs.x.ax!=0xFFFF)
|
||||
return(0);
|
||||
|
||||
memset(®s,0,sizeof(regs));
|
||||
regs.x.ax=0x7;
|
||||
regs.x.cx=0; // Min X
|
||||
regs.x.dx=260; // Max X
|
||||
__dpmi_int(0x33,®s);
|
||||
|
||||
memset(®s,0,sizeof(regs));
|
||||
regs.x.ax=0x8;
|
||||
regs.x.cx=0; // Min Y
|
||||
regs.x.dx=260; // Max Y
|
||||
__dpmi_int(0x33,®s);
|
||||
|
||||
memset(®s,0,sizeof(regs));
|
||||
regs.x.ax=0xF;
|
||||
regs.x.cx=8; // Mickey X
|
||||
regs.x.dx=8; // Mickey Y
|
||||
__dpmi_int(0x33,®s);
|
||||
|
||||
memset(®s,0,sizeof(regs));
|
||||
regs.x.ax=0x2;
|
||||
__dpmi_int(0x33,®s);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
uint32 GetMouseData(uint32 *x, uint32 *y)
|
||||
{
|
||||
if(FCEUI_IsMovieActive()<0)
|
||||
return;
|
||||
|
||||
__dpmi_regs regs;
|
||||
|
||||
memset(®s,0,sizeof(regs));
|
||||
regs.x.ax=0x3;
|
||||
__dpmi_int(0x33,®s);
|
||||
|
||||
*x=regs.x.cx;
|
||||
*y=regs.x.dx;
|
||||
return(regs.x.bx&3);
|
||||
}
|
||||
|
||||
void KillMouse(void)
|
||||
{
|
||||
|
||||
}
|
|
@ -0,0 +1,567 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/farptr.h>
|
||||
#include <pc.h>
|
||||
#include <dos.h>
|
||||
#include <dpmi.h>
|
||||
#include <go32.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "dos.h"
|
||||
#include "dos-sound.h"
|
||||
#include "dos-joystick.h"
|
||||
|
||||
|
||||
static void SBIRQHandler(_go32_dpmi_registers *r);
|
||||
static uint32 LMBuffer; /* Address of low memory DMA playback buffer. */
|
||||
static int LMSelector;
|
||||
|
||||
static uint8 *WaveBuffer;
|
||||
static unsigned int IVector, SBIRQ, SBDMA, SBDMA16, SBPort;
|
||||
static int DSPV,hsmode;
|
||||
static int format;
|
||||
static int frags, fragsize, fragtotal;
|
||||
static volatile int WritePtr, ReadPtr;
|
||||
static volatile int hbusy;
|
||||
static volatile int whichbuf;
|
||||
|
||||
|
||||
static uint8 PICMask;
|
||||
/* Protected mode interrupt vector info. */
|
||||
static _go32_dpmi_seginfo SBIH,SBIHOld;
|
||||
|
||||
/* Real mode interrupt vector info. */
|
||||
static _go32_dpmi_seginfo SBIHRM,SBIHRMOld;
|
||||
static _go32_dpmi_registers SBIHRMRegs;
|
||||
|
||||
static int WriteDSP(uint8 V)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=65536;x;x--)
|
||||
{
|
||||
if(!(inportb(SBPort+0xC)&0x80))
|
||||
{
|
||||
outportb(SBPort+0xC,V);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int ReadDSP(uint8 *V)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=65536;x;x--) /* Should be more than enough time... */
|
||||
{
|
||||
if(inportb(SBPort+0xE)&0x80)
|
||||
{
|
||||
*V=inportb(SBPort+0xA);
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
static int SetVectors(void)
|
||||
{
|
||||
SBIH.pm_offset=SBIHRM.pm_offset=(int)SBIRQHandler;
|
||||
SBIH.pm_selector=SBIHRM.pm_selector=_my_cs();
|
||||
|
||||
/* Get and set real mode interrupt vector. */
|
||||
_go32_dpmi_get_real_mode_interrupt_vector(IVector,&SBIHRMOld);
|
||||
_go32_dpmi_allocate_real_mode_callback_iret(&SBIHRM, &SBIHRMRegs);
|
||||
_go32_dpmi_set_real_mode_interrupt_vector(IVector,&SBIHRM);
|
||||
|
||||
/* Get and set protected mode interrupt vector. */
|
||||
_go32_dpmi_get_protected_mode_interrupt_vector(IVector,&SBIHOld);
|
||||
_go32_dpmi_allocate_iret_wrapper(&SBIH);
|
||||
_go32_dpmi_set_protected_mode_interrupt_vector(IVector,&SBIH);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void ResetVectors(void)
|
||||
{
|
||||
_go32_dpmi_set_protected_mode_interrupt_vector(IVector,&SBIHOld);
|
||||
_go32_dpmi_free_iret_wrapper(&SBIH);
|
||||
_go32_dpmi_set_real_mode_interrupt_vector(IVector,&SBIHRMOld);
|
||||
_go32_dpmi_free_real_mode_callback(&SBIHRM);
|
||||
}
|
||||
|
||||
int GetBLASTER(void)
|
||||
{
|
||||
int check=0;
|
||||
char *s;
|
||||
|
||||
if(!(s=getenv("BLASTER")))
|
||||
{
|
||||
puts(" Error getting BLASTER environment variable.");
|
||||
return(0);
|
||||
}
|
||||
|
||||
while(*s)
|
||||
{
|
||||
switch(toupper(*s))
|
||||
{
|
||||
case 'A': check|=(sscanf(s+1,"%x",&SBPort)==1)?1:0;break;
|
||||
case 'I': check|=(sscanf(s+1,"%d",&SBIRQ)==1)?2:0;break;
|
||||
case 'D': check|=(sscanf(s+1,"%d",&SBDMA)==1)?4:0;break;
|
||||
case 'H': check|=(sscanf(s+1,"%d",&SBDMA16)==1)?8:0;break;
|
||||
}
|
||||
s++;
|
||||
}
|
||||
|
||||
if((check^7)&7 || SBDMA>=4 || (SBDMA16<=4 && check&8) || SBIRQ>15)
|
||||
{
|
||||
puts(" Invalid or incomplete BLASTER environment variable.");
|
||||
return(0);
|
||||
}
|
||||
if(!(check&8))
|
||||
format=0;
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int ResetDSP(void)
|
||||
{
|
||||
uint8 b;
|
||||
|
||||
outportb(SBPort+0x6,0x1);
|
||||
delay(10);
|
||||
outportb(SBPort+0x6,0x0);
|
||||
delay(10);
|
||||
|
||||
if(ReadDSP(&b))
|
||||
if(b==0xAA)
|
||||
return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int GetDSPVersion(void)
|
||||
{
|
||||
int ret;
|
||||
uint8 t;
|
||||
|
||||
if(!WriteDSP(0xE1))
|
||||
return(0);
|
||||
if(!ReadDSP(&t))
|
||||
return(0);
|
||||
ret=t<<8;
|
||||
if(!ReadDSP(&t))
|
||||
return(0);
|
||||
ret|=t;
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static void KillDMABuffer(void)
|
||||
{
|
||||
__dpmi_free_dos_memory(LMSelector);
|
||||
}
|
||||
|
||||
static int MakeDMABuffer(void)
|
||||
{
|
||||
uint32 size;
|
||||
int32 tmp;
|
||||
|
||||
size=fragsize*2; /* Two buffers in the DMA buffer. */
|
||||
size<<=format; /* Twice the size for 16-bit than for 8-bit. */
|
||||
|
||||
size<<=1; /* Double the size in case the first 2 buffers
|
||||
cross a 64KB or 128KB page boundary.
|
||||
*/
|
||||
size=(size+15)>>4; /* Convert to paragraphs */
|
||||
|
||||
if((tmp=__dpmi_allocate_dos_memory(size,&LMSelector))<0)
|
||||
return(0);
|
||||
|
||||
LMBuffer=tmp<<=4;
|
||||
|
||||
if(format) /* Check for and fix 128KB page boundary crossing. */
|
||||
{
|
||||
if((LMBuffer&0x20000) != ((LMBuffer+fragsize*2*2-1)&0x20000))
|
||||
LMBuffer+=fragsize*2*2;
|
||||
}
|
||||
else /* Check for and fix 64KB page boundary crossing. */
|
||||
{
|
||||
if((LMBuffer&0x10000) != ((LMBuffer+fragsize*2-1)&0x10000))
|
||||
LMBuffer+=fragsize*2;
|
||||
}
|
||||
|
||||
DOSMemSet(LMBuffer, format?0:128, (fragsize*2)<<format);
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
static void ProgramDMA(void)
|
||||
{
|
||||
static int PPorts[8]={0x87,0x83,0x81,0x82,0,0x8b,0x89,0x8a};
|
||||
uint32 tmp;
|
||||
|
||||
if(format)
|
||||
{
|
||||
outportb(0xd4,(SBDMA16&0x3)|0x4);
|
||||
outportb(0xd8,0x0);
|
||||
outportb(0xd6,(SBDMA16&0x3)|0x58);
|
||||
tmp=((SBDMA16&3)<<2)+0xC2;
|
||||
}
|
||||
else
|
||||
{
|
||||
outportb(0xA,SBDMA|0x4);
|
||||
outportb(0xC,0x0);
|
||||
outportb(0xB,SBDMA|0x58);
|
||||
tmp=(SBDMA<<1)+1;
|
||||
}
|
||||
|
||||
/* Size of entire buffer. */
|
||||
outportb(tmp,(fragsize*2-1));
|
||||
outportb(tmp,(fragsize*2-1)>>8);
|
||||
|
||||
/* Page of buffer. */
|
||||
outportb(PPorts[format?SBDMA16:SBDMA],LMBuffer>>16);
|
||||
|
||||
/* Offset of buffer within page. */
|
||||
if(format)
|
||||
tmp=((SBDMA16&3)<<2)+0xc0;
|
||||
else
|
||||
tmp=SBDMA<<1;
|
||||
|
||||
outportb(tmp,(LMBuffer>>format));
|
||||
outportb(tmp,(LMBuffer>>(8+format)));
|
||||
}
|
||||
|
||||
int InitSB(int Rate, int bittage)
|
||||
{
|
||||
hsmode=hbusy=0;
|
||||
whichbuf=1;
|
||||
puts("Initializing Sound Blaster...");
|
||||
|
||||
format=bittage?1:0;
|
||||
frags=8;
|
||||
|
||||
if(Rate<=11025)
|
||||
fragsize=1<<5;
|
||||
else if(Rate<=22050)
|
||||
fragsize=1<<6;
|
||||
else
|
||||
fragsize=1<<7;
|
||||
|
||||
fragtotal=frags*fragsize;
|
||||
WaveBuffer=malloc(fragtotal<<format);
|
||||
|
||||
if(format)
|
||||
memset(WaveBuffer,0,fragtotal*2);
|
||||
else
|
||||
memset(WaveBuffer,128,fragtotal);
|
||||
|
||||
WritePtr=ReadPtr=0;
|
||||
|
||||
if((Rate<8192) || (Rate>65535))
|
||||
{
|
||||
printf(" Unsupported playback rate: %d samples per second\n",Rate);
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(!GetBLASTER())
|
||||
return(0);
|
||||
|
||||
/* Disable IRQ line in PIC0 or PIC1 */
|
||||
if(SBIRQ>7)
|
||||
{
|
||||
PICMask=inportb(0xA1);
|
||||
outportb(0xA1,PICMask|(1<<(SBIRQ&7)));
|
||||
}
|
||||
else
|
||||
{
|
||||
PICMask=inportb(0x21);
|
||||
outportb(0x21,PICMask|(1<<SBIRQ));
|
||||
}
|
||||
if(!ResetDSP())
|
||||
{
|
||||
puts(" Error resetting the DSP.");
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(!(DSPV=GetDSPVersion()))
|
||||
{
|
||||
puts(" Error getting the DSP version.");
|
||||
return(0);
|
||||
}
|
||||
|
||||
printf(" DSP Version: %d.%d\n",DSPV>>8,DSPV&0xFF);
|
||||
if(DSPV<0x201)
|
||||
{
|
||||
printf(" DSP version number is too low.\n");
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(DSPV<0x400)
|
||||
format=0;
|
||||
if(!MakeDMABuffer())
|
||||
{
|
||||
puts(" Error creating low-memory DMA buffer.");
|
||||
return(0);
|
||||
}
|
||||
|
||||
if(SBIRQ>7) IVector=SBIRQ+0x68;
|
||||
else IVector=SBIRQ+0x8;
|
||||
|
||||
if(!SetVectors())
|
||||
{
|
||||
puts(" Error setting interrupt vectors.");
|
||||
KillDMABuffer();
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Reenable IRQ line. */
|
||||
if(SBIRQ>7)
|
||||
outportb(0xA1,PICMask&(~(1<<(SBIRQ&7))));
|
||||
else
|
||||
outportb(0x21,PICMask&(~(1<<SBIRQ)));
|
||||
|
||||
ProgramDMA();
|
||||
|
||||
/* Note that the speaker must always be turned on before the mode transfer
|
||||
byte is sent to the DSP if we're going into high-speed mode, since
|
||||
a real Sound Blaster(at least my SBPro) won't accept DSP commands(except
|
||||
for the reset "command") after it goes into high-speed mode.
|
||||
*/
|
||||
WriteDSP(0xD1); // Turn on DAC speaker
|
||||
|
||||
if(DSPV>=0x400)
|
||||
{
|
||||
WriteDSP(0x41); // Set sampling rate
|
||||
WriteDSP(Rate>>8); // High byte
|
||||
WriteDSP(Rate&0xFF); // Low byte
|
||||
if(!format)
|
||||
{
|
||||
WriteDSP(0xC6); // 8-bit output
|
||||
WriteDSP(0x00); // 8-bit mono unsigned PCM
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteDSP(0xB6); // 16-bit output
|
||||
WriteDSP(0x10); // 16-bit mono signed PCM
|
||||
}
|
||||
WriteDSP((fragsize-1)&0xFF);// Low byte of size
|
||||
WriteDSP((fragsize-1)>>8); // High byte of size
|
||||
}
|
||||
else
|
||||
{
|
||||
int tc,command;
|
||||
if(Rate>22050)
|
||||
{
|
||||
tc=(65536-(256000000/Rate))>>8;
|
||||
Rate=256000000/(65536-(tc<<8));
|
||||
command=0x90; // High-speed auto-initialize DMA mode transfer
|
||||
hsmode=1;
|
||||
}
|
||||
else
|
||||
{
|
||||
tc=256-(1000000/Rate);
|
||||
Rate=1000000/(256-tc);
|
||||
command=0x1c; // Auto-initialize DMA mode transfer
|
||||
}
|
||||
WriteDSP(0x40); // Set DSP time constant
|
||||
WriteDSP(tc); // time constant
|
||||
WriteDSP(0x48); // Set DSP block transfer size
|
||||
WriteDSP((fragsize-1)&0xFF);
|
||||
WriteDSP((fragsize-1)>>8);
|
||||
|
||||
WriteDSP(command);
|
||||
}
|
||||
|
||||
/* Enable DMA */
|
||||
if(format)
|
||||
outportb(0xd4,SBDMA16&3);
|
||||
else
|
||||
outportb(0xa,SBDMA);
|
||||
|
||||
printf(" %d hz, %d-bit\n",Rate,8<<format);
|
||||
return(Rate);
|
||||
}
|
||||
|
||||
extern volatile int soundjoyer;
|
||||
extern volatile int soundjoyeron;
|
||||
static int ssilence=0;
|
||||
|
||||
static void SBIRQHandler(_go32_dpmi_registers *r)
|
||||
{
|
||||
uint32 *src;
|
||||
uint32 dest;
|
||||
int32 x;
|
||||
|
||||
|
||||
if(format)
|
||||
{
|
||||
uint8 status;
|
||||
|
||||
outportb(SBPort+4,0x82);
|
||||
status=inportb(SBPort+5);
|
||||
if(status&2)
|
||||
inportb(SBPort+0x0F);
|
||||
}
|
||||
else
|
||||
inportb(SBPort+0x0E);
|
||||
|
||||
#ifdef OLD
|
||||
{
|
||||
uint8 status;
|
||||
|
||||
outportb(SBPort+4,0x82);
|
||||
status=inportb(SBPort+5);
|
||||
if(status&1)
|
||||
inportb(SBPort+0x0E);
|
||||
else if(status&2)
|
||||
inportb(SBPort+0x0F);
|
||||
else
|
||||
return; // Mysterious interrupt source! *eerie music*
|
||||
}
|
||||
#endif
|
||||
|
||||
if(hbusy)
|
||||
{
|
||||
outportb(0x20,0x20);
|
||||
if(SBIRQ>=8)
|
||||
outportb(0xA0,0x20);
|
||||
whichbuf^=1;
|
||||
return;
|
||||
}
|
||||
hbusy=1;
|
||||
|
||||
{
|
||||
/* This code seems to fail on many SB emulators. Bah.
|
||||
SCREW SB EMULATORS. ^_^ */
|
||||
uint32 count;
|
||||
uint32 block;
|
||||
uint32 port;
|
||||
|
||||
if(format)
|
||||
port=((SBDMA16&3)*4)+0xc2;
|
||||
else
|
||||
port=(SBDMA*2)+1;
|
||||
|
||||
count=inportb(port);
|
||||
count|=inportb(port)<<8;
|
||||
|
||||
if(count>=fragsize)
|
||||
block=1;
|
||||
else
|
||||
block=0;
|
||||
dest=LMBuffer+((block*fragsize)<<format);
|
||||
|
||||
#ifdef MOO
|
||||
dest=LMBuffer+((whichbuf*fragsize)<<format);
|
||||
whichbuf^=1;
|
||||
#endif
|
||||
}
|
||||
|
||||
_farsetsel(_dos_ds);
|
||||
|
||||
src=(uint32 *)(WaveBuffer+(ReadPtr<<format));
|
||||
|
||||
if(ssilence)
|
||||
{
|
||||
uint32 sby;
|
||||
if(format) sby=0; /* 16-bit silence. */
|
||||
else sby=0x80808080; /* 8-bit silence. */
|
||||
|
||||
for(x=(fragsize<<format)>>2;x;x--,dest+=4)
|
||||
{
|
||||
_farnspokel(dest,sby);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(x=(fragsize<<format)>>2;x;x--,dest+=4,src++)
|
||||
{
|
||||
_farnspokel(dest,*src);
|
||||
}
|
||||
ReadPtr=(ReadPtr+fragsize)&(fragtotal-1);
|
||||
}
|
||||
|
||||
if(soundjoyeron)
|
||||
{
|
||||
static int coot=0;
|
||||
if(!coot)
|
||||
{
|
||||
UpdateJoyData();
|
||||
soundjoyer=1;
|
||||
}
|
||||
coot=(coot+1)&3;
|
||||
}
|
||||
hbusy=0;
|
||||
outportb(0x20,0x20);
|
||||
if(SBIRQ>=8)
|
||||
outportb(0xA0,0x20);
|
||||
}
|
||||
|
||||
void SilenceSound(int s)
|
||||
{
|
||||
ssilence=s;
|
||||
}
|
||||
|
||||
void WriteSBSound(int32 *Buffer, int Count, int NoBlocking)
|
||||
{
|
||||
int x;
|
||||
|
||||
if(!format)
|
||||
{
|
||||
for(x=0;x<Count;x++)
|
||||
{
|
||||
while(WritePtr==ReadPtr)
|
||||
if(NoBlocking)
|
||||
return;
|
||||
WaveBuffer[WritePtr]=(uint8)((Buffer[x])>>8)^128;
|
||||
WritePtr=(WritePtr+1)&(fragtotal-1);
|
||||
}
|
||||
}
|
||||
else // 16 bit
|
||||
{
|
||||
for(x=0;x<Count;x++)
|
||||
{
|
||||
while(WritePtr==ReadPtr)
|
||||
if(NoBlocking)
|
||||
return;
|
||||
((int16 *)WaveBuffer)[WritePtr]=Buffer[x];
|
||||
WritePtr=(WritePtr+1)&(fragtotal-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void KillSB(void)
|
||||
{
|
||||
if(hsmode)
|
||||
ResetDSP(); /* High-speed mode requires a DSP reset. */
|
||||
else
|
||||
WriteDSP(format?0xD9:0xDA); /* Exit auto-init DMA transfer mode. */
|
||||
WriteDSP(0xD3); /* Turn speaker off. */
|
||||
|
||||
outportb((SBIRQ>7)?0xA1:0x21,PICMask|(1<<(SBIRQ&7)));
|
||||
ResetVectors();
|
||||
outportb((SBIRQ>7)?0xA1:0x21,PICMask);
|
||||
KillDMABuffer();
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
int InitSB(int Rate, int bittage);
|
||||
void KillSB(void);
|
||||
|
||||
void WriteSBSound(int32 *Buffer, int Count, int NoBlocking);
|
||||
void SilenceSound(int s);
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 1998 \Firebug\
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <dpmi.h>
|
||||
#include <sys/farptr.h>
|
||||
#include <go32.h>
|
||||
#include <pc.h>
|
||||
|
||||
#include "dos.h"
|
||||
#include "dos-video.h"
|
||||
|
||||
#define TEXT 3
|
||||
#define G320x200x256 0x13
|
||||
|
||||
static void vga_waitretrace(void)
|
||||
{
|
||||
while(inp(0x3da)&0x8);
|
||||
while(!(inp(0x3da)&0x8));
|
||||
}
|
||||
|
||||
static void vga_setmode(int mode)
|
||||
{
|
||||
__dpmi_regs regs;
|
||||
|
||||
memset(®s,0,sizeof(regs));
|
||||
regs.x.ax=mode;
|
||||
|
||||
__dpmi_int(0x10,®s);
|
||||
}
|
||||
|
||||
void vga_setpalette(int i, int r, int g, int b)
|
||||
{
|
||||
outp(0x3c8,i);
|
||||
outp(0x3c9,r);
|
||||
outp(0x3c9,g);
|
||||
outp(0x3c9,b);
|
||||
}
|
||||
|
||||
int FCEUDvmode=1;
|
||||
|
||||
static int vidready=0;
|
||||
|
||||
/* Part of the VGA low-level mass register setting code derived from
|
||||
code by \Firebug\.
|
||||
*/
|
||||
|
||||
#include "vgatweak.c"
|
||||
|
||||
void SetBorder(void)
|
||||
{
|
||||
inportb(0x3da);
|
||||
outportb(0x3c0,(0x11|0x20));
|
||||
outportb(0x3c0,0x80);
|
||||
}
|
||||
|
||||
void TweakVGA(int VGAMode)
|
||||
{
|
||||
int I;
|
||||
|
||||
vga_waitretrace();
|
||||
|
||||
outportb(0x3C8,0x00);
|
||||
for(I=0;I<768;I++) outportb(0x3C9,0x00);
|
||||
|
||||
outportb(0x3D4,0x11);
|
||||
I=inportb(0x3D5)&0x7F;
|
||||
outportb(0x3D4,0x11);
|
||||
outportb(0x3D5,I);
|
||||
|
||||
switch(VGAMode)
|
||||
{
|
||||
case 1: for(I=0;I<25;I++) VGAPortSet(v256x240[I]);break;
|
||||
case 2: for(I=0;I<25;I++) VGAPortSet(v256x256[I]);break;
|
||||
case 3: for(I=0;I<25;I++) VGAPortSet(v256x256S[I]);break;
|
||||
case 6: for(I=0;I<25;I++) VGAPortSet(v256x224S[I]);break;
|
||||
case 8: for(I=0;I<25;I++) VGAPortSet(v256x224_103[I]);break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
outportb(0x3da,0);
|
||||
}
|
||||
|
||||
|
||||
static uint8 palettedbr[256],palettedbg[256],palettedbb[256];
|
||||
|
||||
static void FlushPalette(void)
|
||||
{
|
||||
int x;
|
||||
for(x=0;x<256;x++)
|
||||
{
|
||||
int z=x;
|
||||
vga_setpalette(z,palettedbr[x]>>2,palettedbg[x]>>2,palettedbb[x]>>2);
|
||||
}
|
||||
}
|
||||
|
||||
void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b)
|
||||
{
|
||||
palettedbr[index]=r;
|
||||
palettedbg[index]=g;
|
||||
palettedbb[index]=b;
|
||||
if(vidready)
|
||||
{
|
||||
vga_setpalette(index,r>>2,g>>2,b>>2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void FCEUD_GetPalette(uint8 i, uint8 *r, uint8 *g, uint8 *b)
|
||||
{
|
||||
*r=palettedbr[i];
|
||||
*g=palettedbg[i];
|
||||
*b=palettedbb[i];
|
||||
}
|
||||
|
||||
static uint32 ScreenLoc;
|
||||
|
||||
int InitVideo(void)
|
||||
{
|
||||
vidready=0;
|
||||
switch(FCEUDvmode)
|
||||
{
|
||||
default:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 6:
|
||||
case 8:
|
||||
vga_setmode(G320x200x256);
|
||||
vidready|=1;
|
||||
ScreenLoc=0xa0000;
|
||||
TweakVGA(FCEUDvmode);
|
||||
SetBorder();
|
||||
DOSMemSet(ScreenLoc, 128, 256*256);
|
||||
break;
|
||||
}
|
||||
vidready|=2;
|
||||
FlushPalette();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void KillVideo(void)
|
||||
{
|
||||
if(vidready)
|
||||
{
|
||||
vga_setmode(TEXT);
|
||||
vidready=0;
|
||||
}
|
||||
}
|
||||
void LockConsole(void){}
|
||||
void UnlockConsole(void){}
|
||||
void BlitScreen(uint8 *XBuf)
|
||||
{
|
||||
uint32 dest;
|
||||
int tlines;
|
||||
|
||||
if(eoptions&4 && !NoWaiting)
|
||||
vga_waitretrace();
|
||||
|
||||
tlines=erendline-srendline+1;
|
||||
|
||||
dest=ScreenLoc;
|
||||
|
||||
switch(FCEUDvmode)
|
||||
{
|
||||
case 1:dest+=(((240-tlines)>>1)<<8);break;
|
||||
case 2:
|
||||
case 3:dest+=(((256-tlines)>>1)<<8);break;
|
||||
case 4:
|
||||
case 5:dest+=(((240-tlines)>>1)*640+((640-512)>>1));break;
|
||||
case 8:
|
||||
case 6:if(tlines>224) tlines=224;dest+=(((224-tlines)>>1)<<8);break;
|
||||
}
|
||||
|
||||
XBuf+=(srendline<<8)+(srendline<<4);
|
||||
|
||||
_farsetsel(_dos_ds);
|
||||
if(eoptions&DO_CLIPSIDES)
|
||||
{
|
||||
asm volatile(
|
||||
"agoop1:\n\t"
|
||||
"movl $30,%%eax\n\t"
|
||||
"agoop2:\n\t"
|
||||
"movl (%%esi),%%edx\n\t"
|
||||
"movl 4(%%esi),%%ecx\n\t"
|
||||
".byte 0x64 \n\t"
|
||||
"movl %%edx,(%%edi)\n\t"
|
||||
".byte 0x64 \n\t"
|
||||
"movl %%ecx,4(%%edi)\n\t"
|
||||
"addl $8,%%esi\n\t"
|
||||
"addl $8,%%edi\n\t"
|
||||
"decl %%eax\n\t"
|
||||
"jne agoop2\n\t"
|
||||
"addl $32,%%esi\n\t"
|
||||
"addl $16,%%edi\n\t"
|
||||
"decb %%bl\n\t"
|
||||
"jne agoop1\n\t"
|
||||
:
|
||||
: "S" (XBuf+8), "D" (dest+8), "b" (tlines)
|
||||
: "%eax","%cc","%edx","%ecx" );
|
||||
}
|
||||
else
|
||||
{
|
||||
asm volatile(
|
||||
"goop1:\n\t"
|
||||
"movl $32,%%eax\n\t"
|
||||
"goop2:\n\t"
|
||||
"movl (%%esi),%%edx\n\t"
|
||||
"movl 4(%%esi),%%ecx\n\t"
|
||||
".byte 0x64 \n\t"
|
||||
"movl %%edx,(%%edi)\n\t"
|
||||
".byte 0x64 \n\t"
|
||||
"movl %%ecx,4(%%edi)\n\t"
|
||||
"addl $8,%%esi\n\t"
|
||||
"addl $8,%%edi\n\t"
|
||||
"decl %%eax\n\t"
|
||||
"jne goop2\n\t"
|
||||
"addl $16,%%esi\n\t"
|
||||
"decb %%bl\n\t"
|
||||
"jne goop1\n\t"
|
||||
:
|
||||
: "S" (XBuf), "D" (dest), "b" (tlines)
|
||||
: "%eax","%cc","%edx","%ecx" );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
extern int FCEUDvmode;
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <crt0.h>
|
||||
#include <sys/farptr.h>
|
||||
#include <go32.h>
|
||||
|
||||
#include "dos.h"
|
||||
#include "dos-joystick.h"
|
||||
#include "dos-video.h"
|
||||
#include "dos-sound.h"
|
||||
#include "../common/args.h"
|
||||
#include "../common/config.h"
|
||||
|
||||
/* _CRT0_FLAG_LOCK_MEMORY might not always result in all memory being locked.
|
||||
Bummer. I'll add code to explicitly lock the data touched by the sound
|
||||
interrupt handler(and the handler itself), if necessary(though that might
|
||||
be tricky...). I'll also to cover the data the keyboard
|
||||
interrupt handler touches.
|
||||
*/
|
||||
|
||||
int _crt0_startup_flags = _CRT0_FLAG_FILL_SBRK_MEMORY | _CRT0_FLAG_LOCK_MEMORY | _CRT0_FLAG_USE_DOS_SLASHES;
|
||||
|
||||
static int f8bit=0;
|
||||
int soundo=44100;
|
||||
int doptions=0;
|
||||
|
||||
|
||||
CFGSTRUCT DriverConfig[]={
|
||||
NAC("sound",soundo),
|
||||
AC(doptions),
|
||||
AC(f8bit),
|
||||
AC(FCEUDvmode),
|
||||
NACA("joybmap",joyBMap),
|
||||
AC(joy),
|
||||
ENDCFGSTRUCT
|
||||
};
|
||||
|
||||
char *DriverUsage=
|
||||
"-vmode x Select video mode(all are 8 bpp).\n\
|
||||
1 = 256x240 6 = 256x224(with scanlines)\n\
|
||||
2 = 256x256 8 = 256x224\n\
|
||||
3 = 256x256(with scanlines)\n\
|
||||
-vsync x Wait for the screen's vertical retrace before updating the\n\
|
||||
screen. Refer to the documentation for caveats.\n\
|
||||
0 = Disabled.\n\
|
||||
1 = Enabled.\n\
|
||||
-sound x Sound.\n\
|
||||
0 = Disabled.\n\
|
||||
Otherwise, x = playback rate.\n\
|
||||
-f8bit x Force 8-bit sound.\n\
|
||||
0 = Disabled.\n\
|
||||
1 = Enabled.";
|
||||
|
||||
ARGPSTRUCT DriverArgs[]={
|
||||
{"-vmode",0,&FCEUDvmode,0},
|
||||
{"-sound",0,&soundo,0},
|
||||
{"-f8bit",0,&f8bit,0},
|
||||
{"-vsync",0,&doptions,DO_VSYNC},
|
||||
{0,0,0,0}
|
||||
};
|
||||
|
||||
void DoDriverArgs(void)
|
||||
{
|
||||
if(!joy) memset(joyBMap,0,sizeof(joyBMap));
|
||||
}
|
||||
|
||||
int InitSound(void)
|
||||
{
|
||||
if(soundo)
|
||||
{
|
||||
if(soundo==1)
|
||||
soundo=44100;
|
||||
soundo=InitSB(soundo,f8bit?0:1);
|
||||
FCEUI_Sound(soundo);
|
||||
}
|
||||
return(soundo);
|
||||
}
|
||||
|
||||
void WriteSound(int32 *Buffer, int Count, int NoWaiting)
|
||||
{
|
||||
WriteSBSound(Buffer,Count,NoWaiting);
|
||||
}
|
||||
|
||||
void KillSound(void)
|
||||
{
|
||||
if(soundo)
|
||||
KillSB();
|
||||
}
|
||||
|
||||
void DOSMemSet(uint32 A, uint8 V, uint32 count)
|
||||
{
|
||||
uint32 x;
|
||||
|
||||
_farsetsel(_dos_ds);
|
||||
for(x=0;x<count;x++)
|
||||
_farnspokeb(A+x,V);
|
||||
}
|
||||
|
||||
static char *arg0;
|
||||
uint8 *GetBaseDirectory(void)
|
||||
{
|
||||
int x=0;
|
||||
uint8 *ret = 0;
|
||||
|
||||
if(arg0)
|
||||
for(x=strlen(arg0);x>=0;x--)
|
||||
{
|
||||
if(arg0[x]=='/' || arg0[x]=='\\')
|
||||
{
|
||||
ret = malloc(x + 1);
|
||||
strncpy(ret,arg0,x);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!ret) { x=0; ret = malloc(1); }
|
||||
|
||||
BaseDirectory[x]=0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
puts("\nStarting FCE Ultra "VERSION_STRING"...\n");
|
||||
arg0=argv[0];
|
||||
return(CLImain(argc,argv));
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "main.h"
|
||||
#include "dface.h"
|
||||
#include "input.h"
|
||||
|
||||
void DOSMemSet(uint32 A, uint8 V, uint32 count);
|
||||
#define DO_VSYNC 1
|
||||
|
|
@ -0,0 +1,720 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "dface.h"
|
||||
#include "input.h"
|
||||
|
||||
#include "../common/cheat.h"
|
||||
|
||||
/* UsrInputType[] is user-specified. InputType[] is current
|
||||
(game loading can override user settings)
|
||||
*/
|
||||
int UsrInputType[3]={SI_GAMEPAD,SI_GAMEPAD,SIFC_NONE};
|
||||
int InputType[3]={0,0,0};
|
||||
static int cspec=0;
|
||||
|
||||
int gametype=0;
|
||||
|
||||
/* Necessary for proper GUI functioning(configuring when a game isn't loaded). */
|
||||
void InputUserActiveFix(void)
|
||||
{
|
||||
int x;
|
||||
for(x=0;x<3;x++) InputType[x]=UsrInputType[x];
|
||||
}
|
||||
|
||||
void ParseGIInput(FCEUGI *gi)
|
||||
{
|
||||
gametype=gi->type;
|
||||
|
||||
InputType[0]=UsrInputType[0];
|
||||
InputType[1]=UsrInputType[1];
|
||||
InputType[2]=UsrInputType[2];
|
||||
|
||||
if(gi->input[0]>=0)
|
||||
InputType[0]=gi->input[0];
|
||||
if(gi->input[1]>=0)
|
||||
InputType[1]=gi->input[1];
|
||||
if(gi->inputfc>=0)
|
||||
InputType[2]=gi->inputfc;
|
||||
cspec = gi->cspecial;
|
||||
|
||||
#ifdef EXTGUI
|
||||
Giggles(gi->cspecial);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static uint8 QuizKingData=0;
|
||||
static uint8 HyperShotData=0;
|
||||
static uint32 MahjongData=0;
|
||||
static uint32 FTrainerData=0;
|
||||
static uint8 TopRiderData=0;
|
||||
|
||||
static uint8 BWorldData[1+13+1];
|
||||
|
||||
static void UpdateFKB(void);
|
||||
static void UpdateGamepad(void);
|
||||
static void UpdateQuizKing(void);
|
||||
static void UpdateHyperShot(void);
|
||||
static void UpdateMahjong(void);
|
||||
static void UpdateFTrainer(void);
|
||||
static void UpdateTopRider(void);
|
||||
|
||||
static uint32 JSreturn=0;
|
||||
int NoWaiting=1;
|
||||
|
||||
#ifndef EXTGUI
|
||||
static void DoCheatSeq(void)
|
||||
{
|
||||
#if defined(DOS) || defined(SDL)
|
||||
SilenceSound(1);
|
||||
#endif
|
||||
KillKeyboard();
|
||||
KillVideo();
|
||||
|
||||
DoConsoleCheatConfig();
|
||||
InitVideo(CurGame);
|
||||
InitKeyboard();
|
||||
#if defined(DOS) || defined(SDL)
|
||||
SilenceSound(0);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "keyscan.h"
|
||||
static char *keys=0;
|
||||
static int DIPS=0;
|
||||
|
||||
static uint8 keyonce[MKK_COUNT];
|
||||
#define KEY(__a) keys[MKK(__a)]
|
||||
|
||||
static int _keyonly(int a)
|
||||
{
|
||||
if(keys[a])
|
||||
{
|
||||
if(!keyonce[a])
|
||||
{
|
||||
keyonce[a]=1;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
else
|
||||
keyonce[a]=0;
|
||||
return(0);
|
||||
}
|
||||
|
||||
#define keyonly(__a) _keyonly(MKK(__a))
|
||||
|
||||
static int cidisabled=0;
|
||||
|
||||
static void KeyboardCommands(void)
|
||||
{
|
||||
int is_shift, is_alt;
|
||||
|
||||
keys=GetKeyboard();
|
||||
|
||||
if(InputType[2]==SIFC_FKB)
|
||||
{
|
||||
if(keyonly(SCROLLLOCK))
|
||||
{
|
||||
cidisabled^=1;
|
||||
FCEUI_DispMessage("Family Keyboard %sabled.",cidisabled?"en":"dis");
|
||||
}
|
||||
#ifdef SDL
|
||||
SDL_WM_GrabInput(cidisabled?SDL_GRAB_ON:SDL_GRAB_OFF);
|
||||
#endif
|
||||
if(cidisabled) return;
|
||||
}
|
||||
|
||||
is_shift = KEY(LEFTSHIFT) | KEY(RIGHTSHIFT);
|
||||
is_alt = KEY(LEFTALT) | KEY(RIGHTALT);
|
||||
|
||||
if(keyonly(F4))
|
||||
{
|
||||
if(is_shift) FCEUI_SetRenderDisable(-1, 2);
|
||||
else FCEUI_SetRenderDisable(2, -1);
|
||||
}
|
||||
#ifdef SDL
|
||||
if(keyonly(ENTER) && is_alt) ToggleFS();
|
||||
#endif
|
||||
|
||||
NoWaiting&=~1;
|
||||
if(KEY(GRAVE))
|
||||
NoWaiting|=1;
|
||||
|
||||
if(gametype==GIT_FDS)
|
||||
{
|
||||
if(keyonly(F6)) FCEUI_FDSSelect();
|
||||
if(keyonly(F8)) FCEUI_FDSInsert();
|
||||
}
|
||||
|
||||
if(keyonly(F9)) FCEUI_SaveSnapshot();
|
||||
if(gametype!=GIT_NSF)
|
||||
{
|
||||
#ifndef EXTGUI
|
||||
if(keyonly(F2)) DoCheatSeq();
|
||||
#endif
|
||||
if(keyonly(F5))
|
||||
{
|
||||
if(is_shift)
|
||||
FCEUI_SaveMovie(NULL,0,NULL);
|
||||
else
|
||||
FCEUI_SaveState(NULL);
|
||||
}
|
||||
if(keyonly(F7))
|
||||
{
|
||||
if(is_shift)
|
||||
FCEUI_LoadMovie(NULL,0);
|
||||
else
|
||||
FCEUI_LoadState(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if(keyonly(F1)) FCEUI_ToggleTileView();
|
||||
|
||||
if(keyonly(MINUS)) DecreaseEmulationSpeed();
|
||||
if(keyonly(EQUAL)) IncreaseEmulationSpeed();
|
||||
if(keyonly(BACKSPACE)) FCEUI_MovieToggleFrameDisplay();
|
||||
if(keyonly(BACKSLASH)) FCEUI_ToggleEmulationPause();
|
||||
if(keyonly(RIGHTCONTROL)) FCEUI_FrameAdvance();
|
||||
|
||||
if(keyonly(F10)) FCEUI_ResetNES();
|
||||
if(keyonly(F11)) FCEUI_PowerNES();
|
||||
|
||||
#ifdef EXTGUI
|
||||
if(keyonly(F3)) GUI_Hide(-1);
|
||||
if(KEY(F12)) GUI_RequestExit();
|
||||
if(KEY(ESCAPE)) CloseGame();
|
||||
#else
|
||||
if(KEY(F12) || KEY(ESCAPE)) CloseGame();
|
||||
#endif
|
||||
|
||||
if(gametype==GIT_VSUNI)
|
||||
{
|
||||
if(keyonly(F8)) FCEUI_VSUniCoin();
|
||||
if(keyonly(F6))
|
||||
{
|
||||
DIPS^=1;
|
||||
FCEUI_VSUniToggleDIPView();
|
||||
}
|
||||
if(!(DIPS&1)) goto DIPSless;
|
||||
if(keyonly(1)) FCEUI_VSUniToggleDIP(0);
|
||||
if(keyonly(2)) FCEUI_VSUniToggleDIP(1);
|
||||
if(keyonly(3)) FCEUI_VSUniToggleDIP(2);
|
||||
if(keyonly(4)) FCEUI_VSUniToggleDIP(3);
|
||||
if(keyonly(5)) FCEUI_VSUniToggleDIP(4);
|
||||
if(keyonly(6)) FCEUI_VSUniToggleDIP(5);
|
||||
if(keyonly(7)) FCEUI_VSUniToggleDIP(6);
|
||||
if(keyonly(8)) FCEUI_VSUniToggleDIP(7);
|
||||
}
|
||||
else
|
||||
{
|
||||
static uint8 bbuf[32];
|
||||
static int bbuft;
|
||||
static int barcoder = 0;
|
||||
|
||||
if(keyonly(H)) FCEUI_NTSCSELHUE();
|
||||
if(keyonly(T)) FCEUI_NTSCSELTINT();
|
||||
if(KEY(KP_MINUS) || KEY(MINUS)) FCEUI_NTSCDEC();
|
||||
if(KEY(KP_PLUS) || KEY(EQUAL)) FCEUI_NTSCINC();
|
||||
|
||||
if((InputType[2] == SIFC_BWORLD) || (cspec == SIS_DATACH))
|
||||
{
|
||||
if(keyonly(F8))
|
||||
{
|
||||
barcoder ^= 1;
|
||||
if(!barcoder)
|
||||
{
|
||||
if(InputType[2] == SIFC_BWORLD)
|
||||
{
|
||||
strcpy(&BWorldData[1],bbuf);
|
||||
BWorldData[0]=1;
|
||||
}
|
||||
else
|
||||
FCEUI_DatachSet(bbuf);
|
||||
FCEUI_DispMessage("Barcode Entered");
|
||||
}
|
||||
else { bbuft = 0; FCEUI_DispMessage("Enter Barcode");}
|
||||
}
|
||||
} else barcoder = 0;
|
||||
|
||||
#define SSM(x) \
|
||||
{ if(barcoder) { if(bbuft < 13) {bbuf[bbuft++] = '0' + x; bbuf[bbuft] = 0;} FCEUI_DispMessage("Barcode: %s",bbuf);} \
|
||||
else { \
|
||||
if(is_shift) FCEUI_SelectMovie(x,1); \
|
||||
else FCEUI_SelectState(x,1); \
|
||||
} }
|
||||
|
||||
DIPSless:
|
||||
if(keyonly(0)) SSM(0);
|
||||
if(keyonly(1)) SSM(1);
|
||||
if(keyonly(2)) SSM(2);
|
||||
if(keyonly(3)) SSM(3);
|
||||
if(keyonly(4)) SSM(4);
|
||||
if(keyonly(5)) SSM(5);
|
||||
if(keyonly(6)) SSM(6);
|
||||
if(keyonly(7)) SSM(7);
|
||||
if(keyonly(8)) SSM(8);
|
||||
if(keyonly(9)) SSM(9);
|
||||
#undef SSM
|
||||
}
|
||||
}
|
||||
|
||||
#define MK(x) {{BUTTC_KEYBOARD},{0},{MKK(x)},1}
|
||||
#define MK2(x1,x2) {{BUTTC_KEYBOARD},{0},{MKK(x1),MKK(x2)},2}
|
||||
|
||||
#define MKZ() {{0},{0},{0},0}
|
||||
|
||||
#define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()}
|
||||
|
||||
ButtConfig GamePadConfig[4][10]={
|
||||
/* Gamepad 1 */
|
||||
{
|
||||
MK(KP3), MK(KP2), MK(TAB), MK(ENTER), MK(W),MK(Z),
|
||||
MK(A), MK(S), MKZ(), MKZ()
|
||||
},
|
||||
|
||||
/* Gamepad 2 */
|
||||
GPZ(),
|
||||
|
||||
/* Gamepad 3 */
|
||||
GPZ(),
|
||||
|
||||
/* Gamepad 4 */
|
||||
GPZ()
|
||||
};
|
||||
|
||||
|
||||
static void UpdateGamepad(void)
|
||||
{
|
||||
if(FCEUI_IsMovieActive()<0)
|
||||
return;
|
||||
|
||||
static int rapid=0;
|
||||
uint32 JS=0;
|
||||
int x;
|
||||
int wg;
|
||||
|
||||
rapid^=1;
|
||||
|
||||
for(wg=0;wg<4;wg++)
|
||||
{
|
||||
for(x=0;x<8;x++)
|
||||
if(DTestButton(&GamePadConfig[wg][x]))
|
||||
JS|=(1<<x)<<(wg<<3);
|
||||
|
||||
if(rapid)
|
||||
for(x=0;x<2;x++)
|
||||
if(DTestButton(&GamePadConfig[wg][8+x]))
|
||||
JS|=(1<<x)<<(wg<<3);
|
||||
}
|
||||
|
||||
// for(x=0;x<32;x+=8) /* Now, test to see if anything weird(up+down at same time)
|
||||
// is happening, and correct */
|
||||
// {
|
||||
// if((JS & (0xC0<<x) ) == (0xC0<<x) ) JS&=~(0xC0<<x);
|
||||
// if((JS & (0x30<<x) ) == (0x30<<x) ) JS&=~(0x30<<x);
|
||||
// }
|
||||
|
||||
JSreturn=JS;
|
||||
}
|
||||
|
||||
ButtConfig powerpadsc[2][12]={
|
||||
{
|
||||
MK(O),MK(P),MK(BRACKET_LEFT),
|
||||
MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
|
||||
MK(APOSTROPHE),
|
||||
MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
|
||||
},
|
||||
{
|
||||
MK(O),MK(P),MK(BRACKET_LEFT),
|
||||
MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
|
||||
MK(APOSTROPHE),
|
||||
MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
|
||||
}
|
||||
};
|
||||
|
||||
static uint32 powerpadbuf[2]={0,0};
|
||||
|
||||
static uint32 UpdatePPadData(int w)
|
||||
{
|
||||
if(FCEUI_IsMovieActive()<0)
|
||||
return;
|
||||
|
||||
uint32 r=0;
|
||||
ButtConfig *ppadtsc=powerpadsc[w];
|
||||
int x;
|
||||
|
||||
for(x=0;x<12;x++)
|
||||
if(DTestButton(&ppadtsc[x])) r|=1<<x;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static uint32 MouseData[3]={0,0,0};
|
||||
static uint8 fkbkeys[0x48];
|
||||
|
||||
void FCEUD_UpdateInput(void)
|
||||
{
|
||||
int x;
|
||||
int t=0;
|
||||
|
||||
UpdatePhysicalInput();
|
||||
KeyboardCommands();
|
||||
|
||||
for(x=0;x<2;x++)
|
||||
switch(InputType[x])
|
||||
{
|
||||
case SI_GAMEPAD:t|=1;break;
|
||||
case SI_ARKANOID:t|=2;break;
|
||||
case SI_ZAPPER:t|=2;break;
|
||||
case SI_POWERPADA:
|
||||
case SI_POWERPADB:powerpadbuf[x]=UpdatePPadData(x);break;
|
||||
}
|
||||
|
||||
switch(InputType[2])
|
||||
{
|
||||
case SIFC_ARKANOID:t|=2;break;
|
||||
case SIFC_SHADOW:t|=2;break;
|
||||
case SIFC_FKB:if(cidisabled) UpdateFKB();break;
|
||||
case SIFC_HYPERSHOT: UpdateHyperShot();break;
|
||||
case SIFC_MAHJONG: UpdateMahjong();break;
|
||||
case SIFC_QUIZKING: UpdateQuizKing();break;
|
||||
case SIFC_FTRAINERB:
|
||||
case SIFC_FTRAINERA: UpdateFTrainer();break;
|
||||
case SIFC_TOPRIDER: UpdateTopRider();break;
|
||||
case SIFC_OEKAKIDS:t|=2;break;
|
||||
|
||||
}
|
||||
|
||||
if(t&1)
|
||||
UpdateGamepad();
|
||||
|
||||
if(t&2)
|
||||
GetMouseData(MouseData);
|
||||
}
|
||||
|
||||
void InitOtherInput(void)
|
||||
{
|
||||
void *InputDPtr;
|
||||
|
||||
int t;
|
||||
int x;
|
||||
int attrib;
|
||||
|
||||
for(t=0,x=0;x<2;x++)
|
||||
{
|
||||
attrib=0;
|
||||
InputDPtr=0;
|
||||
switch(InputType[x])
|
||||
{
|
||||
case SI_POWERPADA:
|
||||
case SI_POWERPADB:InputDPtr=&powerpadbuf[x];break;
|
||||
case SI_GAMEPAD:InputDPtr=&JSreturn;break;
|
||||
case SI_ARKANOID:InputDPtr=MouseData;t|=1;break;
|
||||
case SI_ZAPPER:InputDPtr=MouseData;
|
||||
t|=1;
|
||||
attrib=1;
|
||||
break;
|
||||
}
|
||||
FCEUI_SetInput(x,InputType[x],InputDPtr,attrib);
|
||||
}
|
||||
|
||||
attrib=0;
|
||||
InputDPtr=0;
|
||||
switch(InputType[2])
|
||||
{
|
||||
case SIFC_SHADOW:InputDPtr=MouseData;t|=1;attrib=1;break;
|
||||
case SIFC_OEKAKIDS:InputDPtr=MouseData;t|=1;attrib=1;break;
|
||||
case SIFC_ARKANOID:InputDPtr=MouseData;t|=1;break;
|
||||
case SIFC_FKB:InputDPtr=fkbkeys;break;
|
||||
case SIFC_HYPERSHOT:InputDPtr=&HyperShotData;break;
|
||||
case SIFC_MAHJONG:InputDPtr=&MahjongData;break;
|
||||
case SIFC_QUIZKING:InputDPtr=&QuizKingData;break;
|
||||
case SIFC_TOPRIDER:InputDPtr=&TopRiderData;break;
|
||||
case SIFC_BWORLD:InputDPtr=BWorldData;break;
|
||||
case SIFC_FTRAINERA:
|
||||
case SIFC_FTRAINERB:InputDPtr=&FTrainerData;break;
|
||||
}
|
||||
|
||||
FCEUI_SetInputFC(InputType[2],InputDPtr,attrib);
|
||||
FCEUI_DisableFourScore(eoptions&EO_NOFOURSCORE);
|
||||
|
||||
if(t)
|
||||
InitMouse();
|
||||
}
|
||||
|
||||
|
||||
ButtConfig fkbmap[0x48]=
|
||||
{
|
||||
MK(F1),MK(F2),MK(F3),MK(F4),MK(F5),MK(F6),MK(F7),MK(F8),
|
||||
MK(1),MK(2),MK(3),MK(4),MK(5),MK(6),MK(7),MK(8),MK(9),MK(0),
|
||||
MK(MINUS),MK(EQUAL),MK(BACKSLASH),MK(BACKSPACE),
|
||||
MK(ESCAPE),MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y),MK(U),MK(I),MK(O),
|
||||
MK(P),MK(GRAVE),MK(BRACKET_LEFT),MK(ENTER),
|
||||
MK(LEFTCONTROL),MK(A),MK(S),MK(D),MK(F),MK(G),MK(H),MK(J),MK(K),
|
||||
MK(L),MK(SEMICOLON),MK(APOSTROPHE),MK(BRACKET_RIGHT),MK(INSERT),
|
||||
MK(LEFTSHIFT),MK(Z),MK(X),MK(C),MK(V),MK(B),MK(N),MK(M),MK(COMMA),
|
||||
MK(PERIOD),MK(SLASH),MK(RIGHTALT),MK(RIGHTSHIFT),MK(LEFTALT),MK(SPACE),
|
||||
MK(DELETE),MK(END),MK(PAGEDOWN),
|
||||
MK(CURSORUP),MK(CURSORLEFT),MK(CURSORRIGHT),MK(CURSORDOWN)
|
||||
};
|
||||
|
||||
static void UpdateFKB(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=0;x<0x48;x++)
|
||||
{
|
||||
fkbkeys[x]=0;
|
||||
|
||||
if(DTestButton(&fkbmap[x]))
|
||||
fkbkeys[x]=1;
|
||||
}
|
||||
}
|
||||
|
||||
static ButtConfig HyperShotButtons[4]=
|
||||
{
|
||||
MK(Q),MK(W),MK(E),MK(R)
|
||||
};
|
||||
|
||||
static void UpdateHyperShot(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
HyperShotData=0;
|
||||
for(x=0;x<0x4;x++)
|
||||
{
|
||||
if(DTestButton(&HyperShotButtons[x]))
|
||||
HyperShotData|=1<<x;
|
||||
}
|
||||
}
|
||||
|
||||
static ButtConfig MahjongButtons[21]=
|
||||
{
|
||||
MK(Q),MK(W),MK(E),MK(R),MK(T),
|
||||
MK(A),MK(S),MK(D),MK(F),MK(G),MK(H),MK(J),MK(K),MK(L),
|
||||
MK(Z),MK(X),MK(C),MK(V),MK(B),MK(N),MK(M)
|
||||
};
|
||||
|
||||
static void UpdateMahjong(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
MahjongData=0;
|
||||
for(x=0;x<21;x++)
|
||||
{
|
||||
if(DTestButton(&MahjongButtons[x]))
|
||||
MahjongData|=1<<x;
|
||||
}
|
||||
}
|
||||
|
||||
ButtConfig QuizKingButtons[6]=
|
||||
{
|
||||
MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y)
|
||||
};
|
||||
|
||||
static void UpdateQuizKing(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
QuizKingData=0;
|
||||
|
||||
for(x=0;x<6;x++)
|
||||
{
|
||||
if(DTestButton(&QuizKingButtons[x]))
|
||||
QuizKingData|=1<<x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ButtConfig TopRiderButtons[8]=
|
||||
{
|
||||
MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y),MK(U),MK(I)
|
||||
};
|
||||
|
||||
static void UpdateTopRider(void)
|
||||
{
|
||||
int x;
|
||||
TopRiderData=0;
|
||||
for(x=0;x<8;x++)
|
||||
if(DTestButton(&TopRiderButtons[x]))
|
||||
TopRiderData|=1<<x;
|
||||
}
|
||||
|
||||
ButtConfig FTrainerButtons[12]=
|
||||
{
|
||||
MK(O),MK(P),MK(BRACKET_LEFT),
|
||||
MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
|
||||
MK(APOSTROPHE),
|
||||
MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
|
||||
};
|
||||
|
||||
static void UpdateFTrainer(void)
|
||||
{
|
||||
int x;
|
||||
|
||||
FTrainerData=0;
|
||||
|
||||
for(x=0;x<12;x++)
|
||||
{
|
||||
if(DTestButton(&FTrainerButtons[x]))
|
||||
FTrainerData|=1<<x;
|
||||
}
|
||||
}
|
||||
|
||||
static void subcon(char *text, ButtConfig *bc)
|
||||
{
|
||||
uint8 buf[256];
|
||||
int wc;
|
||||
|
||||
for(wc=0;wc<MAXBUTTCONFIG;wc++)
|
||||
{
|
||||
sprintf(buf,"%s (%d)",text,wc+1);
|
||||
DWaitButton(buf,bc,wc);
|
||||
|
||||
if(wc && bc->ButtType[wc]==bc->ButtType[wc-1] && bc->DeviceNum[wc]==bc->DeviceNum[wc-1] &&
|
||||
bc->ButtonNum[wc]==bc->ButtonNum[wc-1])
|
||||
break;
|
||||
}
|
||||
bc->NumC=wc;
|
||||
}
|
||||
|
||||
void ConfigDevice(int which, int arg)
|
||||
{
|
||||
uint8 buf[256];
|
||||
int x;
|
||||
|
||||
ButtonConfigBegin();
|
||||
switch(which)
|
||||
{
|
||||
case FCFGD_QUIZKING:
|
||||
for(x=0;x<6;x++)
|
||||
{
|
||||
sprintf(buf,"Quiz King Buzzer #%d", x+1);
|
||||
subcon(buf,&QuizKingButtons[x]);
|
||||
}
|
||||
break;
|
||||
case FCFGD_HYPERSHOT:
|
||||
for(x=0;x<4;x++)
|
||||
{
|
||||
sprintf(buf,"Hyper Shot %d: %s",((x&2)>>1)+1,(x&1)?"JUMP":"RUN");
|
||||
subcon(buf,&HyperShotButtons[x]);
|
||||
}
|
||||
break;
|
||||
case FCFGD_POWERPAD:
|
||||
for(x=0;x<12;x++)
|
||||
{
|
||||
sprintf(buf,"PowerPad %d: %d", (arg&1)+1,x+11);
|
||||
subcon(buf,&powerpadsc[arg&1][x]);
|
||||
}
|
||||
break;
|
||||
|
||||
case FCFGD_GAMEPAD:
|
||||
{
|
||||
char *str[10]={"A","B","SELECT","START","UP","DOWN","LEFT","RIGHT","Rapid A","Rapid B"};
|
||||
for(x=0;x<10;x++)
|
||||
{
|
||||
sprintf(buf,"GamePad #%d: %s",arg+1,str[x]);
|
||||
subcon(buf,&GamePadConfig[arg][x]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ButtonConfigEnd();
|
||||
}
|
||||
|
||||
|
||||
CFGSTRUCT InputConfig[]={
|
||||
ACA(UsrInputType),
|
||||
AC(powerpadsc),
|
||||
AC(QuizKingButtons),
|
||||
AC(FTrainerButtons),
|
||||
AC(HyperShotButtons),
|
||||
AC(MahjongButtons),
|
||||
AC(GamePadConfig),
|
||||
AC(fkbmap),
|
||||
ENDCFGSTRUCT
|
||||
};
|
||||
|
||||
|
||||
static void InputCfg(char *text)
|
||||
{
|
||||
if(!strncasecmp(text,"gamepad",strlen("gamepad")))
|
||||
{
|
||||
ConfigDevice(FCFGD_GAMEPAD,(text[strlen("gamepad")]-'1')&3);
|
||||
}
|
||||
else if(!strncasecmp(text,"powerpad",strlen("powerpad")))
|
||||
{
|
||||
ConfigDevice(FCFGD_POWERPAD,(text[strlen("powerpad")]-'1')&1);
|
||||
}
|
||||
else if(!strcasecmp(text,"hypershot"))
|
||||
ConfigDevice(FCFGD_HYPERSHOT,0);
|
||||
else if(!strcasecmp(text,"quizking"))
|
||||
ConfigDevice(FCFGD_QUIZKING,0);
|
||||
}
|
||||
|
||||
static void FCExp(char *text)
|
||||
{
|
||||
static char *fccortab[11]={"none","arkanoid","shadow","4player","fkb","hypershot",
|
||||
"mahjong","quizking","ftrainera","ftrainerb","oekakids"};
|
||||
|
||||
static int fccortabi[11]={SIFC_NONE,SIFC_ARKANOID,SIFC_SHADOW,
|
||||
SIFC_4PLAYER,SIFC_FKB,SIFC_HYPERSHOT,SIFC_MAHJONG,SIFC_QUIZKING,
|
||||
SIFC_FTRAINERA,SIFC_FTRAINERB,SIFC_OEKAKIDS};
|
||||
int y;
|
||||
for(y=0;y<11;y++)
|
||||
if(!strcmp(fccortab[y],text))
|
||||
UsrInputType[2]=fccortabi[y];
|
||||
}
|
||||
|
||||
static char *cortab[6]={"none","gamepad","zapper","powerpada","powerpadb","arkanoid"};
|
||||
static int cortabi[6]={SI_NONE,SI_GAMEPAD,
|
||||
SI_ZAPPER,SI_POWERPADA,SI_POWERPADB,SI_ARKANOID};
|
||||
|
||||
static void Input1(char *text)
|
||||
{
|
||||
int y;
|
||||
|
||||
for(y=0;y<6;y++)
|
||||
if(!strcmp(cortab[y],text))
|
||||
UsrInputType[0]=cortabi[y];
|
||||
}
|
||||
|
||||
static void Input2(char *text)
|
||||
{
|
||||
int y;
|
||||
|
||||
for(y=0;y<6;y++)
|
||||
if(!strcmp(cortab[y],text))
|
||||
UsrInputType[1]=cortabi[y];
|
||||
}
|
||||
|
||||
ARGPSTRUCT InputArgs[]={
|
||||
{"-inputcfg",0,(void *)InputCfg,0x2000},
|
||||
{"-fcexp",0,(void *)FCExp,0x2000},
|
||||
{"-input1",0,(void *)Input1,0x2000},
|
||||
{"-input2",0,(void *)Input2,0x2000},
|
||||
{0,0,0,0}
|
||||
};
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef _aosdfjk02fmasf
|
||||
#define _aosdfjk02fmasf
|
||||
#define MAXBUTTCONFIG 4
|
||||
typedef struct {
|
||||
uint8 ButtType[MAXBUTTCONFIG];
|
||||
uint8 DeviceNum[MAXBUTTCONFIG];
|
||||
uint16 ButtonNum[MAXBUTTCONFIG];
|
||||
uint32 NumC;
|
||||
//uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */
|
||||
} ButtConfig;
|
||||
|
||||
extern CFGSTRUCT InputConfig[];
|
||||
extern ARGPSTRUCT InputArgs[];
|
||||
void ParseGIInput(FCEUGI *GI);
|
||||
|
||||
#define BUTTC_KEYBOARD 0x00
|
||||
#define BUTTC_JOYSTICK 0x01
|
||||
#define BUTTC_MOUSE 0x02
|
||||
|
||||
#define FCFGD_GAMEPAD 1
|
||||
#define FCFGD_POWERPAD 2
|
||||
#define FCFGD_HYPERSHOT 3
|
||||
#define FCFGD_QUIZKING 4
|
||||
|
||||
void InitOtherInput(void);
|
||||
void InputUserActiveFix(void);
|
||||
#ifdef EXTGUI
|
||||
extern ButtConfig GamePadConfig[4][10];
|
||||
extern ButtConfig powerpadsc[2][12];
|
||||
extern ButtConfig QuizKingButtons[6];
|
||||
extern ButtConfig FTrainerButtons[12];
|
||||
#endif
|
||||
|
||||
void IncreaseEmulationSpeed(void);
|
||||
void DecreaseEmulationSpeed(void);
|
||||
|
||||
void FCEUD_UpdateInput(void);
|
||||
#endif
|
|
@ -0,0 +1,161 @@
|
|||
#ifdef SDL
|
||||
#include <SDL.h>
|
||||
#define SDLK_A SDLK_a
|
||||
#define SDLK_B SDLK_b
|
||||
#define SDLK_C SDLK_c
|
||||
#define SDLK_D SDLK_d
|
||||
#define SDLK_E SDLK_e
|
||||
#define SDLK_F SDLK_f
|
||||
#define SDLK_G SDLK_g
|
||||
#define SDLK_H SDLK_h
|
||||
#define SDLK_I SDLK_i
|
||||
#define SDLK_J SDLK_j
|
||||
#define SDLK_K SDLK_k
|
||||
#define SDLK_L SDLK_l
|
||||
#define SDLK_M SDLK_m
|
||||
#define SDLK_N SDLK_n
|
||||
#define SDLK_O SDLK_o
|
||||
#define SDLK_P SDLK_p
|
||||
#define SDLK_Q SDLK_q
|
||||
#define SDLK_R SDLK_r
|
||||
#define SDLK_S SDLK_s
|
||||
#define SDLK_T SDLK_t
|
||||
#define SDLK_U SDLK_u
|
||||
#define SDLK_V SDLK_v
|
||||
#define SDLK_W SDLK_w
|
||||
#define SDLK_X SDLK_x
|
||||
#define SDLK_Y SDLK_y
|
||||
#define SDLK_Z SDLK_z
|
||||
#define SDLK_LEFTCONTROL SDLK_LCTRL
|
||||
#define SDLK_RIGHTCONTROL SDLK_RCTRL
|
||||
#define SDLK_LEFTALT SDLK_LALT
|
||||
#define SDLK_RIGHTALT SDLK_RALT
|
||||
#define SDLK_LEFTSHIFT SDLK_LSHIFT
|
||||
#define SDLK_RIGHTSHIFT SDLK_RSHIFT
|
||||
#define SDLK_CURSORDOWN SDLK_DOWN
|
||||
#define SDLK_CURSORUP SDLK_UP
|
||||
#define SDLK_CURSORLEFT SDLK_LEFT
|
||||
#define SDLK_CURSORRIGHT SDLK_RIGHT
|
||||
#define SDLK_ENTER SDLK_RETURN
|
||||
#define SDLK_EQUAL SDLK_EQUALS
|
||||
#define SDLK_APOSTROPHE SDLK_QUOTE
|
||||
#define SDLK_BRACKET_LEFT SDLK_LEFTBRACKET
|
||||
#define SDLK_BRACKET_RIGHT SDLK_RIGHTBRACKET
|
||||
#define SDLK_SCROLLLOCK SDLK_SCROLLOCK /* I guess the SDL people don't like lots of Ls... */
|
||||
#define SDLK_GRAVE SDLK_BACKQUOTE
|
||||
#define MKK(k) SDLK_##k
|
||||
#define MKK_COUNT (SDLK_LAST+1)
|
||||
|
||||
#elif DOS
|
||||
|
||||
#define SCAN_GRAVE 0x29
|
||||
#define SCAN_1 0x02
|
||||
#define SCAN_2 0x03
|
||||
#define SCAN_3 0x04
|
||||
#define SCAN_4 0x05
|
||||
#define SCAN_5 0x06
|
||||
#define SCAN_6 0x07
|
||||
#define SCAN_7 0x08
|
||||
#define SCAN_8 0x09
|
||||
#define SCAN_9 0x0A
|
||||
#define SCAN_0 0x0B
|
||||
#define SCAN_MINUS 0x0C
|
||||
#define SCAN_EQUAL 0x0D
|
||||
#define SCAN_BACKSLASH 0x2B
|
||||
#define SCAN_BACKSPACE 0x0E
|
||||
#define SCAN_TAB 0x0F
|
||||
#define SCAN_Q 0x10
|
||||
#define SCAN_W 0x11
|
||||
#define SCAN_E 0x12
|
||||
#define SCAN_R 0x13
|
||||
#define SCAN_T 0x14
|
||||
#define SCAN_Y 0x15
|
||||
#define SCAN_U 0x16
|
||||
#define SCAN_I 0x17
|
||||
#define SCAN_O 0x18
|
||||
#define SCAN_P 0x19
|
||||
#define SCAN_BRACKET_LEFT 0x1A
|
||||
#define SCAN_BRACKET_RIGHT 0x1B
|
||||
#define SCAN_LOWBACKSLASH 0x2B
|
||||
#define SCAN_CAPSLOCK 0x3A
|
||||
#define SCAN_A 0x1E
|
||||
#define SCAN_S 0x1F
|
||||
#define SCAN_D 0x20
|
||||
#define SCAN_F 0x21
|
||||
#define SCAN_G 0x22
|
||||
#define SCAN_H 0x23
|
||||
#define SCAN_J 0x24
|
||||
#define SCAN_K 0x25
|
||||
#define SCAN_L 0x26
|
||||
#define SCAN_SEMICOLON 0x27
|
||||
#define SCAN_APOSTROPHE 0x28
|
||||
#define SCAN_ENTER 0x1C
|
||||
#define SCAN_LEFTSHIFT 0x2A
|
||||
#define SCAN_Z 0x2C
|
||||
#define SCAN_X 0x2D
|
||||
#define SCAN_C 0x2E
|
||||
#define SCAN_V 0x2F
|
||||
#define SCAN_B 0x30
|
||||
#define SCAN_N 0x31
|
||||
#define SCAN_M 0x32
|
||||
#define SCAN_COMMA 0x33
|
||||
#define SCAN_PERIOD 0x34
|
||||
#define SCAN_SLASH 0x35
|
||||
#define SCAN_RIGHTSHIFT 0x36
|
||||
#define SCAN_LEFTCONTROL 0x1D
|
||||
#define SCAN_LEFTALT 0x38
|
||||
#define SCAN_SPACE 0x39
|
||||
|
||||
/* Extended keys. */
|
||||
#define SCAN_RIGHTALT (0x38|0x80)
|
||||
#define SCAN_RIGHTCONTROL (0x1D|0x80)
|
||||
#define SCAN_BL_INSERT (0x52|0x80)
|
||||
#define SCAN_BL_DELETE (0x53|0x80)
|
||||
#define SCAN_BL_CURSORLEFT (0x4B|0x80)
|
||||
#define SCAN_BL_HOME (0x47|0x80)
|
||||
#define SCAN_BL_END (0x4F|0x80)
|
||||
#define SCAN_BL_CURSORUP (0x48|0x80)
|
||||
#define SCAN_BL_CURSORDOWN (0x50|0x80)
|
||||
#define SCAN_BL_PAGEUP (0x49|0x80)
|
||||
#define SCAN_BL_PAGEDOWN (0x51|0x80)
|
||||
#define SCAN_BL_CURSORRIGHT (0x4D|0x80)
|
||||
|
||||
#define SCAN_SCROLLLOCK 0x46
|
||||
/* Keys often found in the key pad area. */
|
||||
#define SCAN_NUMLOCK 0x45
|
||||
#define SCAN_HOME 0x47
|
||||
#define SCAN_CURSORLEFT 0x4B
|
||||
#define SCAN_END 0x4F
|
||||
#define SCAN_SLASH 0x35
|
||||
#define SCAN_CURSORUP 0x48
|
||||
#define SCAN_CENTER 0x4C
|
||||
#define SCAN_CURSORDOWN 0x50
|
||||
#define SCAN_INSERT 0x52
|
||||
#define SCAN_PAUSE 0xC5
|
||||
#define SCAN_ASTERISK 0x37
|
||||
#define SCAN_PAGEUP 0x49
|
||||
#define SCAN_CURSORRIGHT 0x4D
|
||||
#define SCAN_PAGEDOWN 0x51
|
||||
#define SCAN_DELETE 0x53
|
||||
#define SCAN_KP_MINUS 0x4A
|
||||
#define SCAN_KP_PLUS 0x4E
|
||||
#define SCAN_KP_ENTER 0x1C
|
||||
|
||||
#define SCAN_ESCAPE 0x01
|
||||
#define SCAN_F1 0x3B
|
||||
#define SCAN_F2 0x3C
|
||||
#define SCAN_F3 0x3D
|
||||
#define SCAN_F4 0x3E
|
||||
#define SCAN_F5 0x3F
|
||||
#define SCAN_F6 0x40
|
||||
#define SCAN_F7 0x41
|
||||
#define SCAN_F8 0x42
|
||||
#define SCAN_F9 0x43
|
||||
#define SCAN_F10 0x44
|
||||
#define SCAN_F11 0x57
|
||||
#define SCAN_F12 0x58
|
||||
|
||||
#define MK_COUNT 256
|
||||
#define MK(k) SCAN_##k
|
||||
|
||||
#endif
|
|
@ -0,0 +1,553 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <signal.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "main.h"
|
||||
#include "throttle.h"
|
||||
|
||||
#include "../common/cheat.h"
|
||||
|
||||
#include "input.h"
|
||||
#include "dface.h"
|
||||
|
||||
extern int32 fps_scale;
|
||||
|
||||
int CloseGame(void);
|
||||
|
||||
static char *soundrecfn=0; /* File name of sound recording. */
|
||||
|
||||
static int ntsccol=0,ntschue=0,ntsctint=0;
|
||||
int soundvol=100;
|
||||
long soundq=0;
|
||||
int _sound=1;
|
||||
long soundrate=48000;
|
||||
#ifdef WIN32
|
||||
long soundbufsize=52;
|
||||
#else
|
||||
long soundbufsize=24;
|
||||
#endif
|
||||
|
||||
#ifdef FRAMESKIP
|
||||
static int frameskip=0;
|
||||
#endif
|
||||
static int inited=0;
|
||||
static int isloaded=0; // Is game loaded?
|
||||
|
||||
int srendlinev[2]={8,0};
|
||||
int erendlinev[2]={231,239};
|
||||
|
||||
|
||||
static uint8 *DrBaseDirectory;
|
||||
|
||||
int eoptions=0;
|
||||
|
||||
static void DriverKill(void);
|
||||
static int DriverInitialize(FCEUGI *gi);
|
||||
int gametype;
|
||||
|
||||
FCEUGI *CurGame=NULL;
|
||||
|
||||
static void ParseGI(FCEUGI *gi)
|
||||
{
|
||||
ParseGIInput(gi);
|
||||
gametype=gi->type;
|
||||
}
|
||||
|
||||
#ifndef EXTGUI
|
||||
void FCEUD_PrintError(char *s)
|
||||
{
|
||||
puts(s);
|
||||
}
|
||||
|
||||
void FCEUD_Message(char *s)
|
||||
{
|
||||
fputs(s,stdout);
|
||||
}
|
||||
#endif
|
||||
|
||||
static char *cpalette=0;
|
||||
static void LoadCPalette(void)
|
||||
{
|
||||
uint8 tmpp[192];
|
||||
FILE *fp;
|
||||
|
||||
if(!(fp=FCEUD_UTF8fopen(cpalette,"rb")))
|
||||
{
|
||||
printf(" Error loading custom palette from file: %s\n",cpalette);
|
||||
return;
|
||||
}
|
||||
fread(tmpp,1,192,fp);
|
||||
FCEUI_SetPaletteArray(tmpp);
|
||||
fclose(fp);
|
||||
}
|
||||
#ifdef EXTGUI
|
||||
extern CFGSTRUCT GUIConfig;
|
||||
#endif
|
||||
static CFGSTRUCT fceuconfig[]={
|
||||
AC(soundrate),
|
||||
AC(soundq),
|
||||
AC(_sound),
|
||||
AC(soundvol),
|
||||
AC(soundbufsize),
|
||||
ACS(cpalette),
|
||||
AC(ntsctint),
|
||||
AC(ntschue),
|
||||
AC(ntsccol),
|
||||
AC(eoptions),
|
||||
ACA(srendlinev),
|
||||
ACA(erendlinev),
|
||||
ADDCFGSTRUCT(InputConfig),
|
||||
ADDCFGSTRUCT(DriverConfig),
|
||||
#ifdef EXTGUI
|
||||
ADDCFGSTRUCT(GUIConfig),
|
||||
#endif
|
||||
ENDCFGSTRUCT
|
||||
};
|
||||
|
||||
static void SaveConfig(void)
|
||||
{
|
||||
char tdir[2048];
|
||||
sprintf(tdir,"%s"PSS"fceu98.cfg",DrBaseDirectory);
|
||||
FCEUI_GetNTSCTH(&ntsctint, &ntschue);
|
||||
SaveFCEUConfig(tdir,fceuconfig);
|
||||
}
|
||||
|
||||
static void LoadConfig(void)
|
||||
{
|
||||
char tdir[2048];
|
||||
sprintf(tdir,"%s"PSS"fceu98.cfg",DrBaseDirectory);
|
||||
FCEUI_GetNTSCTH(&ntsctint, &ntschue); /* Get default settings for if
|
||||
no config file exists. */
|
||||
LoadFCEUConfig(tdir,fceuconfig);
|
||||
InputUserActiveFix();
|
||||
}
|
||||
|
||||
static void CreateDirs(void)
|
||||
{
|
||||
char *subs[7]={"fcs","fcm","snaps","gameinfo","sav","cheats","movie"};
|
||||
char tdir[2048];
|
||||
int x;
|
||||
|
||||
#ifdef WIN32
|
||||
mkdir(DrBaseDirectory);
|
||||
for(x=0;x<6;x++)
|
||||
{
|
||||
sprintf(tdir,"%s"PSS"%s",DrBaseDirectory,subs[x]);
|
||||
mkdir(tdir);
|
||||
}
|
||||
#else
|
||||
mkdir(DrBaseDirectory,S_IRWXU);
|
||||
for(x=0;x<6;x++)
|
||||
{
|
||||
sprintf(tdir,"%s"PSS"%s",DrBaseDirectory,subs[x]);
|
||||
mkdir(tdir,S_IRWXU);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
static void SetSignals(void (*t)(int))
|
||||
{
|
||||
int sigs[11]={SIGINT,SIGTERM,SIGHUP,SIGPIPE,SIGSEGV,SIGFPE,SIGKILL,SIGALRM,SIGABRT,SIGUSR1,SIGUSR2};
|
||||
int x;
|
||||
for(x=0;x<11;x++)
|
||||
signal(sigs[x],t);
|
||||
}
|
||||
|
||||
static void CloseStuff(int signum)
|
||||
{
|
||||
DriverKill();
|
||||
printf("\nSignal %d has been caught and dealt with...\n",signum);
|
||||
switch(signum)
|
||||
{
|
||||
case SIGINT:printf("How DARE you interrupt me!\n");break;
|
||||
case SIGTERM:printf("MUST TERMINATE ALL HUMANS\n");break;
|
||||
case SIGHUP:printf("Reach out and hang-up on someone.\n");break;
|
||||
case SIGPIPE:printf("The pipe has broken! Better watch out for floods...\n");break;
|
||||
case SIGSEGV:printf("Iyeeeeeeeee!!! A segmentation fault has occurred. Have a fluffy day.\n");break;
|
||||
/* So much SIGBUS evil. */
|
||||
#ifdef SIGBUS
|
||||
#if(SIGBUS!=SIGSEGV)
|
||||
case SIGBUS:printf("I told you to be nice to the driver.\n");break;
|
||||
#endif
|
||||
#endif
|
||||
case SIGFPE:printf("Those darn floating points. Ne'er know when they'll bite!\n");break;
|
||||
case SIGALRM:printf("Don't throw your clock at the meowing cats!\n");break;
|
||||
case SIGABRT:printf("Abort, Retry, Ignore, Fail?\n");break;
|
||||
case SIGUSR1:
|
||||
case SIGUSR2:printf("Killing your processes is not nice.\n");break;
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void DoArgs(int argc, char *argv[])
|
||||
{
|
||||
int x;
|
||||
|
||||
static ARGPSTRUCT FCEUArgs[]={
|
||||
{"-soundbufsize",0,&soundbufsize,0},
|
||||
{"-soundrate",0,&soundrate,0},
|
||||
{"-soundq",0,&soundq,0},
|
||||
#ifdef FRAMESKIP
|
||||
{"-frameskip",0,&frameskip,0},
|
||||
#endif
|
||||
{"-sound",0,&_sound,0},
|
||||
{"-soundvol",0,&soundvol,0},
|
||||
{"-cpalette",0,&cpalette,0x4001},
|
||||
{"-soundrecord",0,&soundrecfn,0x4001},
|
||||
|
||||
{"-ntsccol",0,&ntsccol,0},
|
||||
{"-pal",0,&eoptions,0x8000|EO_PAL},
|
||||
|
||||
{"-lowpass",0,&eoptions,0x8000|EO_LOWPASS},
|
||||
{"-gg",0,&eoptions,0x8000|EO_GAMEGENIE},
|
||||
{"-no8lim",0,&eoptions,0x8001},
|
||||
{"-snapname",0,&eoptions,0x8000|EO_SNAPNAME},
|
||||
{"-nofs",0,&eoptions,0x8000|EO_NOFOURSCORE},
|
||||
{"-clipsides",0,&eoptions,0x8000|EO_CLIPSIDES},
|
||||
{"-nothrottle",0,&eoptions,0x8000|EO_NOTHROTTLE},
|
||||
{"-slstart",0,&srendlinev[0],0},{"-slend",0,&erendlinev[0],0},
|
||||
{"-slstartp",0,&srendlinev[1],0},{"-slendp",0,&erendlinev[1],0},
|
||||
{0,(int *)InputArgs,0,0},
|
||||
{0,(int *)DriverArgs,0,0},
|
||||
{0,0,0,0}
|
||||
};
|
||||
|
||||
ParseArguments(argc, argv, FCEUArgs);
|
||||
if(cpalette)
|
||||
{
|
||||
if(cpalette[0]=='0')
|
||||
if(cpalette[1]==0)
|
||||
{
|
||||
free(cpalette);
|
||||
cpalette=0;
|
||||
}
|
||||
}
|
||||
FCEUI_SetVidSystem((eoptions&EO_PAL)?1:0);
|
||||
FCEUI_SetGameGenie((eoptions&EO_GAMEGENIE)?1:0);
|
||||
FCEUI_SetLowPass((eoptions&EO_LOWPASS)?1:0);
|
||||
|
||||
FCEUI_DisableSpriteLimitation(eoptions&1);
|
||||
FCEUI_SetSnapName(eoptions&EO_SNAPNAME);
|
||||
|
||||
for(x=0;x<2;x++)
|
||||
{
|
||||
if(srendlinev[x]<0 || srendlinev[x]>239) srendlinev[x]=0;
|
||||
if(erendlinev[x]<srendlinev[x] || erendlinev[x]>239) erendlinev[x]=239;
|
||||
}
|
||||
|
||||
FCEUI_SetRenderedLines(srendlinev[0],erendlinev[0],srendlinev[1],erendlinev[1]);
|
||||
DoDriverArgs();
|
||||
}
|
||||
|
||||
#include "usage.h"
|
||||
|
||||
/* Loads a game, given a full path/filename. The driver code must be
|
||||
initialized after the game is loaded, because the emulator code
|
||||
provides data necessary for the driver code(number of scanlines to
|
||||
render, what virtual input devices to use, etc.).
|
||||
*/
|
||||
int LoadGame(const char *path)
|
||||
{
|
||||
FCEUGI *tmp;
|
||||
|
||||
CloseGame();
|
||||
if(!(tmp=FCEUI_LoadGame(path,1)))
|
||||
return 0;
|
||||
CurGame=tmp;
|
||||
ParseGI(tmp);
|
||||
RefreshThrottleFPS();
|
||||
|
||||
if(!DriverInitialize(tmp))
|
||||
return(0);
|
||||
if(soundrecfn)
|
||||
{
|
||||
if(!FCEUI_BeginWaveRecord(soundrecfn))
|
||||
{
|
||||
free(soundrecfn);
|
||||
soundrecfn=0;
|
||||
}
|
||||
}
|
||||
isloaded=1;
|
||||
#ifdef EXTGUI
|
||||
if(eoptions&EO_AUTOHIDE) GUI_Hide(1);
|
||||
#endif
|
||||
|
||||
FCEUD_NetworkConnect();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Closes a game. Frees memory, and deinitializes the drivers. */
|
||||
int CloseGame(void)
|
||||
{
|
||||
if(!isloaded) return(0);
|
||||
FCEUI_CloseGame();
|
||||
DriverKill();
|
||||
isloaded=0;
|
||||
CurGame=0;
|
||||
|
||||
if(soundrecfn)
|
||||
FCEUI_EndWaveRecord();
|
||||
|
||||
#ifdef EXTGUI
|
||||
GUI_Hide(0);
|
||||
#endif
|
||||
InputUserActiveFix();
|
||||
return(1);
|
||||
}
|
||||
|
||||
void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count);
|
||||
|
||||
void DoFun(void)
|
||||
{
|
||||
uint8 *gfx;
|
||||
int32 *sound;
|
||||
int32 ssize;
|
||||
static int fskipc=0;
|
||||
static int opause=0;
|
||||
|
||||
#ifdef FRAMESKIP
|
||||
fskipc=(fskipc+1)%(frameskip+1);
|
||||
#endif
|
||||
|
||||
if(NoWaiting) {gfx=0;}
|
||||
FCEUI_Emulate(&gfx, &sound, &ssize, fskipc);
|
||||
FCEUD_Update(gfx, sound, ssize);
|
||||
|
||||
if(opause!=FCEUI_EmulationPaused())
|
||||
{
|
||||
opause=FCEUI_EmulationPaused();
|
||||
SilenceSound(opause);
|
||||
}
|
||||
}
|
||||
|
||||
int CLImain(int argc, char *argv[])
|
||||
{
|
||||
int ret;
|
||||
|
||||
if(!(ret=FCEUI_Initialize()))
|
||||
return(0);
|
||||
|
||||
DrBaseDirectory=GetBaseDirectory();
|
||||
FCEUI_SetBaseDirectory(DrBaseDirectory);
|
||||
|
||||
CreateDirs();
|
||||
|
||||
#ifdef EXTGUI
|
||||
if(argc==2 && !strcmp(argv[1],"-help")) // I hope no one has a game named "-help" :b
|
||||
#else
|
||||
if(argc<=1)
|
||||
#endif
|
||||
{
|
||||
ShowUsage(argv[0]);
|
||||
return(0);
|
||||
}
|
||||
|
||||
LoadConfig();
|
||||
DoArgs(argc-2,&argv[1]);
|
||||
FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
|
||||
if(cpalette)
|
||||
LoadCPalette();
|
||||
|
||||
/* All the config files and arguments are parsed now. */
|
||||
#ifdef EXTGUI
|
||||
return(1);
|
||||
|
||||
#else
|
||||
if(!LoadGame(argv[argc-1]))
|
||||
{
|
||||
DriverKill();
|
||||
return(0);
|
||||
}
|
||||
|
||||
while(CurGame)
|
||||
DoFun();
|
||||
|
||||
#if(0)
|
||||
{
|
||||
int x;
|
||||
for(x=1;x<argc;x++)
|
||||
{ LoadGame(argv[x]); while(CurGame) DoFun(); }
|
||||
}
|
||||
#endif
|
||||
|
||||
CloseGame();
|
||||
|
||||
SaveConfig();
|
||||
|
||||
FCEUI_Kill();
|
||||
|
||||
#endif
|
||||
return(1);
|
||||
}
|
||||
|
||||
static int DriverInitialize(FCEUGI *gi)
|
||||
{
|
||||
#ifndef WIN32
|
||||
SetSignals(CloseStuff);
|
||||
#endif
|
||||
|
||||
/* Initialize video before all else, due to some wacko dependencies
|
||||
in the SexyAL code(DirectSound) that need to be fixed.
|
||||
*/
|
||||
|
||||
if(!InitVideo(gi)) return 0;
|
||||
inited|=4;
|
||||
|
||||
if(InitSound(gi))
|
||||
inited|=1;
|
||||
|
||||
if(InitJoysticks())
|
||||
inited|=2;
|
||||
|
||||
if(!InitKeyboard()) return 0;
|
||||
inited|=8;
|
||||
|
||||
InitOtherInput();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void DriverKill(void)
|
||||
{
|
||||
SaveConfig();
|
||||
|
||||
#ifndef WIN32
|
||||
SetSignals(SIG_IGN);
|
||||
#endif
|
||||
|
||||
if(inited&2)
|
||||
KillJoysticks();
|
||||
if(inited&8)
|
||||
KillKeyboard();
|
||||
if(inited&4)
|
||||
KillVideo();
|
||||
if(inited&1)
|
||||
KillSound();
|
||||
if(inited&16)
|
||||
KillMouse();
|
||||
inited=0;
|
||||
}
|
||||
|
||||
void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count)
|
||||
{
|
||||
#ifdef NETWORK
|
||||
extern int FCEUDnetplay;
|
||||
#endif
|
||||
|
||||
int ocount = Count;
|
||||
// apply frame scaling to Count
|
||||
Count = (Count<<8)/fps_scale;
|
||||
if(Count)
|
||||
{
|
||||
int32 can=GetWriteSound();
|
||||
static int uflow=0;
|
||||
int32 tmpcan;
|
||||
|
||||
// don't underflow when scaling fps
|
||||
if(can >= GetMaxSound() && fps_scale<=256) uflow=1; /* Go into massive underflow mode. */
|
||||
|
||||
if(can > Count) can=Count;
|
||||
else uflow=0;
|
||||
|
||||
WriteSound(Buffer,can);
|
||||
|
||||
//if(uflow) puts("Underflow");
|
||||
tmpcan = GetWriteSound();
|
||||
// don't underflow when scaling fps
|
||||
if(fps_scale>256 || ((tmpcan < Count*0.90) && !uflow))
|
||||
{
|
||||
if(XBuf && (inited&4) && !(NoWaiting & 2))
|
||||
BlitScreen(XBuf);
|
||||
Buffer+=can;
|
||||
Count-=can;
|
||||
if(Count)
|
||||
{
|
||||
if(NoWaiting)
|
||||
{
|
||||
can=GetWriteSound();
|
||||
if(Count>can) Count=can;
|
||||
WriteSound(Buffer,Count);
|
||||
}
|
||||
else
|
||||
{
|
||||
while(Count>0)
|
||||
{
|
||||
WriteSound(Buffer,(Count<ocount) ? Count : ocount);
|
||||
Count -= ocount;
|
||||
}
|
||||
}
|
||||
}
|
||||
} //else puts("Skipped");
|
||||
#ifdef NETWORK
|
||||
else if(!NoWaiting && FCEUDnetplay && (uflow || tmpcan >= (Count * 1.8)))
|
||||
{
|
||||
if(Count > tmpcan) Count=tmpcan;
|
||||
while(tmpcan > 0)
|
||||
{
|
||||
// printf("Overwrite: %d\n", (Count <= tmpcan)?Count : tmpcan);
|
||||
WriteSound(Buffer, (Count <= tmpcan)?Count : tmpcan);
|
||||
tmpcan -= Count;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!NoWaiting && (!(eoptions&EO_NOTHROTTLE) || FCEUI_EmulationPaused()))
|
||||
SpeedThrottle();
|
||||
if(XBuf && (inited&4))
|
||||
{
|
||||
BlitScreen(XBuf);
|
||||
}
|
||||
}
|
||||
FCEUD_UpdateInput();
|
||||
//if(!Count && !NoWaiting && !(eoptions&EO_NOTHROTTLE))
|
||||
// SpeedThrottle();
|
||||
//if(XBuf && (inited&4))
|
||||
//{
|
||||
// BlitScreen(XBuf);
|
||||
//}
|
||||
//if(Count)
|
||||
// WriteSound(Buffer,Count,NoWaiting);
|
||||
//FCEUD_UpdateInput();
|
||||
}
|
||||
|
||||
|
||||
/* Maybe ifndef WXWINDOWS would be better? ^_^ */
|
||||
#ifndef EXTGUI
|
||||
FILE *FCEUD_UTF8fopen(const char *fn, const char *mode)
|
||||
{
|
||||
return(fopen(fn,mode));
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,55 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "../../driver.h"
|
||||
#include "../common/config.h"
|
||||
#include "../common/args.h"
|
||||
|
||||
extern int eoptions;
|
||||
#define EO_NO8LIM 1
|
||||
#define EO_SUBASE 2
|
||||
#define EO_CLIPSIDES 8
|
||||
#define EO_SNAPNAME 16
|
||||
#define EO_NOFOURSCORE 32
|
||||
#define EO_NOTHROTTLE 64
|
||||
#define EO_GAMEGENIE 128
|
||||
#define EO_PAL 256
|
||||
#define EO_LOWPASS 512
|
||||
#define EO_AUTOHIDE 1024
|
||||
|
||||
extern int srendlinev[2],erendlinev[2];
|
||||
extern int NoWaiting;
|
||||
|
||||
extern int soundvol;
|
||||
extern long soundq;
|
||||
extern int _sound;
|
||||
extern long soundrate;
|
||||
extern long soundbufsize;
|
||||
|
||||
int CLImain(int argc, char *argv[]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
static const struct {
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */
|
||||
uint8 pixel_data[32 * 32 * 3 + 1];
|
||||
} fceu_playicon = {
|
||||
32, 32, 3,
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\0\0\0\0\0\0\0\0\0\\\223\373\\\223\373\267\317\373"
|
||||
"\246\304\373\260\312\373\222\267\373\246\304\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\267\317\373\246\304\373\260\312\373\210\261\373\246\304\373\\\223\373\\"
|
||||
"\223\373\210\261\373\222\267\373\267\317\373\241\301\373\\\223\373\\\223"
|
||||
"\373\0\0\0\0\0\0\\\223\373\\\223\373\227\272\373\227\272\373\227\272\373"
|
||||
"\227\272\373\227\272\373\227\272\373\\\223\373\\\223\373z`sr\242\373\227"
|
||||
"\272\373\227\272\373\\\223\373\\\223\373\\\223\373\\\223\373\213\261\373"
|
||||
"z\247\373\213\261\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\313i=\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40"
|
||||
"\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40"
|
||||
"\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\257T*\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40"
|
||||
"\355\235\203\355\235\203\341\232\205\341\232\205\365\255\233\355\235\203"
|
||||
"\355\235\203\350\250\232\365\255\233\355\235\203\307L\14\307L\14\307L\14"
|
||||
"\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256B\12\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\315Z\40\273zc\233l_\325\225\205\325\225\205\325\225\205\273\212"
|
||||
"\201\325\225\205\237qd\325\225\205\317\231\216\307L\14\307L\14\307L\14\307"
|
||||
"L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256B\12\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\315Z\40\344\232\203\301\215\201\344\232\203\273\212\201\325\225"
|
||||
"\205\2114\10\344\232\203\350\250\232\325\225\205\333\230\205\307L\14\307"
|
||||
"L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256"
|
||||
"B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\315Z\40\2259\11}0\10\2259\11}0\10}0\10\307L\14\225"
|
||||
"9\11d&\6}0\10}0\10\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14"
|
||||
"\307L\14\307L\14\307L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40\355\235\203"
|
||||
"\355\233\201\355\235\203\355\235\203\355\235\203\365\255\233\355\235\203"
|
||||
"\341\232\205\355\235\203\355\235\203\307L\14\365\255\233\355\235\203\365"
|
||||
"\255\233\355\235\203\355\235\203\355\235\203\355\235\203\355\235\203\307"
|
||||
"L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\315Z\40\325\225\205\311\221\204\311\221\204"
|
||||
"\325\225\205\311\221\204\325\225\205\311\221\204\325\225\205\325\225\205"
|
||||
"\311\221\204\307L\14\325\225\205\311\221\204\325\225\205\311\221\204\325"
|
||||
"\225\205\311\221\204\325\225\205\311\221\204\307L\14\256B\12\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\315Z\40\325\225\205\325\225\205\325\225\205\325\225\205\325\225"
|
||||
"\205\325\225\205\317\231\216\325\225\205\325\225\205\325\225\205\307L\14"
|
||||
"\325\225\205\317\231\216\325\225\205\317\231\216\325\225\205\325\225\205"
|
||||
"\273zc\241n_\307L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0"
|
||||
"\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40\325\225\205\325"
|
||||
"\225\205\325\225\205\365\255\233\333\243\231\325\225\205\333\230\205\325"
|
||||
"\225\205\325\225\205\325\225\205\307L\14\325\225\205\317\223\204\325\225"
|
||||
"\205\333\230\205\325\225\205\325\225\205\333\230\205\317\223\204\307L\14"
|
||||
"\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\315Z\40\325\225\205\325\225\205\325\225\205"
|
||||
"\325\225\205\311\221\204\325\225\205\325\225\205\325\225\205\344\232\203"
|
||||
"\273\212\201\307L\14\325\225\205\273\212\201\325\225\205\325\225\205\344"
|
||||
"\232\203\273\212\201\344\232\203\273\212\201\341\232\205\256B\12\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\257T*d&\6d&\6d&\6d&\6d&\6d&\6d&\6d&\6}0\10d&\6\256B\12d&\6p+\7"
|
||||
"d&\6d&\6}0\10d&\6}0\10d&\6d&\6\223@\26\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\234\243"
|
||||
"\335\213\237\344\237\244\333\251\247\326\237\244\333\\\223\373\267\252\317"
|
||||
"\222\241\341\267\252\317\210\237\346\241\245\332\267\252\317\246\246\327"
|
||||
"\246\246\327\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0"
|
||||
"\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\257hT\\\223\373\213\261\373\\\223"
|
||||
"\373\241\301\373\210\261\373\246\304\373\222\267\373\241\301\373\260\312"
|
||||
"\373\\\223\373\237\277\373\246\304\373\267\317\373\241\301\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\246\304\373\\\223\373\241"
|
||||
"\301\373\210\261\373\246\304\373\222\267\373\241\301\373\260\312\373\\\223"
|
||||
"\373\237\277\373\246\304\373\267\317\373\241\301\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373"
|
||||
"\\\223\373\\\223\373D\203\270D\203\270\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0"
|
||||
"\0\0\0\0\\\223\373\\\223\373(\211n\0\247\0\0n\0(\211n\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\0\0\0\0\0\0\\\223\373(\211n\0\247\0\0\247\0\0\247\0\0\247\0(\211n\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\210\261\373\246\304\373\241\301\373z\247"
|
||||
"\373\\\223\373\227\272\373\227\272\373\227\272\373\227\272\373\227\272\373"
|
||||
"\227\272\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\0\0\0\0\0\0(\211n\0\247\0\0n\0\0\247\0\\\215\12fs\16"
|
||||
"\0\247\0(\211n\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
|
||||
"\223\373\\\223\373Z\231Z[\230SZ\231Z[\230SZ\231Z[\230S\\\223\373\0\0\0\0"
|
||||
"\0\0\0\247\0\0\247\0\0\247\0\0\247\0vy\7p|\7\0\247\0\0\247\0(\211n\\\223"
|
||||
"\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
|
||||
"\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373b\237L\200\317\20\200\317"
|
||||
"\20\200\317\20\200\317\20\200\317\20\200\317\20[\223H\0\0\0\0\0\0\230P.\323"
|
||||
"d0\230P.\323d0\221M&\313`%\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323"
|
||||
"d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323"
|
||||
"d0\230P.\323d0\230P.\323d0\0\0\0\0\0\0\0\0\0\237N(\225E\35\237N(\225E\35"
|
||||
"\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237"
|
||||
"N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N("
|
||||
"\225E\35\237N(\225E\35\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
|
||||
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
|
||||
};
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/* FCE Ultra - NES/Famicom Emulator
|
||||
*
|
||||
* Copyright notice for this file:
|
||||
* Copyright (C) 2002 Xodnizel
|
||||
* Copyright (C) 2002 Paul Kuliniewicz
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
/* PK: SDL joystick input stuff */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "sdl.h"
|
||||
|
||||
#define MAX_JOYSTICKS 32
|
||||
static SDL_Joystick *Joysticks[MAX_JOYSTICKS] = {NULL};
|
||||
|
||||
int DTestButtonJoy(ButtConfig *bc)
|
||||
{
|
||||
int x;
|
||||
|
||||
for(x=0;x<bc->NumC;x++)
|
||||
{
|
||||
if(bc->ButtonNum[x]&0x8000) /* Axis "button" */
|
||||
{
|
||||
int pos;
|
||||
pos = SDL_JoystickGetAxis(Joysticks[bc->DeviceNum[x]], bc->ButtonNum[x]&16383);
|
||||
if ((bc->ButtonNum[x]&0x4000) && pos <= -16383)
|
||||
return(1);
|
||||
else if (!(bc->ButtonNum[x]&0x4000) && pos >= 16363)
|
||||
return(1);
|
||||
}
|
||||
else if(bc->ButtonNum[x]&0x2000) /* Hat "button" */
|
||||
{
|
||||
if( SDL_JoystickGetHat(Joysticks[bc->DeviceNum[x]],(bc->ButtonNum[x]>>8)&0x1F) & (bc->ButtonNum[x]&0xFF))
|
||||
return(1);
|
||||
}
|
||||
else
|
||||
if(SDL_JoystickGetButton(Joysticks[bc->DeviceNum[x]], bc->ButtonNum[x] ))
|
||||
return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int jinited=0;
|
||||
|
||||
/* Cleanup opened joysticks. */
|
||||
int KillJoysticks (void)
|
||||
{
|
||||
int n; /* joystick index */
|
||||
|
||||
if(!jinited) return(0);
|
||||
for (n = 0; n < MAX_JOYSTICKS; n++)
|
||||
{
|
||||
if (Joysticks[n] != 0)
|
||||
SDL_JoystickClose(Joysticks[n]);
|
||||
Joysticks[n]=0;
|
||||
}
|
||||
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* Initialize joysticks. */
|
||||
int InitJoysticks (void)
|
||||
{
|
||||
int n; /* joystick index */
|
||||
int total;
|
||||
|
||||
SDL_InitSubSystem(SDL_INIT_JOYSTICK);
|
||||
total=SDL_NumJoysticks();
|
||||
if(total>MAX_JOYSTICKS) total=MAX_JOYSTICKS;
|
||||
|
||||
for (n = 0; n < total; n++)
|
||||
{
|
||||
/* Open the joystick under SDL. */
|
||||
Joysticks[n] = SDL_JoystickOpen(n);
|
||||
//printf("Could not open joystick %d: %s.\n",
|
||||
//joy[n] - 1, SDL_GetError());
|
||||
continue;
|
||||
}
|
||||
jinited=1;
|
||||
return(1);
|
||||
}
|
|
@ -0,0 +1,224 @@
|
|||
#include "sdl.h"
|
||||
#include <SDL/SDL_net.h>
|
||||
#include "sdl-netplay.h"
|
||||
|
||||
char *ServerHost;
|
||||
|
||||
static int LocalPortTCP=0xFCE;
|
||||
static int LocalPortUDP=0xFCE;
|
||||
static int RemotePortTCP=0xFCE;
|
||||
|
||||
static int RemotePortUDP; /* Not configurable, figured out during handshake. */
|
||||
|
||||
static TCPsocket Socket;
|
||||
static UDPsocket UDPSocket;
|
||||
static SDLNet_SocketSet set;
|
||||
|
||||
|
||||
static void en32(uint8 *buf, uint32 morp)
|
||||
{
|
||||
buf[0]=morp;
|
||||
buf[1]=morp>>8;
|
||||
buf[2]=morp>>16;
|
||||
buf[3]=morp>>24;
|
||||
}
|
||||
|
||||
static uint32 de32(uint8 *morp)
|
||||
{
|
||||
return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24));
|
||||
}
|
||||
|
||||
|
||||
|
||||
int FCEUD_NetworkConnect(void)
|
||||
{
|
||||
IPaddress rip;
|
||||
|
||||
SDLNet_Init();
|
||||
|
||||
if(netplay==1) /* Be a server. */
|
||||
{
|
||||
TCPsocket tmp;
|
||||
Uint16 p=LocalPortUDP;
|
||||
|
||||
SDLNet_ResolveHost(&rip,NULL,LocalPortTCP);
|
||||
|
||||
UDPSocket=SDLNet_UDP_Open(&p);
|
||||
|
||||
tmp=SDLNet_TCP_Open(&rip);
|
||||
Socket=SDLNet_TCP_Accept(&tmp);
|
||||
|
||||
memcpy(&rip,SDLNet_TCP_GetPeerAddress(Socket),sizeof(IPaddress));
|
||||
|
||||
{
|
||||
uint8 buf[12];
|
||||
uint32 player=1;
|
||||
|
||||
magic=SDL_GetTicks();
|
||||
|
||||
SDLNet_Write32(buf,uport);
|
||||
SDLNet_Write32(buf+4,1);
|
||||
SDLNet_Write32(buf+8,magic);
|
||||
|
||||
SDLNet_TCP_Send(Socket, buf, 12);
|
||||
|
||||
/* Get the UDP port the client is waiting for data on. */
|
||||
SDLNet_TCP_Recv(Socket, buf, 2);
|
||||
RemotePortUDP=de32(buf);
|
||||
}
|
||||
}
|
||||
else /* Be a client */
|
||||
{
|
||||
SDLNet_ResolveHost(&rip,ServerHost,RemotePortTCP);
|
||||
Socket=SDLNet_TCP_Open(&rip);
|
||||
|
||||
{
|
||||
Uint16 p=LocalPortUDP;
|
||||
uint8 buf[12];
|
||||
|
||||
UDPSocket=SDLNet_UDP_Open(&p);
|
||||
|
||||
/* Now, tell the server what local UDP port it should send to. */
|
||||
en32(buf,p);
|
||||
SDLNet_TCP_Send(Socket, buf, 4);
|
||||
|
||||
/* Get the UDP port from the server we should send data to. */
|
||||
SDLNet_TCP_Recv(Socket, buf, 12);
|
||||
RemotePortUDP=de32(buf);
|
||||
magic=de32(buf+8);
|
||||
}
|
||||
set=SDLNet_AllocSocketSet(1);
|
||||
SDLNet_TCP_AddSocket(set,TCPSocket);
|
||||
SDLNet_UDP_AddSocket(set,UDPSocket);
|
||||
} // End client connect code.
|
||||
|
||||
rip.port=RemotePortUDP;
|
||||
SDLNet_UDP_Bind(UDPSocket, 0, &rip);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static int CheckUDP(uint8 *packet, int32 len, int32 alt)
|
||||
{
|
||||
uint32 crc;
|
||||
uint32 repcrc;
|
||||
|
||||
crc=FCEUI_CRC32(0,packet+4,len+8);
|
||||
repcrc=de32(packet);
|
||||
|
||||
if(crc!=repcrc) return(0); /* CRC32 mismatch, bad packet. */
|
||||
packet+=4;
|
||||
|
||||
if(de32(packet)!=magic) /* Magic number mismatch, bad or spoofed packet. */
|
||||
return(0);
|
||||
|
||||
packet+=4;
|
||||
if(alt)
|
||||
{
|
||||
if(de32(packet)<incounter) /* Time warped packet. */
|
||||
return(0);
|
||||
}
|
||||
else
|
||||
if(de32(packet)!=incounter) /* Time warped packet. */
|
||||
return(0);
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* Be careful where these MakeXXX() functions are used. */
|
||||
static uint8 *MakeUDP(uint8 *data, int32 len)
|
||||
{
|
||||
/* UDP packet data header is 12 bytes in length. */
|
||||
static uint8 buf[12+32]; // arbitrary 32.
|
||||
|
||||
en32(buf+4,magic);
|
||||
en32(buf+8,outcounter);
|
||||
memcpy(buf+12,data,len);
|
||||
en32(buf,FCEUI_CRC32(0,buf+4,8+len));
|
||||
return(buf);
|
||||
}
|
||||
|
||||
static uint8 *MakeTCP(uint8 *data, int32 len)
|
||||
{
|
||||
/* TCP packet data header is 4 bytes in length. */
|
||||
static uint8 buf[4+32]; // arbitrary 32.
|
||||
|
||||
en32(buf,outcounter);
|
||||
memcpy(buf+4,data,len);
|
||||
return(buf);
|
||||
}
|
||||
|
||||
#define UDPHEADSIZE 12
|
||||
#define TCPHEADSIZE 4
|
||||
|
||||
void FCEUD_NetworkClose(void)
|
||||
{
|
||||
SDLNet_Quit();
|
||||
}
|
||||
|
||||
/* 1 byte to server */
|
||||
int FCEUD_SendDataToServer(uint8 v,uint8 cmd)
|
||||
{
|
||||
UDPpacket upack;
|
||||
|
||||
upack.channel=0;
|
||||
upack.data=MakeUDP(data,1);
|
||||
upack.len=upack.maxlen=UDPHEADSIZE+1;
|
||||
upack.status=0;
|
||||
|
||||
SDLNet_UDP_Send(UDPSocket,0,&upack);
|
||||
|
||||
outcounter++;
|
||||
return(1);
|
||||
}
|
||||
|
||||
void FCEUD_SendDataToClients(uint8 *data)
|
||||
{
|
||||
UDPpacket upack;
|
||||
|
||||
SDLNet_TCP_Send(Socket,MakeTCP(data,5),TCPHEADSIZE+5);
|
||||
|
||||
upack.channel=0;
|
||||
upack.data=MakeUDP(data,5);
|
||||
upack.len=upack.maxlen=UDPHEADSIZE+5;
|
||||
upack.status=0;
|
||||
|
||||
SDLNet_UDP_Send(UDPSocket,0,&upack);
|
||||
|
||||
outcounter++;
|
||||
return(1);
|
||||
}
|
||||
|
||||
int FCEUD_GetDataFromServer(uint8 *data)
|
||||
{
|
||||
uint8 buf[128];
|
||||
NoWaiting&=~2;
|
||||
|
||||
while(SDLNet_CheckSockets(set,1)==0)
|
||||
{
|
||||
// do something here.
|
||||
}
|
||||
if(SDLNet_SocketReady(Socket))
|
||||
{
|
||||
SDLNet_TCP_Recv
|
||||
if(de32(buf)==incounter) /* New packet, keep. */
|
||||
{
|
||||
unsigned long beefie;
|
||||
memcpy(data,buf+TCPHEADSIZE,5);
|
||||
incounter++;
|
||||
|
||||
if(!ioctl(Socket,FIONREAD,&beefie))
|
||||
if(beefie)
|
||||
NoWaiting|=2;
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
}
|
||||
if(SDLNet_SocketReady(UDPSocket)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue