From d97315ac0bca825d2d50a44453bc5652946e2c67 Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 30 Apr 2007 14:16:20 +0000 Subject: [PATCH] updated bords/mappers/stuff to 0.98.15, lots of them got broken, asmcore support code gone missing git-svn-id: file:///home/notaz/opt/svn/fceu@117 be3aeb3a-fb24-0410-a615-afba39da0efa --- Makefile.base | 4 +- boards/112.c | 89 ++ boards/164.c | 110 +++ boards/183.c | 117 +++ boards/186.c | 104 +++ boards/8157.c | 77 ++ boards/8237.c | 93 ++ boards/90.c | 408 +++++++++ boards/Makefile | 13 +- boards/addrlatch.c | 53 ++ boards/bonza.c | 139 +++ boards/datalatch.c | 207 +++++ boards/deirom.c | 82 ++ boards/dream.c | 56 ++ boards/h2288.c | 190 ++-- boards/karaoke.c | 78 ++ boards/konami-qtai.c | 128 +++ boards/malee.c | 16 +- boards/mapinc.h | 23 +- boards/mmc1.c | 426 +++++++++ boards/mmc3.c | 1408 ++++++++++++++++++++++++++++ boards/mmc3.h | 22 + boards/mmc5.c | 839 +++++++++++++++++ boards/n106.c | 472 ++++++++++ boards/novel.c | 23 +- boards/sachen.c | 422 +++++---- boards/simple.c | 164 ---- boards/subor.c | 79 ++ boards/super24.c | 380 +++----- boards/supervision.c | 37 +- boards/tengen.c | 198 ++++ cart.c | 202 ++-- cart.h | 37 +- driver.h | 38 +- drivers/gp2x/main.c | 2 +- fce.c | 14 +- fce.h | 7 +- fds.c | 1604 +++++++++++++++++--------------- fds.h | 13 +- file.h | 2 + general.c | 5 + general.h | 2 + git.h | 51 +- ines-bad.h | 38 + ines-correct.h | 194 ++++ ines.c | 1921 +++++++++++++++++++++------------------ ines.h | 740 +++++++-------- input.c | 79 +- input.h | 7 + mappers/105.c | 132 --- mappers/113.c | 25 +- mappers/117.c | 41 +- mappers/15.c | 102 +-- mappers/151.c | 11 +- mappers/16.c | 220 ++++- mappers/17.c | 23 +- mappers/18.c | 43 +- mappers/180.c | 3 +- mappers/182.c | 50 - mappers/183.c | 0 mappers/187.c | 170 ++++ mappers/189.c | 36 +- mappers/19.c | 289 ------ mappers/193.c | 20 + mappers/200.c | 36 + mappers/201.c | 44 + mappers/202.c | 39 + mappers/203.c | 36 + mappers/204.c | 38 + mappers/208.c | 139 +++ mappers/21.c | 89 +- mappers/211.c | 146 +++ mappers/212.c | 23 + mappers/213.c | 14 + mappers/214.c | 17 + mappers/215.c | 96 ++ mappers/217.c | 96 ++ mappers/22.c | 28 +- mappers/225.c | 3 +- mappers/226.c | 5 +- mappers/227.c | 9 +- mappers/228.c | 6 +- mappers/229.c | 3 +- mappers/23.c | 42 +- mappers/230.c | 62 ++ mappers/231.c | 41 + mappers/232.c | 13 +- mappers/234.c | 19 +- mappers/235.c | 54 ++ mappers/240.c | 3 +- mappers/241.c | 27 + mappers/242.c | 3 +- mappers/244.c | 38 + mappers/246.c | 14 +- mappers/248.c | 91 -- mappers/24and26.c | 432 ++++----- mappers/25.c | 92 +- mappers/255.c | 67 ++ mappers/27.c | 74 ++ mappers/32.c | 10 +- mappers/33.c | 57 +- mappers/40.c | 13 +- mappers/41.c | 27 +- mappers/42.c | 22 +- mappers/43.c | 70 +- mappers/46.c | 4 +- mappers/{112.c => 50.c} | 66 +- mappers/51.c | 5 +- mappers/{249.c => 57.c} | 37 +- mappers/58.c | 43 + mappers/59.c | 47 + mappers/6.c | 157 ++-- mappers/60.c | 41 + mappers/{245.c => 61.c} | 50 +- mappers/62.c | 41 + mappers/64.c | 151 --- mappers/65.c | 59 +- mappers/67.c | 26 +- mappers/68.c | 39 +- mappers/69.c | 233 +++-- mappers/71.c | 5 +- mappers/72.c | 5 +- mappers/73.c | 24 +- mappers/75.c | 11 +- mappers/76.c | 11 +- mappers/77.c | 8 +- mappers/79.c | 3 +- mappers/8.c | 11 +- mappers/80.c | 80 +- mappers/82.c | 19 +- mappers/83.c | 28 +- mappers/85.c | 152 +++- mappers/86.c | 17 +- mappers/88.c | 46 +- mappers/89.c | 3 +- mappers/90.c | 155 ---- mappers/91.c | 59 ++ mappers/92.c | 6 +- mappers/95.c | 116 ++- mappers/97.c | 3 +- mappers/99.c | 4 +- mappers/Makefile | 85 +- mappers/emu2413.c | 1300 ++++++++++++++++++++++++++ mappers/emu2413.h | 134 +++ mappers/emutypes.h | 44 + mappers/fmopl.c | 871 ------------------ mappers/fmopl.h | 149 --- mappers/mapinc.h | 23 +- mappers/mapshare.h | 5 - mappers/mmc2and4.c | 18 +- mappers/simple.c | 246 ++--- mappers/vrc7snd.c | 190 ---- mappers/vrc7tone.h | 17 + md5.c | 246 +++++ md5.h | 18 + memory.h | 6 +- nsf.c | 982 +++++++++++--------- nsf.h | 100 +- sound.c | 36 +- sound.h | 10 +- state.c | 47 +- state.h | 3 +- svga.c | 11 +- svga.h | 3 +- unif.c | 1033 +++++++++++---------- unif.h | 182 ++-- video.c | 2 - vsuni.c | 419 +++++++++ vsuni.h | 7 + x6502.h | 2 + 170 files changed, 15390 insertions(+), 7280 deletions(-) create mode 100644 boards/112.c create mode 100644 boards/164.c create mode 100644 boards/183.c create mode 100644 boards/186.c create mode 100644 boards/8157.c create mode 100644 boards/8237.c create mode 100644 boards/90.c create mode 100644 boards/addrlatch.c create mode 100644 boards/bonza.c create mode 100644 boards/datalatch.c create mode 100644 boards/deirom.c create mode 100644 boards/dream.c create mode 100644 boards/karaoke.c create mode 100644 boards/konami-qtai.c create mode 100644 boards/mmc1.c create mode 100644 boards/mmc3.c create mode 100644 boards/mmc3.h create mode 100644 boards/mmc5.c create mode 100644 boards/n106.c delete mode 100644 boards/simple.c create mode 100644 boards/subor.c create mode 100644 boards/tengen.c create mode 100644 ines-bad.h create mode 100644 ines-correct.h delete mode 100644 mappers/105.c delete mode 100644 mappers/182.c create mode 100644 mappers/183.c create mode 100644 mappers/187.c delete mode 100644 mappers/19.c create mode 100644 mappers/193.c create mode 100644 mappers/200.c create mode 100644 mappers/201.c create mode 100644 mappers/202.c create mode 100644 mappers/203.c create mode 100644 mappers/204.c create mode 100644 mappers/208.c create mode 100644 mappers/211.c create mode 100644 mappers/212.c create mode 100644 mappers/213.c create mode 100644 mappers/214.c create mode 100644 mappers/215.c create mode 100644 mappers/217.c create mode 100644 mappers/230.c create mode 100644 mappers/231.c create mode 100644 mappers/235.c create mode 100644 mappers/241.c create mode 100644 mappers/244.c delete mode 100644 mappers/248.c create mode 100644 mappers/255.c create mode 100644 mappers/27.c rename mappers/{112.c => 50.c} (50%) rename mappers/{249.c => 57.c} (64%) create mode 100644 mappers/58.c create mode 100644 mappers/59.c create mode 100644 mappers/60.c rename mappers/{245.c => 61.c} (58%) create mode 100644 mappers/62.c delete mode 100644 mappers/64.c delete mode 100644 mappers/90.c create mode 100644 mappers/91.c create mode 100644 mappers/emu2413.c create mode 100644 mappers/emu2413.h create mode 100644 mappers/emutypes.h delete mode 100644 mappers/fmopl.c delete mode 100644 mappers/fmopl.h delete mode 100644 mappers/mapshare.h delete mode 100644 mappers/vrc7snd.c create mode 100644 mappers/vrc7tone.h create mode 100644 md5.c create mode 100644 md5.h create mode 100644 vsuni.c create mode 100644 vsuni.h diff --git a/Makefile.base b/Makefile.base index 734b1b1..af0e348 100644 --- a/Makefile.base +++ b/Makefile.base @@ -1,11 +1,11 @@ CFLAGS = -Wall ${TFLAGS} -OBJECTS = fce.o video.o general.o endian.o svga.o sound.o nsf.o fds.o netplay.o ines.o state.o unif.o input.o file.o cart.o crc32.o memory.o cheat.o debug.o +OBJECTS = fce.o video.o general.o endian.o svga.o sound.o nsf.o fds.o netplay.o ines.o state.o unif.o input.o file.o cart.o crc32.o memory.o cheat.o debug.o md5.o vsuni.o # x6502.o fceu: fceu2 include mappers/Makefile include boards/Makefile -include mbshare/Makefile +#include mbshare/Makefile include input/Makefile fceu2: ${OBJECTS} ${MOBJS} ${MUOBJS} ${MUSOBJS} ${INPOBJS} ${OBJDRIVER} diff --git a/boards/112.c b/boards/112.c new file mode 100644 index 0000000..a58cf5c --- /dev/null +++ b/boards/112.c @@ -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" + +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; + } +} + +static void M112Close(void) +{ + if(WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void M112Power(void) +{ + Sync(); + 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); +} diff --git a/boards/164.c b/boards/164.c new file mode 100644 index 0000000..5b4bf05 --- /dev/null +++ b/boards/164.c @@ -0,0 +1,110 @@ +/* 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)); +} + +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; + setchr8(0); + cmd=0; + SetReadHandler(0x8000,0xFFFF,CartBR); + SetWriteHandler(0x4020,0xFFFF,Write); + SetReadHandler(0x6000,0x7FFF,AWRAM); + SetWriteHandler(0x6000,0x7FFF,BWRAM); + Sync(); +} + +static void Power2(void) +{ + memset(DRegs,0,8); + DRegs[1]=0xFF; + setchr8(0); + 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; + GameStateRestore=StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/boards/183.c b/boards/183.c new file mode 100644 index 0000000..94cf072 --- /dev/null +++ b/boards/183.c @@ -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); +} diff --git a/boards/186.c b/boards/186.c new file mode 100644 index 0000000..3698c6c --- /dev/null +++ b/boards/186.c @@ -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); +} diff --git a/boards/8157.c b/boards/8157.c new file mode 100644 index 0000000..3c4a4fb --- /dev/null +++ b/boards/8157.c @@ -0,0 +1,77 @@ +/* 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) +{ + 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(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=0; + Sync(); +} + +static void UNL8157Reset(void) +{ + cmdreg=0; + 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); +} diff --git a/boards/8237.c b/boards/8237.c new file mode 100644 index 0000000..5b4e2df --- /dev/null +++ b/boards/8237.c @@ -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"); +} diff --git a/boards/90.c b/boards/90.c new file mode 100644 index 0000000..489a540 --- /dev/null +++ b/boards/90.c @@ -0,0 +1,408 @@ +/* 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 int is209; + +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 DECLFR(M90Read) +{ + switch(A) + { + case 0x5800: return (mul[0]*mul[1]); + case 0x5801: return((mul[0]*mul[1])>>8); + case 0x5803: return (regie); + default: return(tekker); + } +} + +static void mira(void) +{ + if(tkcom[0]&0x20 && is209) + { + 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[2]&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]&3) + { + case 1: // 16 KB + setprg16(0x8000,(prgb[0]&0x1F)|((tkcom[3]&6)<<4)); + setprg16(0xC000,(prgb[2]&0x1F)|((tkcom[3]&6)<<4)); + break; + case 2: //2 = 8 KB ?? + if(tkcom[0]&0x4) + { + setprg8(0x8000,(prgb[0]&0x3F)|bankmode); + setprg8(0xa000,(prgb[1]&0x3F)|bankmode); + setprg8(0xc000,(prgb[2]&0x3F)|bankmode); + setprg8(0xe000,(prgb[3]&0x3F)|bankmode); + } + else + { + 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,((~0)&0x3F)|bankmode); + } + break; + case 0: + case 3: + 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(M90Write) +{ + if(A==0x5800) mul[0]=V; + else if(A==0x5801) mul[1]=V; + else if(A==0x5803) regie=V; + + A&=0xF007; + if(A>=0x8000 && A<=0x8003) + { + prgb[A&3]=V; + tekprom(); + } + else if(A>=0x9000 && A<=0x9007) + { + chrlow[A&7]=V; + tekvrom(); + } + else if(A>=0xa000 && A<=0xa007) + { + chrhigh[A&7]=V; + tekvrom(); + } + else if(A>=0xb000 && A<=0xb007) + { + if(A&4) + { + names[A&3]&=0x00FF; + names[A&3]|=V<<8; + } + else + { + names[A&3]&=0xFF00; + names[A&3]|=V; + } + mira(); + } + else if(A>=0xd000 && A<=0xdfff) + { + tkcom[A&3]=V; + tekprom(); + tekvrom(); + mira(); +/* + 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 00: FCEU_printf("Vertical\n");break; + case 01: FCEU_printf("Horizontal\n");break; + case 02: FCEU_printf("Nametable 0 only\n");break; + case 03: 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"); + } +*/ + } + else switch(A) + { + case 0xc000: //FCEU_printf("%s IRQ (C000)\n",V&1?"Enable":"Disable"); + IRQa=V&1;if(!(V&1)) X6502_IRQEnd(FCEU_IQEXT);break; + case 0xc002: //FCEU_printf("Disable IRQ (C002) scanline=%d\n", scanline); + IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break; + case 0xc003: //FCEU_printf("Enable IRQ (C003) scanline=%d\n", scanline); + IRQa=1;break; + case 0xc001: 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 0xc004: //FCEU_printf("Pre Counter Loaded and Xored wiht C006: %d\n",V^IRQXOR); + IRQPre=V^IRQXOR;break; + case 0xc005: //FCEU_printf("Main Counter Loaded and Xored wiht C006: %d\n",V^IRQXOR); + IRQCount=V^IRQXOR;break; + case 0xc006: //FCEU_printf("Xor Value: %d\n",V); + IRQXOR=V;break; + case 0xc007: //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 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(); + } +} + +static void SLWrap(void) +{ + int x; + if((IRQMode&3)!=2) for(x=0;x<8;x++) ClockCounter(); +} + +static uint32 lastread; +static void FP_FASTAPASS(1) M90PPU(uint32 A) +{ + if(lastread!=A) + { + lastread=A; + if((IRQMode&3)==2) + { + ClockCounter(); + ClockCounter(); + } + } +} + +static void togglie() +{ + tekker>>=6; + if(tekker>3) + tekker=0; + else + tekker++; + tekker<<=6; + FCEU_printf("tekker=%04x\n",tekker); + memset(tkcom,0xff,sizeof(tkcom)); + memset(prgb,0xff,sizeof(prgb)); + tekprom(); + tekvrom(); +} + +static void M90Restore(int version) +{ + tekprom(); + tekvrom(); + mira(); +} + +static void M90Power(void) +{ + SetWriteHandler(0x5000,0xffff,M90Write); + SetReadHandler(0x5000,0x5fff,M90Read); + SetReadHandler(0x6000,0xffff,CartBR); + + mul[0]=mul[1]=regie=0xFF; + + memset(tkcom,0xff,sizeof(tkcom)); + memset(prgb,0xff,sizeof(prgb)); + memset(chrlow,0xff,sizeof(chrlow)); + memset(chrhigh,0xff,sizeof(chrhigh)); + memset(names,0x00,sizeof(names)); + + tekker=0; + + tekprom(); + tekvrom(); +} + + +void Mapper90_Init(CartInfo *info) +{ + is209=0; + info->Reset=togglie; + info->Power=M90Power; + PPU_hook = M90PPU; + GameHBIRQHook2 = SLWrap; + GameStateRestore=M90Restore; + AddExState(Tek_StateRegs, ~0, 0, 0); +} + +void Mapper209_Init(CartInfo *info) +{ + is209=1; + info->Reset=togglie; + info->Power=M90Power; + PPU_hook = M90PPU; + GameHBIRQHook2 = SLWrap; + GameStateRestore=M90Restore; + AddExState(Tek_StateRegs, ~0, 0, 0); +} diff --git a/boards/Makefile b/boards/Makefile index 58dd4ef..b63f897 100644 --- a/boards/Makefile +++ b/boards/Makefile @@ -1,9 +1,6 @@ -MUOBJS = boards/simple.o boards/malee.o boards/supervision.o boards/novel.o boards/super24.o boards/h2288.o boards/sachen.o +MUOBJS += boards/mmc5.o boards/mmc3.o boards/mmc1.o boards/tengen.o boards/bonza.o boards/deirom.o +MUOBJS += boards/dream.o boards/konami-qtai.o boards/n106.o boards/karaoke.o boards/90.o boards/112.o +MUOBJS += boards/164.o boards/183.o boards/186.o boards/8237.o boards/8157.o boards/addrlatch.o +MUOBJS += boards/datalatch.o boards/h2288.o boards/malee.o boards/novel.o boards/sachen.o +MUOBJS += boards/subor.o boards/super24.o boards/supervision.o -boards/simple.o: boards/simple.c -boards/malee.o: boards/malee.c -boards/supervision.o: boards/supervision.c -boards/novel.o: boards/novel.c -boards/super24.o: boards/super24.c -boards/h2288.o: boards/h2288.c -boards/sachen.o: boards/sachen.c diff --git a/boards/addrlatch.c b/boards/addrlatch.c new file mode 100644 index 0000000..37be90a --- /dev/null +++ b/boards/addrlatch.c @@ -0,0 +1,53 @@ +/* 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 DECLFW(UNLCC21Write) +{ + addrlatche=A; + setchr8(addrlatche&1); + setmirror(MI_0+((addrlatche&2)>>1)); +} + +static void UNLCC21Power(void) +{ + setprg32(0x8000,0); + setchr8(0); + SetReadHandler(0x8000,0xFFFF,CartBR); + SetWriteHandler(0x8000,0xffff,UNLCC21Write); +} + +static void UNLCC21Restore(int version) +{ + setchr8(addrlatche&1); + setmirror(MI_0+((addrlatche&2)>>1)); +} + +void UNLCC21_Init(CartInfo *info) +{ + info->Power=UNLCC21Power; + GameStateRestore=UNLCC21Restore; + AddExState(&addrlatche, 2, 0, "ALATC"); +} diff --git a/boards/bonza.c b/boards/bonza.c new file mode 100644 index 0000000..5e572f1 --- /dev/null +++ b/boards/bonza.c @@ -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); +} diff --git a/boards/datalatch.c b/boards/datalatch.c new file mode 100644 index 0000000..217adb4 --- /dev/null +++ b/boards/datalatch.c @@ -0,0 +1,207 @@ +/* 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; + +//------------------ CPROM --------------------------- + +static DECLFW(CPROMWrite) +{ + latche=V&3; + setchr4(0x1000,latche); +} + +static void CPROMReset(void) +{ + setprg32(0x8000,0); + setchr8(0); + SetReadHandler(0x8000,0xFFFF,CartBR); + SetWriteHandler(0x8000,0xffff,CPROMWrite); +} + +static void CPROMRestore(int version) +{ + setchr4(0x1000,latche); +} + +void CPROM_Init(CartInfo *info) +{ + info->Power=CPROMReset; + GameStateRestore=CPROMRestore; + AddExState(&latche, 1, 0, "LATC"); +} + +//------------------ CNROM --------------------------- + +DECLFW(CNROMWrite) +{ + latche=V&3; + setchr8(latche); +} + +static void CNROMReset(void) +{ + setprg16(0x8000,0); + setprg16(0xC000,1); + SetReadHandler(0x8000,0xFFFF,CartBR); + SetWriteHandler(0x8000,0xffff,CNROMWrite); +} + +static void CNROMRestore(int version) +{ + setchr8(latche); +} + +void CNROM_Init(CartInfo *info) +{ + info->Power=CNROMReset; + GameStateRestore=CNROMRestore; + AddExState(&latche, 1, 0, "LATC"); +} + +//------------------ NROM128 --------------------------- + +static void NROM128Reset(void) +{ + setprg16(0x8000,0); + setprg16(0xC000,0); + setchr8(0); + SetReadHandler(0x8000,0xFFFF,CartBR); +} + +void NROM128_Init(CartInfo *info) +{ + info->Power=NROM128Reset; +} + +//------------------ NROM256 --------------------------- + +static void NROM256Reset(void) +{ + setprg16(0x8000,0); + setprg16(0xC000,1); + setchr8(0); + SetReadHandler(0x8000,0xFFFF,CartBR); +} + +void NROM256_Init(CartInfo *info) +{ + info->Power=NROM256Reset; +} + +//------------------ MHROM --------------------------- + +static DECLFW(MHROMWrite) +{ + setprg32(0x8000,V>>4); + setchr8(V); + latche=V; +} + +static void MHROMReset(void) +{ + setprg32(0x8000,0); + setchr8(0); + latche=0; + SetReadHandler(0x8000,0xFFFF,CartBR); +} + +static void MHROMRestore(int version) +{ + setprg32(0x8000,latche); + setchr8(latche); + SetWriteHandler(0x8000,0xffff,MHROMWrite); +} + +void MHROM_Init(CartInfo *info) +{ + info->Power=MHROMReset; + AddExState(&latche, 1, 0,"LATC"); + PRGmask32[0]&=1; + CHRmask8[0]&=1; + GameStateRestore=MHROMRestore; +} + +//------------------ UNROM --------------------------- + +static void UNROMRestore(int version) +{ + setprg16(0x8000,latche); +} + +static DECLFW(UNROMWrite) +{ + setprg16(0x8000,V); + latche=V; +} + +static void UNROMReset(void) +{ + setprg16(0x8000,0); + setprg16(0xc000,~0); + setchr8(0); + SetWriteHandler(0x8000,0xffff,UNROMWrite); + SetReadHandler(0x8000,0xFFFF,CartBR); + latche=0; +} + +void UNROM_Init(CartInfo *info) +{ + info->Power=UNROMReset; + PRGmask16[0]&=7; + AddExState(&latche, 1, 0, "LATC"); + GameStateRestore=UNROMRestore; +} + +//------------------ GNROM --------------------------- + +static void GNROMSync() +{ + setchr8(latche&3); + setprg32(0x8000,(latche>>4)&3); +} + +static DECLFW(GNROMWrite) +{ + latche=V&0x33; + GNROMSync(); +} + +static void GNROMStateRestore(int version) +{ + GNROMSync(); +} + +static void GNROMReset(void) +{ + latche=0; + GNROMSync(); + SetWriteHandler(0x8000,0xffff,GNROMWrite); + SetReadHandler(0x8000,0xFFFF,CartBR); +} + +void GNROM_Init(CartInfo *info) +{ + info->Power=GNROMReset; + AddExState(&latche, 1, 0, "LATC"); + GameStateRestore=GNROMStateRestore; +} diff --git a/boards/deirom.c b/boards/deirom.c new file mode 100644 index 0000000..7a1ed43 --- /dev/null +++ b/boards/deirom.c @@ -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); +} diff --git a/boards/dream.c b/boards/dream.c new file mode 100644 index 0000000..16214f7 --- /dev/null +++ b/boards/dream.c @@ -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 latch; + +static void DoPRG(void) +{ + setprg16(0x8000,latch); + setprg16(0xC000,8); +} + +static DECLFW(DREAMWrite) +{ + latch=V&7; + DoPRG(); +} + +static void DREAMPower(void) +{ + latch=0; + SetReadHandler(0x8000,0xFFFF,CartBR); + SetWriteHandler(0x5020,0x5020,DREAMWrite); + setchr8(0); + DoPRG(); +} + +static void Restore(int version) +{ + DoPRG(); +} + +void DreamTech01_Init(CartInfo *info) +{ + GameStateRestore=Restore; + info->Power=DREAMPower; + AddExState(&latch, 1, 0, "LATCH"); +} diff --git a/boards/h2288.c b/boards/h2288.c index 9b9dcbc..c2c6621 100644 --- a/boards/h2288.c +++ b/boards/h2288.c @@ -1,101 +1,89 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell - * - * 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 - */ - -/* Not finished. Darn evil game... *Mumble*... */ - -#include "mapinc.h" - -static uint8 cmd; -static uint8 regs[8]; - -static void DoPRG(void) -{ - if(cmd&0x40) - { - setprg8(0xC000,regs[4]); - setprg8(0xA000,regs[5]); - setprg8(0x8000,~1); - setprg8(0xE000,~0); - } - else - { - setprg8(0x8000,regs[4]); - setprg8(0xA000,regs[5]); - setprg8(0xC000,~1); - setprg8(0xE000,~0); - } -} - -static void DoCHR(void) -{ - uint32 base=(cmd&0x80)<<5; - - setchr2(0x0000^base,regs[0]); - setchr2(0x0800^base,regs[2]); - - setchr1(0x1000^base,regs[6]); - setchr1(0x1400^base,regs[1]); - setchr1(0x1800^base,regs[7]); - setchr1(0x1c00^base,regs[3]); -} - -static DECLFW(H2288Write) -{ - //printf("$%04x:$%02x, $%04x\n",A,V,X.PC.W); - //RAM[0x7FB]=0x60; - switch(A&0xE001) - { - case 0xa000:setmirror((V&1)^1);break; - case 0x8000:// DumpMem("out",0x0000,0xFFFF); - cmd=V;DoPRG();DoCHR(); - X6502_Rebase();break; - case 0x8001:regs[cmd&7]=V; - if((cmd&7)==4 || (cmd&7)==5) { - DoPRG(); - X6502_Rebase(); - } else - DoCHR(); - break; - } -} - -static DECLFR(H2288Read) -{ - //printf("Rd: $%04x, $%04x\n",A,X.PC.W); - return((X.DB&0xFE)|(A&(A>>8))); -} - -static void H2288Reset(void) -{ - int x; - - SetReadHandler(0x5800,0x5FFF,H2288Read); - SetReadHandler(0x8000,0xFFFF,CartBR); - SetWriteHandler(0x8000,0xFFFF,H2288Write); - for(x=0;x<8;x++) regs[x]=0; - cmd=0; - DoPRG(); - DoCHR(); -} - -void H2288_Init(void) -{ - BoardPower=H2288Reset; -} +/* 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"); +} diff --git a/boards/karaoke.c b/boards/karaoke.c new file mode 100644 index 0000000..eccf9c2 --- /dev/null +++ b/boards/karaoke.c @@ -0,0 +1,78 @@ +/* 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 DReg; +static SFORMAT StateRegs[]= +{ + {&DReg, 1, "DREG"}, + {0} +}; + +static void Sync(void) +{ + if(DReg) + { + if(DReg & 0x10) + setprg16(0x8000,(DReg&7)); + else + setprg16(0x8000,(DReg&7)|8); + } + else + setprg16(0x8000,7); +} + +static void StateRestore(int version) +{ + Sync(); +} + +static DECLFW(M188Write) +{ + DReg=V; + Sync(); +} + +static DECLFR(testr) +{ + return(3); +} + + +static void Power(void) +{ + setchr8(0); + setprg8(0xc000,0xE); + setprg8(0xe000,0xF); + DReg = 0; + Sync(); + SetReadHandler(0x6000,0x7FFF,testr); + SetReadHandler(0x8000,0xFFFF,CartBR); + SetWriteHandler(0x8000,0xFFFF,M188Write); +} + + +void Mapper188_Init(CartInfo *info) +{ + info->Power=Power; + GameStateRestore=StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/boards/konami-qtai.c b/boards/konami-qtai.c new file mode 100644 index 0000000..ff552e1 --- /dev/null +++ b/boards/konami-qtai.c @@ -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); +} diff --git a/boards/malee.c b/boards/malee.c index f575159..b0f194e 100644 --- a/boards/malee.c +++ b/boards/malee.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -20,10 +20,7 @@ #include "mapinc.h" -DECLFW(MWrite) -{ - (GameMemBlock-0x7000)[A]=V; -} +static uint8 WRAM[2048]; static void MALEEReset(void) { @@ -31,15 +28,14 @@ static void MALEEReset(void) SetReadHandler(0x8000,0xFFFF,CartBR); SetReadHandler(0x6000,0x67ff,CartBR); SetReadHandler(0x7000,0x77FF,CartBR); - SetWriteHandler(0x7000,0x77FF,MWrite); setprg2r(1,0x6000,0); setprg32(0x8000,0); setchr8(0); } -void MALEE_Init(void) +void MALEE_Init(CartInfo *info) { - AddExState(GameMemBlock, 2048, 0,"RAM"); - SetupCartPRGMapping(0x10,GameMemBlock,2048,1); - BoardPower=MALEEReset; + info->Power=MALEEReset; + SetupCartPRGMapping(0x10, WRAM, 2048, 1); + AddExState(WRAM, 2048, 0,"RAM"); } diff --git a/boards/mapinc.h b/boards/mapinc.h index e6d4c41..7c2b042 100644 --- a/boards/mapinc.h +++ b/boards/mapinc.h @@ -1,11 +1,12 @@ -#include "../types.h" -#include "../x6502.h" -#include "../fce.h" -#include "../version.h" -#include "../memory.h" -#include "../sound.h" -#include "../svga.h" -#include "../state.h" -#define UNIFPRIV -#include "../unif.h" -#include "../cart.h" +#include "../types.h" +#include "../x6502.h" +#include "../fce.h" +#include "../ppu.h" +#include "../memory.h" +#include "../sound.h" +#include "../state.h" +#include "../cart.h" +#include "../cheat.h" +#include "../unif.h" +#include "../svga.h" +#include diff --git a/boards/mmc1.c b/boards/mmc1.c new file mode 100644 index 0000000..0eefc59 --- /dev/null +++ b/boards/mmc1.c @@ -0,0 +1,426 @@ +/* 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. */ // it is now! +} + +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) */ + 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"); + AddExState(&Buffer, 1, 1, "BFFR"); + AddExState(&BufferShift, 1, 1, "BFRS"); +} + +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); +} + + diff --git a/boards/mmc3.c b/boards/mmc3.c new file mode 100644 index 0000000..14ce5cb --- /dev/null +++ b/boards/mmc3.c @@ -0,0 +1,1408 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 1998 BERO + * Copyright (C) 2003 Xodnizel + * Mapper 12 code Copyright (C) 2003 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 + */ + +/* Code for emulating iNES mappers 4,12,44,45,47,49,52,74,114,115,116,118, + 119,148,165,205,214,215,245,249,250,254 +*/ + +#include "mapinc.h" +#include "mmc3.h" + +uint8 MMC3_cmd=0; +uint8 *WRAM=0; +uint8 *CHRRAM=0; +uint32 CHRRAMSize=0; +uint8 EXPREGS[8]={0,0,0,0,0,0,0,0}; /* For bootleg games, mostly. */ + +static uint8 A000B=0,A001B=0; +static uint8 DRegBuf[8]={0,0,0,0,0,0,0,0}; + +#undef IRQCount +#undef IRQLatch +#undef IRQa +uint8 IRQCount=0,IRQLatch=0,IRQa=0; +uint8 IRQReload=0; + +static SFORMAT MMC3_StateRegs[]= +{ + {DRegBuf, 8, "REGS"}, + {&MMC3_cmd, 1, "CMD"}, + {&A000B, 1, "A000"}, + {&A001B, 1, "A001"}, + {&IRQReload, 1, "IRQR"}, + {&IRQCount, 1, "IRQC"}, + {&IRQLatch, 1, "IRQL"}, + {&IRQa, 1, "IRQA"}, + {0} +}; + +static int mmc3opts=0; +static int wrams=0; + +void (*pwrap)(uint32 A, uint8 V); +void (*cwrap)(uint32 A, uint8 V); +void (*mwrap)(uint8 V); + +void GenMMC3Power(void); +void FixMMC3PRG(int V); +void FixMMC3CHR(int V); + +void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery); + +// ---------------------------------------------------------------------- +// ------------------------- Generic MM3 Code --------------------------- +// ---------------------------------------------------------------------- + +void FixMMC3PRG(int V) +{ + if(V&0x40) + { + pwrap(0xC000,DRegBuf[6]); + pwrap(0x8000,~1); + } + else + { + pwrap(0x8000,DRegBuf[6]); + pwrap(0xC000,~1); + } + pwrap(0xA000,DRegBuf[7]); + pwrap(0xE000,~0); +} + +void FixMMC3CHR(int V) +{ + int cbase=(V&0x80)<<5; + + cwrap((cbase^0x000),DRegBuf[0]&(~1)); + cwrap((cbase^0x400),DRegBuf[0]|1); + cwrap((cbase^0x800),DRegBuf[1]&(~1)); + cwrap((cbase^0xC00),DRegBuf[1]|1); + + cwrap(cbase^0x1000,DRegBuf[2]); + cwrap(cbase^0x1400,DRegBuf[3]); + cwrap(cbase^0x1800,DRegBuf[4]); + cwrap(cbase^0x1c00,DRegBuf[5]); +} + +void MMC3RegReset(void) +{ + IRQCount=IRQLatch=IRQa=MMC3_cmd=0; + + DRegBuf[0]=0; + DRegBuf[1]=2; + DRegBuf[2]=4; + DRegBuf[3]=5; + DRegBuf[4]=6; + DRegBuf[5]=7; + DRegBuf[6]=0; + DRegBuf[7]=1; + + FixMMC3PRG(0); + FixMMC3CHR(0); +} + +DECLFW(MMC3_CMDWrite) +{ + switch(A&0xE001) + { + case 0x8000: + if((V&0x40) != (MMC3_cmd&0x40)) + FixMMC3PRG(V); + if((V&0x80) != (MMC3_cmd&0x80)) + FixMMC3CHR(V); + MMC3_cmd = V; + break; + case 0x8001: + { + int cbase=(MMC3_cmd&0x80)<<5; + DRegBuf[MMC3_cmd&0x7]=V; + switch(MMC3_cmd&0x07) + { + case 0: cwrap((cbase^0x000),V&(~1)); + cwrap((cbase^0x400),V|1); + break; + case 1: cwrap((cbase^0x800),V&(~1)); + cwrap((cbase^0xC00),V|1); + break; + case 2: cwrap(cbase^0x1000,V); + break; + case 3: cwrap(cbase^0x1400,V); + break; + case 4: cwrap(cbase^0x1800,V); + break; + case 5: cwrap(cbase^0x1C00,V); + break; + case 6: + if(MMC3_cmd&0x40) + pwrap(0xC000,V); + else + pwrap(0x8000,V); + break; + case 7: + pwrap(0xA000,V); + break; + } + } + break; + case 0xA000: + if(mwrap) mwrap(V&1); + break; + case 0xA001: + A001B=V; + break; + } +} + +DECLFW(MMC3_IRQWrite) +{ + switch(A&0xE001) + { + case 0xC000:IRQLatch=V;break; + case 0xC001:IRQReload=1;break; + case 0xE000:X6502_IRQEnd(FCEU_IQEXT);IRQa=0;break; + case 0xE001:IRQa=1;break; + } +} + +static void ClockMMC3Counter(void) +{ + int count = IRQCount; + if(!count || IRQReload) + { + IRQCount = IRQLatch; + IRQReload = 0; + } + else + IRQCount--; + if(count && !IRQCount) + { + if(IRQa) + { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void MMC3_hb(void) +{ + ClockMMC3Counter(); +} + +static void MMC3_hb_KickMasterHack(void) +{ + if(scanline==238) ClockMMC3Counter(); + ClockMMC3Counter(); +} + +static void MMC3_hb_PALStarWarsHack(void) +{ + if(scanline==240) ClockMMC3Counter(); + ClockMMC3Counter(); +} + +static void genmmc3restore(int version) +{ + if(mwrap) mwrap(A000B&1); + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void GENCWRAP(uint32 A, uint8 V) +{ + setchr1(A,V); +} + +static void GENPWRAP(uint32 A, uint8 V) +{ + setprg8(A,V&0x3F); +} + +static void GENMWRAP(uint8 V) +{ + A000B=V; + setmirror(V^1); +} + +static void GENNOMWRAP(uint8 V) +{ + A000B=V; +} + +static DECLFW(MBWRAM) +{ + WRAM[A-0x6000]=V; +} + +static DECLFR(MAWRAM) +{ + return(WRAM[A-0x6000]); +} + +static DECLFW(MBWRAMMMC6) +{ + WRAM[A&0x3ff]=V; +} + +static DECLFR(MAWRAMMMC6) +{ + return(WRAM[A&0x3ff]); +} + +void GenMMC3Power(void) +{ + SetWriteHandler(0x8000,0xBFFF,MMC3_CMDWrite); + SetWriteHandler(0xC000,0xFFFF,MMC3_IRQWrite); + SetReadHandler(0x8000,0xFFFF,CartBR); + A001B=A000B=0; + setmirror(1); + if(mmc3opts&1) + { + if(wrams==1024) + { + FCEU_CheatAddRAM(1,0x7000,WRAM); + SetReadHandler(0x7000,0x7FFF,MAWRAMMMC6); + SetWriteHandler(0x7000,0x7FFF,MBWRAMMMC6); + } + else + { + FCEU_CheatAddRAM(wrams>>10,0x6000,WRAM); + SetReadHandler(0x6000,0x6000+wrams-1,MAWRAM); + SetWriteHandler(0x6000,0x6000+wrams-1,MBWRAM); + } + if(!(mmc3opts&2)) + FCEU_dwmemset(WRAM,0,wrams); + } + MMC3RegReset(); + if(CHRRAM) + FCEU_dwmemset(CHRRAM,0,CHRRAMSize); +} + +static void GenMMC3Close(void) +{ + if(CHRRAM) + FCEU_gfree(CHRRAM); + if(WRAM) + FCEU_gfree(WRAM); + CHRRAM=WRAM=NULL; +} + +void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery) +{ +pwrap=GENPWRAP; + cwrap=GENCWRAP; + mwrap=GENMWRAP; + + wrams=wram<<10; + + PRGmask8[0]&=(prg>>13)-1; + CHRmask1[0]&=(chr>>10)-1; + CHRmask2[0]&=(chr>>11)-1; + + if(wram) + { + mmc3opts|=1; + WRAM=(uint8*)FCEU_gmalloc(wrams); + AddExState(WRAM, wrams, 0, "WRAM"); + } + + if(battery) + { + mmc3opts|=2; + info->SaveGame[0]=WRAM; + info->SaveGameLen[0]=wrams; + } + + if(!chr) + { + CHRRAM=(uint8*)FCEU_gmalloc(8192); + CHRRAMSize=8192; + SetupCartCHRMapping(0, CHRRAM, 8192, 1); + AddExState(CHRRAM, 8192, 0, "CHRR"); + } + + AddExState(MMC3_StateRegs, ~0, 0, 0); + + info->Power=GenMMC3Power; + info->Reset=MMC3RegReset; + info->Close=GenMMC3Close; + + if(info->CRC32 == 0x5104833e) // Kick Master + GameHBIRQHook = MMC3_hb_KickMasterHack; + else if(info->CRC32 == 0x5a6860f1 || info->CRC32 == 0xae280e20) // Shougi Meikan '92/'93 + GameHBIRQHook = MMC3_hb_KickMasterHack; + else if(info->CRC32 == 0xfcd772eb) // PAL Star Wars, similar problem as Kick Master. + GameHBIRQHook = MMC3_hb_PALStarWarsHack; + else + GameHBIRQHook=MMC3_hb; + GameStateRestore=genmmc3restore; +} + +// ---------------------------------------------------------------------- +// -------------------------- MMC3 Based Code --------------------------- +// ---------------------------------------------------------------------- + +// ---------------------------- Mapper 4 -------------------------------- + +static int hackm4=0;/* For Karnov, maybe others. BLAH. Stupid iNES format.*/ + +static void M4Power(void) +{ + GenMMC3Power(); + A000B=(hackm4^1)&1; + setmirror(hackm4); +} + +void Mapper4_Init(CartInfo *info) +{ + int ws=8; + + if((info->CRC32==0x93991433 || info->CRC32==0xaf65aa84)) + { + FCEU_printf("Low-G-Man can not work normally in the iNES format.\nThis game has been recognized by its CRC32 value, and the appropriate changes will be made so it will run.\nIf you wish to hack this game, you should use the UNIF format for your hack.\n\n"); + ws=0; + } + GenMMC3_Init(info,512,256,ws,info->battery); + info->Power=M4Power; + hackm4=info->mirror; +} + +// ---------------------------- Mapper 12 ------------------------------- + +static void M12CW(uint32 A, uint8 V) +{ + setchr1(A,(EXPREGS[(A&0x1000)>>12]<<8)+V); +} + +static DECLFW(M12Write) +{ + EXPREGS[0]=V&0x01; + EXPREGS[1]=(V&0x10)>>4; +} + +static void M12Power(void) +{ + EXPREGS[0]=EXPREGS[1]=0; + GenMMC3Power(); + SetWriteHandler(0x4100,0x5FFF,M12Write); +} + +void Mapper12_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 8, info->battery); + cwrap=M12CW; + info->Power=M12Power; + AddExState(EXPREGS, 2, 0, "EXPR"); +} + +// ---------------------------- Mapper 44 ------------------------------- + +static void M44PW(uint32 A, uint8 V) +{ + uint32 NV=V; + if(EXPREGS[0]>=6) NV&=0x1F; + else NV&=0x0F; + NV|=EXPREGS[0]<<4; + setprg8(A,NV); +} + +static void M44CW(uint32 A, uint8 V) +{ + uint32 NV=V; + if(EXPREGS[0]<6) NV&=0x7F; + NV|=EXPREGS[0]<<7; + setchr1(A,NV); +} + +static DECLFW(M44Write) +{ + if(A&1) + { + EXPREGS[0]=V&7; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } + else + MMC3_CMDWrite(A,V); +} + +static void M44Power(void) +{ + EXPREGS[0]=0; + GenMMC3Power(); + SetWriteHandler(0xA000,0xBFFF,M44Write); +} + +void Mapper44_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 8, info->battery); + cwrap=M44CW; + pwrap=M44PW; + info->Power=M44Power; + AddExState(EXPREGS, 1, 0, "EXPR"); +} + +// ---------------------------- Mapper 45 ------------------------------- + +static void M45CW(uint32 A, uint8 V) +{ + uint32 NV=V; + if(EXPREGS[2]&8) + NV&=(1<<((EXPREGS[2]&7)+1))-1; + else + NV&=0; + NV|=EXPREGS[0]|((EXPREGS[2]&0xF0)<<4); + // &0x10(not 0xf0) is valid given the original + // description of mapper 45 by kevtris, + // but this fixes Super 8 in 1. + setchr1(A,NV); +} + +static void M45PW(uint32 A, uint8 V) +{ + V&=(EXPREGS[3]&0x3F)^0x3F; + V|=EXPREGS[1]; + setprg8(A,V); +} + +static DECLFW(M45Write) +{ + if(EXPREGS[3]&0x40) + { + WRAM[A-0x6000]=V; + return; + } + EXPREGS[EXPREGS[4]]=V; + EXPREGS[4]=(EXPREGS[4]+1)&3; +// FCEU_printf("write 0=%04x 1=%04x 2=%04x 3=%04x (%04x:%04x)\n",EXPREGS[0],EXPREGS[1],EXPREGS[2],EXPREGS[3],A,V); + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void M45Reset(void) +{ + FCEU_dwmemset(EXPREGS,0,5); + MMC3RegReset(); +} + +static void M45Power(void) +{ + M45Reset(); + GenMMC3Power(); + SetWriteHandler(0x6000,0x7FFF,M45Write); +} + +void Mapper45_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 8, info->battery); + cwrap=M45CW; + pwrap=M45PW; + info->Reset=M45Reset; + info->Power=M45Power; + AddExState(EXPREGS, 5, 0, "EXPR"); +} + +// ---------------------------- Mapper 47 ------------------------------- + +static void M47PW(uint32 A, uint8 V) +{ + V&=0xF; + V|=EXPREGS[0]<<4; + setprg8(A,V); +} + +static void M47CW(uint32 A, uint8 V) +{ + uint32 NV=V; + NV&=0x7F; + NV|=EXPREGS[0]<<7; + setchr1(A,NV); +} + +static DECLFW(M47Write) +{ + EXPREGS[0]=V&1; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void M47Power(void) +{ + EXPREGS[0]=0; + GenMMC3Power(); + SetWriteHandler(0x6000,0x7FFF,M47Write); + SetReadHandler(0x6000,0x7FFF,0); +} + +void Mapper47_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 8, info->battery); + pwrap=M47PW; + cwrap=M47CW; + info->Power=M47Power; + AddExState(EXPREGS, 1, 0, "EXPR"); +} + +// ---------------------------- Mapper 49 ------------------------------- + +static void M49PW(uint32 A, uint8 V) +{ + if(EXPREGS[0]&1) + { + V&=0xF; + V|=(EXPREGS[0]&0xC0)>>2; + setprg8(A,V); + } + else + setprg32(0x8000,(EXPREGS[0]>>4)&3); +} + +static void M49CW(uint32 A, uint8 V) +{ + uint32 NV=V; + NV&=0x7F; + NV|=(EXPREGS[0]&0xC0)<<1; + setchr1(A,NV); +} + +static DECLFW(M49Write) +{ + if(A001B&0x80) + { + EXPREGS[0]=V; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } +} + +static void M49Reset(void) +{ + EXPREGS[0]=0; + MMC3RegReset(); +} + +static void M49Power(void) +{ + M49Reset(); + GenMMC3Power(); + SetWriteHandler(0x6000,0x7FFF,M49Write); + SetReadHandler(0x6000,0x7FFF,0); +} + +void Mapper49_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 0, 0); + cwrap=M49CW; + pwrap=M49PW; + info->Reset=M49Reset; + info->Power=M49Power; + AddExState(EXPREGS, 1, 0, "EXPR"); +} + +// ---------------------------- Mapper 52 ------------------------------- + +static void M52PW(uint32 A, uint8 V) +{ + uint32 NV=V; + NV&=0x1F^((EXPREGS[0]&8)<<1); + NV|=((EXPREGS[0]&6)|((EXPREGS[0]>>3)&EXPREGS[0]&1))<<4; + setprg8(A,NV); +} + +static void M52CW(uint32 A, uint8 V) +{ + uint32 NV=V; + NV&=0xFF^((EXPREGS[0]&0x40)<<1); + NV|=(((EXPREGS[0]>>3)&4)|((EXPREGS[0]>>1)&2)|((EXPREGS[0]>>6)&(EXPREGS[0]>>4)&1))<<7; + setchr1(A,NV); +} + +static DECLFW(M52Write) +{ + if(EXPREGS[1]) + { + WRAM[A-0x6000]=V; + return; + } + EXPREGS[1]=1; + EXPREGS[0]=V; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void M52Reset(void) +{ + EXPREGS[0]=EXPREGS[1]=0; + MMC3RegReset(); +} + +static void M52Power(void) +{ + M52Reset(); + GenMMC3Power(); + SetWriteHandler(0x6000,0x7FFF,M52Write); +} + +void Mapper52_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 8, info->battery); + cwrap=M52CW; + pwrap=M52PW; + info->Reset=M52Reset; + info->Power=M52Power; + AddExState(EXPREGS, 2, 0, "EXPR"); +} + +// ---------------------------- Mapper 74 ------------------------------- + +static void M74CW(uint32 A, uint8 V) +{ +// FCEU_printf("%04x:%04x\n",A,V); +// if((V==0)||(V==1)) //Dai-2-Ji - Super Robot Taisen (As).nes + if((V==0)||(V==1)||(V==2)||(V==3)) //Ying Lie Qun Xia Zhuan (Chinese).nes, 4096 CHR RAM +// if((V==8)||(V==9)) //Di 4 Ci - Ji Qi Ren Dai Zhan (As).nes +// if((V==8)||(V==9)||(V==0xA)||(V==0xB)) //Ying Lie Qun Xia Zhuan (Chinese).nes, 4096 CHR RAM + setchr1r(0x10,A,V); + else + setchr1r(0x0,A,V); +} + +void Mapper74_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 8, info->battery); + cwrap=M74CW; +// CHRRAMSize=2048; + CHRRAMSize=4096; + CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); + AddExState(CHRRAM, CHRRAMSize, 0, "CHRR"); +} + +// ---------------------------- Mapper 114 ------------------------------ + +static uint8 cmdin; +uint8 m114_perm[8] = {0, 3, 1, 5, 6, 7, 2, 4}; + +static void M114PWRAP(uint32 A, uint8 V) +{ + if(EXPREGS[0]&0x80) + { + setprg16(0x8000,EXPREGS[0]&0xF); + setprg16(0xC000,EXPREGS[0]&0xF); + } + else + setprg8(A,V&0x3F); +} + +static DECLFW(M114Write) +{ + if(A==0xE003) + { + IRQa=1; + IRQCount=V; + } + else if(A==0xE002) + { + IRQa=0; + X6502_IRQEnd(FCEU_IQEXT); + } + else switch(A&0xE000) + { + case 0x8000: setmirror((V&1)^1); break; + case 0xA000: MMC3_CMDWrite(0x8000,(V&0xC0)|(m114_perm[V&7])); cmdin=1; break; + case 0xC000: if(!cmdin) break; + MMC3_CMDWrite(0x8001,V); + cmdin=0; + break; + } +} + +static DECLFW(M114ExWrite) +{ + if(A<=0x7FFF) + { + EXPREGS[0]=V; + FixMMC3PRG(MMC3_cmd); + } +} + +static void M114Power(void) +{ + GenMMC3Power(); + SetWriteHandler(0x8000,0xFFFF,M114Write); + SetWriteHandler(0x5000,0x7FFF,M114ExWrite); +} + +static void M114Reset(void) +{ + EXPREGS[0]=0; + MMC3RegReset(); +} + +void Mapper114_Init(CartInfo *info) +{ + GenMMC3_Init(info, 256, 256, 0, 0); + pwrap=M114PWRAP; + info->Power=M114Power; + info->Reset=M114Reset; + AddExState(EXPREGS, 1, 0, "EXPR"); + AddExState(&cmdin, 1, 0, "CMDIN"); +} + +// ---------------------------- Mapper 115 ------------------------------ + +static void M115PW(uint32 A, uint8 V) +{ + setprg8(A,V); + if(EXPREGS[0]&0x80) + setprg16(0x8000,EXPREGS[0]&7); +} + +static void M115CW(uint32 A, uint8 V) +{ + setchr1(A,(uint32)V|((EXPREGS[1]&1)<<8)); +} + +static DECLFW(M115Write) +{ + if(A==0x6000) + EXPREGS[0]=V; + else if(A==0x6001) + EXPREGS[1]=V; + FixMMC3PRG(MMC3_cmd); +} + +static void M115Power(void) +{ + GenMMC3Power(); + SetWriteHandler(0x4100,0x7FFF,M115Write); + SetReadHandler(0x4100,0x7FFF,0); +} + +void Mapper115_Init(CartInfo *info) +{ + GenMMC3_Init(info, 128, 512, 0, 0); + cwrap=M115CW; + pwrap=M115PW; + info->Power=M115Power; + AddExState(EXPREGS, 2, 0, "EXPR"); +} + +// ---------------------------- Mapper 116 ------------------------------ + +static void M116CW(uint32 A, uint8 V) +{ + setchr1(A,V|((EXPREGS[0]&0x4)<<6)); +} + +static DECLFW(M116Write) +{ + EXPREGS[0]=V; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void M116Power(void) +{ + GenMMC3Power(); + SetWriteHandler(0x4100,0x4100,M116Write); +} + +void Mapper116_Init(CartInfo *info) +{ + GenMMC3_Init(info, 128, 512, 0, 0); + cwrap=M116CW; + info->Power=M116Power; + AddExState(EXPREGS, 4, 0, "EXPR"); +} + +// ---------------------------- Mapper 118 ------------------------------ + +static uint8 PPUCHRBus; +static uint8 TKSMIR[8]; + +static void FP_FASTAPASS(1) TKSPPU(uint32 A) +{ + A&=0x1FFF; + A>>=10; + PPUCHRBus=A; + setmirror(MI_0+TKSMIR[A]); +} + +static void TKSWRAP(uint32 A, uint8 V) +{ + TKSMIR[A>>10]=V>>7; + setchr1(A,V&0x7F); + if(PPUCHRBus==(A>>10)) + setmirror(MI_0+(V>>7)); +} + +void Mapper118_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 8, info->battery); + cwrap=TKSWRAP; + mwrap=GENNOMWRAP; + PPU_hook=TKSPPU; + AddExState(&PPUCHRBus, 1, 0, "PPUC"); +} + +// ---------------------------- Mapper 119 ------------------------------ + +static void TQWRAP(uint32 A, uint8 V) +{ + setchr1r((V&0x40)>>2,A,V&0x3F); +} + +void Mapper119_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 64, 0, 0); + cwrap=TQWRAP; + CHRRAMSize=8192; + CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); +} + +// ---------------------------- Mapper 191 ------------------------------ + +static void M191CW(uint32 A, uint8 V) +{ + setchr1r((V&0x80)>>3,A,V); +} + +void Mapper191_Init(CartInfo *info) +{ + GenMMC3_Init(info, 256, 256, 8, info->battery); + cwrap=M191CW; + CHRRAMSize=2048; + CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); + AddExState(CHRRAM, CHRRAMSize, 0, "CHRR"); +} + +// ---------------------------- Mapper 165 ------------------------------ + +static void M165CW(uint32 A, uint8 V) +{ + if(V==0) + setchr4r(0x10,A,0); + else + setchr4(A,V>>2); +} + +static void M165PPUFD(void) +{ + if(EXPREGS[0]==0xFD) + { + M165CW(0x0000,DRegBuf[0]); + M165CW(0x1000,DRegBuf[2]); + } +} + +static void M165PPUFE(void) +{ + if(EXPREGS[0]==0xFE) + { + M165CW(0x0000,DRegBuf[1]); + M165CW(0x1000,DRegBuf[4]); + } +} + +static void M165CWM(uint32 A, uint8 V) +{ + if(((MMC3_cmd&0x7)==0)||((MMC3_cmd&0x7)==2)) M165PPUFD(); + if(((MMC3_cmd&0x7)==1)||((MMC3_cmd&0x7)==4)) M165PPUFE(); +} + +static void FP_FASTAPASS(1) M165PPU(uint32 A) +{ + if((A&0x1FF0)==0x1FD0) + { + EXPREGS[0]=0xFD; + M165PPUFD(); + } else if((A&0x1FF0)==0x1FE0) + { + EXPREGS[0]=0xFE; + M165PPUFE(); + } +} + +static void M165Power(void) +{ + EXPREGS[0]=0xFD; + GenMMC3Power(); +} + +void Mapper165_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 128, 8, info->battery); + cwrap=M165CWM; + PPU_hook=M165PPU; + info->Power=M165Power; + CHRRAMSize = 4096; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); + AddExState(CHRRAM, CHRRAMSize, 0, "CHRR"); + AddExState(EXPREGS, 4, 0, "EXPR"); +} + +// ---------------------------- Mapper 182 ------------------------------ +// òàáëèöà ïåðìóòàöè àíàëîãè÷íà 114 ìàïïåðó, ðåãèñòðû ìàïïåðà ãîðàçäî ñëîæíåå, +// ÷åì èñïîëüçóþòñÿ çäåñü, õîòÿ âñå ïðåêðàñíî ðàáîòàåò. + +//static uint8 m182_perm[8] = {0, 3, 1, 5, 6, 7, 2, 4}; +static DECLFW(M182Write) +{ + switch(A&0xF003) + { + case 0x8001: setmirror((V&1)^1); break; + case 0xA000: MMC3_CMDWrite(0x8000,m114_perm[V&7]); break; + case 0xC000: MMC3_CMDWrite(0x8001,V); break; + case 0xE003: IRQCount=V; IRQa=1; X6502_IRQEnd(FCEU_IQEXT); break; + } +} + +static void M182Power(void) +{ + GenMMC3Power(); + SetWriteHandler(0x8000,0xFFFF,M182Write); +} + +void Mapper182_Init(CartInfo *info) +{ + GenMMC3_Init(info, 256, 256, 0, 0); + info->Power=M182Power; +} + +// ---------------------------- Mapper 205 ------------------------------ + +static void M205PW(uint32 A, uint8 V) +{ + if(EXPREGS[0]&2) + setprg8(A,(V&0x0f)|((EXPREGS[0]&3)<<4)); + else + setprg8(A,(V&0x1f)|((EXPREGS[0]&3)<<4)); +} + +static void M205CW(uint32 A, uint8 V) +{ + setchr1(A,V|((EXPREGS[0]&3)*128)); +} + +static DECLFW(M205Write) +{ + if((A&0x6800)==0x6800) EXPREGS[0]= V; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void M205Reset(void) +{ + EXPREGS[0]=0; + MMC3RegReset(); +} + +static void M205Power(void) +{ + GenMMC3Power(); + SetWriteHandler(0x4020,0x7FFF,M205Write); +} + +void Mapper205_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 8, 0); + pwrap=M205PW; + cwrap=M205CW; + info->Power=M205Power; + info->Reset=M205Reset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} + +// ---------------------------- Mapper 215 ------------------------------ + +static uint8 m215_perm[8] = {0, 2, 5, 3, 6, 1, 7, 4}; + +static void M215CW(uint32 A, uint8 V) +{ + if(EXPREGS[1]&0x04) + setchr1(A,V|0x100); + else + setchr1(A,(V&0x7F)|((EXPREGS[1]&0x10)<<3)); +} + +static void M215PW(uint32 A, uint8 V) +{ + if(EXPREGS[0]&0x80) + { + setprg16(0x8000,(EXPREGS[0]&0x0F)|(EXPREGS[1]&0x10)); + setprg16(0xC000,(EXPREGS[0]&0x0F)|(EXPREGS[1]&0x10)); + } + else if(EXPREGS[1]&0x08) + setprg8(A,(V&0x1F)|0x20); + else + setprg8(A,(V&0x0F)|(EXPREGS[1]&0x10)); +} + +static DECLFW(M215Write) +{ + if(!(EXPREGS[2])) + { + if(A >= 0xc000) + MMC3_IRQWrite(A,V); + else + MMC3_CMDWrite(A,V); + } + else switch(A&0xE001) + { + case 0xE000: X6502_IRQEnd(FCEU_IQEXT); IRQa=0; break; + case 0xE001: IRQCount=V; break; + case 0xC001: IRQa=1; break; + case 0xC000: setmirror(((V|(V>>7))&1)^1); break; + case 0xA000: MMC3_CMDWrite(0x8000,(V&0xC0)|(m215_perm[V&7])); cmdin=1; break; + case 0x8001: if(!cmdin) break; + MMC3_CMDWrite(0x8001,V); + cmdin=0; + break; + } +} + +static DECLFW(M215ExWrite) +{ + switch(A) + { + case 0x5000: + EXPREGS[0]=V; + FixMMC3PRG(MMC3_cmd); + break; + case 0x5001: + EXPREGS[1]=V; + FixMMC3CHR(MMC3_cmd); + break; + case 0x5007: + EXPREGS[2]=V; + MMC3RegReset(); + break; + } +} + +static void M215Power(void) +{ + EXPREGS[0]=0; + EXPREGS[1]=0xFF; + EXPREGS[2]=4; + GenMMC3Power(); + SetWriteHandler(0x8000,0xFFFF,M215Write); + SetWriteHandler(0x5000,0x7FFF,M215ExWrite); +} + +void Mapper215_Init(CartInfo *info) +{ + GenMMC3_Init(info, 256, 256, 0, 0); + cwrap=M215CW; + pwrap=M215PW; + info->Power=M215Power; + AddExState(EXPREGS, 3, 0, "EXPR"); + AddExState(&cmdin, 1, 0, "CMDIN"); +} + +// ---------------------------- Mapper 217 ------------------------------ + +static uint8 m217_perm[8] = {0, 6, 3, 7, 5, 2, 4, 1}; + +static void M217CW(uint32 A, uint8 V) +{ + if(EXPREGS[1]&0x08) + setchr1(A,V|((EXPREGS[1]&3)<<8)); + else + setchr1(A,(V&0x7F)|((EXPREGS[1]&3)<<8)|((EXPREGS[1]&0x10)<<3)); +} + +static void M217PW(uint32 A, uint8 V) +{ + if(EXPREGS[0]&0x80) + { + setprg16(0x8000,(EXPREGS[0]&0x0F)|((EXPREGS[1]&3)<<4)); + setprg16(0xC000,(EXPREGS[0]&0x0F)|((EXPREGS[1]&3)<<4)); + } + else if(EXPREGS[1]&0x08) + setprg8(A,(V&0x1F)|((EXPREGS[1]&3)<<5)); + else + setprg8(A,(V&0x0F)|((EXPREGS[1]&3)<<5)|(EXPREGS[1]&0x10)); +} + +static DECLFW(M217Write) +{ + if(!EXPREGS[2]) + { + if(A >= 0xc000) + MMC3_IRQWrite(A, V); + else + MMC3_CMDWrite(A,V); + } + else switch(A&0xE001) + { + case 0x8000: IRQCount=V; break; + case 0xE000: X6502_IRQEnd(FCEU_IQEXT);IRQa=0; break; + case 0xC001: IRQa=1; break; + case 0xA001: setmirror((V&1)^1); break; + case 0x8001: MMC3_CMDWrite(0x8000,(V&0xC0)|(m217_perm[V&7])); cmdin=1; break; + case 0xA000: if(!cmdin) break; + MMC3_CMDWrite(0x8001,V); + cmdin=0; + break; + } +} + +static DECLFW(M217ExWrite) +{ + switch(A) + { + case 0x5000: + EXPREGS[0]=V; + FixMMC3PRG(MMC3_cmd); + break; + case 0x5001: + EXPREGS[1]=V; + FixMMC3PRG(MMC3_cmd); + break; + case 0x5007: + EXPREGS[2]=V; + break; + } +} + +static void M217Power(void) +{ + EXPREGS[0]=0; + EXPREGS[1]=0xFF; + EXPREGS[2]=3; + GenMMC3Power(); + SetWriteHandler(0x8000,0xFFFF,M217Write); + SetWriteHandler(0x5000,0x7FFF,M217ExWrite); +} + +void Mapper217_Init(CartInfo *info) +{ + GenMMC3_Init(info, 256, 256, 0, 0); + cwrap=M217CW; + pwrap=M217PW; + info->Power=M217Power; + AddExState(EXPREGS, 3, 0, "EXPR"); + AddExState(&cmdin, 1, 0, "CMDIN"); +} + +// ---------------------------- Mapper 245 ------------------------------ + +static void M245CW(uint32 A, uint8 V) +{ + setchr1(A,V&7); + EXPREGS[0]=V; + FixMMC3PRG(MMC3_cmd); +} + +static void M245PW(uint32 A, uint8 V) +{ + setprg8(A,(V&0x3F)|((EXPREGS[0]&2)<<5)); +} + +static void M245Power(void) +{ + EXPREGS[0]=0; + GenMMC3Power(); +} + +void Mapper245_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 8, info->battery); + cwrap=M245CW; + pwrap=M245PW; + info->Power=M245Power; + AddExState(EXPREGS, 1, 0, "EXPR"); +} + +// ---------------------------- Mapper 249 ------------------------------ + +static void M249PW(uint32 A, uint8 V) +{ + if(EXPREGS[0]&0x2) + { + if(V<0x20) + V=(V&1)|((V>>3)&2)|((V>>1)&4)|((V<<2)&8)|((V<<2)&0x10); + else + { + V-=0x20; + V=(V&3)|((V>>1)&4)|((V>>4)&8)|((V>>2)&0x10)|((V<<3)&0x20)|((V<<2)&0xC0); + } + } + setprg8(A,V); +} + +static void M249CW(uint32 A, uint8 V) +{ + if(EXPREGS[0]&0x2) + V=(V&3)|((V>>1)&4)|((V>>4)&8)|((V>>2)&0x10)|((V<<3)&0x20)|((V<<2)&0xC0); + setchr1(A,V); +} + +static DECLFW(M249Write) +{ + EXPREGS[0]=V; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void M249Power(void) +{ + EXPREGS[0]=0; + GenMMC3Power(); + SetWriteHandler(0x5000,0x5000,M249Write); +} + +void Mapper249_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 8, info->battery); + cwrap=M249CW; + pwrap=M249PW; + info->Power=M249Power; + AddExState(EXPREGS, 1, 0, "EXPR"); +} + +// ---------------------------- Mapper 250 ------------------------------ + +static DECLFW(M250Write) +{ + MMC3_CMDWrite((A&0xE000)|((A&0x400)>>10),A&0xFF); +} + +static DECLFW(M250IRQWrite) +{ + MMC3_IRQWrite((A&0xE000)|((A&0x400)>>10),A&0xFF); +} + +static void M250_Power(void) +{ + GenMMC3Power(); + SetWriteHandler(0x8000,0xBFFF,M250Write); + SetWriteHandler(0xC000,0xFFFF,M250IRQWrite); +} + +void Mapper250_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 8, info->battery); + info->Power=M250_Power; +} + +// ---------------------------- Mapper 254 ------------------------------ + +static DECLFR(MR254WRAM) +{ + if(EXPREGS[0]) + return WRAM[A-0x6000]; + else + return WRAM[A-0x6000]^EXPREGS[1]; +} + +static DECLFW(M254Write) +{ + switch (A) { + case 0x8000: EXPREGS[0]=0xff; + break; + case 0xA001: EXPREGS[1]=V; + } + MMC3_CMDWrite(A,V); +} + +static void M254_Power(void) +{ + GenMMC3Power(); + SetWriteHandler(0x8000,0xBFFF,M254Write); + SetReadHandler(0x6000,0x7FFF,MR254WRAM); +} + +void Mapper254_Init(CartInfo *info) +{ + GenMMC3_Init(info, 128, 128, 8, info->battery); + info->Power=M254_Power; + AddExState(EXPREGS, 2, 0, "EXPR"); +} + +// ---------------------------- UNIF Boards ----------------------------- + +void TEROM_Init(CartInfo *info) +{ + GenMMC3_Init(info, 32, 32, 0, 0); +} + +void TFROM_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 64, 0, 0); +} + +void TGROM_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 0, 0, 0); +} + +void TKROM_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 8, info->battery); +} + +void TLROM_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 0, 0); +} + +void TSROM_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 8, 0); +} + +void TLSROM_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 8, 0); + cwrap=TKSWRAP; + mwrap=GENNOMWRAP; + PPU_hook=TKSPPU; + AddExState(&PPUCHRBus, 1, 0, "PPUC"); +} + +void TKSROM_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 256, 8, info->battery); + cwrap=TKSWRAP; + mwrap=GENNOMWRAP; + PPU_hook=TKSPPU; + AddExState(&PPUCHRBus, 1, 0, "PPUC"); +} + +void TQROM_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 64, 0, 0); + cwrap=TQWRAP; + CHRRAMSize=8192; + CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); +} + +void HKROM_Init(CartInfo *info) +{ + GenMMC3_Init(info, 512, 512, 1, info->battery); +} diff --git a/boards/mmc3.h b/boards/mmc3.h new file mode 100644 index 0000000..e2c7149 --- /dev/null +++ b/boards/mmc3.h @@ -0,0 +1,22 @@ +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 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); diff --git a/boards/mmc5.c b/boards/mmc5.c new file mode 100644 index 0000000..d14ca0e --- /dev/null +++ b/boards/mmc5.c @@ -0,0 +1,839 @@ +/* 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;x8KB 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<>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<>4]+=MMC5Sound.raw<<1; +} + +#if 0 +static void Do5PCMHQ() +{ + int32 V; + if(!(MMC5Sound.rawcontrol&0x40) && MMC5Sound.raw) + for(V=MMC5Sound.BC[2];V>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>4]+=amp; + vc-=nesincsize; + while(vc<=0) + { + vc+=wl; + dc=(dc+1)&7; + } + } + MMC5Sound.dcount[P]=dc; + MMC5Sound.vcount[P]=vc; + } +} + +#if 0 +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=1) + { + sfun=Do5SQHQ; + psfun=Do5PCMHQ; + } + else +#endif + { + 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=0;//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); +} diff --git a/boards/n106.c b/boards/n106.c new file mode 100644 index 0000000..2872d16 --- /dev/null +++ b/boards/n106.c @@ -0,0 +1,472 @@ +/* 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=0;//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 0 + if(FSettings.soundq>=1) + { + DoNamcoSoundHQ(); + return; + } +#endif + 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); +} + +#if 0 +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>1]+=duff2; + if(!vco) + { + PlayIndex[P]+=freq; + while((PlayIndex[P]>>TOINDEX)>=lengo) PlayIndex[P]-=lengo<=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=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"); +} diff --git a/boards/novel.c b/boards/novel.c index fe3a37c..26e70ec 100644 --- a/boards/novel.c +++ b/boards/novel.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -20,35 +20,36 @@ #include "mapinc.h" +static uint8 latch; + static void DoNovel(void) { - setprg32(0x8000,GameMemBlock[0]&3); - setchr8(GameMemBlock[0]&7); - X6502_Rebase(); + setprg32(0x8000,latch&3); + setchr8(latch&7); } static DECLFW(NovelWrite) { - GameMemBlock[0]=A&0xFF; - DoNovel(); + latch=A&0xFF; + DoNovel(); } static void NovelReset(void) { SetWriteHandler(0x8000,0xFFFF,NovelWrite); - SetReadHandler(0x8000,0xFFFF,CartBR); + SetReadHandler(0x8000,0xFFFF,CartBR); setprg32(0x8000,0); setchr8(0); } static void NovelRestore(int version) { - DoNovel(); + DoNovel(); } -void Novel_Init(void) +void Novel_Init(CartInfo *info) { - AddExState(&GameMemBlock[0], 1, 0,"L1"); - BoardPower=NovelReset; + AddExState(&latch, 1, 0,"L1"); + info->Power=NovelReset; GameStateRestore=NovelRestore; } diff --git a/boards/sachen.c b/boards/sachen.c index a26dd07..bcec3a9 100644 --- a/boards/sachen.c +++ b/boards/sachen.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -22,276 +22,382 @@ static uint8 cmd; static uint8 latch[8]; -#define CHRRAM (GameMemBlock) + +static void MSync(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]); - X6502_Rebase(); - setchr8(latch[1]); - setmirror(latch[2]&1); -// setchr8(6); + setprg32(0x8000,latch[0]); + setchr8(latch[1]|latch[3]|latch[4]); + MSync(latch[2]); } static DECLFW(S74LS374NWrite) { - //printf("$%04x:$%02x\n",A,V); - A&=0x4101; - if(A==0x4100) - cmd=V&7; - else - { - switch(cmd) + A&=0x4101; + if(A==0x4100) + cmd=V&7; + else { - case 0:latch[0]=0;latch[1]=3;break; - case 4:latch[1]&=3;latch[1]|=(V<<2);break; - case 5:latch[0]=V&0x7;break; - case 6:latch[1]&=0x1C;latch[1]|=V&3;break; - case 7:latch[2]=V&1;break; + switch(cmd) + { + case 2:latch[3]=(V&1)<<3;break; + case 4:latch[4]=(V&1)<<2;break; + case 5:latch[0]=V&0x7;break; + case 6:latch[1]=V&3;break; + case 7:latch[2]=V>>1;break; + } + S74LS374NSynco(); } - S74LS374NSynco(); - } } -static void S74LS374NReset(void) +static void S74LS374NPower(void) { - latch[0]=latch[2]=0; - latch[1]=3; - S74LS374NSynco(); - SetReadHandler(0x8000,0xFFFF,CartBR); - SetWriteHandler(0x4100,0x7FFF,S74LS374NWrite); + latch[0]=latch[1]=latch[2]=latch[3]=latch[4]=0; + S74LS374NSynco(); + SetReadHandler(0x8000,0xFFFF,CartBR); + SetWriteHandler(0x4100,0x7FFF,S74LS374NWrite); } static void S74LS374NRestore(int version) { - S74LS374NSynco(); + S74LS374NSynco(); } -void S74LS374N_Init(void) +void S74LS374N_Init(CartInfo *info) { - BoardPower=S74LS374NReset; - GameStateRestore=S74LS374NRestore; - AddExState(latch, 3, 0, "LATC"); - AddExState(&cmd, 1, 0, "CMD"); + info->Power=S74LS374NPower; + GameStateRestore=S74LS374NRestore; + AddExState(latch, 5, 0, "LATC"); + AddExState(&cmd, 1, 0, "CMD"); } -static int type; -static void S8259Synco(void) +static void S74LS374NASynco(void) { - int x; - - setprg32(0x8000,latch[5]&7); - X6502_Rebase(); + setprg32(0x8000,latch[0]); + setchr8(latch[1]); + MSync(latch[2]); +} - if(!UNIFchrrama) // No CHR RAM? Then BS'ing is ok. - { - if(!type) +static DECLFW(S74LS374NAWrite) +{ + A&=0x4101; + if(A==0x4100) + cmd=V&7; + else { - for(x=0;x<4;x++) - setchr2(0x800*x,(x&1)|((latch[x]&7)<<1)|((latch[4]&7)<<4)); + 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; + } + S74LS374NSynco(); } - else +} + +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 int PPUbus; +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++) - setchr2(0x800*x,(latch[x]&0x7)|((latch[4]&7)<<3)); + 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; + } + } } - } - switch((latch[7]>>1)&3) - { - case 0:setmirrorw(0,0,0,1);break; - case 1:setmirror(MI_H);break; - case 2:setmirror(MI_V);break; - case 3:setmirror(MI_0);break; - } + MSync(latch[7]>>1); } static DECLFW(S8259Write) { - A&=0x4101; - if(A==0x4100) cmd=V; - else - { - latch[cmd&7]=V; - S8259Synco(); - } + A&=0x4101; + if(A==0x4100) + cmd=V; + else + { + latch[cmd&7]=V; + S8259Synco(); + } } static void S8259Reset(void) { - int x; - cmd=0; + int x; + cmd=0; - for(x=0;x<8;x++) latch[x]=0; - if(UNIFchrrama) setchr8(0); + for(x=0;x<8;x++) latch[x]=0; + setchr8(0); - S8259Synco(); - SetReadHandler(0x8000,0xFFFF,CartBR); - SetWriteHandler(0x4100,0x7FFF,S8259Write); + S8259Synco(); + SetReadHandler(0x8000,0xFFFF,CartBR); + SetWriteHandler(0x4100,0x7FFF,S8259Write); } static void S8259Restore(int version) { - S8259Synco(); + 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 S8259A_Init(void) +void S8259B_Init(CartInfo *info) // Kevin's Horton 138 mapper { - BoardPower=S8259Reset; - GameStateRestore=S8259Restore; - AddExState(latch, 8, 0, "LATC"); - AddExState(&cmd, 1, 0, "CMD"); - type=0; + info->Power=S8259Reset; + GameStateRestore=S8259Restore; + AddExState(latch, 8, 0, "LATC"); + AddExState(&cmd, 1, 0, "CMD"); + type=1; +} - //if(!CHRsize[0]) - //{ - // SetupCartCHRMapping(0,CHRRAM,8192,1); - // AddExState(CHRRAM, 8192, 0, "CHRR"); - //} +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 S8259B_Init(void) +void S8259D_Init(CartInfo *info) // Kevin's Horton 137 mapper { - BoardPower=S8259Reset; - GameStateRestore=S8259Restore; - AddExState(latch, 8, 0, "LATC"); - AddExState(&cmd, 1, 0, "CMD"); - type=1; + info->Power=S8259Reset; + GameStateRestore=S8259Restore; + AddExState(latch, 8, 0, "LATC"); + AddExState(&cmd, 1, 0, "CMD"); + type=3; } static void(*WSync)(void); static void SA0161MSynco() { - setprg32(0x8000,(latch[0]>>3)&1); - X6502_Rebase(); - setchr8(latch[0]&7); + setprg32(0x8000,(latch[0]>>3)&1); + setchr8(latch[0]&7); } static DECLFW(SAWrite) { - if(A&0x100) - { - latch[0]=V; - WSync(); - } + if(A&0x100) + { + latch[0]=V; + WSync(); + } } static void SAReset(void) { - latch[0]=0; - WSync(); - SetReadHandler(0x8000,0xFFFF,CartBR); - SetWriteHandler(0x4100,0x5FFF,SAWrite); + latch[0]=0; + WSync(); + SetReadHandler(0x8000,0xFFFF,CartBR); + SetWriteHandler(0x4100,0x5FFF,SAWrite); } -void SA0161M_Init(void) +static void SA0161MRestore(int version) { - WSync=SA0161MSynco; - GameStateRestore=SA0161MSynco; - BoardPower=SAReset; - AddExState(&latch[0], 1, 0, "LATC"); + SA0161MSynco(); +} + +void SA0161M_Init(CartInfo *info) +{ + WSync=SA0161MSynco; + GameStateRestore=SA0161MRestore; + info->Power=SAReset; + AddExState(&latch[0], 1, 0, "LATC"); } static void SA72007Synco() { - setprg32(0x8000,0); - X6502_Rebase(); - setchr8(latch[0]>>7); + setprg32(0x8000,0); + setchr8(latch[0]>>7); +} + +static void SA72007Restore(int version) +{ + SA72007Synco(); } -void SA72007_Init(void) +void SA72007_Init(CartInfo *info) { - WSync=SA72007Synco; - GameStateRestore=SA72007Synco; - BoardPower=SAReset; - AddExState(&latch[0], 1, 0, "LATC"); + WSync=SA72007Synco; + GameStateRestore=SA72007Restore; + info->Power=SAReset; + AddExState(&latch[0], 1, 0, "LATC"); } static void SA72008Synco() { - setprg32(0x8000,(latch[0]>>2)&1); - X6502_Rebase(); - setchr8(latch[0]&3); + setprg32(0x8000,(latch[0]>>2)&1); + setchr8(latch[0]&3); } -void SA72008_Init(void) +static void SA72008Restore(int version) { - WSync=SA72008Synco; - GameStateRestore=SA72008Synco; - BoardPower=SAReset; - AddExState(&latch[0], 1, 0, "LATC"); + SA72008Synco(); +} + +void SA72008_Init(CartInfo *info) +{ + WSync=SA72008Synco; + GameStateRestore=SA72008Restore; + info->Power=SAReset; + AddExState(&latch[0], 1, 0, "LATC"); } static DECLFW(SADWrite) { - latch[0]=V; - WSync(); + latch[0]=V; + WSync(); } static void SADReset(void) { - latch[0]=0; - WSync(); - SetReadHandler(0x8000,0xFFFF,CartBR); - SetWriteHandler(0x8000,0xFFFF,SADWrite); + latch[0]=0; + WSync(); + SetReadHandler(0x8000,0xFFFF,CartBR); + SetWriteHandler(0x8000,0xFFFF,SADWrite); } -static void SA0036Synco() +static void SA0037Synco() { - setprg32(0x8000,0); - X6502_Rebase(); - setchr8(latch[0]>>7); + setprg32(0x8000,(latch[0]>>3)&1); + setchr8(latch[0]&7); } -static void SA0037Synco() +static void SA0037Restore(int version) { - setprg32(0x8000,(latch[0]>>3)&1); - X6502_Rebase(); - setchr8(latch[0]&7); + SA0037Synco(); } -void SA0036_Init(void) +void SA0036_Init(CartInfo *info) { - WSync=SA0036Synco; - GameStateRestore=SA0036Synco; - BoardPower=SADReset; - AddExState(&latch[0], 1, 0, "LATC"); + WSync=SA72007Synco; + GameStateRestore=SA72007Restore; + info->Power=SADReset; + AddExState(&latch[0], 1, 0, "LATC"); } -void SA0037_Init(void) +void SA0037_Init(CartInfo *info) { - WSync=SA0037Synco; - GameStateRestore=SA0037Synco; - BoardPower=SADReset; - AddExState(&latch[0], 1, 0, "LATC"); + WSync=SA0037Synco; + GameStateRestore=SA0037Restore; + info->Power=SADReset; + AddExState(&latch[0], 1, 0, "LATC"); } static void TCU01Synco() { - setprg32(0x8000,(latch[0]>>2)&1); - X6502_Rebase(); - setchr8((latch[0]>>3)&0xF); + setprg32(0x8000,(latch[0]>>2)&1); + setchr8((latch[0]>>3)&0xF); } static DECLFW(TCWrite) { - if((A&0x103)==0x102) - latch[0]=V; - TCU01Synco(); + if((A&0x103)==0x102) + latch[0]=V; + TCU01Synco(); } static void TCU01Reset(void) { - latch[0]=0; - SetReadHandler(0x8000,0xFFFF,CartBR); - SetWriteHandler(0x4100,0xFFFF,TCWrite); - TCU01Synco(); + latch[0]=0; + SetReadHandler(0x8000,0xFFFF,CartBR); + SetWriteHandler(0x4100,0xFFFF,TCWrite); + TCU01Synco(); } -void TCU01_Init(void) +static void TCU01Restore(int version) { - GameStateRestore=TCU01Synco; - BoardPower=TCU01Reset; - AddExState(&latch[0], 1, 0, "LATC"); + 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; +} diff --git a/boards/simple.c b/boards/simple.c deleted file mode 100644 index 5629a5f..0000000 --- a/boards/simple.c +++ /dev/null @@ -1,164 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell - * - * 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 CHRRAM (GameMemBlock) -static uint8 latche; - -DECLFW(CPROMWrite) -{ - latche=V&3; - setvram4(0x1000,CHRRAM+((V&3)<<12)); -} - -static void CPROMReset(void) -{ - setprg32(0x8000,0); - setvram8(0); - SetReadHandler(0x8000,0xFFFF,CartBR); - SetWriteHandler(0x8000,0xffff,CPROMWrite); -} - -static void CPROMRestore(int version) -{ - setvram4(0x1000,CHRRAM+((latche)<<12)); -} - -void CPROM_Init(void) -{ - BoardPower=CPROMReset; - GameStateRestore=CPROMRestore; - AddExState(&latche, 1, 0, "LATC"); -} - -DECLFW(CNROMWrite) -{ - latche=V&3; - setchr8(V&3); -} - -static void CNROMReset(void) -{ - setprg16(0x8000,0); - setprg16(0xC000,1); - SetReadHandler(0x8000,0xFFFF,CartBR); - SetWriteHandler(0x8000,0xffff,CNROMWrite); -} - -static void CNROMRestore(int version) -{ - setchr8(latche); -} - -void CNROM_Init(void) -{ - BoardPower=CNROMReset; - GameStateRestore=CNROMRestore; - AddExState(&latche, 1, 0, "LATC"); -} - -static void NROM128Reset(void) -{ - setprg16(0x8000,0); - setprg16(0xC000,0); - setchr8(0); - SetReadHandler(0x8000,0xFFFF,CartBR); -} - -static void NROM256Reset(void) -{ - setprg16(0x8000,0); - setprg16(0xC000,1); - setchr8(0); - SetReadHandler(0x8000,0xFFFF,CartBR); -} -void NROM128_Init(void) -{ - BoardPower=NROM128Reset; -} - -void NROM256_Init(void) -{ - BoardPower=NROM256Reset; -} - -static DECLFW(MHROMWrite) -{ - setprg32(0x8000,V>>4); - setchr8(V); - latche=V; - X6502_Rebase(); -} - -static void MHROMReset(void) -{ - setprg32(0x8000,0); - setchr8(0); - latche=0; - SetReadHandler(0x8000,0xFFFF,CartBR); -} - -static void MHROMRestore(int version) -{ - setprg32(0x8000,latche); - setchr8(latche); - SetWriteHandler(0x8000,0xffff,MHROMWrite); -} - -void MHROM_Init(void) -{ - BoardPower=MHROMReset; - AddExState(&latche, 1, 0,"LATC"); - PRGmask32[0]&=1; - CHRmask8[0]&=1; - GameStateRestore=MHROMRestore; -} - -static void UNROMRestore(int version) -{ - setprg16(0x8000,latche); -} - -static DECLFW(UNROMWrite) -{ - setprg16(0x8000,V); - latche=V; - X6502_Rebase(); -} - -static void UNROMReset(void) -{ - setprg16(0x8000,0); - setprg16(0xc000,~0); - setvram8(CHRRAM); - SetWriteHandler(0x8000,0xffff,UNROMWrite); - SetReadHandler(0x8000,0xFFFF,CartBR); - latche=0; -} - -void UNROM_Init(void) -{ - BoardPower=UNROMReset; - PRGmask16[0]&=7; - AddExState(&latche, 1, 0, "LATC"); - AddExState(CHRRAM, 8192, 0, "CHRR"); - GameStateRestore=UNROMRestore; -} diff --git a/boards/subor.c b/boards/subor.c new file mode 100644 index 0000000..31e5b65 --- /dev/null +++ b/boards/subor.c @@ -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); +} diff --git a/boards/super24.c b/boards/super24.c index 7cf0646..4265b5c 100644 --- a/boards/super24.c +++ b/boards/super24.c @@ -1,239 +1,141 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell - * - * 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" -//undef printf - -static int32 IRQCount,IRQLatch; -static uint8 IRQa,resetmode,mbia; -static uint8 sizer,bigbank,bigbank2; - -static uint8 DRegBuf[8],MMC3_cmd; - -static int masko8[8]={63,31,15,1,3,0,0,0}; -//static int masko1[8]={511,255,127,7,7,0,0,0}; - -static void swsetprg8(uint32 A, uint32 V) -{ - V&=masko8[sizer&7]; - V|=(bigbank*2); - setprg8r((V/64)&15,A,V); -} - -static void swsetchr1(uint32 A, uint32 V) -{ - if(sizer&0x20) - setchr1r(0x10,A,V); - else - { -// V&=masko1[sizer&7]; - V|=bigbank2*8; - setchr1r((V/512)&15,A,V); - } -} - -static void swsetchr2(uint32 A, uint32 V) -{ - if(sizer&0x20) - setchr2r(0x10,A,V); - else - { - //V&=masko1[sizer&7]>>1; - V|=bigbank2*4; - setchr2r((V/256)&15,A,V); - } -} - -static void Sup24_hb(void) -{ - if(ScreenON || SpriteON) - { - resetmode=0; - if(IRQCount>=0) - { - IRQCount--; - if(IRQCount<0) - { - if(IRQa) - { - resetmode = 1; - X6502_IRQBegin(FCEU_IQEXT); - } - } - } - } -} - -static DECLFW(Sup24IRQWrite) -{ - switch(A&0xE001) - { - case 0xc000:IRQLatch=V; - if(resetmode==1) - IRQCount=IRQLatch; - break; - case 0xc001:resetmode=1; - IRQCount=IRQLatch; - break; - case 0xE000:IRQa=0;X6502_IRQEnd(FCEU_IQEXT); - if(resetmode==1) - {IRQCount=IRQLatch;} - break; - case 0xE001:IRQa=1; - if(resetmode==1) - {IRQCount=IRQLatch;} - break; - } -} - -static INLINE void FixMMC3PRG(int V) -{ - swsetprg8(0xA000,DRegBuf[7]); - swsetprg8(0xE000,~0); - if(V&0x40) - { - swsetprg8(0xC000,DRegBuf[6]); - swsetprg8(0x8000,~1); - } - else - { - swsetprg8(0x8000,DRegBuf[6]); - swsetprg8(0xC000,~1); - } - X6502_Rebase(); -} - -static INLINE void FixMMC3CHR(int V) -{ - int cbase=(V&0x80)<<5; - swsetchr2((cbase^0x000),DRegBuf[0]>>1); - swsetchr2((cbase^0x800),DRegBuf[1]>>1); - swsetchr1(cbase^0x1000,DRegBuf[2]); - swsetchr1(cbase^0x1400,DRegBuf[3]); - swsetchr1(cbase^0x1800,DRegBuf[4]); - swsetchr1(cbase^0x1c00,DRegBuf[5]); -} - -static DECLFW(Super24hiwrite) -{ - //printf("$%04x:$%02x, %d\n",A,V,scanline); - switch(A&0xE001) - { - case 0x8000: - if((V&0x40) != (MMC3_cmd&0x40)) - FixMMC3PRG(V); - if((V&0x80) != (MMC3_cmd&0x80)) - FixMMC3CHR(V); - MMC3_cmd = V; - break; - - case 0x8001: - { - int cbase=(MMC3_cmd&0x80)<<5; - DRegBuf[MMC3_cmd&0x7]=V; - switch(MMC3_cmd&0x07) - { - case 0: V>>=1;swsetchr2((cbase^0x000),V);break; - case 1: V>>=1;swsetchr2((cbase^0x800),V);break; - case 2: swsetchr1(cbase^0x1000,V); break; - case 3: swsetchr1(cbase^0x1400,V); break; - case 4: swsetchr1(cbase^0x1800,V); break; - case 5: swsetchr1(cbase^0x1C00,V); break; - case 6: if (MMC3_cmd&0x40) swsetprg8(0xC000,V); - else swsetprg8(0x8000,V); - X6502_Rebase(); - break; - case 7: swsetprg8(0xA000,V); - X6502_Rebase(); - break; - } - } - break; - - case 0xA000: - mbia=V; - setmirror((V&1)^1); - break; - } -} - - -DECLFW(Super24Write) -{ - //printf("$%04x:$%02x\n",A,V); - switch(A) - { - case 0x5ff0:sizer=V; - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); - break; - case 0x5FF1: - bigbank=V; - FixMMC3PRG(MMC3_cmd); - break; - case 0x5FF2: - bigbank2=V; - FixMMC3CHR(MMC3_cmd); - break; - } -} - -static void Super24Reset(void) -{ - SetWriteHandler(0x8000,0xBFFF,Super24hiwrite); - SetWriteHandler(0x5000,0x7FFF,Super24Write); - SetWriteHandler(0xC000,0xFFFF,Sup24IRQWrite); - SetReadHandler(0x8000,0xFFFF,CartBR); - GameHBIRQHook=Sup24_hb; - IRQCount=IRQLatch=IRQa=resetmode=0; - sizer=0x24; - bigbank=159; - bigbank2=0; - - MMC3_cmd=0; - DRegBuf[6]=0; - DRegBuf[7]=1; - - FixMMC3PRG(0); - FixMMC3CHR(0); -} - -static void MrRestore(int version) -{ - FixMMC3PRG(MMC3_cmd); - FixMMC3CHR(MMC3_cmd); - setmirror((mbia&1)^1); -} - -void Super24_Init(void) -{ - BoardPower=Super24Reset; - SetupCartCHRMapping(0x10, GameMemBlock, 8192, 1); - GameStateRestore=MrRestore; - - AddExState(GameMemBlock, 8192, 0, "CHRR"); - AddExState(DRegBuf, 8, 0, "DREG"); - AddExState(&IRQCount, 4, 1, "IRQC"); - AddExState(&IRQLatch, 4, 1, "IQL1"); - AddExState(&IRQa, 1, 0, "IRQA"); - AddExState(&sizer, 1, 0, "SIZA"); - AddExState(&bigbank, 1, 0, "BIG1"); - AddExState(&bigbank2, 1, 0, "BIG2"); -} +/* 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 uint8 resetmode; +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 DECLFW(Super24IRQ) +{ + switch(A&0xE001) + { + case 0xc000: IRQLatch=V; + if(resetmode==1) + IRQCount=IRQLatch; + break; + case 0xc001: resetmode=1; + IRQCount=IRQLatch; + break; + case 0xE000: IRQa=0; + X6502_IRQEnd(FCEU_IQEXT); + if(resetmode==1) + IRQCount=IRQLatch; + break; + case 0xE001: IRQa=1; + if(resetmode==1) + IRQCount=IRQLatch; + break; + } +} + +static void Super24HB(void) +{ + resetmode=0; + if(IRQCount!=0) + { + IRQCount--; + if(IRQCount==0) + { + if(IRQa) + { + resetmode=1; + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +static void Super24Power(void) +{ + EXPREGS[0]=0x24; + EXPREGS[1]=159; + EXPREGS[2]=0; + GenMMC3Power(); + SetWriteHandler(0x5000,0x7FFF,Super24Write); + SetWriteHandler(0xC000,0xFFFF,Super24IRQ); + 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) +{ + info->Power=Super24Power; + info->Reset=Super24Reset; + info->Close=Super24Close; + cwrap=Super24CW; + pwrap=Super24PW; + CHRRAM=(uint8*)FCEU_gmalloc(8192); + SetupCartCHRMapping(0x10, CHRRAM, 8192, 1); + GameHBIRQHook=Super24HB; + AddExState(CHRRAM, 8192, 0, "CHRR"); + AddExState(EXPREGS, 3, 0, "BIG2"); +} diff --git a/boards/supervision.c b/boards/supervision.c index cb2890f..953c068 100644 --- a/boards/supervision.c +++ b/boards/supervision.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -20,35 +20,33 @@ #include "mapinc.h" -#define CHRRAM (GameMemBlock+16) +static uint8 cmd0, cmd1; static void DoSuper(void) { - setprg8r((GameMemBlock[0]&0xC)>>2,0x6000,((GameMemBlock[0]&0x3)<<4)|0xF); - if(GameMemBlock[0]&0x10) + setprg8r((cmd0&0xC)>>2,0x6000,((cmd0&0x3)<<4)|0xF); + if(cmd0&0x10) { - setprg16r((GameMemBlock[0]&0xC)>>2,0x8000,((GameMemBlock[0]&0x3)<<3)|(GameMemBlock[1]&7)); - setprg16r((GameMemBlock[0]&0xC)>>2,0xc000,((GameMemBlock[0]&0x3)<<3)|7); + 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(((GameMemBlock[0]&0x20)>>5)^1); - X6502_Rebase(); + setmirror(((cmd0&0x20)>>5)^1); } static DECLFW(SuperWrite) { - if(!(GameMemBlock[0]&0x10)) + if(!(cmd0&0x10)) { - GameMemBlock[0]=V; + cmd0=V; DoSuper(); } } static DECLFW(SuperHi) { - GameMemBlock[1]=V; + cmd1=V; DoSuper(); } @@ -56,10 +54,10 @@ static void SuperReset(void) { SetWriteHandler(0x6000,0x7FFF,SuperWrite); SetWriteHandler(0x8000,0xFFFF,SuperHi); - SetReadHandler(0x6000,0xFFFF,CartBR); - GameMemBlock[0]=GameMemBlock[1]=0; + SetReadHandler(0x6000,0xFFFF,CartBR); + cmd0=cmd1=0; setprg32r(4,0x8000,0); - setvram8(CHRRAM); + setchr8(0); } static void SuperRestore(int version) @@ -67,11 +65,10 @@ static void SuperRestore(int version) DoSuper(); } -void Supervision16_Init(void) +void Supervision16_Init(CartInfo *info) { - AddExState(&GameMemBlock[0], 1, 0,"L1"); - AddExState(&GameMemBlock[1], 1, 0,"L2"); - AddExState(CHRRAM, 8192, 0, "CHRR"); - BoardPower=SuperReset; + AddExState(&cmd0, 1, 0,"L1"); + AddExState(&cmd1, 1, 0,"L2"); + info->Power=SuperReset; GameStateRestore=SuperRestore; } diff --git a/boards/tengen.c b/boards/tengen.c new file mode 100644 index 0000000..84f050a --- /dev/null +++ b/boards/tengen.c @@ -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(); +} diff --git a/cart.c b/cart.c index 6a32021..f888397 100644 --- a/cart.c +++ b/cart.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -20,16 +20,22 @@ #include #include -#include /* For GG loading code. */ +#include #include "types.h" -#include "version.h" #include "fce.h" +#include "ppu.h" + #include "cart.h" #include "memory.h" +#include "x6502.h" #include "general.h" + #include "svga.h" +#include "file.h" + +#define FCEUPPU_LineUpdate(...) /* This file contains all code for coordinating the mapping in of the @@ -43,8 +49,9 @@ uint8 *VPageG[8]; uint8 *MMC5SPRVPage[8]; uint8 *MMC5BGVPage[8]; -/* 16 are (sort of) reserved for UNIF/iNES and 16 to map other stuff. */ +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]; @@ -74,29 +81,39 @@ uint8 geniech[3]; uint32 genieaddr[3]; -static INLINE void setpageptr(int s, uint32 A, uint8 *p) +static INLINE void setpageptr(int s, uint32 A, uint8 *p, int ram) { uint32 AB=A>>11; int x; - for(x=(s>>1)-1;x>=0;x--) - Page[AB+x]=p-A; + 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 char nothing[8192]; +static uint8 nothing[8192]; void ResetCartMapping(void) { int x; for(x=0;x<32;x++) { - Page[x]=(uint8 *)(nothing-x*2048); + 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]=(uint8 *)(nothing-0x400*x); + MMC5SPRVPage[x]=MMC5BGVPage[x]=VPageR[x]=nothing-0x400*x; } } @@ -133,12 +150,23 @@ DECLFR(CartBR) return Page[A>>11][A]; } -void FASTAPASS(3) GINLINE setprg2r(int r, unsigned int A, unsigned int V) +DECLFW(CartBW) { - if(!PRGptr[r]) return; - V&=PRGmask2[r]; + //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]; +} - setpageptr(2,A,(&PRGptr[r][V<<11])); +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) @@ -146,11 +174,10 @@ void FASTAPASS(2) setprg2(uint32 A, uint32 V) setprg2r(0,A,V); } -void FASTAPASS(3) GINLINE setprg4r(int r, unsigned int A, unsigned int V) +void FASTAPASS(3) setprg4r(int r, unsigned int A, unsigned int V) { - if(!PRGptr[r]) return; V&=PRGmask4[r]; - setpageptr(4,A,(&PRGptr[r][V<<12])); + setpageptr(4,A,PRGptr[r]?(&PRGptr[r][V<<12]):0,PRGram[r]); } void FASTAPASS(2) setprg4(uint32 A, uint32 V) @@ -158,21 +185,19 @@ void FASTAPASS(2) setprg4(uint32 A, uint32 V) setprg4r(0,A,V); } -void FASTAPASS(3) GINLINE setprg8r(int r, unsigned int A, unsigned int V) +void FASTAPASS(3) setprg8r(int r, unsigned int A, unsigned int V) { - if(!PRGptr[r]) return; - if(PRGsize[r]>=8192) { V&=PRGmask8[r]; - setpageptr(8,A,(&PRGptr[r][V<<13])); + 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][((VA+x)&PRGmask2[r])<<11])); + setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]); } } @@ -181,14 +206,12 @@ void FASTAPASS(2) setprg8(uint32 A, uint32 V) setprg8r(0,A,V); } -void FASTAPASS(3) GINLINE setprg16r(int r, unsigned int A, unsigned int V) +void FASTAPASS(3) setprg16r(int r, unsigned int A, unsigned int V) { - if(!PRGptr[r]) return; - if(PRGsize[r]>=16384) { V&=PRGmask16[r]; - setpageptr(16,A,(&PRGptr[r][V<<14])); + setpageptr(16,A,PRGptr[r]?(&PRGptr[r][V<<14]):0,PRGram[r]); } else { @@ -196,7 +219,7 @@ void FASTAPASS(3) GINLINE setprg16r(int r, unsigned int A, unsigned int V) int x; for(x=0;x<8;x++) - setpageptr(2,A+(x<<11),(&PRGptr[r][((VA+x)&PRGmask2[r])<<11])); + setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]); } } @@ -205,13 +228,12 @@ void FASTAPASS(2) setprg16(uint32 A, uint32 V) setprg16r(0,A,V); } -void FASTAPASS(3) GINLINE setprg32r(int r,unsigned int A, unsigned int V) +void FASTAPASS(3) setprg32r(int r,unsigned int A, unsigned int V) { - if(!PRGptr[r]) return; if(PRGsize[r]>=32768) { V&=PRGmask32[r]; - setpageptr(32,A,(&PRGptr[r][V<<15])); + setpageptr(32,A,PRGptr[r]?(&PRGptr[r][V<<15]):0,PRGram[r]); } else { @@ -219,7 +241,7 @@ void FASTAPASS(3) GINLINE setprg32r(int r,unsigned int A, unsigned int V) int x; for(x=0;x<16;x++) - setpageptr(2,A+(x<<11),(&PRGptr[r][((VA+x)&PRGmask2[r])<<11])); + setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]); } } @@ -228,9 +250,10 @@ void FASTAPASS(2) setprg32(uint32 A, uint32 V) setprg32r(0,A,V); } -void GINLINE FASTAPASS(3) setchr1r(int r, unsigned int A, unsigned int 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)); @@ -239,9 +262,10 @@ void GINLINE FASTAPASS(3) setchr1r(int r, unsigned int A, unsigned int V) VPageR[(A)>>10]=&CHRptr[r][(V)<<10]-(A); } -void GINLINE FASTAPASS(3) setchr2r(int r, unsigned int A, unsigned int V) +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]) @@ -250,9 +274,10 @@ void GINLINE FASTAPASS(3) setchr2r(int r, unsigned int A, unsigned int V) PPUCHRRAM&=~(3<<(A>>10)); } -void GINLINE FASTAPASS(3) setchr4r(int r, unsigned int A, unsigned int V) +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); @@ -262,11 +287,12 @@ void GINLINE FASTAPASS(3) setchr4r(int r, unsigned int A, unsigned int V) PPUCHRRAM&=~(15<<(A>>10)); } -void GINLINE FASTAPASS(2) setchr8r(int r, unsigned int V) +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]; @@ -291,7 +317,7 @@ void FASTAPASS(2) setchr4(unsigned int A, unsigned int V) setchr4r(0,A,V); } -void FASTAPASS(2) setchr8(unsigned int V) +void FASTAPASS(1) setchr8(unsigned int V) { setchr8r(0,V); } @@ -314,12 +340,14 @@ void FASTAPASS(2) setvram4(uint32 A, uint8 *p) 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)); } @@ -328,6 +356,7 @@ 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)); @@ -337,6 +366,7 @@ 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; @@ -346,6 +376,7 @@ void FASTAPASS(2) setvramb8(uint8 *p, uint32 b) void FASTAPASS(3) setntamem(uint8 *p, int ram, uint32 b) { + FCEUPPU_LineUpdate(); vnapage[b]=p; PPUNTARAM&=~(1<>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; + FixGenieMap(); + else + { + modcon=V^0xFF; + if(V==0x71) + modcon=0; + } + break; } } @@ -505,7 +554,7 @@ static DECLFR(GenieFix1) { uint8 r=GenieBackup[0](A); - if((modcon>>1)&1) // No check + if((modcon>>1)&1) // No check return genieval[0]; else if(r==geniech[0]) return genieval[0]; @@ -517,7 +566,7 @@ static DECLFR(GenieFix2) { uint8 r=GenieBackup[1](A); - if((modcon>>2)&1) // No check + if((modcon>>2)&1) // No check return genieval[1]; else if(r==geniech[1]) return genieval[1]; @@ -529,7 +578,7 @@ static DECLFR(GenieFix3) { uint8 r=GenieBackup[2](A); - if((modcon>>3)&1) // No check + if((modcon>>3)&1) // No check return genieval[2]; else if(r==geniech[2]) return genieval[2]; @@ -549,7 +598,7 @@ void FixGenieMap(void) VPageR=VPage; FlushGenieRW(); - + //printf("Rightyo\n"); for(x=0;x<3;x++) if((modcon>>(4+x))&1) { @@ -588,3 +637,54 @@ void GeniePower(void) } +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); + } +} + + diff --git a/cart.h b/cart.h index 2a91681..140c54e 100644 --- a/cart.h +++ b/cart.h @@ -1,3 +1,32 @@ +#ifndef _CART_H +#define _CART_H + +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); @@ -5,7 +34,9 @@ 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]; @@ -44,7 +75,7 @@ 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(2) setchr8(unsigned int V); +void FASTAPASS(1) setchr8(unsigned int V); void FASTAPASS(2) setvram4(uint32 A, uint8 *p); void FASTAPASS(1) setvram8(uint8 *p); @@ -69,3 +100,7 @@ void GeniePower(void); void OpenGenie(void); void CloseGenie(void); +void FCEU_KillGenie(void); + +#endif // ndef _CART_H + diff --git a/driver.h b/driver.h index cfaf2cf..aa6a2c7 100644 --- a/driver.h +++ b/driver.h @@ -59,18 +59,34 @@ void FCEUI_DisableFourScore(int s); #include "version.h" -#define SI_NONE 0 -#define SI_GAMEPAD 1 -#define SI_ZAPPER 2 -#define SI_POWERPAD 3 -#define SI_ARKANOID 4 - -#define SIFC_NONE 0 -#define SIFC_ARKANOID 1 -#define SIFC_SHADOW 2 +#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_OEKA 5 +#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 */ diff --git a/drivers/gp2x/main.c b/drivers/gp2x/main.c index ad36e01..95ed4bd 100644 --- a/drivers/gp2x/main.c +++ b/drivers/gp2x/main.c @@ -193,7 +193,7 @@ static void DoArgs(int argc, char *argv[]) { static char *cortab[5]={"none","gamepad","zapper","powerpad","arkanoid"}; static int cortabi[5]={SI_NONE,SI_GAMEPAD, - SI_ZAPPER,SI_POWERPAD,SI_ARKANOID}; + SI_ZAPPER,SI_POWERPADA,SI_ARKANOID}; static char *fccortab[5]={"none","arkanoid","shadow","4player","fkb"}; static int fccortabi[5]={SIFC_NONE,SIFC_ARKANOID,SIFC_SHADOW, SIFC_4PLAYER,SIFC_FKB}; diff --git a/fce.c b/fce.c index 53abd93..e36a86c 100644 --- a/fce.c +++ b/fce.c @@ -97,7 +97,7 @@ void (*GameInterface)(int h); void FP_FASTAPASS(1) (*PPU_hook)(uint32 A); void (*GameStateRestore)(int version); -void (*GameHBIRQHook)(void); +void (*GameHBIRQHook)(void), (*GameHBIRQHook2)(void); readfunc ARead[0x10000]; writefunc BWrite[0x10000]; @@ -973,6 +973,8 @@ static void DoHBlank(void) Fixit2(); X6502_Run(85-6-16); } + if(GameHBIRQHook2 && (ScreenON || SpriteON)) + GameHBIRQHook2(); //PPU_hook(0,-1); //fprintf(stderr,"%3d: $%04x\n",scanline,RefreshAddr); scanline++; @@ -1044,7 +1046,7 @@ void ResetGameLoaded(void) if(GameLoaded) CloseGame(); GameStateRestore=0; PPU_hook=0; - GameHBIRQHook=0; + GameHBIRQHook=GameHBIRQHook2=0; GameExpSound.Fill=0; GameExpSound.RChange=0; if(GameExpSound.Kill) @@ -1063,6 +1065,10 @@ void ResetGameLoaded(void) } char lastLoadedGameName [2048]; +int UNIFLoad(const char *name, int fp); +int iNESLoad(const char *name, int fp); +int FDSLoad(const char *name, int fp); +int NSFLoad(int fp); FCEUGI *FCEUI_LoadGame(char *name) { @@ -1255,8 +1261,12 @@ void EmLoop(void) X6502_Run(256); { if(ScreenON || SpriteON) + { if(GameHBIRQHook) GameHBIRQHook(); + if(GameHBIRQHook2) + GameHBIRQHook2(); + } X6502_Run(85-16); diff --git a/fce.h b/fce.h index 8734f4c..04d050a 100644 --- a/fce.h +++ b/fce.h @@ -5,6 +5,8 @@ void asmcpu_unpack(void); void asmcpu_pack(void); #endif +#define fceuindbg 0 + extern int GameLoaded; void ResetGameLoaded(void); @@ -72,7 +74,7 @@ extern writefunc BWrite[0x10000]; extern void (*GameInterface)(int h); extern void FP_FASTAPASS(1) (*PPU_hook)(uint32 A); -extern void (*GameHBIRQHook)(void); +extern void (*GameHBIRQHook)(void), (*GameHBIRQHook2)(void); extern void (*GameStateRestore)(int version); #define GI_RESETM2 1 @@ -83,6 +85,9 @@ extern void (*GameStateRestore)(int version); extern FCEUGI FCEUGameInfo; extern int GameAttributes; +extern uint8 pale; +extern uint8 vsdip; + #endif diff --git a/fds.c b/fds.c index 455acc5..f0640a0 100644 --- a/fds.c +++ b/fds.c @@ -1,709 +1,895 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell - * - * 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 -#include -#include - -#include "types.h" -#include "x6502.h" -#include "version.h" -#include "fce.h" -#include "fds.h" -#include "svga.h" -#include "sound.h" -#include "general.h" -#include "state.h" -#include "file.h" -#include "memory.h" -#include "cart.h" - -/* TODO: Add code to put a delay in between the time a disk is inserted - and the when it can be successfully read/written to. This should - prevent writes to wrong places OR add code to prevent disk ejects - when the virtual motor is on(mmm...virtual motor). -*/ - -static DECLFR(FDSRead4030); -static DECLFR(FDSRead4031); -static DECLFR(FDSRead4032); -static DECLFR(FDSRead4033); -static DECLFW(FDSWrite4020); -static DECLFW(FDSWrite4021); -static DECLFW(FDSWrite4022); -static DECLFW(FDSWrite4023); -static DECLFW(FDSWrite4024); -static DECLFW(FDSWrite4025); -static DECLFW(FDSWaveWrite); -static DECLFR(FDSWaveRead); - -static DECLFR(FDSSRead); -static DECLFW(FDSSWrite); -static DECLFR(FDSBIOSRead); -static DECLFR(FDSRAMRead); -static DECLFW(FDSRAMWrite); -static void FDSInit(void); -static void FDSReset(void); -static void FP_FASTAPASS(1) FDSFix(int a); - -#define FDSRAM GameMemBlock -#define mapbyte1 (GameMemBlock+32768) -#define mapbyte2 (GameMemBlock+32768+8) -#define mapbyte3 (GameMemBlock+32768+16) -#define mapbyte4 (GameMemBlock+32768+24) // 8 bytes -#define CHRRAM (GameMemBlock+32768+32+64) - -#define IRQLatch (*(int32*)(CHRRAM+8192)) -#define IRQCount (*(int32*)(CHRRAM+8192+4)) -#define IRQa (*(CHRRAM+8192+8)) - -static void FDSClose(void); -static uint8 header[16]; -#define writeskip mapbyte2[0] - -static char FDSSaveName[2048]; - -uint8 FDSBIOS[8192]; -uint8 *diskdata[4]={0,0,0,0}; - -#define SideWrite mapbyte2[1] -#define DiskPtr (*(uint32*)(mapbyte2+4)) -#define dsr0 mapbyte2[2] -#define dsr1 mapbyte2[3] - -#define DC_INC 1 - -#define DiskSeekIRQ (*(int32*)(mapbyte3+4)) -#define SelectDisk mapbyte3[0] -#define InDisk mapbyte3[1] - -static void FDSReset(void) -{ - memset(mapbyte1,0,8); - memset(mapbyte2,0,8); - memset(mapbyte3+4,0,4); - memset(mapbyte4,0,8); -} - -void FDSGI(int h) -{ - switch(h) - { - case GI_CLOSE: FDSClose();break; - case GI_POWER: FDSReset();FDSInit();break; - } -} - -static void FDSStateRestore(int version) -{ - setmirror(((mapbyte1[5]&8)>>3)^1); -} - -void FDSSound(); -void FDSSoundReset(void); -void FDSSoundStateAdd(void); -static void RenderSound(void); - -static void FDSInit(void) -{ - dsr0=0; - dsr1=0x41; - setmirror(1); - if(InDisk!=255) - dsr1&=0xFE; - - setprg8r(0,0xe000,0); // BIOS - setprg32r(1,0x6000,0); // 32KB RAM - setchr8(0); // 8KB CHR RAM - - MapIRQHook=FDSFix; - GameStateRestore=FDSStateRestore; - - SetReadHandler(0x4030,0x4030,FDSRead4030); - SetReadHandler(0x4031,0x4031,FDSRead4031); - SetReadHandler(0x4032,0x4032,FDSRead4032); - SetReadHandler(0x4033,0x4033,FDSRead4033); - - SetWriteHandler(0x4020,0x4020,FDSWrite4020); - SetWriteHandler(0x4021,0x4021,FDSWrite4021); - SetWriteHandler(0x4022,0x4022,FDSWrite4022); - SetWriteHandler(0x4023,0x4023,FDSWrite4023); - SetWriteHandler(0x4024,0x4024,FDSWrite4024); - SetWriteHandler(0x4025,0x4025,FDSWrite4025); - - SetWriteHandler(0x6000,0xdfff,FDSRAMWrite); - SetReadHandler(0x6000,0xdfff,FDSRAMRead); - SetReadHandler(0xE000,0xFFFF,FDSBIOSRead); - - IRQCount=IRQLatch=IRQa=0; - - FDSSoundReset(); -} - -void FDSControl(int what) -{ - switch(what) - { - case FDS_IDISK:dsr1&=0xFE; - if(InDisk==255) - { - FCEU_DispMessage("Disk %d Side %s Inserted", - SelectDisk>>1,(SelectDisk&1)?"B":"A"); - InDisk=SelectDisk; - } - else - FCEU_DispMessage("Jamming disks is a BAD IDEA"); - break; - case FDS_EJECT: - if(InDisk!=255) - FCEU_DispMessage("Disk Ejected"); - else - FCEU_DispMessage("Cannot Eject Air"); - dsr1|=1; - InDisk=255; - break; - case FDS_SELECT: - if(InDisk!=255) - { - FCEU_DispMessage("Eject disk before selecting."); - break; - } - SelectDisk=((SelectDisk+1)%header[4])&3; - FCEU_DispMessage("Disk %d Side %s Selected", - SelectDisk>>1,(SelectDisk&1)?"B":"A"); - break; - } -} - -static void FP_FASTAPASS(1) FDSFix(int a) -{ - if(IRQa) - { - IRQCount-=a; - if(IRQCount<=0) - { - IRQa=0; - dsr0|=1; - dsr0&=~2; - IRQCount=0xFFFF; - X6502_IRQBegin(FCEU_IQEXT); - } - } - if(DiskSeekIRQ>0) - { - DiskSeekIRQ-=a; - if(DiskSeekIRQ<=0) - { - if(mapbyte1[5]&0x80) - { - dsr0&=~1; - dsr0|=2; - TriggerIRQ(); - } - } - } -} - -void DiskControl(int which) -{ -if(mapbyte1[5]&1) - { - switch(which) - { - case DC_INC: - if(DiskPtr<64999) DiskPtr++; - //DiskSeekIRQ=160+100; - //DiskSeekIRQ=140; - //DiskSeekIRQ=160; - DiskSeekIRQ=150; - break; - } - } -} -static DECLFR(FDSRead4030) -{ - X6502_IRQEnd(FCEU_IQEXT); - return dsr0; -} - -static DECLFR(FDSRead4031) -{ - static uint8 z=0; - if(InDisk!=255) - { - z=diskdata[InDisk][DiskPtr]; - DiskControl(DC_INC); - } - return z; -} - -static DECLFR(FDSRead4032) -{ - return dsr1; -} - -static DECLFR(FDSRead4033) -{ - return 0x80; // battery -} - -static DECLFW(FDSRAMWrite) -{ - (FDSRAM-0x6000)[A]=V; -} - -static DECLFR(FDSBIOSRead) -{ - return (FDSBIOS-0xE000)[A]; -} - -static DECLFR(FDSRAMRead) -{ - return (FDSRAM-0x6000)[A]; -} - -/* Begin FDS sound */ - -#define FDSClock (1789772.7272727272727272/8) - -typedef struct { - int64 cycles; // Cycles per PCM sample - int64 count; // Cycle counter - int64 envcount; // Envelope cycle counter - uint32 b19shiftreg60; - uint32 b24adder66; - uint32 b24latch68; - uint32 b17latch76; - int32 clockcount; // Counter to divide frequency by 8. - uint8 b8shiftreg88; // Modulation register. - uint8 amplitude[2]; // Current amplitudes. - uint8 mwave[0x20]; // Modulation waveform - uint8 cwave[0x40]; // Game-defined waveform(carrier) - uint8 SPSG[0xB]; -} FDSSOUND; - -static FDSSOUND fdso; - -#define SPSG fdso.SPSG -#define b19shiftreg60 fdso.b19shiftreg60 -#define b24adder66 fdso.b24adder66 -#define b24latch68 fdso.b24latch68 -#define b17latch76 fdso.b17latch76 -#define b8shiftreg88 fdso.b8shiftreg88 -#define clockcount fdso.clockcount -#define amplitude fdso.amplitude - -void FDSSoundStateAdd(void) -{ - AddExState(fdso.cwave,64,0,"WAVE"); - AddExState(fdso.mwave,32,0,"MWAV"); - AddExState(amplitude,2,0,"AMPL"); - AddExState(SPSG,0xB,0,"SPSG"); - - AddExState(&b8shiftreg88,1,0,"B88"); - - AddExState(&clockcount, 4, 1, "CLOC"); - AddExState(&b19shiftreg60,4,1,"B60"); - AddExState(&b24adder66,4,1,"B66"); - AddExState(&b24latch68,4,1,"B68"); - AddExState(&b17latch76,4,1,"B76"); - -} - -static DECLFR(FDSSRead) -{ - switch(A&0xF) - { - case 0x0:return(amplitude[0]|(X.DB&0xC0)); - case 0x2:return(amplitude[1]|(X.DB&0xC0)); - } - return(X.DB); -} - -static DECLFW(FDSSWrite) -{ - if(FSettings.SndRate) - RenderSound(); - A-=0x4080; - switch(A) - { - case 0x0: - case 0x4: - if(!(V&0x80)) - { - // if(V&0x40) amplitude[(A&0xF)>>2]=0; - // else amplitude[(A&0xF)>>2]=0x3F; - } - else - amplitude[(A&0xF)>>2]=V&0x3F; - break; - case 0x7: b17latch76=0;SPSG[0x5]=0;break; - case 0x8: - //printf("%d:$%02x\n",SPSG[0x5],V); - fdso.mwave[SPSG[0x5]&0x1F]=V&0x7; - SPSG[0x5]=(SPSG[0x5]+1)&0x1F; - break; - } - //if(A>=0x7 && A!=0x8 && A<=0xF) - //if(A==0xA || A==0x9) printf("$%04x:$%02x\n",A,V); - SPSG[A]=V; -} - -// $4080 - Fundamental wave amplitude data register 92 -// $4082 - Fundamental wave frequency data register 58 -// $4083 - Same as $4082($4083 is the upper 4 bits). - -// $4084 - Modulation amplitude data register 78 -// $4086 - Modulation frequency data register 72 -// $4087 - Same as $4086($4087 is the upper 4 bits) - - -static void DoEnv() -{ - int x; - - for(x=0;x<2;x++) - if(!(SPSG[x<<2]&0x80) && !(SPSG[0x9+x]&0x80)) - { - static int counto[2]={0,0}; - - if(counto[x]<=0) - { - if(SPSG[x<<2]&0x40) - { - if(amplitude[x]<0x3F) - amplitude[x]++; - } - else - { - if(amplitude[x]>0) - amplitude[x]--; - } - counto[x]=(SPSG[x<<2]&0x3F); - } - else - counto[x]--; - } -} - -static DECLFR(FDSWaveRead) -{ - return(fdso.cwave[A&0x3f]|(X.DB&0xC0)); -} - -static DECLFW(FDSWaveWrite) -{ - if(SPSG[0x9]&0x80) - fdso.cwave[A&0x3f]=V&0x3F; -} - -static INLINE void ClockRise(void) -{ - if(!clockcount) - { - b19shiftreg60=(SPSG[0x2]|((SPSG[0x3]&0xF)<<8)); - b17latch76=(SPSG[0x6]|((SPSG[0x07]&0x3)<<8))+b17latch76; - - if(!(SPSG[0x7]&0x80)) - { - b8shiftreg88=(amplitude[1]*((fdso.mwave[(b17latch76>>11)&0x1F]&7))); - //b8shiftreg88=((fdso.mwave[(b17latch76>>11)&0x1F]&7))|(amplitude[1]<<3); - } - else - { b8shiftreg88=0;} - } - else - { - b19shiftreg60<<=1; - b8shiftreg88>>=1; - } - b24adder66=(b24latch68+b19shiftreg60)&0xFFFFFF; -} - -static INLINE void ClockFall(void) -{ -// if(!(SPSG[0x7]&0x80)) - { - if(!(b8shiftreg88&1)) - b24latch68=b24adder66; - } - clockcount=(clockcount+1)&7; -} - -static INLINE int32 FDSDoSound(void) -{ - fdso.count+=fdso.cycles; - if(fdso.count>=((int64)1<<40)) - { - dogk: - fdso.count-=(int64)1<<40; - ClockRise(); - ClockFall(); - } - if(fdso.count>=32768) goto dogk; - - fdso.envcount-=fdso.cycles; - if(fdso.envcount<=0) - { - // Fix this? - fdso.envcount+=((int64)1<<40)*FDSClock/1024; - DoEnv(); - } - - // Might need to emulate applying the amplitude to the waveform a bit better... - return (fdso.cwave[b24latch68>>18]*amplitude[0]); -} - -static int32 FBC=0; - -static void RenderSound(void) -{ - int32 end, start; - int32 x; - - start=FBC; - end=(SOUNDTS<<16)/soundtsinc; - if(end<=start) - return; - FBC=end; - - if(!(SPSG[0x9]&0x80)) - for(x=start;x>4]+=t>>3; - } -} - -void FDSSound(int c) -{ - RenderSound(); - FBC=c; -} - -static void FDS_ESI(void) -{ - if(FSettings.SndRate) - { - fdso.cycles=((int64)1<<40)*FDSClock; - fdso.cycles/=FSettings.SndRate OVERSAMPLE; - } -// fdso.cycles=(int64)32768*FDSClock/(FSettings.SndRate OVERSAMPLE); - SetReadHandler(0x4040,0x407f,FDSWaveRead); - SetWriteHandler(0x4040,0x407f,FDSWaveWrite); - SetWriteHandler(0x4080,0x408A,FDSSWrite); - SetReadHandler(0x4090,0x4092,FDSSRead); -} - -void FDSSoundReset(void) -{ - memset(&fdso,0,sizeof(fdso)); - FDS_ESI(); - GameExpSound.Fill=FDSSound; - GameExpSound.RChange=FDS_ESI; -} - - -static DECLFW(FDSWrite4020) -{ - X6502_IRQEnd(FCEU_IQEXT); - IRQLatch&=0xFF00; - IRQLatch|=V; - mapbyte1[0]=V; -} -static DECLFW(FDSWrite4021) -{ - X6502_IRQEnd(FCEU_IQEXT); - IRQLatch&=0xFF; - IRQLatch|=V<<8; - mapbyte1[1]=V; -} -static DECLFW(FDSWrite4022) -{ - X6502_IRQEnd(FCEU_IQEXT); - IRQCount=IRQLatch; - IRQa=V&2; - mapbyte1[2]=V; -} -static DECLFW(FDSWrite4023) -{ - mapbyte1[3]=V; -} -static DECLFW(FDSWrite4024) -{ - if(InDisk!=255 && !(mapbyte1[5]&0x4) && mapbyte1[3]&0x1) - { - if(DiskPtr>=0 && DiskPtr<65000) - { - if(writeskip) writeskip--; - else if(DiskPtr>=2) - { - SideWrite|=1<>3)&1)^1); -} -static void FreeFDSMemory(void) -{ - int x; - - for(x=0;x4) header[4]=4; - if(!header[4]) header[4]|=1; - for(x=0;x +#include +#include + +#include "types.h" +#include "x6502.h" +#include "fce.h" +#include "fds.h" +#include "sound.h" +#include "general.h" +#include "state.h" +#include "file.h" +#include "memory.h" +#include "cart.h" +#include "md5.h" +#include "netplay.h" + +#include "svga.h" + +/* TODO: Add code to put a delay in between the time a disk is inserted + and the when it can be successfully read/written to. This should + prevent writes to wrong places OR add code to prevent disk ejects + when the virtual motor is on(mmm...virtual motor). +*/ + +static DECLFR(FDSRead4030); +static DECLFR(FDSRead4031); +static DECLFR(FDSRead4032); +static DECLFR(FDSRead4033); + +static DECLFW(FDSWrite); + +static DECLFW(FDSWaveWrite); +static DECLFR(FDSWaveRead); + +static DECLFR(FDSSRead); +static DECLFW(FDSSWrite); +static DECLFR(FDSBIOSRead); +static DECLFR(FDSRAMRead); +static DECLFW(FDSRAMWrite); +static void FDSInit(void); +static void FP_FASTAPASS(1) FDSFix(int a); + +#define FDSRAM GameMemBlock +#define CHRRAM (GameMemBlock+32768) + +static uint8 FDSRegs[6]; +static int32 IRQLatch,IRQCount; +static uint8 IRQa; +static void FDSClose(void); + +static uint8 FDSBIOS[8192]; + +/* Original disk data backup, to help in creating save states. */ +static uint8 *diskdatao[8]={0,0,0,0,0,0,0,0}; + +static uint8 *diskdata[8]={0,0,0,0,0,0,0,0}; + +static unsigned int TotalSides; +static uint8 DiskWritten=0; /* Set to 1 if disk was written to. */ +static uint8 writeskip; +static uint32 DiskPtr; +static int32 DiskSeekIRQ; +static uint8 SelectDisk,InDisk; + +#define DC_INC 1 + +void FDSGI(int h) +{ + switch(h) + { + case GI_CLOSE: FDSClose();break; + case GI_POWER: FDSInit();break; + } +} + +static void FDSStateRestore(int version) +{ + int x; + + setmirror(((FDSRegs[5]&8)>>3)^1); + + if(version >= 9810) + for(x=0;x>1,(SelectDisk&1)?"B":"A"); + InDisk=SelectDisk; + } + else + { + FCEU_DispMessage("Disk %d Side %s Ejected",SelectDisk>>1,(SelectDisk&1)?"B":"A"); + InDisk=255; + } +} +/* +void FCEU_FDSEject(void) +{ + InDisk=255; +} +*/ +void FCEU_FDSSelect(void) +{ + if(TotalSides==0) + { + FCEU_DispMessage("Not FDS; can't select disk."); + return; + } + if(InDisk!=255) + { + FCEU_DispMessage("Eject disk before selecting."); + return; + } + SelectDisk=((SelectDisk+1)%TotalSides)&3; + FCEU_DispMessage("Disk %d Side %c Selected",SelectDisk>>1,(SelectDisk&1)?'B':'A'); +} + +static void FP_FASTAPASS(1) FDSFix(int a) +{ + if((IRQa&2) && IRQCount) + { + IRQCount-=a; + if(IRQCount<=0) + { + if(!(IRQa&1)) + { + IRQa&=~2; + IRQCount=IRQLatch=0; + } + else + IRQCount=IRQLatch; + //IRQCount=IRQLatch; //0xFFFF; + X6502_IRQBegin(FCEU_IQEXT); + //printf("IRQ: %d\n",timestamp); +// printf("IRQ: %d\n",scanline); + } + } + if(DiskSeekIRQ>0) + { + DiskSeekIRQ-=a; + if(DiskSeekIRQ<=0) + { + if(FDSRegs[5]&0x80) + { + X6502_IRQBegin(FCEU_IQEXT2); + } + } + } +} + +static DECLFR(FDSRead4030) +{ + uint8 ret=0; + + /* Cheap hack. */ + if(X.IRQlow&FCEU_IQEXT) ret|=1; + if(X.IRQlow&FCEU_IQEXT2) ret|=2; + + if(!fceuindbg) + { + X6502_IRQEnd(FCEU_IQEXT); + X6502_IRQEnd(FCEU_IQEXT2); + } + return ret; +} + +static DECLFR(FDSRead4031) +{ + static uint8 z=0; + if(InDisk!=255) + { + z=diskdata[InDisk][DiskPtr]; + if(!fceuindbg) + { + if(DiskPtr<64999) DiskPtr++; + DiskSeekIRQ=150; + X6502_IRQEnd(FCEU_IQEXT2); + } + } + return z; +} +static DECLFR(FDSRead4032) +{ + uint8 ret; + + ret=X.DB&~7; + if(InDisk==255) + ret|=5; + + if(InDisk==255 || !(FDSRegs[5]&1) || (FDSRegs[5]&2)) + ret|=2; + return ret; +} + +static DECLFR(FDSRead4033) +{ + return 0x80; // battery +} + +static DECLFW(FDSRAMWrite) +{ + (FDSRAM-0x6000)[A]=V; +} + +static DECLFR(FDSBIOSRead) +{ + return (FDSBIOS-0xE000)[A]; +} + +static DECLFR(FDSRAMRead) +{ + return (FDSRAM-0x6000)[A]; +} + +/* Begin FDS sound */ + +#define FDSClock (1789772.7272727272727272/2) + +typedef struct { + int64 cycles; // Cycles per PCM sample + int64 count; // Cycle counter + int64 envcount; // Envelope cycle counter + uint32 b19shiftreg60; + uint32 b24adder66; + uint32 b24latch68; + uint32 b17latch76; + int32 clockcount; // Counter to divide frequency by 8. + uint8 b8shiftreg88; // Modulation register. + uint8 amplitude[2]; // Current amplitudes. + uint8 speedo[2]; + uint8 mwcount; + uint8 mwstart; + uint8 mwave[0x20]; // Modulation waveform + uint8 cwave[0x40]; // Game-defined waveform(carrier) + uint8 SPSG[0xB]; +} FDSSOUND; + +static FDSSOUND fdso; + +#define SPSG fdso.SPSG +#define b19shiftreg60 fdso.b19shiftreg60 +#define b24adder66 fdso.b24adder66 +#define b24latch68 fdso.b24latch68 +#define b17latch76 fdso.b17latch76 +#define b8shiftreg88 fdso.b8shiftreg88 +#define clockcount fdso.clockcount +#define amplitude fdso.amplitude +#define speedo fdso.speedo + +void FDSSoundStateAdd(void) +{ + AddExState(fdso.cwave,64,0,"WAVE"); + AddExState(fdso.mwave,32,0,"MWAV"); + AddExState(amplitude,2,0,"AMPL"); + AddExState(SPSG,0xB,0,"SPSG"); + + AddExState(&b8shiftreg88,1,0,"B88"); + + AddExState(&clockcount, 4, 1, "CLOC"); + AddExState(&b19shiftreg60,4,1,"B60"); + AddExState(&b24adder66,4,1,"B66"); + AddExState(&b24latch68,4,1,"B68"); + AddExState(&b17latch76,4,1,"B76"); + +} + +static DECLFR(FDSSRead) +{ + switch(A&0xF) + { + case 0x0:return(amplitude[0]|(X.DB&0xC0)); + case 0x2:return(amplitude[1]|(X.DB&0xC0)); + } + return(X.DB); +} + +static DECLFW(FDSSWrite) +{ + if(FSettings.SndRate) + { +#if 0 + if(FSettings.soundq>=1) + RenderSoundHQ(); + else +#endif + RenderSound(); + } + A-=0x4080; + switch(A) + { + case 0x0: + case 0x4: if(V&0x80) + amplitude[(A&0xF)>>2]=V&0x3F; //)>0x20?0x20:(V&0x3F); + break; + case 0x5://printf("$%04x:$%02x\n",A,V); + break; + case 0x7: b17latch76=0;SPSG[0x5]=0;//printf("$%04x:$%02x\n",A,V); + break; + case 0x8: + b17latch76=0; + // printf("%d:$%02x, $%02x\n",SPSG[0x5],V,b17latch76); + fdso.mwave[SPSG[0x5]&0x1F]=V&0x7; + SPSG[0x5]=(SPSG[0x5]+1)&0x1F; + break; + } + //if(A>=0x7 && A!=0x8 && A<=0xF) + //if(A==0xA || A==0x9) + //printf("$%04x:$%02x\n",A,V); + SPSG[A]=V; +} + +// $4080 - Fundamental wave amplitude data register 92 +// $4082 - Fundamental wave frequency data register 58 +// $4083 - Same as $4082($4083 is the upper 4 bits). + +// $4084 - Modulation amplitude data register 78 +// $4086 - Modulation frequency data register 72 +// $4087 - Same as $4086($4087 is the upper 4 bits) + + +static void DoEnv() +{ + int x; + + for(x=0;x<2;x++) + if(!(SPSG[x<<2]&0x80) && !(SPSG[0x3]&0x40)) + { + static int counto[2]={0,0}; + + if(counto[x]<=0) + { + if(!(SPSG[x<<2]&0x80)) + { + if(SPSG[x<<2]&0x40) + { + if(amplitude[x]<0x3F) + amplitude[x]++; + } + else + { + if(amplitude[x]>0) + amplitude[x]--; + } + } + counto[x]=(SPSG[x<<2]&0x3F); + } + else + counto[x]--; + } +} + +static DECLFR(FDSWaveRead) +{ + return(fdso.cwave[A&0x3f]|(X.DB&0xC0)); +} + +static DECLFW(FDSWaveWrite) +{ + //printf("$%04x:$%02x, %d\n",A,V,SPSG[0x9]&0x80); + if(SPSG[0x9]&0x80) + fdso.cwave[A&0x3f]=V&0x3F; +} + +static int ta; +static INLINE void ClockRise(void) +{ + if(!clockcount) + { + ta++; + + b19shiftreg60=(SPSG[0x2]|((SPSG[0x3]&0xF)<<8)); + b17latch76=(SPSG[0x6]|((SPSG[0x07]&0xF)<<8))+b17latch76; + + if(!(SPSG[0x7]&0x80)) + { + int t=fdso.mwave[(b17latch76>>13)&0x1F]&7; + int t2=amplitude[1]; + int adj = 0; + + if((t&3)) + { + if((t&4)) + adj -= (t2 * ((4 - (t&3) ) )); + else + adj += (t2 * ( (t&3) )); + } + adj *= 2; + if(adj > 0x7F) adj = 0x7F; + if(adj < -0x80) adj = -0x80; + //if(adj) printf("%d ",adj); + b8shiftreg88=0x80 + adj; + } + else + { + b8shiftreg88=0x80; + } + } + else + { + b19shiftreg60<<=1; + b8shiftreg88>>=1; + } +// b24adder66=(b24latch68+b19shiftreg60)&0x3FFFFFF; + b24adder66=(b24latch68+b19shiftreg60)&0x1FFFFFF; +} + +static INLINE void ClockFall(void) +{ + //if(!(SPSG[0x7]&0x80)) + { + if((b8shiftreg88&1)) // || clockcount==7) + b24latch68=b24adder66; + } + clockcount=(clockcount+1)&7; +} + +static INLINE int32 FDSDoSound(void) +{ + fdso.count+=fdso.cycles; + if(fdso.count>=((int64)1<<40)) + { + dogk: + fdso.count-=(int64)1<<40; + ClockRise(); + ClockFall(); + fdso.envcount--; + if(fdso.envcount<=0) + { + fdso.envcount+=SPSG[0xA]*3; + DoEnv(); + } + } + if(fdso.count>=32768) goto dogk; + + // Might need to emulate applying the amplitude to the waveform a bit better... + { + int k=amplitude[0]; + if(k>0x20) k=0x20; + return (fdso.cwave[b24latch68>>19]*k)*4/((SPSG[0x9]&0x3)+2); + } +} + +static int32 FBC=0; + +static void RenderSound(void) +{ + int32 end, start; + int32 x; + + start=FBC; + end=(SOUNDTS<<16)/soundtsinc; + if(end<=start) + return; + FBC=end; + + if(!(SPSG[0x9]&0x80)) + for(x=start;x>1; + t>>=4; + Wave[x>>4]+=t; //(t>>2)-(t>>3); //>>3; + } +} + +#if 0 +static void RenderSoundHQ(void) +{ + int32 x; + + if(!(SPSG[0x9]&0x80)) + for(x=FBC;x>1; + WaveHi[x]+=t; //(t<<2)-(t<<1); + } + FBC=SOUNDTS; +} +#endif + +static void HQSync(int32 ts) +{ + FBC=ts; +} + +void FDSSound(int c) +{ + RenderSound(); + FBC=c; +} + +/* +static DECLFR(FDSBIOSPatch) +{ + if(FDSRegs[5]&0x4) + { + X.X=FDSRead4031(0x4031); + FDSWrite(0x4024,X.A); + X.A=X.X; + return(0x60); + } + else + { + return(0x58); + //puts("Write"); + } +} +*/ + +static void FDS_ESI(void) +{ + if(FSettings.SndRate) + { +#if 0 + if(FSettings.soundq>=1) + { + fdso.cycles=(int64)1<<39; + } + else +#endif + { + fdso.cycles=((int64)1<<40)*FDSClock; + fdso.cycles/=FSettings.SndRate *16; + } + } +// fdso.cycles=(int64)32768*FDSClock/(FSettings.SndRate *16); + SetReadHandler(0x4040,0x407f,FDSWaveRead); + SetWriteHandler(0x4040,0x407f,FDSWaveWrite); + SetWriteHandler(0x4080,0x408A,FDSSWrite); + SetReadHandler(0x4090,0x4092,FDSSRead); + + //SetReadHandler(0xE7A3,0xE7A3,FDSBIOSPatch); +} + +void FDSSoundReset(void) +{ + memset(&fdso,0,sizeof(fdso)); + FDS_ESI(); + GameExpSound.HiSync=HQSync; + GameExpSound.HiFill=0;//RenderSoundHQ; + GameExpSound.Fill=FDSSound; + GameExpSound.RChange=FDS_ESI; +} + +static DECLFW(FDSWrite) +{ + //extern int scanline; + //FCEU_printf("$%04x:$%02x, %d\n",A,V,scanline); + switch(A) + { + case 0x4020: + X6502_IRQEnd(FCEU_IQEXT); + IRQLatch&=0xFF00; + IRQLatch|=V; +// printf("$%04x:$%02x\n",A,V); + break; + case 0x4021: + X6502_IRQEnd(FCEU_IQEXT); + IRQLatch&=0xFF; + IRQLatch|=V<<8; +// printf("$%04x:$%02x\n",A,V); + break; + case 0x4022: + X6502_IRQEnd(FCEU_IQEXT); + IRQCount=IRQLatch; + IRQa=V&3; +// printf("$%04x:$%02x\n",A,V); + break; + case 0x4023:break; + case 0x4024: + if(InDisk!=255 && !(FDSRegs[5]&0x4) && (FDSRegs[3]&0x1)) + { + if(DiskPtr>=0 && DiskPtr<65500) + { + if(writeskip) writeskip--; + else if(DiskPtr>=2) + { + DiskWritten=1; + diskdata[InDisk][DiskPtr-2]=V; + } + } + } + break; + case 0x4025: + X6502_IRQEnd(FCEU_IQEXT2); + if(InDisk!=255) + { + if(!(V&0x40)) + { + if(FDSRegs[5]&0x40 && !(V&0x10)) + { + DiskSeekIRQ=200; + DiskPtr-=2; + } + if(DiskPtr<0) DiskPtr=0; + } + if(!(V&0x4)) writeskip=2; + if(V&2) {DiskPtr=0;DiskSeekIRQ=200;} + if(V&0x40) DiskSeekIRQ=200; + } + setmirror(((V>>3)&1)^1); + break; + } + FDSRegs[A&7]=V; +} + +static void FreeFDSMemory(void) +{ + int x; + + for(x=0;x8) TotalSides=8; + if(TotalSides<1) TotalSides=1; + + for(x=0;x -#include -#include -#ifdef GP2X -#include -#endif - -#include "types.h" -#include "x6502.h" -#include "fce.h" -#define INESPRIV -#include "ines.h" -#include "version.h" -#include "svga.h" -#include "general.h" -#include "state.h" -#include "file.h" -#include "memory.h" -#include "cart.h" -#include "crc32.h" -#include "cheat.h" - -static DECLFR(VSRead); - -static uint8 *trainerpoo=0; -static uint8 *ROM=NULL; -uint8 *VROM=NULL; - - -static uint32 ROM_size; -uint32 VROM_size; - -static void CheckVSUni(void); -static int MMC_init(int type); -void (*MapClose)(void); -void (*MapperReset)(void); - -static int MapperNo; -static int SaveGame=0; - -static iNES_HEADER head; - -/* MapperReset() is called when the NES is reset(with the reset button). - Mapperxxx_init is called when the NES has been powered on. -*/ - -static void iNESGI(int h) -{ - switch(h) - { - case GI_RESETM2: - if(MapperReset) - MapperReset(); - break; - case GI_POWER: - SetReadHandler(0x8000,0xFFFF,CartBR); - MMC_init(MapperNo); - break; - case GI_CLOSE: - { - FILE *sp; - - if(ROM) {free(ROM);ROM=0;} - if(VROM) {free(VROM);VROM=0;} - - if(SaveGame) - { - char *soot; - SaveGame=0; - soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav"); - sp=fopen(soot,"wb"); - if (sp==NULL) - FCEU_PrintError("WRAM file \"%s\" cannot be written to.\n",soot); - else - { - void *ptr; - uint32 amount; - ptr=WRAM; - amount=8192; - - if(MapperNo==1) - { - extern uint8 MMC1WRAMsize; - if(MMC1WRAMsize==2) ptr=WRAM+8192; - } - else if(MapperNo==5) - { - extern uint8 MMC5WRAMsize; - if(MMC5WRAMsize==4) - amount=32768; - } - - fwrite(ptr,1,amount,sp); - fclose(sp); -#ifdef GP2X - sync(); -#endif - } - } - if(MapClose) MapClose(); - if(trainerpoo) {free(trainerpoo);trainerpoo=0;} - } - break; - } -} - -uint32 iNESGameCRC32; - -struct CRCMATCH { - uint32 crc; - char *name; -}; - -static void CheckBad(void) -{ - int x; - #define CRCNT 7 - struct CRCMATCH tab[CRCNT]={ - {0x28d183ac,"Antarctic Adventure"}, - {0x7095ac65,"Akumajo Densetsu"}, - {0x1bd7ed5a,"Gradius 2"}, - {0x81c3aa66,"Crisis Force"}, - {0xfe3088df,"Fire Emblem Gaiden"}, - {0xfa8339a5,"Bucky O'Hare"}, - {0x3c539d78,"Ganbare Goemon 2"}, - }; - for(x=0;x=0 || moo[x].input2>=0 || moo[x].inputfc>=0) - { - if(moo[x].crc32==iNESGameCRC32) - { - FCEUGameInfo.input[0]=moo[x].input1; - FCEUGameInfo.input[1]=moo[x].input2; - FCEUGameInfo.inputfc=moo[x].inputfc; - break; - } - x++; - } -} - -struct CHINF { - uint32 crc32; - int32 mapper; - int32 mirror; -}; - -#define SAVCNT 14 -static void CheckHInfo(void) -{ - /* ROM images that have the battery-backed bit set in the header that really - don't have battery-backed RAM is not that big of a problem, so I'll - treat this differently. - */ - - static uint32 savie[SAVCNT]= - { - 0x7cab2e9b,0x3ee43cda,0xe1383deb, /* Mouryou Senki Madara */ - 0x3b3f88f0,0x2545214c, /* Dragon Warrior PRG 0 and 1 */ - 0x8c5a784e, /* DW 2 */ - 0xa86a5318, /* DW 3 */ - 0x506e259d, /* DW 4 */ - 0xcebd2a31,0xb8b88130, /* Final Fantasy */ - 0x466efdc2, /* FF(J) */ - 0xc9556b36, /* FF1+2*/ - 0xd29db3c7, /* FF2 */ - 0x57e220d0, /* FF3 */ - }; - - static struct CHINF moo[]= - { - {0xc68363f6,180,0}, /* Crazy Climber */ - {0xbe939fce,9,1}, /* Punchout*/ - {0x5e66eaea,13,1}, /* Videomation */ - {0xaf5d7aa2,-1,0}, /* Clu Clu Land */ - - {0xc2730c30,34,0}, /* Deadly Towers */ - {0x932ff06e,34,1}, /* Classic Concentration */ - {0x4c7c1af3,34,1}, /* Caesar's Palace */ - {0x9ea1dc76,2,0}, /* Rainbow Islands */ - - {0x9eefb4b4,4,8}, /* Pachi Slot Adventure 2 */ - {0x5337f73c,4,8}, /* Niji no Silk Road */ - {0x7474ac92,4,8}, /* Kabuki: Quantum Fighter */ - - {0x970bd9c2,1,8}, /* Hanjuku Hero */ - - {0xbb7c5f7a,89,8}, /* Mito Koumon or something similar */ - /* Probably a Namco MMC3-workalike */ - {0xa5e6baf9,4,1|4}, /* Dragon Slayer 4 */ - {0xe40b4973,4,1|4}, /* Metro Cross */ - {0xd97c31b0,4,1|4}, /* Rasaaru Ishii no Childs Quest */ - - {0x84382231,9,0}, /* Punch Out (J) */ - - {0xfcdaca80,0,0}, /* Elevator Action */ - {0xe492d45a,0,0}, /* Zippy Race */ - {0x32fa246f,0,0}, /* Tag Team Pro Wrestling */ - {0x6d65cac6,2,0}, /* Terra Cresta */ - {0x28c11d24,2,1}, /* Sukeban Deka */ - {0x02863604,2,1}, /* Sukeban Deka */ - {0x2bb6a0f8,2,1}, /* Sherlock Holmes */ - {0x55773880,2,1}, /* Gilligan's Island */ - {0x419461d0,2,1}, /* Super Cars */ - {0x6e0eb43e,2,1}, /* Puss n Boots */ - {0xfc3e5c86,2,1}, /* Trojan */ - - {0x291bcd7d,1,8}, /* Pachio Kun 2 */ - {0xf74dfc91,1,-1}, /* Win, Lose, or Draw */ - - {0x59280bec,4,8}, /* Jackie Chan */ - - {0xfe364be5,1,8}, /* Deep Dungeon 4 */ - {0xd8ee7669,1,8}, /* Adventures of Rad Gravity */ - {0xa5e8d2cd,1,8}, /* Breakthru */ - {0xf6fa4453,1,8}, /* Bigfoot */ - {0x37ba3261,1,8}, /* Back to the Future 2 and 3 */ - {0x934db14a,1,-1}, /* All-Pro Basketball */ - {0xe94d5181,1,8}, /* Mirai Senshi - Lios */ - {0x7156cb4d,1,8}, /* Muppet Adventure Carnival thingy */ - {0x5b6ca654,1,8}, /* Barbie rev X*/ - {0x57c12280,1,8}, /* Demon Sword */ - - {0xcf322bb3,3,1}, /* John Elway's Quarterback */ - {0x9bde3267,3,1}, /* Adventures of Dino Riki */ - {0x02cc3973,3,8}, /* Ninja Kid */ - {0xb5d28ea2,3,1}, /* Mystery Quest - mapper 3?*/ - {0xbc065fc3,3,1}, /* Pipe Dream */ - - {0x5b837e8d,1,8}, /* Alien Syndrome */ - {0x283ad224,32,8}, /* Ai Sensei no Oshiete */ - {0x5555fca3,32,8}, /* "" "" */ - {0x243a8735,32,0x10|4}, /* Major League */ - - {0x6bc65d7e,66,1}, /* Youkai Club*/ - {0xc2df0a00,66,1}, /* Bio Senshi Dan(hacked) */ - {0xbde3ae9b,66,1}, /* Doraemon */ - {0xd26efd78,66,1}, /* SMB Duck Hunt */ - {0x811f06d9,66,1}, /* Dragon Power */ - - {0x3293afea,66,1}, /* Mississippi Satsujin Jiken */ - {0xe84274c5,66,1}, /* "" "" */ - - - {0x6e68e31a,16,8}, /* Dragon Ball 3*/ - - {0xba51ac6f,78,2}, - {0x3d1c3137,78,8}, - - {0xbda8f8e4,152,8}, /* Gegege no Kitarou 2 */ - {0x026c5fca,152,8}, /* Saint Seiya Ougon Densetsu */ - {0x0f141525,152,8}, /* Arkanoid 2 (Japanese) */ - {0xb1a94b82,152,8}, /* Pocket Zaurus */ - - {0x3f15d20d,153,8}, /* Famicom Jump 2 */ - - {0xbba58be5,70,-1}, /* Family Trainer - Manhattan Police */ - {0x370ceb65,70,-1}, /* Family Trainer - Meiro Dai Sakusen */ - {0xdd8ed0f7,70,1}, /* Kamen Rider Club */ - - {0x90c773c1,118,-1}, /* Goal! 2 */ - {0xb9b4d9e0,118,-1}, /* NES Play Action Football */ - {0x78b657ac,118,-1}, /* Armadillo */ - {0x37b62d04,118,-1}, /* Ys 3 */ - {0x07d92c31,118,-1}, /* RPG Jinsei Game */ - {0x2705eaeb,234,-1}, /* Maxi 15 */ - {0x404b2e8b,4,2}, /* Rad Racer 2 */ - - {0x1356f6a6,4,8}, /* "Cattou Ninden Teyandee" English tranlation. - Should I have even bothered to do this? */ - {0x50fd4fd6,4,8}, /* "" "" */ - - {0xa912b064,51|0x800,8}, /* 11-in-1 Ball Games(has CHR ROM when it shouldn't) */ - {0,-1,-1} - }; - int tofix=0; - int x=0; - - do - { - if(moo[x].crc32==iNESGameCRC32) - { - if(moo[x].mapper>=0) - { - if(moo[x].mapper&0x800 && VROM_size) - { - VROM_size=0; - free(VROM); - tofix|=8; - } - if(MapperNo!=(moo[x].mapper&0xFF)) - { - tofix|=1; - MapperNo=moo[x].mapper&0xFF; - } - } - if(moo[x].mirror>=0) - { - if(moo[x].mirror==8) - { - if(Mirroring==2) /* Anything but hard-wired(four screen). */ - { - tofix|=2; - Mirroring=0; - } - } - else if(Mirroring!=moo[x].mirror) - { - if(Mirroring!=(moo[x].mirror&~4)) - if((moo[x].mirror&~4)<=2) /* Don't complain if one-screen mirroring - needs to be set(the iNES header can't - hold this information). - */ - tofix|=2; - Mirroring=moo[x].mirror; - } - } - break; - } - x++; - } while(moo[x].mirror>=0 || moo[x].mapper>=0); - - for(x=0;x>4); - MapperNo|=(head.ROM_type2&0xF0); - - Mirroring = (head.ROM_type&1); - if(head.ROM_type&8) Mirroring=2; - - if(!(ROM=(uint8 *)FCEU_malloc(ROM_size<<14))) - return 0; - - if (VROM_size) - if(!(VROM=(uint8 *)FCEU_malloc(VROM_size<<13))) - { - free(ROM); - return 0; - } - - memset(ROM,0xFF,ROM_size<<14); - if(VROM_size) memset(VROM,0xFF,VROM_size<<13); - if(head.ROM_type&4) /* Trainer */ - { - if(!(trainerpoo=FCEU_malloc(512))) - return(0); - FCEU_fread(trainerpoo,512,1,fp); - } - ResetCartMapping(); - SetupCartPRGMapping(0,ROM,ROM_size*0x4000,0); - SetupCartPRGMapping(1,WRAM,8192,1); - - FCEU_fread(ROM,0x4000,head.ROM_size,fp); - - if(VROM_size) - FCEU_fread(VROM,0x2000,head.VROM_size,fp); - - printf("File %s loaded.\n",name); - - iNESGameCRC32=CalcCRC32(0,ROM,ROM_size<<14); - if(VROM_size) - iNESGameCRC32=CalcCRC32(iNESGameCRC32,VROM,VROM_size<<13); - printf("\n PRG ROM: %3d x 16k\n CHR ROM: %3d x 8k\n ROM CRC32: %08x\n Mapper: %d\n Mirroring: %s\n",head.ROM_size,head.VROM_size,iNESGameCRC32,MapperNo,Mirroring==2?"None(Four-screen)":Mirroring?"Vertical":"Horizontal"); - if(head.ROM_type&2) puts(" Battery-backed."); - if(head.ROM_type&4) puts(" Trained."); - puts(""); - - CheckBad(); - SetInput(); - CheckHInfo(); - CheckVSUni(); - //if(MapperNo!=4 && MapperNo!=118 && MapperNo!=119) exit(1); // Testing - - /* Must remain here because above functions might change value of - VROM_size and free(VROM). - */ - if(VROM_size) - SetupCartCHRMapping(0,VROM,VROM_size*0x2000,0); - - if(Mirroring==2) - SetupCartMirroring(4,1,ExtraNTARAM); - else if(Mirroring>=0x10) - SetupCartMirroring(2+(Mirroring&1),1,0); - else - SetupCartMirroring(Mirroring&1,(Mirroring&4)>>2,0); - - if(MapperNo==5) DetectMMC5WRAMSize(); - else if(MapperNo==1) DetectMMC1WRAMSize(); - - if(head.ROM_type&2) - { - char *soot; - - SaveGame=1; - soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav"); - sp=fopen(soot,"rb"); - if(sp!=NULL) - { - void *ptr; - uint32 amount; - - ptr=WRAM; - amount=8192; - if(MapperNo==1) - { - extern uint8 MMC1WRAMsize; - if(MMC1WRAMsize==2) ptr=WRAM+8192; - } - else if(MapperNo==5) - { - extern uint8 MMC5WRAMsize; - if(MMC5WRAMsize==4) - amount=32768; - } - if(fread(ptr,1,amount,sp)==amount) - printf(" WRAM Save File \"%s\" loaded...\n",soot); - fclose(sp); - } - - } - GameInterface=iNESGI; - return 1; -} - -#include "banksw.h" - - -void FASTAPASS(1) onemir(uint8 V) -{ - if(Mirroring==2) return; - if(V>1) - V=1; - Mirroring=0x10|V; - setmirror(MI_0+V); -} - -void FASTAPASS(1) MIRROR_SET2(uint8 V) -{ - if(Mirroring==2) return; - Mirroring=V; - setmirror(V); -} - -void FASTAPASS(1) MIRROR_SET(uint8 V) -{ - if(Mirroring==2) return; - V^=1; - Mirroring=V; - setmirror(V); -} - -static void NONE_init(void) -{ - ROM_BANK16(0x8000,0); - ROM_BANK16(0xC000,~0); - - if(VROM_size) - VROM_BANK8(0); - else - setvram8(CHRRAM); -} - -static uint8 secdata[2][32]= -{ - { - 0xff, 0xbf, 0xb7, 0x97, 0x97, 0x17, 0x57, 0x4f, - 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, 0x94, 0x14, - 0x56, 0x4e, 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, - 0xd4, 0x5c, 0x3e, 0x26, 0x87, 0x83, 0x13, 0x00 - }, - { - 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, - 0x00, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - } -}; - -static uint8 *secptr; - -static void CheckVSUni(void) -{ - FCEUGameInfo.type=GIT_VSUNI; - - /* FCE Ultra doesn't complain when headers for these games are bad. */ - secptr=0; - switch(iNESGameCRC32) - { - default:FCEUGameInfo.type=0;break; - - case 0xffbef374: pale=1;break; /* Castlevania */ - - case 0x98e3c75a: - case 0x7cff0f84: pale=2;break; /* SMB */ - - case 0xef7af338: pale=2;break; /* Ice Climber */ - case 0xabe1a0c2: FCEUGameInfo.input[0]=SI_ZAPPER;break; /*Duck hunt */ - case 0x16aa4e2d: pale=7;FCEUGameInfo.input[0]=SI_ZAPPER;break; /* hoganal ^_^ */ - case 0x2b85420e: pale=3;break; /* Dr Mario */ - - case 0xfb0ddde7: pale=2;break; - case 0xc95321a8: pale=6;break; /* Excitebike */ - case 0xb1c4c508: pale=1;break; /* Golf */ - - case 0x66471efe: break; - case 0xca3e9b1a: pale=7;break; /* Pinball*/ - - case 0xf735d926: pale=7; break; /* Gradius */ - - case 0x2019fe65: - case 0x31678411:MapperNo=68;pale=7;break; /* Platoon */ - - case 0x74f713b4:pale=4;break; /* Goonies */ - case 0x9ae2baa0:pale=5;break; /* Slalom */ - case 0xe45485a5:secptr=secdata[1];vsdip=0x20;MapperNo=4;break; /* RBI Baseball */ - case 0x21a653c7:vsdip=0x20;MapperNo=4;break; /* Super Sky Kid */ - case 0xe9a6f17d:vsdip=0x20;break; /* Tetris */ - - case 0x159ef3c1:break; /* Star Luster */ - case 0x9768e5e0:break; /* Stroke and Match Golf */ - - /* FCE Ultra doesn't have correct palettes for the following games. */ - case 0x0fa322c2:pale=2;break; /* Clu Clu Land */ - - case 0x766c2cac: /* Soccer */ - case 0x01357944: /* Battle City */ - case 0xb2816bf9:break; /* Battle City (Bootleg) */ - - case 0x832cf592:FCEUGameInfo.input[0]=SI_ZAPPER;break; /* Freedom Force */ - case 0x63abf889:break; /* Ladies Golf */ - case 0x8c0c2df5:pale=2;MapperNo=1;Mirroring=1;break; /* Top Gun */ - case 0x52c501d0:vsdip=0x80;MapperNo=4;secptr=secdata[0];break; - /* TKO Boxing */ - } - - if(MapperNo==99) - Mirroring=2; -} - - -static int VSindex; - -static DECLFR(VSRead) -{ - //printf("$%04x, $%04x\n",A,X.PC); - switch(A) - { - default: - case 0x5e00: VSindex=0;return 0xFF; - case 0x5e01: return(secptr[(VSindex++)&0x1F]); - } -} - -static void DoVSHooks(void) -{ - if(secptr) - SetReadHandler(0x5e00,0x5e01,VSRead); -} - -void (*MapInitTab[256])(void)= -{ - 0, - Mapper1_init,Mapper2_init,Mapper3_init,Mapper4_init, - Mapper5_init,Mapper6_init,Mapper7_init,Mapper8_init, - Mapper9_init,Mapper10_init,Mapper11_init,0, - Mapper13_init,0,Mapper15_init,Mapper16_init, - Mapper17_init,Mapper18_init,Mapper19_init,0, - Mapper21_init,Mapper22_init,Mapper23_init,Mapper24_init, - Mapper25_init,Mapper26_init,0,0, - 0,0,0,Mapper32_init, - Mapper33_init,Mapper34_init,0,0, - 0,0,0,Mapper40_init, - Mapper41_init,Mapper42_init,Mapper43_init,Mapper44_init, - Mapper45_init,Mapper46_init,Mapper47_init,Mapper33_init,Mapper49_init,0,Mapper51_init,Mapper52_init, - 0,0,0,0,0,0,0,0, - 0,0,0,Mapper64_init, - Mapper65_init,Mapper66_init,Mapper67_init,Mapper68_init, - Mapper69_init,Mapper70_init,Mapper71_init,Mapper72_init, - Mapper73_init,0,Mapper75_init,Mapper76_init, - Mapper77_init,Mapper78_init,Mapper79_init,Mapper80_init, - 0,Mapper82_init,Mapper83_init,0, - Mapper85_init,Mapper86_init,Mapper87_init,Mapper88_init, - Mapper89_init,Mapper90_init,0,Mapper92_init, - Mapper93_init,Mapper94_init,Mapper95_init,Mapper96_init, - Mapper97_init,0,Mapper99_init,0, - 0,0,0,0,Mapper105_init,0,0,0, - 0,0,0,Mapper112_init,Mapper113_init,0,0,0, - Mapper117_init,Mapper118_init,Mapper119_init,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,Mapper140_init, - 0,0,0,0,0,0,0,0, - 0,0,Mapper151_init,Mapper152_init,Mapper153_init,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,Mapper180_init, - 0,Mapper182_init,0,Mapper184_init,Mapper185_init,0,0,0, - Mapper189_init,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0, - 0,0,0,0,Mapper225_init,Mapper226_init,Mapper227_init,Mapper228_init, - Mapper229_init,0,0,Mapper232_init,0,Mapper234_init,Mapper43_init,0, - 0,0,0,Mapper240_init,0,Mapper242_init,0,0, - Mapper245_init,Mapper246_init,0,Mapper248_init,Mapper249_init,Mapper250_init,0,0,0,0,0 -}; - -static DECLFW(BWRAM) -{ - WRAM[A-0x6000]=V; -} - -static DECLFR(AWRAM) -{ - return WRAM[A-0x6000]; -} - -void (*MapStateRestore)(int version); -void iNESStateRestore(int version) -{ - int x; - - if(!MapperNo) return; - - for(x=0;x<4;x++) - setprg8(0x8000+x*8192,PRGBankList[x]); - - if(VROM_size) - for(x=0;x<8;x++) - setchr1(0x400*x,CHRBankList[x]); - - switch(Mirroring) - { - case 0:setmirror(MI_H);break; - case 1:setmirror(MI_V);break; - case 0x12: - case 0x10:setmirror(MI_0);break; - case 0x13: - case 0x11:setmirror(MI_1);break; - } - if(MapStateRestore) MapStateRestore(version); -} - -static int MMC_init(int type) -{ - int x; - - GameStateRestore=iNESStateRestore; - MapClose=0; - MapperReset=0; - MapStateRestore=0; - - setprg8r(1,0x6000,0); - - SetReadHandler(0x6000,0x7FFF,AWRAM); - SetWriteHandler(0x6000,0x7FFF,BWRAM); - FCEU_CheatAddRAM(8,0x6000,WRAM); - - /* This statement represents atrocious code. I need to rewrite - all of the iNES mapper code... */ - IRQCount=IRQLatch=IRQa=0; - if(head.ROM_type&2) - { - extern uint8 MMC5WRAMsize,MMC1WRAMsize; - if(type==5 && MMC5WRAMsize==4) - memset(GameMemBlock+32768,0,sizeof(GameMemBlock)-32768); - else if(type==1 && MMC1WRAMsize==2) - { - memset(GameMemBlock,0,8192); - memset(GameMemBlock+16384,0,sizeof(GameMemBlock)-16384); - } - else - memset(GameMemBlock+8192,0,sizeof(GameMemBlock)-8192); - } - else - memset(GameMemBlock,0,sizeof(GameMemBlock)); - if(head.ROM_type&4) - memcpy(WRAM+4096,trainerpoo,512); - - NONE_init(); - - if(FCEUGameInfo.type==GIT_VSUNI) - DoVSHooks(); - if(type==5) - { - MMC5HackVROMMask=CHRmask4[0]; - MMC5HackExNTARAMPtr=MapperExRAM+0x6000; - MMC5Hack=1; - MMC5HackVROMPTR=VROM; - MMC5HackCHRMode=0; - } - ResetExState(); - AddExState(WRAM, 8192, 0, "WRAM"); - if(type==19 || type==5 || type==6 || type==69 || type==85) - AddExState(MapperExRAM, 32768, 0, "MEXR"); - if((!VROM_size || type==6 || type==19 || type==119) && - (type!=13 && type!=96)) - AddExState(CHRRAM, 8192, 0, "CHRR"); - if(head.ROM_type&8) - AddExState(ExtraNTARAM, 2048, 0, "EXNR"); - - /* Exclude some mappers whose emulation code handle save state stuff - themselves. */ - if(type && type!=13 && type!=96) - { - AddExState(mapbyte1, 32, 0, "MPBY"); - AddExState(&Mirroring, 1, 0, "MIRR"); - AddExState(&IRQCount, 4, 1, "IRQC"); - AddExState(&IRQLatch, 4, 1, "IQL1"); - AddExState(&IRQa, 1, 0, "IRQA"); - AddExState(PRGBankList, 4, 0, "PBL"); - for(x=0;x<8;x++) - { - char tak[8]; - sprintf(tak,"CBL%d",x); - AddExState(&CHRBankList[x], 2, 1,tak); - } - } - - if(MapInitTab[type]) MapInitTab[type](); - else if(type) - { - FCEU_PrintError("iNES mapper #%d is not supported at all.",type); - } - return 1; -} +/* 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 +#include +#include + +#include "types.h" +#include "x6502.h" +#include "fce.h" +#include "cart.h" +#include "ppu.h" + +#define INESPRIV +#include "ines.h" +#include "unif.h" +#include "general.h" +#include "state.h" +#include "file.h" +#include "memory.h" +#include "crc32.h" +#include "md5.h" +#include "cheat.h" +#include "vsuni.h" + +#include "driver.h" +#include "svga.h" + +extern SFORMAT FCEUVSUNI_STATEINFO[]; + +static uint8 *trainerpoo=0; +static uint8 *ROM=NULL; +//static +uint8 *VROM=NULL; + +static CartInfo iNESCart; + +uint8 iNESMirroring=0; +uint16 iNESCHRBankList[8]={0,0,0,0,0,0,0,0}; +int32 iNESIRQLatch=0,iNESIRQCount=0; +uint8 iNESIRQa=0; + +uint32 ROM_size=0; +uint32 VROM_size=0; + +static void iNESPower(void); +static int NewiNES_Init(int num); + +void (*MapClose)(void); +void (*MapperReset)(void); + +static int MapperNo=0; + +static iNES_HEADER head; + +/* MapperReset() is called when the NES is reset(with the reset button). + Mapperxxx_init is called when the NES has been powered on. +*/ + +static DECLFR(TrainerRead) +{ + return(trainerpoo[A&0x1FF]); +} + +static void iNESGI(int h) +{ + switch(h) + { + case GI_RESETM2: + if(MapperReset) + MapperReset(); + if(iNESCart.Reset) + iNESCart.Reset(); + break; + case GI_POWER: + if(iNESCart.Power) + iNESCart.Power(); + if(trainerpoo) + { + int x; + for(x=0;x<512;x++) + { + //X6502_DMW(0x7000+x,trainerpoo[x]); + //if(X6502_DMR(0x7000+x)!=trainerpoo[x]) + unsigned int A=0x7000+x; + BWrite[A](A,trainerpoo[x]); + if(ARead[A](A)!=trainerpoo[x]) + { + SetReadHandler(0x7000,0x71FF,TrainerRead); + break; + } + } + } + break; + case GI_CLOSE: + { + FCEU_SaveGameSave(&iNESCart); + + if(iNESCart.Close) iNESCart.Close(); + if(ROM) {free(ROM);ROM=0;} + if(VROM) {free(VROM);VROM=0;} + if(MapClose) MapClose(); + if(trainerpoo) {FCEU_gfree(trainerpoo);trainerpoo=0;} + } + break; + } +} + +uint32 iNESGameCRC32=0; + +struct CRCMATCH { + uint32 crc; + char *name; +}; + +struct INPSEL { + uint32 crc32; + int input1; + int input2; + int inputfc; +}; + +/* This is mostly for my personal use. So HA. */ +static void SetInput(void) +{ + static struct INPSEL moo[]= + { + {0x3a1694f9,SI_GAMEPAD,SI_GAMEPAD,SIFC_4PLAYER}, /* Nekketsu Kakutou Densetsu */ + +#if 0 + {0xc3c0811d,SI_GAMEPAD,SI_GAMEPAD,SIFC_OEKAKIDS}, /* The two "Oeka Kids" games */ + {0x9d048ea4,SI_GAMEPAD,SI_GAMEPAD,SIFC_OEKAKIDS}, /* */ + + {0xaf4010ea,SI_GAMEPAD,SI_POWERPADB,-1}, /* World Class Track Meet */ + {0xd74b2719,SI_GAMEPAD,SI_POWERPADB,-1}, /* Super Team Games */ + {0x61d86167,SI_GAMEPAD,SI_POWERPADB,-1}, /* Street Cop */ + {0x6435c095,SI_GAMEPAD,SI_POWERPADB,-1}, /* Short Order/Eggsplode */ + + + {0x47232739,SI_GAMEPAD,SI_GAMEPAD,SIFC_TOPRIDER}, /* Top Rider */ + + {0x48ca0ee1,SI_GAMEPAD,SI_GAMEPAD,SIFC_BWORLD}, /* Barcode World */ + {0x9f8f200a,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Super Mogura Tataki!! - Pokkun Moguraa */ + {0x9044550e,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Rairai Kyonshizu */ + {0x2f128512,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Jogging Race */ + {0x60ad090a,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERA}, /* Athletic World */ + + {0x8a12a7d9,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Totsugeki Fuuun Takeshi Jou */ + {0xea90f3e2,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Running Stadium */ + {0x370ceb65,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Meiro Dai Sakusen */ + // Bad dump? {0x69ffb014,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Fuun Takeshi Jou 2 */ + {0x6cca1c1f,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Dai Undoukai */ + {0x29de87af,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Aerobics Studio */ + {0xbba58be5,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Family Trainer: Manhattan Police */ + {0xea90f3e2,SI_GAMEPAD,SI_GAMEPAD,SIFC_FTRAINERB}, /* Family Trainer: Running Stadium */ + + {0xd9f45be9,SI_GAMEPAD,SI_GAMEPAD,SIFC_QUIZKING}, /* Gimme a Break ... */ + {0x1545bd13,SI_GAMEPAD,SI_GAMEPAD,SIFC_QUIZKING}, /* Gimme a Break ... 2 */ + + {0x7b44fb2a,SI_GAMEPAD,SI_GAMEPAD,SIFC_MAHJONG}, /* Ide Yousuke Meijin no Jissen Mahjong 2 */ + {0x9fae4d46,SI_GAMEPAD,SI_GAMEPAD,SIFC_MAHJONG}, /* Ide Yousuke Meijin no Jissen Mahjong */ + + {0x980be936,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, /* Hyper Olympic */ + {0x21f85681,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, /* Hyper Olympic (Gentei Ban) */ + {0x915a53a7,SI_GAMEPAD,SI_GAMEPAD,SIFC_HYPERSHOT}, /* Hyper Sports */ +#endif + {0xad9c63e2,SI_GAMEPAD,-1,SIFC_SHADOW}, /* Space Shadow */ + + {0x24598791,-1,SI_ZAPPER,0}, /* Duck Hunt */ + {0xff24d794,-1,SI_ZAPPER,0}, /* Hogan's Alley */ + {0xbeb8ab01,-1,SI_ZAPPER,0}, /* Gumshoe */ + {0xde8fd935,-1,SI_ZAPPER,0}, /* To the Earth */ + {0xedc3662b,-1,SI_ZAPPER,0}, /* Operation Wolf */ + {0x2a6559a1,-1,SI_ZAPPER,0}, /* Operation Wolf (J) */ + + {0x23d17f5e,SI_GAMEPAD,SI_ZAPPER,0}, /* The Lone Ranger */ + {0xb8b9aca3,-1,SI_ZAPPER,0}, /* Wild Gunman */ + {0x5112dc21,-1,SI_ZAPPER,0}, /* Wild Gunman */ + {0x4318a2f8,-1,SI_ZAPPER,0}, /* Barker Bill's Trick Shooting */ + {0x5ee6008e,-1,SI_ZAPPER,0}, /* Mechanized Attack */ + {0x3e58a87e,-1,SI_ZAPPER,0}, /* Freedom Force */ + {0x851eb9be,SI_GAMEPAD,SI_ZAPPER,0}, /* Shooting Range */ + {0x74bea652,SI_GAMEPAD,SI_ZAPPER,0}, /* Supergun 3-in-1 */ + {0x32fb0583,-1,SI_ARKANOID,0}, /* Arkanoid(NES) */ + {0xd89e5a67,-1,-1,SIFC_ARKANOID}, /* Arkanoid (J) */ + {0x0f141525,-1,-1,SIFC_ARKANOID}, /* Arkanoid 2(J) */ + + {0x912989dc,-1,-1,SIFC_FKB}, /* Playbox BASIC */ + {0xf7606810,-1,-1,SIFC_FKB}, /* Family BASIC 2.0A */ + {0x895037bc,-1,-1,SIFC_FKB}, /* Family BASIC 2.1a */ + {0xb2530afc,-1,-1,SIFC_FKB}, /* Family BASIC 3.0 */ +#if 0 + {0x82f1fb96,-1,-1,SIFC_SUBORKB}, /* Subor 1.0 Russian */ + {0xabb2f974,-1,-1,SIFC_SUBORKB}, /* Study and Game 32-in-1 */ + {0xd5d6eac4,-1,-1,SIFC_SUBORKB}, /* Edu (As) */ + {0x589b6b0d,-1,-1,SIFC_SUBORKB}, /* SuporV20 */ + {0x5e073a1b,-1,-1,SIFC_SUBORKB}, /* Supor English (Chinese) */ + {0x8b265862,-1,-1,SIFC_SUBORKB}, + {0x41401c6d,-1,-1,SIFC_SUBORKB}, /* SuporV40 */ + {0x41ef9ac4,-1,-1,SIFC_SUBORKB}, + {0x368c19a8,-1,-1,SIFC_SUBORKB}, /* LIKO Study Cartridge */ + {0x543ab532,-1,-1,SIFC_SUBORKB}, /* LIKO Color Lines */ +#endif + {0,-1,-1,-1} + }; + int x=0; + + while(moo[x].input1>=0 || moo[x].input2>=0 || moo[x].inputfc>=0) + { + if(moo[x].crc32==iNESGameCRC32) + { + FCEUGameInfo.input[0]=moo[x].input1; + FCEUGameInfo.input[1]=moo[x].input2; + FCEUGameInfo.inputfc=moo[x].inputfc; + break; + } + x++; + } +} + +#define INESB_INCOMPLETE 1 +#define INESB_CORRUPT 2 +#define INESB_HACKED 4 + +struct BADINF { + uint64 md5partial; + char *name; + uint32 type; +}; + + +static struct BADINF BadROMImages[]= +{ + #include "ines-bad.h" +}; + +void CheckBad(uint64 md5partial) +{ + int x; + + x=0; + //printf("0x%llx\n",md5partial); + while(BadROMImages[x].name) + { + if(BadROMImages[x].md5partial == md5partial) + { + FCEU_PrintError("The copy game you have loaded, \"%s\", is bad, and will not work properly on FCE Ultra.", BadROMImages[x].name); + return; + } + x++; + } + +} + + +struct CHINF { + uint32 crc32; + int32 mapper; + int32 mirror; +}; + +static void CheckHInfo(void) +{ + /* ROM images that have the battery-backed bit set in the header that really + don't have battery-backed RAM is not that big of a problem, so I'll + treat this differently by only listing games that should have battery-backed RAM. + + Lower 64 bits of the MD5 hash. + */ + + static uint64 savie[]= + { + 0x498c10dc463cfe95LL, /* Battle Fleet */ + 0x6917ffcaca2d8466LL, /* Famista '90 */ + + 0xd63dcc68c2b20adcLL, /* Final Fantasy J */ + 0x012df596e2b31174LL, /* Final Fantasy 1+2 */ + 0xf6b359a720549ecdLL, /* Final Fantasy 2 */ + 0x5a30da1d9b4af35dLL, /* Final Fantasy 3 */ + + 0x2ee3417ba8b69706LL, /* Hydlide 3*/ + + 0xebbce5a54cf3ecc0LL, /* Justbreed */ + + 0x6a858da551ba239eLL, /* Kaijuu Monogatari */ + 0xa40666740b7d22feLL, /* Mindseeker */ + + 0x77b811b2760104b9LL, /* Mouryou Senki Madara */ + + 0x11b69122efe86e8cLL, /* RPG Jinsei Game */ + + 0xa70b495314f4d075LL, /* Ys 3 */ + + + 0xc04361e499748382LL, /* AD&D Heroes of the Lance */ + 0xb72ee2337ced5792LL, /* AD&D Hillsfar */ + 0x2b7103b7a27bd72fLL, /* AD&D Pool of Radiance */ + + 0x854d7947a3177f57LL, /* Crystalis */ + + 0xb0bcc02c843c1b79LL, /* DW */ + 0x4a1f5336b86851b6LL, /* DW */ + + 0x2dcf3a98c7937c22LL, /* DW 2 */ + 0x733026b6b72f2470LL, /* Dw 3 */ + 0x98e55e09dfcc7533LL, /* DW 4*/ + 0x8da46db592a1fcf4LL, /* Faria */ + 0x91a6846d3202e3d6LL, /* Final Fantasy */ + 0xedba17a2c4608d20LL, /* "" */ + + 0x94b9484862a26cbaLL, /* Legend of Zelda */ + 0x04a31647de80fdabLL, /* "" */ + + 0x9aa1dc16c05e7de5LL, /* Startropics */ + 0x1b084107d0878bd0LL, /* Startropics 2*/ + + 0x836c0ff4f3e06e45LL, /* Zelda 2 */ + + 0 /* Abandon all hope if the game has 0 in the lower 64-bits of its MD5 hash */ + }; + + static struct CHINF moo[]= + { + #include "ines-correct.h" + }; + int tofix=0; + int x; + uint64 partialmd5=0; + + for(x=0;x<8;x++) + { + partialmd5 |= (uint64)iNESCart.MD5[15-x] << (x*8); + //printf("%16llx\n",partialmd5); + } + CheckBad(partialmd5); + + x=0; + + do + { + if(moo[x].crc32==iNESGameCRC32) + { + if(moo[x].mapper>=0) + { + if(moo[x].mapper&0x800 && VROM_size) + { + VROM_size=0; + free(VROM); + VROM=0; + tofix|=8; + } + if(MapperNo!=(moo[x].mapper&0xFF)) + { + tofix|=1; + MapperNo=moo[x].mapper&0xFF; + } + } + if(moo[x].mirror>=0) + { + if(moo[x].mirror==8) + { + if(Mirroring==2) /* Anything but hard-wired(four screen). */ + { + tofix|=2; + Mirroring=0; + } + } + else if(Mirroring!=moo[x].mirror) + { + if(Mirroring!=(moo[x].mirror&~4)) + if((moo[x].mirror&~4)<=2) /* Don't complain if one-screen mirroring + needs to be set(the iNES header can't + hold this information). + */ + tofix|=2; + Mirroring=moo[x].mirror; + } + } + break; + } + x++; + } while(moo[x].mirror>=0 || moo[x].mapper>=0); + + x=0; + while(savie[x] != 0) + { + if(savie[x] == partialmd5) + { + if(!(head.ROM_type&2)) + { + tofix|=4; + head.ROM_type|=2; + } + } + x++; + } + + /* Games that use these iNES mappers tend to have the four-screen bit set + when it should not be. + */ + if((MapperNo==118 || MapperNo==24 || MapperNo==26) && (Mirroring==2)) + { + Mirroring=0; + tofix|=2; + } + + /* Four-screen mirroring implicitly set. */ + if(MapperNo==99) + Mirroring=2; + + if(tofix) + { + char gigastr[768]; + strcpy(gigastr,"The iNES header contains incorrect information. For now, the information will be corrected in RAM. "); + if(tofix&1) + sprintf(gigastr+strlen(gigastr),"The mapper number should be set to %d. ",MapperNo); + if(tofix&2) + { + char *mstr[3]={"Horizontal","Vertical","Four-screen"}; + sprintf(gigastr+strlen(gigastr),"Mirroring should be set to \"%s\". ",mstr[Mirroring&3]); + } + if(tofix&4) + strcat(gigastr,"The battery-backed bit should be set. "); + if(tofix&8) + strcat(gigastr,"This game should not have any CHR ROM. "); + strcat(gigastr,"\n"); + FCEU_printf("%s",gigastr); + } +} + +typedef struct { + int mapper; + void (*init)(CartInfo *); +} NewMI; + +int iNESLoad(const char *name, int fp) +{ + struct md5_context md5; + + if(FCEU_fread(&head,1,16,fp)!=16) + return 0; + + if(memcmp(&head,"NES\x1a",4)) + return 0; + + memset(&iNESCart,0,sizeof(iNESCart)); + + if(!memcmp((char *)(&head)+0x7,"DiskDude",8)) + { + memset((char *)(&head)+0x7,0,0x9); + } + + if(!memcmp((char *)(&head)+0x7,"demiforce",9)) + { + memset((char *)(&head)+0x7,0,0x9); + } + + if(!memcmp((char *)(&head)+0xA,"Ni03",4)) + { + if(!memcmp((char *)(&head)+0x7,"Dis",3)) + memset((char *)(&head)+0x7,0,0x9); + else + memset((char *)(&head)+0xA,0,0x6); + } + +// int ROM_size=0; + if(!head.ROM_size) + { +// FCEU_PrintError("No PRG ROM!"); +// return(0); + ROM_size=256; + //head.ROM_size++; + } + else + ROM_size=head.ROM_size; + +// ROM_size = head.ROM_size; + VROM_size = head.VROM_size; + ROM_size=uppow2(ROM_size); + + if(VROM_size) + VROM_size=uppow2(VROM_size); + + MapperNo = (head.ROM_type>>4); + MapperNo|=(head.ROM_type2&0xF0); + Mirroring = (head.ROM_type&1); + + if(head.ROM_type&8) Mirroring=2; + + if(!(ROM=(uint8 *)FCEU_malloc(ROM_size<<14))) + return 0; + + if(VROM_size) + if(!(VROM=(uint8 *)FCEU_malloc(VROM_size<<13))) + { + free(ROM); + return 0; + } + + memset(ROM,0xFF,ROM_size<<14); + if(VROM_size) memset(VROM,0xFF,VROM_size<<13); + if(head.ROM_type&4) /* Trainer */ + { + trainerpoo=(uint8 *)FCEU_gmalloc(512); + FCEU_fread(trainerpoo,512,1,fp); + } + + ResetCartMapping(); + ResetExState(0,0); + + SetupCartPRGMapping(0,ROM,ROM_size*0x4000,0); + SetupCartPRGMapping(1,WRAM,8192,1); + + FCEU_fread(ROM,0x4000,head.ROM_size,fp); + + if(VROM_size) + FCEU_fread(VROM,0x2000,head.VROM_size,fp); + + md5_starts(&md5); + md5_update(&md5,ROM,ROM_size<<14); + + iNESGameCRC32=CalcCRC32(0,ROM,ROM_size<<14); + + if(VROM_size) + { + iNESGameCRC32=CalcCRC32(iNESGameCRC32,VROM,VROM_size<<13); + md5_update(&md5,VROM,VROM_size<<13); + } + md5_finish(&md5,iNESCart.MD5); + memcpy(FCEUGameInfo.MD5,iNESCart.MD5,sizeof(iNESCart.MD5)); + + iNESCart.CRC32=iNESGameCRC32; + + FCEU_printf(" PRG ROM: %3d x 16KiB\n CHR ROM: %3d x 8KiB\n ROM CRC32: 0x%08lx\n", + head.ROM_size,head.VROM_size,iNESGameCRC32); + + { + int x; + FCEU_printf(" ROM MD5: 0x"); + for(x=0;x<16;x++) + FCEU_printf("%02x",iNESCart.MD5[x]); + FCEU_printf("\n"); + } + FCEU_printf(" Mapper: %d\n Mirroring: %s\n", MapperNo,Mirroring==2?"None(Four-screen)":Mirroring?"Vertical":"Horizontal"); + if(head.ROM_type&2) FCEU_printf(" Battery-backed.\n"); + if(head.ROM_type&4) FCEU_printf(" Trained.\n"); + + SetInput(); + CheckHInfo(); + { + int x; + uint64 partialmd5=0; + + for(x=0;x<8;x++) + { + partialmd5 |= (uint64)iNESCart.MD5[7-x] << (x*8); + } + + FCEU_VSUniCheck(partialmd5, &MapperNo, &Mirroring); + } + /* Must remain here because above functions might change value of + VROM_size and free(VROM). + */ + if(VROM_size) + SetupCartCHRMapping(0,VROM,VROM_size*0x2000,0); + + if(Mirroring==2) + SetupCartMirroring(4,1,ExtraNTARAM); + else if(Mirroring>=0x10) + SetupCartMirroring(2+(Mirroring&1),1,0); + else + SetupCartMirroring(Mirroring&1,(Mirroring&4)>>2,0); + + iNESCart.battery=(head.ROM_type&2)?1:0; + iNESCart.mirror=Mirroring; + + //if(MapperNo != 18) { + // if(ROM) free(ROM); + // if(VROM) free(VROM); + // ROM=VROM=0; + // return(0); + // } + + if(NewiNES_Init(MapperNo)) + { + + } + else + { + iNESCart.Power=iNESPower; + if(head.ROM_type&2) + { + iNESCart.SaveGame[0]=WRAM; + iNESCart.SaveGameLen[0]=8192; + } + } + FCEU_LoadGameSave(&iNESCart); + + GameInterface=iNESGI; + FCEU_printf("\n"); + + // since apparently the iNES format doesn't store this information, + // guess if the settings should be PAL or NTSC from the ROM name + // TODO: MD5 check against a list of all known PAL games instead? + if(strstr(name,"(E)") || strstr(name,"(e)") + || strstr(name,"(F)") || strstr(name,"(f)") + || strstr(name,"(G)") || strstr(name,"(g)") + || strstr(name,"(I)") || strstr(name,"(i)")) + FCEUI_SetVidSystem(1); + else + FCEUI_SetVidSystem(0); + + return 1; +} + +void FASTAPASS(2) VRAM_BANK1(uint32 A, uint8 V) +{ + V&=7; + PPUCHRRAM|=(1<<(A>>10)); + CHRBankList[(A)>>10]=V; + VPage[(A)>>10]=&CHRRAM[V<<10]-(A); +} + +void FASTAPASS(2) VRAM_BANK4(uint32 A, uint32 V) +{ + V&=1; + PPUCHRRAM|=(0xF<<(A>>10)); + CHRBankList[(A)>>10]=(V<<2); + CHRBankList[((A)>>10)+1]=(V<<2)+1; + CHRBankList[((A)>>10)+2]=(V<<2)+2; + CHRBankList[((A)>>10)+3]=(V<<2)+3; + VPage[(A)>>10]=&CHRRAM[V<<10]-(A); +} +void FASTAPASS(2) VROM_BANK1(uint32 A,uint32 V) +{ + setchr1(A,V); + CHRBankList[(A)>>10]=V; +} + +void FASTAPASS(2) VROM_BANK2(uint32 A,uint32 V) +{ + setchr2(A,V); + CHRBankList[(A)>>10]=(V<<1); + CHRBankList[((A)>>10)+1]=(V<<1)+1; +} + +void FASTAPASS(2) VROM_BANK4(uint32 A, uint32 V) +{ + setchr4(A,V); + CHRBankList[(A)>>10]=(V<<2); + CHRBankList[((A)>>10)+1]=(V<<2)+1; + CHRBankList[((A)>>10)+2]=(V<<2)+2; + CHRBankList[((A)>>10)+3]=(V<<2)+3; +} + +void FASTAPASS(1) VROM_BANK8(uint32 V) +{ + setchr8(V); + CHRBankList[0]=(V<<3); + CHRBankList[1]=(V<<3)+1; + CHRBankList[2]=(V<<3)+2; + CHRBankList[3]=(V<<3)+3; + CHRBankList[4]=(V<<3)+4; + CHRBankList[5]=(V<<3)+5; + CHRBankList[6]=(V<<3)+6; + CHRBankList[7]=(V<<3)+7; +} + +void FASTAPASS(2) ROM_BANK8(uint32 A, uint32 V) +{ + setprg8(A,V); + if(A>=0x8000) + PRGBankList[((A-0x8000)>>13)]=V; +} + +void FASTAPASS(2) ROM_BANK16(uint32 A, uint32 V) +{ + setprg16(A,V); + if(A>=0x8000) + { + PRGBankList[((A-0x8000)>>13)]=V<<1; + PRGBankList[((A-0x8000)>>13)+1]=(V<<1)+1; + } +} + +void FASTAPASS(1) ROM_BANK32(uint32 V) +{ + setprg32(0x8000,V); + PRGBankList[0]=V<<2; + PRGBankList[1]=(V<<2)+1; + PRGBankList[2]=(V<<2)+2; + PRGBankList[3]=(V<<2)+3; +} + +void FASTAPASS(1) onemir(uint8 V) +{ + if(Mirroring==2) return; + if(V>1) + V=1; + Mirroring=0x10|V; + setmirror(MI_0+V); +} + +void FASTAPASS(1) MIRROR_SET2(uint8 V) +{ + if(Mirroring==2) return; + Mirroring=V; + setmirror(V); +} + +void FASTAPASS(1) MIRROR_SET(uint8 V) +{ + if(Mirroring==2) return; + V^=1; + Mirroring=V; + setmirror(V); +} + +static void NONE_init(void) +{ + ROM_BANK16(0x8000,0); + ROM_BANK16(0xC000,~0); + + if(VROM_size) + VROM_BANK8(0); + else + setvram8(CHRRAM); +} + +void (*MapInitTab[256])(void)= +{ + 0,0, +// Mapper2_init,Mapper3_init, + 0,0, + 0,0, + Mapper6_init,Mapper7_init,Mapper8_init,Mapper9_init, + Mapper10_init,Mapper11_init, + 0, +// Mapper13_init, + 0, + 0, + Mapper15_init,Mapper16_init,Mapper17_init,Mapper18_init, + 0,0, + Mapper21_init,Mapper22_init,Mapper23_init,Mapper24_init, + Mapper25_init,Mapper26_init,Mapper27_init, + 0,0,0,0, + Mapper32_init,Mapper33_init,Mapper34_init, + 0,0,0,0,0, + Mapper40_init,Mapper41_init,Mapper42_init,Mapper43_init, + 0,0, + Mapper46_init, + 0, + Mapper48_init, + 0, + Mapper50_init,Mapper51_init, + 0,0,0,0,0, + Mapper57_init,Mapper58_init,Mapper59_init,Mapper60_init, + Mapper61_init,Mapper62_init, + 0, + Mapper64_init,Mapper65_init,Mapper66_init,Mapper67_init, + Mapper68_init,Mapper69_init,Mapper70_init,Mapper71_init, + Mapper72_init,Mapper73_init, + 0, + Mapper75_init,Mapper76_init,Mapper77_init,Mapper78_init, + Mapper79_init,Mapper80_init, + 0, + Mapper82_init,Mapper83_init, + 0, + Mapper85_init,Mapper86_init,Mapper87_init,Mapper88_init, + Mapper89_init, + 0, + Mapper91_init,Mapper92_init,Mapper93_init,Mapper94_init, + 0, + Mapper96_init,Mapper97_init, + 0, + Mapper99_init, + 0,0,0,0,0,0,0, + Mapper107_init, + 0,0,0,0, + 0,Mapper113_init, + 0,0,0, + Mapper117_init, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + Mapper140_init, + 0,0,0, + Mapper144_init, + 0,0,0,0,0,0, + Mapper151_init,Mapper152_init,Mapper153_init,Mapper154_init, + 0, + Mapper156_init,Mapper157_init,Mapper158_init,0, + 0,0,0,0,0,0, + Mapper166_init,Mapper167_init, + 0,0,0,0,0,0,0,0,0,0,0,0, + Mapper180_init, + 0,0,0, + Mapper184_init,Mapper185_init, + 0,0,0, + Mapper189_init, + 0, +// Mapper191_init, + 0, + 0, + Mapper193_init, + 0,0,0,0,0,0, + Mapper200_init,Mapper201_init,Mapper202_init,Mapper203_init, + Mapper204_init, + 0,0, + Mapper207_init, + 0,0,0, + Mapper211_init,Mapper212_init,Mapper213_init,Mapper214_init, + 0,0,0,0,0,0,0,0,0,0, + Mapper225_init,Mapper226_init,Mapper227_init,Mapper228_init, + Mapper229_init,Mapper230_init,Mapper231_init,Mapper232_init, + 0, + Mapper234_init,Mapper235_init, + 0,0,0,0, + Mapper240_init,Mapper241_init,Mapper242_init,0, + Mapper244_init, + 0, + Mapper246_init, + 0,0,0,0,0,0,0,0, + Mapper255_init +}; + +static DECLFW(BWRAM) +{ + WRAM[A-0x6000]=V; +} + +static DECLFR(AWRAM) +{ + return WRAM[A-0x6000]; +} + +#ifdef DEBUG_MAPPER +static DECLFW(WriteHandler) +{ + FCEU_printf("$%04x:$%02x\n",A,V); +} +#endif + +void (*MapStateRestore)(int version); +void iNESStateRestore(int version) +{ + int x; + + if(!MapperNo) return; + + for(x=0;x<4;x++) + setprg8(0x8000+x*8192,PRGBankList[x]); + + if(VROM_size) + for(x=0;x<8;x++) + setchr1(0x400*x,CHRBankList[x]); + +if(0) switch(Mirroring) + { + case 0:setmirror(MI_H);break; + case 1:setmirror(MI_V);break; + case 0x12: + case 0x10:setmirror(MI_0);break; + case 0x13: + case 0x11:setmirror(MI_1);break; + } + if(MapStateRestore) MapStateRestore(version); +} + +static void iNESPower(void) +{ + int x; + int type=MapperNo; + + SetReadHandler(0x8000,0xFFFF,CartBR); + GameStateRestore=iNESStateRestore; + MapClose=0; + MapperReset=0; + MapStateRestore=0; + + setprg8r(1,0x6000,0); + + SetReadHandler(0x6000,0x7FFF,AWRAM); + SetWriteHandler(0x6000,0x7FFF,BWRAM); + FCEU_CheatAddRAM(8,0x6000,WRAM); + + #ifdef DEBUG_MAPPER + if(type==0) SetWriteHandler(0x4020,0xFFFF,WriteHandler); + #endif + + /* This statement represents atrocious code. I need to rewrite + all of the iNES mapper code... */ + IRQCount=IRQLatch=IRQa=0; + if(head.ROM_type&2) + memset(GameMemBlock+8192,0,sizeof(GameMemBlock)-8192); + else + memset(GameMemBlock,0,sizeof(GameMemBlock)); + + NONE_init(); + + ResetExState(0,0); + if(FCEUGameInfo.type == GIT_VSUNI) + AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0); + + AddExState(WRAM, 8192, 0, "WRAM"); + if(type==19 || type==6 || type==69 || type==85 || type==96) + AddExState(MapperExRAM, 32768, 0, "MEXR"); + if((!VROM_size || type==6 || type==19) && (type!=13 && type!=96)) + AddExState(CHRRAM, 8192, 0, "CHRR"); + if(head.ROM_type&8) + AddExState(ExtraNTARAM, 2048, 0, "EXNR"); + + /* Exclude some mappers whose emulation code handle save state stuff + themselves. */ + if(type && type!=13 && type!=96) + { + AddExState(mapbyte1, 32, 0, "MPBY"); + AddExState(&Mirroring, 1, 0, "MIRR"); + AddExState(&IRQCount, 4, 1, "IRQC"); + AddExState(&IRQLatch, 4, 1, "IQL1"); + AddExState(&IRQa, 1, 0, "IRQA"); + AddExState(PRGBankList, 4, 0, "PBL"); + for(x=0;x<8;x++) + { + char tak[8]; + sprintf(tak,"CBL%d",x); + AddExState(&CHRBankList[x], 2, 1,tak); + } + } + + if(MapInitTab[type]) MapInitTab[type](); + else if(type) + { + FCEU_PrintError("iNES mapper #%d is not supported at all.",type); + } +} + + +typedef struct { + int number; + void (*init)(CartInfo *); +} BMAPPING; + +static BMAPPING bmap[] = { + {1, Mapper1_Init}, + {2, UNROM_Init}, + {3, CNROM_Init}, + {4, Mapper4_Init}, + {5, Mapper5_Init}, + {12, Mapper12_Init}, + {13, CPROM_Init}, + {19, Mapper19_Init}, + {44, Mapper44_Init}, + {45, Mapper45_Init}, + {47, Mapper47_Init}, + {49, Mapper49_Init}, + {52, Mapper52_Init}, + {74, Mapper74_Init}, + {90, Mapper90_Init}, + {95, Mapper95_Init}, + {105, Mapper105_Init}, + {112, Mapper112_Init}, + {114, Mapper114_Init}, + {115, Mapper115_Init}, + {116, Mapper116_Init}, + {118, Mapper118_Init}, + {119, Mapper119_Init}, + {133, SA72008_Init}, + {137, S8259D_Init}, + {138, S8259B_Init}, + {139, S8259C_Init}, + {141, S8259A_Init}, + {143, TCA01_Init}, + {145, SA72007_Init}, + {146, SA0161M_Init}, + {147, TCU01_Init}, + {148, SA0037_Init}, + {149, SA0036_Init}, + {150, S74LS374N_Init}, + {155, Mapper155_Init}, + {160, Mapper90_Init}, + {163, Mapper163_Init}, + {164, Mapper164_Init}, + {165, Mapper165_Init}, + {182, Mapper182_Init}, + {183, Mapper183_Init}, + {186, Mapper186_Init}, + {187, Mapper187_Init}, + {188, Mapper188_Init}, + {191, Mapper191_Init}, + {205, Mapper205_Init}, + {206, DEIROM_Init}, + {208, Mapper208_Init}, + {209, Mapper209_Init}, + {210, Mapper210_Init}, + {215, Mapper215_Init}, + {216, Mapper216_Init}, + {217, Mapper217_Init}, + {243, S74LS374NA_Init}, + {245, Mapper245_Init}, + {249, Mapper249_Init}, + {250, Mapper250_Init}, + {254, Mapper254_Init}, + { 0, 0} +}; + +static int NewiNES_Init(int num) +{ + BMAPPING *tmp=bmap; + + if(FCEUGameInfo.type == GIT_VSUNI) + AddExState(FCEUVSUNI_STATEINFO, ~0, 0, 0); + + while(tmp->init) + { + if(num==tmp->number) + { + UNIFchrrama=0; // need here for compatibility with UNIF mapper code + if(!VROM_size) + { + int CHRRAMSize; + if(num==13) + CHRRAMSize=16384; + else + CHRRAMSize=8192; + VROM=(uint8 *)malloc(CHRRAMSize); + UNIFchrrama=VROM; + SetupCartCHRMapping(0,VROM,CHRRAMSize,1); + AddExState(VROM,CHRRAMSize, 0, "CHRR"); + } + if(head.ROM_type&8) + AddExState(ExtraNTARAM, 2048, 0, "EXNR"); + tmp->init(&iNESCart); + return(1); + } + tmp++; + } + return(0); +} diff --git a/ines.h b/ines.h index a27cf74..aaa44ca 100644 --- a/ines.h +++ b/ines.h @@ -1,366 +1,374 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 1998 Bero - * Copyright (C) 2002 Ben Parnell - * - * 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 INESPRIV - -void iNESStateRestore(int version); -extern uint32 iNESGameCRC32; - -extern uint8 *VROM; -extern uint32 VROM_size; - -extern void (*MapStateRestore)(int version); -extern void (*MapClose)(void); -extern void (*MapperReset)(void); - -/* This order is necessary */ -#define WRAM (GameMemBlock) -#define sizeofWRAM 8192 - -#define MapperExRAM (GameMemBlock+sizeofWRAM) -#define sizeofMapperExRAM 32768 -/* for the MMC5 code to work properly. It might be fixed later... */ - - -#define CHRRAM (GameMemBlock+sizeofWRAM+sizeofMapperExRAM) -#define sizeofCHRRAM 8192 - -#define ExtraNTARAM (GameMemBlock+sizeofWRAM+sizeofMapperExRAM+sizeofCHRRAM) -#define sizeofExtraNTARAM 2048 - -#define PRGBankList (ExtraNTARAM+sizeofExtraNTARAM) - -#define mapbyte1 (PRGBankList+4) -#define mapbyte2 (mapbyte1+8) -#define mapbyte3 (mapbyte2+8) -#define mapbyte4 (mapbyte3+8) -uint16 iNESCHRBankList[8]; -int32 iNESIRQLatch,iNESIRQCount; -uint8 iNESMirroring; -uint8 iNESIRQa; - -#define IRQa iNESIRQa -#define Mirroring iNESMirroring -#define IRQCount iNESIRQCount -#define IRQLatch iNESIRQLatch -#define CHRBankList iNESCHRBankList -#else -int iNESLoad(char *name, int fp); -#endif - - typedef struct { - char ID[4]; /*NES^Z*/ - uint8 ROM_size; - uint8 VROM_size; - uint8 ROM_type; - uint8 ROM_type2; - uint8 reserve[8]; - } iNES_HEADER; - -void FASTAPASS(2) VRAM_BANK1(uint32 A, uint8 V); -void FASTAPASS(2) VRAM_BANK4(uint32 A,uint32 V); - -void FASTAPASS(2) VROM_BANK1(uint32 A,uint32 V); -void FASTAPASS(2) VROM_BANK2(uint32 A,uint32 V); -void FASTAPASS(2) VROM_BANK4(uint32 A, uint32 V); -void FASTAPASS(1) VROM_BANK8(uint32 V); -void FASTAPASS(2) ROM_BANK8(uint32 A, uint32 V); -void FASTAPASS(2) ROM_BANK16(uint32 A, uint32 V); -void FASTAPASS(2) ROM_BANK32(uint32 V); - -extern uint8 vmask; -extern uint32 vmask1; -extern uint32 vmask2; -extern uint32 vmask4; -extern uint32 pmask8; -extern uint8 pmask16; -extern uint8 pmask32; - -void FASTAPASS(1) onemir(uint8 V); -void FASTAPASS(1) MIRROR_SET2(uint8 V); -void FASTAPASS(1) MIRROR_SET(uint8 V); - - -void DetectMMC1WRAMSize(void); -void DetectMMC5WRAMSize(void); - -void Mapper0_init(void); -void Mapper1_init(void); -void Mapper2_init(void); -void Mapper3_init(void); -void Mapper4_init(void); -void Mapper5_init(void); -void Mapper6_init(void); -void Mapper7_init(void); -void Mapper8_init(void); -void Mapper9_init(void); -void Mapper10_init(void); -void Mapper11_init(void); -void Mapper12_init(void); -void Mapper13_init(void); -void Mapper14_init(void); -void Mapper15_init(void); -void Mapper16_init(void); -void Mapper17_init(void); -void Mapper18_init(void); -void Mapper19_init(void); -void Mapper20_init(void); -void Mapper21_init(void); -void Mapper22_init(void); -void Mapper23_init(void); -void Mapper24_init(void); -void Mapper25_init(void); -void Mapper26_init(void); -void Mapper27_init(void); -void Mapper28_init(void); -void Mapper29_init(void); -void Mapper30_init(void); -void Mapper31_init(void); -void Mapper32_init(void); -void Mapper33_init(void); -void Mapper34_init(void); -void Mapper35_init(void); -void Mapper36_init(void); -void Mapper37_init(void); -void Mapper38_init(void); -void Mapper39_init(void); -void Mapper40_init(void); -void Mapper41_init(void); -void Mapper42_init(void); -void Mapper43_init(void); -void Mapper44_init(void); -void Mapper45_init(void); -void Mapper46_init(void); -void Mapper47_init(void); -void Mapper48_init(void); -void Mapper49_init(void); -void Mapper50_init(void); -void Mapper51_init(void); -void Mapper52_init(void); -void Mapper53_init(void); -void Mapper54_init(void); -void Mapper55_init(void); -void Mapper56_init(void); -void Mapper57_init(void); -void Mapper58_init(void); -void Mapper59_init(void); -void Mapper60_init(void); -void Mapper61_init(void); -void Mapper62_init(void); -void Mapper63_init(void); -void Mapper64_init(void); -void Mapper65_init(void); -void Mapper66_init(void); -void Mapper67_init(void); -void Mapper68_init(void); -void Mapper69_init(void); -void Mapper70_init(void); -void Mapper71_init(void); -void Mapper72_init(void); -void Mapper73_init(void); -void Mapper74_init(void); -void Mapper75_init(void); -void Mapper76_init(void); -void Mapper77_init(void); -void Mapper78_init(void); -void Mapper79_init(void); -void Mapper80_init(void); -void Mapper81_init(void); -void Mapper82_init(void); -void Mapper83_init(void); -void Mapper84_init(void); -void Mapper85_init(void); -void Mapper86_init(void); -void Mapper87_init(void); -void Mapper88_init(void); -void Mapper89_init(void); -void Mapper90_init(void); -void Mapper91_init(void); -void Mapper92_init(void); -void Mapper93_init(void); -void Mapper94_init(void); -void Mapper95_init(void); -void Mapper96_init(void); -void Mapper97_init(void); -void Mapper98_init(void); -void Mapper99_init(void); -void Mapper100_init(void); -void Mapper101_init(void); -void Mapper102_init(void); -void Mapper103_init(void); -void Mapper104_init(void); -void Mapper105_init(void); -void Mapper106_init(void); -void Mapper107_init(void); -void Mapper108_init(void); -void Mapper109_init(void); -void Mapper110_init(void); -void Mapper111_init(void); -void Mapper112_init(void); -void Mapper113_init(void); -void Mapper114_init(void); -void Mapper115_init(void); -void Mapper116_init(void); -void Mapper117_init(void); -void Mapper118_init(void); -void Mapper119_init(void); -void Mapper120_init(void); -void Mapper121_init(void); -void Mapper122_init(void); -void Mapper123_init(void); -void Mapper124_init(void); -void Mapper125_init(void); -void Mapper126_init(void); -void Mapper127_init(void); -void Mapper128_init(void); -void Mapper129_init(void); -void Mapper130_init(void); -void Mapper131_init(void); -void Mapper132_init(void); -void Mapper133_init(void); -void Mapper134_init(void); -void Mapper135_init(void); -void Mapper136_init(void); -void Mapper137_init(void); -void Mapper138_init(void); -void Mapper139_init(void); -void Mapper140_init(void); -void Mapper141_init(void); -void Mapper142_init(void); -void Mapper143_init(void); -void Mapper144_init(void); -void Mapper145_init(void); -void Mapper146_init(void); -void Mapper147_init(void); -void Mapper148_init(void); -void Mapper149_init(void); -void Mapper150_init(void); -void Mapper151_init(void); -void Mapper152_init(void); -void Mapper153_init(void); -void Mapper154_init(void); -void Mapper155_init(void); -void Mapper156_init(void); -void Mapper157_init(void); -void Mapper158_init(void); -void Mapper159_init(void); -void Mapper160_init(void); -void Mapper161_init(void); -void Mapper162_init(void); -void Mapper163_init(void); -void Mapper164_init(void); -void Mapper165_init(void); -void Mapper166_init(void); -void Mapper167_init(void); -void Mapper168_init(void); -void Mapper169_init(void); -void Mapper170_init(void); -void Mapper171_init(void); -void Mapper172_init(void); -void Mapper173_init(void); -void Mapper174_init(void); -void Mapper175_init(void); -void Mapper176_init(void); -void Mapper177_init(void); -void Mapper178_init(void); -void Mapper179_init(void); -void Mapper180_init(void); -void Mapper181_init(void); -void Mapper182_init(void); -void Mapper183_init(void); -void Mapper184_init(void); -void Mapper185_init(void); -void Mapper186_init(void); -void Mapper187_init(void); -void Mapper188_init(void); -void Mapper189_init(void); -void Mapper190_init(void); -void Mapper191_init(void); -void Mapper192_init(void); -void Mapper193_init(void); -void Mapper194_init(void); -void Mapper195_init(void); -void Mapper196_init(void); -void Mapper197_init(void); -void Mapper198_init(void); -void Mapper199_init(void); -void Mapper200_init(void); -void Mapper201_init(void); -void Mapper202_init(void); -void Mapper203_init(void); -void Mapper204_init(void); -void Mapper205_init(void); -void Mapper206_init(void); -void Mapper207_init(void); -void Mapper208_init(void); -void Mapper209_init(void); -void Mapper210_init(void); -void Mapper211_init(void); -void Mapper212_init(void); -void Mapper213_init(void); -void Mapper214_init(void); -void Mapper215_init(void); -void Mapper216_init(void); -void Mapper217_init(void); -void Mapper218_init(void); -void Mapper219_init(void); -void Mapper220_init(void); -void Mapper221_init(void); -void Mapper222_init(void); -void Mapper223_init(void); -void Mapper224_init(void); -void Mapper225_init(void); -void Mapper226_init(void); -void Mapper227_init(void); -void Mapper228_init(void); -void Mapper229_init(void); -void Mapper230_init(void); -void Mapper231_init(void); -void Mapper232_init(void); -void Mapper233_init(void); -void Mapper234_init(void); -void Mapper235_init(void); -void Mapper236_init(void); -void Mapper237_init(void); -void Mapper238_init(void); -void Mapper239_init(void); -void Mapper240_init(void); -void Mapper241_init(void); -void Mapper242_init(void); -void Mapper243_init(void); -void Mapper244_init(void); -void Mapper245_init(void); -void Mapper246_init(void); -void Mapper247_init(void); -void Mapper248_init(void); -void Mapper249_init(void); -void Mapper250_init(void); -void Mapper251_init(void); -void Mapper252_init(void); -void Mapper253_init(void); -void Mapper254_init(void); -void Mapper255_init(void); - -void VRC6_ESI(int t); -void VRC7_ESI(void); -void Mapper5_ESI(void); -void Mapper69_ESI(void); -void Mapper19_ESI(void); +/* 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 "cart.h" +#ifdef INESPRIV + +void iNESStateRestore(int version); +extern uint32 iNESGameCRC32; + +extern uint8 *VROM; + +extern uint32 VROM_size; +extern uint32 ROM_size; + +extern void (*MapStateRestore)(int version); +extern void (*MapClose)(void); +extern void (*MapperReset)(void); + +/* This order is necessary */ +#define WRAM (GameMemBlock) +#define sizeofWRAM 8192 + +#define MapperExRAM (GameMemBlock+sizeofWRAM) +#define sizeofMapperExRAM 32768 +/* for the MMC5 code to work properly. It might be fixed later... */ + +#define CHRRAM (GameMemBlock+sizeofWRAM+sizeofMapperExRAM) +#define sizeofCHRRAM 8192 + +#define ExtraNTARAM (GameMemBlock+sizeofWRAM+sizeofMapperExRAM+sizeofCHRRAM) +#define sizeofExtraNTARAM 2048 + +#define PRGBankList (ExtraNTARAM+sizeofExtraNTARAM) + +#define mapbyte1 (PRGBankList+4) +#define mapbyte2 (mapbyte1+8) +#define mapbyte3 (mapbyte2+8) +#define mapbyte4 (mapbyte3+8) +extern uint16 iNESCHRBankList[8]; +extern int32 iNESIRQLatch,iNESIRQCount; +extern uint8 iNESMirroring; +extern uint8 iNESIRQa; + +#define IRQa iNESIRQa +#define Mirroring iNESMirroring +#define IRQCount iNESIRQCount +#define IRQLatch iNESIRQLatch +#define CHRBankList iNESCHRBankList +#else +#endif + + typedef struct { + char ID[4]; /*NES^Z*/ + uint8 ROM_size; + uint8 VROM_size; + uint8 ROM_type; + uint8 ROM_type2; + uint8 reserve[8]; + } iNES_HEADER; + +void FASTAPASS(2) VRAM_BANK1(uint32 A, uint8 V); +void FASTAPASS(2) VRAM_BANK4(uint32 A,uint32 V); + +void FASTAPASS(2) VROM_BANK1(uint32 A,uint32 V); +void FASTAPASS(2) VROM_BANK2(uint32 A,uint32 V); +void FASTAPASS(2) VROM_BANK4(uint32 A, uint32 V); +void FASTAPASS(1) VROM_BANK8(uint32 V); +void FASTAPASS(2) ROM_BANK8(uint32 A, uint32 V); +void FASTAPASS(2) ROM_BANK16(uint32 A, uint32 V); +void FASTAPASS(1) ROM_BANK32(uint32 V); + +extern uint8 vmask; +extern uint32 vmask1; +extern uint32 vmask2; +extern uint32 vmask4; +extern uint32 pmask8; +extern uint8 pmask16; +extern uint8 pmask32; + +void FASTAPASS(1) onemir(uint8 V); +void FASTAPASS(1) MIRROR_SET2(uint8 V); +void FASTAPASS(1) MIRROR_SET(uint8 V); + +void Mapper0_init(void); +void Mapper1_init(void); +//void Mapper2_init(void); +//void Mapper3_init(void); +void Mapper6_init(void); +void Mapper7_init(void); +void Mapper8_init(void); +void Mapper9_init(void); +void Mapper10_init(void); +void Mapper11_init(void); +void Mapper12_init(void); +//void Mapper13_init(void); +void Mapper14_init(void); +void Mapper15_init(void); +void Mapper16_init(void); +void Mapper17_init(void); +void Mapper18_init(void); +void Mapper19_init(void); +void Mapper20_init(void); +void Mapper21_init(void); +void Mapper22_init(void); +void Mapper23_init(void); +void Mapper24_init(void); +void Mapper25_init(void); +void Mapper26_init(void); +void Mapper27_init(void); +void Mapper28_init(void); +void Mapper29_init(void); +void Mapper30_init(void); +void Mapper31_init(void); +void Mapper32_init(void); +void Mapper33_init(void); +void Mapper34_init(void); +void Mapper35_init(void); +void Mapper36_init(void); +void Mapper37_init(void); +void Mapper38_init(void); +void Mapper39_init(void); +void Mapper40_init(void); +void Mapper41_init(void); +void Mapper42_init(void); +void Mapper43_init(void); +void Mapper44_init(void); +void Mapper45_init(void); +void Mapper46_init(void); +void Mapper47_init(void); +void Mapper48_init(void); +void Mapper49_init(void); +void Mapper50_init(void); +void Mapper51_init(void); +void Mapper53_init(void); +void Mapper54_init(void); +void Mapper55_init(void); +void Mapper56_init(void); +void Mapper57_init(void); +void Mapper58_init(void); +void Mapper59_init(void); +void Mapper60_init(void); +void Mapper61_init(void); +void Mapper62_init(void); +void Mapper63_init(void); +void Mapper64_init(void); +void Mapper65_init(void); +void Mapper66_init(void); +void Mapper67_init(void); +void Mapper68_init(void); +void Mapper69_init(void); +void Mapper70_init(void); +void Mapper71_init(void); +void Mapper72_init(void); +void Mapper73_init(void); +void Mapper74_init(void); +void Mapper75_init(void); +void Mapper76_init(void); +void Mapper77_init(void); +void Mapper78_init(void); +void Mapper79_init(void); +void Mapper80_init(void); +void Mapper81_init(void); +void Mapper82_init(void); +void Mapper83_init(void); +void Mapper84_init(void); +void Mapper85_init(void); +void Mapper86_init(void); +void Mapper87_init(void); +void Mapper88_init(void); +void Mapper89_init(void); +void Mapper91_init(void); +void Mapper92_init(void); +void Mapper93_init(void); +void Mapper94_init(void); +void Mapper96_init(void); +void Mapper97_init(void); +void Mapper98_init(void); +void Mapper99_init(void); +void Mapper100_init(void); +void Mapper101_init(void); +void Mapper102_init(void); +void Mapper103_init(void); +void Mapper104_init(void); +void Mapper106_init(void); +void Mapper107_init(void); +void Mapper108_init(void); +void Mapper109_init(void); +void Mapper110_init(void); +void Mapper111_init(void); +//void Mapper112_init(void); +void Mapper113_init(void); +//void Mapper114_init(void); +void Mapper115_init(void); +void Mapper116_init(void); +void Mapper117_init(void); +void Mapper120_init(void); +void Mapper121_init(void); +void Mapper122_init(void); +void Mapper123_init(void); +void Mapper124_init(void); +void Mapper126_init(void); +void Mapper127_init(void); +void Mapper128_init(void); +void Mapper129_init(void); +void Mapper130_init(void); +void Mapper131_init(void); +void Mapper132_init(void); +void Mapper134_init(void); +void Mapper135_init(void); +void Mapper136_init(void); +void Mapper137_init(void); +//void Mapper138_init(void); +void Mapper139_init(void); +void Mapper140_init(void); +void Mapper141_init(void); +void Mapper142_init(void); +void Mapper143_init(void); +void Mapper144_init(void); +//void Mapper145_init(void); +//void Mapper146_init(void); +//void Mapper147_init(void); +//void Mapper149_init(void); +void Mapper150_init(void); +void Mapper151_init(void); +void Mapper152_init(void); +void Mapper153_init(void); +void Mapper154_init(void); +void Mapper156_init(void); +void Mapper157_init(void); +void Mapper158_init(void); +void Mapper159_init(void); +void Mapper160_init(void); +void Mapper161_init(void); +void Mapper162_init(void); +void Mapper166_init(void); +void Mapper167_init(void); +void Mapper168_init(void); +void Mapper169_init(void); +void Mapper170_init(void); +void Mapper171_init(void); +void Mapper172_init(void); +void Mapper173_init(void); +void Mapper174_init(void); +void Mapper175_init(void); +void Mapper176_init(void); +void Mapper177_init(void); +void Mapper178_init(void); +void Mapper179_init(void); +void Mapper180_init(void); +void Mapper181_init(void); +void Mapper184_init(void); +void Mapper185_init(void); +void Mapper189_init(void); +//void Mapper191_init(void); +void Mapper192_init(void); +void Mapper193_init(void); +void Mapper194_init(void); +void Mapper195_init(void); +void Mapper196_init(void); +void Mapper197_init(void); +void Mapper198_init(void); +void Mapper199_init(void); +void Mapper200_init(void); +void Mapper201_init(void); +void Mapper202_init(void); +void Mapper203_init(void); +void Mapper204_init(void); +void Mapper207_init(void); +void Mapper211_init(void); +void Mapper212_init(void); +void Mapper213_init(void); +void Mapper214_init(void); +void Mapper218_init(void); +void Mapper219_init(void); +void Mapper220_init(void); +void Mapper221_init(void); +void Mapper222_init(void); +void Mapper223_init(void); +void Mapper224_init(void); +void Mapper225_init(void); +void Mapper226_init(void); +void Mapper227_init(void); +void Mapper228_init(void); +void Mapper229_init(void); +void Mapper230_init(void); +void Mapper231_init(void); +void Mapper232_init(void); +void Mapper233_init(void); +void Mapper234_init(void); +void Mapper235_init(void); +void Mapper236_init(void); +void Mapper237_init(void); +void Mapper238_init(void); +void Mapper239_init(void); +void Mapper240_init(void); +void Mapper241_init(void); +void Mapper242_init(void); +void Mapper244_init(void); +void Mapper245_init(void); +void Mapper246_init(void); +void Mapper247_init(void); +void Mapper249_init(void); +void Mapper251_init(void); +void Mapper252_init(void); +void Mapper253_init(void); +void Mapper255_init(void); + +void NSFVRC6_Init(void); +void NSFMMC5_Init(void); +void NSFAY_Init(void); +void NSFN106_Init(void); +void NSFVRC7_Init(void); +void Mapper19_ESI(void); + +void Mapper1_Init(CartInfo *); +void Mapper4_Init(CartInfo *); +void Mapper5_Init(CartInfo *); +void Mapper12_Init(CartInfo *); +void Mapper19_Init(CartInfo *); +void Mapper44_Init(CartInfo *); +void Mapper45_Init(CartInfo *); +void Mapper47_Init(CartInfo *); +void Mapper49_Init(CartInfo *); +void Mapper52_Init(CartInfo *); +void Mapper74_Init(CartInfo *); +void Mapper90_Init(CartInfo *); +void Mapper95_Init(CartInfo *); +void Mapper105_Init(CartInfo *); +void Mapper112_Init(CartInfo *); +void Mapper114_Init(CartInfo *); +void Mapper115_Init(CartInfo *); +void Mapper116_Init(CartInfo *); +void Mapper118_Init(CartInfo *); +void Mapper119_Init(CartInfo *); +void Mapper125_Init(CartInfo *); +void Mapper155_Init(CartInfo *); +void Mapper163_Init(CartInfo *); +void Mapper164_Init(CartInfo *); +void Mapper165_Init(CartInfo *); +void Mapper182_Init(CartInfo *); +void Mapper183_Init(CartInfo *); +void Mapper186_Init(CartInfo *); +void Mapper187_Init(CartInfo *); +void Mapper188_Init(CartInfo *); +void Mapper191_Init(CartInfo *); +void Mapper205_Init(CartInfo *); +void Mapper208_Init(CartInfo *); +void Mapper209_Init(CartInfo *); +void Mapper210_Init(CartInfo *); +void Mapper215_Init(CartInfo *); +void Mapper216_Init(CartInfo *); +void Mapper217_Init(CartInfo *); +void Mapper245_Init(CartInfo *); +void Mapper249_Init(CartInfo *); +void Mapper250_Init(CartInfo *); +void Mapper254_Init(CartInfo *); diff --git a/input.c b/input.c index e4223bc..1548e41 100644 --- a/input.c +++ b/input.c @@ -31,6 +31,8 @@ #include "state.h" #include "movie.h" +#include "fds.h" +#include "vsuni.h" #include "dprintf.h" extern INPUTC *FCEU_InitZapper(int w); @@ -61,6 +63,14 @@ static INPUTC DummyJPort={0,0,0,0,0}; static INPUTC *JPorts[2]={&DummyJPort,&DummyJPort}; static INPUTCFC *FCExp=0; +/* This function is a quick hack to get the NSF player to use emulated gamepad + input. +*/ +uint8 FCEU_GetJoyJoy(void) +{ + return(joy[0]|joy[1]|joy[2]|joy[3]); +} + static uint8 FP_FASTAPASS(1) ReadGPVS(int w) { uint8 ret=0; @@ -195,7 +205,7 @@ void UpdateInput(void) if(netplay) NetplayUpdate(&joy[0],&joy[1]); #endif if (current < 0) FCEUMOV_AddJoy(joy); - FlushCommandQueue(); + //FlushCommandQueue(); } static DECLFR(VSUNIRead0) @@ -255,7 +265,7 @@ static void FASTAPASS(1) SetInputStuff(int x) break; case SI_ARKANOID:JPorts[x]=FCEU_InitArkanoid(x);break; case SI_ZAPPER:JPorts[x]=FCEU_InitZapper(x);break; - case SI_POWERPAD:JPorts[x]=FCEU_InitPowerpad(x);break; + case SI_POWERPADA:JPorts[x]=FCEU_InitPowerpad(x);break; case SI_NONE:JPorts[x]=&DummyJPort;break; } @@ -351,17 +361,74 @@ void FCEU_DoSimpleCommand(int cmd) { switch(cmd) { -// case FCEUNPCMD_FDSINSERT: FCEU_FDSInsert();break; -// case FCEUNPCMD_FDSSELECT: FCEU_FDSSelect();break; + case FCEUNPCMD_FDSINSERT: FCEU_FDSInsert();break; + case FCEUNPCMD_FDSSELECT: FCEU_FDSSelect();break; // case FCEUNPCMD_FDSEJECT: FCEU_FDSEject();break; -// case FCEUNPCMD_VSUNICOIN: FCEU_VSUniCoin(); break; -// case FCEUNPCMD_VSUNIDIP0 ... (FCEUNPCMD_VSUNIDIP0 + 7): FCEU_VSUniToggleDIP(cmd - FCEUNPCMD_VSUNIDIP0);break; + case FCEUNPCMD_VSUNICOIN: FCEU_VSUniCoin(); break; + case FCEUNPCMD_VSUNIDIP0 ... (FCEUNPCMD_VSUNIDIP0 + 7): FCEU_VSUniToggleDIP(cmd - FCEUNPCMD_VSUNIDIP0);break; case FCEUNPCMD_POWER: PowerNES();break; case FCEUNPCMD_RESET: ResetNES();break; default: printf("FCEU_DoSimpleCommand: can't handle cmd %i\n", cmd); break; } } +void FCEU_QSimpleCommand(int cmd) +{ +// if(FCEUnetplay) +// FCEUNET_SendCommand(cmd, 0); +// else + { + // totally wrong: +// if(!FCEUMOV_IsPlaying()) +// FCEU_DoSimpleCommand(cmd); +// else +// FCEUMOV_AddCommand(cmd); + + FCEU_DoSimpleCommand(cmd); +// if(FCEUMOV_IsRecording()) +// FCEUMOV_AddCommand(cmd); + } +} + +void FCEUI_FDSSelect(void) +{ + FCEU_QSimpleCommand(FCEUNPCMD_FDSSELECT); +} + +int FCEUI_FDSInsert(void) +{ + FCEU_QSimpleCommand(FCEUNPCMD_FDSINSERT); + return(1); +} + +/* +int FCEUI_FDSEject(void) +{ + FCEU_QSimpleCommand(FCEUNPCMD_FDSEJECT); + return(1); +} +*/ +void FCEUI_VSUniToggleDIP(int w) +{ + FCEU_QSimpleCommand(FCEUNPCMD_VSUNIDIP0 + w); +} + +void FCEUI_VSUniCoin(void) +{ + FCEU_QSimpleCommand(FCEUNPCMD_VSUNICOIN); +} + +void FCEUI_ResetNES(void) +{ + FCEU_QSimpleCommand(FCEUNPCMD_RESET); +} + +void FCEUI_PowerNES(void) +{ + FCEU_QSimpleCommand(FCEUNPCMD_POWER); +} + + SFORMAT FCEUCTRL_STATEINFO[]={ { joy_readbit, 2, "JYRB"}, diff --git a/input.h b/input.h index 8c301cf..3adc898 100644 --- a/input.h +++ b/input.h @@ -24,3 +24,10 @@ extern void (*InputScanlineHook)(uint8 *buf, int line); void FCEU_DoSimpleCommand(int cmd); +void FCEUI_FDSSelect(void); +int FCEUI_FDSInsert(void); +void FCEUI_VSUniToggleDIP(int w); +void FCEUI_VSUniCoin(void); +void FCEUI_ResetNES(void); +void FCEUI_PowerNES(void); + diff --git a/mappers/105.c b/mappers/105.c deleted file mode 100644 index 07f4ceb..0000000 --- a/mappers/105.c +++ /dev/null @@ -1,132 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 1998 BERO - * Copyright (C) 2002 Ben Parnell - * - * 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 MMC1_reg mapbyte1 -#define MMC1_buf mapbyte2[0] -#define MMC1_sft mapbyte3[0] -#define lastn mapbyte2[1] - -#define NWCDIP 0xE - -static void FP_FASTAPASS(1) NWCIRQHook(int a) -{ - if(!(MMC1_reg[1]&0x10)) - { - IRQCount+=a; - if((IRQCount|(NWCDIP<<25))>=0x3e000000) - { - IRQCount=0; - X6502_IRQBegin(FCEU_IQEXT); - } - } -} - - -static void MMC1PRG(void) -{ - if(MMC1_reg[1]&8) - { - switch(MMC1_reg[0]&0xC) - { - case 0xC: ROM_BANK16(0x8000,8+(MMC1_reg[3]&7)); - ROM_BANK16(0xC000,15); - break; - case 0x8: ROM_BANK16(0xC000,8+((MMC1_reg[3])&7)); - ROM_BANK16(0x8000,8); - break; - case 0x0: - case 0x4: - ROM_BANK16(0x8000,8+(MMC1_reg[3]&6)); - ROM_BANK16(0xc000,8+((MMC1_reg[3]&6)+1)); - break; - } - } - else - { - ROM_BANK32((MMC1_reg[1]>>1)&3); - } - X6502_Rebase(); -} - -DECLFW(Mapper105_write) -{ - int n=(A>>13)-4; - - if (V&0x80) - { - MMC1_sft=MMC1_buf=0; - return; - } - - if(lastn!=n) - { - MMC1_sft=MMC1_buf=0; - } - lastn=n; - - //MMC1_reg[n]&=~((1)<<(MMC1_sft)); - MMC1_buf|=(V&1)<<(MMC1_sft++); - - if (MMC1_sft==5) - { - if(n==3) V&=0xF; - else V&=0x1F; - - MMC1_reg[n]=V=MMC1_buf; - MMC1_sft = MMC1_buf=0; - - switch(n){ - case 0: - switch(MMC1_reg[0]&3) - { - case 2: MIRROR_SET(0);break; - case 3: MIRROR_SET(1);break; - case 0: onemir(0);break; - case 1: onemir(1);break; - } - MMC1PRG(); - break; - case 1: - if(MMC1_reg[1]&0x10) - {IRQCount=0;X6502_IRQEnd(FCEU_IQEXT);} - MMC1PRG(); - break; - case 3: - MMC1PRG(); - break; - } - } -} - - -void Mapper105_init(void) -{ - int i; - for(i=0;i<4;i++) MMC1_reg[i]=0; - MMC1_sft = MMC1_buf =0; - MMC1_reg[0]=0xC; - ROM_BANK32(0); - SetWriteHandler(0x8000,0xFFFF,Mapper105_write); - MapIRQHook=NWCIRQHook; -} - diff --git a/mappers/113.c b/mappers/113.c index 4662ed5..525f131 100644 --- a/mappers/113.c +++ b/mappers/113.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -28,16 +28,31 @@ DECLFW(Mapper113_write) { ROM_BANK32((V>>3)&7); - VROM_BANK8(V&7); - X6502_Rebase(); + VROM_BANK8(((V>>3)&8)|(V&7)); + //printf("$%04x:$%02x\n",A,V); } /* Deathbots */ DECLFW(Mapper113_writeh) { - ROM_BANK32(V&0xF); - X6502_Rebase(); + //printf("$%04x:$%02x\n",A,V); + // ROM_BANK32(V&0x7); + //VROM_BANK8((V>>4)&0x7); + switch(A) { + case 0x8008: + case 0x8009: + ROM_BANK32(V>>3); + VROM_BANK8(((V>>3)&0x08)+(V&0x07) ); + break; + case 0x8E66: + case 0x8E67: + VROM_BANK8( (V&0x07)?0:1 ); + break; + case 0xE00A: + MIRROR_SET2( 2 ); + break; + } } diff --git a/mappers/117.c b/mappers/117.c index 6f1051c..f7302b4 100644 --- a/mappers/117.c +++ b/mappers/117.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -24,10 +24,14 @@ DECLFW(Mapper117_write) { + //if(A>=0xc000) + //printf("$%04x:$%02x, %d,%d\n",A,V,scanline,timestamp); switch(A) { - case 0xc003:IRQCount=V;break; - case 0xc001:IRQa=V;break; + 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; case 0xa000:VROM_BANK1(0x0000,V);break; case 0xa001:VROM_BANK1(0x0400,V);break; case 0xa002:VROM_BANK1(0x0800,V);break; @@ -36,30 +40,25 @@ DECLFW(Mapper117_write) case 0xa005:VROM_BANK1(0x1400,V);break; case 0xa006:VROM_BANK1(0x1800,V);break; case 0xa007:VROM_BANK1(0x1c00,V);break; - case 0x8000:ROM_BANK8(0x8000,V); - X6502_Rebase();break; - case 0x8001:ROM_BANK8(0xa000,V); - X6502_Rebase();break; - case 0x8002:ROM_BANK8(0xc000,V); - X6502_Rebase();break; - case 0x8003:ROM_BANK8(0xe000,V); - X6502_Rebase();break; + case 0x8000:ROM_BANK8(0x8000,V);break; + case 0x8001:ROM_BANK8(0xa000,V);break; + case 0x8002:ROM_BANK8(0xc000,V);break; + case 0x8003:ROM_BANK8(0xe000,V);break; } } static void Mapper117_hb(void) { - if(IRQa) + //if(scanline==0x40) X6502_IRQBegin(FCEU_IQEXT); + //return; + if(IRQa==3 && IRQCount) { - if(IRQCount<=0) - { - IRQa=0; - TriggerIRQ(); - } - else - { - IRQCount--; - } + IRQCount--; + if(!IRQCount) + { + IRQa&=1; + X6502_IRQBegin(FCEU_IQEXT); + } } } diff --git a/mappers/15.c b/mappers/15.c index e3ad005..e649af6 100644 --- a/mappers/15.c +++ b/mappers/15.c @@ -1,8 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 1998 BERO - * Copyright (C) 2002 Ben Parnell + * 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 @@ -21,71 +20,54 @@ #include "mapinc.h" +static void Sync(void) +{ + int x; + + setmirror(((mapbyte1[0]>>6)&1)^1); + switch(mapbyte1[1]&0x3) + { + case 0x0: + for(x=0;x<4;x++) + setprg8(0x8000+x*8192,(((mapbyte1[0]&0x7F)<<1)+x)^(mapbyte1[0]>>7)); + break; + case 0x2: + for(x=0;x<4;x++) + setprg8(0x8000+x*8192,((mapbyte1[0]&0x7F)<<1)+(mapbyte1[0]>>7)); + break; + case 0x1: + case 0x3: + for(x=0;x<4;x++) + { + unsigned int b; + b=mapbyte1[0]&0x7F; + if(x>=2 && !(mapbyte1[1]&0x2)) + b=0x7F; + setprg8(0x8000+x*8192,(x&1)+((b<<1)^(mapbyte1[0]>>7))); + } + break; + } +} -DECLFW(Mapper15_write) +static DECLFW(Mapper15_write) { -switch(A) - { - case 0x8000: - if(V&0x80) - { - ROM_BANK8(0x8000,(V<<1)+1); - ROM_BANK8(0xA000,(V<<1)); - ROM_BANK8(0xC000,(V<<1)+2); - ROM_BANK8(0xE000,(V<<1)+1); - } - else - { - ROM_BANK16(0x8000,V); - ROM_BANK16(0xC000,V+1); - } - MIRROR_SET((V>>6)&1); - X6502_Rebase(); - break; - case 0x8001: - MIRROR_SET(0); - ROM_BANK16(0x8000,V); - ROM_BANK16(0xc000,~0); - X6502_Rebase(); - break; - case 0x8002: - if(V&0x80) - { - ROM_BANK8(0x8000,((V<<1)+1)); - ROM_BANK8(0xA000,((V<<1)+1)); - ROM_BANK8(0xC000,((V<<1)+1)); - ROM_BANK8(0xE000,((V<<1)+1)); - } - else - { - ROM_BANK8(0x8000,(V<<1)); - ROM_BANK8(0xA000,(V<<1)); - ROM_BANK8(0xC000,(V<<1)); - ROM_BANK8(0xE000,(V<<1)); - } - X6502_Rebase(); - break; - case 0x8003: - MIRROR_SET((V>>6)&1); - if(V&0x80) - { - ROM_BANK8(0xC000,(V<<1)+1); - ROM_BANK8(0xE000,(V<<1)); - } - else - { - ROM_BANK16(0xC000,V); - } - X6502_Rebase(); - break; - } + mapbyte1[0]=V; + mapbyte1[1]=A&3; + Sync(); +} + +static void StateRestore(int version) +{ + Sync(); } void Mapper15_init(void) { - ROM_BANK32(0); - SetWriteHandler(0x8000,0xFFFF,Mapper15_write); + mapbyte1[0]=mapbyte1[1]=0; + Sync(); + GameStateRestore=StateRestore; + SetWriteHandler(0x8000,0xFFFF,Mapper15_write); } diff --git a/mappers/151.c b/mappers/151.c index e7c123e..5d2cb28 100644 --- a/mappers/151.c +++ b/mappers/151.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -26,12 +26,9 @@ DECLFW(Mapper151_write) { switch(A&0xF000) { - case 0x8000:ROM_BANK8(0x8000,V); - X6502_Rebase();break; - case 0xA000:ROM_BANK8(0xA000,V); - X6502_Rebase();break; - case 0xC000:ROM_BANK8(0xC000,V); - X6502_Rebase();break; + case 0x8000:ROM_BANK8(0x8000,V);break; + case 0xA000:ROM_BANK8(0xA000,V);break; + case 0xC000:ROM_BANK8(0xC000,V);break; case 0xe000:VROM_BANK4(0x0000,V);break; case 0xf000:VROM_BANK4(0x1000,V);break; } diff --git a/mappers/16.c b/mappers/16.c index 58dd0b1..fd922fb 100644 --- a/mappers/16.c +++ b/mappers/16.c @@ -2,7 +2,7 @@ * * Copyright notice for this file: * Copyright (C) 1998 BERO - * Copyright (C) 2002 Ben Parnell + * 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 @@ -43,10 +43,7 @@ static DECLFW(Mapper16_write) if(A<=0x7) VROM_BANK1(A<<10,V); else if(A==0x8) - { ROM_BANK16(0x8000,V); - X6502_Rebase(); - } else switch(A) { case 0x9: switch(V&3) { case 0x00:MIRROR_SET2(1);break; @@ -81,40 +78,39 @@ static void PRGO(void) uint32 base=(mapbyte1[0]&1)<<4; ROM_BANK16(0x8000,(mapbyte2[0]&0xF)|base); ROM_BANK16(0xC000,base|0xF); - X6502_Rebase(); } static DECLFW(Mapper153_write) { - A&=0xF; + A&=0xF; if(A<=0x7) - { - mapbyte1[A&7]=V; - PRGO(); - } + { + mapbyte1[A&7]=V; + PRGO(); + } else if(A==0x8) - { - mapbyte2[0]=V; - PRGO(); - } - else switch(A) { - case 0x9: switch(V&3) { - case 0x00:MIRROR_SET2(1);break; + { + mapbyte2[0]=V; + PRGO(); + } + else switch(A) { + case 0x9: switch(V&3) { + case 0x00:MIRROR_SET2(1);break; case 0x01:MIRROR_SET2(0);break; case 0x02:onemir(0);break; case 0x03:onemir(1);break; } break; case 0xA:X6502_IRQEnd(FCEU_IQEXT); - IRQa=V&1; - IRQCount=IRQLatch; - break; + IRQa=V&1; + IRQCount=IRQLatch; + break; case 0xB:IRQLatch&=0xFF00; - IRQLatch|=V; - break; + IRQLatch|=V; + break; case 0xC:IRQLatch&=0xFF; - IRQLatch|=V<<8; - break; + IRQLatch|=V<<8; + break; } } @@ -131,3 +127,179 @@ void Mapper153_init(void) /* This mapper/board seems to have WRAM at $6000-$7FFF, so I'll let the main ines code take care of that memory region. */ } + + +static uint8 BarcodeData[256]; +static int BarcodeReadPos; +static int BarcodeCycleCount; +static uint32 BarcodeOut; + +int FCEUI_DatachSet(const uint8 *rcode) +{ + int prefix_parity_type[10][6] = { + {0,0,0,0,0,0}, {0,0,1,0,1,1}, {0,0,1,1,0,1}, {0,0,1,1,1,0}, + {0,1,0,0,1,1}, {0,1,1,0,0,1}, {0,1,1,1,0,0}, {0,1,0,1,0,1}, + {0,1,0,1,1,0}, {0,1,1,0,1,0} + }; + int data_left_odd[10][7] = { + {0,0,0,1,1,0,1}, {0,0,1,1,0,0,1}, {0,0,1,0,0,1,1}, {0,1,1,1,1,0,1}, + {0,1,0,0,0,1,1}, {0,1,1,0,0,0,1}, {0,1,0,1,1,1,1}, {0,1,1,1,0,1,1}, + {0,1,1,0,1,1,1}, {0,0,0,1,0,1,1} + }; + int data_left_even[10][7] = { + {0,1,0,0,1,1,1}, {0,1,1,0,0,1,1}, {0,0,1,1,0,1,1}, {0,1,0,0,0,0,1}, + {0,0,1,1,1,0,1}, {0,1,1,1,0,0,1}, {0,0,0,0,1,0,1}, {0,0,1,0,0,0,1}, + {0,0,0,1,0,0,1}, {0,0,1,0,1,1,1} + }; + int data_right[10][7] = { + {1,1,1,0,0,1,0}, {1,1,0,0,1,1,0}, {1,1,0,1,1,0,0}, {1,0,0,0,0,1,0}, + {1,0,1,1,1,0,0}, {1,0,0,1,1,1,0}, {1,0,1,0,0,0,0}, {1,0,0,0,1,0,0}, + {1,0,0,1,0,0,0}, {1,1,1,0,1,0,0} + }; + uint8 code[13+1]; + uint32 tmp_p=0; + int i, j; + int len; + + for(i=len=0;i<13;i++) + { + if(!rcode[i]) break; + + if((code[i]=rcode[i]-'0') > 9) + return(0); + len++; + } + if(len!=13 && len!=12 && len!=8 && len!=7) return(0); + + #define BS(x) BarcodeData[tmp_p]=x;tmp_p++ + + for(j=0;j<32;j++) + { + BS(0x00); + } + + /* Left guard bars */ + BS(1); BS(0); BS(1); + + if(len==13 || len==12) + { + uint32 csum; + + for(i=0;i<6;i++) + if(prefix_parity_type[code[0]][i]) + { + for(j=0;j<7;j++) + { + BS(data_left_even[code[i+1]][j]); + } + } + else + for(j=0;j<7;j++) + { + BS(data_left_odd[code[i+1]][j]); + } + + /* Center guard bars */ + BS(0); BS(1); BS(0); BS(1); BS(0); + + for(i=7;i<12;i++) + for(j=0;j<7;j++) + { + BS(data_right[code[i]][j]); + } + csum=0; + for(i=0;i<12;i++) csum+=code[i]*((i&1)?3:1); + csum=(10-(csum%10))%10; + //printf("%d\n",csum); + for(j=0;j<7;j++) + { + BS(data_right[csum][j]); + } + + } + else if(len==8 || len==7) + { + uint32 csum=0; + + for(i=0;i<7;i++) csum+=(i&1)?code[i]:(code[i]*3); + + csum=(10-(csum%10))%10; + + for(i=0;i<4;i++) + for(j=0;j<7;j++) + { + BS(data_left_odd[code[i]][j]); + } + + + /* Center guard bars */ + BS(0); BS(1); BS(0); BS(1); BS(0); + + for(i=4;i<7;i++) + for(j=0;j<7;j++) + { + BS(data_right[code[i]][j]); + } + + for(j=0;j<7;j++) + { BS(data_right[csum][j]);} + + } + + /* Right guard bars */ + BS(1); BS(0); BS(1); + + for(j=0;j<32;j++) + { + BS(0x00); + } + + BS(0xFF); + #undef BS + BarcodeReadPos=0; + BarcodeOut=0x8; + BarcodeCycleCount=0; + return(1); +} + +static void FP_FASTAPASS(1) BarcodeIRQHook(int a) +{ + BandaiIRQHook(a); + + BarcodeCycleCount+=a; + + if(BarcodeCycleCount >= 1000) + { + BarcodeCycleCount -= 1000; + if(BarcodeData[BarcodeReadPos]==0xFF) + { + BarcodeOut=0; + } + else + { + BarcodeOut=(BarcodeData[BarcodeReadPos]^1)<<3; + BarcodeReadPos++; + } + } +} + +static DECLFR(Mapper157_read) +{ + uint8 ret; + + ret=BarcodeOut; + return(ret); +} + +void Mapper157_init(void) +{ + FCEUGameInfo.cspecial = SIS_DATACH; + MapIRQHook=BarcodeIRQHook; + SetWriteHandler(0x6000,0xFFFF,Mapper16_write); + SetReadHandler(0x6000,0x7FFF,Mapper157_read); + + BarcodeData[0]=0xFF; + BarcodeReadPos=0; + BarcodeOut=0; + BarcodeCycleCount=0; +} diff --git a/mappers/17.c b/mappers/17.c index 1e76421..7fae1a8 100644 --- a/mappers/17.c +++ b/mappers/17.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -27,10 +27,9 @@ static void FP_FASTAPASS(1) FFEIRQHook(int a) if(IRQa) { IRQCount+=a; - if(IRQCount>=0x10000) { - TriggerIRQ(); + X6502_IRQBegin(FCEU_IQEXT); IRQa=0; IRQCount=0; } @@ -42,24 +41,20 @@ DECLFW(Mapper17_write) { switch(A){ default: - break; + break; case 0x42FE: onemir((V>>4)&1); break; case 0x42FF: MIRROR_SET((V>>4)&1); - break; - case 0x4501:IRQa=V&1;break; + break; + case 0x4501:IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break; case 0x4502:IRQCount&=0xFF00;IRQCount|=V;break; case 0x4503:IRQCount&=0x00FF;IRQCount|=V<<8;IRQa=1;break; - case 0x4504: ROM_BANK8(0x8000,V); - X6502_Rebase();break; - case 0x4505: ROM_BANK8(0xA000,V); - X6502_Rebase();break; - case 0x4506: ROM_BANK8(0xC000,V); - X6502_Rebase();break; - case 0x4507: ROM_BANK8(0xE000,V); - X6502_Rebase();break; + case 0x4504: ROM_BANK8(0x8000,V);break; + case 0x4505: ROM_BANK8(0xA000,V);break; + case 0x4506: ROM_BANK8(0xC000,V);break; + case 0x4507: ROM_BANK8(0xE000,V);break; case 0x4510: VROM_BANK1(0x0000,V);break; case 0x4511: VROM_BANK1(0x0400,V);break; case 0x4512: VROM_BANK1(0x0800,V);break; diff --git a/mappers/18.c b/mappers/18.c index 13b3ab9..b682b26 100644 --- a/mappers/18.c +++ b/mappers/18.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -39,38 +39,37 @@ void FP_FASTAPASS(1) JalecoIRQHook(int a) DECLFW(Mapper18_write) { - A&=0xF003; - if(A>=0x8000 && A<=0x9001) - { + A&=0xF003; + if(A>=0x8000 && A<=0x9001) + { int x=((A>>1)&1)|((A-0x8000)>>11); K4buf2[x]&=(0xF0)>>((A&1)<<2); K4buf2[x]|=(V&0xF)<<((A&1)<<2); ROM_BANK8(0x8000+(x<<13),K4buf2[x]); - X6502_Rebase(); - } - else if(A>=0xa000 && A<=0xd003) - { - int x=((A>>1)&1)|((A-0xA000)>>11); + } + else if(A>=0xa000 && A<=0xd003) + { + int x=((A>>1)&1)|((A-0xA000)>>11); K4buf[x]&=(0xF0)>>((A&1)<<2); K4buf[x]|=(V&0xF)<<((A&1)<<2); VROM_BANK1(x<<10,K4buf[x]); - } + } else switch(A) { - case 0xe000:IRQLatch&=0xFFF0;IRQLatch|=(V&0x0f);break; - case 0xe001:IRQLatch&=0xFF0F;IRQLatch|=(V&0x0f)<<4;break; - case 0xe002:IRQLatch&=0xF0FF;IRQLatch|=(V&0x0f)<<8;break; - case 0xe003:IRQLatch&=0x0FFF;IRQLatch|=(V&0x0f)<<12;break; - case 0xf000:IRQCount=IRQLatch; - break; - case 0xf001:IRQa=V&1; - X6502_IRQEnd(FCEU_IQEXT); - break; - case 0xf002:MIRROR_SET2(V&1); - if(V&2) onemir(0); - break; + case 0xe000:IRQLatch&=0xFFF0;IRQLatch|=(V&0x0f);break; + case 0xe001:IRQLatch&=0xFF0F;IRQLatch|=(V&0x0f)<<4;break; + case 0xe002:IRQLatch&=0xF0FF;IRQLatch|=(V&0x0f)<<8;break; + case 0xe003:IRQLatch&=0x0FFF;IRQLatch|=(V&0x0f)<<12;break; + case 0xf000:IRQCount=IRQLatch; + break; + case 0xf001:IRQa=V&1; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xf002:MIRROR_SET2(V&1); + if(V&2) onemir(0); + break; } } diff --git a/mappers/180.c b/mappers/180.c index 45342dc..bd877c8 100644 --- a/mappers/180.c +++ b/mappers/180.c @@ -4,8 +4,7 @@ DECLFW(Mapper180_write) { - ROM_BANK16(0xC000,V); - X6502_Rebase(); +ROM_BANK16(0xC000,V); } void Mapper180_init(void) diff --git a/mappers/182.c b/mappers/182.c deleted file mode 100644 index a7f65e5..0000000 --- a/mappers/182.c +++ /dev/null @@ -1,50 +0,0 @@ -#include "mapinc.h" - -DECLFW(Mapper182_write) -{ - switch(A&0xf003) - { - case 0xe003:IRQCount=V;IRQa=1;break; - case 0x8001:MIRROR_SET(V&1);break; - case 0xA000:mapbyte1[0]=V;break; - case 0xC000: - switch(mapbyte1[0]&7) - { - case 0:VROM_BANK2(0x0000,V>>1);break; - case 1:VROM_BANK1(0x1400,V);break; - case 2:VROM_BANK2(0x0800,V>>1);break; - case 3:VROM_BANK1(0x1c00,V);break; - case 4:ROM_BANK8(0x8000,V); - X6502_Rebase();break; - case 5:ROM_BANK8(0xA000,V); - X6502_Rebase();break; - case 6:VROM_BANK1(0x1000,V);break; - case 7:VROM_BANK1(0x1800,V);break; - } - break; - - - } -} - -void blop(void) -{ - if(IRQa) - { - if(IRQCount) - { - IRQCount--; - if(!IRQCount) - { - IRQa=0; - TriggerIRQ(); - } - } - } -} -void Mapper182_init(void) -{ - SetWriteHandler(0x8000,0xFFFF,Mapper182_write); - GameHBIRQHook=blop; -} - diff --git a/mappers/183.c b/mappers/183.c new file mode 100644 index 0000000..e69de29 diff --git a/mappers/187.c b/mappers/187.c new file mode 100644 index 0000000..c9925df --- /dev/null +++ b/mappers/187.c @@ -0,0 +1,170 @@ +/* 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 "mapinc.h" + +static uint8 LastWr; +static uint8 ExtMode; +static uint8 cmd; +static uint8 DRegs[8]; +static uint32 count=0; +static uint32 last=0; +static int safe=0; +static uint8 poofish; + +static void Sync(void) +{ + int x; + uint32 base=0; + + if(cmd&0x80) base=0x1000; + setchr2(0x0000^base,(0x100|DRegs[0])>>1); + setchr2(0x0800^base,(0x100|DRegs[1])>>1); + for(x=0;x<4;x++) + setchr1((0x1000^base)+x*0x400,DRegs[2+x]); + + if(ExtMode&0x80) + { + if(ExtMode&0x20) + setprg32(0x8000,(ExtMode&0x1F)>>1); + else + { + setprg16(0x8000,(ExtMode&0x1F)); + setprg16(0xc000,(ExtMode&0x1F)); + } + } + else + { + setprg8(0x8000,DRegs[6]); + setprg8(0xa000,DRegs[7]); + setprg8(0xc000,~1); + setprg8(0xe000,~0); + } +} + +static DECLFW(M187Write) +{ +// FCEU_printf("Write: %04x:%04x (%04x,%d)\n",A,V,X.PC,scanline); + LastWr=V; + if(A==0x5000) + ExtMode=V; + Sync(); +} + +static DECLFW(M187HWrite) +{ +// FCEU_printf("Write: %04x:%04x (%04x,%d)\n",A,V,X.PC,scanline); + //if(A==0x8003 && X.PC<0x800) FCEUI_DumpMem("dmp",0x0000,0xFFFF); + //printf("$%04x:$%02x, %04x\n",A,V,X.PC); + LastWr=V; + + if(A==0x8003) + { +// if(V==0x28 || V==0x2A) + poofish=V; + } + else if(A==0x8000) poofish=0; + + switch(A) + { + case 0xc000:IRQLatch=IRQCount=V;break; + case 0xc001:IRQCount=IRQLatch;last=count=0;break; + case 0xe000:IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break; + case 0xe001:IRQa=1;break; + case 0xa000:MIRROR_SET(V&1);break; + + case 0x8000:cmd=V;safe=1;break; + case 0x8001: + if(safe) + { + //printf("Cmd: %d, %02x, %04x\n",cmd&0x7,V,X.PC); + DRegs[cmd&7]=V; + Sync(); + safe=0; + } + if(poofish==0x28) + setprg8(0xC000,0x17); + else if(poofish==0x2A) + setprg8(0xA000,0x0F); + break; + + } +} + +static DECLFR(ProtRead) +{ + switch(LastWr&0x3) + { + case 0x1: + case 0x0: return(0x83); + case 0x2: return(0x42); + } + return(0); +} + +DECLFW(Write_IRQFM); + +static void M187Power(void) +{ + Write_IRQFM(0x4017,0x40); + SetWriteHandler(0x5000,0x5fff,M187Write); + SetWriteHandler(0x8000,0xFFFF,M187HWrite); + SetReadHandler(0x5000,0x5FFF,ProtRead); + SetWriteHandler(0x6000,0x7FFF,M187Write); + SetReadHandler(0x8000,0xffff,CartBR); + Sync(); +} + +static void sl(void) +{ + if(IRQa) + { + if(IRQCount>=0) + { + IRQCount--; + if(IRQCount<0) + { + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +static void FP_FASTAPASS(1) foo(uint32 A) +{ + if((A&0x2000) && !(last&0x2000)) + { + count++; + if(count==42) + { + sl(); + count=0; + } + } + last=A; +} + +void Mapper187_Init(CartInfo *info) +{ + info->Power=M187Power; +// GameHBIRQHook=sl; + PPU_hook=foo; +} + diff --git a/mappers/189.c b/mappers/189.c index bdcf4b7..68df5b5 100644 --- a/mappers/189.c +++ b/mappers/189.c @@ -8,31 +8,45 @@ #define cmd mapbyte1[0] static DECLFW(Mapper189_write) { - if(A==0x4120) - { - ROM_BANK32(V>>4); - X6502_Rebase(); - } + //if(A>=0xc000) printf("$%04x:$%02x\n",A,V); + if((A&0xF100)==0x4100) ROM_BANK32(V>>4); + else if((A&0xF100)==0x6100) ROM_BANK32(V&3); else switch(A&0xE001) { case 0xa000:MIRROR_SET(V&1);break; case 0x8000:cmd=V;break; case 0x8001:switch(cmd&7) - { - case 0:VROM_BANK2(0x0000,V>>1);break; - case 1:VROM_BANK2(0x0800,V>>1);break; - case 2:VROM_BANK1(0x1000,V);break; + { + case 0:VROM_BANK2(0x0000,V>>1);break; + case 1:VROM_BANK2(0x0800,V>>1);break; + case 2:VROM_BANK1(0x1000,V);break; case 3:VROM_BANK1(0x1400,V);break; case 4:VROM_BANK1(0x1800,V);break; case 5:VROM_BANK1(0x1C00,V);break; - } - break; + } + case 0xc000:IRQLatch=V;break; + case 0xc001:IRQCount=IRQLatch;break; + case 0xe000:IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break; + case 0xe001:IRQa=1;break; + break; } } +void m189irq(void) +{ + if(IRQa) + { + if(IRQCount) + { + IRQCount--; + if(!IRQCount) X6502_IRQBegin(FCEU_IQEXT); + } + } +} void Mapper189_init(void) { + GameHBIRQHook=m189irq; SetWriteHandler(0x4120,0xFFFF,Mapper189_write); SetReadHandler(0x6000,0x7FFF,0); ROM_BANK32(0); diff --git a/mappers/19.c b/mappers/19.c deleted file mode 100644 index 0258b47..0000000 --- a/mappers/19.c +++ /dev/null @@ -1,289 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell - * - * 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 dopol mapbyte1[0] -#define gorfus mapbyte1[1] -#define gorko mapbyte1[2] - -static void NamcoSound(int Count); -static void NamcoSoundHack(void); - -static int32 inc; -void FP_FASTAPASS(1) NamcoIRQHook(int a) -{ - if(IRQa) - { - IRQCount+=a; - if(IRQCount>=0x7fff) - { - X6502_IRQBegin(FCEU_IQEXT); - IRQa=0; - IRQCount=0x7fff; - } - } -} - -DECLFR(Namco_Read4800) -{ - uint8 ret=MapperExRAM[dopol&0x7f]; - if(dopol&0x80) - dopol=(dopol&0x80)|((dopol+1)&0x7f); - return ret; -} - -DECLFR(Namco_Read5000) -{ - return(IRQCount); -} - -DECLFR(Namco_Read5800) -{ - return(IRQCount>>8); -} - -static void FASTAPASS(2) DoNTARAMROM(int w, uint8 V) -{ - mapbyte2[w]=V; - //if(V>=0xE0) - // setntamem(NTARAM+((V&1)<<10), 1, w); - if((V>=0xE0)) // || ((gorko>>(6+(w>>1)))&1) ) - setntamem(NTARAM+((V&1)<<10), 1, w); - else - { - V&=CHRmask1[0]; - setntamem(VROM+(V<<10), 0, w); - } -// else -// setntamem(NTARAM+((V&1)<<10), 1, w); -} - -static void FixNTAR(void) -{ - int x; - - for(x=0;x<4;x++) - DoNTARAMROM(x,mapbyte2[x]); -} - -static void FASTAPASS(2) DoCHRRAMROM(int x, uint8 V) -{ - mapbyte3[x]=V; - if(!((gorfus>>((x>>2)+6))&1) && (V>=0xE0)) - VRAM_BANK1(x<<10,V&7); - else - VROM_BANK1(x<<10,V); -} - -static void FixCRR(void) -{ - int x; - for(x=0;x<8;x++) - DoCHRRAMROM(x,mapbyte3[x]); -} - -static DECLFW(Mapper19_write) -{ - A&=0xF800; - - if(A>=0x8000 && A<=0xb800) - DoCHRRAMROM((A-0x8000)>>11,V); - else if(A>=0xC000 && A<=0xd800) - DoNTARAMROM((A-0xC000)>>11,V); - else switch(A) - { - case 0x4800: - if(dopol&0x40) - { - if(FSettings.SndRate) - { - NamcoSoundHack(); - GameExpSound.Fill=NamcoSound; - } - } - MapperExRAM[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; - //FixNTAR(); - ROM_BANK8(0x8000,V); - X6502_Rebase(); - break; - case 0xE800:gorfus=V&0xC0; - FixCRR(); - ROM_BANK8(0xA000,V); - X6502_Rebase(); - break; - case 0xF000: - ROM_BANK8(0xC000,V); - X6502_Rebase(); - break; - } -} - -static int dwave=0; -static void DoNamcoSound(uint32 *Wave, int Count); - -static void NamcoSoundHack(void) -{ - int32 z,a; - - 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 uint8 PlayIndex[8]; -static int32 vcount[8]; - -static void DoNamcoSound(uint32 *Wave, int Count) -{ - int P,V; - - - //FCEU_DispMessage("%d",MapperExRAM[0x7F]>>4); - for(P=7;P>=7-((MapperExRAM[0x7F]>>4)&7);P--) - { - if((MapperExRAM[0x44+(P<<3)]&0xE0) && (MapperExRAM[0x47+(P<<3)]&0xF)) - { - uint32 freq; - int32 vco; - uint32 duff,duff2,lengo,envelope; - //uint64 ta; - - vco=vcount[P]; - freq=MapperExRAM[0x40+(P<<3)]; - freq|=MapperExRAM[0x42+(P<<3)]<<8; - freq|=(MapperExRAM[0x44+(P<<3)]&3)<<16; - - if(!freq) continue; - - { - int c=((MapperExRAM[0x7F]>>4)&7)+1; - - inc=(long double)(FSettings.SndRate<<15)/((long double)freq* - 21477272/((long double)0x400000*c*45)); - } - - envelope=((MapperExRAM[0x47+(P<<3)]&0xF)<<18)/15; - duff=MapperExRAM[(((MapperExRAM[0x46+(P<<3)]+PlayIndex[P])>>1)&0xFF)]; - if((MapperExRAM[0x46+(P<<3)]+PlayIndex[P])&1) - duff>>=4; - duff&=0xF; - duff2=(duff*envelope)>>14; - - lengo=((8-((MapperExRAM[0x44+(P<<3)]>>2)&7)))<<2; - for(V=0;V=inc) - { - PlayIndex[P]++; - if(PlayIndex[P]>=lengo) - PlayIndex[P]=0; - vco-=inc; - duff=MapperExRAM[(((MapperExRAM[0x46+(P<<3)]+PlayIndex[P])&0xFF)>>1)]; - if((MapperExRAM[0x46+(P<<3)]+PlayIndex[P])&1) - duff>>=4; - duff&=0xF; - duff2=(duff*envelope)>>14; - } - Wave[V>>4]+=duff2; - vco+=0x8000; - } - vcount[P]=vco; - } - } -} - -static void Mapper19_StateRestore(int version) -{ - FixNTAR(); - if(version>=80) - FixCRR(); -} - -static void M19SC(void) -{ - if(FSettings.SndRate) - Mapper19_ESI(); -} - -void Mapper19_ESI(void) -{ - GameExpSound.RChange=M19SC; - SetWriteHandler(0xf800,0xffff,Mapper19_write); - SetWriteHandler(0x4800,0x4fff,Mapper19_write); - SetReadHandler(0x4800,0x4fff,Namco_Read4800); -} - -void Mapper19_init(void) -{ - if(!Mirroring) - { - DoNTARAMROM(0,0xE0); - DoNTARAMROM(1,0xE0); - DoNTARAMROM(2,0xE1); - DoNTARAMROM(3,0xE1); - } - else - { - DoNTARAMROM(0,0xE0); - DoNTARAMROM(2,0xE0); - DoNTARAMROM(1,0xE1); - DoNTARAMROM(3,0xE1); - } - VROM_BANK8(~0); - SetWriteHandler(0x8000,0xffff,Mapper19_write); - SetWriteHandler(0x4020,0x5fff,Mapper19_write); - SetReadHandler(0x4800,0x4fff,Namco_Read4800); - SetReadHandler(0x5000,0x57ff,Namco_Read5000); - SetReadHandler(0x5800,0x5fff,Namco_Read5800); - - MapIRQHook=NamcoIRQHook; - MapStateRestore=Mapper19_StateRestore; - GameExpSound.RChange=M19SC; - if(FSettings.SndRate) - Mapper19_ESI(); - gorfus=0xFF; -} - diff --git a/mappers/193.c b/mappers/193.c new file mode 100644 index 0000000..0afa247 --- /dev/null +++ b/mappers/193.c @@ -0,0 +1,20 @@ +#include "mapinc.h" + +static DECLFW(m193w) +{ + //printf("$%04x:$%02x\n",A,V); + switch(A&3) + { + case 0:VROM_BANK4(0x0000,V>>2);break; + case 1:VROM_BANK2(0x1000,V>>1);break; + case 2:VROM_BANK2(0x1800,V>>1);break; + case 3:ROM_BANK8(0x8000,V);break; + } +} + +void Mapper193_init(void) +{ + ROM_BANK32(~0); + SetWriteHandler(0x4018,0x7fff,m193w); + SetReadHandler(0x4018,0x7fff,0); +} diff --git a/mappers/200.c b/mappers/200.c new file mode 100644 index 0000000..ec13308 --- /dev/null +++ b/mappers/200.c @@ -0,0 +1,36 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2003 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 DECLFW(Mapper200_write) +{ +// FCEU_printf("%04x, %02x\n",A,V); + ROM_BANK16(0x8000,A&0x07); + ROM_BANK16(0xC000,A&0x07); + VROM_BANK8(A&0x07); + MIRROR_SET((A&0x08)>>3); +} + +void Mapper200_init(void) +{ + SetWriteHandler(0x8000,0xffff,Mapper200_write); +} + diff --git a/mappers/201.c b/mappers/201.c new file mode 100644 index 0000000..03e77e6 --- /dev/null +++ b/mappers/201.c @@ -0,0 +1,44 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2003 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 DECLFW(Mapper201_write) +{ +// FCEU_printf("%04x, %02x\n",A,V); + if(A&0x08) + { + ROM_BANK32(A&0x03); + VROM_BANK8(A&0x03); + } + else + { + ROM_BANK32(0); + VROM_BANK8(0); + } +} + +void Mapper201_init(void) +{ + ROM_BANK32(0); + VROM_BANK8(0); + SetWriteHandler(0x8000,0xffff,Mapper201_write); +} + diff --git a/mappers/202.c b/mappers/202.c new file mode 100644 index 0000000..cac2a88 --- /dev/null +++ b/mappers/202.c @@ -0,0 +1,39 @@ +/* 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 "mapinc.h" + +static DECLFW(Mapper202_write) +{ + int tmp=(A>>1)&0x7; + + MIRROR_SET(A&1); + ROM_BANK16(0x8000,tmp); + ROM_BANK16(0xc000,tmp+(((tmp&0x6)==0x6)?1:0)); + VROM_BANK8(tmp); +} + +void Mapper202_init(void) +{ + ROM_BANK16(0x8000,0); + ROM_BANK16(0xc000,0); + VROM_BANK8(0); + SetWriteHandler(0x8000,0xFFFF,Mapper202_write); +} diff --git a/mappers/203.c b/mappers/203.c new file mode 100644 index 0000000..6ab5d52 --- /dev/null +++ b/mappers/203.c @@ -0,0 +1,36 @@ +/* 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 "mapinc.h" + +static DECLFW(Mapper203_write) +{ + ROM_BANK16(0x8000,(V>>2)&3); + ROM_BANK16(0xc000,(V>>2)&3); + VROM_BANK8(V&3); +} + +void Mapper203_init(void) +{ + ROM_BANK16(0x8000,0); + ROM_BANK16(0xc000,0); + VROM_BANK8(0); + SetWriteHandler(0x8000,0xFFFF,Mapper203_write); +} diff --git a/mappers/204.c b/mappers/204.c new file mode 100644 index 0000000..3d79918 --- /dev/null +++ b/mappers/204.c @@ -0,0 +1,38 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2003 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 DECLFW(Mapper204_write) +{ + int tmp2=A&0x6; + int tmp1=tmp2+((tmp2==0x6)?0:(A&1)); + MIRROR_SET((A>>4)&1); + ROM_BANK16(0x8000,tmp1); + ROM_BANK16(0xc000,tmp2+((tmp2==0x6)?1:(A&1))); + VROM_BANK8(tmp1); +} + +void Mapper204_init(void) +{ + ROM_BANK32(~0); + VROM_BANK8(~0); + SetWriteHandler(0x8000,0xFFFF,Mapper204_write); +} diff --git a/mappers/208.c b/mappers/208.c new file mode 100644 index 0000000..29b7efe --- /dev/null +++ b/mappers/208.c @@ -0,0 +1,139 @@ +/* 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 "mapinc.h" + +static uint8 PRGSel; +static uint8 PBuf[4],PSel; +static uint8 cmd; +static uint8 DRegs[8]; +static uint32 count=0; +static uint32 last=0; + +static DECLFW(M208Write1) +{ + PRGSel=(V&0x1)|((V>>3)&0x2); + setprg32(0x8000,PRGSel); +} + +static DECLFW(M208Write2) +{ + 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 + + }; + if(A<=0x57FF) PSel=V; + else + PBuf[(A&0x03)]=V^lut[PSel]; +} + +static DECLFR(M208Read) +{ + return(PBuf[(A&0x3)]); +} + +static void Sync(void) +{ + int x; + + setchr2(0x0000,DRegs[0]>>1); + setchr2(0x0800,DRegs[1]>>1); + for(x=0;x<4;x++) + setchr1(0x1000+x*0x400,DRegs[2+x]); +} + +static DECLFW(M208HWrite) +{ + switch(A&0xe001) + { + case 0xc000:IRQLatch=IRQCount=V;break; + case 0xc001:IRQCount=IRQLatch;last=count=0;break; + case 0xe000:IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break; + case 0xe001:IRQa=1;break; + case 0x8000:cmd=V;break; + case 0x8001:DRegs[cmd&7]=V; + Sync(); + break; + + } +} + +static void M208Power(void) +{ + PRGSel=3; + setprg32(0x8000,3); + SetWriteHandler(0x4800,0x4FFF,M208Write1); + SetWriteHandler(0x5000,0x5fff,M208Write2); + SetWriteHandler(0x8000,0xFFFF,M208HWrite); + SetReadHandler(0x5800,0x5FFF,M208Read); + SetReadHandler(0x8000,0xffff,CartBR); +} + +static void sl(void) +{ + if(IRQa) + { + if(IRQCount>=0) + { + IRQCount--; + if(IRQCount<0) + { + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +static void FP_FASTAPASS(1) foo(uint32 A) +{ + if((A&0x2000) && !(last&0x2000)) + { + count++; + if(count==42) + { + sl(); + count=0; + } + } + last=A; +} + +void Mapper208_Init(CartInfo *info) +{ + info->Power=M208Power; + //GameHBIRQHook=sl; + PPU_hook=foo; +} + diff --git a/mappers/21.c b/mappers/21.c index ba20a86..8d60d4c 100644 --- a/mappers/21.c +++ b/mappers/21.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -28,24 +28,20 @@ static int acount=0; DECLFW(Mapper21_write) { - A|=((A>>5)&0xF); + A|=((A>>5)&0xF); - if((A&0xF000)==0xA000) - { - ROM_BANK8(0xA000,V); - X6502_Rebase(); - } - else if((A&0xF000)==0x8000) - { + if((A&0xF000)==0xA000) + ROM_BANK8(0xA000,V); + else if((A&0xF000)==0x8000) + { if(K4sel&2) ROM_BANK8(0xC000,V); else ROM_BANK8(0x8000,V); - X6502_Rebase(); - } - else if(A>=0xb000 && A<=0xefff) - { - A&=0xF006; + } + else if(A>=0xb000 && A<=0xefff) + { + A&=0xF006; { int x=((A>>2)&1)|((A-0xB000)>>11); @@ -54,47 +50,50 @@ DECLFW(Mapper21_write) VROM_BANK1(x<<10,K4buf[x]); } - } - else switch(A&0xF006) + } + else switch(A&0xF006) { - case 0x9000: - switch(V&0x3) - { - case 0:MIRROR_SET(0);break; - case 1:MIRROR_SET(1);break; - case 2:onemir(0);break; - case 3:onemir(1);break; - } - break; - case 0x9006: - case 0x9004: - case 0x9002:if((K4sel&2)!=(V&2)) - { - uint8 swa; - swa=PRGBankList[0]; - ROM_BANK8(0x8000,PRGBankList[2]); - ROM_BANK8(0xc000,swa); - X6502_Rebase(); - } - K4sel=V; - break; - case 0xf000:IRQLatch&=0xF0;IRQLatch|=V&0xF;break; + case 0x9000: + switch(V&0x3) + { + case 0:MIRROR_SET(0);break; + case 1:MIRROR_SET(1);break; + case 2:onemir(0);break; + case 3:onemir(1);break; + } + break; + case 0x9006: + case 0x9004: + case 0x9002:if((K4sel&2)!=(V&2)) + { + uint8 swa; + swa=PRGBankList[0]; + ROM_BANK8(0x8000,PRGBankList[2]); + ROM_BANK8(0xc000,swa); + } + K4sel=V; + break; + case 0xf000:IRQLatch&=0xF0;IRQLatch|=V&0xF;break; case 0xf002:IRQLatch&=0x0F;IRQLatch|=V<<4;break; - case 0xf004:IRQCount=IRQLatch; - IRQa=V&2;K4IRQ=V&1;break; - case 0xf006:IRQa=K4IRQ;break; + case 0xf004:IRQCount=IRQLatch;acount=0; + IRQa=V&2;K4IRQ=V&1; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xf006:IRQa=K4IRQ;X6502_IRQEnd(FCEU_IQEXT);break; } } static void FP_FASTAPASS(1) KonamiIRQHook(int a) { - #define LCYCS 114 + #define LCYCS ((227*2)+1) + //#define LCYCS 341 if(IRQa) - { - acount+=a; + { +// acount+=a*3; + acount+=a*4; if(acount>=LCYCS) { doagainbub:acount-=LCYCS;IRQCount++; - if(IRQCount&0x100) {TriggerIRQ();IRQCount=IRQLatch;} + if(IRQCount&0x100) {X6502_IRQBegin(FCEU_IQEXT);IRQCount=IRQLatch;} if(acount>=LCYCS) goto doagainbub; } } diff --git a/mappers/211.c b/mappers/211.c new file mode 100644 index 0000000..5e6c5b2 --- /dev/null +++ b/mappers/211.c @@ -0,0 +1,146 @@ +#include "mapinc.h" + +static uint8 mul[2]; +static uint8 regie; +#define tkcom1 mapbyte1[1] +#define tkcom2 mapbyte1[2] +#define tkcom3 mapbyte1[3] + +#define prgb mapbyte2 +#define chr mapbyte3 + +static uint16 names[4]; +static uint8 tekker; + +static DECLFR(tekread) +{ +// FCEU_printf("READ READ READ: $%04x, $%04x, $%04x\n",A,X.PC,tekker); + switch(A) + { + case 0x5000:return(tekker); + case 0x5800:return(mul[0]*mul[1]); + case 0x5801:return((mul[0]*mul[1])>>8); + case 0x5803:return(regie); + default:break; + } + return(X.DB); +} + +static void mira(void) +{ + int x; + if(tkcom1&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(((tkcom3&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); + } + } +} + +static void tekprom(void) +{ + switch(tkcom1&3) + { + case 1: // 16 KB + ROM_BANK16(0x8000,prgb[0]); + ROM_BANK16(0xC000,prgb[2]); + break; + + case 2: //2 = 8 KB ?? + ROM_BANK8(0x8000,prgb[0]); + ROM_BANK8(0xa000,prgb[1]); + ROM_BANK8(0xc000,prgb[2]); + ROM_BANK8(0xe000,~0); + break; + } +} + +static void tekvrom(void) +{ + int x; + switch(tkcom1&0x18) + { + case 0x00: // 8KB + setchr8(chr[0]); + break; + case 0x08: // 4KB + for(x=0;x<8;x+=4) + setchr4(x<<10,chr[x]); + break; + case 0x10: // 2KB + for(x=0;x<8;x+=2) + setchr2(x<<10,chr[x]); + break; + case 0x18: // 1KB + for(x=0;x<8;x++) + setchr1(x<<10,chr[x]); + break; + } +} + +static DECLFW(Mapper211_write) +{ + if(A==0x5800) mul[0]=V; + else if(A==0x5801) mul[1]=V; + else if(A==0x5803) regie=V; + + A&=0xF007; + if(A>=0x8000 && A<=0x8003) + { + prgb[A&3]=V; + tekprom(); + } + else if(A>=0x9000 && A<=0x9007) + { + chr[A&7]=V; + tekvrom(); + } + else if(A>=0xb000 && A<=0xb007) + { + names[A&3]=V&3; + mira(); + } + else switch(A) + { + case 0xc002:IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break; + case 0xc003: + case 0xc004:if(!IRQa) {IRQa=1;IRQCount=IRQLatch;} break; + case 0xc005:IRQCount=IRQLatch=V; + X6502_IRQEnd(FCEU_IQEXT);break; + case 0xd000: tkcom1=V; mira(); break; + case 0xd001: tkcom3=V; mira(); break; + } +} + +static void Mapper211_hb(void) +{ + if(IRQCount) IRQCount--; + if(!IRQCount) + { + if(IRQa) X6502_IRQBegin(FCEU_IQEXT); + IRQa=0; + } +} +static void togglie() +{ + tekker^=0xFF; +} + +void Mapper211_init(void) +{ + tekker=0xFF; + MapperReset=togglie; + SetWriteHandler(0x5000,0xffff,Mapper211_write); + SetReadHandler(0x5000,0x5fff,tekread); + GameHBIRQHook=Mapper211_hb; +} + diff --git a/mappers/212.c b/mappers/212.c new file mode 100644 index 0000000..b069fc3 --- /dev/null +++ b/mappers/212.c @@ -0,0 +1,23 @@ +#include "mapinc.h" + +static DECLFW(Mapper212_write) +{ + if((A&0x4000)==0x4000) + { + ROM_BANK32((A&6)>>1); + } + else + { + ROM_BANK16(0x8000,A&7); + ROM_BANK16(0xc000,A&7); + } + VROM_BANK8(A&7); + MIRROR_SET((A>>3)&1); +} + +void Mapper212_init(void) +{ + ROM_BANK32(~0); + VROM_BANK8(~0); + SetWriteHandler(0x8000,0xFFFF,Mapper212_write); +} diff --git a/mappers/213.c b/mappers/213.c new file mode 100644 index 0000000..e0b8d82 --- /dev/null +++ b/mappers/213.c @@ -0,0 +1,14 @@ +#include "mapinc.h" + +static DECLFW(Mapper213_write) +{ + ROM_BANK32((A>>1)&3); + VROM_BANK8((A>>3)&7); +} + +void Mapper213_init(void) +{ + ROM_BANK32(0); + VROM_BANK8(0); + SetWriteHandler(0x8000,0xFFFF,Mapper213_write); +} diff --git a/mappers/214.c b/mappers/214.c new file mode 100644 index 0000000..03a73ce --- /dev/null +++ b/mappers/214.c @@ -0,0 +1,17 @@ +#include "mapinc.h" + +static DECLFW(Mapper214_write) +{ +// FCEU_printf("%02x:%02x\n",A,V); + ROM_BANK16(0x8000,(A>>2)&3); + ROM_BANK16(0xC000,(A>>2)&3); + VROM_BANK8(A&3); +} + +void Mapper214_init(void) +{ + ROM_BANK16(0x8000,0); + ROM_BANK16(0xC000,0); + VROM_BANK8(0); + SetWriteHandler(0x8000,0xFFFF,Mapper214_write); +} diff --git a/mappers/215.c b/mappers/215.c new file mode 100644 index 0000000..772691c --- /dev/null +++ b/mappers/215.c @@ -0,0 +1,96 @@ +/* +#include "mapinc.h" + +static uint8 cmdin; +static uint8 cmd; +static uint8 regs[8]; +static uint8 master,chrm; + +static void DoPRG215(void) +{ + if(master&0x80) + { + setprg16(0x8000,master&0x1F); + setprg16(0xc000,master&0x1F); + } + else + { + setprg8(0x8000,regs[4]); 6 + setprg8(0xA000,regs[6]); 7 0, 2, 5, 3, 6, 1, 7, 4 + setprg8(0xC000,~1); + setprg8(0xE000,~0); + } + +} + +static void DoCHR215(void) +{ + uint32 base=(cmd&0x80)<<5; + int orie=(chrm&0x4)<<6; + + setchr2(0x0000^base,(orie|regs[0])>>1); 0 + setchr2(0x0800^base,(orie|regs[5])>>1); 1 + + setchr1(0x1000,orie|regs[1]); 2 + setchr1(0x1400,orie|regs[3]); 3 + setchr1(0x1800,orie|regs[7]); 4 + setchr1(0x1c00,orie|regs[2]); 5 +} + +static DECLFW(Write215_write) +{ + switch(A&0xF001) + { + case 0xF001:IRQCount=V+2;break; + case 0xF000:X6502_IRQEnd(FCEU_IQEXT);break; + } + if(A==0x5000) + { + master=V; + DoPRG215(); +// DoCHR215(); + } + else if(A==0x5001) + { + chrm=V; + DoCHR215(); + } + else + switch(A&0xE001) + { + case 0xC000:setmirror(((V|(V>>7))&1)^1);break; + case 0xa000:cmd=V;cmdin=1;DoCHR215();break; + case 0x8001:if(!cmdin) break; + regs[cmd&7]=V; + DoPRG215(); + DoCHR215(); + cmdin=0; + break; + } +} + +static void hooko215(void) +{ + if(IRQCount) + { + IRQCount--; + if(!IRQCount) + { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +void Mapper215_init(void) +{ + int x; + for(x=0;x<8;x++) regs[x]=0; + master=chrm=cmd=cmdin=IRQCount=0; + GameHBIRQHook=hooko215; + SetReadHandler(0x8000,0xFFFF,CartBR); + SetWriteHandler(0x5000,0xFFFF,Write215_write); + DoPRG215(); + DoCHR215(); +} + +*/ diff --git a/mappers/217.c b/mappers/217.c new file mode 100644 index 0000000..6f7a251 --- /dev/null +++ b/mappers/217.c @@ -0,0 +1,96 @@ +/* +#include "mapinc.h" + +static uint8 cmdin; +static uint8 cmd; +static uint8 regs[8]; +static uint8 master,chrm; + +static void DoPRG217(void) +{ + if(master&0x80) + { + setprg16(0x8000,master&0x1F); + setprg16(0xc000,master&0x1F); + } + else + { + setprg8(0x8000,regs[1]); + setprg8(0xA000,regs[3]); + setprg8(0xC000,~1); + setprg8(0xE000,~0); + } +} + +static void DoCHR217(void) +{ + uint32 base=(cmd&0x80)<<5; + int orie=(chrm&0x4)<<6; + + setchr2(0x0000^base,(orie|regs[0])>>1); + setchr2(0x0800^base,(orie|regs[7])>>1); + + setchr1(0x1000,orie|regs[5]); + setchr1(0x1400,orie|regs[2]); + setchr1(0x1800,orie|regs[6]); + setchr1(0x1c00,orie|regs[4]); +} + +static DECLFW(Write217_write) +{ +// if(A==0x5000) +// { +// master=V; +// DoPRG217(); +// } +// else if(A==0x5001) +// { +// chrm=V; +// DoCHR217(); +// } +// else if(A==0x5007) +// { +// } + + switch(A&0xE001) + { + case 0x4000:master=V;DoPRG217();break; + case 0x8000:IRQCount=V;break; + case 0xc001:break; + case 0xe000:X6502_IRQEnd(FCEU_IQEXT);break; + case 0xe001:break; + case 0xa001:setmirror((V&1)^1);break; + case 0x8001:cmd=V;cmdin=1;DoPRG217();DoCHR217();break; + case 0xa000:if(!cmdin) break; + regs[cmd&7]=V; + DoPRG217(); + DoCHR217(); + cmdin=0; + break; + } +} + +static void hooko217(void) +{ + if(IRQCount) + { + IRQCount--; + if(!IRQCount) + { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +void Mapper217_init(void) +{ + int x; + for(x=0;x<8;x++) regs[x]=0; + master=chrm=cmd=cmdin=IRQCount=0; + GameHBIRQHook=hooko217; + SetReadHandler(0x8000,0xFFFF,CartBR); + SetWriteHandler(0x5000,0xFFFF,Write217_write); + DoPRG217(); + DoCHR217(); +} +*/ \ No newline at end of file diff --git a/mappers/22.c b/mappers/22.c index a40e05f..4a08094 100644 --- a/mappers/22.c +++ b/mappers/22.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -30,12 +30,10 @@ DECLFW(Mapper22_write) { switch(A&0xF000) { - case 0x8000:ROM_BANK8(0x8000,V); - X6502_Rebase();break; - case 0xa000:ROM_BANK8(0xA000,V); - X6502_Rebase();break; + case 0x8000:ROM_BANK8(0x8000,V);break; + case 0xa000:ROM_BANK8(0xA000,V);break; case 0x9000:switch(V&3) - { + { case 0x00:MIRROR_SET2(1);break; case 0x01:MIRROR_SET2(0);break; case 0x02:onemir(0);break; @@ -46,20 +44,20 @@ DECLFW(Mapper22_write) } else { - A&=0xF003; - if(A>=0xb000 && A<=0xe003) - { - int x=(A&1)|((A-0xB000)>>11); + A&=0xF003; + if(A>=0xb000 && A<=0xe003) + { + int x=(A&1)|((A-0xB000)>>11); - K4buf[x]&=(0xF0)>>((A&2)<<1); - K4buf[x]|=(V&0xF)<<((A&2)<<1); - VROM_BANK1(x<<10,K4buf[x]>>1); - } + K4buf[x]&=(0xF0)>>((A&2)<<1); + K4buf[x]|=(V&0xF)<<((A&2)<<1); + VROM_BANK1(x<<10,K4buf[x]>>1); + } } } void Mapper22_init(void) { - SetWriteHandler(0x8000,0xffff,Mapper22_write); + SetWriteHandler(0x8000,0xffff,Mapper22_write); } diff --git a/mappers/225.c b/mappers/225.c index 23992fc..14e38f2 100644 --- a/mappers/225.c +++ b/mappers/225.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -76,7 +76,6 @@ DECLFW(Mapper225_write) { ROM_BANK32(((((A>>7)&0x1F)+(banks<<5)))); } - X6502_Rebase(); } void Mapper225_init(void) diff --git a/mappers/226.c b/mappers/226.c index 45dc067..bde4f52 100644 --- a/mappers/226.c +++ b/mappers/226.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -31,7 +31,6 @@ static void DoPRG(void) } else ROM_BANK32(b); - X6502_Rebase(); } static DECLFW(Mapper226_write) @@ -75,7 +74,7 @@ void Mapper226_init(void) M26Reset(); } -#ifdef OLD // What the heck is this?? +#ifdef OLD // What the heck is this?? DECLFW(Mapper226_write) { MIRROR_SET((A>>13)&1); diff --git a/mappers/227.c b/mappers/227.c index 2754369..457e79e 100644 --- a/mappers/227.c +++ b/mappers/227.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -30,11 +30,11 @@ static void DoSync(uint32 A) rg[1]=A>>8; MIRROR_SET((A>>1)&1); - if(A&1) //32 KB + if(A&1) //32 KB { ROM_BANK32(p); } - else //16 KB + else //16 KB { ROM_BANK16(0x8000,(p<<1)|((A&4)>>2)); ROM_BANK16(0xc000,(p<<1)|((A&4)>>2)); @@ -51,7 +51,6 @@ static void DoSync(uint32 A) else ROM_BANK16(0xC000,(p<<1)&(~7)); } - X6502_Rebase(); } static DECLFW(Mapper227_write) @@ -73,7 +72,7 @@ static void M227Restore(int version) void Mapper227_init(void) { - SetWriteHandler(0x8000,0xffff,Mapper227_write); + SetWriteHandler(0x6000,0xffff,Mapper227_write); MapperReset=M227Reset; GameStateRestore=M227Restore; M227Reset(); diff --git a/mappers/228.c b/mappers/228.c index e38063d..bfae3a6 100644 --- a/mappers/228.c +++ b/mappers/228.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -27,16 +27,16 @@ static DECLFW(Mapper228_write) MIRROR_SET((A>>13)&1); page=(A>>7)&0x3F; + //printf("%04x\n",A); if((page&0x30)==0x30) page-=0x10; - + pagel=pageh=(page<<1) + (((A>>6)&1)&((A>>5)&1)); pageh+=((A>>5)&1)^1; ROM_BANK16(0x8000,pagel); ROM_BANK16(0xC000,pageh); VROM_BANK8( (V&0x3) | ((A&0xF)<<2) ); - X6502_Rebase(); } static void A52Reset(void) diff --git a/mappers/229.c b/mappers/229.c index 46c898b..a78dd73 100644 --- a/mappers/229.c +++ b/mappers/229.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -37,7 +37,6 @@ else ROM_BANK16(0xC000,A&0x1f); } VROM_BANK8(A); - X6502_Rebase(); } } diff --git a/mappers/23.c b/mappers/23.c index db96e8e..d61a555 100644 --- a/mappers/23.c +++ b/mappers/23.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -23,8 +23,8 @@ #define K4buf mapbyte2 #define K4IRQ mapbyte1[1] #define K4sel mapbyte1[0] - -DECLFW(Mapper23_write) +static int acount=0; +static DECLFW(Mapper23_write) { if((A&0xF000)==0x8000) { @@ -32,13 +32,9 @@ DECLFW(Mapper23_write) ROM_BANK8(0xC000,V); else ROM_BANK8(0x8000,V); - X6502_Rebase(); - } + } else if((A&0xF000)==0xA000) - { ROM_BANK8(0xA000,V); - X6502_Rebase(); - } else { A|=((A>>2)&0x3)|((A>>4)&0x3)|((A>>6)&0x3); @@ -56,7 +52,7 @@ DECLFW(Mapper23_write) { case 0xf000:X6502_IRQEnd(FCEU_IQEXT);IRQLatch&=0xF0;IRQLatch|=V&0xF;break; case 0xf001:X6502_IRQEnd(FCEU_IQEXT);IRQLatch&=0x0F;IRQLatch|=V<<4;break; - case 0xf002:X6502_IRQEnd(FCEU_IQEXT);IRQCount=IRQLatch;IRQa=V&2;K4IRQ=V&1;break; + case 0xf002:X6502_IRQEnd(FCEU_IQEXT);acount=0;IRQCount=IRQLatch;IRQa=V&2;K4IRQ=V&1;break; case 0xf003:X6502_IRQEnd(FCEU_IQEXT);IRQa=K4IRQ;break; case 0x9001: case 0x9002: @@ -67,34 +63,34 @@ DECLFW(Mapper23_write) swa=PRGBankList[0]; ROM_BANK8(0x8000,PRGBankList[2]); ROM_BANK8(0xc000,swa); - X6502_Rebase(); } K4sel=V; break; case 0x9000: - switch(V&0x3) - { + if(V!=0xFF) + switch(V&0x3) + { case 0:MIRROR_SET(0);break; - case 1:MIRROR_SET(1);break; - case 2:onemir(0);break; - case 3:onemir(1);break; - } - break; + case 1:MIRROR_SET(1);break; + case 2:onemir(0);break; + case 3:onemir(1);break; + } + break; } } } void FP_FASTAPASS(1) KonamiIRQHook2(int a) { - static int acount=0; + #define LCYCS 341 if(IRQa) - { - acount+=(a<<1)+a; - if(acount>=342) + { + acount+=a*3; + if(acount>=LCYCS) { - doagainbub:acount-=342;IRQCount++; + doagainbub:acount-=LCYCS;IRQCount++; if(IRQCount&0x100) {X6502_IRQBegin(FCEU_IQEXT);IRQCount=IRQLatch;} - if(acount>=342) goto doagainbub; + if(acount>=LCYCS) goto doagainbub; } } } diff --git a/mappers/230.c b/mappers/230.c new file mode 100644 index 0000000..cbf1fbe --- /dev/null +++ b/mappers/230.c @@ -0,0 +1,62 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2003 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 rom_sw mapbyte1[0] + +void Mapper230_Reset(void) +{ + rom_sw ^= 1; //1 - rom_sw; + + if( rom_sw ) { + ROM_BANK16(0x8000,0); + ROM_BANK16(0xc000,7); + } else { + ROM_BANK16(0x8000,8); + ROM_BANK16(0xc000,39); + } + MIRROR_SET2(1); +} + +static DECLFW(Mapper230_write) +{ + if( rom_sw ) { + ROM_BANK16( 0x8000, V&0x07 ); + } else { + if( V & 0x20 ) { + ROM_BANK16( 0x8000, (V&0x1F)+8 ); + ROM_BANK16( 0xc000, (V&0x1F)+8 ); + } else { + ROM_BANK32( ((V&0x1E) >> 1) + 4 ); + } + MIRROR_SET2( ((V & 0x40) >> 6) ); + } +} + +void Mapper230_init(void) +{ + ROM_BANK16(0x8000,0); + ROM_BANK16(0xc000,7); + SetWriteHandler(0x8000, 0xffff, Mapper230_write); + MapperReset = Mapper230_Reset; + rom_sw = 1; +} + diff --git a/mappers/231.c b/mappers/231.c new file mode 100644 index 0000000..9b8d1fc --- /dev/null +++ b/mappers/231.c @@ -0,0 +1,41 @@ +/* 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 "mapinc.h" + +static DECLFW(Mapper231_write) +{ + if(A&0x20) + ROM_BANK32((A>>1)&0xF); + else + { + ROM_BANK16(0x8000,(A&0x1E)); + ROM_BANK16(0xc000,(A&0x1E)); + } + MIRROR_SET((A>>7)&1); +} + +void Mapper231_init(void) +{ + ROM_BANK16(0x8000,0); + ROM_BANK16(0xc000,0); + SetWriteHandler(0x8000,0xffff,Mapper231_write); +} + diff --git a/mappers/232.c b/mappers/232.c index 5084ba4..548db8c 100644 --- a/mappers/232.c +++ b/mappers/232.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -24,16 +24,15 @@ static void DoIt(void) { ROM_BANK16(0x8000,(mapbyte1[1]&3) | ((mapbyte1[0]&0x18)>>1)); ROM_BANK16(0xc000,3|(((mapbyte1[0])&0x18)>>1)); - X6502_Rebase(); } DECLFW(Mapper232_write) { - if(A<=0x9FFF) - mapbyte1[0]=V; - else - mapbyte1[1]=V; - DoIt(); + if(A<=0x9FFF) + mapbyte1[0]=V; + else + mapbyte1[1]=V; + DoIt(); } static void QuattroReset(void) diff --git a/mappers/234.c b/mappers/234.c index 4a2b9ee..d8ca53f 100644 --- a/mappers/234.c +++ b/mappers/234.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -35,7 +35,6 @@ static void DoBS(void) ROM_BANK32(r1&0xF); VROM_BANK8( ((r1&0xF)<<2) | ((r2>>4)&3) ); } - X6502_Rebase(); } static void R1Set(uint8 V) @@ -92,17 +91,17 @@ static void M15Reset(void) void Mapper234_init(void) { SetWriteHandler(0xff80,0xff9f,R1W); - SetReadHandler(0xff80,0xff9f,R1R); + SetReadHandler(0xff80,0xff9f,R1R); - SetWriteHandler(0xffe8,0xfff7,R2W); - SetReadHandler(0xffe8,0xfff7,R2R); + SetWriteHandler(0xffe8,0xfff7,R2W); + SetReadHandler(0xffe8,0xfff7,R2R); - SetReadHandler(0x6000,0x7FFF,0); - SetWriteHandler(0x6000,0x7FFF,0); + SetReadHandler(0x6000,0x7FFF,0); + SetWriteHandler(0x6000,0x7FFF,0); - M15Reset(); + M15Reset(); - GameStateRestore=M15Restore; - MapperReset=M15Reset; + GameStateRestore=M15Restore; + MapperReset=M15Reset; } diff --git a/mappers/235.c b/mappers/235.c new file mode 100644 index 0000000..e54907e --- /dev/null +++ b/mappers/235.c @@ -0,0 +1,54 @@ +/* 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 DECLFW(Mapper235_write) +{ + uint32 m; + int z; + + if(A&0x400) + onemir(0); + else + setmirror(((A>>13)&1)^1); + m=A&0x1f; + + z=(A>>8)&3; + + if(A&0x800) + { + setprg16r(0x10|z,0x8000,(m<<1)|((A>>12)&1)); + setprg16r(0x10|z,0xC000,(m<<1)|((A>>12)&1)); + + } + else + setprg32r(0x10|z,0x8000,m); +} + +void Mapper235_init(void) +{ + /* Fixme: Possible crashy bug if header is bad. */ + SetupCartPRGMapping(0x10,PRGptr[0],1024*1024,0); + SetupCartPRGMapping(0x12,PRGptr[0]+1024*1024,1024,0); + setprg32r(0x10,0x8000,0); + SetReadHandler(0x8000,0xffff,CartBROB); + SetWriteHandler(0x8000,0xffff,Mapper235_write); +} diff --git a/mappers/240.c b/mappers/240.c index 0869349..dbbfe19 100644 --- a/mappers/240.c +++ b/mappers/240.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -28,7 +28,6 @@ DECLFW(Mapper240_write) { ROM_BANK32(V>>4); VROM_BANK8(V&0xF); - X6502_Rebase(); } } diff --git a/mappers/241.c b/mappers/241.c new file mode 100644 index 0000000..c0fe7fe --- /dev/null +++ b/mappers/241.c @@ -0,0 +1,27 @@ +#include "mapinc.h" + +static DECLFW(M241wr) +{ +// FCEU_printf("Wr: $%04x:$%02x, $%04x\n",A,V,X.PC); + if(A<0x8000) + { +// printf("$%04x:$%02x, $%04x\n",A,V,X.PC); + } + else + ROM_BANK32(V); +} + +static DECLFR(M241rd) +{ + //DumpMem("out",0x8000,0xffff); + //printf("Rd: $%04x, $%04x\n",A,X.PC); + return(0x50); +} + +void Mapper241_init(void) +{ + ROM_BANK32(0); + SetWriteHandler(0x5000,0x5fff,M241wr); + SetWriteHandler(0x8000,0xFFFF,M241wr); + SetReadHandler(0x4020,0x5fff,M241rd); +} diff --git a/mappers/242.c b/mappers/242.c index 3b4dced..2fa4171 100644 --- a/mappers/242.c +++ b/mappers/242.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -24,7 +24,6 @@ DECLFW(Mapper242_write) { ROM_BANK32((A>>3)&0xF); - X6502_Rebase(); switch(V&3) { case 0:MIRROR_SET(0);break; diff --git a/mappers/244.c b/mappers/244.c new file mode 100644 index 0000000..13ea2c1 --- /dev/null +++ b/mappers/244.c @@ -0,0 +1,38 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2003 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 DECLFW(Mapper244_write_1) +{ + ROM_BANK32((A-0x8065)&0x03); +} + +static DECLFW(Mapper244_write_2) +{ + VROM_BANK8((A-0x80A5)&0x07); +} + +void Mapper244_init(void) +{ + ROM_BANK32(0); + SetWriteHandler(0x8065,0x80a4,Mapper244_write_1); + SetWriteHandler(0x80a5,0x80e4,Mapper244_write_2); +} diff --git a/mappers/246.c b/mappers/246.c index d36b277..8623233 100644 --- a/mappers/246.c +++ b/mappers/246.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -25,14 +25,10 @@ DECLFW(Mapper246_write) { switch(A&0xF007) { - case 0x6000:ROM_BANK8(0x8000,V); - X6502_Rebase();break; - case 0x6001:ROM_BANK8(0xA000,V); - X6502_Rebase();break; - case 0x6002:ROM_BANK8(0xC000,V); - X6502_Rebase();break; - case 0x6003:ROM_BANK8(0xE000,V); - X6502_Rebase();break; + case 0x6000:ROM_BANK8(0x8000,V);break; + case 0x6001:ROM_BANK8(0xA000,V);break; + case 0x6002:ROM_BANK8(0xC000,V);break; + case 0x6003:ROM_BANK8(0xE000,V);break; case 0x6004:VROM_BANK2(0x0000,V);break; case 0x6005:VROM_BANK2(0x0800,V);break; case 0x6006:VROM_BANK2(0x1000,V);break; diff --git a/mappers/248.c b/mappers/248.c deleted file mode 100644 index e2dff8c..0000000 --- a/mappers/248.c +++ /dev/null @@ -1,91 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell - * - * 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 cmd mapbyte1[0] -#define lpa mapbyte1[1] -#define prgl mapbyte2 - -static void PRGSynco(void) -{ - if(lpa&0x80) - { - ROM_BANK16(0x8000,lpa&0xF); - } - else - { - ROM_BANK8(0x8000,prgl[0]&0x1F); - ROM_BANK8(0xa000,prgl[1]&0x1F); - } - X6502_Rebase(); -} - -static DECLFW(Mapper248_writelow) -{ - lpa=V; - PRGSynco(); -} - -static DECLFW(Mapper248_write) -{ - switch(A&0xF001) - { - case 0xa000:MIRROR_SET(V&1);break; // Not sure if this is right. Mirroring may be hard wired... - case 0xc000:IRQLatch=V;break; - case 0xc001:IRQCount=IRQLatch;break; - case 0xe000:IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break; - case 0xe001:IRQa=1;break; - case 0x8000:cmd=V;break; - case 0x8001:switch(cmd&7) - { - case 0:VROM_BANK2(0x000,V>>1);break; - case 1:VROM_BANK2(0x800,V>>1);break; - case 2:VROM_BANK1(0x1000,V);break; - case 3:VROM_BANK1(0x1400,V);break; - case 4:VROM_BANK1(0x1800,V);break; - case 5:VROM_BANK1(0x1c00,V);break; - case 6:prgl[0]=V;PRGSynco();break; - case 7:prgl[1]=V;PRGSynco();break; - } - break; - } -} - -static void Mapper248_hb(void) -{ - if(IRQa) - { - IRQCount--; - if(IRQCount<0) - { - X6502_IRQBegin(FCEU_IQEXT); - IRQCount=IRQLatch; - } - } -} - -void Mapper248_init(void) -{ - SetWriteHandler(0x6000,0x6fff,Mapper248_writelow); - SetWriteHandler(0x8000,0xffff,Mapper248_write); - GameHBIRQHook=Mapper248_hb; -} - diff --git a/mappers/24and26.c b/mappers/24and26.c index 50f732a..3368856 100644 --- a/mappers/24and26.c +++ b/mappers/24and26.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -20,11 +20,9 @@ #include "mapinc.h" +static void (*sfun[3])(void); + #define vrctemp mapbyte1[0] -#define regb000 mapbyte3[0] -#define regb001 mapbyte3[1] -#define regb002 mapbyte3[2] -#define exchstat mapbyte4[0] #define VPSG2 mapbyte3 #define VPSG mapbyte2 @@ -33,81 +31,74 @@ static void DoSQV2(void); static void DoSawV(void); static int swaparoo; -static int32 inc; -static DECLFW(VRC6PSGW90) -{ - DoSQV1();VPSG[0]=V; -} -static DECLFW(VRC6PSGW91) -{ - DoSQV1();VPSG[2]=V; -} -static DECLFW(VRC6PSGW92) -{ - DoSQV1();VPSG[3]=V; -} -static DECLFW(VRC6PSGWA0) -{ - DoSQV2();VPSG[4]=V; -} -static DECLFW(VRC6PSGWA1) -{ - DoSQV2();VPSG[6]=V; -} -static DECLFW(VRC6PSGWA2) -{ - DoSQV2();VPSG[7]=V; -} -static DECLFW(VRC6PSGWB0) -{ - DoSawV();VPSG2[0]=V; -} -static DECLFW(VRC6PSGWB1) -{ - DoSawV();VPSG2[1]=V; -} -static DECLFW(VRC6PSGWB2) -{ - DoSawV();VPSG2[2]=V; -} static int acount=0; static void FP_FASTAPASS(1) KonamiIRQHook(int a) { - #define LCYCS 114 + #define LCYCS 341 +// #define LCYCS ((227*2)+1) if(IRQa) { - acount+=a; + acount+=a*3; if(acount>=LCYCS) { doagainbub:acount-=LCYCS;IRQCount++; - if(IRQCount==0x100) {TriggerIRQ();IRQCount=IRQLatch;} + if(IRQCount==0x100) + { + X6502_IRQBegin(FCEU_IQEXT); + IRQCount=IRQLatch; + } if(acount>=LCYCS) goto doagainbub; } } } -DECLFW(Mapper24_write) +static DECLFW(VRC6SW) { - if(swaparoo) - A=(A&0xFFFC)|((A>>1)&1)|((A<<1)&2); + A&=0xF003; + if(A>=0x9000 && A<=0x9002) + { + VPSG[A&3]=V; + if(sfun[0]) sfun[0](); + } + else if(A>=0xa000 && A<=0xa002) + { + VPSG[4|(A&3)]=V; + if(sfun[1]) sfun[1](); + } + else if(A>=0xb000 && A<=0xb002) + { + VPSG2[A&3]=V; + if(sfun[2]) sfun[2](); + } +} + +static DECLFW(Mapper24_write) +{ + if(swaparoo) + A=(A&0xFFFC)|((A>>1)&1)|((A<<1)&2); + if(A>=0x9000 && A<=0xb002) + { + VRC6SW(A,V); + return; + } + A&=0xF003; +// if(A>=0xF000) printf("%d, %d, $%04x:$%02x\n",scanline,timestamp,A,V); switch(A&0xF003) - { - case 0x8000:ROM_BANK16(0x8000,V); - X6502_Rebase();break; + { + case 0x8000:ROM_BANK16(0x8000,V);break; case 0xB003: - switch(V&0xF) - { - case 0x0:MIRROR_SET2(1);break; - case 0x4:MIRROR_SET2(0);break; - case 0x8:onemir(0);break; - case 0xC:onemir(1);break; - } - break; - case 0xC000:ROM_BANK8(0xC000,V); - X6502_Rebase();break; + switch(V&0xF) + { + case 0x0:MIRROR_SET2(1);break; + case 0x4:MIRROR_SET2(0);break; + case 0x8:onemir(0);break; + case 0xC:onemir(1);break; + } + break; + case 0xC000:ROM_BANK8(0xC000,V);break; case 0xD000:VROM_BANK1(0x0000,V);break; case 0xD001:VROM_BANK1(0x0400,V);break; case 0xD002:VROM_BANK1(0x0800,V);break; @@ -116,113 +107,73 @@ DECLFW(Mapper24_write) case 0xE001:VROM_BANK1(0x1400,V);break; case 0xE002:VROM_BANK1(0x1800,V);break; case 0xE003:VROM_BANK1(0x1c00,V);break; - case 0xF000:IRQLatch=V;break; + case 0xF000:IRQLatch=V; + //acount=0; + break; case 0xF001:IRQa=V&2; vrctemp=V&1; - if(V&2) {IRQCount=IRQLatch;} - //acount=0; + if(V&2) + { + IRQCount=IRQLatch; + acount=0; + } + X6502_IRQEnd(FCEU_IQEXT); break; - case 0xf002:IRQa=vrctemp;break; + case 0xf002:IRQa=vrctemp; + X6502_IRQEnd(FCEU_IQEXT);break; case 0xF003:break; } } -static int CVBC[3]={0,0,0}; -static int32 vcount[2]; +static int32 CVBC[3]; +static int32 vcount[3]; +static int32 dcount[2]; -static void DoSQV1(void) +static INLINE void DoSQV(int x) { - uint8 amp; - int32 freq; - int V; - int32 start,end; - - start=CVBC[0]; - end=(SOUNDTS<<16)/soundtsinc; - if(end<=start) return; - CVBC[0]=end; - - if(VPSG[0x3]&0x80) + int32 V; + int32 amp=(((VPSG[x<<2]&15)<<8)*6/8)>>4; + int32 start,end; + + start=CVBC[x]; + end=(SOUNDTS<<16)/soundtsinc; + if(end<=start) return; + CVBC[x]=end; + + if(VPSG[(x<<2)|0x2]&0x80) + { + if(VPSG[x<<2]&0x80) + { + for(V=start;V>4]+=amp; + } + else + { + int32 thresh=(VPSG[x<<2]>>4)&7; + int32 freq=((VPSG[(x<<2)|0x1]|((VPSG[(x<<2)|0x2]&15)<<8))+1)<<17; + for(V=start;Vthresh) /* Greater than, not >=. Important. */ + Wave[V>>4]+=amp; + vcount[x]-=nesincsize; + while(vcount[x]<=0) /* Should only be <0 in a few circumstances. */ { - amp=(VPSG[0]&15)<<4; - if(VPSG[0]&0x80) - { - for(V=start;V>4]+=amp; - } - else - { - unsigned long dcycs; - freq=(((VPSG[0x2]|((VPSG[0x3]&15)<<8))+1)); - inc=(long double)((unsigned long)((FSettings.SndRate OVERSAMPLE)<<12))/((long double)PSG_base/freq); - switch(VPSG[0]&0x70) - { - default: - case 0x00:dcycs=inc>>4;break; - case 0x10:dcycs=inc>>3;break; - case 0x20:dcycs=(inc*3)>>4;break; - case 0x30:dcycs=inc>>2;break; - case 0x40:dcycs=(inc*5)>>4;break; - case 0x50:dcycs=(inc*6)>>4;break; - case 0x60:dcycs=(inc*7)>>4;break; - case 0x70:dcycs=inc>>1;break; - } - for(V=start;V>4]+=amp; - vcount[0]+=0x1000; - if(vcount[0]>=inc) vcount[0]-=inc; - } - } + vcount[x]+=freq; + dcount[x]=(dcount[x]+1)&15; } + } + } + } } -static void DoSQV2(void) -{ - uint8 amp; - int32 freq; - int V; - int32 start,end; - start=CVBC[1]; - end=(SOUNDTS<<16)/soundtsinc; - if(end<=start) return; - CVBC[1]=end; +static void DoSQV1(void) +{ + DoSQV(0); +} - if(VPSG[0x7]&0x80) - { - amp=(VPSG[4]&15)<<4; - if(VPSG[4]&0x80) - { - for(V=start;V>4]+=amp; - } - else - { - unsigned long dcycs; - freq=(((VPSG[0x6]|((VPSG[0x7]&15)<<8))+1)); - inc=(long double)((unsigned long)((FSettings.SndRate OVERSAMPLE)<<12))/((long double)PSG_base/freq); - switch(VPSG[4]&0x70) - { - default: - case 0x00:dcycs=inc>>4;break; - case 0x10:dcycs=inc>>3;break; - case 0x20:dcycs=(inc*3)>>4;break; - case 0x30:dcycs=inc>>2;break; - case 0x40:dcycs=(inc*5)>>4;break; - case 0x50:dcycs=(inc*6)>>4;break; - case 0x60:dcycs=(inc*7)>>4;break; - case 0x70:dcycs=inc>>1;break; - } - for(V=start;V>4]+=amp; - vcount[1]+=0x1000; - if(vcount[1]>=inc) vcount[1]-=inc; - } - } - } +static void DoSQV2(void) +{ + DoSQV(1); } static void DoSawV(void) @@ -237,7 +188,7 @@ static void DoSawV(void) if(VPSG2[2]&0x80) { - static int64 saw1phaseacc=0; + static int32 saw1phaseacc=0; uint32 freq3; static uint8 b3=0; static int32 phaseacc=0; @@ -247,13 +198,13 @@ static void DoSawV(void) for(V=start;V>3)&0x1f)<<4); + duff=(((phaseacc>>3)&0x1f)<<4)*6/8; } Wave[V>>4]+=duff; } } } -void VRC6Sound(int Count) +#if 0 +static INLINE void DoSQVHQ(int x) { - int x; + int32 V; + int32 amp=((VPSG[x<<2]&15)<<8)*6/8; - DoSQV1(); - DoSQV2(); - DoSawV(); - for(x=0;x<3;x++) - CVBC[x]=Count; + if(VPSG[(x<<2)|0x2]&0x80) + { + if(VPSG[x<<2]&0x80) + { + for(V=CVBC[x];V>4)&7; + for(V=CVBC[x];Vthresh) /* Greater than, not >=. Important. */ + WaveHi[V]+=amp; + vcount[x]--; + if(vcount[x]<=0) /* Should only be <0 in a few circumstances. */ + { + vcount[x]=(VPSG[(x<<2)|0x1]|((VPSG[(x<<2)|0x2]&15)<<8))+1; + dcount[x]=(dcount[x]+1)&15; + } + } + } + } + CVBC[x]=SOUNDTS; } -static int satype=0; +static void DoSQV1HQ(void) +{ + DoSQVHQ(0); +} -void VRC6SoundC(void) +static void DoSQV2HQ(void) { - int x; + DoSQVHQ(1); +} - if(FSettings.SndRate) - VRC6_ESI(satype); - else +static void DoSawVHQ(void) +{ + static uint8 b3=0; + static int32 phaseacc=0; + int32 V; + + if(VPSG2[2]&0x80) + { + for(V=CVBC[2];V>3)&0x1f)<<8)*6/8; + vcount[2]--; + if(vcount[2]<=0) { - SetWriteHandler(0x9000+x,0x9002+x,0); - SetWriteHandler(0xa000+x,0xa002+x,0); - SetWriteHandler(0xb000+x,0xb002+x,0); + vcount[2]=(VPSG2[1]+((VPSG2[2]&15)<<8)+1)<<1; + phaseacc+=VPSG2[0]&0x3f; + b3++; + if(b3==7) + { + b3=0; + phaseacc=0; + } + } } + } + CVBC[2]=SOUNDTS; } +#endif + -void VRC6_ESI(int t) +void VRC6Sound(int Count) { - int x; + int x; - satype=t; + DoSQV1(); + DoSQV2(); + DoSawV(); + for(x=0;x<3;x++) + CVBC[x]=Count; +} - GameExpSound.RChange=VRC6SoundC; +#if 0 +void VRC6SoundHQ(void) +{ + DoSQV1HQ(); + DoSQV2HQ(); + DoSawVHQ(); +} + +void VRC6SyncHQ(int32 ts) +{ + int x; + for(x=0;x<3;x++) CVBC[x]=ts; +} +#endif + +static void VRC6_ESI(void) +{ + GameExpSound.RChange=VRC6_ESI; GameExpSound.Fill=VRC6Sound; + GameExpSound.HiFill=0;//VRC6SoundHQ; + GameExpSound.HiSync=0;//VRC6SyncHQ; + + memset(CVBC,0,sizeof(CVBC)); + memset(vcount,0,sizeof(vcount)); + memset(dcount,0,sizeof(dcount)); if(FSettings.SndRate) - for(x=000;x<0x1000;x+=4) + { +#if 0 + if(FSettings.soundq>=1) + { + sfun[0]=DoSQV1HQ; + sfun[1]=DoSQV2HQ; + sfun[2]=DoSawVHQ; + } + else +#endif { - uint32 a; - - a=0x9000+x; - SetWriteHandler(a,a,VRC6PSGW90); - SetWriteHandler(a+(1^t),a+(1^t),VRC6PSGW91); - SetWriteHandler(a+(2^t),a+(2^t),VRC6PSGW92); - - a=0xa000+x; - SetWriteHandler(a,a,VRC6PSGWA0); - SetWriteHandler(a+(1^t),a+(1^t),VRC6PSGWA1); - SetWriteHandler(a+(2^t),a+(2^t),VRC6PSGWA2); - - a=0xb000+x; - SetWriteHandler(a,a,VRC6PSGWB0); - SetWriteHandler(a+(1^t),a+(1^t),VRC6PSGWB1); - SetWriteHandler(a+(2^t),a+(2^t),VRC6PSGWB2); + sfun[0]=DoSQV1; + sfun[1]=DoSQV2; + sfun[2]=DoSawV; } + } + else + memset(sfun,0,sizeof(sfun)); } void Mapper24_init(void) { SetWriteHandler(0x8000,0xffff,Mapper24_write); - if(FSettings.SndRate) - VRC6_ESI(0); - GameExpSound.RChange=VRC6SoundC; + VRC6_ESI(); MapIRQHook=KonamiIRQHook; - swaparoo=0; + swaparoo=0; } void Mapper26_init(void) { SetWriteHandler(0x8000,0xffff,Mapper24_write); - if(FSettings.SndRate) - VRC6_ESI(3); - GameExpSound.RChange=VRC6SoundC; + VRC6_ESI(); MapIRQHook=KonamiIRQHook; - swaparoo=1; + swaparoo=1; } +void NSFVRC6_Init(void) +{ + VRC6_ESI(); + SetWriteHandler(0x8000,0xbfff,VRC6SW); +} diff --git a/mappers/25.c b/mappers/25.c index 0735b9b..f8c1d73 100644 --- a/mappers/25.c +++ b/mappers/25.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -24,70 +24,70 @@ #define K4IRQ mapbyte1[1] #define K4sel mapbyte1[0] -DECLFW(Mapper25_write) +static int acount=0; +static DECLFW(Mapper25_write) { - A=(A&0xF003)|((A&0xC)>>2); + A=(A&0xF003)|((A&0xC)>>2); - if((A&0xF000)==0xA000) - { - ROM_BANK8(0xA000,V); - X6502_Rebase(); - } - else if(A>=0xB000 && A<=0xEFFF) - { + if((A&0xF000)==0xA000) + ROM_BANK8(0xA000,V); + else if(A>=0xB000 && A<=0xEFFF) + { int x=(A&1)|((A-0xB000)>>11); K4buf[x]&=(0xF0)>>((A&2)<<1); K4buf[x]|=(V&0xF)<<((A&2)<<1); VROM_BANK1(x<<10,K4buf[x]); - } - else if((A&0xF000)==0x8000) - { + } + else if((A&0xF000)==0x8000) + { if(K4sel&2) ROM_BANK8(0xC000,V); else ROM_BANK8(0x8000,V); - X6502_Rebase(); - } - else switch(A) - { - case 0x9000:switch(V&0x3) - { - case 0:MIRROR_SET(0);break; - case 1:MIRROR_SET(1);break; - case 2:onemir(0);break; - case 3:onemir(1);break; - } - break; - case 0x9001:if((K4sel&2)!=(V&2)) - { - uint8 swa; - swa=PRGBankList[0]; - ROM_BANK8(0x8000,PRGBankList[2]); - ROM_BANK8(0xc000,swa); - X6502_Rebase(); - } - K4sel=V; - break; - case 0xf000:IRQLatch&=0xF0;IRQLatch|=V&0xF;break; - case 0xf002:IRQLatch&=0x0F;IRQLatch|=V<<4;break; - case 0xf001:IRQCount=IRQLatch;IRQa=V&2;K4IRQ=V&1;break; - case 0xf003:IRQa=K4IRQ;break; + } + else switch(A) + { + case 0x9000:switch(V&0x3) + { + case 0:MIRROR_SET(0);break; + case 1:MIRROR_SET(1);break; + case 2:onemir(0);break; + case 3:onemir(1);break; + } + break; + case 0x9001:if((K4sel&2)!=(V&2)) + { + uint8 swa; + swa=PRGBankList[0]; + ROM_BANK8(0x8000,PRGBankList[2]); + ROM_BANK8(0xc000,swa); + } + K4sel=V; + break; + case 0xf000:IRQLatch&=0xF0;IRQLatch|=V&0xF;break; + case 0xf002:IRQLatch&=0x0F;IRQLatch|=V<<4;break; + case 0xf001:IRQCount=IRQLatch;IRQa=V&2;K4IRQ=V&1;acount=0;X6502_IRQEnd(FCEU_IQEXT);break; + case 0xf003:IRQa=K4IRQ;X6502_IRQEnd(FCEU_IQEXT);break; } } static void FP_FASTAPASS(1) KonamiIRQHook(int a) { - static int count=0; - #define LCYCS 114 +// #define LCYCS ((227*2)) + #define LCYCS 341 if(IRQa) { - count+=a; - if(count>=LCYCS) + acount+=a*3; + // acount+=a*4; + if(acount>=LCYCS) { - doagainbub:count-=LCYCS;IRQCount++; - if(IRQCount&0x100) {count=0;TriggerIRQ();IRQCount=IRQLatch;} - if(count>=LCYCS) goto doagainbub; + doagainbub:acount-=LCYCS;IRQCount++; + if(IRQCount&0x100) + {//acount=0; + X6502_IRQBegin(FCEU_IQEXT);IRQCount=IRQLatch; + } + if(acount>=LCYCS) goto doagainbub; } } } diff --git a/mappers/255.c b/mappers/255.c new file mode 100644 index 0000000..ede7af3 --- /dev/null +++ b/mappers/255.c @@ -0,0 +1,67 @@ +/* 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 DECLFW(Mapper255_write) +{ + uint32 pbank=(A>>7)&0x1F; + uint32 cbank=A&0x3F; + uint32 rbank=(A>>14)&1; + +// printf("$%04x:$%02x\n",A,V); +// printf("%2x:%2x:%2x,%2x\n",pbank,cbank,rbank,(A&0x40)>>6); + + if(A&0x1000) + { + ROM_BANK16(0x8000,((pbank|(rbank<<5))<<1)|((A&0x40)>>6)); + ROM_BANK16(0xc000,((pbank|(rbank<<5))<<1)|((A&0x40)>>6)); + } + else + { + ROM_BANK32(pbank|(rbank<<5)); + } + MIRROR_SET((A>>13)&1); + VROM_BANK8((rbank<<6)|cbank); +} + +static DECLFW(Mapper255_wl) +{ +// printf("Wr: $%04x:$%02x\n",A,V); + mapbyte1[A&3]=V&0xF; +} + +static DECLFR(Mapper255_read) +{ + //printf("Rd: $%04x\n",A); + return(mapbyte1[A&3]); //|(X.DB&0xF0)); +} + +void Mapper255_init(void) +{ + mapbyte1[0]=mapbyte1[1]=0xF; + ROM_BANK32(0); + VROM_BANK8(0); + SetWriteHandler(0x5800,0x5FFF,Mapper255_wl); + SetWriteHandler(0x8000,0xffff,Mapper255_write); + SetReadHandler(0x5800,0x5FFF,Mapper255_read); +} diff --git a/mappers/27.c b/mappers/27.c new file mode 100644 index 0000000..9dbe5cf --- /dev/null +++ b/mappers/27.c @@ -0,0 +1,74 @@ +#include "mapinc.h" + +static uint32 regchr[9]; + +static DECLFW(Mapper27_write) +{ + A&=0xF00F; + int regnum; + if((A>=0xB000) && (A<=0xE003)) { + regnum=((((A>>12)+1)&0x03)<<1)|((A&0x02)>>1); + if(A&1) + regchr[regnum]=(regchr[regnum]&0x0F)|(V<<4); + else + regchr[regnum]=(regchr[regnum]&0xFF0)|(V&0xF); + VROM_BANK1(regnum<<10,regchr[regnum]); + } + switch(A) + { + case 0x8000: if(regchr[8]&2) + ROM_BANK8(0xc000,V); + else + ROM_BANK8(0x8000,V); + break; + case 0xA000: ROM_BANK8(0xa000,V); break; + case 0x9000: + 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; + } + case 0x9002: regchr[8]=V; break; + case 0xF000: //X6502_IRQEnd(FCEU_IQEXT); + IRQLatch=(IRQLatch&0xF0)|(V&0x0F); + break; + case 0xF001: //X6502_IRQEnd(FCEU_IQEXT); + IRQLatch=(IRQLatch&0x0F)|((V&0xF)<<4); + break; + case 0xF003: IRQa=((IRQa&0x1)<<1)|(IRQa&0x1); + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xF002: IRQa=V&3; + if(IRQa&0x02) IRQCount=IRQLatch; + X6502_IRQEnd(FCEU_IQEXT); + break; + } +// if((A&0xF000)==0xF000) FCEU_printf("$%04x:$%02x, %d\n",A,V, scanline); +} + +static void Mapper27_hb(void) +{ +// FCEU_printf("%02x-%d,%d,%d\n",scanline,IRQa,IRQCount,IRQLatch); + if(IRQa&0x2){ + if(IRQCount==0xFF){ + X6502_IRQBegin(FCEU_IQEXT); + IRQCount=IRQLatch+1; + } else { + IRQCount++; + } + } +} + +void Mapper27_init(void) +{ + int i; + for (i=0; i<9; i++) { + regchr[i]=0; + } + IRQa=0; + IRQCount=IRQLatch=0; + SetWriteHandler(0x8000,0xffff,Mapper27_write); + GameHBIRQHook=Mapper27_hb; +} + diff --git a/mappers/32.c b/mappers/32.c index fd455d2..13e4bba 100644 --- a/mappers/32.c +++ b/mappers/32.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -28,20 +28,16 @@ static DECLFW(Mapper32_write) switch(A>>12) { case 0x8: - mapbyte1[1]=V; + mapbyte1[1]=V; if(IREMCon) {ROM_BANK8(0xc000,V);ROM_BANK8(0x8000,~1);} else {ROM_BANK8(0x8000,V);ROM_BANK8(0xc000,~1);} - X6502_Rebase(); break; - case 0x9:MIRROR_SET2(V&1); - IREMCon=(V>>1)&1; + case 0x9:IREMCon=(V>>1)&1; if(IREMCon) {ROM_BANK8(0xc000,mapbyte1[1]);ROM_BANK8(0x8000,~1);} else {ROM_BANK8(0x8000,mapbyte1[1]); ROM_BANK8(0xc000,~1);} MIRROR_SET(V&1); - X6502_Rebase(); break; case 0xa:ROM_BANK8(0xA000,V); - X6502_Rebase(); break; } diff --git a/mappers/33.c b/mappers/33.c index a675ec0..f3362c0 100644 --- a/mappers/33.c +++ b/mappers/33.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -20,28 +20,35 @@ #include "mapinc.h" +static int is48; + static DECLFW(Mapper33_write) { - A&=0xF003; + //printf("%04x:%02x, %d\n",A,V,scanline); - //printf("$%04x:$%02x, %d\n",A,V,scanline); + A&=0xF003; if(A>=0xA000 && A<=0xA003) VROM_BANK1(0x1000+((A&3)<<10),V); - else switch(A){ - case 0x8000:if(!mapbyte1[0]) - MIRROR_SET((V>>6)&1); - ROM_BANK8(0x8000,V); - X6502_Rebase(); - break; - case 0x8001:ROM_BANK8(0xA000,V); - X6502_Rebase();break; - case 0x8002:VROM_BANK2(0x0000,V);break; - case 0x8003:VROM_BANK2(0x0800,V);break; - case 0xc000:IRQLatch=V;break; - case 0xc001:IRQCount=IRQLatch;break; - case 0xc003:IRQa=0;break; - case 0xc002:IRQa=1;break; - case 0xe000:mapbyte1[0]=1;MIRROR_SET((V>>6)&1);break; + else switch(A) + { + case 0x8000:if(!is48) MIRROR_SET((V>>6)&1); + ROM_BANK8(0x8000,V); + break; + case 0x8001:ROM_BANK8(0xA000,V); break; + case 0x8002:VROM_BANK2(0x0000,V);break; + case 0x8003:VROM_BANK2(0x0800,V);break; + } +} + +static DECLFW(Mapper48_HiWrite) +{ + switch(A&0xF003) + { + case 0xc000:IRQLatch=V;break; + case 0xc001:IRQCount=IRQLatch;break; + case 0xc003:IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break; + case 0xc002:IRQa=1;break; + case 0xe000:MIRROR_SET((V>>6)&1);break; } } @@ -52,7 +59,7 @@ static void heho(void) IRQCount++; if(IRQCount==0x100) { - TriggerIRQ(); + X6502_IRQBegin(FCEU_IQEXT); IRQa=0; } } @@ -60,6 +67,14 @@ static void heho(void) void Mapper33_init(void) { - SetWriteHandler(0x8000,0xffff,Mapper33_write); - GameHBIRQHook=heho; + SetWriteHandler(0x8000,0xffff,Mapper33_write); + is48=0; +} + +void Mapper48_init(void) +{ + SetWriteHandler(0x8000,0xffff,Mapper33_write); + SetWriteHandler(0xc000,0xffff,Mapper48_HiWrite); + GameHBIRQHook=heho; + is48=1; } diff --git a/mappers/40.c b/mappers/40.c index d608de2..471a7cc 100644 --- a/mappers/40.c +++ b/mappers/40.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -25,10 +25,9 @@ static DECLFW(Mapper40_write) { switch(A&0xe000) { - case 0x8000:IRQa=0;IRQCount=0;break; + case 0x8000:IRQa=0;IRQCount=0;X6502_IRQEnd(FCEU_IQEXT);break; case 0xa000:IRQa=1;break; - case 0xe000:ROM_BANK8(0xc000,V&7); - X6502_Rebase();break; + case 0xe000:ROM_BANK8(0xc000,V&7);break; } } @@ -37,11 +36,11 @@ static void FP_FASTAPASS(1) Mapper40IRQ(int a) if(IRQa) { if(IRQCount<4096) - IRQCount+=a; - else + IRQCount+=a; + else { IRQa=0; - TriggerIRQ(); + X6502_IRQBegin(FCEU_IQEXT); } } } diff --git a/mappers/41.c b/mappers/41.c index ce63408..dfb6908 100644 --- a/mappers/41.c +++ b/mappers/41.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -28,24 +28,29 @@ DECLFW(Mapper41_write) { if(A<0x8000) { - ROM_BANK32(A&7); - X6502_Rebase(); - MIRROR_SET((A>>5)&1); - calreg=A; - calchr&=0x3; - calchr|=(A>>1)&0xC; - VROM_BANK8(calchr); + ROM_BANK32(A&7); + MIRROR_SET((A>>5)&1); + calreg=A; + calchr&=0x3; + calchr|=(A>>1)&0xC; + VROM_BANK8(calchr); } else if(calreg&0x4) { - calchr&=0xC; - calchr|=A&3; - VROM_BANK8(calchr); + calchr&=0xC; + calchr|=A&3; + VROM_BANK8(calchr); } } +static void M41Reset(void) +{ + calreg=calchr=0; +} + void Mapper41_init(void) { + MapperReset=M41Reset; ROM_BANK32(0); SetWriteHandler(0x8000,0xffff,Mapper41_write); SetWriteHandler(0x6000,0x67ff,Mapper41_write); diff --git a/mappers/42.c b/mappers/42.c index 6bab879..bf31ac2 100644 --- a/mappers/42.c +++ b/mappers/42.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -23,12 +23,13 @@ static DECLFW(Mapper42_write) { +// FCEU_printf("%04x:%04x\n",A,V); switch(A&0xe003) { - case 0xe000:mapbyte1[0]=V;ROM_BANK8(0x6000,V&0xF); - X6502_Rebase();break; + case 0x8000:VROM_BANK8(V);break; + case 0xe000:mapbyte1[0]=V;ROM_BANK8(0x6000,V&0xF);break; case 0xe001:MIRROR_SET((V>>3)&1);break; - case 0xe002:IRQa=V&2;if(!IRQa) IRQCount=0;break; + case 0xe002:IRQa=V&2;if(!IRQa) IRQCount=0;X6502_IRQEnd(FCEU_IQEXT);break; } } @@ -36,13 +37,12 @@ static void FP_FASTAPASS(1) Mapper42IRQ(int a) { if(IRQa) { - if(IRQCount<24576) - IRQCount+=a; + IRQCount+=a; + if(IRQCount>=32768) IRQCount-=32768; + if(IRQCount>=24576) + X6502_IRQBegin(FCEU_IQEXT); else - { - IRQa=0; - TriggerIRQ(); - } + X6502_IRQEnd(FCEU_IQEXT); } } @@ -56,7 +56,7 @@ void Mapper42_init(void) { ROM_BANK8(0x6000,0); ROM_BANK32(~0); - SetWriteHandler(0xe000,0xffff,Mapper42_write); + SetWriteHandler(0x6000,0xffff,Mapper42_write); SetReadHandler(0x6000,0x7fff,CartBR); MapStateRestore=Mapper42_StateRestore; MapIRQHook=Mapper42IRQ; diff --git a/mappers/43.c b/mappers/43.c index 0ca0cee..ef7d40d 100644 --- a/mappers/43.c +++ b/mappers/43.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -22,43 +22,55 @@ -DECLFW(Mapper43_write) +static DECLFW(Mapper43_write) { - uint32 m; - int z; - - if(A&0x400) - onemir(0); + //printf("$%04x:$%02x\n",A,V); + if((A&0x8122)==0x8122) + { + X6502_IRQEnd(FCEU_IQEXT); + if(V&2) IRQa=1; else - MIRROR_SET((A>>13)&1); - m=A&0x1f; + IRQCount=IRQa=0; + } +} - z=(A>>8)&3; +static DECLFW(M43Low) +{ +// int transo[8]={4,3,4,4,4,7,5,6}; + int transo[8]={4,3,2,3,4,7,5,6}; + A&=0xF0FF; + if(A==0x4022) + setprg8(0x6000,transo[V&7]); + //printf("$%04x:$%02x\n",A,V); +} - switch(CHRmask8[0]) +static void FP_FASTAPASS(1) M43Ho(int a) +{ + IRQCount+=a; + if(IRQa) + if(IRQCount>=4096) { - default: - case 0xFF: - if(z&2) - m|=0x20; - break; - case 0x1FF: - m|=z<<5; - break; + X6502_IRQBegin(FCEU_IQEXT); } - - if(A&0x800) - { - ROM_BANK16(0x8000,(m<<1)|((A&0x1000)>>12)); - ROM_BANK16(0xC000,(m<<1)|((A&0x1000)>>12)); - } - else - ROM_BANK32(m); - X6502_Rebase(); } +//static DECLFR(boo) +//{ +// printf("$%04x\n",A); +// return( ROM[0x2000*8 +0x1000 +(A-0x5000)]); +//} + void Mapper43_init(void) { - ROM_BANK32(0); + setprg4(0x5000,16); + setprg8(0x6000,2); + setprg8(0x8000,1); + setprg8(0xa000,0); + setprg8(0xc000,4); + setprg8(0xe000,9); SetWriteHandler(0x8000,0xffff,Mapper43_write); + SetWriteHandler(0x4020,0x7fff,M43Low); + //SetReadHandler(0x5000,0x5fff,boo); + SetReadHandler(0x6000,0xffff,CartBR); + MapIRQHook=M43Ho; } diff --git a/mappers/46.c b/mappers/46.c index ab8133e..8c4ef6d 100644 --- a/mappers/46.c +++ b/mappers/46.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -30,7 +30,6 @@ DECLFW(Mapper46_writel) A64reg=V; ROM_BANK32((A64wr&1)+((A64reg&0xF)<<1)); VROM_BANK8(((A64wr>>4)&7)+((A64reg&0xF0)>>1)); - X6502_Rebase(); } DECLFW(Mapper46_write) @@ -38,7 +37,6 @@ DECLFW(Mapper46_write) A64wr=V; ROM_BANK32((V&1)+((A64reg&0xF)<<1)); VROM_BANK8(((V>>4)&7)+((A64reg&0xF0)>>1)); - X6502_Rebase(); } void Mapper46_init(void) diff --git a/mappers/112.c b/mappers/50.c similarity index 50% rename from mappers/112.c rename to mappers/50.c index 273d550..8d7f515 100644 --- a/mappers/112.c +++ b/mappers/50.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -21,33 +21,55 @@ #include "mapinc.h" +static void FP_FASTAPASS(1) Mapper50IRQ(int a) +{ + if(IRQa) + { + if(IRQCount<4096) + IRQCount+=a; + else + { + IRQa=0; + X6502_IRQBegin(FCEU_IQEXT); + } + } +} -DECLFW(Mapper112_write) +static void M50Restore(int version) { -switch(A) + setprg8(0xc000,mapbyte1[0]); +} + +static DECLFW(M50W) { - case 0xe000:MIRROR_SET(V&1);break; - case 0x8000:mapbyte1[0]=V;break; - case 0xa000:switch(mapbyte1[0]) - { - case 0:ROM_BANK8(0x8000,V);break; - case 1:ROM_BANK8(0xA000,V);break; - case 2: V&=0xFE;VROM_BANK1(0,V); - VROM_BANK1(0x400,(V+1));break; - case 3: V&=0xFE;VROM_BANK1(0x800,V); - VROM_BANK1(0xC00,(V+1));break; - case 4:VROM_BANK1(0x1000,V);break; - case 5:VROM_BANK1(0x1400,V);break; - case 6:VROM_BANK1(0x1800,V);break; - case 7:VROM_BANK1(0x1c00,V);break; - } - X6502_Rebase(); - break; + if((A&0xD060)==0x4020) + { + if(A&0x100) + { + IRQa=V&1; + if(!IRQa) IRQCount=0; + X6502_IRQEnd(FCEU_IQEXT); + } + else + { + V=((V&1)<<2)|((V&2)>>1)|((V&4)>>1)|(V&8); + mapbyte1[0]=V; + setprg8(0xc000,V); + } } } -void Mapper112_init(void) +void Mapper50_init(void) { - SetWriteHandler(0x8000,0xffff,Mapper112_write); + SetWriteHandler(0x4020,0x5fff,M50W); + SetReadHandler(0x6000,0xffff,CartBR); + MapStateRestore=M50Restore; + MapIRQHook=Mapper50IRQ; + + setprg8(0x6000,0xF); + setprg8(0x8000,0x8); + setprg8(0xa000,0x9); + setprg8(0xc000,0x0); + setprg8(0xe000,0xB); } diff --git a/mappers/51.c b/mappers/51.c index 90986ea..cc1fbbd 100644 --- a/mappers/51.c +++ b/mappers/51.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -26,7 +26,7 @@ static uint32 Get8K(uint32 A) { uint32 bank; - + bank=(page<<2)|((A>>13)&1); if(A&0x4000 && !(mode&1)) bank|=0xC; @@ -45,7 +45,6 @@ static void Synco(void) MIRROR_SET2(0); for(x=0x6000;x<0x10000;x+=8192) ROM_BANK8(x,Get8K(x)); - X6502_Rebase(); } static DECLFW(Write) diff --git a/mappers/249.c b/mappers/57.c similarity index 64% rename from mappers/249.c rename to mappers/57.c index 6225d49..b64d270 100644 --- a/mappers/249.c +++ b/mappers/57.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -20,27 +20,30 @@ #include "mapinc.h" -uint8 doh; -static DECLFW(Mapper249_write) + +static DECLFW(Mapper57_write) { - switch(A&0xe001) + A&=0x8800; + if(A==0x8800) { - case 0x8000:doh=V;break; - case 0x8001:switch(doh&7) - { - case 0:VROM_BANK2(0x0000,V>>1);break; - case 1:VROM_BANK2(0x0800,V>>1);break; - case 2:VROM_BANK1(0x1000,V);break; -// case 6:ROM_BANK8(0xa000,V);break; -// case 2:ROM_BANK8(0x8000,V);break; - } + mapbyte1[0]=V; + if(V&0x80) + ROM_BANK32(2|(V>>6)); + else + { + ROM_BANK16(0x8000,(V>>5)&3); + ROM_BANK16(0xc000,(V>>5)&3); + } + MIRROR_SET((V&0x8)>>3); } -// printf("$%04x:$%02x\n",A,V); + else + mapbyte1[1]=V; + VROM_BANK8((mapbyte1[1]&3)|(mapbyte1[0]&7)|((mapbyte1[0]&0x10)>>1)); + //printf("$%04x:$%02x\n",A,V); } -void Mapper249_init(void) +void Mapper57_init(void) { - SetWriteHandler(0x8000,0xffff,Mapper249_write); + SetWriteHandler(0x8000,0xffff,Mapper57_write); } - diff --git a/mappers/58.c b/mappers/58.c new file mode 100644 index 0000000..d3cc505 --- /dev/null +++ b/mappers/58.c @@ -0,0 +1,43 @@ +/* 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 DECLFW(M58Write) +{ + //printf("$%04x:$%02x\n",A,V); + if(A&0x40) + { + ROM_BANK16(0x8000,(A&0x07)); + ROM_BANK16(0xc000,(A&0x07)); + } + else + ROM_BANK32((A&0x06)>>1); + + VROM_BANK8((A&0x38)>>3); + MIRROR_SET2((V&2)>>1); +} + +void Mapper58_init(void) +{ + ROM_BANK32(0); + VROM_BANK8(0); + SetWriteHandler(0x8000,0xFFFF,M58Write); +} diff --git a/mappers/59.c b/mappers/59.c new file mode 100644 index 0000000..30ddb8b --- /dev/null +++ b/mappers/59.c @@ -0,0 +1,47 @@ +/* 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 int ay; +static DECLFW(Mapper59_write) +{ + //printf("$%04x:$%02x\n",A,V); + setprg32(0x8000,(A&0x70)>>4); + setchr8(A&0x7); + //if(A&0x100) + // setprg32r(0x10,0x8000,0); + ay=A; + MIRROR_SET2((A&0x8)>>3); +} + +static DECLFR(m59rd) +{ + if(ay&0x100) return(0); + else + return(CartBR(A)); +} + +void Mapper59_init(void) +{ + setprg32(0x8000,0); + SetReadHandler(0x8000,0xffff,m59rd); + SetWriteHandler(0x8000,0xffff,Mapper59_write); +} diff --git a/mappers/6.c b/mappers/6.c index 29caa6a..45a8f0d 100644 --- a/mappers/6.c +++ b/mappers/6.c @@ -1,77 +1,80 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell - * - * 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 FVRAM_BANK8(A,V) {VPage[0]=VPage[1]=VPage[2]=VPage[3]=VPage[4]=VPage[5]=VPage[6]=VPage[7]=V?&MapperExRAM[(V)<<13]-(A):&CHRRAM[(V)<<13]-(A);CHRBankList[0]=((V)<<3);CHRBankList[1]=((V)<<3)+1;CHRBankList[2]=((V)<<3)+2;CHRBankList[3]=((V)<<3)+3;CHRBankList[4]=((V)<<3)+4;CHRBankList[5]=((V)<<3)+5;CHRBankList[6]=((V)<<3)+6;CHRBankList[7]=((V)<<3)+7;PPUCHRRAM=0xFF;} - -static void FP_FASTAPASS(1) FFEIRQHook(int a) -{ - if(IRQa) - { - IRQCount+=a; - if(IRQCount>=0x10000) - { - TriggerIRQ(); - IRQa=0; - IRQCount=0; - } - } -} - -DECLFW(Mapper6_write) -{ - if(A<0x8000) - { - switch(A){ - case 0x42FF:MIRROR_SET((V>>4)&1);break; - case 0x42FE:onemir((V>>3)&2);break; - case 0x4501:IRQa=0;break; - case 0x4502:IRQCount&=0xFF00;IRQCount|=V;break; - case 0x4503:IRQCount&=0xFF;IRQCount|=V<<8;IRQa=1;break; - } - } else { - ROM_BANK16(0x8000,V>>2); - FVRAM_BANK8(0x0000,V&3); - X6502_Rebase(); - } -} -void Mapper6_StateRestore(int version) -{ - int x; - for(x=0;x<8;x++) - if(PPUCHRRAM&(1<7) - VPage[x]=&MapperExRAM[(CHRBankList[x]&31)*0x400]-(x*0x400); - else VPage[x]=&CHRRAM[(CHRBankList[x]&7)*0x400]-(x*0x400); - } -} -void Mapper6_init(void) -{ -MapIRQHook=FFEIRQHook; -ROM_BANK16(0xc000,7); - -SetWriteHandler(0x4020,0x5fff,Mapper6_write); -SetWriteHandler(0x8000,0xffff,Mapper6_write); -MapStateRestore=Mapper6_StateRestore; -} - +/* 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 FFEmode; + +#define FVRAM_BANK8(A,V) {VPage[0]=VPage[1]=VPage[2]=VPage[3]=VPage[4]=VPage[5]=VPage[6]=VPage[7]=V?&MapperExRAM[(V)<<13]-(A):&CHRRAM[(V)<<13]-(A);CHRBankList[0]=((V)<<3);CHRBankList[1]=((V)<<3)+1;CHRBankList[2]=((V)<<3)+2;CHRBankList[3]=((V)<<3)+3;CHRBankList[4]=((V)<<3)+4;CHRBankList[5]=((V)<<3)+5;CHRBankList[6]=((V)<<3)+6;CHRBankList[7]=((V)<<3)+7;PPUCHRRAM=0xFF;} + +static void FP_FASTAPASS(1) FFEIRQHook(int a) +{ + if(IRQa) + { + IRQCount+=a; + if(IRQCount>=0x10000) + { + X6502_IRQBegin(FCEU_IQEXT); + IRQa=0; + IRQCount=0; + } + } +} + +DECLFW(Mapper6_write) +{ + if(A<0x8000) + { + switch(A){ + case 0x42FF:MIRROR_SET((V>>4)&1);break; + case 0x42FE:onemir((V>>3)&2); FFEmode=V&0x80;break; + case 0x4501:IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break; + case 0x4502:IRQCount&=0xFF00;IRQCount|=V;break; + case 0x4503:IRQCount&=0xFF;IRQCount|=V<<8;IRQa=1;break; + } + } else { + switch (FFEmode) + { + case 0x80: setchr8(V); break; + default: ROM_BANK16(0x8000,V>>2); + FVRAM_BANK8(0x0000,V&3); + } + } +} +void Mapper6_StateRestore(int version) +{ + int x; + for(x=0;x<8;x++) + if(PPUCHRRAM&(1<7) + VPage[x]=&MapperExRAM[(CHRBankList[x]&31)*0x400]-(x*0x400); + else VPage[x]=&CHRRAM[(CHRBankList[x]&7)*0x400]-(x*0x400); + } +} +void Mapper6_init(void) +{ +MapIRQHook=FFEIRQHook; +ROM_BANK16(0xc000,7); + +SetWriteHandler(0x4020,0x5fff,Mapper6_write); +SetWriteHandler(0x8000,0xffff,Mapper6_write); +MapStateRestore=Mapper6_StateRestore; +} diff --git a/mappers/60.c b/mappers/60.c new file mode 100644 index 0000000..b48087c --- /dev/null +++ b/mappers/60.c @@ -0,0 +1,41 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2003 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 DECLFW(Mapper60_write) +{ + if(A&0x80) { + ROM_BANK16(0x8000,(A&0x70)>>4); + ROM_BANK16(0xC000,(A&0x70)>>4); + } + else + ROM_BANK32((A&0x70)>>5); + VROM_BANK8(A&7); + MIRROR_SET((A&8)>>3); +} + +void Mapper60_init(void) +{ + ROM_BANK32(0); + SetWriteHandler(0x8000,0xffff, Mapper60_write); +} + + diff --git a/mappers/245.c b/mappers/61.c similarity index 58% rename from mappers/245.c rename to mappers/61.c index ae20c18..4303932 100644 --- a/mappers/245.c +++ b/mappers/61.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -20,33 +20,35 @@ #include "mapinc.h" -static void Synco(void) -{ - ROM_BANK8(0x8000,mapbyte2[0]); - ROM_BANK8(0xA000,mapbyte2[1]); - ROM_BANK8(0xc000,0x3e); - ROM_BANK8(0xe000,0x3f); - X6502_Rebase(); -} -static DECLFW(Mapper245_write) + +static DECLFW(Mapper61_write) { - switch(A&0xe001) +// printf("$%04x:$%02x\n",A,V); + switch(A&0x30) { - case 0xa000:mapbyte1[1]=V;Synco();break; - case 0x8000:mapbyte1[0]=V;break; - case 0x8001:switch(mapbyte1[0]&7) - { -// default:printf("ark\n");break; - case 6:mapbyte2[0]=V;Synco();break; - case 7:mapbyte2[1]=V;Synco();break; - }break; - //case 0xa001:MIRROR_SET2(V>>7);break; + case 0x00: + case 0x30: + ROM_BANK32(A&0xF); + break; + case 0x20: + case 0x10: + ROM_BANK16(0x8000,((A&0xF)<<1)| (((A&0x20)>>4)) ); + ROM_BANK16(0xC000,((A&0xF)<<1)| (((A&0x20)>>4)) ); + break; } -// printf("$%04x:$%02x\n",A,V); + #ifdef moo + if(!(A&0x10)) + ROM_BANK32(A&0xF); + else + { + ROM_BANK16(0x8000,((A&0xF)<<1)| (((A&0x10)>>4)^1) ); + ROM_BANK16(0xC000,((A&0xF)<<1)| (((A&0x10)>>4)^1) ); + } + #endif + MIRROR_SET((A&0x80)>>7); } -void Mapper245_init(void) +void Mapper61_init(void) { - SetWriteHandler(0x8000,0xffff,Mapper245_write); + SetWriteHandler(0x8000,0xffff,Mapper61_write); } - diff --git a/mappers/62.c b/mappers/62.c new file mode 100644 index 0000000..ed0f01d --- /dev/null +++ b/mappers/62.c @@ -0,0 +1,41 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2003 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 DECLFW(Mapper62_write) +{ + VROM_BANK8(((A&0x1F)<<2)|(V&0x03)); + if((A&0x20)>>5) { + ROM_BANK16(0x8000,(A&0x40)|((A>>8)&0x3F)); + ROM_BANK16(0xc000,(A&0x40)|((A>>8)&0x3F)); + } + else + ROM_BANK32(((A&0x40)|((A>>8)&0x3F))>>1); + MIRROR_SET((A&0x80)>>7); +} + +void Mapper62_init(void) +{ + SetWriteHandler(0x8000,0xffff, Mapper62_write); + ROM_BANK32(0); +} + + diff --git a/mappers/64.c b/mappers/64.c deleted file mode 100644 index 68c7696..0000000 --- a/mappers/64.c +++ /dev/null @@ -1,151 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell - * - * 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 cmd mapbyte1[0] -#define mir mapbyte1[1] -#define rmode mapbyte1[2] -#define regsl mapbyte2 -#define regsh mapbyte3 - -static void RAMBO1_hb(void) -{ - rmode=0; - if(IRQCount>=0) - { - IRQCount--; - if(IRQCount<0) - { - if(IRQa) - { -// printf("IRQ: %d\n",scanline); - rmode = 1; - X6502_IRQBegin(FCEU_IQEXT); - } - } - } -} - -static void Synco(void) -{ - int x; - - if(cmd&0x20) - { - setchr1(0x0000,regsl[0]); - setchr1(0x0800,regsl[1]); - setchr1(0x0400,regsh[0]); - setchr1(0x0c00,regsh[1]); - } - else - { - setchr2(0x0000,regsl[0]>>1); - setchr2(0x0800,regsl[1]>>1); - } - - for(x=0;x<4;x++) - setchr1(0x1000+x*0x400,regsl[2+x]); - - setprg8(0x8000,regsl[6]); - setprg8(0xA000,regsl[7]); - - setprg8(0xC000,regsh[7]); - X6502_Rebase(); -} - - -static DECLFW(RAMBO1_write) -{ - //if(A>=0xC000 && A<=0xFFFF) printf("$%04x:$%02x, %d, %d\n",A,V,scanline,timestamp); - switch(A&0xF001) - { - case 0xa000:mir=V&1; - setmirror(mir^1); - break; - case 0x8000:cmd = V; - break; - case 0x8001: - if((cmd&15)<8) - regsl[cmd&7]=V; - else - regsh[cmd&7]=V; - Synco(); - break; - case 0xc000:IRQLatch=V; - if(rmode==1) - { - IRQCount=IRQLatch; - } - break; - case 0xc001:rmode=1; - IRQCount=IRQLatch; - 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) -{ - if(version<74) - { - int x; - - x=mapbyte1[1]; // was MMC3_cmd - cmd=x; - - regsl[0]=CHRBankList[0]; - regsl[1]=CHRBankList[2]; - regsh[0]=CHRBankList[1]; - regsh[1]=CHRBankList[3]; - - for(x=0;x<4;x++) - regsl[2+x]=CHRBankList[4+x]; - - regsl[6]=PRGBankList[0]; - regsl[7]=PRGBankList[1]; - regsh[7]=PRGBankList[2]; - mir=Mirroring^1; - } - Synco(); - setmirror(mir^1); -} - -void Mapper64_init(void) -{ - int x; - - for(x=0;x<8;x++) - regsl[x]=regsh[x]=~0; - cmd=0; - mir=0; - setmirror(1); - Synco(); - GameHBIRQHook=RAMBO1_hb; - GameStateRestore=RAMBO1_Restore; - SetWriteHandler(0x8000,0xffff,RAMBO1_write); -} diff --git a/mappers/65.c b/mappers/65.c index 51983ef..d817694 100644 --- a/mappers/65.c +++ b/mappers/65.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -26,42 +26,45 @@ void FP_FASTAPASS(1) IREMIRQHook(int a) if(IRQa) { IRQCount-=a; - if(IRQCount<=0-4) + if(IRQCount<-4) { - TriggerIRQ(); + X6502_IRQBegin(FCEU_IQEXT); IRQa=0; IRQCount=0xFFFF; } } } -DECLFW(Mapper65_write) +static DECLFW(Mapper65_write) { -switch(A) -{ -case 0x8000:ROM_BANK8(0x8000,V); - X6502_Rebase();break; -case 0x9000:MIRROR_SET2((V>>6)&1);break; -case 0x9003:IRQa=V&0x80;break; -case 0x9004:IRQCount=IRQLatch;break; -case 0x9005: IRQLatch&=0x00FF; - IRQLatch|=V<<8; - break; -case 0x9006: IRQLatch&=0xFF00;IRQLatch|=V; - break; -case 0xB000:VROM_BANK1(0x0000,V);break; -case 0xB001:VROM_BANK1(0x0400,V);break; -case 0xB002:VROM_BANK1(0x0800,V);break; -case 0xB003:VROM_BANK1(0x0C00,V);break; -case 0xB004:VROM_BANK1(0x1000,V);break; -case 0xB005:VROM_BANK1(0x1400,V);break; -case 0xB006:VROM_BANK1(0x1800,V);break; -case 0xB007:VROM_BANK1(0x1C00,V);break; -case 0xa000:ROM_BANK8(0xA000,V); - X6502_Rebase();break; -case 0xC000:ROM_BANK8(0xC000,V); - X6502_Rebase();break; + //if(A>=0x9000 && A<=0x9006) + // printf("$%04x:$%02x, %d\n",A,V,scanline); + switch(A) + { + //default: printf("$%04x:$%02x\n",A,V); + // break; + case 0x8000:ROM_BANK8(0x8000,V);break; + // case 0x9000:printf("$%04x:$%02x\n",A,V);MIRROR_SET2((V>>6)&1);break; + case 0x9001:MIRROR_SET(V>>7);break; + case 0x9003:IRQa=V&0x80;X6502_IRQEnd(FCEU_IQEXT);break; + case 0x9004:IRQCount=IRQLatch;break; + case 0x9005: IRQLatch&=0x00FF; + IRQLatch|=V<<8; + break; + case 0x9006: IRQLatch&=0xFF00;IRQLatch|=V; + break; + case 0xB000:VROM_BANK1(0x0000,V);break; + case 0xB001:VROM_BANK1(0x0400,V);break; + case 0xB002:VROM_BANK1(0x0800,V);break; + case 0xB003:VROM_BANK1(0x0C00,V);break; + case 0xB004:VROM_BANK1(0x1000,V);break; + case 0xB005:VROM_BANK1(0x1400,V);break; + case 0xB006:VROM_BANK1(0x1800,V);break; + case 0xB007:VROM_BANK1(0x1C00,V);break; + case 0xa000:ROM_BANK8(0xA000,V);break; + case 0xC000:ROM_BANK8(0xC000,V);break; } + //MIRROR_SET2(1); } void Mapper65_init(void) diff --git a/mappers/67.c b/mappers/67.c index f5bbb2b..9d560f9 100644 --- a/mappers/67.c +++ b/mappers/67.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -23,7 +23,7 @@ #define suntoggle mapbyte1[0] -DECLFW(Mapper67_write) +static DECLFW(Mapper67_write) { A&=0xF800; if((A&0x800) && A<=0xb800) @@ -34,11 +34,18 @@ DECLFW(Mapper67_write) { case 0xc800: case 0xc000:if(!suntoggle) - {IRQCount&=0xFF;IRQCount|=V<<8;} - else{IRQCount&=0xFF00;IRQCount|=V;} + { + IRQCount&=0xFF; + IRQCount|=V<<8; + } + else + { + IRQCount&=0xFF00; + IRQCount|=V; + } suntoggle^=1; break; - case 0xd800:suntoggle=0;IRQa=V&0x10;break; + case 0xd800:suntoggle=0;IRQa=V&0x10;X6502_IRQEnd(FCEU_IQEXT);break; case 0xe800:switch(V&3) { @@ -48,8 +55,7 @@ DECLFW(Mapper67_write) case 3:onemir(1);break; } break; - case 0xf800:ROM_BANK16(0x8000,V); - X6502_Rebase();break; + case 0xf800:ROM_BANK16(0x8000,V);break; } } static void FP_FASTAPASS(1) SunIRQHook(int a) @@ -58,7 +64,11 @@ static void FP_FASTAPASS(1) SunIRQHook(int a) { IRQCount-=a; if(IRQCount<=0) - {TriggerIRQ();IRQa=0;IRQCount=0xFFFF;} + { + X6502_IRQBegin(FCEU_IQEXT); + IRQa=0; + IRQCount=0xFFFF; + } } } void Mapper67_init(void) diff --git a/mappers/68.c b/mappers/68.c index f1e5f68..9c25f1b 100644 --- a/mappers/68.c +++ b/mappers/68.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -24,16 +24,16 @@ static void Fixerit(void) { switch(mapbyte2[0]&3) { - case 0:vnapage[0]=vnapage[2]=VROM+(((mapbyte1[0]|128)&CHRmask1[0])<<10); - vnapage[1]=vnapage[3]=VROM+(((mapbyte1[1]|128)&CHRmask1[0])<<10); - break; - case 1:vnapage[0]=vnapage[1]=VROM+(((mapbyte1[0]|128)&CHRmask1[0])<<10); - vnapage[2]=vnapage[3]=VROM+(((mapbyte1[1]|128)&CHRmask1[0])<<10); + case 0:vnapage[0]=vnapage[2]=CHRptr[0]+(((mapbyte1[0]|128)&CHRmask1[0])<<10); + vnapage[1]=vnapage[3]=CHRptr[0]+(((mapbyte1[1]|128)&CHRmask1[0])<<10); + break; + case 1:vnapage[0]=vnapage[1]=CHRptr[0]+(((mapbyte1[0]|128)&CHRmask1[0])<<10); + vnapage[2]=vnapage[3]=CHRptr[0]+(((mapbyte1[1]|128)&CHRmask1[0])<<10); + break; + case 2:vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=CHRptr[0]+(((mapbyte1[0]|128)&CHRmask1[0])<<10); + break; + case 3:vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=CHRptr[0]+(((mapbyte1[1]|128)&CHRmask1[0])<<10); break; - case 2:vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=VROM+(((mapbyte1[0]|128)&CHRmask1[0])<<10); - break; - case 3:vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=VROM+(((mapbyte1[1]|128)&CHRmask1[0])<<10); - break; } } @@ -49,12 +49,12 @@ DECLFW(Mapper68_write) { case 0xc000:mapbyte1[0]=V; if(VROM_size && mapbyte2[0]&0x10) - Fixerit(); + Fixerit(); break; case 0xd000:mapbyte1[1]=V; - if(VROM_size && mapbyte2[0]&0x10) - Fixerit(); + if(VROM_size && mapbyte2[0]&0x10) + Fixerit(); break; case 0xe000: mapbyte2[0]=V; @@ -69,13 +69,12 @@ DECLFW(Mapper68_write) } } else if(VROM_size) - { - Fixerit(); - PPUNTARAM=0; - } + { + Fixerit(); + PPUNTARAM=0; + } break; - case 0xf000: ROM_BANK16(0x8000,V); - X6502_Rebase();break; + case 0xf000: ROM_BANK16(0x8000,V);break; } } @@ -93,7 +92,7 @@ static void Mapper68_StateRestore(int version) } else if(VROM_size) { - Fixerit(); + Fixerit(); PPUNTARAM=0; } } diff --git a/mappers/69.c b/mappers/69.c index 3e427bb..948c304 100644 --- a/mappers/69.c +++ b/mappers/69.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -19,58 +19,60 @@ */ #include "mapinc.h" + static void AYSound(int Count); +//static void AYSoundHQ(void); static void DoAYSQ(int x); -static void DoAYNoise(void); +//static void DoAYSQHQ(int x); #define sunselect mapbyte1[0] #define sungah mapbyte1[1] -#define sunindex mapbyte1[2] - -static uint16 znreg; -static int32 inc; +static uint8 sunindex; -DECLFW(SUN5BWRAM) +static DECLFW(SUN5BWRAM) { if((sungah&0xC0)==0xC0) (WRAM-0x6000)[A]=V; } -DECLFR(SUN5AWRAM) +static DECLFR(SUN5AWRAM) { if((sungah&0xC0)==0x40) return X.DB; return CartBR(A); } -DECLFW(Mapper69_SWL) +static DECLFW(Mapper69_SWL) { sunindex=V%14; } -DECLFW(Mapper69_SWH) + +static DECLFW(Mapper69_SWH) { + int x; GameExpSound.Fill=AYSound; + GameExpSound.HiFill=0;//AYSoundHQ; + if(FSettings.SndRate); switch(sunindex) { case 0: case 1: - case 8:DoAYSQ(0);break; + case 8:/*if(FSettings.soundq>=1) DoAYSQHQ(0); else*/ DoAYSQ(0);break; case 2: case 3: - case 9:DoAYSQ(1);break; + case 9:/*if(FSettings.soundq>=1) DoAYSQHQ(1); else*/ DoAYSQ(1);break; case 4: case 5: - case 10:DoAYSQ(2);break; - case 6:DoAYNoise();znreg=0xFFFF;break; - case 7:DoAYNoise(); - DoAYSQ(0); - DoAYSQ(1); - DoAYSQ(2);break; + case 10:/*if(FSettings.soundq>=1) DoAYSQHQ(2); else*/ DoAYSQ(2);break; + case 7: + for(x=0;x<2;x++) + /*if(FSettings.soundq>=1) DoAYSQHQ(x); else*/ DoAYSQ(x); + break; } MapperExRAM[sunindex]=V; } -DECLFW(Mapper69_write) +static DECLFW(Mapper69_write) { switch(A&0xE000) { @@ -91,14 +93,10 @@ DECLFW(Mapper69_write) } else setprg8(0x6000,V); - X6502_Rebase(); break; - case 9:ROM_BANK8(0x8000,V); - X6502_Rebase();break; - case 0xa:ROM_BANK8(0xa000,V); - X6502_Rebase();break; - case 0xb:ROM_BANK8(0xc000,V); - X6502_Rebase();break; + case 9:ROM_BANK8(0x8000,V);break; + case 0xa:ROM_BANK8(0xa000,V);break; + case 0xb:ROM_BANK8(0xc000,V);break; case 0xc: switch(V&3) { @@ -108,165 +106,152 @@ DECLFW(Mapper69_write) case 3:onemir(1);break; } break; - case 0xd:IRQa=V;break; - case 0xe:IRQCount&=0xFF00;IRQCount|=V;break; - case 0xf:IRQCount&=0x00FF;IRQCount|=V<<8;break; + case 0xd:IRQa=V;X6502_IRQEnd(FCEU_IQEXT);break; + case 0xe:IRQCount&=0xFF00;IRQCount|=V;X6502_IRQEnd(FCEU_IQEXT);break; + case 0xf:IRQCount&=0x00FF;IRQCount|=V<<8;X6502_IRQEnd(FCEU_IQEXT);break; } break; } } -static int32 vcount[4]; -static int CAYBC[4]={0,0,0,0}; +static int32 vcount[3]; +static int32 dcount[3]; +static int CAYBC[3]; + static void DoAYSQ(int x) { - int V; - uint32 freq; - unsigned char amp; + int32 freq=((MapperExRAM[x<<1]|((MapperExRAM[(x<<1)+1]&15)<<8))+1)<<(4+17); + int32 amp=(MapperExRAM[0x8+x]&15)<<2; int32 start,end; + int V; + + amp+=amp>>1; start=CAYBC[x]; end=(SOUNDTS<<16)/soundtsinc; if(end<=start) return; CAYBC[x]=end; - if(!(MapperExRAM[0x7]&(1<>1)) - Wave[V>>4]+=amp; - vcoo+=0x1000; - if(vcoo>=inc) vcoo-=inc; - } - vcount[x]=vcoo; + if(dcount[x]) + Wave[V>>4]+=amp; + vcount[x]-=nesincsize; + while(vcount[x]<=0) + { + dcount[x]^=1; + vcount[x]+=freq; } + } } -static void DoAYNoise(void) -{ - int V; - uint32 freq; - unsigned char amp; - int32 start,end; - - start=CAYBC[3]; - end=(SOUNDTS<<16)/soundtsinc; - if(end<=start) return; - CAYBC[3]=end; - - amp=0; - for(V=0;V<3;V++) - { - if(!(MapperExRAM[0x7]&(8<44100) - inc=((freq<<11)/(FSettings.SndRate OVERSAMPLE))<<4; - else - inc=(freq<<15)/(FSettings.SndRate OVERSAMPLE); - for(V=start;V=32768) - { - unsigned char feedback; - mixer=0; - if(znreg&1) mixer+=amp; - feedback=((znreg>>13)&1)^((znreg>>14)&1); - znreg=(znreg<<1)+(feedback); - vcount[3]-=32768; - } - Wave[V>>4]+=mixer; - vcount[3]+=inc; - } - } +#if 0 +static void DoAYSQHQ(int x) +{ + int32 V; + int32 freq=((MapperExRAM[x<<1]|((MapperExRAM[(x<<1)+1]&15)<<8))+1)<<4; + int32 amp=(MapperExRAM[0x8+x]&15)<<6; + amp+=amp>>1; + if(!(MapperExRAM[0x7]&(1<=19) + if(mapbyte1[1]&0x40) { - if(mapbyte1[1]&0x40) - { - if(mapbyte1[1]&0x80) // Select WRAM - setprg8r(0x10,0x6000,0); - } - else - setprg8(0x6000,mapbyte1[1]); + if(mapbyte1[1]&0x80) // Select WRAM + setprg8r(0x10,0x6000,0); } else - mapbyte1[1]=0xC0; + setprg8(0x6000,mapbyte1[1]); } -static void M69SC(void) +void Mapper69_ESI(void) { - if(FSettings.SndRate) - Mapper69_ESI(); - else - SetWriteHandler(0xc000,0xffff,(writefunc)0); + GameExpSound.RChange=Mapper69_ESI; + GameExpSound.HiSync=AYHiSync; + memset(dcount,0,sizeof(dcount)); + memset(vcount,0,sizeof(vcount)); + memset(CAYBC,0,sizeof(CAYBC)); } -void Mapper69_ESI(void) +void NSFAY_Init(void) { - GameExpSound.RChange=M69SC; - if(FSettings.SndRate) - { - SetWriteHandler(0xc000,0xdfff,Mapper69_SWL); - SetWriteHandler(0xe000,0xffff,Mapper69_SWH); - } + sunindex=0; + SetWriteHandler(0xc000,0xdfff,Mapper69_SWL); + SetWriteHandler(0xe000,0xffff,Mapper69_SWH); + Mapper69_ESI(); } void Mapper69_init(void) { + sunindex=0; + SetupCartPRGMapping(0x10,WRAM,8192,1); SetWriteHandler(0x8000,0xbfff,Mapper69_write); + SetWriteHandler(0xc000,0xdfff,Mapper69_SWL); + SetWriteHandler(0xe000,0xffff,Mapper69_SWH); SetWriteHandler(0x6000,0x7fff,SUN5BWRAM); SetReadHandler(0x6000,0x7fff,SUN5AWRAM); Mapper69_ESI(); MapIRQHook=SunIRQHook; MapStateRestore=Mapper69_StateRestore; - znreg=0; } diff --git a/mappers/71.c b/mappers/71.c index 4c34706..9b1a99d 100644 --- a/mappers/71.c +++ b/mappers/71.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -29,8 +29,7 @@ switch(A&0xF000) case 0xF000: case 0xE000: case 0xD000: - case 0xC000:ROM_BANK16(0x8000,V); - X6502_Rebase();break; + case 0xC000:ROM_BANK16(0x8000,V);break; case 0x9000:onemir((V>>3)&2);break; } } diff --git a/mappers/72.c b/mappers/72.c index c0a2c63..480a035 100644 --- a/mappers/72.c +++ b/mappers/72.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -25,10 +25,7 @@ DECLFW(Mapper72_write) { mapbyte1[0]=V; if(V&0x80) - { ROM_BANK16(0x8000,V&0xF); - X6502_Rebase(); - } if(V&0x40) VROM_BANK8(V&0xF); } diff --git a/mappers/73.c b/mappers/73.c index 0911fd8..b49fa24 100644 --- a/mappers/73.c +++ b/mappers/73.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -22,17 +22,19 @@ -DECLFW(Mapper73_write) +static DECLFW(Mapper73_write) { -switch(A&0xF000) + //if(A>=0xd000 && A<=0xdfff) + X6502_IRQEnd(FCEU_IQEXT); /* How are IRQs acknowledged on this chip? */ + switch(A&0xF000) { - case 0x8000:IRQCount&=0xFFF0;IRQCount|=(V&0xF);break; - case 0x9000:IRQCount&=0xFF0F;IRQCount|=(V&0xF)<<4;break; - case 0xa000:IRQCount&=0xF0FF;IRQCount|=(V&0xF)<<8;break; - case 0xb000:IRQCount&=0x0FFF;IRQCount|=(V&0xF)<<12;break; - case 0xc000:IRQa=V&2;break; - case 0xf000:ROM_BANK16(0x8000,V); - X6502_Rebase();break; + //default: printf("$%04x:$%02x\n",A,V);break; + case 0x8000:IRQCount&=0xFFF0;IRQCount|=(V&0xF);break; + case 0x9000:IRQCount&=0xFF0F;IRQCount|=(V&0xF)<<4;break; + case 0xa000:IRQCount&=0xF0FF;IRQCount|=(V&0xF)<<8;break; + case 0xb000:IRQCount&=0x0FFF;IRQCount|=(V&0xF)<<12;break; + case 0xc000:IRQa=V&2;break; + case 0xf000:ROM_BANK16(0x8000,V);break; } } @@ -45,7 +47,7 @@ static void FP_FASTAPASS(1) Mapper73IRQHook(int a) { IRQCount&=0xFFFF; IRQa=0; - TriggerIRQ(); + X6502_IRQBegin(FCEU_IQEXT); } } } diff --git a/mappers/75.c b/mappers/75.c index cf0c6ee..f2b00bd 100644 --- a/mappers/75.c +++ b/mappers/75.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -28,16 +28,13 @@ DECLFW(Mapper75_write) { switch(A&0xF000) { - case 0x8000:ROM_BANK8(0x8000,V); - X6502_Rebase();break; + case 0x8000:ROM_BANK8(0x8000,V);break; case 0x9000: VROM_BANK4(0x0000,map75ar[0]|((V&2)<<3)); VROM_BANK4(0x1000,map75ar[1]|((V&4)<<2)); map75sel=V;MIRROR_SET(V&1);break; - case 0xa000:ROM_BANK8(0xa000,V); - X6502_Rebase();break; - case 0xc000:ROM_BANK8(0xc000,V); - X6502_Rebase();break; + case 0xa000:ROM_BANK8(0xa000,V);break; + case 0xc000:ROM_BANK8(0xc000,V);break; case 0xe000:V&=0xF;map75ar[0]=V;V|=(map75sel&2)<<3;VROM_BANK4(0x0000,V);break; case 0xf000:V&=0xF;map75ar[1]=V;V|=(map75sel&4)<<2;VROM_BANK4(0x1000,V);break; } diff --git a/mappers/76.c b/mappers/76.c index 40aa821..a59ef1e 100644 --- a/mappers/76.c +++ b/mappers/76.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -19,10 +19,9 @@ */ #include "mapinc.h" +static uint8 MMC3_cmd; - - -DECLFW(Mapper76_write) +static DECLFW(Mapper76_write) { switch(A&0xE001){ case 0x8000: @@ -35,12 +34,10 @@ DECLFW(Mapper76_write) case 4: VROM_BANK2(0x1000,V);break; case 5: VROM_BANK2(0x1800,V);break; case 6: - if (MMC3_cmd&0x40) ROM_BANK8(0xC000,V); + if(MMC3_cmd&0x40) ROM_BANK8(0xC000,V); else ROM_BANK8(0x8000,V); - X6502_Rebase(); break; case 7: ROM_BANK8(0xA000,V); - X6502_Rebase(); break; } break; diff --git a/mappers/77.c b/mappers/77.c index e3c0e52..06f15cc 100644 --- a/mappers/77.c +++ b/mappers/77.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -27,18 +27,16 @@ static DECLFW(Mapper77_write) mapbyte1[0]=V; ROM_BANK32(V&0x7); VROM_BANK2(0x0000, (V&0xf0)>>4); - X6502_Rebase(); } static void Mapper77_StateRestore(int version) { int x; - - if(version>=72) + + if(version>=7200) { ROM_BANK32(mapbyte1[0]&0x7); VROM_BANK2(0x0000, (mapbyte1[0]&0xf0)>>4); - X6502_Rebase(); } for(x=2;x<8;x++) VRAM_BANK1(x*0x400,x); diff --git a/mappers/79.c b/mappers/79.c index 1e9d219..9148eae 100644 --- a/mappers/79.c +++ b/mappers/79.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -27,7 +27,6 @@ DECLFW(Mapper79_write) if(A<0x8000 && ((A^0x4100)==0)) { ROM_BANK32((V>>3)&1); - X6502_Rebase(); } VROM_BANK8(V); } diff --git a/mappers/8.c b/mappers/8.c index 46a7d00..53c91a2 100644 --- a/mappers/8.c +++ b/mappers/8.c @@ -1,8 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 1998 BERO - * Copyright (C) 2002 Ben Parnell + * 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 @@ -19,21 +18,17 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - #include "mapinc.h" - - -DECLFW(Mapper8_write) +static DECLFW(Mapper8_write) { ROM_BANK16(0x8000,V>>3); VROM_BANK8(V&7); - X6502_Rebase(); } void Mapper8_init(void) { - ROM_BANK32(0); + ROM_BANK32(0); SetWriteHandler(0x8000,0xFFFF,Mapper8_write); } diff --git a/mappers/80.c b/mappers/80.c index b867398..1e7982e 100644 --- a/mappers/80.c +++ b/mappers/80.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -20,33 +20,81 @@ #include "mapinc.h" +static uint32 lastA; +static int isfu; +static uint8 CCache[8]; +static void FP_FASTAPASS(1) Fudou_PPU(uint32 A) +{ + static int last=-1; + static uint8 z; + + if(A>=0x2000) return; + + A>>=10; + lastA=A; + + z=CCache[A]; + if(z!=last) + { + onemir(z); + last=z; + } +} + +static void mira() +{ + if(isfu) + { + int x; + CCache[0]=CCache[1]=mapbyte2[0]>>7; + CCache[2]=CCache[3]=mapbyte2[1]>>7; -DECLFW(Mapper80_write) + for(x=0;x<4;x++) + CCache[4+x]=mapbyte2[2+x]>>7; + + onemir(CCache[lastA]); + } + else + MIRROR_SET2(mapbyte1[0]&1); +} + +static DECLFW(Mapper80_write) { -switch(A) + switch(A) { - case 0x7ef0: VROM_BANK1(0x000,V);VROM_BANK1(0x400,(V+1));break; - case 0x7ef1: VROM_BANK1(0x800,V);VROM_BANK1(0xC00,(V+1));break; + case 0x7ef0: mapbyte2[0]=V;VROM_BANK2(0x0000,(V>>1)&0x3F);mira();break; + case 0x7ef1: mapbyte2[1]=V;VROM_BANK2(0x0800,(V>>1)&0x3f);mira();break; - case 0x7ef2: VROM_BANK1(0x1000,V);break; - case 0x7ef3: VROM_BANK1(0x1400,V);break; - case 0x7ef4: VROM_BANK1(0x1800,V);break; - case 0x7ef5: VROM_BANK1(0x1c00,V);break; + case 0x7ef2: mapbyte2[2]=V;VROM_BANK1(0x1000,V);mira();break; + case 0x7ef3: mapbyte2[3]=V;VROM_BANK1(0x1400,V);mira();break; + case 0x7ef4: mapbyte2[4]=V;VROM_BANK1(0x1800,V);mira();break; + case 0x7ef5: mapbyte2[5]=V;VROM_BANK1(0x1c00,V);mira();break; + case 0x7ef6: mapbyte1[0]=V;mira();break; case 0x7efa: - case 0x7efb: ROM_BANK8(0x8000,V); - X6502_Rebase();break; + case 0x7efb: ROM_BANK8(0x8000,V);break; case 0x7efd: - case 0x7efc: ROM_BANK8(0xA000,V); - X6502_Rebase();break; + case 0x7efc: ROM_BANK8(0xA000,V);break; case 0x7efe: - case 0x7eff: ROM_BANK8(0xC000,V); - X6502_Rebase();break; + case 0x7eff: ROM_BANK8(0xC000,V);break; } } +static void booga(int version) +{ + mira(); +} + void Mapper80_init(void) { -SetWriteHandler(0x4020,0x7fff,Mapper80_write); + SetWriteHandler(0x4020,0x7fff,Mapper80_write); + MapStateRestore=booga; + isfu=0; } +void Mapper207_init(void) +{ + Mapper80_init(); + isfu=1; + PPU_hook=Fudou_PPU; +} diff --git a/mappers/82.c b/mappers/82.c index a4f643e..b4288b1 100644 --- a/mappers/82.c +++ b/mappers/82.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -20,7 +20,7 @@ #include "mapinc.h" -#define ctrl mapbyte1[6] +#define ctrl mapbyte1[6] static void DoCHR(void) { @@ -43,15 +43,12 @@ static DECLFW(Mapper82_write) switch(A) { case 0x7ef6:ctrl=V&3; - MIRROR_SET2(V&1); - DoCHR(); - break; - case 0x7efa:V>>=2;mapbyte2[0]=V;ROM_BANK8(0x8000,V); - X6502_Rebase();break; - case 0x7efb:V>>=2;mapbyte2[1]=V;ROM_BANK8(0xa000,V); - X6502_Rebase();break; - case 0x7efc:V>>=2;mapbyte2[2]=V;ROM_BANK8(0xc000,V); - X6502_Rebase();break; + MIRROR_SET2(V&1); + DoCHR(); + break; + case 0x7efa:V>>=2;mapbyte2[0]=V;ROM_BANK8(0x8000,V);break; + case 0x7efb:V>>=2;mapbyte2[1]=V;ROM_BANK8(0xa000,V);break; + case 0x7efc:V>>=2;mapbyte2[2]=V;ROM_BANK8(0xc000,V);break; } } diff --git a/mappers/83.c b/mappers/83.c index 5cc7d03..3ab004f 100644 --- a/mappers/83.c +++ b/mappers/83.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -20,14 +20,20 @@ #include "mapinc.h" -void FP_FASTAPASS(1) m83IRQHook(int a) + +/*void Mapper83_init(void) +{ + +} +*/ +static void FP_FASTAPASS(1) m83IRQHook(int a) { if(IRQa) { IRQCount-=a; if(IRQCount<0) { - TriggerIRQ(); + X6502_IRQBegin(FCEU_IQEXT); IRQa=0; IRQCount=0xFFFF; } @@ -46,9 +52,8 @@ static DECLFR(rdlow) static void m83prg(void) { - ROM_BANK16(0x8000,mapbyte1[0]&0x3F); + ROM_BANK16(0x8000,(mapbyte1[0]&0x3F)); ROM_BANK16(0xC000,(mapbyte1[0]&0x30)|0xF); - X6502_Rebase(); } static void m83chr(void) @@ -82,11 +87,11 @@ static DECLFW(Mapper83_write) case 0x03:onemir(1);break; } break; - case 0x8200:IRQCount&=0xFF00;IRQCount|=V;break; + case 0x8200:IRQCount&=0xFF00;IRQCount|=V;X6502_IRQEnd(FCEU_IQEXT);break; case 0x8201:IRQa=1;IRQCount&=0xFF;IRQCount|=V<<8;break; - //case 0x8300:ROM_BANK8(0x8000,V);break; - //case 0x8301:ROM_BANK8(0xA000,V);break; - //case 0x8302:ROM_BANK8(0xC000,V);break; + case 0x8300:ROM_BANK8(0x8000,V);break; + case 0x8301:ROM_BANK8(0xA000,V);break; + case 0x8302:ROM_BANK8(0xC000,V);break; case 0x8310:mapbyte2[0]=V;m83chr();break; case 0x8311:mapbyte2[1]=V;m83chr();break; case 0x8312:mapbyte2[2]=V;m83chr();break; @@ -95,14 +100,14 @@ static DECLFW(Mapper83_write) case 0x8315:mapbyte2[5]=V;m83chr();break; case 0x8316:mapbyte2[6]=V;m83chr();break; case 0x8317:mapbyte2[7]=V;m83chr();break; + case 0x8318:mapbyte1[1]=V;m83prg();break; } // printf("$%04x:$%02x, $%04x\n",A,V,X.PC.W); - + } void Mapper83_init(void) { - ROM_BANK8(0xc000,0x1e); ROM_BANK8(0xe000,0x1f); @@ -111,4 +116,5 @@ void Mapper83_init(void) SetReadHandler(0x5100,0x5103,rdlow); SetWriteHandler(0x5100,0x5103,wrlow); SetWriteHandler(0x8000,0xffff,Mapper83_write); + mapbyte1[1]=0xF; } diff --git a/mappers/85.c b/mappers/85.c index c93788b..bae3b66 100644 --- a/mappers/85.c +++ b/mappers/85.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -21,16 +21,45 @@ #include "mapinc.h" #define vrctemp mapbyte1[0] -#define indox mapbyte1[1] +static uint8 indox; + +#include "emu2413.h" static int acount=0; -void KillOPL(void); -void UpdateOPL(int Count); -void vrc7translate(uint8 A, uint8 V); -void LoadOPL(void); -extern uint8 VRC7Instrument[16][8]; -extern uint8 VRC7Chan[3][6]; +static OPLL *VRC7Sound=NULL; +static int dwave=0; + +void DoVRC7Sound(void) +{ + int32 z,a; + + //if(FSettings.soundq>=1) return; + z=((SOUNDTS<<16)/soundtsinc)>>4; + a=z-dwave; + + moocow(VRC7Sound, &Wave[dwave], a, 1); + + dwave+=a; +} + +void UpdateOPLNEO(int32 *Wave, int Count) +{ + moocow(VRC7Sound, Wave, Count, 4); +} + +void UpdateOPL(int Count) +{ + int32 z,a; + + z=((SOUNDTS<<16)/soundtsinc)>>4; + a=z-dwave; + + if(VRC7Sound && a) + moocow(VRC7Sound, &Wave[dwave], a, 1); + + dwave=0; +} static INLINE void DaMirror(int V) { @@ -40,55 +69,64 @@ static INLINE void DaMirror(int V) DECLFW(Mapper85_write) { - A|=(A&8)<<1; - - if(A>=0xa000 && A<=0xDFFF) - { - A&=0xF010; - { - int x=((A>>4)&1)|((A-0xA000)>>11); - mapbyte3[x]=V; - setchr1(x<<10,V); - } - } - else if(A==0x9030) - { - if(FSettings.SndRate) - vrc7translate(indox,V); - GameExpSound.Fill=UpdateOPL; - } - else switch(A&0xF010) + A|=(A&8)<<1; + + if(A>=0xa000 && A<=0xDFFF) + { + // printf("$%04x, $%04x\n",X.PC,A); + A&=0xF010; + { + int x=((A>>4)&1)|((A-0xA000)>>11); + mapbyte3[x]=V; + setchr1(x<<10,V); + } + } + else if(A==0x9030) + { + if(FSettings.SndRate) + { + OPLL_writeReg(VRC7Sound, indox, V); + GameExpSound.Fill=UpdateOPL; + GameExpSound.NeoFill=UpdateOPLNEO; + } + } + else switch(A&0xF010) { - case 0x8000:mapbyte2[0]=V;setprg8(0x8000,V); - X6502_Rebase();break; - case 0x8010:mapbyte2[1]=V;setprg8(0xa000,V); - X6502_Rebase();break; - case 0x9000:mapbyte2[2]=V;setprg8(0xc000,V); - X6502_Rebase();break; + case 0x8000:mapbyte2[0]=V;setprg8(0x8000,V);break; + case 0x8010:mapbyte2[1]=V;setprg8(0xa000,V);break; + case 0x9000:mapbyte2[2]=V;setprg8(0xc000,V);break; case 0x9010:indox=V;break; case 0xe000:mapbyte2[3]=V;DaMirror(V);break; case 0xE010:IRQLatch=V; + X6502_IRQEnd(FCEU_IQEXT); break; case 0xF000:IRQa=V&2; vrctemp=V&1; - if(V&2) {IRQCount=IRQLatch;acount=0;} + if(V&2) {IRQCount=IRQLatch;} + acount=0; + X6502_IRQEnd(FCEU_IQEXT); break; case 0xf010:if(vrctemp) IRQa=1; else IRQa=0; + X6502_IRQEnd(FCEU_IQEXT); break; } } static void FP_FASTAPASS(1) KonamiIRQHook(int a) { + #define ACBOO 341 +// #define ACBOO ((227*2)+1) if(IRQa) { - acount+=(a<<1)+a; - if(acount>=339) + acount+=a*3; + + if(acount>=ACBOO) { - doagainbub:acount-=339;IRQCount++; - if(IRQCount&0x100) {TriggerIRQ();IRQCount=IRQLatch;} - if(acount>=339) goto doagainbub; + doagainbub:acount-=ACBOO; + IRQCount++; + if(IRQCount&0x100) {X6502_IRQBegin(FCEU_IQEXT);IRQCount=IRQLatch;} + if(acount>=ACBOO) goto doagainbub; } } } @@ -97,7 +135,7 @@ void Mapper85_StateRestore(int version) { int x; - if(version<72) + if(version<7200) { for(x=0;x<8;x++) mapbyte3[x]=CHRBankList[x]; @@ -111,22 +149,37 @@ void Mapper85_StateRestore(int version) for(x=0;x<3;x++) setprg8(0x8000+x*8192,mapbyte2[x]); DaMirror(mapbyte2[3]); - LoadOPL(); + //LoadOPL(); } static void M85SC(void) { - KillOPL(); + if(VRC7Sound) + OPLL_set_rate(VRC7Sound, FSettings.SndRate); } -void VRC7_ESI(void) +static void M85SKill(void) +{ + if(VRC7Sound) + OPLL_delete(VRC7Sound); + VRC7Sound=NULL; +} + +static void VRC7SI(void) +{ + GameExpSound.RChange=M85SC; + GameExpSound.Kill=M85SKill; + + VRC7Sound=OPLL_new(3579545, FSettings.SndRate?FSettings.SndRate:44100); + OPLL_reset(VRC7Sound); + OPLL_reset(VRC7Sound); +} + +void NSFVRC7_Init(void) { - if(FSettings.SndRate) - { SetWriteHandler(0x9010,0x901F,Mapper85_write); SetWriteHandler(0x9030,0x903F,Mapper85_write); - } - GameExpSound.RChange=M85SC; + VRC7SI(); } void Mapper85_init(void) @@ -134,10 +187,9 @@ void Mapper85_init(void) MapIRQHook=KonamiIRQHook; SetWriteHandler(0x8000,0xffff,Mapper85_write); GameStateRestore=Mapper85_StateRestore; - VRC7_ESI(); if(!VROM_size) SetupCartCHRMapping(0, CHRRAM, 8192, 1); - AddExState(VRC7Instrument, 16, 0, "VC7I"); - AddExState(VRC7Chan, sizeof(VRC7Chan), 0, "V7CH"); - + //AddExState(VRC7Instrument, 16, 0, "VC7I"); + //AddExState(VRC7Chan, sizeof(VRC7Chan), 0, "V7CH"); + VRC7SI(); } diff --git a/mappers/86.c b/mappers/86.c index 60777b8..8404985 100644 --- a/mappers/86.c +++ b/mappers/86.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -22,12 +22,17 @@ DECLFW(Mapper86_write) { - VROM_BANK8((V&3)|((V>>4)&4)); - ROM_BANK32((V>>4)&3); - X6502_Rebase(); + if(A>=0x6000 && A<=0x6fFF) + { + VROM_BANK8((V&3)|((V>>4)&4)); + ROM_BANK32((V>>4)&3); + } + //else + //if(A!=0x6000) + // printf("$%04x:$%02x\n",A,V); } - void Mapper86_init(void) { - SetWriteHandler(0x6000,0x6000,Mapper86_write); + SetWriteHandler(0x6000,0x6fff,Mapper86_write); + SetWriteHandler(0x4020,0xffff,Mapper86_write); } diff --git a/mappers/88.c b/mappers/88.c index 84c9ded..96ef0ed 100644 --- a/mappers/88.c +++ b/mappers/88.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -20,39 +20,43 @@ #include "mapinc.h" +static int mn; static DECLFW(Mapper88_write) { //if(A>=0x8002 || A<0x8000) //if(A==0xc000) // printf("$%04x:$%02x\n",A,V); - switch(A) //&0xc001) + switch(A&0x8001) //&0xc001) { - //case 0xc000: - //MIRROR_SET((V&0x40)>>6); - //onemir((V&0x40)>>6); - //break; - case 0x8000:mapbyte1[0]=V;break; + case 0x8000:mapbyte1[0]=V; + if(mn) + onemir((V>>6)&1); + break; case 0x8001: - switch(mapbyte1[0]&7) - { - case 0:VROM_BANK2(0,V>>1);break; - case 1:VROM_BANK2(0x800,V>>1);break; - case 2:VROM_BANK1(0x1000,V|0x40);break; - case 3:VROM_BANK1(0x1400,V|0x40);break; - case 4:VROM_BANK1(0x1800,V|0x40);break; - case 5:VROM_BANK1(0x1c00,V|0x40);break; - case 6:ROM_BANK8(0x8000,V); - X6502_Rebase();break; - case 7:ROM_BANK8(0xA000,V); - X6502_Rebase();break; - } - break; + switch(mapbyte1[0]&7) + { + case 0:VROM_BANK2(0,V>>1);break; + case 1:VROM_BANK2(0x800,V>>1);break; + case 2:VROM_BANK1(0x1000,V|0x40);break; + case 3:VROM_BANK1(0x1400,V|0x40);break; + case 4:VROM_BANK1(0x1800,V|0x40);break; + case 5:VROM_BANK1(0x1c00,V|0x40);break; + case 6:ROM_BANK8(0x8000,V);break; + case 7:ROM_BANK8(0xA000,V);break; + } + break; } } void Mapper88_init(void) { + mn=0; SetWriteHandler(0x8000,0xffff,Mapper88_write); } +void Mapper154_init(void) +{ + mn=1; + SetWriteHandler(0x8000,0xffff,Mapper88_write); +} diff --git a/mappers/89.c b/mappers/89.c index cdc028a..a3a6f09 100644 --- a/mappers/89.c +++ b/mappers/89.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -25,7 +25,6 @@ DECLFW(Mapper89_write) VROM_BANK8((V&7)|((V>>4)&8)); ROM_BANK16(0x8000,(V>>4)&7); onemir((V>>3)&1); - X6502_Rebase(); } void Mapper89_init(void) diff --git a/mappers/90.c b/mappers/90.c deleted file mode 100644 index 35ceb0d..0000000 --- a/mappers/90.c +++ /dev/null @@ -1,155 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell - * - * 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 tkcom1 mapbyte1[1] -#define tkcom2 mapbyte1[2] - -#define prgb mapbyte2 -#define unkl (mapbyte2+4) -#define chrlow mapbyte3 -#define chrhigh mapbyte4 - -static uint8 tekker=0x80; - -static DECLFR(tekread) -{ - return tekker; -} - -static void tekprom(void) -{ - switch(tkcom1&3) - { - case 1: // 16 KB - ROM_BANK16(0x8000,prgb[0]); - ROM_BANK16(0xC000,prgb[2]); - break; - - case 2: //2 = 8 KB ?? - case 3: - ROM_BANK8(0x8000,prgb[0]); - ROM_BANK8(0xa000,prgb[1]); - ROM_BANK8(0xc000,prgb[2]); - ROM_BANK8(0xe000,prgb[3]); - break; - } - X6502_Rebase(); -} - -static void tekvrom(void) -{ - int x; - switch(tkcom1&0x18) - { - case 0x00: // 8KB - VROM_BANK8(chrlow[0]|(chrhigh[0]<<8)); - break; - case 0x08: // 4KB - for(x=0;x<8;x+=4) - VROM_BANK4(x<<10,chrlow[x]|(chrhigh[x]<<8)); - break; - case 0x10: // 2KB - for(x=0;x<8;x+=2) - VROM_BANK2(x<<10,chrlow[x]|(chrhigh[x]<<8)); - break; - case 0x18: // 1KB - for(x=0;x<8;x++) - VROM_BANK1(x<<10,chrlow[x]|(chrhigh[x]<<8)); - break; - } -} - -static DECLFW(Mapper90_write) -{ - A&=0xF007; - - if(A>=0x8000 && A<=0x8003) - { - prgb[A&3]=V; - tekprom(); - } - else if(A>=0x9000 && A<=0x9007) - { - chrlow[A&7]=V; - tekvrom(); - } - else if(A>=0xa000 && A<=0xa007) - { - chrhigh[A&7]=V; - tekvrom(); - } - else if(A>=0xb000 && A<=0xb003) - { - unkl[A&3]=V; - } - else switch(A) - { - case 0xc004: - case 0xc000:IRQLatch=V;break; - - case 0xc005: - case 0xc001:X6502_IRQEnd(FCEU_IQEXT); - IRQCount=V;break; - case 0xc006: - case 0xc002:X6502_IRQEnd(FCEU_IQEXT); - IRQa=0; - IRQCount=IRQLatch; - break; - case 0xc007: - case 0xc003:IRQa=1;break; - - case 0xd000:tkcom1=V;break; - case 0xd001:switch(V&3){ - case 0x00:MIRROR_SET(0);break; - case 0x01:MIRROR_SET(1);break; - case 0x02:onemir(0);break; - case 0x03:onemir(1);break; - } - break; - break; - } -} - -static void Mapper90_hb(void) -{ - if(IRQa) - { - if(IRQCount) - { - IRQCount--; - if(!IRQCount) - { - X6502_IRQBegin(FCEU_IQEXT); - IRQCount=IRQLatch; - } - } - } -} - -void Mapper90_init(void) -{ - tekker^=0x80; - SetWriteHandler(0x8000,0xffff,Mapper90_write); - SetReadHandler(0x5000,0x5000,tekread); - GameHBIRQHook=Mapper90_hb; -} - diff --git a/mappers/91.c b/mappers/91.c new file mode 100644 index 0000000..8858103 --- /dev/null +++ b/mappers/91.c @@ -0,0 +1,59 @@ +/* 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 DECLFW(Mapper91_write) +{ +//if(A>=0x7001) +//printf("$%04x:$%02x, %d\n",A,V,scanline); + A&=0xF007; + + if(A>=0x6000 && A<=0x6003) VROM_BANK2((A&3)*2048,V); + else switch(A&0xF003) + { + case 0x7000: + case 0x7001:ROM_BANK8(0x8000+(A&1)*8192,V);break; + case 0x7002:IRQa=IRQCount=0;X6502_IRQEnd(FCEU_IQEXT);break; + case 0x7003:IRQa=1;X6502_IRQEnd(FCEU_IQEXT);break; +// default: printf("Iyee: $%04x:$%02x\n",A,V);break; + } + //if(A>=0x7000) + // printf("$%04x:$%02x, %d\n",A,V,scanline); +} + +static void Mapper91_hb(void) +{ + if(IRQCount<8 && IRQa) + { + IRQCount++; + if(IRQCount>=8) + { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +void Mapper91_init(void) +{ + SetWriteHandler(0x4020,0xFFFF,Mapper91_write); + GameHBIRQHook=Mapper91_hb; +} + diff --git a/mappers/92.c b/mappers/92.c index 4b8ce71..e2ad374 100644 --- a/mappers/92.c +++ b/mappers/92.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -29,12 +29,12 @@ static DECLFW(Mapper92_write) if(A>=0x9000) { - if(reg==0xD) { ROM_BANK16(0xc000,bank); X6502_Rebase(); } + if(reg==0xD) ROM_BANK16(0xc000,bank); else if(reg==0xE) VROM_BANK8(bank); } else { - if(reg==0xB) { ROM_BANK16(0xc000,bank); X6502_Rebase(); } + if(reg==0xB) ROM_BANK16(0xc000,bank); else if(reg==0x7) VROM_BANK8(bank); } } diff --git a/mappers/95.c b/mappers/95.c index 4b208be..11b6a8e 100644 --- a/mappers/95.c +++ b/mappers/95.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -20,8 +20,18 @@ #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} +}; -#define dbarray mapbyte1 static void FP_FASTAPASS(1) dragonbust_ppu(uint32 A) { static int last=-1; @@ -29,10 +39,11 @@ static void FP_FASTAPASS(1) dragonbust_ppu(uint32 A) if(A>=0x2000) return; - A>>=13; + A>>=10; - z=dbarray[A]; + lastA=A; + z=MirCache[A]; if(z!=last) { onemir(z); @@ -40,39 +51,86 @@ static void FP_FASTAPASS(1) dragonbust_ppu(uint32 A) } } +static void toot(void) +{ + int x; + + MirCache[0]=MirCache[1]=(DRegs[0]>>4)&1; + MirCache[2]=MirCache[3]=(DRegs[1]>>4)&1; -DECLFW(Mapper95_write) + for(x=0;x<4;x++) + MirCache[4+x]=(DRegs[2+x]>>5)&1; + onemir(MirCache[lastA]); +} + +static DECLFW(Mapper95_write) { - switch(A&0xF001){ - - case 0x8000: - MMC3_cmd = V; - break; - - case 0x8001: - switch(MMC3_cmd&7){ - case 0: dbarray[0]=dbarray[1]=(V&0x20)>>4;onemir((V&0x20)>>4);V>>=1;VROM_BANK2(0x0000,V);break; - case 1: dbarray[2]=dbarray[3]=(V&0x20)>>4;onemir((V&0x20)>>4);V>>=1;VROM_BANK2(0x0800,V);break; - case 2: dbarray[4]=(V&0x20)>>4;onemir((V&0x20)>>4);VROM_BANK1(0x1000,V); break; - case 3: dbarray[5]=(V&0x20)>>4;onemir((V&0x20)>>4);VROM_BANK1(0x1400,V); break; - case 4: dbarray[6]=(V&0x20)>>4;onemir((V&0x20)>>4);VROM_BANK1(0x1800,V); break; - case 5: dbarray[7]=(V&0x20)>>4;onemir((V&0x20)>>4);VROM_BANK1(0x1C00,V); break; - case 6: - ROM_BANK8(0x8000,V); - X6502_Rebase(); - break; - case 7: - ROM_BANK8(0xA000,V); - X6502_Rebase(); - break; + switch(A&0xF001) + { + + case 0x8000: + cmd = V; + break; + + case 0x8001: + switch(cmd&0x07) + { + case 0: DRegs[0]=(V&0x3F)>>1;toot();V>>=1;setchr2(0x0000,V&0x1F);break; + case 1: DRegs[1]=(V&0x3F)>>1;toot();V>>=1;setchr2(0x0800,V&0x1F);break; + case 2: DRegs[2]=V&0x3F;toot();setchr1(0x1000,V&0x1F); break; + case 3: DRegs[3]=V&0x3F;toot();setchr1(0x1400,V&0x1F); break; + case 4: DRegs[4]=V&0x3F;toot();setchr1(0x1800,V&0x1F); break; + case 5: DRegs[5]=V&0x3F;toot();setchr1(0x1C00,V&0x1F); break; + case 6: DRegs[6]=V&0x3F; + setprg8(0x8000,V); + break; + case 7: DRegs[7]=V&0x3F; + setprg8(0xA000,V); + break; } break; + } } + +static void DBSync() +{ + int x; + + setchr2(0x0000,DRegs[0]); + setchr2(0x0800,DRegs[1]); + + for(x=0;x<4;x++) + setchr1(0x1000+x*0x400,DRegs[2+x]); + + setprg8(0x8000,DRegs[6]); + setprg8(0xa000,DRegs[7]); + toot(); +} + +static void DBPower(void) +{ + memset(DRegs,0x3F,8); + DRegs[0]=DRegs[1]=0x1F; + + DBSync(); + + setprg8(0xc000,0x3E); + setprg8(0xe000,0x3F); + + SetReadHandler(0x8000,0xffff,CartBR); + SetWriteHandler(0x8000,0xffff,Mapper95_write); +} + +static void StateRestore(int version) +{ + DBSync(); } -void Mapper95_init(void) +void Mapper95_Init(CartInfo *info) { - SetWriteHandler(0x8000,0xffff,Mapper95_write); + info->Power=DBPower; + AddExState(DB_StateRegs, ~0, 0, 0); PPU_hook=dragonbust_ppu; + GameStateRestore=StateRestore; } diff --git a/mappers/97.c b/mappers/97.c index e02b12d..2990c0e 100644 --- a/mappers/97.c +++ b/mappers/97.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -25,7 +25,6 @@ DECLFW(Mapper97_write) { ROM_BANK16(0xC000,V&15); -X6502_Rebase(); switch(V>>6) { case 0:break; diff --git a/mappers/99.c b/mappers/99.c index c71611e..7a55536 100644 --- a/mappers/99.c +++ b/mappers/99.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -26,10 +26,12 @@ static DECLFW(morko) { VROM_BANK8((V>>2)&1); oldmorko(A,V); + setprg8(0x8000,V&0x4); /* Special for VS Gumshoe */ } void Mapper99_init(void) { + ROM_BANK32(0); oldmorko=GetWriteHandler(0x4016); SetWriteHandler(0x4016,0x4016,morko); } diff --git a/mappers/Makefile b/mappers/Makefile index c95ca8f..a29a0bf 100644 --- a/mappers/Makefile +++ b/mappers/Makefile @@ -1,74 +1,13 @@ -MOBJS = mappers/mmc2and4.o mappers/simple.o mappers/112.o mappers/117.o mappers/15.o mappers/151.o mappers/16.o mappers/17.o mappers/18.o mappers/180.o mappers/184.o mappers/19.o mappers/21.o mappers/22.o mappers/225.o mappers/226.o mappers/228.o mappers/229.o mappers/23.o mappers/24and26.o mappers/240.o mappers/246.o mappers/25.o mappers/32.o mappers/33.o mappers/40.o mappers/41.o mappers/6.o mappers/64.o mappers/65.o mappers/67.o mappers/68.o mappers/69.o mappers/71.o mappers/73.o mappers/75.o mappers/76.o mappers/79.o mappers/8.o mappers/80.o mappers/85.o mappers/90.o mappers/95.o mappers/97.o mappers/99.o mappers/182.o mappers/vrc7snd.o mappers/46.o mappers/43.o mappers/42.o mappers/113.o mappers/86.o mappers/89.o mappers/83.o mappers/77.o mappers/92.o mappers/105.o mappers/88.o mappers/248.o mappers/fmopl.o mappers/242.o mappers/232.o mappers/72.o mappers/234.o mappers/227.o mappers/82.o mappers/189.o mappers/245.o mappers/249.o mappers/51.o +MOBJS += mappers/6.o mappers/8.o mappers/15.o mappers/16.o mappers/17.o mappers/18.o mappers/21.o mappers/22.o +MOBJS += mappers/23.o mappers/24and26.o mappers/25.o mappers/27.o mappers/32.o mappers/33.o mappers/40.o +MOBJS += mappers/41.o mappers/42.o mappers/43.o mappers/46.o mappers/50.o mappers/51.o mappers/57.o mappers/58.o +MOBJS += mappers/59.o mappers/60.o mappers/61.o mappers/62.o mappers/65.o mappers/67.o mappers/68.o mappers/69.o +MOBJS += mappers/71.o mappers/72.o mappers/73.o mappers/75.o mappers/76.o mappers/77.o mappers/79.o mappers/80.o +MOBJS += mappers/82.o mappers/83.o mappers/85.o mappers/86.o mappers/88.o mappers/89.o mappers/91.o mappers/92.o +MOBJS += mappers/95.o mappers/97.o mappers/99.o mappers/113.o mappers/117.o mappers/151.o mappers/180.o mappers/183.o +MOBJS += mappers/184.o mappers/187.o mappers/189.o mappers/193.o mappers/200.o mappers/201.o mappers/202.o mappers/203.o +MOBJS += mappers/204.o mappers/208.o mappers/211.o mappers/212.o mappers/213.o mappers/214.o mappers/215.o +MOBJS += mappers/217.o mappers/225.o mappers/226.o mappers/227.o mappers/228.o mappers/229.o mappers/230.o mappers/231.o +MOBJS += mappers/232.o mappers/234.o mappers/235.o mappers/240.o mappers/241.o mappers/242.o mappers/244.o mappers/246.o +MOBJS += mappers/255.o mappers/emu2413.o mappers/mmc2and4.o mappers/simple.o -fmopl.o: mappers/fmopl.c mappers/fmopl.h -vrc7snd.o: mappers/vrc7snd.c - -mappers/simple.o: mappers/simple.c -mappers/mmc2and4.o: mappers/mmc2and4.c - -mappers/112.o: mappers/112.c -mappers/117.o: mappers/117.c -mappers/15.o: mappers/15.c -mappers/151.o: mappers/151.c -mappers/16.o: mappers/16.c -mappers/17.o: mappers/17.c -mappers/18.o: mappers/18.c -mappers/19.o: mappers/19.c -mappers/180.o: mappers/180.c -mappers/184.o: mappers/184.c -mappers/21.o: mappers/21.c -mappers/22.o: mappers/22.c -mappers/23.o: mappers/23.c -mappers/24and26.o: mappers/24and26.c -mappers/25.o: mappers/25.c -mappers/225.o: mappers/225.c -mappers/226.o: mappers/226.c -mappers/228.o: mappers/228.c -mappers/229.o: mappers/229.c -mappers/240.o: mappers/240.c -mappers/246.o: mappers/246.c -mappers/32.o: mappers/32.c -mappers/33.o: mappers/33.c -mappers/40.o: mappers/40.c -mappers/41.o: mappers/41.c -mappers/6.o: mappers/6.c -mappers/64.o: mappers/64.c -mappers/65.o: mappers/65.c -mappers/67.o: mappers/67.c -mappers/68.o: mappers/68.c -mappers/69.o: mappers/69.c -mappers/71.o: mappers/71.c -mappers/73.o: mappers/73.c -mappers/75.o: mappers/75.c -mappers/76.o: mappers/76.c -mappers/79.o: mappers/79.c -mappers/8.o: mappers/8.c -mappers/80.o: mappers/80.c -mappers/85.o: mappers/85.c -mappers/90.o: mappers/90.c -mappers/95.o: mappers/95.c -mappers/97.o: mappers/97.c -mappers/99.o: mappers/99.c -mappers/182.o: mappers/182.c -mappers/46.o: mappers/46.c -mappers/43.o: mappers/43.c -mappers/42.o: mappers/42.c -mappers/113.o: mappers/113.c -mappers/86.o: mappers/86.c -mappers/89.o: mappers/89.c -mappers/83.o: mappers/83.c -mappers/77.o: mappers/77.c -mappers/92.o: mappers/92.c -mappers/105.o: mappers/105.c -mappers/88.o: mappers/88.c -mappers/248.o: mappers/248.c -mappers/242.o: mappers/242.c -mappers/232.o: mappers/232.c -mappers/72.o: mappers/72.c -mappers/234.o: mappers/234.c -mappers/227.o: mappers/227.c -mappers/82.o: mappers/82.c -mappers/189.o: mappers/189.c -mappers/245.o: mappers/245.c -mappers/249.o: mappers/249.c -mappers/51.o: mappers/51.c diff --git a/mappers/emu2413.c b/mappers/emu2413.c new file mode 100644 index 0000000..49aa339 --- /dev/null +++ b/mappers/emu2413.c @@ -0,0 +1,1300 @@ +/*********************************************************************************** + + emu2413.c -- YM2413 emulator written by Mitsutaka Okazaki 2001 + + 2001 01-08 : Version 0.10 -- 1st version. + 2001 01-15 : Version 0.20 -- semi-public version. + 2001 01-16 : Version 0.30 -- 1st public version. + 2001 01-17 : Version 0.31 -- Fixed bassdrum problem. + : Version 0.32 -- LPF implemented. + 2001 01-18 : Version 0.33 -- Fixed the drum problem, refine the mix-down method. + -- Fixed the LFO bug. + 2001 01-24 : Version 0.35 -- Fixed the drum problem, + support undocumented EG behavior. + 2001 02-02 : Version 0.38 -- Improved the performance. + Fixed the hi-hat and cymbal model. + Fixed the default percussive datas. + Noise reduction. + Fixed the feedback problem. + 2001 03-03 : Version 0.39 -- Fixed some drum bugs. + Improved the performance. + 2001 03-04 : Version 0.40 -- Improved the feedback. + Change the default table size. + Clock and Rate can be changed during play. + 2001 06-24 : Version 0.50 -- Improved the hi-hat and the cymbal tone. + Added VRC7 patch (OPLL_reset_patch is changed). + Fixed OPLL_reset() bug. + Added OPLL_setMask, OPLL_getMask and OPLL_toggleMask. + Added OPLL_writeIO. + 2001 09-28 : Version 0.51 -- Removed the noise table. + 2002 01-28 : Version 0.52 -- Added Stereo mode. + 2002 02-07 : Version 0.53 -- Fixed some drum bugs. + 2002 02-20 : Version 0.54 -- Added the best quality mode. + 2002 03-02 : Version 0.55 -- Removed OPLL_init & OPLL_close. + 2002 05-30 : Version 0.60 -- Fixed HH&CYM generator and all voice datas. + + 2004 01-24 : Modified by xodnizel to remove code not needed for the VRC7, among other things. + + References: + fmopl.c -- 1999,2000 written by Tatsuyuki Satoh (MAME development). + fmopl.c(fixed) -- (C) 2002 Jarek Burczynski. + s_opl.c -- 2001 written by Mamiya (NEZplug development). + fmgen.cpp -- 1999,2000 written by cisc. + fmpac.ill -- 2000 created by NARUTO. + MSX-Datapack + YMU757 data sheet + YM2143 data sheet + +**************************************************************************************/ +#include +#include +#include +#include +#include "emu2413.h" + +static const unsigned char default_inst[15][8] = { + #include "vrc7tone.h" +}; + +/* Size of Sintable ( 8 -- 18 can be used. 9 recommended.)*/ +#define PG_BITS 9 +#define PG_WIDTH (1<>(b)) + +/* Leave the lower b bit(s). */ +#define LOWBITS(c,b) ((c)&((1<<(b))-1)) + +/* Expand x which is s bits to d bits. */ +#define EXPAND_BITS(x,s,d) ((x)<<((d)-(s))) + +/* Expand x which is s bits to d bits and fill expanded bits '1' */ +#define EXPAND_BITS_X(x,s,d) (((x)<<((d)-(s)))|((1<<((d)-(s)))-1)) + +/* Adjust envelope speed which depends on sampling rate. */ +#define rate_adjust(x) (rate==49716?x:(e_uint32)((double)(x)*clk/72/rate + 0.5)) /* added 0.5 to round the value*/ + +#define MOD(o,x) (&(o)->slot[(x)<<1]) +#define CAR(o,x) (&(o)->slot[((x)<<1)|1]) + +#define BIT(s,b) (((s)>>(b))&1) + +/* Input clock */ +static e_uint32 clk = 844451141; +/* Sampling rate */ +static e_uint32 rate = 3354932; + +/* WaveTable for each envelope amp */ +static e_uint16 fullsintable[PG_WIDTH]; +static e_uint16 halfsintable[PG_WIDTH]; + +static e_uint16 *waveform[2] = { fullsintable, halfsintable }; + +/* LFO Table */ +static e_int32 pmtable[PM_PG_WIDTH]; +static e_int32 amtable[AM_PG_WIDTH]; + +/* Phase delta for LFO */ +static e_uint32 pm_dphase; +static e_uint32 am_dphase; + +/* dB to Liner table */ +static e_int16 DB2LIN_TABLE[(DB_MUTE + DB_MUTE) * 2]; + +/* Liner to Log curve conversion table (for Attack rate). */ +static e_uint16 AR_ADJUST_TABLE[1 << EG_BITS]; + +/* Definition of envelope mode */ +enum +{ SETTLE, ATTACK, DECAY, SUSHOLD, SUSTINE, RELEASE, FINISH }; + +/* Phase incr table for Attack */ +static e_uint32 dphaseARTable[16][16]; +/* Phase incr table for Decay and Release */ +static e_uint32 dphaseDRTable[16][16]; + +/* KSL + TL Table */ +static e_uint32 tllTable[16][8][1 << TL_BITS][4]; +static e_int32 rksTable[2][8][2]; + +/* Phase incr table for PG */ +static e_uint32 dphaseTable[512][8][16]; + +/*************************************************** + + Create tables + +****************************************************/ +INLINE static e_int32 +Min (e_int32 i, e_int32 j) +{ + if(i < j) + return i; + else + return j; +} + +/* Table for AR to LogCurve. */ +static void +makeAdjustTable (void) +{ + e_int32 i; + + AR_ADJUST_TABLE[0] = (1 << EG_BITS); + for (i = 1; i < 128; i++) + AR_ADJUST_TABLE[i] = (e_uint16) ((double) (1 << EG_BITS) - 1 - (1 << EG_BITS) * log (i) / log (128)); +} + + +/* Table for dB(0 -- (1<= DB_MUTE) DB2LIN_TABLE[i] = 0; + DB2LIN_TABLE[i + DB_MUTE + DB_MUTE] = (e_int16) (-DB2LIN_TABLE[i]); + } +} + +/* Liner(+0.0 - +1.0) to dB((1<> (20 - DP_BITS)); +} + +static void +makeTllTable (void) +{ +#define dB2(x) ((x)*2) + + static double kltable[16] = { + dB2 (0.000), dB2 (9.000), dB2 (12.000), dB2 (13.875), dB2 (15.000), dB2 (16.125), dB2 (16.875), dB2 (17.625), + dB2 (18.000), dB2 (18.750), dB2 (19.125), dB2 (19.500), dB2 (19.875), dB2 (20.250), dB2 (20.625), dB2 (21.000) + }; + + e_int32 tmp; + e_int32 fnum, block, TL, KL; + + for (fnum = 0; fnum < 16; fnum++) + for (block = 0; block < 8; block++) + for (TL = 0; TL < 64; TL++) + for (KL = 0; KL < 4; KL++) + { + if(KL == 0) + { + tllTable[fnum][block][TL][KL] = TL2EG (TL); + } + else + { + tmp = (e_int32) (kltable[fnum] - dB2 (3.000) * (7 - block)); + if(tmp <= 0) + tllTable[fnum][block][TL][KL] = TL2EG (TL); + else + tllTable[fnum][block][TL][KL] = (e_uint32) ((tmp >> (3 - KL)) / EG_STEP) + TL2EG (TL); + } + } +} + +#ifdef USE_SPEC_ENV_SPEED +static double attacktime[16][4] = { + {0, 0, 0, 0}, + {1730.15, 1400.60, 1153.43, 988.66}, + {865.08, 700.30, 576.72, 494.33}, + {432.54, 350.15, 288.36, 247.16}, + {216.27, 175.07, 144.18, 123.58}, + {108.13, 87.54, 72.09, 61.79}, + {54.07, 43.77, 36.04, 30.90}, + {27.03, 21.88, 18.02, 15.45}, + {13.52, 10.94, 9.01, 7.72}, + {6.76, 5.47, 4.51, 3.86}, + {3.38, 2.74, 2.25, 1.93}, + {1.69, 1.37, 1.13, 0.97}, + {0.84, 0.70, 0.60, 0.54}, + {0.50, 0.42, 0.34, 0.30}, + {0.28, 0.22, 0.18, 0.14}, + {0.00, 0.00, 0.00, 0.00} +}; + +static double decaytime[16][4] = { + {0, 0, 0, 0}, + {20926.60, 16807.20, 14006.00, 12028.60}, + {10463.30, 8403.58, 7002.98, 6014.32}, + {5231.64, 4201.79, 3501.49, 3007.16}, + {2615.82, 2100.89, 1750.75, 1503.58}, + {1307.91, 1050.45, 875.37, 751.79}, + {653.95, 525.22, 437.69, 375.90}, + {326.98, 262.61, 218.84, 187.95}, + {163.49, 131.31, 109.42, 93.97}, + {81.74, 65.65, 54.71, 46.99}, + {40.87, 32.83, 27.36, 23.49}, + {20.44, 16.41, 13.68, 11.75}, + {10.22, 8.21, 6.84, 5.87}, + {5.11, 4.10, 3.42, 2.94}, + {2.55, 2.05, 1.71, 1.47}, + {1.27, 1.27, 1.27, 1.27} +}; +#endif + +/* Rate Table for Attack */ +static void +makeDphaseARTable (void) +{ + e_int32 AR, Rks, RM, RL; +#ifdef USE_SPEC_ENV_SPEED + e_uint32 attacktable[16][4]; + + for (RM = 0; RM < 16; RM++) + for (RL = 0; RL < 4; RL++) + { + if(RM == 0) + attacktable[RM][RL] = 0; + else if(RM == 15) + attacktable[RM][RL] = EG_DP_WIDTH; + else + attacktable[RM][RL] = (e_uint32) ((double) (1 << EG_DP_BITS) / (attacktime[RM][RL] * 3579545 / 72000)); + + } +#endif + + for (AR = 0; AR < 16; AR++) + for (Rks = 0; Rks < 16; Rks++) + { + RM = AR + (Rks >> 2); + RL = Rks & 3; + if(RM > 15) + RM = 15; + switch (AR) + { + case 0: + dphaseARTable[AR][Rks] = 0; + break; + case 15: + dphaseARTable[AR][Rks] = 0;/*EG_DP_WIDTH;*/ + break; + default: +#ifdef USE_SPEC_ENV_SPEED + dphaseARTable[AR][Rks] = rate_adjust (attacktable[RM][RL]); +#else + dphaseARTable[AR][Rks] = rate_adjust ((3 * (RL + 4) << (RM + 1))); +#endif + break; + } + } +} + +/* Rate Table for Decay and Release */ +static void +makeDphaseDRTable (void) +{ + e_int32 DR, Rks, RM, RL; + +#ifdef USE_SPEC_ENV_SPEED + e_uint32 decaytable[16][4]; + + for (RM = 0; RM < 16; RM++) + for (RL = 0; RL < 4; RL++) + if(RM == 0) + decaytable[RM][RL] = 0; + else + decaytable[RM][RL] = (e_uint32) ((double) (1 << EG_DP_BITS) / (decaytime[RM][RL] * 3579545 / 72000)); +#endif + + for (DR = 0; DR < 16; DR++) + for (Rks = 0; Rks < 16; Rks++) + { + RM = DR + (Rks >> 2); + RL = Rks & 3; + if(RM > 15) + RM = 15; + switch (DR) + { + case 0: + dphaseDRTable[DR][Rks] = 0; + break; + default: +#ifdef USE_SPEC_ENV_SPEED + dphaseDRTable[DR][Rks] = rate_adjust (decaytable[RM][RL]); +#else + dphaseDRTable[DR][Rks] = rate_adjust ((RL + 4) << (RM - 1)); +#endif + break; + } + } +} + +static void +makeRksTable (void) +{ + + e_int32 fnum8, block, KR; + + for (fnum8 = 0; fnum8 < 2; fnum8++) + for (block = 0; block < 8; block++) + for (KR = 0; KR < 2; KR++) + { + if(KR != 0) + rksTable[fnum8][block][KR] = (block << 1) + fnum8; + else + rksTable[fnum8][block][KR] = block >> 1; + } +} + +/************************************************************ + + Calc Parameters + +************************************************************/ + +INLINE static e_uint32 +calc_eg_dphase (OPLL_SLOT * slot) +{ + + switch (slot->eg_mode) + { + case ATTACK: + return dphaseARTable[slot->patch.AR][slot->rks]; + + case DECAY: + return dphaseDRTable[slot->patch.DR][slot->rks]; + + case SUSHOLD: + return 0; + + case SUSTINE: + return dphaseDRTable[slot->patch.RR][slot->rks]; + + case RELEASE: + if(slot->sustine) + return dphaseDRTable[5][slot->rks]; + else if(slot->patch.EG) + return dphaseDRTable[slot->patch.RR][slot->rks]; + else + return dphaseDRTable[7][slot->rks]; + + case FINISH: + return 0; + + default: + return 0; + } +} + +/************************************************************* + + OPLL internal interfaces + +*************************************************************/ + +#define UPDATE_PG(S) (S)->dphase = dphaseTable[(S)->fnum][(S)->block][(S)->patch.ML] +#define UPDATE_TLL(S)\ +(((S)->type==0)?\ +((S)->tll = tllTable[((S)->fnum)>>5][(S)->block][(S)->patch.TL][(S)->patch.KL]):\ +((S)->tll = tllTable[((S)->fnum)>>5][(S)->block][(S)->volume][(S)->patch.KL])) +#define UPDATE_RKS(S) (S)->rks = rksTable[((S)->fnum)>>8][(S)->block][(S)->patch.KR] +#define UPDATE_WF(S) (S)->sintbl = waveform[(S)->patch.WF] +#define UPDATE_EG(S) (S)->eg_dphase = calc_eg_dphase(S) +#define UPDATE_ALL(S)\ + UPDATE_PG(S);\ + UPDATE_TLL(S);\ + UPDATE_RKS(S);\ + UPDATE_WF(S); \ + UPDATE_EG(S) /* EG should be updated last. */ + + +/* Slot key on */ +INLINE static void +slotOn (OPLL_SLOT * slot) +{ + slot->eg_mode = ATTACK; + slot->eg_phase = 0; + slot->phase = 0; +} + +/* Slot key on without reseting the phase */ +INLINE static void +slotOn2 (OPLL_SLOT * slot) +{ + slot->eg_mode = ATTACK; + slot->eg_phase = 0; +} + +/* Slot key off */ +INLINE static void +slotOff (OPLL_SLOT * slot) +{ + if(slot->eg_mode == ATTACK) + slot->eg_phase = EXPAND_BITS (AR_ADJUST_TABLE[HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS)], EG_BITS, EG_DP_BITS); + slot->eg_mode = RELEASE; +} + +/* Channel key on */ +INLINE static void +keyOn (OPLL * opll, e_int32 i) +{ + if(!opll->slot_on_flag[i * 2]) + slotOn (MOD(opll,i)); + if(!opll->slot_on_flag[i * 2 + 1]) + slotOn (CAR(opll,i)); + opll->key_status[i] = 1; +} + +/* Channel key off */ +INLINE static void +keyOff (OPLL * opll, e_int32 i) +{ + if(opll->slot_on_flag[i * 2 + 1]) + slotOff (CAR(opll,i)); + opll->key_status[i] = 0; +} + +/* Set sustine parameter */ +INLINE static void +setSustine (OPLL * opll, e_int32 c, e_int32 sustine) +{ + CAR(opll,c)->sustine = sustine; + if(MOD(opll,c)->type) + MOD(opll,c)->sustine = sustine; +} + +/* Volume : 6bit ( Volume register << 2 ) */ +INLINE static void +setVolume (OPLL * opll, e_int32 c, e_int32 volume) +{ + CAR(opll,c)->volume = volume; +} + +INLINE static void +setSlotVolume (OPLL_SLOT * slot, e_int32 volume) +{ + slot->volume = volume; +} + +/* Set F-Number ( fnum : 9bit ) */ +INLINE static void +setFnumber (OPLL * opll, e_int32 c, e_int32 fnum) +{ + CAR(opll,c)->fnum = fnum; + MOD(opll,c)->fnum = fnum; +} + +/* Set Block data (block : 3bit ) */ +INLINE static void +setBlock (OPLL * opll, e_int32 c, e_int32 block) +{ + CAR(opll,c)->block = block; + MOD(opll,c)->block = block; +} + +INLINE static void update_key_status (OPLL * opll) +{ + int ch; + + for (ch = 0; ch < 6; ch++) + opll->slot_on_flag[ch * 2] = opll->slot_on_flag[ch * 2 + 1] = (opll->HiFreq[ch]) & 0x10; +} + +/*********************************************************** + + Initializing + +***********************************************************/ + +static void +OPLL_SLOT_reset (OPLL_SLOT * slot, int type) +{ + slot->type = type; + slot->sintbl = waveform[0]; + slot->phase = 0; + slot->dphase = 0; + slot->output[0] = 0; + slot->output[1] = 0; + slot->feedback = 0; + slot->eg_mode = SETTLE; + slot->eg_phase = EG_DP_WIDTH; + slot->eg_dphase = 0; + slot->rks = 0; + slot->tll = 0; + slot->sustine = 0; + slot->fnum = 0; + slot->block = 0; + slot->volume = 0; + slot->pgout = 0; + slot->egout = 0; +} + +static void +internal_refresh (void) +{ + makeDphaseTable (); + makeDphaseARTable (); + makeDphaseDRTable (); + pm_dphase = (e_uint32) rate_adjust (PM_SPEED * PM_DP_WIDTH / (clk / 72)); + am_dphase = (e_uint32) rate_adjust (AM_SPEED * AM_DP_WIDTH / (clk / 72)); +} + +static void +maketables (e_uint32 c, e_uint32 r) +{ + if(c != clk) + { + clk = c; + makePmTable (); + makeAmTable (); + makeDB2LinTable (); + makeAdjustTable (); + makeTllTable (); + makeRksTable (); + makeSinTable (); + //makeDefaultPatch (); + } + + if(r != rate) + { + rate = r; + internal_refresh (); + } +} + +OPLL *OPLL_new (e_uint32 clk, e_uint32 rate) +{ + OPLL *opll; + + maketables (clk, rate); + + opll = (OPLL *) calloc (sizeof (OPLL), 1); + if(opll == NULL) + return NULL; + + opll->mask = 0; + + OPLL_reset (opll); + + return opll; +} + + +void +OPLL_delete (OPLL * opll) +{ + free (opll); +} + +/* Reset whole of OPLL except patch datas. */ +void +OPLL_reset (OPLL * opll) +{ + e_int32 i; + + if(!opll) + return; + + opll->adr = 0; + opll->out = 0; + + opll->pm_phase = 0; + opll->am_phase = 0; + + opll->mask = 0; + + for (i = 0; i < 12; i++) + OPLL_SLOT_reset(&opll->slot[i], i%2); + + for (i = 0; i < 6; i++) + { + opll->key_status[i] = 0; + //setPatch (opll, i, 0); + } + + for (i = 0; i < 0x40; i++) + OPLL_writeReg (opll, i, 0); + +#ifndef EMU2413_COMPACTION + opll->realstep = (e_uint32) ((1 << 31) / rate); + opll->opllstep = (e_uint32) ((1 << 31) / (clk / 72)); + opll->oplltime = 0; +#endif +} + +/* Force Refresh (When external program changes some parameters). */ +void +OPLL_forceRefresh (OPLL * opll) +{ + e_int32 i; + + if(opll == NULL) + return; + + for (i = 0; i < 12; i++) + { + UPDATE_PG (&opll->slot[i]); + UPDATE_RKS (&opll->slot[i]); + UPDATE_TLL (&opll->slot[i]); + UPDATE_WF (&opll->slot[i]); + UPDATE_EG (&opll->slot[i]); + } +} + +void +OPLL_set_rate (OPLL * opll, e_uint32 r) +{ + if(opll->quality) + rate = 49716; + else + rate = r; + internal_refresh (); + rate = r; +} + +void +OPLL_set_quality (OPLL * opll, e_uint32 q) +{ + opll->quality = q; + OPLL_set_rate (opll, rate); +} + +/********************************************************* + + Generate wave data + +*********************************************************/ +/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 2PI). */ +#if( SLOT_AMP_BITS - PG_BITS ) > 0 +#define wave2_2pi(e) ( (e) >> ( SLOT_AMP_BITS - PG_BITS )) +#else +#define wave2_2pi(e) ( (e) << ( PG_BITS - SLOT_AMP_BITS )) +#endif + +/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 4PI). */ +#if( SLOT_AMP_BITS - PG_BITS - 1 ) == 0 +#define wave2_4pi(e) (e) +#elif( SLOT_AMP_BITS - PG_BITS - 1 ) > 0 +#define wave2_4pi(e) ( (e) >> ( SLOT_AMP_BITS - PG_BITS - 1 )) +#else +#define wave2_4pi(e) ( (e) << ( 1 + PG_BITS - SLOT_AMP_BITS )) +#endif + +/* Convert Amp(0 to EG_HEIGHT) to Phase(0 to 8PI). */ +#if( SLOT_AMP_BITS - PG_BITS - 2 ) == 0 +#define wave2_8pi(e) (e) +#elif( SLOT_AMP_BITS - PG_BITS - 2 ) > 0 +#define wave2_8pi(e) ( (e) >> ( SLOT_AMP_BITS - PG_BITS - 2 )) +#else +#define wave2_8pi(e) ( (e) << ( 2 + PG_BITS - SLOT_AMP_BITS )) +#endif + + + +/* Update AM, PM unit */ +static void +update_ampm (OPLL * opll) +{ + opll->pm_phase = (opll->pm_phase + pm_dphase) & (PM_DP_WIDTH - 1); + opll->am_phase = (opll->am_phase + am_dphase) & (AM_DP_WIDTH - 1); + opll->lfo_am = amtable[HIGHBITS (opll->am_phase, AM_DP_BITS - AM_PG_BITS)]; + opll->lfo_pm = pmtable[HIGHBITS (opll->pm_phase, PM_DP_BITS - PM_PG_BITS)]; +} + +/* PG */ +INLINE static void +calc_phase (OPLL_SLOT * slot, e_int32 lfo) +{ + if(slot->patch.PM) + slot->phase += (slot->dphase * lfo) >> PM_AMP_BITS; + else + slot->phase += slot->dphase; + + slot->phase &= (DP_WIDTH - 1); + + slot->pgout = HIGHBITS (slot->phase, DP_BASE_BITS); +} + +/* EG */ +static void +calc_envelope (OPLL_SLOT * slot, e_int32 lfo) +{ +#define S2E(x) (SL2EG((e_int32)(x/SL_STEP))<<(EG_DP_BITS-EG_BITS)) + + static e_uint32 SL[16] = { + S2E (0.0), S2E (3.0), S2E (6.0), S2E (9.0), S2E (12.0), S2E (15.0), S2E (18.0), S2E (21.0), + S2E (24.0), S2E (27.0), S2E (30.0), S2E (33.0), S2E (36.0), S2E (39.0), S2E (42.0), S2E (48.0) + }; + + e_uint32 egout; + + switch (slot->eg_mode) + { + + case ATTACK: + egout = AR_ADJUST_TABLE[HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS)]; + slot->eg_phase += slot->eg_dphase; + if((EG_DP_WIDTH & slot->eg_phase)||(slot->patch.AR==15)) + { + egout = 0; + slot->eg_phase = 0; + slot->eg_mode = DECAY; + UPDATE_EG (slot); + } + break; + + case DECAY: + egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS); + slot->eg_phase += slot->eg_dphase; + if(slot->eg_phase >= SL[slot->patch.SL]) + { + if(slot->patch.EG) + { + slot->eg_phase = SL[slot->patch.SL]; + slot->eg_mode = SUSHOLD; + UPDATE_EG (slot); + } + else + { + slot->eg_phase = SL[slot->patch.SL]; + slot->eg_mode = SUSTINE; + UPDATE_EG (slot); + } + } + break; + + case SUSHOLD: + egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS); + if(slot->patch.EG == 0) + { + slot->eg_mode = SUSTINE; + UPDATE_EG (slot); + } + break; + + case SUSTINE: + case RELEASE: + egout = HIGHBITS (slot->eg_phase, EG_DP_BITS - EG_BITS); + slot->eg_phase += slot->eg_dphase; + if(egout >= (1 << EG_BITS)) + { + slot->eg_mode = FINISH; + egout = (1 << EG_BITS) - 1; + } + break; + + case FINISH: + egout = (1 << EG_BITS) - 1; + break; + + default: + egout = (1 << EG_BITS) - 1; + break; + } + + if(slot->patch.AM) + egout = EG2DB (egout + slot->tll) + lfo; + else + egout = EG2DB (egout + slot->tll); + + if(egout >= DB_MUTE) + egout = DB_MUTE - 1; + + slot->egout = egout; +} + +/* CARRIOR */ +INLINE static e_int32 +calc_slot_car (OPLL_SLOT * slot, e_int32 fm) +{ + slot->output[1] = slot->output[0]; + + if(slot->egout >= (DB_MUTE - 1)) + { + slot->output[0] = 0; + } + else + { + slot->output[0] = DB2LIN_TABLE[slot->sintbl[(slot->pgout+wave2_8pi(fm))&(PG_WIDTH-1)] + slot->egout]; + } + + return (slot->output[1] + slot->output[0]) >> 1; +} + +/* MODULATOR */ +INLINE static e_int32 +calc_slot_mod (OPLL_SLOT * slot) +{ + e_int32 fm; + + slot->output[1] = slot->output[0]; + + if(slot->egout >= (DB_MUTE - 1)) + { + slot->output[0] = 0; + } + else if(slot->patch.FB != 0) + { + fm = wave2_4pi (slot->feedback) >> (7 - slot->patch.FB); + slot->output[0] = DB2LIN_TABLE[slot->sintbl[(slot->pgout + fm)&(PG_WIDTH-1)] + slot->egout]; + } + else + { + slot->output[0] = DB2LIN_TABLE[slot->sintbl[slot->pgout] + slot->egout]; + } + + slot->feedback = (slot->output[1] + slot->output[0]) >> 1; + + return slot->feedback; + +} + +static INLINE e_int16 calc (OPLL * opll) +{ + e_int32 inst = 0, out = 0; + e_int32 i; + + update_ampm (opll); + + for (i = 0; i < 12; i++) + { + calc_phase(&opll->slot[i],opll->lfo_pm); + calc_envelope(&opll->slot[i],opll->lfo_am); + } + + for (i = 0; i < 6; i++) + if(!(opll->mask & OPLL_MASK_CH (i)) && (CAR(opll,i)->eg_mode != FINISH)) + inst += calc_slot_car (CAR(opll,i), calc_slot_mod(MOD(opll,i))); + + out = inst; + return (e_int16) out; +} + +void moocow(OPLL* opll, e_int32 *buf, e_int32 len, int shift) +{ + while(len > 0) + { + *buf+=(calc(opll)+32768)<quality) + return calc (opll); + + while (opll->realstep > opll->oplltime) + { + opll->oplltime += opll->opllstep; + opll->prev = opll->next; + opll->next = calc (opll); + } + + opll->oplltime -= opll->realstep; + opll->out = (e_int16) (((double) opll->next * (opll->opllstep - opll->oplltime) + + (double) opll->prev * opll->oplltime) / opll->opllstep); + + return (e_int16) opll->out; +} +#endif + +e_uint32 +OPLL_setMask (OPLL * opll, e_uint32 mask) +{ + e_uint32 ret; + + if(opll) + { + ret = opll->mask; + opll->mask = mask; + return ret; + } + else + return 0; +} + +e_uint32 +OPLL_toggleMask (OPLL * opll, e_uint32 mask) +{ + e_uint32 ret; + + if(opll) + { + ret = opll->mask; + opll->mask ^= mask; + return ret; + } + else + return 0; +} + +/**************************************************** + + I/O Ctrl + +*****************************************************/ + +static void setInstrument(OPLL * opll, e_uint i, e_uint inst) +{ + const e_uint8 *src; + OPLL_PATCH *modp, *carp; + + opll->patch_number[i]=inst; + + if(inst) + src=default_inst[inst-1]; + else + src=opll->CustInst; + + modp=&MOD(opll,i)->patch; + carp=&CAR(opll,i)->patch; + + modp->AM=(src[0]>>7)&1; + modp->PM=(src[0]>>6)&1; + modp->EG=(src[0]>>5)&1; + modp->KR=(src[0]>>4)&1; + modp->ML=(src[0]&0xF); + + carp->AM=(src[1]>>7)&1; + carp->PM=(src[1]>>6)&1; + carp->EG=(src[1]>>5)&1; + carp->KR=(src[1]>>4)&1; + carp->ML=(src[1]&0xF); + + modp->KL=(src[2]>>6)&3; + modp->TL=(src[2]&0x3F); + + carp->KL = (src[3] >> 6) & 3; + carp->WF = (src[3] >> 4) & 1; + + modp->WF = (src[3] >> 3) & 1; + + modp->FB = (src[3]) & 7; + + modp->AR = (src[4]>>4)&0xF; + modp->DR = (src[4]&0xF); + + carp->AR = (src[5]>>4)&0xF; + carp->DR = (src[5]&0xF); + + modp->SL = (src[6]>>4)&0xF; + modp->RR = (src[6]&0xF); + + carp->SL = (src[7]>>4)&0xF; + carp->RR = (src[7]&0xF); +} + + +void +OPLL_writeReg (OPLL * opll, e_uint32 reg, e_uint32 data) +{ + + e_int32 i, v, ch; + + data = data & 0xff; + reg = reg & 0x3f; + + switch (reg) + { + case 0x00: + opll->CustInst[0]=data; + for (i = 0; i < 6; i++) + { + if(opll->patch_number[i] == 0) + { + setInstrument(opll, i, 0); + UPDATE_PG (MOD(opll,i)); + UPDATE_RKS (MOD(opll,i)); + UPDATE_EG (MOD(opll,i)); + } + } + break; + + case 0x01: + opll->CustInst[1]=data; + for (i = 0; i < 6; i++) + { + if(opll->patch_number[i] == 0) + { + setInstrument(opll, i, 0); + UPDATE_PG (CAR(opll,i)); + UPDATE_RKS (CAR(opll,i)); + UPDATE_EG (CAR(opll,i)); + } + } + break; + + case 0x02: + opll->CustInst[2]=data; + for (i = 0; i < 6; i++) + { + if(opll->patch_number[i] == 0) + { + setInstrument(opll, i, 0); + UPDATE_TLL(MOD(opll,i)); + } + } + break; + + case 0x03: + opll->CustInst[3]=data; + for (i = 0; i < 6; i++) + { + if(opll->patch_number[i] == 0) + { + setInstrument(opll, i, 0); + UPDATE_WF(MOD(opll,i)); + UPDATE_WF(CAR(opll,i)); + } + } + break; + + case 0x04: + opll->CustInst[4]=data; + for (i = 0; i < 6; i++) + { + if(opll->patch_number[i] == 0) + { + setInstrument(opll, i, 0); + UPDATE_EG (MOD(opll,i)); + } + } + break; + + case 0x05: + opll->CustInst[5]=data; + for (i = 0; i < 6; i++) + { + if(opll->patch_number[i] == 0) + { + setInstrument(opll, i, 0); + UPDATE_EG(CAR(opll,i)); + } + } + break; + + case 0x06: + opll->CustInst[6]=data; + for (i = 0; i < 6; i++) + { + if(opll->patch_number[i] == 0) + { + setInstrument(opll, i, 0); + UPDATE_EG (MOD(opll,i)); + } + } + break; + + case 0x07: + opll->CustInst[7]=data; + for (i = 0; i < 6; i++) + { + if(opll->patch_number[i] == 0) + { + setInstrument(opll, i, 0); + UPDATE_EG (CAR(opll,i)); + } + } + break; + + case 0x10: + case 0x11: + case 0x12: + case 0x13: + case 0x14: + case 0x15: + ch = reg - 0x10; + opll->LowFreq[ch]=data; + setFnumber (opll, ch, data + ((opll->HiFreq[ch] & 1) << 8)); + UPDATE_ALL (MOD(opll,ch)); + UPDATE_ALL (CAR(opll,ch)); + break; + + case 0x20: + case 0x21: + case 0x22: + case 0x23: + case 0x24: + case 0x25: + ch = reg - 0x20; + opll->HiFreq[ch]=data; + + setFnumber (opll, ch, ((data & 1) << 8) + opll->LowFreq[ch]); + setBlock (opll, ch, (data >> 1) & 7); + setSustine (opll, ch, (data >> 5) & 1); + if(data & 0x10) + keyOn (opll, ch); + else + keyOff (opll, ch); + UPDATE_ALL (MOD(opll,ch)); + UPDATE_ALL (CAR(opll,ch)); + update_key_status (opll); + break; + + case 0x30: + case 0x31: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + opll->InstVol[reg-0x30]=data; + i = (data >> 4) & 15; + v = data & 15; + setInstrument(opll, reg-0x30, i); + setVolume (opll, reg - 0x30, v << 2); + UPDATE_ALL (MOD(opll,reg - 0x30)); + UPDATE_ALL (CAR(opll,reg - 0x30)); + break; + + default: + break; + + } +} + +void +OPLL_writeIO (OPLL * opll, e_uint32 adr, e_uint32 val) +{ + if(adr & 1) + OPLL_writeReg (opll, opll->adr, val); + else + opll->adr = val; +} + diff --git a/mappers/emu2413.h b/mappers/emu2413.h new file mode 100644 index 0000000..906b4c5 --- /dev/null +++ b/mappers/emu2413.h @@ -0,0 +1,134 @@ +#ifndef _EMU2413_H_ +#define _EMU2413_H_ + +#include "emutypes.h" + +#ifdef EMU2413_DLL_EXPORTS + #define EMU2413_API __declspec(dllexport) +#elif defined(EMU2413_DLL_IMPORTS) + #define EMU2413_API __declspec(dllimport) +#else + #define EMU2413_API +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define PI 3.14159265358979323846 + +enum {OPLL_VRC7_TONE=0} ; + +/* voice data */ +typedef struct { + e_uint32 TL,FB,EG,ML,AR,DR,SL,RR,KR,KL,AM,PM,WF ; +} OPLL_PATCH ; + +/* slot */ +typedef struct { + + OPLL_PATCH patch; + + e_int32 type ; /* 0 : modulator 1 : carrier */ + + /* OUTPUT */ + e_int32 feedback ; + e_int32 output[2] ; /* Output value of slot */ + + /* for Phase Generator (PG) */ + e_uint16 *sintbl ; /* Wavetable */ + e_uint32 phase ; /* Phase */ + e_uint32 dphase ; /* Phase increment amount */ + e_uint32 pgout ; /* output */ + + /* for Envelope Generator (EG) */ + e_int32 fnum ; /* F-Number */ + e_int32 block ; /* Block */ + e_int32 volume ; /* Current volume */ + e_int32 sustine ; /* Sustine 1 = ON, 0 = OFF */ + e_uint32 tll ; /* Total Level + Key scale level*/ + e_uint32 rks ; /* Key scale offset (Rks) */ + e_int32 eg_mode ; /* Current state */ + e_uint32 eg_phase ; /* Phase */ + e_uint32 eg_dphase ; /* Phase increment amount */ + e_uint32 egout ; /* output */ + +} OPLL_SLOT ; + +/* Mask */ +#define OPLL_MASK_CH(x) (1<<(x)) + +/* opll */ +typedef struct { + + e_uint32 adr ; + e_int32 out ; + +#ifndef EMU2413_COMPACTION + e_uint32 realstep ; + e_uint32 oplltime ; + e_uint32 opllstep ; + e_int32 prev, next ; +#endif + + /* Register */ + e_uint8 LowFreq[6]; + e_uint8 HiFreq[6]; + e_uint8 InstVol[6]; + + e_uint8 CustInst[8]; + + e_int32 slot_on_flag[6 * 2] ; + + /* Pitch Modulator */ + e_uint32 pm_phase ; + e_int32 lfo_pm ; + + /* Amp Modulator */ + e_int32 am_phase ; + e_int32 lfo_am ; + + e_uint32 quality; + + /* Channel Data */ + e_int32 patch_number[6]; + e_int32 key_status[6] ; + + /* Slot */ + OPLL_SLOT slot[6 * 2] ; + + e_uint32 mask ; + +} OPLL ; + +/* Create Object */ +EMU2413_API OPLL *OPLL_new(e_uint32 clk, e_uint32 rate) ; +EMU2413_API void OPLL_delete(OPLL *) ; + +/* Setup */ +EMU2413_API void OPLL_reset(OPLL *) ; +EMU2413_API void OPLL_set_rate(OPLL *opll, e_uint32 r) ; +EMU2413_API void OPLL_set_quality(OPLL *opll, e_uint32 q) ; + +/* Port/Register access */ +EMU2413_API void OPLL_writeIO(OPLL *, e_uint32 reg, e_uint32 val) ; +EMU2413_API void OPLL_writeReg(OPLL *, e_uint32 reg, e_uint32 val) ; + +/* Synthsize */ +EMU2413_API e_int16 OPLL_calc(OPLL *) ; + +/* Misc */ +EMU2413_API void OPLL_forceRefresh(OPLL *) ; + +/* Channel Mask */ +EMU2413_API e_uint32 OPLL_setMask(OPLL *, e_uint32 mask) ; +EMU2413_API e_uint32 OPLL_toggleMask(OPLL *, e_uint32 mask) ; + + +void moocow(OPLL* opll, e_int32 *buf, e_int32 len, int shift); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/mappers/emutypes.h b/mappers/emutypes.h new file mode 100644 index 0000000..fdef420 --- /dev/null +++ b/mappers/emutypes.h @@ -0,0 +1,44 @@ +#ifndef _EMUTYPES_H_ +#define _EMUTYPES_H_ + +#ifndef INLINE + +#if defined(_MSC_VER) +#define INLINE __forceinline +#elif defined(__GNUC__) +#define INLINE __inline__ +#elif defined(_MWERKS_) +#define INLINE inline +#else +#define INLINE +#endif +#endif + +#if defined(EMU_DLL_IMPORTS) +#define EMU2149_DLL_IMPORTS +#define EMU2212_DLL_IMPORTS +#define EMU2413_DLL_IMPORTS +#define EMU8950_DLL_IMPORTS +#define EMU76489_DLL_IMPORTS +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef unsigned int e_uint; +typedef signed int e_int; + +typedef unsigned char e_uint8 ; +typedef signed char e_int8 ; + +typedef unsigned short e_uint16 ; +typedef signed short e_int16 ; + +typedef unsigned int e_uint32 ; +typedef signed int e_int32 ; + +#ifdef __cplusplus +} +#endif +#endif diff --git a/mappers/fmopl.c b/mappers/fmopl.c deleted file mode 100644 index b2fc12c..0000000 --- a/mappers/fmopl.c +++ /dev/null @@ -1,871 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 1999,2000 Tatsuyuki Satoh - * Copyright (C) 2001,2002 Ben Parnell - * - * 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 - */ - -/* This file has been heavily modified from the original(mostly unused - code was removed). If you want to use it for anything other than - VRC7 sound emulation, you should get the original from the AdPlug - source distribution or the MAME(version 0.37b16) source distribution - (but be careful about the different licenses). - - Xodnizel -*/ - -#include -#include -#include -#include -#include -#include "mapinc.h" -#include "fmopl.h" - -#ifndef PI -#define PI 3.14159265358979323846 -#endif - -/* -------------------- preliminary define section --------------------- */ -/* attack/decay rate time rate */ -#define OPL_ARRATE 141280 /* RATE 4 = 2826.24ms @ 3.6MHz */ -#define OPL_DRRATE 1956000 /* RATE 4 = 39280.64ms @ 3.6MHz */ - -#define DELTAT_MIXING_LEVEL (1) /* DELTA-T ADPCM MIXING LEVEL */ - -#define FREQ_BITS 24 /* frequency turn */ - -/* counter bits = 20 , octerve 7 */ -#define FREQ_RATE (1<<(FREQ_BITS-20)) -#define TL_BITS (FREQ_BITS+2) - -/* final output shift , limit minimum and maximum */ -#define OPL_OUTSB (TL_BITS+3-16) /* OPL output final shift 16bit */ -#define OPL_MAXOUT (0x7fff< max ) - val = max; - else if ( val < min ) - val = min; - - return val; -} - -/* ----- key on ----- */ -INLINE void OPL_KEYON(OPL_SLOT *SLOT) -{ - /* sin wave restart */ - SLOT->Cnt = 0; - /* set attack */ - SLOT->evm = ENV_MOD_AR; - SLOT->evs = SLOT->evsa; - SLOT->evc = EG_AST; - SLOT->eve = EG_AED; -} -/* ----- key off ----- */ -INLINE void OPL_KEYOFF(OPL_SLOT *SLOT) -{ - if( SLOT->evm > ENV_MOD_RR) - { - /* set envelope counter from envleope output */ - SLOT->evm = ENV_MOD_RR; - if( !(SLOT->evc&EG_DST) ) - //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<evc = EG_DST; - SLOT->eve = EG_DED; - SLOT->evs = SLOT->evsr; - } -} - -/* ---------- calcrate Envelope Generator & Phase Generator ---------- */ -/* return : envelope output */ -INLINE UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT ) -{ - /* calcrate envelope generator */ - if( (SLOT->evc+=SLOT->evs) >= SLOT->eve ) - { - switch( SLOT->evm ){ - case ENV_MOD_AR: /* ATTACK -> DECAY1 */ - /* next DR */ - SLOT->evm = ENV_MOD_DR; - SLOT->evc = EG_DST; - SLOT->eve = SLOT->SL; - SLOT->evs = SLOT->evsd; - break; - case ENV_MOD_DR: /* DECAY -> SL or RR */ - SLOT->evc = SLOT->SL; - SLOT->eve = EG_DED; - if(SLOT->eg_typ) - { - SLOT->evs = 0; - } - else - { - SLOT->evm = ENV_MOD_RR; - SLOT->evs = SLOT->evsr; - } - break; - case ENV_MOD_RR: /* RR -> OFF */ - SLOT->evc = EG_OFF; - SLOT->eve = EG_OFF+1; - SLOT->evs = 0; - break; - } - } - /* calcrate envelope */ - return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0); -} - -/* set algorythm connection */ -static void set_algorythm( OPL_CH *CH) -{ - INT32 *carrier = &outd[0]; - CH->connect1 = CH->CON ? carrier : &feedback2; - CH->connect2 = carrier; -} - -/* ---------- frequency counter for operater update ---------- */ -INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT) -{ - int ksr; - - /* frequency step counter */ - SLOT->Incr = CH->fc * SLOT->mul; - ksr = CH->kcode >> SLOT->KSR; - - if( SLOT->ksr != ksr ) - { - SLOT->ksr = ksr; - /* attack , decay rate recalcration */ - SLOT->evsa = SLOT->AR[ksr]; - SLOT->evsd = SLOT->DR[ksr]; - SLOT->evsr = SLOT->RR[ksr]; - } - SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); -} - -/* set multi,am,vib,EG-TYP,KSR,mul */ -INLINE void set_mul(FM_OPL *OPL,int slot,int v) -{ - OPL_CH *CH = &OPL->P_CH[slot/2]; - OPL_SLOT *SLOT = &CH->SLOT[slot&1]; - - SLOT->mul = MUL_TABLE[v&0x0f]; - SLOT->KSR = (v&0x10) ? 0 : 2; - SLOT->eg_typ = (v&0x20)>>5; - SLOT->vib = (v&0x40); - SLOT->ams = (v&0x80); - CALC_FCSLOT(CH,SLOT); -} - -/* set ksl & tl */ -INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v) -{ - OPL_CH *CH = &OPL->P_CH[slot/2]; - OPL_SLOT *SLOT = &CH->SLOT[slot&1]; - int ksl = v>>6; /* 0 / 1.5 / 3 / 6 db/OCT */ - -// if(slot&1) -// if(ksl) {sprintf(errmsg,"doh");howlong=255;ksl=0;} - - SLOT->ksl = ksl ? ksl : 31; -// SLOT->ksl = ksl ? 3-ksl : 31; - SLOT->TL = (v&0x3f)*(0.75/EG_STEP); /* 0.75db step */ - - if( !(OPL->mode&0x80) ) - { /* not CSM latch total level */ - SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); - } -} - -/* set attack rate & decay rate */ -INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v) -{ - OPL_CH *CH = &OPL->P_CH[slot/2]; - OPL_SLOT *SLOT = &CH->SLOT[slot&1]; - int ar = v>>4; - int dr = v&0x0f; - - SLOT->AR = ar ? &OPL->AR_TABLE[ar<<2] : RATE_0; - SLOT->evsa = SLOT->AR[SLOT->ksr]; - if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa; - - SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0; - SLOT->evsd = SLOT->DR[SLOT->ksr]; - if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd; -} - -/* set sustain level & release rate */ -INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v) -{ - OPL_CH *CH = &OPL->P_CH[slot/2]; - OPL_SLOT *SLOT = &CH->SLOT[slot&1]; - int sl = v>>4; - int rr = v & 0x0f; - - SLOT->SL = SL_TABLE[sl]; - if( SLOT->evm == ENV_MOD_DR ) SLOT->eve = SLOT->SL; - SLOT->RR = &OPL->DR_TABLE[rr<<2]; - SLOT->evsr = SLOT->RR[SLOT->ksr]; - if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr; -} - -/* operator output calcrator */ -#define OP_OUT(slot,env,con) slot->wavetable[((slot->Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env] -/* ---------- calcrate one of channel ---------- */ -INLINE void OPL_CALC_CH( OPL_CH *CH ) -{ - UINT32 env_out; - OPL_SLOT *SLOT; - - feedback2 = 0; - /* SLOT 1 */ - SLOT = &CH->SLOT[SLOT1]; - env_out=OPL_CALC_SLOT(SLOT); - if( env_out < EG_ENT-1 ) - { - /* PG */ - if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); - else SLOT->Cnt += SLOT->Incr; - /* connectoion */ - if(CH->FB) - { - int feedback1 = (CH->op1_out[0]+CH->op1_out[1])>>CH->FB; - CH->op1_out[1] = CH->op1_out[0]; - *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT,env_out,feedback1); - } - else - { - *CH->connect1 += OP_OUT(SLOT,env_out,0); - } - }else - { - CH->op1_out[1] = CH->op1_out[0]; - CH->op1_out[0] = 0; - } - /* SLOT 2 */ - SLOT = &CH->SLOT[SLOT2]; - env_out=OPL_CALC_SLOT(SLOT); - if( env_out < EG_ENT-1 ) - { - /* PG */ - if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); - else SLOT->Cnt += SLOT->Incr; - /* connectoion */ - outd[0] += OP_OUT(SLOT,env_out, feedback2); - } -} - -/* ----------- initialize time tabls ----------- */ -static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE ) -{ - int i; - double rate; - - /* make attack rate & decay rate tables */ - for (i = 0;i < 4;i++) OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0; - for (i = 4;i <= 60;i++){ - rate = OPL->freqbase; /* frequency rate */ - if( i < 60 ) rate *= 1.0+(i&3)*0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */ - rate *= 1<<((i>>2)-1); /* b2-5 : shift bit */ - rate *= (double)(EG_ENT<AR_TABLE[i] = rate / ARRATE; - OPL->DR_TABLE[i] = rate / DRRATE; - } - for (i = 60;i < 76;i++) - { - OPL->AR_TABLE[i] = EG_AED-1; - OPL->DR_TABLE[i] = OPL->DR_TABLE[60]; - } -} - -/* ---------- generic table initialize ---------- */ -static int OPLOpenTable( void ) -{ - int s,t; - double rate; - int i,j; - double pom; - - /* allocate dynamic tables */ - if( (TL_TABLE = malloc(TL_MAX*2*sizeof(INT32))) == NULL) - return 0; - if( (SIN_TABLE = malloc(SIN_ENT*4 *sizeof(INT32 *))) == NULL) - { - free(TL_TABLE); - return 0; - } - if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(INT32))) == NULL) - { - free(TL_TABLE); - free(SIN_TABLE); - return 0; - } - if( (VIB_TABLE = malloc(VIB_ENT*2 *sizeof(INT32))) == NULL) - { - free(TL_TABLE); - free(SIN_TABLE); - free(AMS_TABLE); - return 0; - } - /* make total level table */ - for (t = 0;t < EG_ENT-1 ;t++){ - rate = ((1< voltage */ - TL_TABLE[ t] = (int)rate; - TL_TABLE[TL_MAX+t] = -TL_TABLE[t]; - - } - /* fill volume off area */ - for ( t = EG_ENT-1; t < TL_MAX ;t++){ - TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0; - } - - /* make sinwave table (total level offet) */ - /* degree 0 = degree 180 = off */ - SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2] = &TL_TABLE[EG_ENT-1]; - for (s = 1;s <= SIN_ENT/4;s++){ - pom = sin(2*PI*s/SIN_ENT); /* sin */ - pom = 20*log10(1/pom); /* decibel */ - j = pom / EG_STEP; /* TL_TABLE steps */ - - /* degree 0 - 90 , degree 180 - 90 : plus section */ - SIN_TABLE[ s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j]; - /* degree 180 - 270 , degree 360 - 270 : minus section */ - SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT -s] = &TL_TABLE[TL_MAX+j]; - - } - for (s = 0;s < SIN_ENT;s++) - { - SIN_TABLE[SIN_ENT*1+s] = s<(SIN_ENT/2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT]; - SIN_TABLE[SIN_ENT*2+s] = SIN_TABLE[s % (SIN_ENT/2)]; - SIN_TABLE[SIN_ENT*3+s] = (s/(SIN_ENT/4))&1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT*2+s]; - } - - /* envelope counter -> envelope output table */ - for (i=0; i= EG_ENT ) pom = EG_ENT-1; */ - ENV_CURVE[i] = (int)pom; - /* DECAY ,RELEASE curve */ - ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i; - } - /* off */ - ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1; - /* make LFO ams table */ - for (i=0; iSLOT[SLOT1]; - OPL_SLOT *slot2 = &CH->SLOT[SLOT2]; - /* all key off */ - OPL_KEYOFF(slot1); - OPL_KEYOFF(slot2); - /* total level latch */ - slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl); - slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl); - /* key on */ - CH->op1_out[0] = CH->op1_out[1] = 0; - OPL_KEYON(slot1); - OPL_KEYON(slot2); -} - -/* ---------- opl initialize ---------- */ -static void OPL_initalize(FM_OPL *OPL) -{ - int fn; - - /* frequency base */ - OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0; - /* make time tables */ - init_timetables( OPL , OPL_ARRATE , OPL_DRRATE ); - /* make fnumber -> increment counter table */ - for( fn=0 ; fn < 1024 ; fn++ ) - { - OPL->FN_TABLE[fn] = OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2; - } - /* LFO freq.table */ - OPL->amsIncr = OPL->rate ? (double)AMS_ENT*(1<rate * 3.7 * ((double)OPL->clock/3600000) : 0; - OPL->vibIncr = OPL->rate ? (double)VIB_ENT*(1<rate * 6.4 * ((double)OPL->clock/3600000) : 0; -} - -/* ---------- write a OPL registers ---------- */ -static void OPLWriteReg(FM_OPL *OPL, int r, int v) -{ - OPL_CH *CH; - int slot; - int block_fnum; - - switch(r&0xe0) - { - case 0x00: /* 00-1f:controll */ - switch(r&0x1f) - { - case 0x01: - /* wave selector enable */ - if(OPL->type&OPL_TYPE_WAVESEL) - { - OPL->wavesel = v&0x20; - if(!OPL->wavesel) - { - /* preset compatible mode */ - int c; - for(c=0;cmax_ch;c++) - { - OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0]; - OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0]; - } - } - } - return; - } - break; - case 0x20: /* am,vib,ksr,eg type,mul */ - slot = slot_array[r&0x1f]; - if(slot == -1) return; - set_mul(OPL,slot,v); - return; - case 0x40: - slot = slot_array[r&0x1f]; - if(slot == -1) return; - set_ksl_tl(OPL,slot,v); - return; - case 0x60: - slot = slot_array[r&0x1f]; - if(slot == -1) return; - set_ar_dr(OPL,slot,v); - return; - case 0x80: - slot = slot_array[r&0x1f]; - if(slot == -1) return; - set_sl_rr(OPL,slot,v); - return; - case 0xa0: - switch(r) - { - case 0xbd: - /* amsep,vibdep,r,bd,sd,tom,tc,hh */ - { - OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0]; - OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0]; - } - return; - } - /* keyon,block,fnum */ - if( (r&0x0f) > 8) return; - CH = &OPL->P_CH[r&0x0f]; - if(!(r&0x10)) - { /* a0-a8 */ - block_fnum = (CH->block_fnum&0x1f00) | v; - } - else - { /* b0-b8 */ - int keyon = (v>>5)&1; - block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff); - if(CH->keyon != keyon) - { - if( (CH->keyon=keyon) ) - { - CH->op1_out[0] = CH->op1_out[1] = 0; - OPL_KEYON(&CH->SLOT[SLOT1]); - OPL_KEYON(&CH->SLOT[SLOT2]); - } - else - { - OPL_KEYOFF(&CH->SLOT[SLOT1]); - OPL_KEYOFF(&CH->SLOT[SLOT2]); - } - } - } - /* update */ - if(CH->block_fnum != block_fnum) - { - int blockRv = 7-(block_fnum>>10); - int fnum = block_fnum&0x3ff; - CH->block_fnum = block_fnum; - - CH->ksl_base = KSL_TABLE[block_fnum>>6]; - CH->fc = OPL->FN_TABLE[fnum]>>blockRv; - CH->kcode = CH->block_fnum>>9; - if( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1; - CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); - CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); - } - return; - case 0xc0: - /* FB,C */ - if( (r&0x0f) > 8) return; - CH = &OPL->P_CH[r&0x0f]; - { - int feedback = (v>>1)&7; - CH->FB = feedback ? (8+1) - feedback : 0; - CH->CON = v&1; - set_algorythm(CH); - } - return; - case 0xe0: /* wave type */ - slot = slot_array[r&0x1f]; - if(slot == -1) return; - CH = &OPL->P_CH[slot/2]; - if(OPL->wavesel) - { - CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT]; - } - return; - } -} - -/* lock/unlock for common table */ -static int OPL_LockTable(void) -{ - num_lock++; - if(num_lock>1) return 0; - /* first time */ - cur_chip = NULL; - /* allocate total level table (128kb space) */ - if( !OPLOpenTable() ) - { - num_lock--; - return -1; - } - return 0; -} - -static void OPL_UnLockTable(void) -{ - if(num_lock) num_lock--; - if(num_lock) return; - /* last time */ - cur_chip = NULL; - OPLCloseTable(); -} - -/*******************************************************************************/ -/* YM3812 local section */ -/*******************************************************************************/ - -/* ---------- update one of chip ----------- */ -void YM3812UpdateOne(FM_OPL *OPL, UINT32 *buffer, int length) -{ - int i; - UINT32 *buf = buffer; - UINT32 amsCnt = OPL->amsCnt; - UINT32 vibCnt = OPL->vibCnt; - OPL_CH *CH,*R_CH; - - if( (void *)OPL != cur_chip ){ - cur_chip = (void *)OPL; - /* channel pointers */ - S_CH = OPL->P_CH; - E_CH = &S_CH[6]; - /* LFO state */ - amsIncr = OPL->amsIncr; - vibIncr = OPL->vibIncr; - ams_table = OPL->ams_table; - vib_table = OPL->vib_table; - } - R_CH = E_CH; - for( i=0; i < length ; i++ ) - { - /* channel A channel B channel C */ - /* LFO */ - ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT]; - vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT]; - outd[0] = 0; - /* FM part */ - for(CH=S_CH ; CH < R_CH ; CH++) - OPL_CALC_CH(CH); - /* limit check */ - //data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT ); - /* store to sound buffer */ - { - int32 d=outd[0]>>OPL_OUTSB; - if(d<-32768) d=-32768; - d+=32768; - buf[i] += d; - } - } - - OPL->amsCnt = amsCnt; - OPL->vibCnt = vibCnt; -} - -/* ---------- reset one of chip ---------- */ -void OPLResetChip(FM_OPL *OPL) -{ - int c,s; - int i; - - /* reset chip */ - OPL->mode = 0; /* normal mode */ - - /* reset with register write */ - OPLWriteReg(OPL,0x01,0); /* wabesel disable */ - for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0); - /* reset OPerator paramater */ - for( c = 0 ; c < OPL->max_ch ; c++ ) - { - OPL_CH *CH = &OPL->P_CH[c]; - /* OPL->P_CH[c].PAN = OPN_CENTER; */ - for(s = 0 ; s < 2 ; s++ ) - { - /* wave table */ - CH->SLOT[s].wavetable = &SIN_TABLE[0]; - /* CH->SLOT[s].evm = ENV_MOD_RR; */ - CH->SLOT[s].evc = EG_OFF; - CH->SLOT[s].eve = EG_OFF+1; - CH->SLOT[s].evs = 0; - } - } -} - -/* ---------- Create one of vietual YM3812 ---------- */ -/* 'rate' is sampling rate and 'bufsiz' is the size of the */ -FM_OPL *OPLCreate(int type, int clock, int rate) -{ - char *ptr; - FM_OPL *OPL; - int state_size; - int max_ch = 9; /* normaly 9 channels */ - - if( OPL_LockTable() ==-1) return NULL; - /* allocate OPL state space */ - state_size = sizeof(FM_OPL); - state_size += sizeof(OPL_CH)*max_ch; - - /* allocate memory block */ - ptr = malloc(state_size); - if(ptr==NULL) return NULL; - /* clear */ - memset(ptr,0,state_size); - OPL = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL); - OPL->P_CH = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch; - - /* set channel state pointer */ - OPL->type = type; - OPL->clock = clock; - OPL->rate = rate; - OPL->max_ch = max_ch; - /* init grobal tables */ - OPL_initalize(OPL); - /* reset chip */ - OPLResetChip(OPL); - - return OPL; -} - -/* ---------- Destroy one of vietual YM3812 ---------- */ -void OPLDestroy(FM_OPL *OPL) -{ - OPL_UnLockTable(); - free(OPL); -} - -/* ---------- YM3812 I/O interface ---------- */ -void OPLWrite(FM_OPL *OPL,UINT8 a,UINT8 v) -{ - OPLWriteReg(OPL,a,v); -} diff --git a/mappers/fmopl.h b/mappers/fmopl.h deleted file mode 100644 index f11a087..0000000 --- a/mappers/fmopl.h +++ /dev/null @@ -1,149 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 1999,2000 Tatsuyuki Satoh - * Copyright (C) 2001,2002 Ben Parnell - * - * 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 - */ -/* This file has been heavily modified from the original(mostly unused - code was removed). If you want to use it for anything other than - VRC7 sound emulation, you should get the original from the AdPlug - source distribution or the MAME(version 0.37b16) source distribution - (but be careful about the different licenses). - - Xodnizel -*/ - -#ifndef __FMOPL_H_ -#define __FMOPL_H_ - -/* --- system optimize --- */ -/* select bit size of output : 8 or 16 */ -#define OPL_OUTPUT_BIT 16 - -/* compiler dependence */ -#ifndef OSD_CPU_H -#define OSD_CPU_H - -typedef unsigned char UINT8; /* unsigned 8bit */ -typedef unsigned short UINT16; /* unsigned 16bit */ -typedef unsigned long UINT32; /* unsigned 32bit */ -typedef signed char INT8; /* signed 8bit */ -typedef signed short INT16; /* signed 16bit */ -typedef signed long INT32; /* signed 32bit */ -#endif - -#if (OPL_OUTPUT_BIT==16) -typedef INT16 OPLSAMPLE; -#endif -#if (OPL_OUTPUT_BIT==8) -typedef unsigned char OPLSAMPLE; -#endif - - -/* !!!!! here is private section , do not access there member direct !!!!! */ - -#define OPL_TYPE_WAVESEL 0x01 /* waveform select */ - -/* Saving is necessary for member of the 'R' mark for suspend/resume */ -/* ---------- OPL one of slot ---------- */ -typedef struct fm_opl_slot { - INT32 TL; /* total level :TL << 8 */ - INT32 TLL; /* adjusted now TL */ - UINT8 KSR; /* key scale rate :(shift down bit) */ - INT32 *AR; /* attack rate :&AR_TABLE[AR<<2] */ - INT32 *DR; /* decay rate :&DR_TALBE[DR<<2] */ - INT32 SL; /* sustin level :SL_TALBE[SL] */ - INT32 *RR; /* release rate :&DR_TABLE[RR<<2] */ - UINT8 ksl; /* keyscale level :(shift down bits) */ - UINT8 ksr; /* key scale rate :kcode>>KSR */ - UINT32 mul; /* multiple :ML_TABLE[ML] */ - UINT32 Cnt; /* frequency count : */ - UINT32 Incr; /* frequency step : */ - /* envelope generator state */ - UINT8 eg_typ; /* envelope type flag */ - UINT8 evm; /* envelope phase */ - INT32 evc; /* envelope counter */ - INT32 eve; /* envelope counter end point */ - INT32 evs; /* envelope counter step */ - INT32 evsa; /* envelope step for AR :AR[ksr] */ - INT32 evsd; /* envelope step for DR :DR[ksr] */ - INT32 evsr; /* envelope step for RR :RR[ksr] */ - /* LFO */ - UINT8 ams; /* ams flag */ - UINT8 vib; /* vibrate flag */ - /* wave selector */ - INT32 **wavetable; -}OPL_SLOT; - -/* ---------- OPL one of channel ---------- */ -typedef struct fm_opl_channel { - OPL_SLOT SLOT[2]; - UINT8 CON; /* connection type */ - UINT8 FB; /* feed back :(shift down bit) */ - INT32 *connect1; /* slot1 output pointer */ - INT32 *connect2; /* slot2 output pointer */ - INT32 op1_out[2]; /* slot1 output for selfeedback */ - /* phase generator state */ - UINT32 block_fnum; /* block+fnum : */ - UINT8 kcode; /* key code : KeyScaleCode */ - UINT32 fc; /* Freq. Increment base */ - UINT32 ksl_base; /* KeyScaleLevel Base step */ - UINT8 keyon; /* key on/off flag */ -} OPL_CH; - -/* OPL state */ -typedef struct fm_opl_f { - UINT8 type; /* chip type */ - int clock; /* master clock (Hz) */ - int rate; /* sampling rate (Hz) */ - double freqbase; /* frequency base */ - double TimerBase; /* Timer base time (==sampling time) */ - UINT8 address; /* address register */ - UINT32 mode; /* Reg.08 : CSM , notesel,etc. */ - - /* FM channel slots */ - OPL_CH *P_CH; /* pointer of CH */ - int max_ch; /* maximum channel */ - - /* time tables */ - INT32 AR_TABLE[75]; /* atttack rate tables */ - INT32 DR_TABLE[75]; /* decay rate tables */ - UINT32 FN_TABLE[1024]; /* fnumber -> increment counter */ - /* LFO */ - INT32 *ams_table; - INT32 *vib_table; - INT32 amsCnt; - INT32 amsIncr; - INT32 vibCnt; - INT32 vibIncr; - /* wave selector enable flag */ - UINT8 wavesel; - -} FM_OPL; - -/* ---------- Generic interface section ---------- */ -#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL) - -FM_OPL *OPLCreate(int type, int clock, int rate); -void OPLDestroy(FM_OPL *OPL); - -void OPLResetChip(FM_OPL *OPL); -void OPLWrite(FM_OPL *OPL,UINT8 a,UINT8 v); - -/* YM3626/YM3812 local section */ -void YM3812UpdateOne(FM_OPL *OPL, UINT32 *buffer, int length); - -#endif diff --git a/mappers/mapinc.h b/mappers/mapinc.h index ebe446c..9eec5c9 100644 --- a/mappers/mapinc.h +++ b/mappers/mapinc.h @@ -1,12 +1,13 @@ -#include "../types.h" -#include "../x6502.h" -#include "../fce.h" +#include "../types.h" +#include "../x6502.h" +#include "../fce.h" +#include "../ppu.h" #define INESPRIV -#include "../ines.h" -#include "../version.h" -#include "../memory.h" -#include "../sound.h" -#include "../svga.h" -#include "../state.h" -#include "../cart.h" -#include "mapshare.h" +#include "../cart.h" +#include "../ines.h" +#include "../memory.h" +#include "../sound.h" +#include "../state.h" +#include "../svga.h" +#include "../dprintf.h" +#include diff --git a/mappers/mapshare.h b/mappers/mapshare.h deleted file mode 100644 index 4853050..0000000 --- a/mappers/mapshare.h +++ /dev/null @@ -1,5 +0,0 @@ -void MMC3_hb(void); - -#define resetmode mapbyte1[0] -#define MMC3_cmd mapbyte1[1] - diff --git a/mappers/mmc2and4.c b/mappers/mmc2and4.c index 1b23e49..022d736 100644 --- a/mappers/mmc2and4.c +++ b/mappers/mmc2and4.c @@ -1,7 +1,7 @@ /* FCE Ultra - NES/Famicom Emulator * * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell + * 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 @@ -64,16 +64,14 @@ static void FP_FASTAPASS(1) latchcheck(uint32 VAddr) } } -DECLFW(Mapper9_write) // $Axxx +DECLFW(Mapper9_write) // $Axxx { ROM_BANK8(0x8000,V); - X6502_Rebase(); } DECLFW(Mapper10_write) { ROM_BANK16(0x8000,V); - X6502_Rebase(); } DECLFW(Mapper9and10_write) @@ -81,19 +79,19 @@ DECLFW(Mapper9and10_write) switch(A&0xF000) { case 0xB000: - if (latcha1==0xFD) { VROM_BANK4(0x0000,V);} + if(latcha1==0xFD) { VROM_BANK4(0x0000,V);} MMC4reg[0]=V; break; case 0xC000: - if (latcha1==0xFE) {VROM_BANK4(0x0000,V);} + if(latcha1==0xFE) {VROM_BANK4(0x0000,V);} MMC4reg[1]=V; break; case 0xD000: - if (latcha2==0xFD) {VROM_BANK4(0x1000,V);} + if(latcha2==0xFD) {VROM_BANK4(0x1000,V);} MMC4reg[2]=V; break; case 0xE000: - if (latcha2==0xFE) {VROM_BANK4(0x1000,V);} + if(latcha2==0xFE) {VROM_BANK4(0x1000,V);} MMC4reg[3]=V; break; case 0xF000: @@ -109,7 +107,7 @@ void Mapper9_init(void) ROM_BANK8(0xA000,~2); ROM_BANK8(0x8000,0); SetWriteHandler(0xA000,0xAFFF,Mapper9_write); - SetWriteHandler(0xB000,0xFFFF,Mapper9and10_write); + SetWriteHandler(0xB000,0xFFFF,Mapper9and10_write); PPU_hook=latchcheck; } @@ -117,7 +115,7 @@ void Mapper10_init(void) { latcha1=latcha2=0xFE; SetWriteHandler(0xA000,0xAFFF,Mapper10_write); - SetWriteHandler(0xB000,0xFFFF,Mapper9and10_write); + SetWriteHandler(0xB000,0xFFFF,Mapper9and10_write); PPU_hook=latchcheck; } diff --git a/mappers/simple.c b/mappers/simple.c index de6c42f..b2c76d8 100644 --- a/mappers/simple.c +++ b/mappers/simple.c @@ -2,7 +2,7 @@ * * Copyright notice for this file: * Copyright (C) 1998 BERO - * Copyright (C) 2002 Ben Parnell + * 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 @@ -18,42 +18,41 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include + #include "mapinc.h" static uint8 latche; -static DECLFW(Mapper2_write) -{ - latche=V; - ROM_BANK16(0x8000,V); - X6502_Rebase(); -} - -void Mapper2_init(void) -{ - SetWriteHandler(0x8000,0xFFFF,Mapper2_write); - AddExState(&latche, 1, 0, "LATC"); -} - -static DECLFW(Mapper3_write) -{ - VROM_BANK8(V); - latche=V; -} - -void Mapper3_init(void) -{ - SetWriteHandler(0x8000,0xFFFF,Mapper3_write); - AddExState(&latche, 1, 0, "LATC"); -} - -DECLFW(Mapper7_write) -{ +//static DECLFW(Mapper2_write) +//{ +// latche=V; +// ROM_BANK16(0x8000,V); +//} +// +//void Mapper2_init(void) +//{ +// SetWriteHandler(0x8000,0xFFFF,Mapper2_write); +// AddExState(&latche, 1, 0, "LATC"); +//} + +//static DECLFW(Mapper3_write) +//{ +// VROM_BANK8(V); +// latche=V; +//} + +//void Mapper3_init(void) +//{ +// SetWriteHandler(0x8000,0xFFFF,Mapper3_write); +// AddExState(&latche, 1, 0, "LATC"); +//} + +static DECLFW(Mapper7_write) +{ +// FCEU_printf("%04x,%04x\n",A,V); ROM_BANK32(V&0xF); onemir((V>>4)&1); latche=V; - X6502_Rebase(); } void Mapper7_init(void) @@ -61,70 +60,69 @@ void Mapper7_init(void) onemir(0); ROM_BANK32(0); SetWriteHandler(0x8000,0xFFFF,Mapper7_write); - AddExState(&latche, 1, 0, "LATC"); + AddExState(&latche, 1, 0, "LATC"); } -DECLFW(Mapper11_write) +static DECLFW(Mapper11_write) { - ROM_BANK32(V); + ROM_BANK32(V&0xF); VROM_BANK8(V>>4); - latche=V; - X6502_Rebase(); + latche=V; } void Mapper11_init(void) { ROM_BANK32(0); - SetWriteHandler(0x8000,0xFFFF,Mapper11_write); - AddExState(&latche, 1, 0, "LATC"); -} - -static DECLFW(Mapper13_write) -{ - setchr4r(0x10,0x1000,V&3); - setprg32(0x8000,(V>>4)&3); - latche=V; - X6502_Rebase(); -} - -static void Mapper13_StateRestore(int version) -{ - setchr4r(0x10,0x0000,0); - setchr4r(0x10,0x1000,latche&3); - setprg32(0x8000,(latche>>4)&3); - X6502_Rebase(); -} - -void Mapper13_init(void) -{ - SetWriteHandler(0x8000,0xFFFF,Mapper13_write); - GameStateRestore=Mapper13_StateRestore; - AddExState(&latche, 1, 0, "LATC"); - AddExState(MapperExRAM, 16384, 0, "CHRR"); - SetupCartCHRMapping(0x10, MapperExRAM, 16384, 1); - - latche=0; - Mapper13_StateRestore(VERSION_NUMERIC); -} - -DECLFW(Mapper34_write) -{ -switch(A) + SetWriteHandler(0x8000,0xFFFF,Mapper11_write); + AddExState(&latche, 1, 0, "LATC"); +} +void Mapper144_init(void) +{ + ROM_BANK32(0); + SetWriteHandler(0x8001,0xFFFF,Mapper11_write); + AddExState(&latche, 1, 0, "LATC"); + +} +//static DECLFW(Mapper13_write) +//{ +// setchr4r(0x10,0x1000,V&3); +// setprg32(0x8000,(V>>4)&3); +// latche=V; +//} + +//static void Mapper13_StateRestore(int version) +//{ +// setchr4r(0x10,0x0000,0); +// setchr4r(0x10,0x1000,latche&3); +// setprg32(0x8000,(latche>>4)&3); +//} + +//void Mapper13_init(void) +//{ +// SetWriteHandler(0x8000,0xFFFF,Mapper13_write); +// GameStateRestore=Mapper13_StateRestore; +// AddExState(&latche, 1, 0, "LATC"); +// AddExState(MapperExRAM, 16384, 0, "CHRR"); +// SetupCartCHRMapping(0x10, MapperExRAM, 16384, 1); +// latche=0; +// Mapper13_StateRestore(FCEU_VERSION_NUMERIC); +//} + +static DECLFW(Mapper34_write) +{ + switch(A) { - case 0x7FFD:ROM_BANK32(V); - X6502_Rebase();break; - case 0x7FFE:VROM_BANK4(0x0000,V);break; - case 0x7fff:VROM_BANK4(0x1000,V);break; + case 0x7FFD:ROM_BANK32(V);break; + case 0x7FFE:VROM_BANK4(0x0000,V);break; + case 0x7fff:VROM_BANK4(0x1000,V);break; } if(A>=0x8000) - { ROM_BANK32(V); - X6502_Rebase(); - } } void Mapper34_init(void) { + ROM_BANK32(0); SetWriteHandler(0x7ffd,0xffff,Mapper34_write); } @@ -133,7 +131,6 @@ DECLFW(Mapper66_write) VROM_BANK8(V&0xF); ROM_BANK32((V>>4)); latche=V; - X6502_Rebase(); } void Mapper66_init(void) @@ -147,9 +144,8 @@ DECLFW(Mapper152_write) { ROM_BANK16(0x8000,(V>>4)&0x7); VROM_BANK8(V&0xF); - onemir((V>>7)&1); /* Saint Seiya...hmm. */ + onemir((V>>7)&1); /* Saint Seiya...hmm. */ latche=V; - X6502_Rebase(); } void Mapper152_init(void) @@ -164,7 +160,6 @@ static DECLFW(Mapper70_write) ROM_BANK16(0x8000,V>>4); VROM_BANK8(V&0xF); latche=V; - X6502_Rebase(); } void Mapper70_init(void) @@ -175,12 +170,11 @@ void Mapper70_init(void) /* Should be two separate emulation functions for this "mapper". Sigh. URGE TO KILL RISING. */ static DECLFW(Mapper78_write) { - //printf("$%04x:$%02x\n",A,V); + //printf("$%04x:$%02x\n",A,V&0x8); ROM_BANK16(0x8000,V&0x7); VROM_BANK8(V>>4); onemir((V>>3)&1); latche=V; - X6502_Rebase(); } void Mapper78_init(void) @@ -206,7 +200,6 @@ DECLFW(Mapper93_write) ROM_BANK16(0x8000,V>>4); MIRROR_SET(V&1); latche=V; - X6502_Rebase(); } void Mapper93_init(void) @@ -220,7 +213,6 @@ DECLFW(Mapper94_write) { ROM_BANK16(0x8000,V>>2); latche=V; - X6502_Rebase(); } void Mapper94_init(void) @@ -241,23 +233,21 @@ static DECLFW(Mapper96_write) setprg32(0x8000,V&3); setchr4r(0x10,0x0000,(latche&4)|M96LA); setchr4r(0x10,0x1000,(latche&4)|3); - X6502_Rebase(); } static void FP_FASTAPASS(1) M96Hook(uint32 A) { - if((A&0x3000)!=0x2000) - return; + if((A&0x3000)!=0x2000) return; + //if((A&0x3ff)>=0x3c0) return; M96LA=(A>>8)&3; setchr4r(0x10,0x0000,(latche&4)|M96LA); } -static void M96Sync() +static void M96Sync(int v) { setprg32(0x8000,latche&3); setchr4r(0x10,0x0000,(latche&4)|M96LA); setchr4r(0x10,0x1000,(latche&4)|3); - X6502_Rebase(); } void Mapper96_init(void) @@ -268,7 +258,8 @@ void Mapper96_init(void) AddExState(&M96LA, 1, 0, "LAVA"); SetupCartCHRMapping(0x10, MapperExRAM, 32768, 1); latche=M96LA=0; - M96Sync(); + M96Sync(0); + setmirror(MI_0); GameStateRestore=M96Sync; } @@ -276,7 +267,6 @@ static DECLFW(Mapper140_write) { VROM_BANK8(V&0xF); ROM_BANK32((V>>4)&0xF); - X6502_Rebase(); } void Mapper140_init(void) @@ -285,34 +275,68 @@ void Mapper140_init(void) SetWriteHandler(0x6000,0x7FFF,Mapper140_write); } -static void M185Sync() +static void M185Sync(int version) { - int x; +// 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 - if(!(mapbyte1[0]&3)) -// if(!(mapbyte1[0]==0x21)) - { - for(x=0;x<8;x++) - setchr1r(0x10,x<<10,0); - } - else - setchr8(0); +// if((mapbyte1[0]&3)==1) // 6, 3 +// if(mapbyte1[0]&1) // 1, 2, 3, 5 +// if(mapbyte1[0]&2) // 1, 2, 4, 5, + if((mapbyte1[0]&2)||((mapbyte1[0]&3)==1)) // 1, 2, 3, 4, 5 + setchr8(0); + else + setchr8r(0x10,0); } static DECLFW(Mapper185_write) { - mapbyte1[0]=V; - M185Sync(); - // printf("Wr: $%04x:$%02x\n",A,V); + mapbyte1[0]=V; + M185Sync(0); } void Mapper185_init(void) { - memset(MapperExRAM,0xFF,1024); - MapStateRestore=M185Sync; - mapbyte1[0]=0; - M185Sync(); + int x; + for(x=0;x<8192;x++) + MapperExRAM[x]=0xff; + MapStateRestore=M185Sync; + mapbyte1[0]=0; + M185Sync(0); + SetupCartCHRMapping(0x10,MapperExRAM,8192,0); + SetWriteHandler(0x8000,0xFFFF,Mapper185_write); +} + - SetupCartCHRMapping(0x10,MapperExRAM,1024,0); - SetWriteHandler(0x8000,0xFFFF,Mapper185_write); +static DECLFW(M156Write) +{ + if(A>=0xc000 && A<=0xC003) + VROM_BANK1((A&3)*1024,V); + else if(A>=0xc008 && A<=0xc00b) + VROM_BANK1(0x1000+(A&3)*1024,V); + if(A==0xc010) ROM_BANK16(0x8000,V); +// printf("$%04x:$%02x\n",A,V); } + +void Mapper156_init(void) +{ + onemir(0); + SetWriteHandler(0xc000,0xc010,M156Write); +} + +static DECLFW(m107w) +{ + ROM_BANK32((V>>1)&0x3); + VROM_BANK8(V&0x7); +} + +void Mapper107_init(void) +{ + SetWriteHandler(0x8000,0xffff,m107w); +} + diff --git a/mappers/vrc7snd.c b/mappers/vrc7snd.c deleted file mode 100644 index ea02830..0000000 --- a/mappers/vrc7snd.c +++ /dev/null @@ -1,190 +0,0 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell - * - * 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 -#include -#include "mapinc.h" -#include "fmopl.h" - -static void VRC7_LoadInstrument(uint8 Chan); -void vrc7translate(uint8 Reg,uint8 V); - -FM_OPL *fmob=0; -uint8 VRC7Chan[3][6]; -static void InitOPL(void); - -void OPL2_setreg(uint8 A, uint8 V) -{ - if(fmob) - OPLWrite(fmob,A,V); -} - - -void LoadOPL(void) -{ - int x; - int y; - - for(x=y=0;x<0x40;x++) - y|=MapperExRAM[x]; - if(y) - { - InitOPL(); - for(x=0;x<6;x++) - { - VRC7_LoadInstrument(x); - vrc7translate(0x10+x,VRC7Chan[0][x]); - } - } -} - -static int dwave=0; - -void VRC7Update(void) -{ - int32 z,a; - - z=((SOUNDTS<<16)/soundtsinc)>>4; - a=z-dwave; - - if(a && fmob) - YM3812UpdateOne(fmob, &Wave[dwave], a); - dwave+=a; -} - -void UpdateOPL(int Count) -{ - int32 z,a; - - z=((SOUNDTS<<16)/soundtsinc)>>4; - a=z-dwave; - - if(fmob && a) - YM3812UpdateOne(fmob, &Wave[dwave], a); - - dwave=0; -} - -void KillOPL(void) -{ - if(fmob) OPLDestroy(fmob); - fmob=0; -} - -static void InitOPL(void) -{ - int x; - - if(!fmob) - { - if(!( fmob=OPLCreate(OPL_TYPE_WAVESEL,1789772*2,FSettings.SndRate))) - return; - } - GameExpSound.Kill=KillOPL; - OPLResetChip(fmob); - - for(x=0x1;x<0xF6;x++) - OPL2_setreg(x,0); - OPL2_setreg(0xBD,0xC0); - OPL2_setreg(1,0x20); /* Enable waveform type manipulation */ -} - -/* This following code is in the public domain, but the author, Quietust(see */ -/* the "AUTHORS" file, would appreciate credit to go to him if this code */ -/* is used. */ - -uint8 VRC7Instrument[16][8] = { - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* Custom instrument. */ - {0x03,0x01,0x14,0x80,0xC2,0x90,0x43,0x14}, /* Currently working on this one */ - {0x13,0x41,0x10,0x0B,0xFF,0xF2,0x32,0xD6}, - {0x01,0x01,0x10,0x08,0xF0,0xF4,0x00,0x04}, /* 90% perfect */ - {0x21,0x41,0x1B,0x08,0x66,0x80,0x30,0x85}, - {0x22,0x21,0x20,0x03,0x75,0x70,0x24,0x14}, - {0x02,0x01,0x06,0x00,0xF0,0xF2,0x03,0x95}, /* Do not touch! 98% perfect! */ - {0x21,0x41,0x18,0x10,0x93,0xE0,0x21,0x15}, - {0x01,0x22,0x13,0x00,0xF0,0x82,0x00,0x15}, - {0x05,0x01,0x22,0x00,0x60,0xE3,0xA0,0xF5}, /* 90% perfect */ - {0x85,0x01,0x20,0x00,0xD7,0xA2,0x22,0xF5}, /* 90% perfect */ - {0x07,0x81,0x2B,0x05,0xF4,0xF2,0x14,0xF4}, /* 95% perfect */ - {0x21,0x41,0x20,0x18,0xF3,0x80,0x13,0x95}, - {0x01,0x02,0x20,0x00,0xF9,0x92,0x41,0x75}, /* Do not touch! 98% perfect! */ - {0x21,0x62,0x0E,0x00,0x84,0x85,0x45,0x15}, /* 90% perfect */ - {0x21,0x62,0x0E,0x00,0xA1,0xA0,0x34,0x16} /* Do not touch! 98% perfect! */ -}; - -static uint8 InstTrans[6] = {0x00,0x01,0x02,0x08,0x09,0x0A}; - -static void VRC7_LoadInstrument(uint8 Chan) -{ - uint8 *i; - uint8 x = InstTrans[Chan]; - uint8 y = (VRC7Chan[2][Chan] >> 4) & 0xF; - - i=VRC7Instrument[y]; - - OPL2_setreg((0x20+x),i[0]); - OPL2_setreg((0x23+x),i[1]); - OPL2_setreg((0x40+x),i[2]); - OPL2_setreg((0x43+x),((i[3] & 0xC0) - | ((VRC7Chan[2][Chan] << 2) & 0x3C))); // quiet - OPL2_setreg(0xe0+x,(i[3] >> 3) & 0x01); - OPL2_setreg(0xe3+x,(i[3] >> 4) & 0x01); - OPL2_setreg(0xC0+Chan,(i[3] << 1) & 0x0E); - OPL2_setreg(0x60+x,i[4]); - OPL2_setreg(0x63+x,i[5]); - OPL2_setreg(0x80+x,i[6]); - OPL2_setreg(0x83+x,i[7]); -} - -void vrc7translate(uint8 Reg,uint8 V) -{ - uint8 x = Reg & 0x0F, y; - if(!fmob) InitOPL(); - - MapperExRAM[Reg]=V; - - VRC7Update(); - switch ((Reg & 0xF0) >> 4) - { - case 0: - if (x & 0x08) break; - VRC7Instrument[0][x] = V; - for (y = 0; y < 6; y++) - if (!(VRC7Chan[2][y]&0xF0)) - VRC7_LoadInstrument(y); - break; - case 1: - if(x>5) break; - VRC7Chan[0][x] = V; - OPL2_setreg(0xA0 + x,(VRC7Chan[0][x] << 1) & 0xFE); - OPL2_setreg(0xB0 + x,((VRC7Chan[0][x] >> 7) & 0x01) | ((VRC7Chan[1][x] << 1) & 0x3E)); - break; - case 2: - if(x>5) break; - VRC7Chan[1][x] = V; - OPL2_setreg(0xB0 + x,(((VRC7Chan[0][x] >> 7) & 0x01) | ((VRC7Chan[1][x] << 1) & 0x3E))); - break; - case 3: - if(x>5) break; - VRC7Chan[2][x] = V; - VRC7_LoadInstrument(x); - break; - } -} diff --git a/mappers/vrc7tone.h b/mappers/vrc7tone.h new file mode 100644 index 0000000..d136307 --- /dev/null +++ b/mappers/vrc7tone.h @@ -0,0 +1,17 @@ +/* VRC7 instruments, January 17, 2004 update -Xodnizel */ + {0x03, 0x21, 0x04, 0x06, 0x8D, 0xF2, 0x42, 0x17}, + {0x13, 0x41, 0x05, 0x0E, 0x99, 0x96, 0x63, 0x12}, + {0x31, 0x11, 0x10, 0x0A, 0xF0, 0x9C, 0x32, 0x02}, + {0x21, 0x61, 0x1D, 0x07, 0x9F, 0x64, 0x20, 0x27}, + {0x22, 0x21, 0x1E, 0x06, 0xF0, 0x76, 0x08, 0x28}, + {0x02, 0x01, 0x06, 0x00, 0xF0, 0xF2, 0x03, 0x95}, + {0x21, 0x61, 0x1C, 0x07, 0x82, 0x81, 0x16, 0x07}, + {0x23, 0x21, 0x1A, 0x17, 0xEF, 0x82, 0x25, 0x15}, + {0x25, 0x11, 0x1F, 0x00, 0x86, 0x41, 0x20, 0x11}, + {0x85, 0x01, 0x1F, 0x0F, 0xE4, 0xA2, 0x11, 0x12}, + {0x07, 0xC1, 0x2B, 0x45, 0xB4, 0xF1, 0x24, 0xF4}, + {0x61, 0x23, 0x11, 0x06, 0x96, 0x96, 0x13, 0x16}, + {0x01, 0x02, 0xD3, 0x05, 0x82, 0xA2, 0x31, 0x51}, + {0x61, 0x22, 0x0D, 0x02, 0xC3, 0x7F, 0x24, 0x05}, + {0x21, 0x62, 0x0E, 0x00, 0xA1, 0xA0, 0x44, 0x17}, + diff --git a/md5.c b/md5.c new file mode 100644 index 0000000..174d3ee --- /dev/null +++ b/md5.c @@ -0,0 +1,246 @@ +/* + * RFC 1321 compliant MD5 implementation, + * by Christophe Devine ; + * this program is licensed under the GPL. + */ + +/* Modified October 3, 2003, to remove testing code, and add + include of "types.h". + + Added simple MD5 to ASCII string conversion function. + -Xodnizel +*/ + +#include +#include "types.h" +#include "md5.h" + +#define GET_UINT32(n,b,i) \ +{ \ + (n) = ( (uint32) (b)[(i) + 3] << 24 ) \ + | ( (uint32) (b)[(i) + 2] << 16 ) \ + | ( (uint32) (b)[(i) + 1] << 8 ) \ + | ( (uint32) (b)[(i) ] ); \ +} + +#define PUT_UINT32(n,b,i) \ +{ \ + (b)[(i) ] = (uint8) ( (n) ); \ + (b)[(i) + 1] = (uint8) ( (n) >> 8 ); \ + (b)[(i) + 2] = (uint8) ( (n) >> 16 ); \ + (b)[(i) + 3] = (uint8) ( (n) >> 24 ); \ +} + +void md5_starts( struct md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; +} + +void md5_process( struct md5_context *ctx, uint8 data[64] ) +{ + uint32 A, B, C, D, X[16]; + + GET_UINT32( X[0], data, 0 ); + GET_UINT32( X[1], data, 4 ); + GET_UINT32( X[2], data, 8 ); + GET_UINT32( X[3], data, 12 ); + GET_UINT32( X[4], data, 16 ); + GET_UINT32( X[5], data, 20 ); + GET_UINT32( X[6], data, 24 ); + GET_UINT32( X[7], data, 28 ); + GET_UINT32( X[8], data, 32 ); + GET_UINT32( X[9], data, 36 ); + GET_UINT32( X[10], data, 40 ); + GET_UINT32( X[11], data, 44 ); + GET_UINT32( X[12], data, 48 ); + GET_UINT32( X[13], data, 52 ); + GET_UINT32( X[14], data, 56 ); + GET_UINT32( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define P(a,b,c,d,k,s,t) \ +{ \ + a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) + + P( A, B, C, D, 0, 7, 0xD76AA478 ); + P( D, A, B, C, 1, 12, 0xE8C7B756 ); + P( C, D, A, B, 2, 17, 0x242070DB ); + P( B, C, D, A, 3, 22, 0xC1BDCEEE ); + P( A, B, C, D, 4, 7, 0xF57C0FAF ); + P( D, A, B, C, 5, 12, 0x4787C62A ); + P( C, D, A, B, 6, 17, 0xA8304613 ); + P( B, C, D, A, 7, 22, 0xFD469501 ); + P( A, B, C, D, 8, 7, 0x698098D8 ); + P( D, A, B, C, 9, 12, 0x8B44F7AF ); + P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); + P( B, C, D, A, 11, 22, 0x895CD7BE ); + P( A, B, C, D, 12, 7, 0x6B901122 ); + P( D, A, B, C, 13, 12, 0xFD987193 ); + P( C, D, A, B, 14, 17, 0xA679438E ); + P( B, C, D, A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) (y ^ (z & (x ^ y))) + + P( A, B, C, D, 1, 5, 0xF61E2562 ); + P( D, A, B, C, 6, 9, 0xC040B340 ); + P( C, D, A, B, 11, 14, 0x265E5A51 ); + P( B, C, D, A, 0, 20, 0xE9B6C7AA ); + P( A, B, C, D, 5, 5, 0xD62F105D ); + P( D, A, B, C, 10, 9, 0x02441453 ); + P( C, D, A, B, 15, 14, 0xD8A1E681 ); + P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); + P( A, B, C, D, 9, 5, 0x21E1CDE6 ); + P( D, A, B, C, 14, 9, 0xC33707D6 ); + P( C, D, A, B, 3, 14, 0xF4D50D87 ); + P( B, C, D, A, 8, 20, 0x455A14ED ); + P( A, B, C, D, 13, 5, 0xA9E3E905 ); + P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); + P( C, D, A, B, 7, 14, 0x676F02D9 ); + P( B, C, D, A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) (x ^ y ^ z) + + P( A, B, C, D, 5, 4, 0xFFFA3942 ); + P( D, A, B, C, 8, 11, 0x8771F681 ); + P( C, D, A, B, 11, 16, 0x6D9D6122 ); + P( B, C, D, A, 14, 23, 0xFDE5380C ); + P( A, B, C, D, 1, 4, 0xA4BEEA44 ); + P( D, A, B, C, 4, 11, 0x4BDECFA9 ); + P( C, D, A, B, 7, 16, 0xF6BB4B60 ); + P( B, C, D, A, 10, 23, 0xBEBFBC70 ); + P( A, B, C, D, 13, 4, 0x289B7EC6 ); + P( D, A, B, C, 0, 11, 0xEAA127FA ); + P( C, D, A, B, 3, 16, 0xD4EF3085 ); + P( B, C, D, A, 6, 23, 0x04881D05 ); + P( A, B, C, D, 9, 4, 0xD9D4D039 ); + P( D, A, B, C, 12, 11, 0xE6DB99E5 ); + P( C, D, A, B, 15, 16, 0x1FA27CF8 ); + P( B, C, D, A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) (y ^ (x | ~z)) + + P( A, B, C, D, 0, 6, 0xF4292244 ); + P( D, A, B, C, 7, 10, 0x432AFF97 ); + P( C, D, A, B, 14, 15, 0xAB9423A7 ); + P( B, C, D, A, 5, 21, 0xFC93A039 ); + P( A, B, C, D, 12, 6, 0x655B59C3 ); + P( D, A, B, C, 3, 10, 0x8F0CCC92 ); + P( C, D, A, B, 10, 15, 0xFFEFF47D ); + P( B, C, D, A, 1, 21, 0x85845DD1 ); + P( A, B, C, D, 8, 6, 0x6FA87E4F ); + P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); + P( C, D, A, B, 6, 15, 0xA3014314 ); + P( B, C, D, A, 13, 21, 0x4E0811A1 ); + P( A, B, C, D, 4, 6, 0xF7537E82 ); + P( D, A, B, C, 11, 10, 0xBD3AF235 ); + P( C, D, A, B, 2, 15, 0x2AD7D2BB ); + P( B, C, D, A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; +} + +void md5_update( struct md5_context *ctx, uint8 *input, uint32 length ) +{ + uint32 left, fill; + + if( ! length ) return; + + left = ( ctx->total[0] >> 3 ) & 0x3F; + fill = 64 - left; + + ctx->total[0] += length << 3; + ctx->total[1] += length >> 29; + + ctx->total[0] &= 0xFFFFFFFF; + ctx->total[1] += ctx->total[0] < ( length << 3 ); + + if( left && length >= fill ) + { + memcpy( (void *) (ctx->buffer + left), (void *) input, fill ); + md5_process( ctx, ctx->buffer ); + length -= fill; + input += fill; + left = 0; + } + + while( length >= 64 ) + { + md5_process( ctx, input ); + length -= 64; + input += 64; + } + + if( length ) + { + memcpy( (void *) (ctx->buffer + left), (void *) input, length ); + } +} + +static uint8 md5_padding[64] = +{ + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +void md5_finish( struct md5_context *ctx, uint8 digest[16] ) +{ + uint32 last, padn; + uint8 msglen[8]; + + PUT_UINT32( ctx->total[0], msglen, 0 ); + PUT_UINT32( ctx->total[1], msglen, 4 ); + + last = ( ctx->total[0] >> 3 ) & 0x3F; + padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); + + md5_update( ctx, md5_padding, padn ); + md5_update( ctx, msglen, 8 ); + + PUT_UINT32( ctx->state[0], digest, 0 ); + PUT_UINT32( ctx->state[1], digest, 4 ); + PUT_UINT32( ctx->state[2], digest, 8 ); + PUT_UINT32( ctx->state[3], digest, 12 ); +} + + +/* Uses a static buffer, so beware of how it's used. */ +char *md5_asciistr(uint8 digest[16]) +{ + static char str[33]; + static char trans[16]={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'}; + int x; + + for(x=0;x<16;x++) + { + str[x*2]=trans[digest[x]&0x0F]; + str[x*2+1]=trans[digest[x]>>4]; + } + return(str); +} diff --git a/md5.h b/md5.h new file mode 100644 index 0000000..39c01ec --- /dev/null +++ b/md5.h @@ -0,0 +1,18 @@ +#ifndef _MD5_H +#define _MD5_H + +struct md5_context +{ + uint32 total[2]; + uint32 state[4]; + uint8 buffer[64]; +}; + +void md5_starts( struct md5_context *ctx ); +void md5_update( struct md5_context *ctx, uint8 *input, uint32 length ); +void md5_finish( struct md5_context *ctx, uint8 digest[16] ); + +/* Uses a static buffer, so beware of how it's used. */ +char *md5_asciistr(uint8 digest[16]); + +#endif /* md5.h */ diff --git a/memory.h b/memory.h index 122a858..32df99a 100644 --- a/memory.h +++ b/memory.h @@ -18,12 +18,14 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* Various macros for faster memory stuff - (at least that's the idea) +/* Various macros for faster memory stuff + (at least that's the idea) */ #define FCEU_dwmemset(d,c,n) {int _x; for(_x=n-4;_x>=0;_x-=4) *(uint32 *)&(d)[_x]=c;} void *FCEU_malloc(uint32 size); void FCEU_free(void *ptr); +#define FCEU_gmalloc FCEU_malloc +#define FCEU_gfree FCEU_free void FASTAPASS(3) FCEU_memmove(void *d, void *s, uint32 l); diff --git a/nsf.c b/nsf.c index 2db647c..9e09cfb 100644 --- a/nsf.c +++ b/nsf.c @@ -1,412 +1,570 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell - * - * 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 -#include -#include -#include - -#include "types.h" -#include "x6502.h" -#include "fce.h" -#include "svga.h" -#include "video.h" -#include "sound.h" -#include "ines.h" -#include "nsf.h" -#include "nsfbgnew.h" -#include "general.h" -#include "memory.h" -#include "file.h" -#include "fds.h" -#include "cart.h" -#include "input.h" - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -uint8 SongReload; -uint8 CurrentSong; - -static int sinetable[32]; - - -static uint8 NSFROM[0x30+6]= -{ -/* 0x00 */ - -0x08,0x48,0x8A,0x48,0x98,0x48, /* Store regs */ -0xA9,0xFF, -0x8D,0xF2,0x5F, /* NMI has occured */ -0x68,0xA8,0x68,0xAA,0x68,0x28, -0x40, /* Restore regs */ - -/* 0x12 */ - -0xAD,0xF2,0x5F, /* See if an NMI occured */ -0xF0,0xFB, /* If it hasn't, loop */ - -0xA9,0x00, -0x8D,0xF2,0x5F, /* Clear play pending reg*/ - - -0xAD,0xF0,0x5F, /* See if we need to init. */ -0xF0,0x09, /* If 0, go to JMP */ - -0xAD,0xF1,0x5F, /* Confirm and load A */ -0xAE,0xF3,0x5F, /* Load X with PAL/NTSC byte */ - -0x20,0x00,0x00, /* JSR to init routine */ - -0x20,0x00,0x00, /* JSR to play routine */ - -0x4C,0x12,0x38, /* Loop */ - -0xA2,0xFF,0x9A, /* Initialize the stack pointer. */ -0x4C,0x12,0x38 -}; - -static DECLFR(NSFROMRead) -{ - return (NSFROM-0x3800)[A]; -} - - - -static uint8 *NSFDATA=0; -static int NSFMaxBank; - -static int NSFSize; -static uint8 BSon; -static uint16 PlayAddr; -static uint16 InitAddr; -static uint16 LoadAddr; - -NSF_HEADER NSFHeader; - -void NSFGI(int h) -{ - switch(h) - { - case GI_CLOSE: - if(NSFDATA) {free(NSFDATA);NSFDATA=0;} - break; - case GI_POWER: NSF_init();break; - } -} - -// First 32KB is reserved for sound chip emulation in the iNES mapper code. - -#define WRAM (GameMemBlock+32768) -#define FDSMEM (GameMemBlock+32768) - -static INLINE void BANKSET(uint32 A, uint32 bank) -{ - bank&=NSFMaxBank; - if(NSFHeader.SoundChip&4) - memcpy(FDSMEM+(A-0x6000),NSFDATA+(bank<<12),4096); - else - setprg4(A,bank); -} - -int NSFLoad(int fp) -{ - int x; - - FCEU_fseek(fp,0,SEEK_SET); - FCEU_fread(&NSFHeader,1,0x80,fp); - if (memcmp(NSFHeader.ID,"NESM\x1a",5)) - return 0; - NSFHeader.SongName[31]=NSFHeader.Artist[31]=NSFHeader.Copyright[31]=0; - - LoadAddr=NSFHeader.LoadAddressLow; - LoadAddr|=NSFHeader.LoadAddressHigh<<8; - - InitAddr=NSFHeader.InitAddressLow; - InitAddr|=NSFHeader.InitAddressHigh<<8; - - PlayAddr=NSFHeader.PlayAddressLow; - PlayAddr|=NSFHeader.PlayAddressHigh<<8; - - NSFSize=FCEU_fgetsize(fp)-0x80; - - NSFMaxBank=((NSFSize+(LoadAddr&0xfff)+4095)/4096); - NSFMaxBank=uppow2(NSFMaxBank); - - if(!(NSFDATA=(uint8 *)FCEU_malloc(NSFMaxBank*4096))) - return 0; - - FCEU_fseek(fp,0x80,SEEK_SET); - memset(NSFDATA,0x00,NSFMaxBank*4096); - FCEU_fread(NSFDATA+(LoadAddr&0xfff),1,NSFSize,fp); - - NSFMaxBank--; - - BSon=0; - for(x=0;x<8;x++) - BSon|=NSFHeader.BankSwitch[x]; - - FCEUGameInfo.type=GIT_NSF; - FCEUGameInfo.input[0]=FCEUGameInfo.input[1]=SI_NONE; - - for(x=0;;x++) - { - if(NSFROM[x]==0x20) - { - NSFROM[x+1]=InitAddr&0xFF; - NSFROM[x+2]=InitAddr>>8; - NSFROM[x+4]=PlayAddr&0xFF; - NSFROM[x+5]=PlayAddr>>8; - break; - } - } - - if(NSFHeader.VideoSystem==0) - FCEUGameInfo.vidsys=GIV_NTSC; - else if(NSFHeader.VideoSystem==1) - FCEUGameInfo.vidsys=GIV_PAL; - - { - double fruit=0; - for(x=0;x<32;x++) - { - double ta,no; - - ta=sin(fruit)*7; - ta+=modf(ta,&no); - sinetable[x]=ta; - fruit+=(double)M_PI*2/32; - } - } - GameInterface=NSFGI; - - puts("NSF Loaded. File information:\n"); - printf(" Name: %s\n Artist: %s\n Copyright: %s\n\n",NSFHeader.SongName,NSFHeader.Artist,NSFHeader.Copyright); - if(NSFHeader.SoundChip) - { - static char *tab[6]={"Konami VRCVI","Konami VRCVII","Nintendo FDS","Nintendo MMC5","Namco 106","Sunsoft FME-07"}; - for(x=0;x<6;x++) - if(NSFHeader.SoundChip&(1<=6) - BANKSET(0x6000+(x-6)*4096,NSFHeader.BankSwitch[x]); - BANKSET(0x8000+x*4096,NSFHeader.BankSwitch[x]); - } - } - else - { - int32 x; - for(x=(LoadAddr&0x7000);x<0x8000;x+=0x1000) - BANKSET(0x8000+x,((x-(LoadAddr&0x7000))>>12)); - } - - SetWriteHandler(0x2000,0x3fff,0); - SetReadHandler(0x2000,0x37ff,0); - SetReadHandler(0x3836,0x3FFF,0); - SetReadHandler(0x3800,0x3835,NSFROMRead); - - SetWriteHandler(0x4020,0x5fff,NSF_write); - SetReadHandler(0x4020,0x5fff,NSF_read); - - - if(NSFHeader.SoundChip&1) { - VRC6_ESI(0); - } else if (NSFHeader.SoundChip&2) { - VRC7_ESI(); - } else if (NSFHeader.SoundChip&4) { - FDSSoundReset(); - } else if (NSFHeader.SoundChip&8) { - Mapper5_ESI(); - } else if (NSFHeader.SoundChip&0x10) { - Mapper19_ESI(); - } else if (NSFHeader.SoundChip&0x20) { - Mapper69_ESI(); - } - CurrentSong=NSFHeader.StartingSong; - SongReload=1; -} - -static uint8 DoUpdateStuff=0; -DECLFW(NSF_write) -{ -switch(A) -{ - case 0x5FF2:if((X.PC&0xF000)==0x3000) DoUpdateStuff=V;break; - - case 0x5FF6: - case 0x5FF7:if(!(NSFHeader.SoundChip&4)) return; - case 0x5FF8: - case 0x5FF9: - case 0x5FFA: - case 0x5FFB: - case 0x5FFC: - case 0x5FFD: - case 0x5FFE: - case 0x5FFF:if(!BSon) return; - A&=0xF; - BANKSET((A*4096),V); - X6502_Rebase(); - break; -} -} - -DECLFR(NSF_read) -{ - int x; - - if((X.PC&0xF000)==0x3000) - switch(A) - { - case 0x5ff0:x=SongReload;SongReload=0;return x; - case 0x5ff1: - { - memset(RAM,0x00,0x800); - memset(WRAM,0x00,8192); - BWrite[0x4015](0x4015,0xF); - for(x=0;x<0x14;x++) - {if(x!=0x11) BWrite[0x4015](0x4015,0);} - BWrite[0x4015](0x4015,0x0); - for(x=0;x<0x14;x++) - {if(x!=0x11) BWrite[0x4015](0x4015,0);} - BWrite[0x4011](0x4011,0x40); - BWrite[0x4015](0x4015,0xF); - BWrite[0x4017](0x4017,0x40); - if(NSFHeader.SoundChip&4) - BWrite[0x4089](0x4089,0x80); - if(BSon) - { - for(x=0;x<8;x++) - BANKSET(0x8000+x*4096,NSFHeader.BankSwitch[x]); - X6502_Rebase(); - } - return (CurrentSong-1); - } - case 0x5FF2:return DoUpdateStuff; - case 0x5FF3:return PAL; - } - return 0; -} -static int32 *Bufpl; -void DrawNSF(uint8 *XBuf) -{ - char snbuf[16]; - static int z=0; - int x,y; - uint8 *XBuf2,*tmpb; - - XBuf+=8; - XBuf2=XBuf; - - tmpb=NSFBG+8; - for(y=120;y;y--) - { - uint8 *offs; - - offs=tmpb+sinetable[((z+y)>>2)&31]; - memcpy(XBuf2,offs,256); - memcpy(XBuf2+(120*272),offs,256); - - XBuf2+=272; - tmpb+=272; - } - tmpb=NSFBG+8; - z=(z+1)&127; - - DrawTextTrans(XBuf+10*272+4+(((31-strlen((char *)(NSFHeader.SongName)))<<2)), 272, NSFHeader.SongName, 38); - DrawTextTrans(XBuf+30*272+4+(((31-strlen((char *)(NSFHeader.Artist)))<<2)), 272, NSFHeader.Artist, 38); - DrawTextTrans(XBuf+50*272+4+(((31-strlen((char *)(NSFHeader.Copyright)))<<2)), 272, NSFHeader.Copyright, 38); - - DrawTextTrans(XBuf+90*272+4+(((31-strlen("Song:"))<<2)), 272, (uint8 *)"Song:", 38); - sprintf(snbuf,"<%d/%d>",CurrentSong,NSFHeader.TotalSongs); - DrawTextTrans(XBuf+102*272+4+(((31-strlen(snbuf))<<2)), 272, (uint8 *)snbuf, 38); - - GetSoundBuffer(&Bufpl); - for(x=0;x<256;x++) - XBuf[x+(224-((((Bufpl[x]>>(7)^128)&255)*3)>>3))*272]=38; -} - -void NSFControl(int z) -{ - if(z==1) - { - if(CurrentSong1) CurrentSong--; - } - SongReload=0xFF; -} +/* 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 +#include +#include +#include + +#include "types.h" +#include "x6502.h" +#include "fce.h" +#include "video.h" +#include "sound.h" +#include "nsf.h" +#include "general.h" +#include "memory.h" +#include "file.h" +#include "fds.h" +#include "cart.h" +#include "input.h" + +#include "svga.h" + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +static uint8 SongReload; +static int CurrentSong; + +static DECLFW(NSF_write); +static DECLFR(NSF_read); + +static int vismode=1; + +static uint8 NSFROM[0x30+6]= +{ +/* 0x00 - NMI */ +0x8D,0xF4,0x3F, /* Stop play routine NMIs. */ +0xA2,0xFF,0x9A, /* Initialize the stack pointer. */ +0xAD,0xF0,0x3F, /* See if we need to init. */ +0xF0,0x09, /* If 0, go to play routine playing. */ + +0xAD,0xF1,0x3F, /* Confirm and load A */ +0xAE,0xF3,0x3F, /* Load X with PAL/NTSC byte */ + +0x20,0x00,0x00, /* JSR to init routine */ + +0xA9,0x00, +0xAA, +0xA8, +0x20,0x00,0x00, /* JSR to play routine */ +0x8D,0xF5,0x3F, /* Start play routine NMIs. */ +0x90,0xFE, /* Loopie time. */ + +/* 0x20 */ +0x8D,0xF3,0x3F, /* Init init NMIs */ +0x18, +0x90,0xFE /* Loopie time. */ +}; + +static DECLFR(NSFROMRead) +{ + return (NSFROM-0x3800)[A]; +} + +static int doreset=0; +static int NSFNMIFlags; +static uint8 *NSFDATA=0; +static int NSFMaxBank; + +static int NSFSize; +static uint8 BSon; +static uint16 PlayAddr; +static uint16 InitAddr; +static uint16 LoadAddr; + +static NSF_HEADER NSFHeader; + +void NSFMMC5_Close(void); +static uint8 *ExWRAM=0; + +void NSFGI(int h) +{ + switch(h) + { + case GI_CLOSE: + if(NSFDATA) {free(NSFDATA);NSFDATA=0;} + if(ExWRAM) {free(ExWRAM);ExWRAM=0;} + if(NSFHeader.SoundChip&1) { +// NSFVRC6_Init(); + } else if(NSFHeader.SoundChip&2) { +// NSFVRC7_Init(); + } else if(NSFHeader.SoundChip&4) { +// FDSSoundReset(); + } else if(NSFHeader.SoundChip&8) { + NSFMMC5_Close(); + } else if(NSFHeader.SoundChip&0x10) { +// NSFN106_Init(); + } else if(NSFHeader.SoundChip&0x20) { +// NSFAY_Init(); + } + break; + case GI_RESETM2: + case GI_POWER: NSF_init();break; + } +} + +// First 32KB is reserved for sound chip emulation in the iNES mapper code. + +static INLINE void BANKSET(uint32 A, uint32 bank) +{ + bank&=NSFMaxBank; + if(NSFHeader.SoundChip&4) + memcpy(ExWRAM+(A-0x6000),NSFDATA+(bank<<12),4096); + else + setprg4(A,bank); +} + +int NSFLoad(int fp) +{ + int x; + + FCEU_fseek(fp,0,SEEK_SET); + FCEU_fread(&NSFHeader,1,0x80,fp); + if(memcmp(NSFHeader.ID,"NESM\x1a",5)) + return 0; + NSFHeader.SongName[31]=NSFHeader.Artist[31]=NSFHeader.Copyright[31]=0; + + LoadAddr=NSFHeader.LoadAddressLow; + LoadAddr|=NSFHeader.LoadAddressHigh<<8; + + if(LoadAddr<0x6000) + { + FCEUD_PrintError("Invalid load address."); + return(0); + } + InitAddr=NSFHeader.InitAddressLow; + InitAddr|=NSFHeader.InitAddressHigh<<8; + + PlayAddr=NSFHeader.PlayAddressLow; + PlayAddr|=NSFHeader.PlayAddressHigh<<8; + + NSFSize=FCEU_fgetsize(fp)-0x80; + + NSFMaxBank=((NSFSize+(LoadAddr&0xfff)+4095)/4096); + NSFMaxBank=uppow2(NSFMaxBank); + + if(!(NSFDATA=(uint8 *)FCEU_malloc(NSFMaxBank*4096))) + return 0; + + FCEU_fseek(fp,0x80,SEEK_SET); + memset(NSFDATA,0x00,NSFMaxBank*4096); + FCEU_fread(NSFDATA+(LoadAddr&0xfff),1,NSFSize,fp); + + NSFMaxBank--; + + BSon=0; + for(x=0;x<8;x++) + BSon|=NSFHeader.BankSwitch[x]; + + FCEUGameInfo.type=GIT_NSF; + FCEUGameInfo.input[0]=FCEUGameInfo.input[1]=SI_GAMEPAD; + FCEUGameInfo.cspecial=SIS_NSF; + + for(x=0;;x++) + { + if(NSFROM[x]==0x20) + { + NSFROM[x+1]=InitAddr&0xFF; + NSFROM[x+2]=InitAddr>>8; + NSFROM[x+8]=PlayAddr&0xFF; + NSFROM[x+9]=PlayAddr>>8; + break; + } + } + + if(NSFHeader.VideoSystem==0) + FCEUGameInfo.vidsys=GIV_NTSC; + else if(NSFHeader.VideoSystem==1) + FCEUGameInfo.vidsys=GIV_PAL; + + GameInterface=NSFGI; + + FCEU_printf("NSF Loaded. File information:\n\n"); + FCEU_printf(" Name: %s\n Artist: %s\n Copyright: %s\n\n",NSFHeader.SongName,NSFHeader.Artist,NSFHeader.Copyright); + if(NSFHeader.SoundChip) + { + static char *tab[6]={"Konami VRCVI","Konami VRCVII","Nintendo FDS","Nintendo MMC5","Namco 106","Sunsoft FME-07"}; + + for(x=0;x<6;x++) + if(NSFHeader.SoundChip&(1<=6) + BANKSET(0x6000+(x-6)*4096,NSFHeader.BankSwitch[x]); + BANKSET(0x8000+x*4096,NSFHeader.BankSwitch[x]); + } + } + else + { + int32 x; + for(x=(LoadAddr&0xF000);x<0x10000;x+=0x1000) + BANKSET(x,((x-(LoadAddr&0x7000))>>12)); + } + + SetReadHandler(0xFFFA,0xFFFD,NSFVectorRead); + + SetWriteHandler(0x2000,0x3fff,0); + SetReadHandler(0x2000,0x37ff,0); + SetReadHandler(0x3836,0x3FFF,0); + SetReadHandler(0x3800,0x3835,NSFROMRead); + + SetWriteHandler(0x5ff6,0x5fff,NSF_write); + + SetWriteHandler(0x3ff0,0x3fff,NSF_write); + SetReadHandler(0x3ff0,0x3fff,NSF_read); + + + if(NSFHeader.SoundChip&1) { + NSFVRC6_Init(); + } else if(NSFHeader.SoundChip&2) { + NSFVRC7_Init(); + } else if(NSFHeader.SoundChip&4) { + FDSSoundReset(); + } else if(NSFHeader.SoundChip&8) { + NSFMMC5_Init(); + } else if(NSFHeader.SoundChip&0x10) { + NSFN106_Init(); + } else if(NSFHeader.SoundChip&0x20) { + NSFAY_Init(); + } + CurrentSong=NSFHeader.StartingSong; + SongReload=0xFF; + NSFNMIFlags=0; +} + +static DECLFW(NSF_write) +{ + switch(A) + { + case 0x3FF3:NSFNMIFlags|=1;break; + case 0x3FF4:NSFNMIFlags&=~2;break; + case 0x3FF5:NSFNMIFlags|=2;break; + + case 0x5FF6: + case 0x5FF7:if(!(NSFHeader.SoundChip&4)) return; + case 0x5FF8: + case 0x5FF9: + case 0x5FFA: + case 0x5FFB: + case 0x5FFC: + case 0x5FFD: + case 0x5FFE: + case 0x5FFF:if(!BSon) return; + A&=0xF; + BANKSET((A*4096),V); + break; + } +} + +static DECLFR(NSF_read) +{ + int x; + + switch(A) + { + case 0x3ff0:x=SongReload; + if(!fceuindbg) + SongReload=0; + return x; + case 0x3ff1: + if(!fceuindbg) + { + memset(RAM,0x00,0x800); + + BWrite[0x4015](0x4015,0x0); + for(x=0;x<0x14;x++) + BWrite[0x4000+x](0x4000+x,0); + BWrite[0x4015](0x4015,0xF); + + if(NSFHeader.SoundChip&4) + { + BWrite[0x4017](0x4017,0xC0); /* FDS BIOS writes $C0 */ + BWrite[0x4089](0x4089,0x80); + BWrite[0x408A](0x408A,0xE8); + } + else + { + memset(ExWRAM,0x00,8192); + BWrite[0x4017](0x4017,0xC0); + BWrite[0x4017](0x4017,0xC0); + BWrite[0x4017](0x4017,0x40); + } + + if(BSon) + { + for(x=0;x<8;x++) + BANKSET(0x8000+x*4096,NSFHeader.BankSwitch[x]); + } + return (CurrentSong-1); + } + case 0x3FF3:return PAL; + } + return 0; +} + +uint8 FCEU_GetJoyJoy(void); + +static int special=0; + +void DrawNSF(uint8 *XBuf) +{ + char snbuf[16]; + int x; + + if(vismode==0) return; + + memset(XBuf,0,256*240); + + + { + int32 *Bufpl; + int32 mul=0; + + int l; + l=GetSoundBuffer(&Bufpl); + + if(special==0) + { + if(FSettings.SoundVolume) + mul=8192*240/(16384*FSettings.SoundVolume/50); + for(x=0;x<256;x++) + { + uint32 y; + y=142+((Bufpl[(x*l)>>8]*mul)>>14); + if(y<240) + XBuf[x+y*256]=3; + } + } + else if(special==1) + { + if(FSettings.SoundVolume) + mul=8192*240/(8192*FSettings.SoundVolume/50); + for(x=0;x<256;x++) + { + double r; + uint32 xp,yp; + + r=(Bufpl[(x*l)>>8]*mul)>>14; + xp=128+r*cos(x*M_PI*2/256); + yp=120+r*sin(x*M_PI*2/256); + xp&=255; + yp%=240; + XBuf[xp+yp*256]=3; + } + } + else if(special==2) + { + static double theta=0; + if(FSettings.SoundVolume) + mul=8192*240/(16384*FSettings.SoundVolume/50); + for(x=0;x<128;x++) + { + double xc,yc; + double r,t; + uint32 m,n; + + xc=(double)128-x; + yc=0-((double)( ((Bufpl[(x*l)>>8]) *mul)>>14)); + t=M_PI+atan(yc/xc); + r=sqrt(xc*xc+yc*yc); + + t+=theta; + m=128+r*cos(t); + n=120+r*sin(t); + + if(m<256 && n<240) + XBuf[m+n*256]=3; + + } + for(x=128;x<256;x++) + { + double xc,yc; + double r,t; + uint32 m,n; + + xc=(double)x-128; + yc=(double)((Bufpl[(x*l)>>8]*mul)>>14); + t=atan(yc/xc); + r=sqrt(xc*xc+yc*yc); + + t+=theta; + m=128+r*cos(t); + n=120+r*sin(t); + + if(m<256 && n<240) + XBuf[m+n*256]=3; + + } + theta+=(double)M_PI/256; + } + } + + DrawTextTrans(XBuf+10*256+4+(((31-strlen((char*)NSFHeader.SongName))<<2)), 256, NSFHeader.SongName, 6); + DrawTextTrans(XBuf+26*256+4+(((31-strlen((char*)NSFHeader.Artist))<<2)), 256,NSFHeader.Artist, 6); + DrawTextTrans(XBuf+42*256+4+(((31-strlen((char*)NSFHeader.Copyright))<<2)), 256,NSFHeader.Copyright, 6); + + DrawTextTrans(XBuf+70*256+4+(((31-strlen("Song:"))<<2)), 256, (uint8*)"Song:", 6); + sprintf(snbuf,"<%d/%d>",CurrentSong,NSFHeader.TotalSongs); + DrawTextTrans(XBuf+82*256+4+(((31-strlen(snbuf))<<2)), 256, (uint8*)snbuf, 6); + + { + static uint8 last=0; + uint8 tmp; + tmp=FCEU_GetJoyJoy(); + if((tmp&JOY_RIGHT) && !(last&JOY_RIGHT)) + { + if(CurrentSong1) + { + CurrentSong--; + SongReload=0xFF; + } + } + else if((tmp&JOY_UP) && !(last&JOY_UP)) + { + CurrentSong+=10; + if(CurrentSong>NSFHeader.TotalSongs) CurrentSong=NSFHeader.TotalSongs; + SongReload=0xFF; + } + else if((tmp&JOY_DOWN) && !(last&JOY_DOWN)) + { + CurrentSong-=10; + if(CurrentSong<1) CurrentSong=1; + SongReload=0xFF; + } + else if((tmp&JOY_START) && !(last&JOY_START)) + SongReload=0xFF; + else if((tmp&JOY_A) && !(last&JOY_A)) + { + special=(special+1)%3; + } + last=tmp; + } +} + +void DoNSFFrame(void) +{ + if(((NSFNMIFlags&1) && SongReload) || (NSFNMIFlags&2)) + TriggerNMI(); +} + +void FCEUI_NSFSetVis(int mode) +{ + vismode=mode; +} + +int FCEUI_NSFChange(int amount) +{ + CurrentSong+=amount; + if(CurrentSong<1) CurrentSong=1; + else if(CurrentSong>NSFHeader.TotalSongs) CurrentSong=NSFHeader.TotalSongs; + SongReload=0xFF; + + return(CurrentSong); +} + +/* Returns total songs */ +int FCEUI_NSFGetInfo(uint8 *name, uint8 *artist, uint8 *copyright, int maxlen) +{ + strncpy((char*)name,(char*)NSFHeader.SongName,maxlen); + strncpy((char*)artist,(char*)NSFHeader.Artist,maxlen); + strncpy((char*)copyright,(char*)NSFHeader.Copyright,maxlen); + return(NSFHeader.TotalSongs); +} diff --git a/nsf.h b/nsf.h index 3333201..c7bbb19 100644 --- a/nsf.h +++ b/nsf.h @@ -1,53 +1,47 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell - * - * 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 - */ - -typedef struct { - char ID[5]; /*NESM^Z*/ - uint8 Version; - uint8 TotalSongs; - uint8 StartingSong; - uint8 LoadAddressLow; - uint8 LoadAddressHigh; - uint8 InitAddressLow; - uint8 InitAddressHigh; - uint8 PlayAddressLow; - uint8 PlayAddressHigh; - uint8 SongName[32]; - uint8 Artist[32]; - uint8 Copyright[32]; - uint8 NTSCspeed[2]; // Unused - uint8 BankSwitch[8]; - uint8 PALspeed[2]; // Unused - uint8 VideoSystem; - uint8 SoundChip; - uint8 Expansion[4]; - uint8 reserve[8]; - } NSF_HEADER; -int NSFLoad(int fp); -DECLFW(NSF_write); -DECLFR(NSF_read); -void NSF_init(void); -extern uint8 CurrentSong; -extern uint8 SongReload; -void DrawNSF(uint8 *XBuf); -void NSFControl(int z); -extern NSF_HEADER NSFHeader; -void NSFDealloc(void); -void NSFDodo(void); +/* 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 + */ + +typedef struct { + char ID[5]; /*NESM^Z*/ + uint8 Version; + uint8 TotalSongs; + uint8 StartingSong; + uint8 LoadAddressLow; + uint8 LoadAddressHigh; + uint8 InitAddressLow; + uint8 InitAddressHigh; + uint8 PlayAddressLow; + uint8 PlayAddressHigh; + uint8 SongName[32]; + uint8 Artist[32]; + uint8 Copyright[32]; + uint8 NTSCspeed[2]; // Unused + uint8 BankSwitch[8]; + uint8 PALspeed[2]; // Unused + uint8 VideoSystem; + uint8 SoundChip; + uint8 Expansion[4]; + uint8 reserve[8]; + } NSF_HEADER; +void NSF_init(void); +void DrawNSF(uint8 *XBuf); +void NSFDealloc(void); +void NSFDodo(void); +void DoNSFFrame(void); diff --git a/sound.c b/sound.c index 0951e6f..9fb3216 100644 --- a/sound.c +++ b/sound.c @@ -83,6 +83,7 @@ static const uint32 SNoiseFreqTable[0x10]= static uint32 NoiseFreqTable[0x10]; int64 nesincsizeLL; +int64 nesincsize; static const uint8 NTSCPCMTable[0x10]= { @@ -330,15 +331,6 @@ static DECLFW(Write_PSG) X6502_IRQEnd(FCEU_IQDPCM); } break; - case 0x17: - V&=0xC0; - fcnt=0; - if(V&0x80) - FrameSoundUpdate(); - fhcnt=fhinc; - X6502_IRQEnd(FCEU_IQFCOUNT); - SIRQStat&=~0x40; - break; } PSG[A]=V; } @@ -851,12 +843,25 @@ static void RDoNoise(void) } } +DECLFW(Write_IRQFM) +{ + V=(V&0xC0)>>6; + fcnt=0; + if(V&0x2) + FrameSoundUpdate(); + fcnt=1; + fhcnt=fhinc; + X6502_IRQEnd(FCEU_IQFCOUNT); + SIRQStat&=~0x40; +// IRQFrameMode=V; +} + void SetNESSoundMap(void) { SetWriteHandler(0x4000,0x4013,Write_PSG); SetWriteHandler(0x4011,0x4011,Write0x11); SetWriteHandler(0x4015,0x4015,Write_PSG); - SetWriteHandler(0x4017,0x4017,Write_PSG); + SetWriteHandler(0x4017,0x4017,Write_IRQFM); SetReadHandler(0x4015,0x4015,Read_PSG); } @@ -917,6 +922,7 @@ static void FilterSound(uint32 *in, int32 *out, int16 *outMono, int count) +static int32 inbuf=0; int FlushEmulateSound(void) { int x; @@ -962,12 +968,15 @@ int FlushEmulateSound(void) for(x=0;x<5;x++) ChannelBC[x]=end&0xF; soundtsoffs=(soundtsinc*(end&0xF))>>16; - return(end>>4); + end>>=4; + inbuf=end; + return(end); } -void GetSoundBuffer(int32 **W) +int GetSoundBuffer(int32 **W) { *W=WaveNSF; + return inbuf; } void PowerSound(void) @@ -1023,7 +1032,8 @@ void SetSoundVariables(void) if(GameExpSound.RChange) GameExpSound.RChange(); - nesincsizeLL=(int64)((int64)562949953421312*(long double)(PAL?PAL_CPU:NTSC_CPU)/(FSettings.SndRate OVERSAMPLE)); + nesincsizeLL=(int64)((int64)562949953421312*(double)(PAL?PAL_CPU:NTSC_CPU)/(FSettings.SndRate OVERSAMPLE)); + nesincsize=(int64)(((int64)1<<17)*(double)(PAL?PAL_CPU:NTSC_CPU)/(FSettings.SndRate * 16)); PSG_base=(uint32)(PAL?(long double)PAL_CPU/16:(long double)NTSC_CPU/16); for(x=0;x<0x10;x++) diff --git a/sound.h b/sound.h index 02c6a68..9cffd4c 100644 --- a/sound.h +++ b/sound.h @@ -27,11 +27,17 @@ typedef struct { void (*Fill)(int Count); void (*RChange)(void); void (*Kill)(void); + + // from 0.98.15, currently unused + void (*NeoFill)(int32 *Wave, int Count); + void (*HiFill)(void); + void (*HiSync)(int32 ts); } EXPSOUND; extern EXPSOUND GameExpSound; extern int64 nesincsizeLL; +extern int64 nesincsize; extern uint8 PSG[]; extern uint32 PSG_base; extern int32 PCMIRQCount; @@ -62,7 +68,9 @@ extern uint8 fcnt; extern int32 fhcnt; extern int32 fhinc; -void GetSoundBuffer(int32 **W); +uint8 FCEU_GetJoyJoy(void); + +int GetSoundBuffer(int32 **W); int FlushEmulateSound(void); extern uint32 Wave[2048]; extern int32 WaveFinal[2048]; diff --git a/state.c b/state.c index e306eda..c50223d 100644 --- a/state.c +++ b/state.c @@ -43,7 +43,11 @@ #include "memory.h" #include "ppu.h" -static SFORMAT SFMDATA[64]; +static void (*SPreSave)(void) = 0; +static void (*SPostSave)(void) = 0; + +#define SFMDATA_SIZE (64) +static SFORMAT SFMDATA[SFMDATA_SIZE]; static int SFEXINDEX; static int stateversion; @@ -313,7 +317,11 @@ void SaveState(void) totalsize+=WriteStateChunk(st,3,FCEUPPU_STATEINFO); totalsize+=WriteStateChunk(st,4,FCEUCTRL_STATEINFO); totalsize+=WriteStateChunk(st,5,SFSND); + + + if(SPreSave) SPreSave(); totalsize+=WriteStateChunk(st,0x10,SFMDATA); + if(SPostSave) SPostSave(); fseek(st,4,SEEK_SET); write32(totalsize,st); @@ -418,27 +426,48 @@ void SaveStateRefresh(void) SaveStateStatus[0]=-1; } -void ResetExState(void) +void ResetExState(void (*PreSave)(void), void (*PostSave)(void)) { int x; for(x=0;x -#include -#include -#ifdef GP2X -#include -#endif - - -#include "types.h" -#include "fce.h" -#include "unif.h" -#include "version.h" -#include "svga.h" -#include "general.h" -#include "state.h" -#include "endian.h" -#include "file.h" -#include "cart.h" -#include "memory.h" -#include "input.h" - -typedef struct { - char ID[4]; - uint32 info; -} UNIF_HEADER; - -typedef struct { - char *name; - void (*init)(void); - int flags; -} BMAPPING; - -typedef struct { - char *name; - int (*init)(int fp); -} BFMAPPING; - -void (*BoardClose)(void); -void (*BoardPower)(void); -void (*BoardReset)(void); - -static int vramo; -static int mirrortodo; -int UNIFbattery; -static char *boardname; -static char *sboardname; -char *UNIFchrrama; - -static UNIF_HEADER unhead; -static UNIF_HEADER uchead; - - -static uint8 *malloced[32]; - -static int FixRomSize(uint32 size, uint32 minimum) -{ - int x=1; - - if(size15) - return(0); - printf(" PRG ROM %d size: %d",z,(int) uchead.info); - if(malloced[z]) - free(malloced[z]); - t=FixRomSize(uchead.info,2048); - if(!(malloced[z]=FCEU_malloc(t))) - return(0); - memset(malloced[z]+uchead.info,0xFF,t-uchead.info); - if(FCEU_fread(malloced[z],1,uchead.info,fp)!=uchead.info) - { - puts("Read Error!"); - return(0); - } - else - puts(""); - - SetupCartPRGMapping(z,malloced[z],t,0); - return(1); -} - -static int SetBoardName(int fp) -{ - if(!(boardname=FCEU_malloc(uchead.info+1))) - return(0); - FCEU_fread(boardname,1,uchead.info,fp); - boardname[uchead.info]=0; - printf(" Board name: %s\n",boardname); - sboardname=boardname; - if(!memcmp(boardname,"NES-",4) || !memcmp(boardname,"UNL-",4) || !memcmp(boardname,"HVC-",4) || !memcmp(boardname,"BTL-",4) || !memcmp(boardname,"BMC-",4)) - sboardname+=4; - return(1); -} - -static int LoadCHR(int fp) -{ - int z,t; - z=uchead.ID[3]-'0'; - if(z<0 || z>15) - return(0); - printf(" CHR ROM %d size: %d",z,(int) uchead.info); - if(malloced[16+z]) - free(malloced[16+z]); - t=FixRomSize(uchead.info,8192); - if(!(malloced[16+z]=FCEU_malloc(t))) - return(0); - memset(malloced[16+z]+uchead.info,0xFF,t-uchead.info); - if(FCEU_fread(malloced[16+z],1,uchead.info,fp)!=uchead.info) - { - puts("Read Error!"); - return(0); - } - else - puts(""); - - SetupCartCHRMapping(z,malloced[16+z],t,0); - return(1); -} - - -#define BMCFLAG_FORCE4 1 -#define BMCFLAG_CHRROK 2 // Ok for generic UNIF code to make available - // 8KB of CHR RAM if no CHR ROM is present. -#define BMC 48 - -BMAPPING bmap[BMC] = { - -/* Sachen Carts */ - { "TC-U01-1.5M", TCU01_Init,0}, - { "Sachen-8259B", S8259B_Init,BMCFLAG_CHRROK}, - { "Sachen-8259A", S8259A_Init,BMCFLAG_CHRROK}, - { "Sachen-74LS374N", S74LS374N_Init,0}, - { "SA-016-1M", SA0161M_Init,0}, - { "SA-72007", SA72007_Init,0}, - { "SA-72008", SA72008_Init,0}, - { "SA-0036", SA0036_Init,0}, - { "SA-0037", SA0037_Init,0}, - - { "H2288", H2288_Init,0}, -// /* AVE carts. */ -// { "MB-91", MB91_Init,0}, // DeathBots -// { "NINA-06", NINA06_Init,0}, // F-15 City War -// { "NINA-03", NINA03_Init,0}, // Tiles of Fate -// { "NINA-001", NINA001_Init,0}, // Impossible Mission 2 - - { "HKROM", HKROM_Init,0}, - - { "EWROM", EWROM_Init,0}, - { "EKROM", EKROM_Init,0}, - { "ELROM", ELROM_Init,0}, - { "ETROM", ETROM_Init,0}, - - { "SAROM", SAROM_Init,0}, - { "SBROM", SBROM_Init,0}, - { "SCROM", SCROM_Init,0}, - { "SEROM", SEROM_Init,0}, - { "SGROM", SGROM_Init,0}, - { "SKROM", SKROM_Init,0}, - { "SLROM", SLROM_Init,0}, - { "SL1ROM", SL1ROM_Init,0}, - { "SNROM", SNROM_Init,0}, - { "SOROM", SOROM_Init,0}, - - { "TGROM", TGROM_Init,0}, - { "TR1ROM", TFROM_Init,BMCFLAG_FORCE4}, - { "TFROM", TFROM_Init,0}, - { "TLROM", TLROM_Init,0}, - { "TKROM", TKROM_Init,0}, - { "TSROM", TSROM_Init,0}, - - { "TLSROM", TLSROM_Init,0}, - { "TKSROM", TKSROM_Init,0}, - { "TQROM", TQROM_Init,0}, - { "TVROM", TLROM_Init,BMCFLAG_FORCE4}, - - { "CPROM", CPROM_Init,0}, - { "CNROM", CNROM_Init,0}, - { "NROM", NROM256_Init,0 }, - { "RROM", NROM128_Init,0 }, - { "RROM-128", NROM128_Init,0 }, - { "NROM-128", NROM128_Init,0 }, - { "NROM-256", NROM256_Init,0 }, - { "MHROM", MHROM_Init,0}, - { "UNROM", UNROM_Init,0}, - { "MARIO1-MALEE2", MALEE_Init,0}, - { "Supervision16in1", Supervision16_Init,0}, - { "NovelDiamond9999999in1", Novel_Init,0}, - { "Super24in1SC03", Super24_Init,0} -}; - -#define BMF 7 -BFMAPPING bfunc[BMF] = { - { "CTRL", CTRL }, - { "TVCI", TVCI }, - { "BATR", EnableBattery }, - { "MIRR", DoMirroring }, - { "PRG", LoadPRG }, - { "CHR", LoadCHR }, - { "MAPR", SetBoardName } -}; - -int LoadUNIFChunks(int fp) -{ - int x; - int t; - for(;;) - { - t=FCEU_fread(&uchead,1,4,fp); - if(t<4) - { - if(t>0) - return 0; - return 1; - } - if(!(FCEU_read32(&uchead.info,fp))) - return 0; - t=0; - for(x=0;x +#include +#include + + +#include "types.h" +#include "fce.h" +#include "cart.h" +#include "unif.h" +#include "ines.h" +#include "general.h" +#include "state.h" +#include "endian.h" +#include "file.h" +#include "memory.h" +#include "input.h" +#include "md5.h" + +#include "svga.h" + +typedef struct { + char ID[4]; + uint32 info; +} UNIF_HEADER; + +typedef struct { + char *name; + void (*init)(CartInfo *); + int flags; +} BMAPPING; + +typedef struct { + char *name; + int (*init)(int fp); +} BFMAPPING; + +static CartInfo UNIFCart; + +static int vramo; +static int mirrortodo; +static uint8 *boardname; +static uint8 *sboardname; + +static uint32 CHRRAMSize; +uint8 *UNIFchrrama=0; + +static UNIF_HEADER unhead; +static UNIF_HEADER uchead; + + +static uint8 *malloced[32]; +static uint32 mallocedsizes[32]; + +static int FixRomSize(uint32 size, uint32 minimum) +{ + int x=1; + + if(size0) + if(index<99) + namebuf[index++]=t; + + namebuf[index]=0; + FCEU_printf("%s\n",namebuf); + + if(!FCEUGameInfo.name) + { + FCEUGameInfo.name=malloc(strlen(namebuf)+1); + strcpy((char *)FCEUGameInfo.name,namebuf); + } + return(1); +} +static int DINF(int fp) +{ + char name[100], method[100]; + uint8 d, m; + uint16 y; + int t; + + if(FCEU_fread(name,1,100,fp)!=100) + return(0); + if((t=FCEU_fgetc(fp))==EOF) return(0); + d=t; + if((t=FCEU_fgetc(fp))==EOF) return(0); + m=t; + if((t=FCEU_fgetc(fp))==EOF) return(0); + y=t; + if((t=FCEU_fgetc(fp))==EOF) return(0); + y|=t<<8; + if(FCEU_fread(method,1,100,fp)!=100) + return(0); + name[99]=method[99]=0; + FCEU_printf(" Dumped by: %s\n",name); + FCEU_printf(" Dumped with: %s\n",method); + { + char *months[12]={"January","February","March","April","May","June","July", + "August","September","October","November","December"}; + FCEU_printf(" Dumped on: %s %d, %d\n",months[(m-1)%12],d,y); + } + return(1); +} + +static int CTRL(int fp) +{ + int t; + + if((t=FCEU_fgetc(fp))==EOF) + return(0); + /* The information stored in this byte isn't very helpful, but it's + better than nothing...maybe. + */ + + if(t&1) FCEUGameInfo.input[0]=FCEUGameInfo.input[1]=SI_GAMEPAD; + else FCEUGameInfo.input[0]=FCEUGameInfo.input[1]=SI_NONE; + + if(t&2) FCEUGameInfo.input[1]=SI_ZAPPER; + //else if(t&0x10) FCEUGameInfo->input[1]=SI_POWERPAD; + + return(1); +} + +static int TVCI(int fp) +{ + int t; + if( (t=FCEU_fgetc(fp)) ==EOF) + return(0); + if(t<=2) + { + char *stuffo[3]={"NTSC","PAL","NTSC and PAL"}; + if(t==0) + { + FCEUGameInfo.vidsys=GIV_NTSC; + FCEUI_SetVidSystem(0); + } + else if(t==1) + { + FCEUGameInfo.vidsys=GIV_PAL; + FCEUI_SetVidSystem(1); + } + FCEU_printf(" TV Standard Compatibility: %s\n",stuffo[t]); + } + return(1); +} + +static int EnableBattery(int fp) +{ + FCEU_printf(" Battery-backed.\n"); + if(FCEU_fgetc(fp)==EOF) + return(0); + UNIFCart.battery=1; + return(1); +} + +static int LoadPRG(int fp) +{ + int z,t; + z=uchead.ID[3]-'0'; + + if(z<0 || z>15) + return(0); + FCEU_printf(" PRG ROM %d size: %d",z,(int) uchead.info); + if(malloced[z]) + free(malloced[z]); + t=FixRomSize(uchead.info,2048); + if(!(malloced[z]=(uint8 *)FCEU_malloc(t))) + return(0); + mallocedsizes[z]=t; + memset(malloced[z]+uchead.info,0xFF,t-uchead.info); + if(FCEU_fread(malloced[z],1,uchead.info,fp)!=uchead.info) + { + FCEU_printf("Read Error!\n"); + return(0); + } + else + FCEU_printf("\n"); + + SetupCartPRGMapping(z,malloced[z],t,0); + return(1); +} + +static int SetBoardName(int fp) +{ + if(!(boardname=(uint8 *)FCEU_malloc(uchead.info+1))) + return(0); + FCEU_fread(boardname,1,uchead.info,fp); + boardname[uchead.info]=0; + FCEU_printf(" Board name: %s\n",boardname); + sboardname=boardname; + if(!memcmp(boardname,"NES-",4) || !memcmp(boardname,"UNL-",4) || !memcmp(boardname,"HVC-",4) || !memcmp(boardname,"BTL-",4) || !memcmp(boardname,"BMC-",4)) + sboardname+=4; + return(1); +} + +static int LoadCHR(int fp) +{ + int z,t; + z=uchead.ID[3]-'0'; + if(z<0 || z>15) + return(0); + FCEU_printf(" CHR ROM %d size: %d",z,(int) uchead.info); + if(malloced[16+z]) + free(malloced[16+z]); + t=FixRomSize(uchead.info,8192); + if(!(malloced[16+z]=(uint8 *)FCEU_malloc(t))) + return(0); + mallocedsizes[16+z]=t; + memset(malloced[16+z]+uchead.info,0xFF,t-uchead.info); + if(FCEU_fread(malloced[16+z],1,uchead.info,fp)!=uchead.info) + { + FCEU_printf("Read Error!\n"); + return(0); + } + else + FCEU_printf("\n"); + + SetupCartCHRMapping(z,malloced[16+z],t,0); + return(1); +} + + +#define BMCFLAG_FORCE4 1 +#define BMCFLAG_16KCHRR 2 +#define BMCFLAG_32KCHRR 4 + +static BMAPPING bmap[] = { + +/* Sachen Carts */ + { "TC-U01-1.5M", TCU01_Init,0}, + { "Sachen-8259A", S8259A_Init,0}, + { "Sachen-8259B", S8259B_Init,0}, + { "Sachen-8259C", S8259C_Init,0}, + { "Sachen-8259D", S8259D_Init,0}, + { "Sachen-74LS374N", S74LS374N_Init,0}, + { "Sachen-74LS374NA", S74LS374NA_Init,0}, //seems to be custom mapper + { "SA-016-1M", SA0161M_Init,0}, + { "SA-72007", SA72007_Init,0}, + { "SA-72008", SA72008_Init,0}, + { "SA-0036", SA0036_Init,0}, + { "SA-0037", SA0037_Init,0}, + { "SA-NROM", TCA01_Init,0}, + + { "H2288", UNLH2288_Init,0}, + { "8237", UNL8237_Init,0}, + +// /* AVE carts. */ +// { "MB-91", MB91_Init,0}, // DeathBots +// { "NINA-06", NINA06_Init,0}, // F-15 City War +// { "NINA-03", NINA03_Init,0}, // Tiles of Fate +// { "NINA-001", NINA001_Init,0}, // Impossible Mission 2 + + { "HKROM", HKROM_Init,0}, + + { "EWROM", EWROM_Init,0}, + { "EKROM", EKROM_Init,0}, + { "ELROM", ELROM_Init,0}, + { "ETROM", ETROM_Init,0}, + + { "SAROM", SAROM_Init,0}, + { "SBROM", SBROM_Init,0}, + { "SCROM", SCROM_Init,0}, + { "SEROM", SEROM_Init,0}, + { "SGROM", SGROM_Init,0}, + { "SKROM", SKROM_Init,0}, + { "SLROM", SLROM_Init,0}, + { "SL1ROM", SL1ROM_Init,0}, + { "SNROM", SNROM_Init,0}, + { "SOROM", SOROM_Init,0}, + + { "TGROM", TGROM_Init,0}, + { "TR1ROM", TFROM_Init,BMCFLAG_FORCE4}, + + { "TEROM", TEROM_Init,0}, + { "TFROM", TFROM_Init,0}, + { "TLROM", TLROM_Init,0}, + { "TKROM", TKROM_Init,0}, + { "TSROM", TSROM_Init,0}, + + { "TLSROM", TLSROM_Init,0}, + { "TKSROM", TKSROM_Init,0}, + { "TQROM", TQROM_Init,0}, + { "TVROM", TLROM_Init,BMCFLAG_FORCE4}, + + { "CPROM", CPROM_Init,BMCFLAG_16KCHRR}, + { "CNROM", CNROM_Init,0}, + { "GNROM", GNROM_Init,0}, + { "NROM", NROM256_Init,0 }, + { "RROM", NROM128_Init,0 }, + { "RROM-128", NROM128_Init,0 }, + { "NROM-128", NROM128_Init,0 }, + { "NROM-256", NROM256_Init,0 }, + { "MHROM", MHROM_Init,0}, + { "UNROM", UNROM_Init,0}, + { "MARIO1-MALEE2", MALEE_Init,0}, + + { "CC-21", UNLCC21_Init,0}, + + { "8157", UNL8157_Init,0}, + { "Supervision16in1", Supervision16_Init,0}, + { "NovelDiamond9999999in1", Novel_Init,0}, + { "Super24in1SC03", Super24_Init,0}, + { "SuperHIK8in1", Mapper45_Init,0}, + { "DREAMTECH01", DreamTech01_Init,0}, + { "KONAMI-QTAI", Mapper190_Init,0}, + {0,0,0} +}; + +static BFMAPPING bfunc[] = { + { "CTRL", CTRL }, + { "TVCI", TVCI }, + { "BATR", EnableBattery }, + { "MIRR", DoMirroring }, + { "PRG", LoadPRG }, + { "CHR", LoadCHR }, + { "NAME", NAME }, + { "MAPR", SetBoardName }, + { "DINF", DINF }, + { 0, 0 } +}; + +int LoadUNIFChunks(int fp) +{ + int x; + int t; + for(;;) + { + t=FCEU_fread(&uchead,1,4,fp); + if(t<4) + { + if(t>0) + return 0; + return 1; + } + if(!(FCEU_read32(&uchead.info,fp))) + return 0; + t=0; + x=0; + //printf("Funky: %s\n",((uint8 *)&uchead)); + while(bfunc[x].name) + { + if(!memcmp(&uchead,bfunc[x].name,strlen(bfunc[x].name))) + { + if(!bfunc[x].init(fp)) + return 0; + t=1; + break; + } + x++; + } + if(!t) + if(FCEU_fseek(fp,uchead.info,SEEK_CUR)) + return(0); + } +} + +static int InitializeBoard(void) +{ + int x=0; + + if(!sboardname) return(0); + + while(bmap[x].name) + { + if(!strcmp((char *)sboardname,(char *)bmap[x].name)) + { + if(!malloced[16]) + { + if(bmap[x].flags & BMCFLAG_16KCHRR) + CHRRAMSize = 16384; + else + CHRRAMSize = 8192; + if((UNIFchrrama=(uint8 *)FCEU_malloc(CHRRAMSize))) + { + SetupCartCHRMapping(0,UNIFchrrama,CHRRAMSize,1); + AddExState(UNIFchrrama, CHRRAMSize, 0,"CHRR"); + } + else + return(-1); + } + if(bmap[x].flags&BMCFLAG_FORCE4) + mirrortodo=4; + MooMirroring(); + bmap[x].init(&UNIFCart); + return(1); + } + x++; + } + FCEU_PrintError("Board type not supported."); + return(0); +} + +static void UNIFGI(int h) +{ + switch(h) + { + case GI_RESETM2: + if(UNIFCart.Reset) + UNIFCart.Reset(); + break; + case GI_POWER: + if(UNIFCart.Power) + UNIFCart.Power(); + if(UNIFchrrama) memset(UNIFchrrama,0,8192); + break; + case GI_CLOSE: + FCEU_SaveGameSave(&UNIFCart); + if(UNIFCart.Close) + UNIFCart.Close(); + FreeUNIF(); + break; + } +} + +int UNIFLoad(const char *name, int fp) +{ + FCEU_fseek(fp,0,SEEK_SET); + FCEU_fread(&unhead,1,4,fp); + if(memcmp(&unhead,"UNIF",4)) + return 0; + + ResetCartMapping(); + + ResetExState(0,0); + ResetUNIF(); + if(!FCEU_read32(&unhead.info,fp)) + goto aborto; + if(FCEU_fseek(fp,0x20,SEEK_SET)<0) + goto aborto; + if(!LoadUNIFChunks(fp)) + goto aborto; + { + int x; + struct md5_context md5; + + md5_starts(&md5); + + for(x=0;x<32;x++) + if(malloced[x]) + { + md5_update(&md5,malloced[x],mallocedsizes[x]); + } + md5_finish(&md5,UNIFCart.MD5); + FCEU_printf(" ROM MD5: 0x"); + for(x=0;x<16;x++) + FCEU_printf("%02x",UNIFCart.MD5[x]); + FCEU_printf("\n"); + memcpy(FCEUGameInfo.MD5,UNIFCart.MD5,sizeof(UNIFCart.MD5)); + } + + if(!InitializeBoard()) + goto aborto; + + FCEU_LoadGameSave(&UNIFCart); + GameInterface=UNIFGI; + return 1; + + aborto: + + FreeUNIF(); + ResetUNIF(); + + + return 0; +} diff --git a/unif.h b/unif.h index 1db41dd..f423765 100644 --- a/unif.h +++ b/unif.h @@ -1,94 +1,88 @@ -/* FCE Ultra - NES/Famicom Emulator - * - * Copyright notice for this file: - * Copyright (C) 2002 Ben Parnell - * - * 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 - */ - -#ifndef UNIFPRIV -int UNIFLoad(char *name, int fp); -#endif - -void TCU01_Init(void); -void S8259B_Init(void); -void S8259A_Init(void); -void S74LS374N_Init(void); -void SA0161M_Init(void); - -void SA72007_Init(void); -void SA72008_Init(void); -void SA0036_Init(void); -void SA0037_Init(void); - -void H2288_Init(void); - -void HKROM_Init(void); - -void ETROM_Init(void); -void EKROM_Init(void); -void ELROM_Init(void); -void EWROM_Init(void); - -void SAROM_Init(void); -void SBROM_Init(void); -void SCROM_Init(void); -void SEROM_Init(void); -void SGROM_Init(void); -void SKROM_Init(void); -void SLROM_Init(void); -void SL1ROM_Init(void); -void SNROM_Init(void); -void SOROM_Init(void); - -void NROM_Init(void); -void NROM256_Init(void); -void NROM128_Init(void); -void MHROM_Init(void); -void UNROM_Init(void); -void MALEE_Init(void); -void Supervision16_Init(void); -void Super24_Init(void); -void Novel_Init(void); -void CNROM_Init(void); -void CPROM_Init(void); - -void TFROM_Init(void); -void TGROM_Init(void); -void TKROM_Init(void); -void TSROM_Init(void); -void TLROM_Init(void); -void TLSROM_Init(void); -void TKSROM_Init(void); -void TQROM_Init(void); -void TQROM_Init(void); - - -void UNIFOpenWRAM(int t, char *ext, int override); -void UNIFWriteWRAM(uint8 *p, int size); -void UNIFReadWRAM(uint8 *p, int size); -void UNIFCloseWRAM(void); -#define UOW_RD 0 -#define UOW_WR 1 - -extern void (*BoardClose)(void); -extern void (*BoardPower)(void); -extern void (*BoardReset)(void); - -#define UNIFMemBlock (GameMemBlock+32768) - -extern int UNIFbattery; -extern char *UNIFchrrama; // Meh. So I can't stop CHR RAM - // bank switcherooing with certain boards... +/* 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 TCA01_Init(CartInfo *info); +void TCU01_Init(CartInfo *info); +void S8259A_Init(CartInfo *info); +void S8259B_Init(CartInfo *info); +void S8259C_Init(CartInfo *info); +void S8259D_Init(CartInfo *info); +void S74LS374N_Init(CartInfo *info); +void S74LS374NA_Init(CartInfo *info); +void SA0161M_Init(CartInfo *info); + +void SA72007_Init(CartInfo *info); +void SA72008_Init(CartInfo *info); +void SA0036_Init(CartInfo *info); +void SA0037_Init(CartInfo *info); + +void UNLH2288_Init(CartInfo *info); +void UNL8237_Init(CartInfo *info); +void UNL8157_Init(CartInfo *info); + +void HKROM_Init(CartInfo *info); + +void ETROM_Init(CartInfo *info); +void EKROM_Init(CartInfo *info); +void ELROM_Init(CartInfo *info); +void EWROM_Init(CartInfo *info); + +void SAROM_Init(CartInfo *info); +void SBROM_Init(CartInfo *info); +void SCROM_Init(CartInfo *info); +void SEROM_Init(CartInfo *info); +void SGROM_Init(CartInfo *info); +void SKROM_Init(CartInfo *info); +void SLROM_Init(CartInfo *info); +void SL1ROM_Init(CartInfo *info); +void SNROM_Init(CartInfo *info); +void SOROM_Init(CartInfo *info); + +void NROM_Init(CartInfo *info); +void NROM256_Init(CartInfo *info); +void NROM128_Init(CartInfo *info); +void MHROM_Init(CartInfo *info); +void UNROM_Init(CartInfo *info); +void MALEE_Init(CartInfo *info); +void Supervision16_Init(CartInfo *info); +void Super24_Init(CartInfo *info); +void Novel_Init(CartInfo *info); +void CNROM_Init(CartInfo *info); +void CPROM_Init(CartInfo *info); +void GNROM_Init(CartInfo *info); + +void TEROM_Init(CartInfo *info); +void TFROM_Init(CartInfo *info); +void TGROM_Init(CartInfo *info); +void TKROM_Init(CartInfo *info); +void TSROM_Init(CartInfo *info); +void TLROM_Init(CartInfo *info); +void TLSROM_Init(CartInfo *info); +void TKSROM_Init(CartInfo *info); +void TQROM_Init(CartInfo *info); +void TQROM_Init(CartInfo *info); + +void DEIROM_Init(CartInfo *info); +void DreamTech01_Init(CartInfo *info); +void Mapper190_Init(CartInfo *info); +void UNLCC21_Init(CartInfo *info); + +extern uint8 *UNIFchrrama; // Meh. So I can stop CHR RAM + // bank switcherooing with certain boards... diff --git a/video.c b/video.c index adcb786..397f82e 100644 --- a/video.c +++ b/video.c @@ -46,8 +46,6 @@ uint8 *XBuf=NULL; int InitVirtualVideo(void) { - uint32 m; - if(!XBuf) /* Some driver code may allocate XBuf externally. */ if(!(XBuf = (uint8*) (FCEU_malloc(320 * 240)))) return 0; diff --git a/vsuni.c b/vsuni.c new file mode 100644 index 0000000..3fb3bcd --- /dev/null +++ b/vsuni.c @@ -0,0 +1,419 @@ +/* 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 +#include + +#include "types.h" +#include "x6502.h" +#include "fce.h" +#include "input.h" +#include "netplay.h" +#include "vsuni.h" +#include "state.h" + +#include "svga.h" + +#define IOPTION_GUN 0x1 +#define IOPTION_SWAPDIRAB 0x2 + +#define IOPTION_PREDIP 0x10 +typedef struct +{ + char *name; + uint64 md5partial; + int mapper; + int mirroring; + int ppu; + int ioption; + int predip; +} VSUNIENTRY; + +VSUNIENTRY *curvs; + +static uint8 DIPS=0; +uint8 vsdip=0; + +void FCEUI_VSUniToggleDIPView(void) +{ + DIPS=!DIPS; +} + +void FCEU_VSUniToggleDIP(int w) +{ + vsdip^=1<> w) & 1) != state) + FCEUI_VSUniToggleDIP(w); +} + +uint8 FCEUI_VSUniGetDIPs(void) +{ + return(vsdip); +} + +static uint8 secdata[2][32]= +{ + { + 0xff, 0xbf, 0xb7, 0x97, 0x97, 0x17, 0x57, 0x4f, + 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, 0x94, 0x14, + 0x56, 0x4e, 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, + 0xd4, 0x5c, 0x3e, 0x26, 0x87, 0x83, 0x13, 0x00 + }, + { + 0x00, 0x00, 0x00, 0x00, 0xb4, 0x00, 0x00, 0x00, + 0x00, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x94, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + } +}; + +static uint8 *secptr; + +static uint8 VSindex; + +static DECLFR(VSSecRead) +{ + switch(A) + { + case 0x5e00: VSindex=0;return X.DB; + case 0x5e01: return(secptr[(VSindex++)&0x1F]); + } + return(0x00); +} +uint8 coinon=0; + +void FCEU_VSUniCoin(void) +{ + coinon=6; +} + +static int curppu; +static int64 curmd5; + +#define RP2C04_001 1 +#define RP2C04_002 2 +#define RP2C04_003 3 +#define RP2C05_004 4 +#define RCP2C03B 5 +#define RC2C05_01 6 +#define RC2C05_02 7 +#define RC2C05_03 8 +#define RC2C05_04 9 + +static readfunc OldReadPPU; +static writefunc OldWritePPU[2]; + +static DECLFR(A2002_Gumshoe) +{ + return( (OldReadPPU(A)&~0x3F) | 0x1C); +} + +static DECLFR(A2002_Topgun) +{ + return( (OldReadPPU(A)&~0x3F) | 0x1B); +} + +static DECLFR(A2002_MBJ) // Mighty Bomb Jack +{ + return( (OldReadPPU(A)&~0x3F) | 0x3D); +} + +static DECLFW(B2000_2001_2C05) +{ + OldWritePPU[(A&1)^1](A ^ 1, V); +} +static uint8 xevselect = 0; +static DECLFR(XevRead) +{ + //printf("%04x\n",A); + if(A == 0x54FF) + { + return(0x5); + } + else if(A == 0x5678) + { + return(xevselect?0:1); + } + else if(A == 0x578F) + { + return(xevselect?0xd1:0x89); + } + else if(A == 0x5567) + { + xevselect ^=1; + return(xevselect?0x37:0x3E); + } + return(X.DB); +} + +void FCEU_VSUniSwap(uint8 *j0, uint8 *j1) +{ + if(curvs->ioption & IOPTION_SWAPDIRAB) + { + uint16 t=*j0; + *j0=(*j0&0xC)|(*j1&0xF3); + *j1=(*j1&0xC)|(t&0xF3); + } +} + +void FCEU_VSUniPower(void) +{ + coinon = 0; + VSindex = 0; + + if(secptr) + SetReadHandler(0x5e00,0x5e01,VSSecRead); + + if(curppu == RC2C05_04) + { + OldReadPPU = GetReadHandler(0x2002); + SetReadHandler(0x2002, 0x2002, A2002_Topgun); + } + else if(curppu == RC2C05_03) + { + OldReadPPU = GetReadHandler(0x2002); + SetReadHandler(0x2002, 0x2002, A2002_Gumshoe); + } + else if(curppu == RC2C05_02) + { + OldReadPPU = GetReadHandler(0x2002); + SetReadHandler(0x2002, 0x2002, A2002_MBJ); + } + if(curppu == RC2C05_04 || curppu == RC2C05_01 || curppu == RC2C05_03 || curppu == RC2C05_02) + { + OldWritePPU[0] = GetWriteHandler(0x2000); + OldWritePPU[1] = GetWriteHandler(0x2001); + SetWriteHandler(0x2000, 0x2001, B2000_2001_2C05); + } + if(curmd5 == 0x2d396247cf58f9faLL) /* Super Xevious */ + { + SetReadHandler(0x5400,0x57FF,XevRead); + } +} + +/* Games that will probably not be supported ever(or for a long time), since they require + dual-system: + + Balloon Fight + VS Mahjong + VS Tennis + Wrecking Crew +*/ + +/* Games/PPU list. Information copied from MAME. ROMs are exchangable, so don't take + this list as "this game must use this PPU". + +RP2C04-001: +- Baseball +- Freedom Force +- Gradius +- Hogan's Alley +- Mach Rider (Japan, Fighting Course) +- Pinball +- Platoon +- Super Xevious + +RP2C04-002: +- Castlevania +- Ladies golf +- Mach Rider (Endurance Course) +- Raid on Bungeling Bay (Japan) +- Slalom +- Stroke N' Match Golf +- Wrecking Crew + +RP2C04-003: +- Dr mario +- Excite Bike +- Goonies +- Soccer +- TKO Boxing + +RP2c05-004: +- Clu Clu Land +- Excite Bike (Japan) +- Ice Climber +- Ice Climber Dual (Japan) +- Super Mario Bros. + +Rcp2c03b: +- Battle City +- Duck Hunt +- Mahjang +- Pinball (Japan) +- Rbi Baseball +- Star Luster +- Stroke and Match Golf (Japan) +- Super Skykid +- Tennis +- Tetris + +RC2C05-01: +- Ninja Jajamaru Kun (Japan) + +RC2C05-02: +- Mighty Bomb Jack (Japan) + +RC2C05-03: +- Gumshoe + +RC2C05-04: +- Top Gun +*/ + +VSUNIENTRY VSUniGames[] = +{ + {"Baseball", 0x691d4200ea42be45LL, 99, 2,RP2C04_001,0}, + {"Battle City", 0x8540949d74c4d0ebLL, 99, 2,RP2C04_001,0}, + {"Battle City(Bootleg)",0x8093cbe7137ac031LL, 99, 2,RP2C04_001,0}, + + {"Clu Clu Land", 0x1b8123218f62b1eeLL, 99, 2,RP2C05_004,IOPTION_SWAPDIRAB}, + {"Dr Mario", 0xe1af09c477dc0081LL, 1, 0,RP2C04_003,IOPTION_SWAPDIRAB}, + {"Duck Hunt", 0x47735d1e5f1205bbLL, 99, 2,RCP2C03B ,IOPTION_GUN}, + {"Excitebike", 0x3dcd1401bcafde77LL, 99, 2,RP2C04_003,0}, + {"Excitebike (J)", 0x7ea51c9d007375f0LL, 99, 2,RP2C05_004,0}, + {"Freedom Force", 0xed96436bd1b5e688LL, 4, 0,RP2C04_001,IOPTION_GUN}, /* Wrong color in game select screen? */ + {"Stroke and Match Golf",0x612325606e82bc66LL, 99, 2,RP2C04_002,IOPTION_SWAPDIRAB|IOPTION_PREDIP,0x01}, + + {"Goonies", 0x3b0085c4ff29098eLL, 151,1,RP2C04_003,0}, + {"Gradius", 0x50687ae63bdad976LL,151, 1,RP2C04_001,IOPTION_SWAPDIRAB}, + {"Gumshoe", 0xb8500780bf69ce29LL, 99, 2,RC2C05_03,IOPTION_GUN}, + {"Hogan's Alley", 0xd78b7f0bb621fb45LL, 99, 2,RP2C04_001,IOPTION_GUN}, + {"Ice Climber", 0xd21e999513435e2aLL, 99, 2,RP2C05_004,IOPTION_SWAPDIRAB}, + {"Ladies Golf", 0x781b24be57ef6785LL, 99, 2,RP2C04_002,IOPTION_SWAPDIRAB|IOPTION_PREDIP,0x1}, + + {"Mach Rider", 0x015672618af06441LL, 99, 2, RP2C04_002,0}, + {"Mach Rider (J)", 0xa625afb399811a8aLL, 99, 2, RP2C04_001,0}, + {"Mighty Bomb Jack", 0xe6a89f4873fac37bLL, 0, 2, RC2C05_02,0}, + {"Ninja Jajamaru Kun", 0xb26a2c31474099c0LL, 99, 2,RC2C05_01 ,IOPTION_SWAPDIRAB}, + {"Pinball", 0xc5f49d3de7f2e9b8LL, 99, 2,RP2C04_001,IOPTION_PREDIP,0x01}, + {"Pinball (J)", 0x66ab1a3828cc901cLL, 99, 2,RCP2C03B,IOPTION_PREDIP,0x1}, + {"Platoon", 0x160f237351c19f1fLL, 68, 1,RP2C04_001,0}, + {"RBI Baseball", 0x6a02d345812938afLL, 4, 1,RP2C04_001 ,IOPTION_SWAPDIRAB}, + {"Soccer", 0xd4e7a9058780eda3LL, 99, 2,RP2C04_003,IOPTION_SWAPDIRAB}, + {"Star Luster", 0x8360e134b316d94cLL, 99, 2,RCP2C03B ,0}, + {"Stroke and Match Golf (J)",0x869bb83e02509747LL, 99, 2,RCP2C03B,IOPTION_SWAPDIRAB|IOPTION_PREDIP,0x1}, + {"Super Sky Kid", 0x78d04c1dd4ec0101LL, 4, 1,RCP2C03B ,IOPTION_SWAPDIRAB | IOPTION_PREDIP,0x20}, + + {"Super Xevious", 0x2d396247cf58f9faLL, 206, 0,RP2C04_001,0}, + {"Tetris", 0x531a5e8eea4ce157LL, 99, 2,RCP2C03B ,IOPTION_PREDIP,0x20}, + {"Top Gun", 0xf1dea36e6a7b531dLL, 2, 0,RC2C05_04 ,0}, + {"VS Castlevania", 0x92fd6909c81305b9LL, 2, 1,RP2C04_002,0}, + {"VS Slalom", 0x4889b5a50a623215LL, 0, 1,RP2C04_002,0}, + {"VS Super Mario Bros",0x39d8cfa788e20b6cLL, 99, 2,RP2C05_004,0}, + {"VS TKO Boxing", 0x6e1ee06171d8ce3aLL,4, 1,RP2C04_003,IOPTION_PREDIP,0x00}, + {0} +}; + +void FCEU_VSUniCheck(uint64 md5partial, int *MapperNo, uint8 *Mirroring) +{ + VSUNIENTRY *vs = VSUniGames; + + while(vs->name) + { + if(md5partial == vs->md5partial) + { + + if(vs->ppu < RCP2C03B) pale = vs->ppu; + //puts(vs->name); + *MapperNo = vs->mapper; + *Mirroring = vs->mirroring; + FCEUGameInfo.type = GIT_VSUNI; + FCEUGameInfo.cspecial = SIS_VSUNISYSTEM; + FCEUGameInfo.inputfc = SIFC_NONE; + curppu = vs->ppu; + curmd5 = md5partial; + + secptr = 0; + + { + static int64 tko=0x6e1ee06171d8ce3aULL, rbi=0x6a02d345812938afULL; + if(md5partial == tko) + secptr=secdata[0]; + if(md5partial == rbi) + secptr = secdata[1]; + } + + vsdip = 0x0; + if(vs->ioption & IOPTION_PREDIP) + { + vsdip= vs->predip; + } + if(vs->ioption & IOPTION_GUN) + { + FCEUGameInfo.input[0] = SI_ZAPPER; + FCEUGameInfo.input[1] = SI_NONE; + } + else + { + FCEUGameInfo.input[0] = FCEUGameInfo.input[1] = SI_GAMEPAD; + } + curvs = vs; + return; + } + vs++; + } +} + +void FCEU_VSUniDraw(uint8 *XBuf) +{ + uint32 *dest; + int y,x; + + if(!DIPS) return; + + dest=(uint32 *)(XBuf+256*12+164); + for(y=24;y;y--,dest+=(256-72)>>2) + { + for(x=72>>2;x;x--,dest++) + *dest=0; + } + + dest=(uint32 *)(XBuf+256*(12+4)+164+6 ); + for(y=16;y;y--,dest+=(256>>2)-16) + for(x=8;x;x--) + { + *dest=0x01010101; + dest+=2; + } + + dest=(uint32 *)(XBuf+256*(12+4)+164+6 ); + for(x=0;x<8;x++,dest+=2) + { + uint32 *da=dest+(256>>2); + + if(!((vsdip>>x)&1)) + da+=(256>>2)*10; + for(y=4;y;y--,da+=256>>2) + *da=0; + } +} + + +SFORMAT FCEUVSUNI_STATEINFO[]={ + { &vsdip, 1, "vsdp"}, + { &coinon, 1, "vscn"}, + { &VSindex, 1, "vsin"}, + { 0} +}; diff --git a/vsuni.h b/vsuni.h new file mode 100644 index 0000000..14fb715 --- /dev/null +++ b/vsuni.h @@ -0,0 +1,7 @@ +void FCEU_VSUniPower(void); +void FCEU_VSUniCheck(uint64 md5partial, int *, uint8 *); +void FCEU_VSUniDraw(uint8 *XBuf); + +void FCEU_VSUniToggleDIP(int); /* For movies and netplay */ +void FCEU_VSUniCoin(void); +void FCEU_VSUniSwap(uint8 *j0, uint8 *j1); diff --git a/x6502.h b/x6502.h index 1a44b30..f13bbdd 100644 --- a/x6502.h +++ b/x6502.h @@ -52,6 +52,8 @@ extern void FP_FASTAPASS(1) (*MapIRQHook)(int a); #define FCEU_IQDPCM 0x10 #define FCEU_IQFCOUNT 0x20 #define FCEU_IQTEMP 0x80 +// from 0.98.15 +#define FCEU_IQEXT2 0x02 #if defined(DEBUG_ASM_6502) #define TriggerIRQ TriggerIRQ_d -- 2.39.2