Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/ClusterM/fceux.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeromus <zeromus@users.sf.net>2006-07-18 06:53:36 +0400
committerzeromus <zeromus@users.sf.net>2006-07-18 06:53:36 +0400
commitdfd763c100bf35da5f592bc874ec3fccda0cc9fa (patch)
tree3076e253b46850fb68859814c22bb4b6156edca5
initial checkin of tasbuild
[[Split portion of a mixed commit.]]
-rw-r--r--.gitignore17
-rw-r--r--boards/112.c90
-rw-r--r--boards/117.c101
-rw-r--r--boards/164.c116
-rw-r--r--boards/183.c117
-rw-r--r--boards/185.c116
-rw-r--r--boards/186.c104
-rw-r--r--boards/187.c104
-rw-r--r--boards/189.c48
-rw-r--r--boards/208.c83
-rw-r--r--boards/222.c99
-rw-r--r--boards/235.c70
-rw-r--r--boards/57.c93
-rw-r--r--boards/8157.c80
-rw-r--r--boards/8237.c93
-rw-r--r--boards/88.c87
-rw-r--r--boards/90.c466
-rw-r--r--boards/95.c124
-rw-r--r--boards/Makefile.am.inc1
-rw-r--r--boards/__dummy_mapper.c96
-rw-r--r--boards/bmc13in1jy110.c103
-rw-r--r--boards/bmc42in1r.c87
-rw-r--r--boards/bmc64in1nr.c93
-rw-r--r--boards/bmc70in1.c116
-rw-r--r--boards/bmcgk192.c67
-rw-r--r--boards/bonza.c139
-rw-r--r--boards/cc21.c56
-rw-r--r--boards/datalatch.c272
-rw-r--r--boards/deirom.c82
-rw-r--r--boards/dream.c56
-rw-r--r--boards/fk23c.c112
-rw-r--r--boards/h2288.c89
-rw-r--r--boards/karaoke.c71
-rw-r--r--boards/kof97.c50
-rw-r--r--boards/konami-qtai.c128
-rw-r--r--boards/malee.c41
-rw-r--r--boards/mapinc.h11
-rw-r--r--boards/mmc1.c423
-rw-r--r--boards/mmc3.c1602
-rw-r--r--boards/mmc3.h23
-rw-r--r--boards/mmc5.c834
-rw-r--r--boards/n106.c469
-rw-r--r--boards/novel.c55
-rw-r--r--boards/sachen.c398
-rw-r--r--boards/sheroes.c86
-rw-r--r--boards/sl1632.c159
-rw-r--r--boards/sonic5.c71
-rw-r--r--boards/subor.c79
-rw-r--r--boards/super24.c99
-rw-r--r--boards/supervision.c74
-rw-r--r--boards/t-262.c83
-rw-r--r--boards/tengen.c198
-rw-r--r--cart.c685
-rw-r--r--cart.h100
-rw-r--r--cheat.c855
-rw-r--r--cheat.h7
-rw-r--r--crc32.c33
-rw-r--r--crc32.h1
-rw-r--r--debug.c535
-rw-r--r--debug.h24
-rw-r--r--drawing.h228
-rw-r--r--driver.h317
-rw-r--r--drivers/common/Makefile.am.inc1
-rw-r--r--drivers/common/args.c98
-rw-r--r--drivers/common/args.h12
-rw-r--r--drivers/common/cheat.c523
-rw-r--r--drivers/common/cheat.h21
-rw-r--r--drivers/common/config.c152
-rw-r--r--drivers/common/config.h40
-rw-r--r--drivers/common/hq2x.c2991
-rw-r--r--drivers/common/hq2x.h4
-rw-r--r--drivers/common/hq3x.c3865
-rw-r--r--drivers/common/hq3x.h4
-rw-r--r--drivers/common/scale2x.c923
-rw-r--r--drivers/common/scale2x.h52
-rw-r--r--drivers/common/scale3x.c382
-rw-r--r--drivers/common/scale3x.h33
-rw-r--r--drivers/common/scalebit.c385
-rw-r--r--drivers/common/scalebit.h43
-rw-r--r--drivers/common/vidblit.c843
-rw-r--r--drivers/common/vidblit.h25
-rw-r--r--drivers/pc/dface.h72
-rw-r--r--drivers/pc/dos-joystick.c200
-rw-r--r--drivers/pc/dos-joystick.h27
-rw-r--r--drivers/pc/dos-keyboard.c131
-rw-r--r--drivers/pc/dos-mouse.c80
-rw-r--r--drivers/pc/dos-sound.c567
-rw-r--r--drivers/pc/dos-sound.h26
-rw-r--r--drivers/pc/dos-video.c246
-rw-r--r--drivers/pc/dos-video.h22
-rw-r--r--drivers/pc/dos.c128
-rw-r--r--drivers/pc/dos.h27
-rw-r--r--drivers/pc/input.c720
-rw-r--r--drivers/pc/input.h38
-rw-r--r--drivers/pc/keyscan.h161
-rw-r--r--drivers/pc/main.c553
-rw-r--r--drivers/pc/main.h55
-rw-r--r--drivers/pc/sdl-icon.h134
-rw-r--r--drivers/pc/sdl-joystick.c99
-rw-r--r--drivers/pc/sdl-netplay.c224
-rw-r--r--drivers/pc/sdl-netplay.h0
-rw-r--r--drivers/pc/sdl-opengl.c241
-rw-r--r--drivers/pc/sdl-opengl.h6
-rw-r--r--drivers/pc/sdl-sound.c373
-rw-r--r--drivers/pc/sdl-throttle.c86
-rw-r--r--drivers/pc/sdl-video.c432
-rw-r--r--drivers/pc/sdl-video.h1
-rw-r--r--drivers/pc/sdl.c429
-rw-r--r--drivers/pc/sdl.h50
-rw-r--r--drivers/pc/throttle.c41
-rw-r--r--drivers/pc/throttle.h2
-rw-r--r--drivers/pc/unix-netplay.c292
-rw-r--r--drivers/pc/unix-netplay.h9
-rw-r--r--drivers/pc/usage.h60
-rw-r--r--drivers/pc/vgatweak.c168
-rw-r--r--drivers/sexyal/convert.c14
-rw-r--r--drivers/sexyal/convert.h2
-rw-r--r--drivers/sexyal/convert.inc20387
-rw-r--r--drivers/sexyal/convertgenbin0 -> 14284 bytes
-rw-r--r--drivers/sexyal/convertgen.c155
-rw-r--r--drivers/sexyal/drivers/dsound.c276
-rw-r--r--drivers/sexyal/drivers/oss.c241
-rw-r--r--drivers/sexyal/drivers/oss.h6
-rw-r--r--drivers/sexyal/drivers/osxcoreaudio.c5
-rw-r--r--drivers/sexyal/md5.c229
-rw-r--r--drivers/sexyal/md5.h15
-rw-r--r--drivers/sexyal/sexyal.c115
-rw-r--r--drivers/sexyal/sexyal.h52
-rw-r--r--drivers/sexyal/smallc.c63
-rw-r--r--drivers/sexyal/smallc.h7
-rw-r--r--drivers/win/Makefile.am.inc5
-rw-r--r--drivers/win/args.c40
-rw-r--r--drivers/win/aviout.c412
-rw-r--r--drivers/win/basicbot.c933
-rw-r--r--drivers/win/basicbot.h3
-rw-r--r--drivers/win/cheat.c487
-rw-r--r--drivers/win/cheat.h2
-rw-r--r--drivers/win/common.h46
-rw-r--r--drivers/win/config.c137
-rw-r--r--drivers/win/debug.c707
-rw-r--r--drivers/win/debug.h6
-rw-r--r--drivers/win/input.c1823
-rw-r--r--drivers/win/input.h53
-rw-r--r--drivers/win/joystick.c426
-rw-r--r--drivers/win/joystick.h11
-rw-r--r--drivers/win/keyboard.c187
-rw-r--r--drivers/win/keyboard.h7
-rw-r--r--drivers/win/keyscan.h128
-rw-r--r--drivers/win/log.c106
-rw-r--r--drivers/win/log.h2
-rw-r--r--drivers/win/main.c684
-rw-r--r--drivers/win/memwatch.c450
-rw-r--r--drivers/win/memwatch.h3
-rw-r--r--drivers/win/netplay.c490
-rw-r--r--drivers/win/netplay.h1
-rw-r--r--drivers/win/ppuview.c352
-rw-r--r--drivers/win/ppuview.h0
-rw-r--r--drivers/win/res.resbin0 -> 43064 bytes
-rw-r--r--drivers/win/sound.c665
-rw-r--r--drivers/win/state.c40
-rw-r--r--drivers/win/throttle.c146
-rw-r--r--drivers/win/video.c1125
-rw-r--r--drivers/win/wave.c47
-rw-r--r--drivers/win/window.c2222
-rw-r--r--endian.c103
-rw-r--r--endian.h7
-rw-r--r--fceu.c780
-rw-r--r--fceu.h115
-rw-r--r--fceustr.c27
-rw-r--r--fceustr.h4
-rw-r--r--fcoeffs.h1589
-rw-r--r--fds.c887
-rw-r--r--fds.h5
-rw-r--r--file.c574
-rw-r--r--file.h18
-rw-r--r--filter.c201
-rw-r--r--filter.h3
-rw-r--r--fir/c44100ntsc.coef1039
-rw-r--r--fir/c44100ntsc.h512
-rw-r--r--fir/c44100ntsc.scm12
-rw-r--r--fir/c44100pal.coef1039
-rw-r--r--fir/c44100pal.h512
-rw-r--r--fir/c44100pal.scm12
-rw-r--r--fir/c48000ntsc.coef1039
-rw-r--r--fir/c48000ntsc.h512
-rw-r--r--fir/c48000ntsc.scm12
-rw-r--r--fir/c48000pal.coef1039
-rw-r--r--fir/c48000pal.h512
-rw-r--r--fir/c48000pal.scm12
-rw-r--r--fir/c96000ntsc.coef1039
-rw-r--r--fir/c96000ntsc.h512
-rw-r--r--fir/c96000ntsc.scm12
-rw-r--r--fir/c96000pal.coef1039
-rw-r--r--fir/c96000pal.h512
-rw-r--r--fir/c96000pal.scm12
-rw-r--r--fir/toh.c24
-rw-r--r--general.c314
-rw-r--r--general.h22
-rw-r--r--git.h29
-rw-r--r--ines-bad.h38
-rw-r--r--ines-correct.h213
-rw-r--r--ines.c1362
-rw-r--r--ines.h389
-rw-r--r--input.c772
-rw-r--r--input.h187
-rw-r--r--input/arkanoid.c119
-rw-r--r--input/bworld.c74
-rw-r--r--input/cursor.c86
-rw-r--r--input/fkb.c102
-rw-r--r--input/fkb.h72
-rw-r--r--input/ftrainer.c74
-rw-r--r--input/hypershot.c50
-rw-r--r--input/mahjong.c79
-rw-r--r--input/oekakids.c95
-rw-r--r--input/powerpad.c85
-rw-r--r--input/quiz.c75
-rw-r--r--input/shadow.c151
-rw-r--r--input/share.h9
-rw-r--r--input/suborkb.c94
-rw-r--r--input/suborkb.h96
-rw-r--r--input/toprider.c62
-rw-r--r--input/zapper.c166
-rw-r--r--mappers/113.c64
-rw-r--r--mappers/15.c73
-rw-r--r--mappers/151.c41
-rw-r--r--mappers/16.c303
-rw-r--r--mappers/17.c73
-rw-r--r--mappers/18.c80
-rw-r--r--mappers/180.c14
-rw-r--r--mappers/183.c0
-rw-r--r--mappers/184.c15
-rw-r--r--mappers/193.c20
-rw-r--r--mappers/200.c36
-rw-r--r--mappers/201.c44
-rw-r--r--mappers/202.c39
-rw-r--r--mappers/203.c36
-rw-r--r--mappers/204.c38
-rw-r--r--mappers/21.c106
-rw-r--r--mappers/212.c23
-rw-r--r--mappers/213.c14
-rw-r--r--mappers/214.c17
-rw-r--r--mappers/215.c96
-rw-r--r--mappers/217.c96
-rw-r--r--mappers/22.c63
-rw-r--r--mappers/225.c87
-rw-r--r--mappers/226.c105
-rw-r--r--mappers/227.c79
-rw-r--r--mappers/228.c53
-rw-r--r--mappers/229.c48
-rw-r--r--mappers/23.c103
-rw-r--r--mappers/230.c62
-rw-r--r--mappers/231.c41
-rw-r--r--mappers/232.c50
-rw-r--r--mappers/234.c107
-rw-r--r--mappers/240.c39
-rw-r--r--mappers/241.c27
-rw-r--r--mappers/242.c41
-rw-r--r--mappers/244.c38
-rw-r--r--mappers/246.c44
-rw-r--r--mappers/24and26.c369
-rw-r--r--mappers/25.c100
-rw-r--r--mappers/255.c67
-rw-r--r--mappers/27.c74
-rw-r--r--mappers/32.c53
-rw-r--r--mappers/33.c80
-rw-r--r--mappers/40.c58
-rw-r--r--mappers/41.c57
-rw-r--r--mappers/42.c64
-rw-r--r--mappers/43.c76
-rw-r--r--mappers/46.c48
-rw-r--r--mappers/50.c75
-rw-r--r--mappers/51.c66
-rw-r--r--mappers/59.c47
-rw-r--r--mappers/6.c80
-rw-r--r--mappers/60.c41
-rw-r--r--mappers/61.c54
-rw-r--r--mappers/62.c41
-rw-r--r--mappers/65.c74
-rw-r--r--mappers/67.c78
-rw-r--r--mappers/68.c105
-rw-r--r--mappers/69.c252
-rw-r--r--mappers/71.c41
-rw-r--r--mappers/72.c37
-rw-r--r--mappers/73.c60
-rw-r--r--mappers/75.c47
-rw-r--r--mappers/76.c54
-rw-r--r--mappers/77.c54
-rw-r--r--mappers/79.c40
-rw-r--r--mappers/8.c34
-rw-r--r--mappers/80.c100
-rw-r--r--mappers/82.c62
-rw-r--r--mappers/83.c131
-rw-r--r--mappers/85.c195
-rw-r--r--mappers/86.c38
-rw-r--r--mappers/89.c34
-rw-r--r--mappers/91.c59
-rw-r--r--mappers/92.c45
-rw-r--r--mappers/97.c42
-rw-r--r--mappers/99.c37
-rw-r--r--mappers/Makefile.am.inc1
-rw-r--r--mappers/emu2413.c1300
-rw-r--r--mappers/emu2413.h134
-rw-r--r--mappers/emutypes.h44
-rw-r--r--mappers/mapinc.h11
-rw-r--r--mappers/mmc2and4.c121
-rw-r--r--mappers/simple.c100
-rw-r--r--mappers/vrc7tone.h17
-rw-r--r--md5.c246
-rw-r--r--md5.h18
-rw-r--r--memory.c100
-rw-r--r--memory.h31
-rw-r--r--movie.c1447
-rw-r--r--movie.h19
-rw-r--r--netplay.c331
-rw-r--r--netplay.h23
-rw-r--r--nsf.c568
-rw-r--r--nsf.h47
-rw-r--r--ops.h485
-rw-r--r--palette.c366
-rw-r--r--palette.h11
-rw-r--r--palettes/conv.c74
-rw-r--r--palettes/palettes.h229
-rw-r--r--palettes/rp2c04001.h64
-rw-r--r--palettes/rp2c04002.h64
-rw-r--r--palettes/rp2c04003.h64
-rw-r--r--palettes/rp2c05004.h64
-rw-r--r--ppu.c1428
-rw-r--r--ppu.h20
-rw-r--r--pputile.h157
-rw-r--r--ppuview.h6
-rw-r--r--sound.c1280
-rw-r--r--sound.h62
-rw-r--r--soundexp.c42
-rw-r--r--state.c679
-rw-r--r--state.h43
-rw-r--r--types.h97
-rw-r--r--unif.c571
-rw-r--r--unif.h102
-rw-r--r--unzip.c1303
-rw-r--r--unzip.h279
-rw-r--r--vc8/fceuxdsp.ncbbin0 -> 76800 bytes
-rw-r--r--vc8/fceuxdsp.sln26
-rw-r--r--vc8/fceuxdsp.suobin0 -> 8192 bytes
-rw-r--r--vc8/fceuxdsp.vcproj1778
-rw-r--r--vc8/fceuxdsp.vcproj.ZERO-XP.Administrator.user121
-rw-r--r--video.c494
-rw-r--r--video.h6
-rw-r--r--vsuni.c417
-rw-r--r--vsuni.h7
-rw-r--r--wave.c131
-rw-r--r--wave.h1
-rw-r--r--x6502.c705
-rw-r--r--x6502.h76
-rw-r--r--x6502struct.h28
354 files changed, 100178 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..674deb69
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,17 @@
+# A simulation of Subversion default ignores, generated by reposurgeon.
+*.o
+*.lo
+*.la
+*.al
+*.libs
+*.so
+*.so.[0-9]*
+*.a
+*.pyc
+*.pyo
+*.rej
+*~
+*.#*
+.*.swp
+.DS_store
+# Simulated Subversion default ignores end here
diff --git a/boards/112.c b/boards/112.c
new file mode 100644
index 00000000..2bb1e4b8
--- /dev/null
+++ b/boards/112.c
@@ -0,0 +1,90 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint8 reg[8];
+static uint8 mirror, cmd;
+static uint8 *WRAM=NULL;
+
+static SFORMAT StateRegs[]=
+{
+ {&cmd, 1, "CMD"},
+ {&mirror, 1, "MIRR"},
+ {reg, 8, "REGS"},
+ {0}
+};
+
+static void Sync(void)
+{
+ setmirror(mirror^1);
+ setprg8(0x8000,reg[0]);
+ setprg8(0xA000,reg[1]);
+ setchr2(0x0000,reg[2]>>1);
+ setchr2(0x0800,reg[3]>>1);
+ setchr1(0x1000,reg[4]);
+ setchr1(0x1400,reg[5]);
+ setchr1(0x1800,reg[6]);
+ setchr1(0x1C00,reg[7]);
+}
+
+static DECLFW(M112Write)
+{
+ switch(A)
+ {
+ case 0xe000: mirror=V&1; Sync(); ;break;
+ case 0x8000: cmd=V&7; break;
+ case 0xa000: reg[cmd]=V; Sync(); break;
+ }
+FCEU_printf("%04x:%04x %d\n",A,V,scanline);
+}
+
+static void M112Close(void)
+{
+ if(WRAM)
+ FCEU_gfree(WRAM);
+ WRAM = NULL;
+}
+
+static void M112Power(void)
+{
+ setprg16(0xC000,~0);
+ setprg8r(0x10,0x6000,0);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x8000,0xFFFF,M112Write);
+ SetReadHandler(0x6000,0x7FFF,CartBR);
+ SetWriteHandler(0x6000,0x7FFF,CartBW);
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+}
+
+void Mapper112_Init(CartInfo *info)
+{
+ info->Power=M112Power;
+ info->Close=M112Close;
+ GameStateRestore=StateRestore;
+ WRAM=(uint8*)FCEU_gmalloc(8192);
+ SetupCartPRGMapping(0x10,WRAM,8192,1);
+ AddExState(WRAM, 8192, 0, "WRAM");
+ AddExState(&StateRegs, ~0, 0, 0);
+}
diff --git a/boards/117.c b/boards/117.c
new file mode 100644
index 00000000..67460151
--- /dev/null
+++ b/boards/117.c
@@ -0,0 +1,101 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint8 prgreg[4], chrreg[8];
+static uint8 IRQa, IRQCount, IRQLatch;
+
+static SFORMAT StateRegs[]=
+{
+ {&IRQa, 1, "IRQA"},
+ {&IRQCount, 1, "IRQC"},
+ {&IRQLatch, 1, "IRQL"},
+ {prgreg, 4, "PREGS"},
+ {chrreg, 8, "CREGS"},
+ {0}
+};
+
+static void Sync(void)
+{
+ setprg8(0x8000,prgreg[0]);
+ setprg8(0xa000,prgreg[1]);
+ setprg8(0xc000,prgreg[2]);
+ setprg8(0xe000,prgreg[3]);
+ int i;
+ for(i=0; i<8; i++)
+ setchr1(i<<10,chrreg[i]);
+}
+
+static DECLFW(M117Write)
+{
+ if(A<0x8004)
+ {
+ prgreg[A&3]=V;
+ Sync();
+ }
+ else if((A>=0xA000)&&(A<=0xA007))
+ {
+ chrreg[A&7]=V;
+ Sync();
+ }
+ else switch(A)
+ {
+ case 0xc001: IRQLatch=V; break;
+ case 0xc003: IRQCount=IRQLatch; IRQa|=2; break;
+ case 0xe000: IRQa&=~1; IRQa|=V&1; X6502_IRQEnd(FCEU_IQEXT); break;
+ case 0xc002: X6502_IRQEnd(FCEU_IQEXT); break;
+ }
+}
+
+static void M117Power(void)
+{
+ prgreg[0]=~3; prgreg[1]=~2; prgreg[2]=~1; prgreg[3]=~0;
+ Sync();
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x8000,0xFFFF,M117Write);
+}
+
+static void M117IRQHook(void)
+{
+ if(IRQa==3&&IRQCount)
+ {
+ IRQCount--;
+ if(!IRQCount)
+ {
+ IRQa&=1;
+ X6502_IRQBegin(FCEU_IQEXT);
+ }
+ }
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+}
+
+void Mapper117_Init(CartInfo *info)
+{
+ info->Power=M117Power;
+ GameHBIRQHook=M117IRQHook;
+ GameStateRestore=StateRestore;
+ AddExState(&StateRegs, ~0, 0, 0);
+}
+
diff --git a/boards/164.c b/boards/164.c
new file mode 100644
index 00000000..0bb85b3e
--- /dev/null
+++ b/boards/164.c
@@ -0,0 +1,116 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint8 cmd;
+static uint8 DRegs[8];
+static SFORMAT StateRegs[]=
+{
+ {&cmd, 1, "CMD"},
+ {DRegs, 8, "DREG"},
+ {0}
+};
+
+static void Sync(void)
+{
+ setprg32(0x8000,(DRegs[0]<<4)|(DRegs[1]&0xF));
+ setchr8(0);
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+}
+
+static DECLFW(Write)
+{
+ switch (A&0x7300)
+ {
+ case 0x5100: DRegs[0]=V; Sync(); break;
+ case 0x5000: DRegs[1]=V; Sync(); break;
+ }
+}
+
+static DECLFW(Write2)
+{
+ switch (A&0x7300)
+ {
+ case 0x5200: DRegs[0]=V; Sync(); break;
+ case 0x5000: DRegs[1]=V; Sync(); break;
+ }
+}
+
+static uint8 WRAM[8192];
+static DECLFR(AWRAM)
+{
+ return(WRAM[A-0x6000]);
+}
+
+static DECLFW(BWRAM)
+{
+ WRAM[A-0x6000]=V;
+}
+
+static void Power(void)
+{
+ memset(DRegs,0,8);
+ DRegs[1]=0xFF;
+ cmd=0;
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x4020,0xFFFF,Write);
+ SetReadHandler(0x6000,0x7FFF,AWRAM);
+ SetWriteHandler(0x6000,0x7FFF,BWRAM);
+ Sync();
+}
+
+static void M163HB(void)
+{
+ if(scanline==127&&DRegs[1]&0x80)
+ setchr4(0x0000,1);
+}
+
+
+static void Power2(void)
+{
+ memset(DRegs,0,8);
+ DRegs[1]=0xFF;
+ cmd=0;
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x4020,0xFFFF,Write2);
+ SetReadHandler(0x6000,0x7FFF,AWRAM);
+ SetWriteHandler(0x6000,0x7FFF,BWRAM);
+ Sync();
+}
+
+void Mapper164_Init(CartInfo *info)
+{
+ info->Power=Power;
+ GameStateRestore=StateRestore;
+ AddExState(&StateRegs, ~0, 0, 0);
+}
+
+void Mapper163_Init(CartInfo *info)
+{
+ info->Power=Power2;
+ GameHBIRQHook=M163HB;
+ GameStateRestore=StateRestore;
+ AddExState(&StateRegs, ~0, 0, 0);
+}
diff --git a/boards/183.c b/boards/183.c
new file mode 100644
index 00000000..94cf0726
--- /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/185.c b/boards/185.c
new file mode 100644
index 00000000..ef560c57
--- /dev/null
+++ b/boards/185.c
@@ -0,0 +1,116 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Family Study Box by Fukutake Shoten
+ */
+
+#include "mapinc.h"
+
+static uint8 *DummyCHR=NULL;
+static uint8 datareg;
+static void(*Sync)(void);
+
+
+static SFORMAT StateRegs[]=
+{
+ {&datareg, 1, "DREG"},
+ {0}
+};
+
+// on off
+//1 0x0F, 0xF0 - Bird Week
+//2 0x33, 0x00 - B-Wings
+//3 0x11, 0x00 - Mighty Bomb Jack
+//4 0x22, 0x20 - Sansuu 1 Nen, Sansuu 2 Nen
+//5 0xFF, 0x00 - Sansuu 3 Nen
+//6 0x21, 0x13 - Spy vs Spy
+//7 0x20, 0x21 - Seicross
+
+static void Sync185(void)
+{
+ // little dirty eh? ;_)
+ if((datareg&3)&&(datareg!=0x13)) // 1, 2, 3, 4, 5, 6
+ setchr8(0);
+ else
+ setchr8r(0x10,0);
+}
+
+static void Sync181(void)
+{
+ if(!(datareg&1)) // 7
+ setchr8(0);
+ else
+ setchr8r(0x10,0);
+}
+
+static DECLFW(MWrite)
+{
+ datareg=V;
+ Sync();
+}
+
+static void MPower(void)
+{
+ datareg=0;
+ Sync();
+ setprg16(0x8000,0);
+ setprg16(0xC000,~0);
+ SetWriteHandler(0x8000,0xFFFF,MWrite);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+}
+
+static void MClose(void)
+{
+ if(DummyCHR)
+ FCEU_gfree(DummyCHR);
+ DummyCHR=NULL;
+}
+
+static void MRestore(int version)
+{
+ Sync();
+}
+
+void Mapper185_Init(CartInfo *info)
+{
+ Sync=Sync185;
+ info->Power=MPower;
+ info->Close=MClose;
+ GameStateRestore=MRestore;
+ DummyCHR=(uint8*)FCEU_gmalloc(8192);
+ int x;
+ for(x=0;x<8192;x++)
+ DummyCHR[x]=0xff;
+ SetupCartCHRMapping(0x10,DummyCHR,8192,0);
+ AddExState(StateRegs, ~0, 0, 0);
+}
+
+void Mapper181_Init(CartInfo *info)
+{
+ Sync=Sync181;
+ info->Power=MPower;
+ info->Close=MClose;
+ GameStateRestore=MRestore;
+ DummyCHR=(uint8*)FCEU_gmalloc(8192);
+ int x;
+ for(x=0;x<8192;x++)
+ DummyCHR[x]=0xff;
+ SetupCartCHRMapping(0x10,DummyCHR,8192,0);
+ AddExState(StateRegs, ~0, 0, 0);
+}
diff --git a/boards/186.c b/boards/186.c
new file mode 100644
index 00000000..3698c6ca
--- /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/187.c b/boards/187.c
new file mode 100644
index 00000000..5f28bb5f
--- /dev/null
+++ b/boards/187.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
+ */
+
+#include "mapinc.h"
+#include "mmc3.h"
+
+static void M187CW(uint32 A, uint8 V)
+{
+ if((A&0x1000)==((MMC3_cmd&0x80)<<5))
+ setchr1(A,V|0x100);
+ else
+ setchr1(A,V);
+}
+
+static void M187PW(uint32 A, uint8 V)
+{
+ if(EXPREGS[0]&0x80)
+ {
+ uint8 bank=EXPREGS[0]&0x1F;
+ if(EXPREGS[0]&0x20)
+ setprg32(0x8000,bank>>2);
+ else
+ {
+ setprg16(0x8000,bank);
+ setprg16(0xC000,bank);
+ }
+ }
+ else
+ setprg8(A,V&0x3F);
+}
+
+static DECLFW(M187Write8000)
+{
+ EXPREGS[2]=1;
+ MMC3_CMDWrite(A,V);
+}
+
+static DECLFW(M187Write8001)
+{
+ if(EXPREGS[2])
+ MMC3_CMDWrite(A,V);
+}
+
+static DECLFW(M187Write8003)
+{
+ EXPREGS[2]=0;
+ if(V==0x28)setprg8(0xC000,0x17);
+ else if(V==0x2A)setprg8(0xA000,0x0F);
+}
+
+
+static DECLFW(M187WriteLo)
+{
+ EXPREGS[1]=V;
+ if(A==0x5000)
+ {
+ EXPREGS[0]=V;
+ FixMMC3PRG(MMC3_cmd);
+ }
+}
+
+static uint8 prot_data[4] = { 0x83, 0x83, 0x42, 0x00 };
+static DECLFR(M187Read)
+{
+ return prot_data[EXPREGS[1]&3];
+}
+
+static void M187Power(void)
+{
+ EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=0;
+ GenMMC3Power();
+ Write_IRQFM(0x4017,0x40);
+ SetReadHandler(0x5000,0x5FFF,M187Read);
+ SetWriteHandler(0x5000,0x5FFF,M187WriteLo);
+ SetWriteHandler(0x8000,0x8000,M187Write8000);
+ SetWriteHandler(0x8001,0x8001,M187Write8001);
+ SetWriteHandler(0x8003,0x8003,M187Write8003);
+}
+
+void Mapper187_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 256, 256, 0, 0);
+ pwrap=M187PW;
+ cwrap=M187CW;
+ info->Power=M187Power;
+ AddExState(EXPREGS, 3, 0, "EXPR");
+}
diff --git a/boards/189.c b/boards/189.c
new file mode 100644
index 00000000..445d099c
--- /dev/null
+++ b/boards/189.c
@@ -0,0 +1,48 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+#include "mmc3.h"
+
+static void M189PW(uint32 A, uint8 V)
+{
+ setprg32(0x8000,EXPREGS[0]&3);
+}
+
+static DECLFW(M189Write)
+{
+ EXPREGS[0]=V|(V>>4); //actually, there is a two versions of 189 mapper with hi or lo bits bankswitching.
+ FixMMC3PRG(MMC3_cmd);
+}
+
+static void M189Power(void)
+{
+ EXPREGS[0]=EXPREGS[1]=0;
+ GenMMC3Power();
+ SetWriteHandler(0x4120,0x7FFF,M189Write);
+}
+
+void Mapper189_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 256, 256, 0, 0);
+ pwrap=M189PW;
+ info->Power=M189Power;
+ AddExState(EXPREGS, 2, 0, "EXPR");
+}
diff --git a/boards/208.c b/boards/208.c
new file mode 100644
index 00000000..14156a6d
--- /dev/null
+++ b/boards/208.c
@@ -0,0 +1,83 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+#include "mmc3.h"
+
+static uint8 lut[256]={
+ 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x59, 0x49, 0x19, 0x09, 0x59, 0x49, 0x19, 0x09,
+ 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x51, 0x41, 0x11, 0x01, 0x51, 0x41, 0x11, 0x01,
+ 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x59, 0x49, 0x19, 0x09, 0x59, 0x49, 0x19, 0x09,
+ 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x51, 0x41, 0x11, 0x01, 0x51, 0x41, 0x11, 0x01,
+ 0x00, 0x10, 0x40, 0x50, 0x00, 0x10, 0x40, 0x50,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x18, 0x48, 0x58, 0x08, 0x18, 0x48, 0x58,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x10, 0x40, 0x50, 0x00, 0x10, 0x40, 0x50,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x18, 0x48, 0x58, 0x08, 0x18, 0x48, 0x58,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x58, 0x48, 0x18, 0x08, 0x58, 0x48, 0x18, 0x08,
+ 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x50, 0x40, 0x10, 0x00, 0x50, 0x40, 0x10, 0x00,
+ 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x58, 0x48, 0x18, 0x08, 0x58, 0x48, 0x18, 0x08,
+ 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,0x50, 0x40, 0x10, 0x00, 0x50, 0x40, 0x10, 0x00,
+ 0x01, 0x11, 0x41, 0x51, 0x01, 0x11, 0x41, 0x51,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x09, 0x19, 0x49, 0x59, 0x09, 0x19, 0x49, 0x59,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x11, 0x41, 0x51, 0x01, 0x11, 0x41, 0x51,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x09, 0x19, 0x49, 0x59, 0x09, 0x19, 0x49, 0x59,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static void M208PW(uint32 A, uint8 V)
+{
+ setprg32(0x8000,EXPREGS[5]);
+}
+
+static DECLFW(M208Write)
+{
+ EXPREGS[5]=(V&0x1)|((V>>3)&0x2);
+ FixMMC3PRG(MMC3_cmd);
+}
+
+static DECLFW(M208ProtWrite)
+{
+ if(A<=0x57FF)
+ EXPREGS[4]=V;
+ else
+ EXPREGS[(A&0x03)]=V^lut[EXPREGS[4]];
+}
+
+static DECLFR(M208ProtRead)
+{
+ return(EXPREGS[(A&0x3)]);
+}
+
+static void M208Power(void)
+{
+ EXPREGS[5]=3;
+ GenMMC3Power();
+ SetWriteHandler(0x4800,0x4FFF,M208Write);
+ SetWriteHandler(0x5000,0x5fff,M208ProtWrite);
+ SetReadHandler(0x5800,0x5FFF,M208ProtRead);
+ SetReadHandler(0x8000,0xffff,CartBR);
+}
+
+void Mapper208_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 128, 256, 0, 0);
+ pwrap=M208PW;
+ info->Power=M208Power;
+ AddExState(EXPREGS, 6, 0, "EXPR");
+}
diff --git a/boards/222.c b/boards/222.c
new file mode 100644
index 00000000..1784314a
--- /dev/null
+++ b/boards/222.c
@@ -0,0 +1,99 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include "mapinc.h"
+
+static uint16 IRQCount;
+static uint8 IRQa;
+static uint8 prg_reg[2];
+static uint8 chr_reg[8];
+
+static SFORMAT StateRegs[]=
+{
+ {&IRQCount, 2, "IRQC"},
+ {&IRQa, 2, "IRQA"},
+ {prg_reg, 2, "PRG"},
+ {chr_reg, 8, "CHR"},
+ {0}
+};
+
+static void M222IRQ(void)
+{
+ if(IRQa)
+ {
+ IRQCount++;
+ if(IRQCount>=240)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ IRQa=0;
+ }
+ }
+}
+
+static void Sync(void)
+{
+ setprg8(0x8000,prg_reg[0]);
+ setprg8(0xA000,prg_reg[1]);
+ int i;
+ for(i=0; i<8; i++)
+ setchr1(i<<10,chr_reg[i]);
+}
+
+static DECLFW(M222Write)
+{
+ switch(A&0xF003)
+ {
+ case 0x8000: prg_reg[0]=V; break;
+ case 0xA000: prg_reg[1]=V; break;
+ case 0xB000: chr_reg[0]=V; break;
+ case 0xB002: chr_reg[1]=V; break;
+ case 0xC000: chr_reg[2]=V; break;
+ case 0xC002: chr_reg[3]=V; break;
+ case 0xD000: chr_reg[4]=V; break;
+ case 0xD002: chr_reg[5]=V; break;
+ case 0xE000: chr_reg[6]=V; break;
+ case 0xE002: chr_reg[7]=V; break;
+ case 0xF000: IRQCount=IRQa=V;
+ X6502_IRQEnd(FCEU_IQEXT);
+ break;
+ }
+ Sync();
+}
+
+static void M222Power(void)
+{
+ setprg16(0xC000,~0);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x8000,0xFFFF,M222Write);
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+}
+
+void Mapper222_Init(CartInfo *info)
+{
+ info->Power=M222Power;
+ GameHBIRQHook=M222IRQ;
+ GameStateRestore=StateRestore;
+ AddExState(&StateRegs, ~0, 0, 0);
+}
diff --git a/boards/235.c b/boards/235.c
new file mode 100644
index 00000000..e866e39e
--- /dev/null
+++ b/boards/235.c
@@ -0,0 +1,70 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint16 cmdreg;
+static SFORMAT StateRegs[]=
+{
+ {&cmdreg, 2, "CMDREG"},
+ {0}
+};
+
+static void Sync(void)
+{
+ if(cmdreg&0x400)
+ setmirror(MI_0);
+ else
+ setmirror(((cmdreg>>13)&1)^1);
+ if(cmdreg&0x800)
+ {
+ setprg16(0x8000,((cmdreg&0x300)>>3)|((cmdreg&0x1F)<<1)|((cmdreg>>12)&1));
+ setprg16(0xC000,((cmdreg&0x300)>>3)|((cmdreg&0x1F)<<1)|((cmdreg>>12)&1));
+ }
+ else
+ setprg32(0x8000,((cmdreg&0x300)>>4)|(cmdreg&0x1F));
+}
+
+static DECLFW(M235Write)
+{
+ cmdreg=A;
+ Sync();
+}
+
+static void M235Power(void)
+{
+ setchr8(0);
+ SetWriteHandler(0x8000,0xFFFF,M235Write);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ cmdreg=0;
+ Sync();
+}
+
+static void M235Restore(int version)
+{
+ Sync();
+}
+
+void Mapper235_Init(CartInfo *info)
+{
+ info->Power=M235Power;
+ GameStateRestore=M235Restore;
+ AddExState(&StateRegs, ~0, 0, 0);
+}
diff --git a/boards/57.c b/boards/57.c
new file mode 100644
index 00000000..5a4f98a9
--- /dev/null
+++ b/boards/57.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"
+
+static uint8 prg_reg;
+static uint8 chr_reg;
+static uint8 hrd_flag;
+
+static SFORMAT StateRegs[]=
+{
+ {&prg_reg, 1, "PRG"},
+ {&chr_reg, 1, "CHR"},
+ {0}
+};
+
+static void Sync(void)
+{
+ if(prg_reg&0x80)
+ setprg32(0x8000,prg_reg>>6);
+ else
+ {
+ setprg16(0x8000,(prg_reg>>5)&3);
+ setprg16(0xC000,(prg_reg>>5)&3);
+ }
+ setmirror((prg_reg&8)>>3);
+ setchr8((chr_reg&3)|(prg_reg&7)|((prg_reg&0x10)>>1));
+}
+
+static DECLFR(M57Read)
+{
+ return hrd_flag;
+}
+
+static DECLFW(M57Write)
+{
+ if((A&0x8800)==0x8800)
+ prg_reg=V;
+ else
+ chr_reg=V;
+ Sync();
+}
+
+static void M57Power(void)
+{
+ prg_reg=0;
+ chr_reg=0;
+ hrd_flag=0;
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x8000,0xFFFF,M57Write);
+ SetReadHandler(0x6000,0x6000,M57Read);
+ Sync();
+}
+
+static void M57Reset()
+{
+ if(hrd_flag==3)
+ hrd_flag=0;
+ else
+ hrd_flag++;
+ FCEU_printf("Select Register = %02x\n",hrd_flag);
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+}
+
+void Mapper57_Init(CartInfo *info)
+{
+ info->Power=M57Power;
+ info->Reset=M57Reset;
+ GameStateRestore=StateRestore;
+ AddExState(&StateRegs, ~0, 0, 0);
+}
diff --git a/boards/8157.c b/boards/8157.c
new file mode 100644
index 00000000..91e45fef
--- /dev/null
+++ b/boards/8157.c
@@ -0,0 +1,80 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint16 cmdreg;
+static uint8 invalid_data;
+static SFORMAT StateRegs[]=
+{
+ {&cmdreg, 2, "CMDREG"},
+ {0}
+};
+
+static void Sync(void)
+{
+ setprg16r((cmdreg&0x060)>>5,0x8000,(cmdreg&0x01C)>>2);
+ setprg16r((cmdreg&0x060)>>5,0xC000,(cmdreg&0x200)?(~0):0);
+ setmirror(((cmdreg&2)>>1)^1);
+}
+
+static DECLFR(UNL8157Read)
+{
+ if(invalid_data&&cmdreg&0x100)
+ return 0xFF;
+ else
+ return CartBR(A);
+}
+
+static DECLFW(UNL8157Write)
+{
+ cmdreg=A;
+ Sync();
+}
+
+static void UNL8157Power(void)
+{
+ setchr8(0);
+ SetWriteHandler(0x8000,0xFFFF,UNL8157Write);
+ SetReadHandler(0x8000,0xFFFF,UNL8157Read);
+ cmdreg=0x200;
+ invalid_data=1;
+ Sync();
+}
+
+static void UNL8157Reset(void)
+{
+ cmdreg=0;
+ invalid_data^=1;
+ Sync();
+}
+
+static void UNL8157Restore(int version)
+{
+ Sync();
+}
+
+void UNL8157_Init(CartInfo *info)
+{
+ info->Power=UNL8157Power;
+ info->Reset=UNL8157Reset;
+ GameStateRestore=UNL8157Restore;
+ AddExState(&StateRegs, ~0, 0, 0);
+}
diff --git a/boards/8237.c b/boards/8237.c
new file mode 100644
index 00000000..5b4e2df1
--- /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/88.c b/boards/88.c
new file mode 100644
index 00000000..03fbf5ba
--- /dev/null
+++ b/boards/88.c
@@ -0,0 +1,87 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint8 reg[8];
+static uint8 mirror, cmd, is154;
+
+static SFORMAT StateRegs[]=
+{
+ {&cmd, 1, "CMD"},
+ {&mirror, 1, "MIRR"},
+ {reg, 8, "REGS"},
+ {0}
+};
+
+static void Sync(void)
+{
+ setchr2(0x0000,reg[0]>>1);
+ setchr2(0x0800,reg[1]>>1);
+ setchr1(0x1000,reg[2]|0x40);
+ setchr1(0x1400,reg[3]|0x40);
+ setchr1(0x1800,reg[4]|0x40);
+ setchr1(0x1C00,reg[5]|0x40);
+ setprg8(0x8000,reg[6]);
+ setprg8(0xA000,reg[7]);
+}
+
+static void MSync(void)
+{
+ if(is154)setmirror(MI_0+(mirror&1));
+}
+
+static DECLFW(M88Write)
+{
+ switch(A&0x8001)
+ {
+ case 0x8000: cmd=V&7; mirror=V>>6; MSync(); break;
+ case 0x8001: reg[cmd]=V; Sync(); break;
+ }
+}
+
+static void M88Power(void)
+{
+ setprg16(0xC000,~0);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x8000,0xFFFF,M88Write);
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+ MSync();
+}
+
+void Mapper88_Init(CartInfo *info)
+{
+ is154=0;
+ info->Power=M88Power;
+ GameStateRestore=StateRestore;
+ AddExState(&StateRegs, ~0, 0, 0);
+}
+
+void Mapper154_Init(CartInfo *info)
+{
+ is154=1;
+ info->Power=M88Power;
+ GameStateRestore=StateRestore;
+ AddExState(&StateRegs, ~0, 0, 0);
+}
diff --git a/boards/90.c b/boards/90.c
new file mode 100644
index 00000000..994910d7
--- /dev/null
+++ b/boards/90.c
@@ -0,0 +1,466 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+//#define DEBUG90
+
+static int is209;
+static int is211;
+
+static uint8 IRQMode; // from $c001
+static uint8 IRQPre; // from $c004
+static uint8 IRQPreSize; // from $c007
+static uint8 IRQCount; // from $c005
+static uint8 IRQXOR; // Loaded from $C006
+static uint8 IRQa; // $c002, $c003, and $c000
+
+static uint8 mul[2];
+static uint8 regie;
+
+static uint8 tkcom[4];
+static uint8 prgb[4];
+static uint8 chrlow[8];
+static uint8 chrhigh[8];
+
+static uint16 names[4];
+static uint8 tekker;
+
+static SFORMAT Tek_StateRegs[]={
+ {&IRQMode, 1, "IRQMODE"},
+ {&IRQPre, 1, "IRQPRE"},
+ {&IRQPreSize, 1, "IRQPRESIZE"},
+ {&IRQCount, 1, "IRQC"},
+ {&IRQXOR, 1, "IRQXOR"},
+ {&IRQa, 1, "IRQa"},
+ {mul, 2, "MUL"},
+ {&regie, 1, "REGI"},
+ {tkcom, 4, "TKCO"},
+ {prgb, 4, "PRGB"},
+ {chrlow, 4, "CHRL"},
+ {chrhigh, 8, "CHRH"},
+ {&names[0], 2|FCEUSTATE_RLSB, "NMS0"},
+ {&names[1], 2|FCEUSTATE_RLSB, "NMS1"},
+ {&names[2], 2|FCEUSTATE_RLSB, "NMS2"},
+ {&names[3], 2|FCEUSTATE_RLSB, "NMS3"},
+ {&tekker, 1, "TEKR"},
+ {0}
+};
+
+static void mira(void)
+{
+ if((tkcom[0]&0x20&&is209)||is211)
+ {
+ int x;
+ if(tkcom[0]&0x40) // Name tables are ROM-only
+ {
+ for(x=0;x<4;x++)
+ setntamem(CHRptr[0]+(((names[x])&CHRmask1[0])<<10),0,x);
+ }
+ else // Name tables can be RAM or ROM.
+ {
+ for(x=0;x<4;x++)
+ {
+ if((tkcom[1]&0x80)==(names[x]&0x80)) // RAM selected.
+ setntamem(NTARAM+((names[x]&0x1)<<10),1,x);
+ else
+ setntamem(CHRptr[0]+(((names[x])&CHRmask1[0])<<10),0,x);
+ }
+ }
+ }
+ else
+ {
+ switch(tkcom[1]&3)
+ {
+ case 0: setmirror(MI_V); break;
+ case 1: setmirror(MI_H); break;
+ case 2: setmirror(MI_0); break;
+ case 3: setmirror(MI_1); break;
+ }
+ }
+}
+
+static void tekprom(void)
+{
+ uint32 bankmode=((tkcom[3]&6)<<5);
+ switch(tkcom[0]&7)
+ {
+ case 00: if(tkcom[0]&0x80)
+ setprg8(0x6000,(((prgb[3]<<2)+3)&0x3F)|bankmode);
+ setprg32(0x8000,0x0F|((tkcom[3]&6)<<3));
+ break;
+ case 01: if(tkcom[0]&0x80)
+ setprg8(0x6000,(((prgb[3]<<1)+1)&0x3F)|bankmode);
+ setprg16(0x8000,(prgb[1]&0x1F)|((tkcom[3]&6)<<4));
+ setprg16(0xC000,0x1F|((tkcom[3]&6)<<4));
+ break;
+ case 03: // bit reversion
+ case 02: if(tkcom[0]&0x80)
+ setprg8(0x6000,(prgb[3]&0x3F)|bankmode);
+ setprg8(0x8000,(prgb[0]&0x3F)|bankmode);
+ setprg8(0xa000,(prgb[1]&0x3F)|bankmode);
+ setprg8(0xc000,(prgb[2]&0x3F)|bankmode);
+ setprg8(0xe000,0x3F|bankmode);
+ break;
+ case 04: if(tkcom[0]&0x80)
+ setprg8(0x6000,(((prgb[3]<<2)+3)&0x3F)|bankmode);
+ setprg32(0x8000,(prgb[3]&0x0F)|((tkcom[3]&6)<<3));
+ break;
+ case 05: if(tkcom[0]&0x80)
+ setprg8(0x6000,(((prgb[3]<<1)+1)&0x3F)|bankmode);
+ setprg16(0x8000,(prgb[1]&0x1F)|((tkcom[3]&6)<<4));
+ setprg16(0xC000,(prgb[3]&0x1F)|((tkcom[3]&6)<<4));
+ break;
+ case 07: // bit reversion
+ case 06: if(tkcom[0]&0x80)
+ setprg8(0x6000,(prgb[3]&0x3F)|bankmode);
+ setprg8(0x8000,(prgb[0]&0x3F)|bankmode);
+ setprg8(0xa000,(prgb[1]&0x3F)|bankmode);
+ setprg8(0xc000,(prgb[2]&0x3F)|bankmode);
+ setprg8(0xe000,(prgb[3]&0x3F)|bankmode);
+ break;
+ }
+}
+
+static void tekvrom(void)
+{
+ int x, bank=0, mask=0xFFFF;
+ if(!(tkcom[3]&0x20))
+ {
+ bank=(tkcom[3]&1)|((tkcom[3]&0x18)>>2);
+ switch (tkcom[0]&0x18)
+ {
+ case 0x00: bank<<=5; mask=0x1F; break;
+ case 0x08: bank<<=6; mask=0x3F; break;
+ case 0x10: bank<<=7; mask=0x7F; break;
+ case 0x18: bank<<=8; mask=0xFF; break;
+ }
+ }
+ switch(tkcom[0]&0x18)
+ {
+ case 0x00: // 8KB
+ setchr8(((chrlow[0]|(chrhigh[0]<<8))&mask)|bank);
+ break;
+ case 0x08: // 4KB
+ for(x=0;x<8;x+=4)
+ setchr4(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank);
+ break;
+ case 0x10: // 2KB
+ for(x=0;x<8;x+=2)
+ setchr2(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank);
+ break;
+ case 0x18: // 1KB
+ for(x=0;x<8;x++)
+ setchr1(x<<10,((chrlow[x]|(chrhigh[x]<<8))&mask)|bank);
+ break;
+ }
+}
+
+static DECLFW(M90TekWrite)
+{
+ switch(A)
+ {
+ case 0x5800: mul[0]=V; break;
+ case 0x5801: mul[1]=V; break;
+ case 0x5803: regie=V; break;
+ }
+}
+
+static DECLFR(M90TekRead)
+{
+ switch(A)
+ {
+ case 0x5800: return (mul[0]*mul[1]);
+ case 0x5801: return((mul[0]*mul[1])>>8);
+ case 0x5803: return (regie);
+ }
+ return(tekker);
+}
+
+static DECLFW(M90PRGWrite)
+{
+ prgb[A&3]=V;
+ tekprom();
+}
+
+static DECLFW(M90CHRlowWrite)
+{
+ chrlow[A&7]=V;
+ tekvrom();
+}
+
+static DECLFW(M90CHRhiWrite)
+{
+ chrhigh[A&7]=V;
+ tekvrom();
+}
+
+static DECLFW(M90NTWrite)
+{
+ if(A&4)
+ {
+ names[A&3]&=0x00FF;
+ names[A&3]|=V<<8;
+ }
+ else
+ {
+ names[A&3]&=0xFF00;
+ names[A&3]|=V;
+ }
+ mira();
+}
+
+static DECLFW(M90IRQWrite)
+{
+ switch(A&7)
+ {
+ case 00: //FCEU_printf("%s IRQ (C000)\n",V&1?"Enable":"Disable");
+ IRQa=V&1;if(!(V&1)) X6502_IRQEnd(FCEU_IQEXT);break;
+ case 02: //FCEU_printf("Disable IRQ (C002) scanline=%d\n", scanline);
+ IRQa=0;X6502_IRQEnd(FCEU_IQEXT);break;
+ case 03: //FCEU_printf("Enable IRQ (C003) scanline=%d\n", scanline);
+ IRQa=1;break;
+ case 01: IRQMode=V;
+/* FCEU_printf("IRQ Count method: ");
+ switch (IRQMode&3)
+ {
+ case 00: FCEU_printf("M2 cycles\n");break;
+ case 01: FCEU_printf("PPU A12 toggles\n");break;
+ case 02: FCEU_printf("PPU reads\n");break;
+ case 03: FCEU_printf("Writes to CPU space\n");break;
+ }
+ FCEU_printf("Counter prescaler size: %s\n",(IRQMode&4)?"3 bits":"8 bits");
+ FCEU_printf("Counter prescaler size adjust: %s\n",(IRQMode&8)?"Used C007":"Normal Operation");
+ if((IRQMode>>6)==2) FCEU_printf("Counter Down\n");
+ else if((IRQMode>>6)==1) FCEU_printf("Counter Up\n");
+ else FCEU_printf("Counter Stopped\n");
+*/ break;
+ case 04: //FCEU_printf("Pre Counter Loaded and Xored wiht C006: %d\n",V^IRQXOR);
+ IRQPre=V^IRQXOR;break;
+ case 05: //FCEU_printf("Main Counter Loaded and Xored wiht C006: %d\n",V^IRQXOR);
+ IRQCount=V^IRQXOR;break;
+ case 06: //FCEU_printf("Xor Value: %d\n",V);
+ IRQXOR=V;break;
+ case 07: //if(!(IRQMode&8)) FCEU_printf("C001 is clear, no effect applied\n");
+ // else if(V==0xFF) FCEU_printf("Prescaler is changed for 12bits\n");
+ // else FCEU_printf("Counter Stopped\n");
+ IRQPreSize=V;break;
+ }
+}
+
+static DECLFW(M90ModeWrite)
+{
+ tkcom[A&3]=V;
+ tekprom();
+ tekvrom();
+ mira();
+
+#ifdef DEBUG90
+ switch (A&3)
+ {
+ case 00: FCEU_printf("Main Control Register:\n");
+ FCEU_printf(" PGR Banking mode: %d\n",V&7);
+ FCEU_printf(" CHR Banking mode: %d\n",(V>>3)&3);
+ FCEU_printf(" 6000-7FFF addresses mapping: %s\n",(V&0x80)?"Yes":"No");
+ FCEU_printf(" Nametable control: %s\n",(V&0x20)?"Enabled":"Disabled");
+ if(V&0x20)
+ FCEU_printf(" Nametable can be: %s\n",(V&0x40)?"ROM Only":"RAM or ROM");
+ break;
+ case 01: FCEU_printf("Mirroring mode: ");
+ switch (V&3)
+ {
+ case 0: FCEU_printf("Vertical\n");break;
+ case 1: FCEU_printf("Horizontal\n");break;
+ case 2: FCEU_printf("Nametable 0 only\n");break;
+ case 3: FCEU_printf("Nametable 1 only\n");break;
+ }
+ FCEU_printf("Mirroring flag: %s\n",(V&0x80)?"On":"Off");
+ break;
+ case 02: if((((tkcom[0])>>5)&3)==1)
+ FCEU_printf("Nametable ROM/RAM select mode: %d\n",V>>7);
+ break;
+ case 03:
+ FCEU_printf("CHR Banking mode: %s\n",(V&0x20)?"Entire CHR ROM":"256Kb Switching mode");
+ if(!(V&0x20)) FCEU_printf("256K CHR bank number: %02x\n",(V&1)|((V&0x18)>>2));
+ FCEU_printf("512K PRG bank number: %d\n",(V&6)>>1);
+ FCEU_printf("CHR Bank mirroring: %s\n",(V&0x80)?"Swapped":"Normal operate");
+ }
+#endif
+}
+
+static void CCL(void)
+{
+ if((IRQMode>>6) == 1) // Count Up
+ {
+ IRQCount++;
+ if((IRQCount == 0) && IRQa)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ }
+ }
+ else if((IRQMode>>6) == 2) // Count down
+ {
+ IRQCount--;
+ if((IRQCount == 0xFF) && IRQa)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ }
+ }
+}
+
+static void ClockCounter(void)
+{
+ uint8 premask;
+
+ if(IRQMode & 0x4)
+ premask = 0x7;
+ else
+ premask = 0xFF;
+ if((IRQMode>>6) == 1) // Count up
+ {
+ IRQPre++;
+ if((IRQPre & premask) == 0) CCL();
+ }
+ else if((IRQMode>>6) == 2) // Count down
+ {
+ IRQPre--;
+ if((IRQPre & premask) == premask) CCL();
+ }
+}
+
+void FP_FASTAPASS(1) CPUWrap(int a)
+{
+ int x;
+ if((IRQMode&3)==0) for(x=0;x<a;x++) ClockCounter();
+}
+
+static void SLWrap(void)
+{
+ int x;
+ if((IRQMode&3)==1) for(x=0;x<8;x++) ClockCounter();
+}
+
+static uint32 lastread;
+static void FP_FASTAPASS(1) M90PPU(uint32 A)
+{
+ if((IRQMode&3)==2)
+ {
+ if(lastread!=A)
+ {
+ ClockCounter();
+ ClockCounter();
+ }
+ lastread=A;
+ }
+// else
+// {
+// if((!lastread)&&(A&0x1000))
+// ClockCounter();
+// lastread=A&0x1000;
+// }
+
+}
+
+static void togglie()
+{
+ tekker>>=6;
+ if(tekker>3)
+ tekker=0;
+ else
+ tekker++;
+ tekker<<=6;
+ FCEU_printf("tekker=%04x\n",tekker);
+ memset(tkcom,0x00,sizeof(tkcom));
+ memset(prgb,0xff,sizeof(prgb));
+ tekprom();
+ tekvrom();
+}
+
+static void M90Restore(int version)
+{
+ tekprom();
+ tekvrom();
+ mira();
+}
+
+static void M90Power(void)
+{
+ SetWriteHandler(0x5000,0x5fff,M90TekWrite);
+ SetWriteHandler(0x8000,0x8fff,M90PRGWrite);
+ SetWriteHandler(0x9000,0x9fff,M90CHRlowWrite);
+ SetWriteHandler(0xA000,0xAfff,M90CHRhiWrite);
+ SetWriteHandler(0xB000,0xBfff,M90NTWrite);
+ SetWriteHandler(0xC000,0xCfff,M90IRQWrite);
+ SetWriteHandler(0xD000,0xDfff,M90ModeWrite);
+
+ SetReadHandler(0x5000,0x5fff,M90TekRead);
+ SetReadHandler(0x6000,0xffff,CartBR);
+
+ mul[0]=mul[1]=regie=0xFF;
+
+ memset(tkcom,0x00,sizeof(tkcom));
+ memset(prgb,0xff,sizeof(prgb));
+ memset(chrlow,0xff,sizeof(chrlow));
+ memset(chrhigh,0xff,sizeof(chrhigh));
+ memset(names,0x00,sizeof(names));
+
+ if(is211)
+ tekker=0xC0;
+ else
+ tekker=0x00;
+
+ tekprom();
+ tekvrom();
+}
+
+
+void Mapper90_Init(CartInfo *info)
+{
+ is211=0;
+ is209=0;
+ info->Reset=togglie;
+ info->Power=M90Power;
+ PPU_hook=M90PPU;
+ GameHBIRQHook2=SLWrap;
+ MapIRQHook=CPUWrap;
+ GameStateRestore=M90Restore;
+ AddExState(Tek_StateRegs, ~0, 0, 0);
+}
+
+void Mapper209_Init(CartInfo *info)
+{
+ is211=0;
+ is209=1;
+ info->Reset=togglie;
+ info->Power=M90Power;
+ GameHBIRQHook2=SLWrap;
+ GameStateRestore=M90Restore;
+ AddExState(Tek_StateRegs, ~0, 0, 0);
+}
+
+void Mapper211_Init(CartInfo *info)
+{
+ is211=1;
+ info->Reset=togglie;
+ info->Power=M90Power;
+ GameHBIRQHook2=SLWrap;
+ GameStateRestore=M90Restore;
+ AddExState(Tek_StateRegs, ~0, 0, 0);
+}
diff --git a/boards/95.c b/boards/95.c
new file mode 100644
index 00000000..7b69435d
--- /dev/null
+++ b/boards/95.c
@@ -0,0 +1,124 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint8 lastA;
+static uint8 DRegs[8];
+static uint8 cmd;
+static uint8 MirCache[8];
+
+static SFORMAT DB_StateRegs[]={
+ {DRegs, 8, "DREG"},
+ {&cmd, 1, "CMD"},
+ {&lastA, 1, "LAST"},
+ {0}
+};
+
+static void toot(void)
+{
+ int x;
+
+ MirCache[0]=MirCache[1]=(DRegs[0]>>4)&1;
+ MirCache[2]=MirCache[3]=(DRegs[1]>>4)&1;
+
+ for(x=0;x<4;x++)
+ MirCache[4+x]=(DRegs[2+x]>>5)&1;
+ onemir(MirCache[lastA]);
+}
+
+static void Sync()
+{
+ setchr2(0x0000,DRegs[0]&0x1F);
+ setchr2(0x0800,DRegs[1]&0x1F);
+ setchr1(0x1000,DRegs[2]&0x1F);
+ setchr1(0x1400,DRegs[3]&0x1F);
+ setchr1(0x1800,DRegs[4]&0x1F);
+ setchr1(0x1C00,DRegs[5]&0x1F);
+ setprg8(0x8000,DRegs[6]&0x1F);
+ setprg8(0xa000,DRegs[7]&0x1F);
+ toot();
+}
+
+static DECLFW(Mapper95_write)
+{
+ switch(A&0xF001)
+ {
+ case 0x8000: cmd = V; break;
+ case 0x8001:
+ switch(cmd&0x07)
+ {
+ case 0: DRegs[0]=(V&0x3F)>>1; break;
+ case 1: DRegs[1]=(V&0x3F)>>1; break;
+ case 2: DRegs[2]=V&0x3F; break;
+ case 3: DRegs[3]=V&0x3F; break;
+ case 4: DRegs[4]=V&0x3F; break;
+ case 5: DRegs[5]=V&0x3F; break;
+ case 6: DRegs[6]=V&0x3F; break;
+ case 7: DRegs[7]=V&0x3F; break;
+ }
+ Sync();
+ }
+}
+
+static void FP_FASTAPASS(1) dragonbust_ppu(uint32 A)
+{
+ static int last=-1;
+ static uint8 z;
+
+ if(A>=0x2000) return;
+
+ A>>=10;
+ lastA=A;
+ z=MirCache[A];
+ if(z!=last)
+ {
+ onemir(z);
+ last=z;
+ }
+}
+
+static void DBPower(void)
+{
+ memset(DRegs,0x3F,8);
+ DRegs[0]=DRegs[1]=0x1F;
+
+ Sync();
+
+ setprg8(0xc000,0x3E);
+ setprg8(0xe000,0x3F);
+
+ SetReadHandler(0x8000,0xffff,CartBR);
+ SetWriteHandler(0x8000,0xffff,Mapper95_write);
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+}
+
+void Mapper95_Init(CartInfo *info)
+{
+ info->Power=DBPower;
+ AddExState(DB_StateRegs, ~0, 0, 0);
+ PPU_hook=dragonbust_ppu;
+ GameStateRestore=StateRestore;
+}
+
diff --git a/boards/Makefile.am.inc b/boards/Makefile.am.inc
new file mode 100644
index 00000000..bd1eb46f
--- /dev/null
+++ b/boards/Makefile.am.inc
@@ -0,0 +1 @@
+fceu_SOURCES += boards/112.c boards/117.c boards/164.c boards/183.c boards/185.c boards/186.c boards/187.c boards/189.c boards/208.c boards/222.c boards/235.c boards/57.c boards/8157.c boards/8237.c boards/88.c boards/90.c boards/95.c boards/bmc13in1jy110.c boards/bmc42in1r.c boards/bmc64in1nr.c boards/bmc70in1.c boards/bmcgk192.c boards/bonza.c boards/cc21.c boards/datalatch.c boards/deirom.c boards/dream.c boards/fk23c.c boards/h2288.c boards/karaoke.c boards/kof97.c boards/konami-qtai.c boards/malee.c boards/mmc1.c boards/mmc3.c boards/mmc5.c boards/n106.c boards/novel.c boards/sachen.c boards/sheroes.c boards/sl1632.c boards/sonic5.c boards/subor.c boards/super24.c boards/supervision.c boards/t-262.c boards/tengen.c boards/__dummy_mapper.c \ No newline at end of file
diff --git a/boards/__dummy_mapper.c b/boards/__dummy_mapper.c
new file mode 100644
index 00000000..ac95ba9c
--- /dev/null
+++ b/boards/__dummy_mapper.c
@@ -0,0 +1,96 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2006 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint8 reg[8];
+/*
+static uint8 *WRAM=NULL;
+static uint32 WRAMSIZE;
+static uint8 *CHRRAM=NULL;
+static uint32 CHRRAMSIZE;
+*/
+
+static SFORMAT StateRegs[]=
+{
+ {reg, 8, "REGS"},
+ {0}
+};
+
+static void Sync(void)
+{
+}
+
+static DECLFW(MNNNWrite)
+{
+}
+
+static void MNNNPower(void)
+{
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x8000,0xFFFF,MNNNWrite);
+}
+
+static void MNNNReset(void)
+{
+}
+
+/*
+static void MNNNClose(void)
+{
+ if(WRAM)
+ FCEU_gfree(WRAM);
+ if(CHRRAM)
+ FCEU_gfree(CHRRAM);
+ WRAM=CHRRAM=NULL;
+}
+*/
+
+static void MNNNIRQHook(void)
+{
+ X6502_IRQBegin(FCEU_IQEXT);
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+}
+
+void MapperNNN_Init(CartInfo *info)
+{
+ info->Reset=MNNNReset;
+ info->Power=MNNNPower;
+// info->Close=MNNNClose;
+ GameHBIRQHook=MNNNIRQHook;
+ GameStateRestore=StateRestore;
+/*
+ CHRRAMSIZE=8192;
+ CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSIZE);
+ SetupCartPRGMapping(0x10,CHRRAM,CHRRAMSIZE,1);
+ AddExState(CHRRAM, CHRRAMSIZE, 0, "WRAM");
+*/
+/*
+ WRAMSIZE=8192;
+ WRAM=(uint8*)FCEU_gmalloc(WRAMSIZE);
+ SetupCartPRGMapping(0x10,WRAM,WRAMSIZE,1);
+ AddExState(WRAM, WRAMSIZE, 0, "WRAM");
+*/
+ AddExState(&StateRegs, ~0, 0, 0);
+} \ No newline at end of file
diff --git a/boards/bmc13in1jy110.c b/boards/bmc13in1jy110.c
new file mode 100644
index 00000000..4909d3fa
--- /dev/null
+++ b/boards/bmc13in1jy110.c
@@ -0,0 +1,103 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * BMC 42-in-1 reset switch
+ */
+
+#include "mapinc.h"
+
+static uint8 bank_mode;
+static uint8 bank_value;
+static uint8 prgb[4];
+static SFORMAT StateRegs[]=
+{
+ {0}
+};
+
+static void Sync(void)
+{
+ FCEU_printf("%02x: %02x %02x\n", bank_mode, bank_value, prgb[0]);
+ switch(bank_mode&7)
+ {
+ case 0:
+ setprg32(0x8000,bank_value&7); break;
+ case 1:
+ setprg16(0x8000,((8+(bank_value&7))>>1)+prgb[1]);
+ setprg16(0xC000,(bank_value&7)>>1);
+ case 4:
+ setprg32(0x8000,8+(bank_value&7)); break;
+ case 5:
+ setprg16(0x8000,((8+(bank_value&7))>>1)+prgb[1]);
+ setprg16(0xC000,((8+(bank_value&7))>>1)+prgb[3]);
+ case 2:
+ setprg8(0x8000,prgb[0]>>2);
+ setprg8(0xa000,prgb[1]);
+ setprg8(0xc000,prgb[2]);
+ setprg8(0xe000,~0);
+ break;
+ case 3:
+ setprg8(0x8000,prgb[0]);
+ setprg8(0xa000,prgb[1]);
+ setprg8(0xc000,prgb[2]);
+ setprg8(0xe000,prgb[3]);
+ break;
+ }
+}
+
+static DECLFW(BMC13in1JY110Write)
+{
+ FCEU_printf("%04x:%04x\n",A,V);
+ switch(A)
+ {
+ case 0x8000:
+ case 0x8001:
+ case 0x8002:
+ case 0x8003: prgb[A&3]=V; break;
+ case 0xD000: bank_mode=V; break;
+ case 0xD001: setmirror(V&3);
+ case 0xD002: break;
+ case 0xD003: bank_value=V; break;
+ }
+ Sync();
+}
+
+static void BMC13in1JY110Power(void)
+{
+ prgb[0]=prgb[1]=prgb[2]=prgb[3]=0;
+ bank_mode=0;
+ bank_value=0;
+ setprg32(0x8000,0);
+ setchr8(0);
+ SetWriteHandler(0x8000,0xFFFF,BMC13in1JY110Write);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+}
+
+void BMC13in1JY110_Init(CartInfo *info)
+{
+ info->Power=BMC13in1JY110Power;
+ AddExState(&StateRegs, ~0, 0, 0);
+ GameStateRestore=StateRestore;
+}
+
+
diff --git a/boards/bmc42in1r.c b/boards/bmc42in1r.c
new file mode 100644
index 00000000..340a4b8a
--- /dev/null
+++ b/boards/bmc42in1r.c
@@ -0,0 +1,87 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * BMC 42-in-1 reset switch
+ */
+
+#include "mapinc.h"
+
+static uint8 hrd_sw;
+static uint8 latche;
+static SFORMAT StateRegs[]=
+{
+ {&latche, 1, "LATCHE"},
+ {&hrd_sw, 1, "HRDSW"},
+ {0}
+};
+
+static void Sync(void)
+{
+ if(!(latche&0x20))
+ setprg32r(hrd_sw,0x8000,(latche>>1)&0x0f);
+ else
+ {
+ setprg16r(hrd_sw,0x8000,latche&0x1f);
+ setprg16r(hrd_sw,0xC000,latche&0x1f);
+ }
+ switch((latche>>6)&3)
+ {
+ case 0: setmirrorw(0,0,0,1); break;
+ case 1: setmirror(MI_V); break;
+ case 2: setmirror(MI_H); break;
+ case 3: setmirror(MI_1); break;
+ }
+}
+
+static DECLFW(BMC42in1rWrite)
+{
+ latche=V;
+ Sync();
+}
+
+static void BMC42in1rReset(void)
+{
+ hrd_sw^=1;
+ Sync();
+}
+
+static void BMC42in1rPower(void)
+{
+ latche=0x00;
+ hrd_sw=0;
+ setchr8(0);
+ Sync();
+ SetWriteHandler(0x8000,0xFFFF,BMC42in1rWrite);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+}
+
+void BMC42in1r_Init(CartInfo *info)
+{
+ info->Power=BMC42in1rPower;
+ info->Reset=BMC42in1rReset;
+ AddExState(&StateRegs, ~0, 0, 0);
+ GameStateRestore=StateRestore;
+}
+
+
diff --git a/boards/bmc64in1nr.c b/boards/bmc64in1nr.c
new file mode 100644
index 00000000..888ef7a4
--- /dev/null
+++ b/boards/bmc64in1nr.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
+ *
+ * BMC 42-in-1 reset switch
+ */
+
+#include "mapinc.h"
+
+static uint8 regs[4];
+
+static SFORMAT StateRegs[]=
+{
+ {regs, 4, "REGS"},
+ {0}
+};
+
+static void Sync(void)
+{
+ if(regs[0]&0x80)
+ {
+ if(regs[1]&0x80)
+ setprg32(0x8000,regs[1]&0x1F);
+ else
+ {
+ int bank=((regs[1]&0x1f)<<1)|((regs[1]>>6)&1);
+ setprg16(0x8000,bank);
+ setprg16(0xC000,bank);
+ }
+ }
+ else
+ {
+ int bank=((regs[1]&0x1f)<<1)|((regs[1]>>6)&1);
+ setprg16(0xC000,bank);
+ }
+ if(regs[0]&0x20)
+ setmirror(MI_H);
+ else
+ setmirror(MI_V);
+ setchr8((regs[2]<<2)|((regs[0]>>1)&3));
+}
+
+static DECLFW(BMC64in1nrWriteLo)
+{
+ regs[A&3]=V;
+ Sync();
+}
+
+static DECLFW(BMC64in1nrWriteHi)
+{
+ regs[3]=V;
+ Sync();
+}
+
+static void BMC64in1nrPower(void)
+{
+ regs[0]=0x80;
+ regs[1]=0x43;
+ regs[2]=regs[3]=0;
+ Sync();
+ SetWriteHandler(0x5000,0x5003,BMC64in1nrWriteLo);
+ SetWriteHandler(0x8000,0xFFFF,BMC64in1nrWriteHi);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+}
+
+void BMC64in1nr_Init(CartInfo *info)
+{
+ info->Power=BMC64in1nrPower;
+ AddExState(&StateRegs, ~0, 0, 0);
+ GameStateRestore=StateRestore;
+}
+
+
diff --git a/boards/bmc70in1.c b/boards/bmc70in1.c
new file mode 100644
index 00000000..81c5438d
--- /dev/null
+++ b/boards/bmc70in1.c
@@ -0,0 +1,116 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint8 is_large_banks;
+static uint8 large_bank;
+static uint8 prg_bank;
+static uint8 chr_bank;
+static uint8 bank_mode;
+static uint8 mirroring;
+static SFORMAT StateRegs[]=
+{
+ {&large_bank, 1, "LB"},
+ {&prg_bank, 1, "PRG"},
+ {&chr_bank, 1, "CHR"},
+ {&bank_mode, 1, "BM"},
+ {&mirroring, 1, "MIRR"},
+ {0}
+};
+
+static void Sync(void)
+{
+ switch (bank_mode)
+ {
+ case 0x00:
+ case 0x10: setprg16(0x8000,large_bank|prg_bank);
+ setprg16(0xC000,large_bank|7);
+ break;
+ case 0x20: setprg32(0x8000,(large_bank|prg_bank)>>1);
+ break;
+ case 0x30: setprg16(0x8000,large_bank|prg_bank);
+ setprg16(0xC000,large_bank|prg_bank);
+ break;
+ }
+ setmirror(mirroring);
+ if(!is_large_banks)
+ setchr8(chr_bank);
+}
+
+static DECLFR(BMC70in1Read)
+{
+ if(bank_mode==0x10)
+ if(is_large_banks)
+ return CartBR((A&0xFFF0)|0x06);
+ else
+ return CartBR((A&0xFFF0)|0x0d);
+ else
+ return CartBR(A);
+}
+
+static DECLFW(BMC70in1Write)
+{
+ if(A&0x4000)
+ {
+ bank_mode=A&0x30;
+ prg_bank=A&7;
+ }
+ else
+ {
+ mirroring=((A&0x20)>>5)^1;
+ if(is_large_banks)
+ large_bank=(A&3)<<3;
+ else
+ chr_bank=A&7;
+ }
+ Sync();
+}
+
+static void BMC70in1Power(void)
+{
+ setchr8(0);
+ bank_mode=0;
+ large_bank=0;
+ Sync();
+ SetReadHandler(0x8000,0xFFFF,BMC70in1Read);
+ SetWriteHandler(0x8000,0xffff,BMC70in1Write);
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+}
+
+void BMC70in1_Init(CartInfo *info)
+{
+ is_large_banks=0;
+ info->Power=BMC70in1Power;
+ GameStateRestore=StateRestore;
+ AddExState(&StateRegs, ~0, 0, 0);
+}
+
+void BMC70in1B_Init(CartInfo *info)
+{
+ is_large_banks=1;
+ info->Power=BMC70in1Power;
+ GameStateRestore=StateRestore;
+ AddExState(&StateRegs, ~0, 0, 0);
+}
diff --git a/boards/bmcgk192.c b/boards/bmcgk192.c
new file mode 100644
index 00000000..7484ba58
--- /dev/null
+++ b/boards/bmcgk192.c
@@ -0,0 +1,67 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint16 addrlatche;
+
+static void Sync(void)
+{
+ if(addrlatche&0x40)
+ {
+ setprg16(0x8000,addrlatche&7);
+ setprg16(0xC000,addrlatche&7);
+ }
+ else
+ setprg32(0x8000,(addrlatche>>1)&3);
+ setchr8((addrlatche>>3)&7);
+ setmirror(((addrlatche&0x80)>>7)^1);
+}
+
+static DECLFW(BMCGK192Write)
+{
+ addrlatche=A;
+ Sync();
+}
+
+static void BMCGK192Reset(void)
+{
+ setprg32(0x8000,0);
+}
+
+static void BMCGK192Power(void)
+{
+ setprg32(0x8000,0);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x8000,0xffff,BMCGK192Write);
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+}
+
+void Mapper58_Init(CartInfo *info)
+{
+ info->Power=BMCGK192Power;
+ info->Reset=BMCGK192Reset;
+ GameStateRestore=StateRestore;
+ AddExState(&addrlatche, 2, 0, "ALATC");
+}
diff --git a/boards/bonza.c b/boards/bonza.c
new file mode 100644
index 00000000..5e572f14
--- /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/cc21.c b/boards/cc21.c
new file mode 100644
index 00000000..9a171ae0
--- /dev/null
+++ b/boards/cc21.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 uint16 addrlatche;
+
+//------------------ UNLCC21 ---------------------------
+
+static void UNLCC21Sync(void)
+{
+ setchr8(addrlatche&1);
+ setmirror(MI_0+((addrlatche&2)>>1));
+}
+
+static DECLFW(UNLCC21Write)
+{
+ addrlatche=A;
+ UNLCC21Sync();
+}
+
+static void UNLCC21Power(void)
+{
+ setprg32(0x8000,0);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x8000,0xffff,UNLCC21Write);
+}
+
+static void UNLCC21Restore(int version)
+{
+ UNLCC21Sync();
+}
+
+void UNLCC21_Init(CartInfo *info)
+{
+ info->Power=UNLCC21Power;
+ GameStateRestore=UNLCC21Restore;
+ AddExState(&addrlatche, 2, 0, "ALATC");
+}
diff --git a/boards/datalatch.c b/boards/datalatch.c
new file mode 100644
index 00000000..b3452fe1
--- /dev/null
+++ b/boards/datalatch.c
@@ -0,0 +1,272 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint8 latche, latcheinit;
+static uint16 addrreg0, addrreg1;
+static void(*WSync)(void);
+
+static DECLFW(LatchWrite)
+{
+ latche=V;
+ WSync();
+}
+
+static void LatchPower(void)
+{
+ latche=latcheinit;
+ WSync();
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(addrreg0,addrreg1,LatchWrite);
+}
+
+static void StateRestore(int version)
+{
+ WSync();
+}
+
+void Latch_Init(CartInfo *info, void (*proc)(void), uint8 init, uint16 adr0, uint16 adr1)
+{
+ latcheinit=init;
+ addrreg0=adr0;
+ addrreg1=adr1;
+ WSync=proc;
+ info->Power=LatchPower;
+ GameStateRestore=StateRestore;
+ AddExState(&latche, 1, 0, "LATC");
+}
+
+//------------------ CPROM ---------------------------
+
+static void CPROMSync(void)
+{
+ setchr4(0x0000,0);
+ setchr4(0x1000,latche&3);
+ setprg16(0x8000,0);
+ setprg16(0xC000,1);
+}
+
+void CPROM_Init(CartInfo *info)
+{
+ Latch_Init(info, CPROMSync, 0, 0x8000, 0xFFFF);
+}
+
+//------------------ CNROM ---------------------------
+
+static void CNROMSync(void)
+{
+ setchr8(latche&3);
+ setprg16(0x8000,0);
+ setprg16(0xC000,1);
+}
+
+void CNROM_Init(CartInfo *info)
+{
+ Latch_Init(info, CNROMSync, 0, 0x8000, 0xFFFF);
+}
+
+//------------------ ANROM ---------------------------
+
+static void ANROMSync()
+{
+ setprg32(0x8000,latche&0xf);
+ setmirror(MI_0+((latche>>4)&1));
+ setchr8(0);
+}
+
+void ANROM_Init(CartInfo *info)
+{
+ Latch_Init(info, ANROMSync, 0, 0x8000, 0xFFFF);
+}
+
+//------------------ Map 70 ---------------------------
+
+static void M70Sync()
+{
+ setprg16(0x8000,latche>>4);
+ setprg16(0xc000,~0);
+ setchr8(latche&0xf);
+}
+
+void Mapper70_Init(CartInfo *info)
+{
+ Latch_Init(info, M70Sync, 0, 0x8000, 0xFFFF);
+}
+
+//------------------ Map 152 ---------------------------
+
+static void M152Sync()
+{
+ setprg16(0x8000,(latche>>4)&7);
+ setprg16(0xc000,~0);
+ setchr8(latche&0xf);
+ setmirror(MI_0+((latche>>7)&1)); /* Saint Seiya...hmm. */
+}
+
+void Mapper152_Init(CartInfo *info)
+{
+ Latch_Init(info, M152Sync, 0, 0x8000, 0xFFFF);
+}
+
+//------------------ Map 78 ---------------------------
+/* Should be two separate emulation functions for this "mapper". Sigh. URGE TO KILL RISING. */
+static void M78Sync()
+{
+ setprg16(0x8000,(latche&7));
+ setprg16(0xc000,~0);
+ setchr8(latche>>4);
+ setmirror(MI_0+((latche>>3)&1));
+}
+
+void Mapper78_Init(CartInfo *info)
+{
+ Latch_Init(info, M78Sync, 0, 0x8000, 0xFFFF);
+}
+
+//------------------ MHROM ---------------------------
+
+static void MHROMSync(void)
+{
+ setprg32(0x8000,latche>>4);
+ setchr8(latche&0xf);
+}
+
+void MHROM_Init(CartInfo *info)
+{
+ Latch_Init(info, MHROMSync, 0, 0x8000, 0xFFFF);
+}
+
+void Mapper140_Init(CartInfo *info)
+{
+ Latch_Init(info, MHROMSync, 0, 0x6000, 0x7FFF);
+}
+
+//------------------ Map 87 ---------------------------
+
+static void M87Sync(void)
+{
+ setprg16(0x8000,0);
+ setprg16(0xC000,1);
+ setchr8(latche>>1);
+}
+
+void Mapper87_Init(CartInfo *info)
+{
+ Latch_Init(info, M87Sync, ~0, 0x6000, 0xFFFF);
+}
+
+//------------------ Map 11 ---------------------------
+
+static void M11Sync(void)
+{
+ setprg32(0x8000,latche&0xf);
+ setchr8(latche>>4);
+}
+
+void Mapper11_Init(CartInfo *info)
+{
+ Latch_Init(info, M11Sync, 0, 0x8000, 0xFFFF);
+}
+
+void Mapper144_Init(CartInfo *info)
+{
+ Latch_Init(info, M11Sync, 0, 0x8001, 0xFFFF);
+}
+
+//------------------ UNROM ---------------------------
+
+static void UNROMSync(void)
+{
+ setprg16(0x8000,latche);
+ setprg16(0xc000,~0);
+ setchr8(0);
+}
+
+void UNROM_Init(CartInfo *info)
+{
+ Latch_Init(info, UNROMSync, 0, 0x8000, 0xFFFF);
+}
+
+//------------------ Map 93 ---------------------------
+
+static void SSUNROMSync(void)
+{
+ setprg16(0x8000,latche>>4);
+ setprg16(0xc000,~0);
+ setchr8(0);
+}
+
+void SUNSOFT_UNROM_Init(CartInfo *info)
+{
+ Latch_Init(info, SSUNROMSync, 0, 0x8000, 0xFFFF);
+}
+
+//------------------ Map 94 ---------------------------
+
+static void M94Sync(void)
+{
+ setprg16(0x8000,latche>>2);
+ setprg16(0xc000,~0);
+ setchr8(0);
+}
+
+void Mapper94_Init(CartInfo *info)
+{
+ Latch_Init(info, M94Sync, 0, 0x8000, 0xFFFF);
+}
+
+//------------------ Map 107 ---------------------------
+
+static void M107Sync(void)
+{
+ setprg32(0x8000,(latche>>1)&3);
+ setchr8(latche&7);
+}
+
+void Mapper107_Init(CartInfo *info)
+{
+ Latch_Init(info, M107Sync, ~0, 0x8000, 0xFFFF);
+}
+
+//------------------ NROM ---------------------------
+
+#ifdef DEBUG_MAPPER
+static DECLFW(WriteHandler)
+{
+ FCEU_printf("$%04x:$%02x\n",A,V);
+}
+#endif
+
+static void NROMPower(void)
+{
+ setprg16(0x8000,0);
+ setprg16(0xC000,~0);
+ setchr8(0);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ #ifdef DEBUG_MAPPER
+ SetWriteHandler(0x4020,0xFFFF,WriteHandler);
+ #endif
+}
+
+void NROM_Init(CartInfo *info)
+{
+ info->Power=NROMPower;
+}
diff --git a/boards/deirom.c b/boards/deirom.c
new file mode 100644
index 00000000..7a1ed430
--- /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 00000000..cf33afef
--- /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 latche;
+
+static void Sync(void)
+{
+ setprg16(0x8000,latche);
+ setprg16(0xC000,8);
+}
+
+static DECLFW(DREAMWrite)
+{
+ latche=V&7;
+ Sync();
+}
+
+static void DREAMPower(void)
+{
+ latche=0;
+ Sync();
+ setchr8(0);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x5020,0x5020,DREAMWrite);
+}
+
+static void Restore(int version)
+{
+ Sync();
+}
+
+void DreamTech01_Init(CartInfo *info)
+{
+ GameStateRestore=Restore;
+ info->Power=DREAMPower;
+ AddExState(&latche, 1, 0, "LATCH");
+}
diff --git a/boards/fk23c.c b/boards/fk23c.c
new file mode 100644
index 00000000..267c80c1
--- /dev/null
+++ b/boards/fk23c.c
@@ -0,0 +1,112 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+#include "mmc3.h"
+
+static uint8 unromchr;
+
+static void BMCFK23CCW(uint32 A, uint8 V)
+{
+ if(EXPREGS[0]&0x40)
+ setchr8((EXPREGS[2]&0xFC)|unromchr);
+ else
+ {
+ uint16 base=(EXPREGS[2]&0x7F)<<3;
+ setchr1(A,V|base);
+ if(EXPREGS[3]&2)
+ {
+ setchr1(0x0400,EXPREGS[6]|base);
+ setchr1(0x0C00,EXPREGS[7]|base);
+ }
+ }
+}
+
+static void BMCFK23CPW(uint32 A, uint8 V)
+{
+ if(EXPREGS[0]&4)
+ setprg32(0x8000,EXPREGS[1]>>1);
+ else
+ {
+ if(EXPREGS[0]&2)
+ setprg8(A,(V&(0x3F>>(EXPREGS[0]&3)))|(EXPREGS[1]<<1));
+ else
+ setprg8(A,V);
+ if(EXPREGS[3]&2)
+ {
+ setprg8(0xC000,EXPREGS[4]);
+ setprg8(0xE000,EXPREGS[5]);
+ }
+ }
+}
+
+static DECLFW(BMCFK23C8003Write)
+{
+ if(EXPREGS[0]&0x40)
+ {
+ unromchr=V&3;
+ FixMMC3CHR(MMC3_cmd);
+ }
+ else
+ {
+ if((A==0x8001)&&(EXPREGS[3]&2&&MMC3_cmd&8))
+ {
+ EXPREGS[4|(MMC3_cmd&3)]=V;
+ FixMMC3PRG(MMC3_cmd);
+ FixMMC3CHR(MMC3_cmd);
+ }
+ else
+ MMC3_CMDWrite(A,V);
+ }
+}
+
+static DECLFW(BMCFK23CWrite)
+{
+ EXPREGS[A&3]=V;
+ FixMMC3PRG(MMC3_cmd);
+ FixMMC3CHR(MMC3_cmd);
+}
+
+static void BMCFK23CReset(void)
+{
+ EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
+ EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
+ MMC3RegReset();
+}
+
+static void BMCFK23CPower(void)
+{
+ EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=0;
+ EXPREGS[4]=EXPREGS[5]=EXPREGS[6]=EXPREGS[7]=0xFF;
+ GenMMC3Power();
+ SetWriteHandler(0x5ff0,0x5fff,BMCFK23CWrite);
+ SetWriteHandler(0x8000,0x8003,BMCFK23C8003Write);
+}
+
+void BMCFK23C_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, 0);
+ cwrap=BMCFK23CCW;
+ pwrap=BMCFK23CPW;
+ info->Power=BMCFK23CPower;
+ info->Reset=BMCFK23CReset;
+ AddExState(EXPREGS, 8, 0, "EXPR");
+ AddExState(&unromchr, 1, 0, "UNCHR");
+}
diff --git a/boards/h2288.c b/boards/h2288.c
new file mode 100644
index 00000000..c2c66210
--- /dev/null
+++ b/boards/h2288.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"
+#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 00000000..e089cda1
--- /dev/null
+++ b/boards/karaoke.c
@@ -0,0 +1,71 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+extern uint32 ROM_size;
+static uint8 latche;
+
+static void Sync(void)
+{
+ if(latche)
+ {
+ if(latche&0x10)
+ setprg16(0x8000,(latche&7));
+ else
+ setprg16(0x8000,(latche&7)|8);
+ }
+ else
+ setprg16(0x8000,7+(ROM_size>>4));
+}
+
+static DECLFW(M188Write)
+{
+ latche=V;
+ Sync();
+}
+
+static DECLFR(ExtDev)
+{
+ return(3);
+}
+
+static void Power(void)
+{
+ latche=0;
+ Sync();
+ setchr8(0);
+ setprg16(0xc000,0x7);
+ SetReadHandler(0x6000,0x7FFF,ExtDev);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x8000,0xFFFF,M188Write);
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+}
+
+void Mapper188_Init(CartInfo *info)
+{
+ info->Power=Power;
+ GameStateRestore=StateRestore;
+ AddExState(&latche, 1, 0, "LATCH");
+}
diff --git a/boards/kof97.c b/boards/kof97.c
new file mode 100644
index 00000000..e40f4cf4
--- /dev/null
+++ b/boards/kof97.c
@@ -0,0 +1,50 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+#include "mmc3.h"
+
+static DECLFW(UNLKOF97CMDWrite)
+{
+ V=(V&0xD8)|((V&0x20)>>4)|((V&4)<<3)|((V&2)>>1)|((V&1)<<2); //76143502
+ if(A==0x9000) A=0x8001;
+ MMC3_CMDWrite(A,V);
+}
+
+static DECLFW(UNLKOF97IRQWrite)
+{
+ V=(V&0xD8)|((V&0x20)>>4)|((V&4)<<3)|((V&2)>>1)|((V&1)<<2);
+ if(A==0xD000) A=0xC001;
+ else if(A==0xF000) A=0xE001;
+ MMC3_IRQWrite(A,V);
+}
+
+static void UNLKOF97Power(void)
+{
+ GenMMC3Power();
+ SetWriteHandler(0x8000,0xA000,UNLKOF97CMDWrite);
+ SetWriteHandler(0xC000,0xF000,UNLKOF97IRQWrite);
+}
+
+void UNLKOF97_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 128, 256, 0, 0);
+ info->Power=UNLKOF97Power;
+}
diff --git a/boards/konami-qtai.c b/boards/konami-qtai.c
new file mode 100644
index 00000000..ff552e10
--- /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[]=
+{
+ {&regs, 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
new file mode 100644
index 00000000..7feb95e1
--- /dev/null
+++ b/boards/malee.c
@@ -0,0 +1,41 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint8 WRAM[2048];
+
+static void MALEEReset(void)
+{
+ setprg2r(0x10,0x7000,0);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetReadHandler(0x6000,0x67FF,CartBR);
+ SetReadHandler(0x7000,0x77FF,CartBR);
+ setprg2r(1,0x6000,0);
+ setprg32(0x8000,0);
+ setchr8(0);
+}
+
+void MALEE_Init(CartInfo *info)
+{
+ info->Power=MALEEReset;
+ SetupCartPRGMapping(0x10, WRAM, 2048, 1);
+ AddExState(WRAM, 2048, 0,"RAM");
+}
diff --git a/boards/mapinc.h b/boards/mapinc.h
new file mode 100644
index 00000000..eef1b4a2
--- /dev/null
+++ b/boards/mapinc.h
@@ -0,0 +1,11 @@
+#include "../types.h"
+#include "../x6502.h"
+#include "../fceu.h"
+#include "../ppu.h"
+#include "../memory.h"
+#include "../sound.h"
+#include "../state.h"
+#include "../cart.h"
+#include "../cheat.h"
+#include "../unif.h"
+#include <string.h>
diff --git a/boards/mmc1.c b/boards/mmc1.c
new file mode 100644
index 00000000..29cf5b96
--- /dev/null
+++ b/boards/mmc1.c
@@ -0,0 +1,423 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 1998 BERO
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static void GenMMC1Power(void);
+static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery);
+
+static uint8 DRegs[4];
+static uint8 Buffer,BufferShift;
+
+static int mmc1opts;
+
+static void (*MMC1CHRHook4)(uint32 A, uint8 V);
+static void (*MMC1PRGHook16)(uint32 A, uint8 V);
+
+static uint8 *WRAM=NULL;
+static uint8 *CHRRAM=NULL;
+static int is155;
+
+static DECLFW(MBWRAM)
+{
+ if(!(DRegs[3]&0x10)||is155)
+ Page[A>>11][A]=V; // WRAM is enabled.
+}
+
+static DECLFR(MAWRAM)
+{
+ if((DRegs[3]&0x10)&&!is155)
+ return X.DB; // WRAM is disabled
+ return(Page[A>>11][A]);
+}
+
+static void MMC1CHR(void)
+{
+ if(mmc1opts&4)
+ {
+ if(DRegs[0]&0x10)
+ setprg8r(0x10,0x6000,(DRegs[1]>>4)&1);
+ else
+ setprg8r(0x10,0x6000,(DRegs[1]>>3)&1);
+ }
+ if(MMC1CHRHook4)
+ {
+ if(DRegs[0]&0x10)
+ {
+ MMC1CHRHook4(0x0000,DRegs[1]);
+ MMC1CHRHook4(0x1000,DRegs[2]);
+ }
+ else
+ {
+ MMC1CHRHook4(0x0000,(DRegs[1]&0xFE));
+ MMC1CHRHook4(0x1000,DRegs[1]|1);
+ }
+ }
+ else
+ {
+ if(DRegs[0]&0x10)
+ {
+ setchr4(0x0000,DRegs[1]);
+ setchr4(0x1000,DRegs[2]);
+ }
+ else
+ setchr8(DRegs[1]>>1);
+ }
+}
+
+static void MMC1PRG(void)
+{
+ uint8 offs=DRegs[1]&0x10;
+ if(MMC1PRGHook16)
+ {
+ switch(DRegs[0]&0xC)
+ {
+ case 0xC: MMC1PRGHook16(0x8000,(DRegs[3]+offs));
+ MMC1PRGHook16(0xC000,0xF+offs);
+ break;
+ case 0x8: MMC1PRGHook16(0xC000,(DRegs[3]+offs));
+ MMC1PRGHook16(0x8000,offs);
+ break;
+ case 0x0:
+ case 0x4:
+ MMC1PRGHook16(0x8000,((DRegs[3]&~1)+offs));
+ MMC1PRGHook16(0xc000,((DRegs[3]&~1)+offs+1));
+ break;
+ }
+ }
+ else switch(DRegs[0]&0xC)
+ {
+ case 0xC: setprg16(0x8000,(DRegs[3]+offs));
+ setprg16(0xC000,0xF+offs);
+ break;
+ case 0x8: setprg16(0xC000,(DRegs[3]+offs));
+ setprg16(0x8000,offs);
+ break;
+ case 0x0:
+ case 0x4:
+ setprg16(0x8000,((DRegs[3]&~1)+offs));
+ setprg16(0xc000,((DRegs[3]&~1)+offs+1));
+ break;
+ }
+}
+
+static void MMC1MIRROR(void)
+{
+ switch(DRegs[0]&3)
+ {
+ case 2: setmirror(MI_V); break;
+ case 3: setmirror(MI_H); break;
+ case 0: setmirror(MI_0); break;
+ case 1: setmirror(MI_1); break;
+ }
+}
+
+static uint64 lreset;
+static DECLFW(MMC1_write)
+{
+ int n=(A>>13)-4;
+ //FCEU_DispMessage("%016x",timestampbase+timestamp);
+ //printf("$%04x:$%02x, $%04x\n",A,V,X.PC);
+ //DumpMem("out",0xe000,0xffff);
+
+ /* The MMC1 is busy so ignore the write. */
+ /* As of version FCE Ultra 0.81, the timestamp is only
+ increased before each instruction is executed(in other words
+ precision isn't that great), but this should still work to
+ deal with 2 writes in a row from a single RMW instruction. */
+ if((timestampbase+timestamp)<(lreset+2)) return;
+ if(V&0x80)
+ {
+ DRegs[0]|=0xC;
+ BufferShift=Buffer=0;
+ MMC1PRG();
+ lreset=timestampbase+timestamp;
+ return;
+ }
+ Buffer|=(V&1)<<(BufferShift++);
+ if(BufferShift==5)
+ {
+ DRegs[n] = Buffer;
+ BufferShift = Buffer = 0;
+ switch(n)
+ {
+ case 0: MMC1MIRROR(); MMC1CHR(); MMC1PRG(); break;
+ case 1: MMC1CHR(); MMC1PRG(); break;
+ case 2: MMC1CHR(); break;
+ case 3: MMC1PRG(); break;
+ }
+ }
+}
+
+static void MMC1_Restore(int version)
+{
+ MMC1MIRROR();
+ MMC1CHR();
+ MMC1PRG();
+ lreset=0; /* timestamp(base) is not stored in save states. */
+}
+
+static void MMC1CMReset(void)
+{
+ int i;
+ for(i=0;i<4;i++)
+ DRegs[i]=0;
+ Buffer = BufferShift = 0;
+ DRegs[0]=0x1F;
+ DRegs[1]=0;
+ DRegs[2]=0; // Should this be something other than 0?
+ DRegs[3]=0;
+
+ MMC1MIRROR();
+ MMC1CHR();
+ MMC1PRG();
+}
+
+static int DetectMMC1WRAMSize(uint32 crc32)
+{
+ switch(crc32)
+ {
+ case 0xc6182024: /* Romance of the 3 Kingdoms */
+ case 0x2225c20f: /* Genghis Khan */
+ case 0x4642dda6: /* Nobunaga's Ambition */
+ case 0x29449ba9: /* "" "" (J) */
+ case 0x2b11e0b0: /* "" "" (J) */
+ case 0xb8747abf: /* Best Play Pro Yakyuu Special (J) */
+ case 0xc9556b36: /* Final Fantasy I & II (J) [!] */
+ FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n");
+ return(16);
+ break;
+ default:return(8);
+ }
+}
+
+static uint32 NWCIRQCount;
+static uint8 NWCRec;
+#define NWCDIP 0xE
+
+static void FP_FASTAPASS(1) NWCIRQHook(int a)
+{
+ if(!(NWCRec&0x10))
+ {
+ NWCIRQCount+=a;
+ if((NWCIRQCount|(NWCDIP<<25))>=0x3e000000)
+ {
+ NWCIRQCount=0;
+ X6502_IRQBegin(FCEU_IQEXT);
+ }
+ }
+}
+
+static void NWCCHRHook(uint32 A, uint8 V)
+{
+ if((V&0x10)) // && !(NWCRec&0x10))
+ {
+ NWCIRQCount=0;
+ X6502_IRQEnd(FCEU_IQEXT);
+ }
+ NWCRec=V;
+ if(V&0x08)
+ MMC1PRG();
+ else
+ setprg32(0x8000,(V>>1)&3);
+}
+
+static void NWCPRGHook(uint32 A, uint8 V)
+{
+ if(NWCRec&0x8)
+ setprg16(A,8|(V&0x7));
+ else
+ setprg32(0x8000,(NWCRec>>1)&3);
+}
+
+static void NWCPower(void)
+{
+ GenMMC1Power();
+ setchr8r(0,0);
+}
+
+void Mapper105_Init(CartInfo *info)
+{
+ GenMMC1Init(info, 256, 256, 8, 0);
+ MMC1CHRHook4=NWCCHRHook;
+ MMC1PRGHook16=NWCPRGHook;
+ MapIRQHook=NWCIRQHook;
+ info->Power=NWCPower;
+}
+
+static void GenMMC1Power(void)
+{
+ lreset=0;
+ if(mmc1opts&1)
+ {
+ FCEU_CheatAddRAM(8,0x6000,WRAM);
+ if(mmc1opts&4)
+ FCEU_dwmemset(WRAM,0,8192)
+ else if(!(mmc1opts&2))
+ FCEU_dwmemset(WRAM,0,8192);
+ }
+ SetWriteHandler(0x8000,0xFFFF,MMC1_write);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+
+ if(mmc1opts&1)
+ {
+ SetReadHandler(0x6000,0x7FFF,MAWRAM);
+ SetWriteHandler(0x6000,0x7FFF,MBWRAM);
+ setprg8r(0x10,0x6000,0);
+ }
+
+ MMC1CMReset();
+}
+
+static void GenMMC1Close(void)
+{
+ if(CHRRAM)
+ FCEU_gfree(CHRRAM);
+ if(WRAM)
+ FCEU_gfree(WRAM);
+ CHRRAM=WRAM=NULL;
+}
+
+static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery)
+{
+ is155=0;
+
+ info->Close=GenMMC1Close;
+ MMC1PRGHook16=MMC1CHRHook4=0;
+ mmc1opts=0;
+ PRGmask16[0]&=(prg>>14)-1;
+ CHRmask4[0]&=(chr>>12)-1;
+ CHRmask8[0]&=(chr>>13)-1;
+
+ if(wram)
+ {
+ WRAM=(uint8*)FCEU_gmalloc(wram*1024);
+ mmc1opts|=1;
+ if(wram>8) mmc1opts|=4;
+ SetupCartPRGMapping(0x10,WRAM,wram*1024,1);
+ AddExState(WRAM, wram*1024, 0, "WRAM");
+ if(battery)
+ {
+ mmc1opts|=2;
+ info->SaveGame[0]=WRAM+((mmc1opts&4)?8192:0);
+ info->SaveGameLen[0]=8192;
+ }
+ }
+ if(!chr)
+ {
+ CHRRAM=(uint8*)FCEU_gmalloc(8192);
+ SetupCartCHRMapping(0, CHRRAM, 8192, 1);
+ AddExState(CHRRAM, 8192, 0, "CHRR");
+ }
+ AddExState(DRegs, 4, 0, "DREG");
+
+ info->Power=GenMMC1Power;
+ GameStateRestore=MMC1_Restore;
+ AddExState(&lreset, 8, 1, "LRST");
+}
+
+void Mapper1_Init(CartInfo *info)
+{
+ int ws=DetectMMC1WRAMSize(info->CRC32);
+ GenMMC1Init(info, 512, 256, ws, info->battery);
+}
+
+/* Same as mapper 1, without respect for WRAM enable bit. */
+void Mapper155_Init(CartInfo *info)
+{
+ GenMMC1Init(info,512,256,8,info->battery);
+ is155=1;
+}
+
+void SAROM_Init(CartInfo *info)
+{
+ GenMMC1Init(info, 128, 64, 8, info->battery);
+}
+
+void SBROM_Init(CartInfo *info)
+{
+ GenMMC1Init(info, 128, 64, 0, 0);
+}
+
+void SCROM_Init(CartInfo *info)
+{
+ GenMMC1Init(info, 128, 128, 0, 0);
+}
+
+void SEROM_Init(CartInfo *info)
+{
+ GenMMC1Init(info, 32, 64, 0, 0);
+}
+
+void SGROM_Init(CartInfo *info)
+{
+ GenMMC1Init(info, 256, 0, 0, 0);
+}
+
+void SKROM_Init(CartInfo *info)
+{
+ GenMMC1Init(info, 256, 64, 8, info->battery);
+}
+
+void SLROM_Init(CartInfo *info)
+{
+ GenMMC1Init(info, 256, 128, 0, 0);
+}
+
+void SL1ROM_Init(CartInfo *info)
+{
+ GenMMC1Init(info, 128, 128, 0, 0);
+}
+
+/* Begin unknown - may be wrong - perhaps they use different MMC1s from the
+ similarly functioning boards?
+*/
+
+void SL2ROM_Init(CartInfo *info)
+{
+ GenMMC1Init(info, 256, 256, 0, 0);
+}
+
+void SFROM_Init(CartInfo *info)
+{
+ GenMMC1Init(info, 256, 256, 0, 0);
+}
+
+void SHROM_Init(CartInfo *info)
+{
+ GenMMC1Init(info, 256, 256, 0, 0);
+}
+
+/* End unknown */
+/* */
+/* */
+
+void SNROM_Init(CartInfo *info)
+{
+ GenMMC1Init(info, 256, 0, 8, info->battery);
+}
+
+void SOROM_Init(CartInfo *info)
+{
+ GenMMC1Init(info, 256, 0, 16, info->battery);
+}
+
+
diff --git a/boards/mmc3.c b/boards/mmc3.c
new file mode 100644
index 00000000..63459101
--- /dev/null
+++ b/boards/mmc3.c
@@ -0,0 +1,1602 @@
+/* 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;
+uint8 *WRAM;
+uint8 *CHRRAM;
+uint32 CHRRAMSize;
+uint8 EXPREGS[8]; /* For bootleg games, mostly. */
+
+static uint8 A000B,A001B;
+static uint8 DRegBuf[8];
+
+#undef IRQCount
+#undef IRQLatch
+#undef IRQa
+uint8 IRQCount,IRQLatch,IRQa;
+uint8 IRQReload;
+
+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;
+static int isRevB=1;
+
+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)
+{
+// FCEU_printf("%04x:%04x\n",A,V);
+ 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;
+ Write_IRQFM(0x4017,0x40);
+ break;
+ }
+}
+
+DECLFW(MMC3_IRQWrite)
+{
+// FCEU_printf("%04x:%04x\n",A,V);
+ 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|isRevB) && !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();
+}
+
+void GenMMC3Restore(int version)
+{
+ if(mwrap) mwrap(A000B&1);
+ FixMMC3PRG(MMC3_cmd);
+ FixMMC3CHR(MMC3_cmd);
+}
+
+static void GENCWRAP(uint32 A, uint8 V)
+{
+ if(!UNIFchrrama) 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)
+{
+ if(UNIFchrrama) setchr8(0);
+
+ 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;
+}
+
+//static uint16 _a12;
+//static void FP_FASTAPASS(1) MMC3_PPU(uint32 A)
+//{
+// if(A&0x2000)return;
+// if((!_a12)&&(A&0x1000))
+// ClockMMC3Counter();
+// _a12=A&0x1000;
+//}
+
+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) // duplicated CHR RAM set up
+// {
+// 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;
+// PPU_hook=MMC3_PPU;
+ 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 37 -------------------------------
+
+static void M37PW(uint32 A, uint8 V)
+{
+ if(EXPREGS[0]!=2)
+ V&=0x7;
+ else
+ V&=0xF;
+ V|=EXPREGS[0]<<3;
+ setprg8(A,V);
+}
+
+static void M37CW(uint32 A, uint8 V)
+{
+ uint32 NV=V;
+ NV&=0x7F;
+ NV|=EXPREGS[0]<<6;
+ setchr1(A,NV);
+}
+
+static DECLFW(M37Write)
+{
+ EXPREGS[0]=(V&6)>>1;
+ FixMMC3PRG(MMC3_cmd);
+ FixMMC3CHR(MMC3_cmd);
+}
+
+static void M37Reset(void)
+{
+ EXPREGS[0]=0;
+ MMC3RegReset();
+}
+
+static void M37Power(void)
+{
+ EXPREGS[0]=0;
+ GenMMC3Power();
+ SetWriteHandler(0x6000,0x7FFF,M37Write);
+}
+
+void Mapper37_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ pwrap=M37PW;
+ cwrap=M37CW;
+ info->Power=M37Power;
+ info->Reset=M37Reset;
+ AddExState(EXPREGS, 1, 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)
+{
+ if(!UNIFchrrama)
+ {
+ uint32 NV=V;
+ if(EXPREGS[2]&8)
+ NV&=(1<<((EXPREGS[2]&7)+1))-1;
+// else
+// NV&=0;
+ NV|=EXPREGS[0]|((EXPREGS[2]&0xF0)<<4);
+ 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;
+ if(!EXPREGS[4])
+ {
+ FCEU_printf("CHROR %02x, PRGOR %02x, CHRAND %02x, PRGAND %02x\n",EXPREGS[0],EXPREGS[1],EXPREGS[2],EXPREGS[3]);
+ FCEU_printf("CHR0 %03x, CHR1 %03x, PRG0 %03x, PRG1 %03x\n",
+ (0x00&((1<<((EXPREGS[2]&7)+1))-1))|(EXPREGS[0]|((EXPREGS[2]&0xF0)<<4)),
+ (0xFF&((1<<((EXPREGS[2]&7)+1))-1))|(EXPREGS[0]|((EXPREGS[2]&0xF0)<<4)),
+ (0x00&((EXPREGS[3]&0x3F)^0x3F))|(EXPREGS[1]),
+ (0xFF&((EXPREGS[3]&0x3F)^0x3F))|(EXPREGS[1]));
+ }
+ FixMMC3PRG(MMC3_cmd);
+ FixMMC3CHR(MMC3_cmd);
+}
+
+static void M45Reset(void)
+{
+ EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=EXPREGS[3]=EXPREGS[4]=0;
+ MMC3RegReset();
+}
+
+static void M45Power(void)
+{
+ setchr8(0);
+ 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)
+{
+ if((V==8)||(V==9)) //Di 4 Ci - Ji Qi Ren Dai Zhan (As).nes, Ji Jia Zhan Shi (As).nes
+ setchr1r(0x10,A,V);
+ else
+ setchr1r(0,A,V);
+}
+
+void Mapper74_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ cwrap=M74CW;
+ CHRRAMSize=2048;
+ 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;
+ IRQLatch=V;
+ IRQReload=1;
+ }
+ 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)
+{
+ if(EXPREGS[0]&0x80)
+ setprg32(0x8000,(EXPREGS[0]&7)>>1);
+ else
+ setprg8(A,V);
+}
+
+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));
+ if(EXPREGS[0]&2)
+ setchr8r(0x10,0);
+ else
+ setchr1(A,V);
+}
+
+static DECLFW(M116Write)
+{
+ EXPREGS[0]=V;
+ 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;
+ CHRRAM = (uint8*)FCEU_gmalloc(8192);
+ SetupCartCHRMapping(0x10, CHRRAM, 8192, 1);
+ 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 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: if(V)
+ {
+ IRQLatch=V;
+ IRQReload=1;
+ 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 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 192 -------------------------------
+
+static void M192CW(uint32 A, uint8 V)
+{
+ if((V==8)||(V==9)||(V==0xA)||(V==0xB)) //Ying Lie Qun Xia Zhuan (Chinese),
+ setchr1r(0x10,A,V);
+ else
+ setchr1r(0,A,V);
+}
+
+void Mapper192_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ cwrap=M192CW;
+ CHRRAMSize=4096;
+ CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
+ SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
+ AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
+}
+
+// ---------------------------- Mapper 194 -------------------------------
+
+static void M194CW(uint32 A, uint8 V)
+{
+ if(V<=1) //Dai-2-Ji - Super Robot Taisen (As).nes
+ setchr1r(0x10,A,V);
+ else
+ setchr1r(0,A,V);
+}
+
+void Mapper194_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ cwrap=M194CW;
+ CHRRAMSize=2048;
+ CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
+ SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
+ AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
+}
+
+// ---------------------------- Mapper 198 -------------------------------
+
+static uint8 *wramtw;
+static uint16 wramsize;
+static void M198CW(uint32 A, uint8 V)
+{
+ if(V<=3) // Crystalis (c).nes, Captain Tsubasa Vol 2 - Super Striker (C)
+ setchr1r(0x10,A,V);
+ else
+ setchr1r(0,A,V);
+}
+
+static void M198Power(void)
+{
+ GenMMC3Power();
+ setprg4r(0x10,0x5000,0);
+ SetWriteHandler(0x5000,0x5fff,CartBW);
+ SetReadHandler(0x5000,0x5fff,CartBR);
+}
+
+static void M198Close(void)
+{
+ if(wramtw)
+ FCEU_gfree(wramtw);
+ wramtw=NULL;
+}
+
+void Mapper198_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 512, 256, 8, info->battery);
+ cwrap=M198CW;
+ info->Power=M198Power;
+ info->Close=M198Close;
+ CHRRAMSize=4096;
+ CHRRAM=(uint8*)FCEU_gmalloc(CHRRAMSize);
+ SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1);
+ wramsize=4096;
+ wramtw=(uint8*)FCEU_gmalloc(wramsize);
+ SetupCartPRGMapping(0x10, wramtw, wramsize, 1);
+ AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
+ AddExState(wramtw, wramsize, 0, "WRAMTW");
+}
+
+// ---------------------------- Mapper 199 -------------------------------
+
+static uint8 *wramtw;
+static uint16 wramsize;
+static void M199PW(uint32 A, uint8 V)
+{
+ if(V>=0x50)
+ setprg8(A,V&0x4F);
+ else
+ setprg8(A,V);
+}
+
+void Mapper199_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 1024, 256, 8, info->battery);
+ pwrap=M199PW;
+ info->Power=M198Power;
+ info->Close=M198Close;
+ wramsize=4096;
+ wramtw=(uint8*)FCEU_gmalloc(wramsize);
+ SetupCartPRGMapping(0x10, wramtw, wramsize, 1);
+ AddExState(CHRRAM, CHRRAMSize, 0, "CHRR");
+ AddExState(wramtw, wramsize, 0, "WRAMTW");
+}
+
+// ---------------------------- 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)<<7));
+}
+
+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 0xC001: IRQLatch=V; break;
+ case 0xA001: IRQReload=1; break;
+ case 0xE001: IRQa=1; break;
+ case 0xE000: X6502_IRQEnd(FCEU_IQEXT); IRQa=0; 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 00000000..4e7452e3
--- /dev/null
+++ b/boards/mmc3.h
@@ -0,0 +1,23 @@
+extern uint8 MMC3_cmd;
+extern uint8 *WRAM;
+extern uint8 *CHRRAM;
+extern uint8 EXPREGS[8];
+#undef IRQCount
+#undef IRQLatch
+#undef IRQa
+extern uint8 IRQCount,IRQLatch,IRQa;
+extern uint8 IRQReload;
+
+extern void (*pwrap)(uint32 A, uint8 V);
+extern void (*cwrap)(uint32 A, uint8 V);
+extern void (*mwrap)(uint8 V);
+
+void GenMMC3Power(void);
+void GenMMC3Restore(int version);
+void MMC3RegReset(void);
+void FixMMC3PRG(int V);
+void FixMMC3CHR(int V);
+DECLFW(MMC3_CMDWrite);
+DECLFW(MMC3_IRQWrite);
+
+void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery);
diff --git a/boards/mmc5.c b/boards/mmc5.c
new file mode 100644
index 00000000..ce3fc9c8
--- /dev/null
+++ b/boards/mmc5.c
@@ -0,0 +1,834 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* None of this code should use any of the iNES bank switching wrappers. */
+
+#include "mapinc.h"
+
+static void (*sfun)(int P);
+static void (*psfun)(void);
+
+void MMC5RunSound(int Count);
+void MMC5RunSoundHQ(void);
+
+static INLINE void MMC5SPRVROM_BANK1(uint32 A,uint32 V)
+{
+ if(CHRptr[0])
+ {
+ V&=CHRmask1[0];
+ MMC5SPRVPage[(A)>>10]=&CHRptr[0][(V)<<10]-(A);
+ }
+}
+
+static INLINE void MMC5BGVROM_BANK1(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask1[0];MMC5BGVPage[(A)>>10]=&CHRptr[0][(V)<<10]-(A);}}
+
+static INLINE void MMC5SPRVROM_BANK2(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask2[0];MMC5SPRVPage[(A)>>10]=MMC5SPRVPage[((A)>>10)+1]=&CHRptr[0][(V)<<11]-(A);}}
+static INLINE void MMC5BGVROM_BANK2(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask2[0];MMC5BGVPage[(A)>>10]=MMC5BGVPage[((A)>>10)+1]=&CHRptr[0][(V)<<11]-(A);}}
+
+static INLINE void MMC5SPRVROM_BANK4(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask4[0];MMC5SPRVPage[(A)>>10]=MMC5SPRVPage[((A)>>10)+1]= MMC5SPRVPage[((A)>>10)+2]=MMC5SPRVPage[((A)>>10)+3]=&CHRptr[0][(V)<<12]-(A);}}
+static INLINE void MMC5BGVROM_BANK4(uint32 A,uint32 V) {if(CHRptr[0]){V&=CHRmask4[0];MMC5BGVPage[(A)>>10]=MMC5BGVPage[((A)>>10)+1]=MMC5BGVPage[((A)>>10)+2]=MMC5BGVPage[((A)>>10)+3]=&CHRptr[0][(V)<<12]-(A);}}
+
+static INLINE void MMC5SPRVROM_BANK8(uint32 V) {if(CHRptr[0]){V&=CHRmask8[0];MMC5SPRVPage[0]=MMC5SPRVPage[1]=MMC5SPRVPage[2]=MMC5SPRVPage[3]=MMC5SPRVPage[4]=MMC5SPRVPage[5]=MMC5SPRVPage[6]=MMC5SPRVPage[7]=&CHRptr[0][(V)<<13];}}
+static INLINE void MMC5BGVROM_BANK8(uint32 V) {if(CHRptr[0]){V&=CHRmask8[0];MMC5BGVPage[0]=MMC5BGVPage[1]=MMC5BGVPage[2]=MMC5BGVPage[3]=MMC5BGVPage[4]=MMC5BGVPage[5]=MMC5BGVPage[6]=MMC5BGVPage[7]=&CHRptr[0][(V)<<13];}}
+
+static uint8 PRGBanks[4];
+static uint8 WRAMPage;
+static uint8 CHRBanksA[8], CHRBanksB[4];
+static uint8 WRAMMaskEnable[2];
+static uint8 ABMode; /* A=0, B=1 */
+
+static uint8 IRQScanline,IRQEnable;
+static uint8 CHRMode, NTAMirroring, NTFill, ATFill;
+
+static uint8 MMC5IRQR;
+static uint8 MMC5LineCounter;
+static uint8 mmc5psize, mmc5vsize;
+static uint8 mul[2];
+
+static uint8 *WRAM=NULL;
+static uint8 *MMC5fill=NULL;
+static uint8 *ExRAM=NULL;
+
+static uint8 MMC5WRAMsize;
+static uint8 MMC5WRAMIndex[8];
+
+static uint8 MMC5ROMWrProtect[4];
+static uint8 MMC5MemIn[5];
+
+static void MMC5CHRA(void);
+static void MMC5CHRB(void);
+
+typedef struct __cartdata {
+ uint32 crc32;
+ uint8 size;
+} cartdata;
+
+
+// ETROM seems to have 16KB of WRAM, ELROM seems to have 8KB
+// EWROM seems to have 32KB of WRAM
+
+#define MMC5_NOCARTS 14
+cartdata MMC5CartList[MMC5_NOCARTS]=
+{
+ {0x9c18762b,2}, /* L'Empereur */
+ {0x26533405,2},
+ {0x6396b988,2},
+
+ {0xaca15643,2}, /* Uncharted Waters */
+ {0xfe3488d1,2}, /* Dai Koukai Jidai */
+
+ {0x15fe6d0f,2}, /* BKAC */
+ {0x39f2ce4b,2}, /* Suikoden */
+
+ {0x8ce478db,2}, /* Nobunaga's Ambition 2 */
+ {0xeee9a682,2},
+
+ {0x1ced086f,2}, /* Ishin no Arashi */
+
+ {0xf540677b,4}, /* Nobunaga...Bushou Fuuun Roku */
+
+ {0x6f4e4312,4}, /* Aoki Ookami..Genchou */
+
+ {0xf011e490,4}, /* Romance of the 3 Kingdoms 2 */
+ {0x184c2124,4}, /* Sangokushi 2 */
+};
+
+
+int DetectMMC5WRAMSize(uint32 crc32)
+{
+ int x;
+ for(x=0;x<MMC5_NOCARTS;x++)
+ if(crc32==MMC5CartList[x].crc32)
+ {
+ FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n");
+ return(MMC5CartList[x].size*8);
+ }
+ return(8);
+}
+
+static void BuildWRAMSizeTable(void)
+{
+ int x;
+ for(x=0;x<8;x++)
+ {
+ switch(MMC5WRAMsize)
+ {
+ case 0: MMC5WRAMIndex[x]=255; break;
+ case 1: MMC5WRAMIndex[x]=(x>3)?255:0; break;
+ case 2: MMC5WRAMIndex[x]=(x&4)>>2; break;
+ case 4: MMC5WRAMIndex[x]=(x>3)?255:(x&3); break;
+ }
+ }
+}
+
+static void MMC5CHRA(void)
+{
+ int x;
+ switch(mmc5vsize&3)
+ {
+ case 0: setchr8(CHRBanksA[7]);
+ MMC5SPRVROM_BANK8(CHRBanksA[7]);
+ break;
+ case 1: setchr4(0x0000,CHRBanksA[3]);
+ setchr4(0x1000,CHRBanksA[7]);
+ MMC5SPRVROM_BANK4(0x0000,CHRBanksA[3]);
+ MMC5SPRVROM_BANK4(0x1000,CHRBanksA[7]);
+ break;
+ case 2: setchr2(0x0000,CHRBanksA[1]);
+ setchr2(0x0800,CHRBanksA[3]);
+ setchr2(0x1000,CHRBanksA[5]);
+ setchr2(0x1800,CHRBanksA[7]);
+ MMC5SPRVROM_BANK2(0x0000,CHRBanksA[1]);
+ MMC5SPRVROM_BANK2(0x0800,CHRBanksA[3]);
+ MMC5SPRVROM_BANK2(0x1000,CHRBanksA[5]);
+ MMC5SPRVROM_BANK2(0x1800,CHRBanksA[7]);
+ break;
+ case 3: for(x=0;x<8;x++)
+ {
+ setchr1(x<<10,CHRBanksA[x]);
+ MMC5SPRVROM_BANK1(x<<10,CHRBanksA[x]);
+ }
+ break;
+ }
+}
+
+static void MMC5CHRB(void)
+{
+ int x;
+ switch(mmc5vsize&3)
+ {
+ case 0: setchr8(CHRBanksB[3]);
+ MMC5BGVROM_BANK8(CHRBanksB[3]);
+ break;
+ case 1: setchr4(0x0000,CHRBanksB[3]);
+ setchr4(0x1000,CHRBanksB[3]);
+ MMC5BGVROM_BANK4(0x0000,CHRBanksB[3]);
+ MMC5BGVROM_BANK4(0x1000,CHRBanksB[3]);
+ break;
+ case 2: setchr2(0x0000,CHRBanksB[1]);
+ setchr2(0x0800,CHRBanksB[3]);
+ setchr2(0x1000,CHRBanksB[1]);
+ setchr2(0x1800,CHRBanksB[3]);
+ MMC5BGVROM_BANK2(0x0000,CHRBanksB[1]);
+ MMC5BGVROM_BANK2(0x0800,CHRBanksB[3]);
+ MMC5BGVROM_BANK2(0x1000,CHRBanksB[1]);
+ MMC5BGVROM_BANK2(0x1800,CHRBanksB[3]);
+ break;
+ case 3: for(x=0;x<8;x++)
+ {
+ setchr1(x<<10,CHRBanksB[x&3]);
+ MMC5BGVROM_BANK1(x<<10,CHRBanksB[x&3]);
+ }
+ break;
+ }
+}
+
+static void FASTAPASS(2) MMC5WRAM(uint32 A, uint32 V)
+{
+ //printf("%02x\n",V);
+ V=MMC5WRAMIndex[V&7];
+ if(V!=255)
+ {
+ setprg8r(0x10,A,V);
+ MMC5MemIn[(A-0x6000)>>13]=1;
+ }
+ else
+ MMC5MemIn[(A-0x6000)>>13]=0;
+}
+
+static void MMC5PRG(void)
+{
+ int x;
+ switch(mmc5psize&3)
+ {
+ case 0: MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=
+ MMC5ROMWrProtect[2]=MMC5ROMWrProtect[3]=1;
+ setprg32(0x8000,((PRGBanks[1]&0x7F)>>2));
+ for(x=0;x<4;x++)
+ MMC5MemIn[1+x]=1;
+ break;
+ case 1: if(PRGBanks[1]&0x80)
+ {
+ MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=1;
+ setprg16(0x8000,(PRGBanks[1]>>1));
+ MMC5MemIn[1]=MMC5MemIn[2]=1;
+ }
+ else
+ {
+ MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=0;
+ MMC5WRAM(0x8000,PRGBanks[1]&7&0xFE);
+ MMC5WRAM(0xA000,(PRGBanks[1]&7&0xFE)+1);
+ }
+ MMC5MemIn[3]=MMC5MemIn[4]=1;
+ MMC5ROMWrProtect[2]=MMC5ROMWrProtect[3]=1;
+ setprg16(0xC000,(PRGBanks[3]&0x7F)>>1);
+ break;
+ case 2: if(PRGBanks[1]&0x80)
+ {
+ MMC5MemIn[1]=MMC5MemIn[2]=1;
+ MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=1;
+ setprg16(0x8000,(PRGBanks[1]&0x7F)>>1);
+ }
+ else
+ {
+ MMC5ROMWrProtect[0]=MMC5ROMWrProtect[1]=0;
+ MMC5WRAM(0x8000,PRGBanks[1]&7&0xFE);
+ MMC5WRAM(0xA000,(PRGBanks[1]&7&0xFE)+1);
+ }
+ if(PRGBanks[2]&0x80)
+ {
+ MMC5ROMWrProtect[2]=1;
+ MMC5MemIn[3]=1;
+ setprg8(0xC000,PRGBanks[2]&0x7F);
+ }
+ else
+ {
+ MMC5ROMWrProtect[2]=0;
+ MMC5WRAM(0xC000,PRGBanks[2]&7);
+ }
+ MMC5MemIn[4]=1;
+ MMC5ROMWrProtect[3]=1;
+ setprg8(0xE000,PRGBanks[3]&0x7F);
+ break;
+ case 3: for(x=0;x<3;x++)
+ if(PRGBanks[x]&0x80)
+ {
+ MMC5ROMWrProtect[x]=1;
+ setprg8(0x8000+(x<<13),PRGBanks[x]&0x7F);
+ MMC5MemIn[1+x]=1;
+ }
+ else
+ {
+ MMC5ROMWrProtect[x]=0;
+ MMC5WRAM(0x8000+(x<<13),PRGBanks[x]&7);
+ }
+ MMC5MemIn[4]=1;
+ MMC5ROMWrProtect[3]=1;
+ setprg8(0xE000,PRGBanks[3]&0x7F);
+ break;
+ }
+}
+
+static DECLFW(Mapper5_write)
+{
+ if(A>=0x5120&&A<=0x5127)
+ {
+ ABMode = 0;
+ CHRBanksA[A&7]=V;
+ MMC5CHRA();
+ }
+ else switch(A)
+ {
+ case 0x5105: {
+ int x;
+ for(x=0;x<4;x++)
+ {
+ switch((V>>(x<<1))&3)
+ {
+ case 0:PPUNTARAM|=1<<x;vnapage[x]=NTARAM;break;
+ case 1:PPUNTARAM|=1<<x;vnapage[x]=NTARAM+0x400;break;
+ case 2:PPUNTARAM|=1<<x;vnapage[x]=ExRAM;break;
+ case 3:PPUNTARAM&=~(1<<x);vnapage[x]=MMC5fill;break;
+ }
+ }
+ }
+ NTAMirroring=V;
+ break;
+ case 0x5113: WRAMPage=V;MMC5WRAM(0x6000,V&7);break;
+ case 0x5100: mmc5psize=V;MMC5PRG();break;
+ case 0x5101: mmc5vsize=V;
+ if(!ABMode)
+ { MMC5CHRB();MMC5CHRA();}
+ else
+ { MMC5CHRA();MMC5CHRB();}
+ break;
+ case 0x5114:
+ case 0x5115:
+ case 0x5116:
+ case 0x5117: PRGBanks[A&3]=V;MMC5PRG();break;
+ case 0x5128:
+ case 0x5129:
+ case 0x512a:
+ case 0x512b: ABMode=1;
+ CHRBanksB[A&3]=V;
+ MMC5CHRB();
+ break;
+ case 0x5102: WRAMMaskEnable[0]=V;break;
+ case 0x5103: WRAMMaskEnable[1]=V;break;
+ case 0x5104: CHRMode=V;MMC5HackCHRMode=V&3;break;
+ case 0x5106: if(V!=NTFill)
+ {
+ uint32 t;
+ t=V|(V<<8)|(V<<16)|(V<<24);
+ FCEU_dwmemset(MMC5fill,t,0x3c0);
+ }
+ NTFill=V;
+ break;
+ case 0x5107: if(V!=ATFill)
+ {
+ unsigned char moop;
+ uint32 t;
+ moop=V|(V<<2)|(V<<4)|(V<<6);
+ t=moop|(moop<<8)|(moop<<16)|(moop<<24);
+ FCEU_dwmemset(MMC5fill+0x3c0,t,0x40);
+ }
+ ATFill=V;
+ break;
+ case 0x5200: MMC5HackSPMode=V;break;
+ case 0x5201: MMC5HackSPScroll=(V>>3)&0x1F;break;
+ case 0x5202: MMC5HackSPPage=V&0x3F;break;
+ case 0x5203: X6502_IRQEnd(FCEU_IQEXT);IRQScanline=V;break;
+ case 0x5204: X6502_IRQEnd(FCEU_IQEXT);IRQEnable=V&0x80;break;
+ case 0x5205: mul[0]=V;break;
+ case 0x5206: mul[1]=V;break;
+ }
+}
+
+static DECLFR(MMC5_ReadROMRAM)
+{
+ if(MMC5MemIn[(A-0x6000)>>13])
+ return Page[A>>11][A];
+ else
+ return X.DB;
+}
+
+static DECLFW(MMC5_WriteROMRAM)
+{
+ if(A>=0x8000)
+ if(MMC5ROMWrProtect[(A-0x8000)>>13]) return;
+ if(MMC5MemIn[(A-0x6000)>>13])
+ if(((WRAMMaskEnable[0]&3)|((WRAMMaskEnable[1]&3)<<2)) == 6) Page[A>>11][A]=V;
+}
+
+static DECLFW(MMC5_ExRAMWr)
+{
+ if(MMC5HackCHRMode!=3)
+ ExRAM[A&0x3ff]=V;
+}
+
+static DECLFR(MMC5_ExRAMRd)
+{
+ /* Not sure if this is correct, so I'll comment it out for now. */
+ //if(MMC5HackCHRMode>=2)
+ return ExRAM[A&0x3ff];
+ //else
+ // return(X.DB);
+}
+
+static DECLFR(MMC5_read)
+{
+ switch(A)
+ {
+ case 0x5204: X6502_IRQEnd(FCEU_IQEXT);
+ {
+ uint8 x;
+ x=MMC5IRQR;
+ if(!fceuindbg)
+ MMC5IRQR&=0x40;
+ return x;
+ }
+ case 0x5205: return (mul[0]*mul[1]);
+ case 0x5206: return ((mul[0]*mul[1])>>8);
+ }
+ return(X.DB);
+}
+
+void MMC5Synco(void)
+{
+ int x;
+
+ MMC5PRG();
+ for(x=0;x<4;x++)
+ {
+ switch((NTAMirroring>>(x<<1))&3)
+ {
+ case 0:PPUNTARAM|=1<<x;vnapage[x]=NTARAM;break;
+ case 1:PPUNTARAM|=1<<x;vnapage[x]=NTARAM+0x400;break;
+ case 2:PPUNTARAM|=1<<x;vnapage[x]=ExRAM;break;
+ case 3:PPUNTARAM&=~(1<<x);vnapage[x]=MMC5fill;break;
+ }
+ }
+ MMC5WRAM(0x6000,WRAMPage&7);
+ if(!ABMode)
+ {
+ MMC5CHRB();
+ MMC5CHRA();
+ }
+ else
+ {
+ MMC5CHRA();
+ MMC5CHRB();
+ }
+ {
+ uint32 t;
+ t=NTFill|(NTFill<<8)|(NTFill<<16)|(NTFill<<24);
+ FCEU_dwmemset(MMC5fill,t,0x3c0);
+ }
+ {
+ unsigned char moop;
+ uint32 t;
+ moop=ATFill|(ATFill<<2)|(ATFill<<4)|(ATFill<<6);
+ t=moop|(moop<<8)|(moop<<16)|(moop<<24);
+ FCEU_dwmemset(MMC5fill+0x3c0,t,0x40);
+ }
+ X6502_IRQEnd(FCEU_IQEXT);
+ MMC5HackCHRMode=CHRMode&3;
+}
+
+void MMC5_hb(int scanline)
+{
+ if(scanline==240)
+ {
+ MMC5LineCounter=0;
+ MMC5IRQR=0x40;
+ return;
+ }
+ if(MMC5LineCounter<240)
+ {
+ if(MMC5LineCounter==IRQScanline)
+ {
+ MMC5IRQR|=0x80;
+ if(IRQEnable&0x80)
+ X6502_IRQBegin(FCEU_IQEXT);
+ }
+ MMC5LineCounter++;
+ }
+ if(MMC5LineCounter==240)
+ MMC5IRQR=0;
+}
+
+void MMC5_StateRestore(int version)
+{
+ MMC5Synco();
+}
+
+typedef struct {
+ uint16 wl[2];
+ uint8 env[2];
+ uint8 enable;
+ uint8 running;
+ uint8 raw;
+ uint8 rawcontrol;
+ int32 dcount[2];
+ int32 BC[3];
+ int32 vcount[2];
+} MMC5APU;
+
+static MMC5APU MMC5Sound;
+
+
+static void Do5PCM()
+{
+ int32 V;
+ int32 start,end;
+
+ start=MMC5Sound.BC[2];
+ end=(SOUNDTS<<16)/soundtsinc;
+ if(end<=start) return;
+ MMC5Sound.BC[2]=end;
+
+ if(!(MMC5Sound.rawcontrol&0x40) && MMC5Sound.raw)
+ for(V=start;V<end;V++)
+ Wave[V>>4]+=MMC5Sound.raw<<1;
+}
+
+static void Do5PCMHQ()
+{
+ int32 V;
+ if(!(MMC5Sound.rawcontrol&0x40) && MMC5Sound.raw)
+ for(V=MMC5Sound.BC[2];V<SOUNDTS;V++)
+ WaveHi[V]+=MMC5Sound.raw<<5;
+ MMC5Sound.BC[2]=SOUNDTS;
+}
+
+
+static DECLFW(Mapper5_SW)
+{
+ A&=0x1F;
+
+ GameExpSound.Fill=MMC5RunSound;
+ GameExpSound.HiFill=MMC5RunSoundHQ;
+
+ switch(A)
+ {
+ case 0x10:if(psfun) psfun();MMC5Sound.rawcontrol=V;break;
+ case 0x11:if(psfun) psfun();MMC5Sound.raw=V;break;
+
+ case 0x0:
+ case 0x4://printf("%04x:$%02x\n",A,V&0x30);
+ if(sfun) sfun(A>>2);
+ MMC5Sound.env[A>>2]=V;
+ break;
+ case 0x2:
+ case 0x6: if(sfun) sfun(A>>2);
+ MMC5Sound.wl[A>>2]&=~0x00FF;
+ MMC5Sound.wl[A>>2]|=V&0xFF;
+ break;
+ case 0x3:
+ case 0x7://printf("%04x:$%02x\n",A,V>>3);
+ MMC5Sound.wl[A>>2]&=~0x0700;
+ MMC5Sound.wl[A>>2]|=(V&0x07)<<8;
+ MMC5Sound.running|=1<<(A>>2);
+ break;
+ case 0x15:if(sfun)
+ {
+ sfun(0);
+ sfun(1);
+ }
+ MMC5Sound.running&=V;
+ MMC5Sound.enable=V;
+ //printf("%02x\n",V);
+ break;
+ }
+}
+
+static void Do5SQ(int P)
+{
+ static int tal[4]={1,2,4,6};
+ int32 V,amp,rthresh,wl;
+ int32 start,end;
+
+ start=MMC5Sound.BC[P];
+ end=(SOUNDTS<<16)/soundtsinc;
+ if(end<=start) return;
+ MMC5Sound.BC[P]=end;
+
+ wl=MMC5Sound.wl[P]+1;
+ amp=(MMC5Sound.env[P]&0xF)<<4;
+ rthresh=tal[(MMC5Sound.env[P]&0xC0)>>6];
+
+ if(wl>=8 && (MMC5Sound.running&(P+1)))
+ {
+ int dc,vc;
+
+ wl<<=18;
+ dc=MMC5Sound.dcount[P];
+ vc=MMC5Sound.vcount[P];
+
+ for(V=start;V<end;V++)
+ {
+ if(dc<rthresh)
+ Wave[V>>4]+=amp;
+ vc-=nesincsize;
+ while(vc<=0)
+ {
+ vc+=wl;
+ dc=(dc+1)&7;
+ }
+ }
+ MMC5Sound.dcount[P]=dc;
+ MMC5Sound.vcount[P]=vc;
+ }
+}
+
+static void Do5SQHQ(int P)
+{
+ static int tal[4]={1,2,4,6};
+ int32 V,amp,rthresh,wl;
+
+ wl=MMC5Sound.wl[P]+1;
+ amp=((MMC5Sound.env[P]&0xF)<<8);
+ rthresh=tal[(MMC5Sound.env[P]&0xC0)>>6];
+
+ if(wl>=8 && (MMC5Sound.running&(P+1)))
+ {
+ int dc,vc;
+
+ wl<<=1;
+
+ dc=MMC5Sound.dcount[P];
+ vc=MMC5Sound.vcount[P];
+ for(V=MMC5Sound.BC[P];V<SOUNDTS;V++)
+ {
+ if(dc<rthresh)
+ WaveHi[V]+=amp;
+ vc--;
+ if(vc<=0) /* Less than zero when first started. */
+ {
+ vc=wl;
+ dc=(dc+1)&7;
+ }
+ }
+ MMC5Sound.dcount[P]=dc;
+ MMC5Sound.vcount[P]=vc;
+ }
+ MMC5Sound.BC[P]=SOUNDTS;
+}
+
+void MMC5RunSoundHQ(void)
+{
+ Do5SQHQ(0);
+ Do5SQHQ(1);
+ Do5PCMHQ();
+}
+
+void MMC5HiSync(int32 ts)
+{
+ int x;
+ for(x=0;x<3;x++) MMC5Sound.BC[x]=ts;
+}
+
+void MMC5RunSound(int Count)
+{
+ int x;
+ Do5SQ(0);
+ Do5SQ(1);
+ Do5PCM();
+ for(x=0;x<3;x++)
+ MMC5Sound.BC[x]=Count;
+}
+
+void Mapper5_ESI(void)
+{
+ GameExpSound.RChange=Mapper5_ESI;
+ if(FSettings.SndRate)
+ {
+ if(FSettings.soundq>=1)
+ {
+ sfun=Do5SQHQ;
+ psfun=Do5PCMHQ;
+ }
+ else
+ {
+ sfun=Do5SQ;
+ psfun=Do5PCM;
+ }
+ }
+ else
+ {
+ sfun=0;
+ psfun=0;
+ }
+ memset(MMC5Sound.BC,0,sizeof(MMC5Sound.BC));
+ memset(MMC5Sound.vcount,0,sizeof(MMC5Sound.vcount));
+ GameExpSound.HiSync=MMC5HiSync;
+}
+
+void NSFMMC5_Init(void)
+{
+ memset(&MMC5Sound,0,sizeof(MMC5Sound));
+ mul[0]=mul[1]=0;
+ ExRAM=(uint8*)FCEU_gmalloc(1024);
+ Mapper5_ESI();
+ SetWriteHandler(0x5c00,0x5fef,MMC5_ExRAMWr);
+ SetReadHandler(0x5c00,0x5fef,MMC5_ExRAMRd);
+ MMC5HackCHRMode=2;
+ SetWriteHandler(0x5000,0x5015,Mapper5_SW);
+ SetWriteHandler(0x5205,0x5206,Mapper5_write);
+ SetReadHandler(0x5205,0x5206,MMC5_read);
+}
+
+void NSFMMC5_Close(void)
+{
+ FCEU_gfree(ExRAM);
+ ExRAM=0;
+}
+
+static void GenMMC5Reset(void)
+{
+ int x;
+
+ for(x=0;x<4;x++) PRGBanks[x]=~0;
+ for(x=0;x<8;x++) CHRBanksA[x]=~0;
+ for(x=0;x<4;x++) CHRBanksB[x]=~0;
+ WRAMMaskEnable[0]=WRAMMaskEnable[1]=~0;
+
+ mmc5psize=mmc5vsize=3;
+ CHRMode=0;
+
+ NTAMirroring=NTFill=ATFill=0xFF;
+
+ MMC5Synco();
+
+ SetWriteHandler(0x4020,0x5bff,Mapper5_write);
+ SetReadHandler(0x4020,0x5bff,MMC5_read);
+
+ SetWriteHandler(0x5c00,0x5fff,MMC5_ExRAMWr);
+ SetReadHandler(0x5c00,0x5fff,MMC5_ExRAMRd);
+
+ SetWriteHandler(0x6000,0xFFFF,MMC5_WriteROMRAM);
+ SetReadHandler(0x6000,0xFFFF,MMC5_ReadROMRAM);
+
+ SetWriteHandler(0x5000,0x5015,Mapper5_SW);
+ SetWriteHandler(0x5205,0x5206,Mapper5_write);
+ SetReadHandler(0x5205,0x5206,MMC5_read);
+
+ //GameHBIRQHook=MMC5_hb;
+ FCEU_CheatAddRAM(8,0x6000,WRAM);
+ FCEU_CheatAddRAM(1,0x5c00,ExRAM);
+}
+
+static SFORMAT MMC5_StateRegs[]={
+ { PRGBanks, 4, "PRGB"},
+ { CHRBanksA, 8, "CHRA"},
+ { CHRBanksB, 4, "CHRB"},
+ { &WRAMPage, 1, "WRMP"},
+ { WRAMMaskEnable, 2, "WRME"},
+ { &ABMode, 1, "ABMD"},
+ { &IRQScanline, 1, "IRQS"},
+ { &IRQEnable, 1, "IRQE"},
+ { &CHRMode, 1, "CHRM"},
+ { &NTAMirroring, 1, "NTAM"},
+ { &NTFill, 1, "NTFL"},
+ { &ATFill, 1, "ATFL"},
+
+ { &MMC5Sound.wl[0], 2|FCEUSTATE_RLSB, "SDW0"},
+ { &MMC5Sound.wl[1], 2|FCEUSTATE_RLSB, "SDW1"},
+ { MMC5Sound.env, 2, "SDEV"},
+ { &MMC5Sound.enable, 1, "SDEN"},
+ { &MMC5Sound.running, 1, "SDRU"},
+ { &MMC5Sound.raw, 1, "SDRW"},
+ { &MMC5Sound.rawcontrol, 1, "SDRC"},
+ {0}
+};
+
+static void GenMMC5_Init(CartInfo *info, int wsize, int battery)
+{
+ if(wsize)
+ {
+ WRAM=(uint8*)FCEU_gmalloc(wsize*1024);
+ SetupCartPRGMapping(0x10,WRAM,wsize*1024,1);
+ AddExState(WRAM, wsize*1024, 0, "WRAM");
+ }
+
+ MMC5fill=(uint8*)FCEU_gmalloc(1024);
+ ExRAM=(uint8*)FCEU_gmalloc(1024);
+
+ AddExState(MMC5_StateRegs, ~0, 0, 0);
+ AddExState(WRAM, wsize*1024, 0, "WRAM");
+ AddExState(ExRAM, 1024, 0, "ERAM");
+ AddExState(&MMC5HackSPMode, 1, 0, "SPLM");
+ AddExState(&MMC5HackSPScroll, 1, 0, "SPLS");
+ AddExState(&MMC5HackSPPage, 1, 0, "SPLP");
+
+ MMC5WRAMsize=wsize/8;
+ BuildWRAMSizeTable();
+ GameStateRestore=MMC5_StateRestore;
+ info->Power=GenMMC5Reset;
+
+ if(battery)
+ {
+ info->SaveGame[0]=WRAM;
+ if(wsize<=16)
+ info->SaveGameLen[0]=8192;
+ else
+ info->SaveGameLen[0]=32768;
+ }
+
+ MMC5HackVROMMask=CHRmask4[0];
+ MMC5HackExNTARAMPtr=ExRAM;
+ MMC5Hack=1;
+ MMC5HackVROMPTR=CHRptr[0];
+ MMC5HackCHRMode=0;
+ MMC5HackSPMode=MMC5HackSPScroll=MMC5HackSPPage=0;
+ Mapper5_ESI();
+}
+
+void Mapper5_Init(CartInfo *info)
+{
+ GenMMC5_Init(info, DetectMMC5WRAMSize(info->CRC32), info->battery);
+}
+
+// ELROM seems to have 0KB of WRAM
+// EKROM seems to have 8KB of WRAM
+// ETROM seems to have 16KB of WRAM
+// EWROM seems to have 32KB of WRAM
+
+// ETROM and EWROM are battery-backed, EKROM isn't.
+
+void ETROM_Init(CartInfo *info)
+{
+ GenMMC5_Init(info, 16,info->battery);
+}
+
+void ELROM_Init(CartInfo *info)
+{
+ GenMMC5_Init(info,0,0);
+}
+
+void EWROM_Init(CartInfo *info)
+{
+ GenMMC5_Init(info,32,info->battery);
+}
+
+void EKROM_Init(CartInfo *info)
+{
+ GenMMC5_Init(info,8,info->battery);
+}
diff --git a/boards/n106.c b/boards/n106.c
new file mode 100644
index 00000000..311cacb4
--- /dev/null
+++ b/boards/n106.c
@@ -0,0 +1,469 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint16 IRQCount;
+static uint8 IRQa;
+
+static uint8 WRAM[8192];
+static uint8 IRAM[128];
+
+static DECLFR(AWRAM)
+{
+ return(WRAM[A-0x6000]);
+}
+
+static DECLFW(BWRAM)
+{
+ WRAM[A-0x6000]=V;
+}
+
+void Mapper19_ESI(void);
+
+static uint8 NTAPage[4];
+
+static uint8 dopol;
+static uint8 gorfus;
+static uint8 gorko;
+
+static void NamcoSound(int Count);
+static void NamcoSoundHack(void);
+static void DoNamcoSound(int32 *Wave, int Count);
+static void DoNamcoSoundHQ(void);
+static void SyncHQ(int32 ts);
+
+static int is210; /* Lesser mapper. */
+
+static uint8 PRG[3];
+static uint8 CHR[8];
+
+static SFORMAT N106_StateRegs[]={
+ {PRG,3,"PRG"},
+ {CHR,8,"CHR"},
+ {NTAPage,4,"NTA"},
+ {0}
+};
+
+static void SyncPRG(void)
+{
+ setprg8(0x8000,PRG[0]);
+ setprg8(0xa000,PRG[1]);
+ setprg8(0xc000,PRG[2]);
+ setprg8(0xe000,0x3F);
+}
+
+static void FP_FASTAPASS(1) NamcoIRQHook(int a)
+{
+ if(IRQa)
+ {
+ IRQCount+=a;
+ if(IRQCount>=0x7FFF)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ IRQa=0;
+ IRQCount=0x7FFF; //7FFF;
+ }
+ }
+}
+
+static DECLFR(Namco_Read4800)
+{
+ uint8 ret=IRAM[dopol&0x7f];
+ /* Maybe I should call NamcoSoundHack() here? */
+ if(!fceuindbg)
+ if(dopol&0x80)
+ dopol=(dopol&0x80)|((dopol+1)&0x7f);
+ return ret;
+}
+
+static DECLFR(Namco_Read5000)
+{
+ return(IRQCount);
+}
+
+static DECLFR(Namco_Read5800)
+{
+ return(IRQCount>>8);
+}
+
+static void FASTAPASS(2) DoNTARAMROM(int w, uint8 V)
+{
+ NTAPage[w]=V;
+ if(V>=0xE0)
+ setntamem(NTARAM+((V&1)<<10), 1, w);
+ else
+ {
+ V&=CHRmask1[0];
+ setntamem(CHRptr[0]+(V<<10), 0, w);
+ }
+}
+
+static void FixNTAR(void)
+{
+ int x;
+ for(x=0;x<4;x++)
+ DoNTARAMROM(x,NTAPage[x]);
+}
+
+static void FASTAPASS(2) DoCHRRAMROM(int x, uint8 V)
+{
+ CHR[x]=V;
+ if(!is210 && !((gorfus>>((x>>2)+6))&1) && (V>=0xE0))
+ {
+ // printf("BLAHAHA: %d, %02x\n",x,V);
+ //setchr1r(0x10,x<<10,V&7);
+ }
+ else
+ setchr1(x<<10,V);
+}
+
+static void FixCRR(void)
+{
+ int x;
+ for(x=0;x<8;x++)
+ DoCHRRAMROM(x,CHR[x]);
+}
+
+static DECLFW(Mapper19C0D8_write)
+{
+ DoNTARAMROM((A-0xC000)>>11,V);
+}
+
+static uint32 FreqCache[8];
+static uint32 EnvCache[8];
+static uint32 LengthCache[8];
+
+static void FixCache(int a,int V)
+{
+ int w=(a>>3)&0x7;
+ switch(a&0x07)
+ {
+ case 0x00:FreqCache[w]&=~0x000000FF;FreqCache[w]|=V;break;
+ case 0x02:FreqCache[w]&=~0x0000FF00;FreqCache[w]|=V<<8;break;
+ case 0x04:FreqCache[w]&=~0x00030000;FreqCache[w]|=(V&3)<<16;
+ LengthCache[w]=(8-((V>>2)&7))<<2;
+ break;
+ case 0x07:EnvCache[w]=(double)(V&0xF)*576716;break;
+ }
+}
+
+static DECLFW(Mapper19_write)
+{
+ A&=0xF800;
+ if(A>=0x8000 && A<=0xb800)
+ DoCHRRAMROM((A-0x8000)>>11,V);
+ else switch(A)
+ {
+ case 0x4800:
+ if(dopol&0x40)
+ {
+ if(FSettings.SndRate)
+ {
+ NamcoSoundHack();
+ GameExpSound.Fill=NamcoSound;
+ GameExpSound.HiFill=DoNamcoSoundHQ;
+ GameExpSound.HiSync=SyncHQ;
+ }
+ FixCache(dopol,V);
+ }
+ IRAM[dopol&0x7f]=V;
+ if(dopol&0x80)
+ dopol=(dopol&0x80)|((dopol+1)&0x7f);
+ break;
+ case 0xf800:
+ dopol=V;break;
+ case 0x5000:
+ IRQCount&=0xFF00;IRQCount|=V;X6502_IRQEnd(FCEU_IQEXT);break;
+ case 0x5800:
+ IRQCount&=0x00ff;IRQCount|=(V&0x7F)<<8;
+ IRQa=V&0x80;
+ X6502_IRQEnd(FCEU_IQEXT);
+ break;
+ case 0xE000:
+ gorko=V&0xC0;
+ PRG[0]=V&0x3F;
+ SyncPRG();
+ break;
+ case 0xE800:
+ gorfus=V&0xC0;
+ FixCRR();
+ PRG[1]=V&0x3F;
+ SyncPRG();
+ break;
+ case 0xF000:
+ PRG[2]=V&0x3F;
+ SyncPRG();
+ break;
+ }
+}
+
+static int dwave=0;
+
+static void NamcoSoundHack(void)
+{
+ int32 z,a;
+ if(FSettings.soundq>=1)
+ {
+ DoNamcoSoundHQ();
+ return;
+ }
+ z=((SOUNDTS<<16)/soundtsinc)>>4;
+ a=z-dwave;
+ if(a) DoNamcoSound(&Wave[dwave], a);
+ dwave+=a;
+}
+
+static void NamcoSound(int Count)
+{
+ int32 z,a;
+ z=((SOUNDTS<<16)/soundtsinc)>>4;
+ a=z-dwave;
+ if(a) DoNamcoSound(&Wave[dwave], a);
+ dwave=0;
+}
+
+static uint32 PlayIndex[8];
+static int32 vcount[8];
+static int32 CVBC;
+
+#define TOINDEX (16+1)
+
+// 16:15
+static void SyncHQ(int32 ts)
+{
+ CVBC=ts;
+}
+
+
+/* Things to do:
+ 1 Read freq low
+ 2 Read freq mid
+ 3 Read freq high
+ 4 Read envelope
+ ...?
+*/
+
+static INLINE uint32 FetchDuff(uint32 P, uint32 envelope)
+{
+ uint32 duff;
+ duff=IRAM[((IRAM[0x46+(P<<3)]+(PlayIndex[P]>>TOINDEX))&0xFF)>>1];
+ if((IRAM[0x46+(P<<3)]+(PlayIndex[P]>>TOINDEX))&1)
+ duff>>=4;
+ duff&=0xF;
+ duff=(duff*envelope)>>16;
+ return(duff);
+}
+
+static void DoNamcoSoundHQ(void)
+{
+ int32 P,V;
+ int32 cyclesuck=(((IRAM[0x7F]>>4)&7)+1)*15;
+
+ for(P=7;P>=(7-((IRAM[0x7F]>>4)&7));P--)
+ {
+ if((IRAM[0x44+(P<<3)]&0xE0) && (IRAM[0x47+(P<<3)]&0xF))
+ {
+ uint32 freq;
+ int32 vco;
+ uint32 duff2,lengo,envelope;
+
+ vco=vcount[P];
+ freq=FreqCache[P];
+ envelope=EnvCache[P];
+ lengo=LengthCache[P];
+
+ duff2=FetchDuff(P,envelope);
+ for(V=CVBC<<1;V<SOUNDTS<<1;V++)
+ {
+ WaveHi[V>>1]+=duff2;
+ if(!vco)
+ {
+ PlayIndex[P]+=freq;
+ while((PlayIndex[P]>>TOINDEX)>=lengo) PlayIndex[P]-=lengo<<TOINDEX;
+ duff2=FetchDuff(P,envelope);
+ vco=cyclesuck;
+ }
+ vco--;
+ }
+ vcount[P]=vco;
+ }
+ }
+ CVBC=SOUNDTS;
+}
+
+
+static void DoNamcoSound(int32 *Wave, int Count)
+{
+ int P,V;
+ for(P=7;P>=7-((IRAM[0x7F]>>4)&7);P--)
+ {
+ if((IRAM[0x44+(P<<3)]&0xE0) && (IRAM[0x47+(P<<3)]&0xF))
+ {
+ int32 inc;
+ uint32 freq;
+ int32 vco;
+ uint32 duff,duff2,lengo,envelope;
+
+ vco=vcount[P];
+ freq=FreqCache[P];
+ envelope=EnvCache[P];
+ lengo=LengthCache[P];
+
+ if(!freq) {/*printf("Ack");*/ continue;}
+
+ {
+ int c=((IRAM[0x7F]>>4)&7)+1;
+ inc=(long double)(FSettings.SndRate<<15)/((long double)freq*21477272/((long double)0x400000*c*45));
+ }
+
+ duff=IRAM[(((IRAM[0x46+(P<<3)]+PlayIndex[P])&0xFF)>>1)];
+ if((IRAM[0x46+(P<<3)]+PlayIndex[P])&1)
+ duff>>=4;
+ duff&=0xF;
+ duff2=(duff*envelope)>>19;
+ for(V=0;V<Count*16;V++)
+ {
+ if(vco>=inc)
+ {
+ PlayIndex[P]++;
+ if(PlayIndex[P]>=lengo)
+ PlayIndex[P]=0;
+ vco-=inc;
+ duff=IRAM[(((IRAM[0x46+(P<<3)]+PlayIndex[P])&0xFF)>>1)];
+ if((IRAM[0x46+(P<<3)]+PlayIndex[P])&1)
+ duff>>=4;
+ duff&=0xF;
+ duff2=(duff*envelope)>>19;
+ }
+ Wave[V>>4]+=duff2;
+ vco+=0x8000;
+ }
+ vcount[P]=vco;
+ }
+ }
+}
+
+static void Mapper19_StateRestore(int version)
+{
+ SyncPRG();
+ FixNTAR();
+ FixCRR();
+ int x;
+ for(x=0x40;x<0x80;x++)
+ FixCache(x,IRAM[x]);
+}
+
+static void M19SC(void)
+{
+ if(FSettings.SndRate)
+ Mapper19_ESI();
+}
+
+void Mapper19_ESI(void)
+{
+ GameExpSound.RChange=M19SC;
+ memset(vcount,0,sizeof(vcount));
+ memset(PlayIndex,0,sizeof(PlayIndex));
+ CVBC=0;
+}
+
+void NSFN106_Init(void)
+{
+ SetWriteHandler(0xf800,0xffff,Mapper19_write);
+ SetWriteHandler(0x4800,0x4fff,Mapper19_write);
+ SetReadHandler(0x4800,0x4fff,Namco_Read4800);
+ Mapper19_ESI();
+}
+
+static int battery=0;
+
+static void N106_Power(void)
+{
+ int x;
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x8000,0xffff,Mapper19_write);
+ SetWriteHandler(0x4020,0x5fff,Mapper19_write);
+ if(!is210)
+ {
+ SetWriteHandler(0xc000,0xdfff,Mapper19C0D8_write);
+ SetReadHandler(0x4800,0x4fff,Namco_Read4800);
+ SetReadHandler(0x5000,0x57ff,Namco_Read5000);
+ SetReadHandler(0x5800,0x5fff,Namco_Read5800);
+ NTAPage[0]=NTAPage[1]=NTAPage[2]=NTAPage[3]=0xFF;
+ FixNTAR();
+ }
+
+ SetReadHandler(0x6000,0x7FFF,AWRAM);
+ SetWriteHandler(0x6000,0x7FFF,BWRAM);
+ FCEU_CheatAddRAM(8,0x6000,WRAM);
+
+ gorfus=0xFF;
+ SyncPRG();
+ FixCRR();
+
+ if(!battery)
+ {
+ FCEU_dwmemset(WRAM,0,8192);
+ FCEU_dwmemset(IRAM,0,128);
+ }
+ for(x=0x40;x<0x80;x++)
+ FixCache(x,IRAM[x]);
+}
+
+void Mapper19_Init(CartInfo *info)
+{
+ is210=0;
+ battery=info->battery;
+ info->Power=N106_Power;
+
+ MapIRQHook=NamcoIRQHook;
+ GameStateRestore=Mapper19_StateRestore;
+ GameExpSound.RChange=M19SC;
+
+ if(FSettings.SndRate)
+ Mapper19_ESI();
+
+ AddExState(WRAM, 8192, 0, "WRAM");
+ AddExState(IRAM, 128, 0, "WRAM");
+ AddExState(N106_StateRegs, ~0, 0, 0);
+
+ if(info->battery)
+ {
+ info->SaveGame[0]=WRAM;
+ info->SaveGameLen[0]=8192;
+ info->SaveGame[1]=IRAM;
+ info->SaveGameLen[1]=128;
+ }
+}
+
+static void Mapper210_StateRestore(int version)
+{
+ SyncPRG();
+ FixCRR();
+}
+
+void Mapper210_Init(CartInfo *info)
+{
+ is210=1;
+ GameStateRestore=Mapper210_StateRestore;
+ info->Power=N106_Power;
+ AddExState(WRAM, 8192, 0, "WRAM");
+}
diff --git a/boards/novel.c b/boards/novel.c
new file mode 100644
index 00000000..26e70ec0
--- /dev/null
+++ b/boards/novel.c
@@ -0,0 +1,55 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint8 latch;
+
+static void DoNovel(void)
+{
+ setprg32(0x8000,latch&3);
+ setchr8(latch&7);
+}
+
+static DECLFW(NovelWrite)
+{
+ latch=A&0xFF;
+ DoNovel();
+}
+
+static void NovelReset(void)
+{
+ SetWriteHandler(0x8000,0xFFFF,NovelWrite);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ setprg32(0x8000,0);
+ setchr8(0);
+}
+
+static void NovelRestore(int version)
+{
+ DoNovel();
+}
+
+void Novel_Init(CartInfo *info)
+{
+ AddExState(&latch, 1, 0,"L1");
+ info->Power=NovelReset;
+ GameStateRestore=NovelRestore;
+}
diff --git a/boards/sachen.c b/boards/sachen.c
new file mode 100644
index 00000000..64ad5f6d
--- /dev/null
+++ b/boards/sachen.c
@@ -0,0 +1,398 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint8 cmd;
+static uint8 latch[8];
+
+static void S74LS374MSync(uint8 mirr)
+{
+ switch(mirr&3)
+ {
+ case 0:setmirror(MI_V);break;
+ case 1:setmirror(MI_H);break;
+ case 2:setmirrorw(0,1,1,1);break;
+ case 3:setmirror(MI_0);break;
+ }
+}
+
+static void S74LS374NSynco(void)
+{
+ setprg32(0x8000,latch[0]);
+ setchr8(latch[1]|latch[3]|latch[4]);
+ S74LS374MSync(latch[2]);
+}
+
+static DECLFW(S74LS374NWrite)
+{
+ A&=0x4101;
+ if(A==0x4100)
+ cmd=V&7;
+ else
+ {
+ switch(cmd)
+ {
+ case 2:latch[0]=V&1; latch[3]=(V&1)<<3;break;
+ case 4:latch[4]=(V&1)<<2;break;
+ case 5:latch[0]=V&7;break;
+ case 6:latch[1]=V&3;break;
+ case 7:latch[2]=V>>1;break;
+ }
+ S74LS374NSynco();
+ }
+}
+
+static DECLFR(S74LS374NRead)
+{
+ uint8 ret;
+ if((A&0x4100)==0x4100)
+ ret=(X.DB&0xC0)|((~cmd)&0x3F);
+ else
+ ret=X.DB;
+ return ret;
+}
+
+static void S74LS374NPower(void)
+{
+ latch[0]=latch[1]=latch[2]=latch[3]=latch[4]=0;
+ S74LS374NSynco();
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x4100,0x7FFF,S74LS374NWrite);
+ SetReadHandler(0x4100,0x5fff,S74LS374NRead);
+}
+
+static void S74LS374NRestore(int version)
+{
+ S74LS374NSynco();
+}
+
+void S74LS374N_Init(CartInfo *info)
+{
+ info->Power=S74LS374NPower;
+ GameStateRestore=S74LS374NRestore;
+ AddExState(latch, 5, 0, "LATC");
+ AddExState(&cmd, 1, 0, "CMD");
+}
+
+static void S74LS374NASynco(void)
+{
+ setprg32(0x8000,latch[0]);
+ setchr8(latch[1]);
+ S74LS374MSync(latch[2]);
+}
+
+static DECLFW(S74LS374NAWrite)
+{
+ A&=0x4101;
+ if(A==0x4100)
+ cmd=V&7;
+ else
+ {
+ switch(cmd)
+ {
+ case 0:latch[0]=0;latch[1]=3;break;
+ case 2:latch[3]=(V&1)<<3;break;
+ case 4:latch[1]=(latch[1]&6)|(V&3);break;
+ case 5:latch[0]=V&1;break;
+ case 6:latch[1]=(latch[1]&1)|latch[3]|((V&3)<<1);break;
+ case 7:latch[2]=V&1;break;
+ }
+ S74LS374NASynco();
+ }
+}
+
+static void S74LS374NAPower(void)
+{
+ latch[0]=latch[2]=latch[3]=latch[4]=0;
+ latch[1]=3;
+ S74LS374NASynco();
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x4100,0x7FFF,S74LS374NAWrite);
+}
+
+void S74LS374NA_Init(CartInfo *info)
+{
+ info->Power=S74LS374NAPower;
+ GameStateRestore=S74LS374NRestore;
+ AddExState(latch, 5, 0, "LATC");
+ AddExState(&cmd, 1, 0, "CMD");
+}
+
+static int type;
+static void S8259Synco(void)
+{
+ int x;
+ setprg32(0x8000,latch[5]&7);
+
+ if(!UNIFchrrama) // No CHR RAM? Then BS'ing is ok.
+ {
+ for(x=0;x<4;x++)
+ {
+ int bank;
+ if(latch[7]&1)
+ bank=(latch[0]&0x7)|((latch[4]&7)<<3);
+ else
+ bank=(latch[x]&0x7)|((latch[4]&7)<<3);
+ switch (type)
+ {
+ case 00: bank=(bank<<1)|(x&1); setchr2(0x800*x,bank); break;
+ case 01: setchr2(0x800*x,bank); break;
+ case 02: bank=(bank<<2)|(x&3); setchr2(0x800*x,bank); break;
+ case 03: bank=latch[x]&7;
+ switch (x&3)
+ {
+ case 01: bank|=(latch[4]&1)<<4;break;
+ case 02: bank|=(latch[4]&2)<<3;break;
+ case 03: bank|=((latch[4]&4)<<2)|((latch[6]&1)<<3);break;
+ }
+ setchr1(0x400*x,bank);
+ setchr4(0x1000,~0);
+ break;
+ }
+ }
+ }
+ if(!(latch[7]&1))
+ S74LS374MSync(latch[7]>>1);
+ else
+ setmirror(MI_V);
+}
+
+static DECLFW(S8259Write)
+{
+ A&=0x4101;
+ if(A==0x4100)
+ cmd=V;
+ else
+ {
+ latch[cmd&7]=V;
+ S8259Synco();
+ }
+}
+
+static void S8259Reset(void)
+{
+ int x;
+ cmd=0;
+
+ for(x=0;x<8;x++) latch[x]=0;
+ setchr8(0);
+
+ S8259Synco();
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x4100,0x7FFF,S8259Write);
+}
+
+static void S8259Restore(int version)
+{
+ S8259Synco();
+}
+
+void S8259A_Init(CartInfo *info) // Kevin's Horton 141 mapper
+{
+ info->Power=S8259Reset;
+ GameStateRestore=S8259Restore;
+ AddExState(latch, 8, 0, "LATC");
+ AddExState(&cmd, 1, 0, "CMD");
+ type=0;
+}
+
+void S8259B_Init(CartInfo *info) // Kevin's Horton 138 mapper
+{
+ info->Power=S8259Reset;
+ GameStateRestore=S8259Restore;
+ AddExState(latch, 8, 0, "LATC");
+ AddExState(&cmd, 1, 0, "CMD");
+ type=1;
+}
+
+void S8259C_Init(CartInfo *info) // Kevin's Horton 139 mapper
+{
+ info->Power=S8259Reset;
+ GameStateRestore=S8259Restore;
+ AddExState(latch, 8, 0, "LATC");
+ AddExState(&cmd, 1, 0, "CMD");
+ type=2;
+}
+
+void S8259D_Init(CartInfo *info) // Kevin's Horton 137 mapper
+{
+ info->Power=S8259Reset;
+ GameStateRestore=S8259Restore;
+ AddExState(latch, 8, 0, "LATC");
+ AddExState(&cmd, 1, 0, "CMD");
+ type=3;
+}
+
+static void(*WSync)(void);
+
+static DECLFW(SAWrite)
+{
+ if(A&0x100)
+ {
+ latch[0]=V;
+ WSync();
+ }
+}
+
+static void SAPower(void)
+{
+ latch[0]=0;
+ WSync();
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x4100,0x5FFF,SAWrite);
+}
+
+static void SARestore(int version)
+{
+ WSync();
+}
+
+static DECLFW(SADWrite)
+{
+ latch[0]=V;
+ WSync();
+}
+
+static void SADPower(void)
+{
+ latch[0]=0;
+ WSync();
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x8000,0xFFFF,SADWrite);
+}
+
+static void SA0161MSynco()
+{
+ setprg32(0x8000,(latch[0]>>3)&1);
+ setchr8(latch[0]&7);
+}
+
+static void SA72007Synco()
+{
+ setprg32(0x8000,0);
+ setchr8(latch[0]>>7);
+}
+
+static void SA72008Synco()
+{
+ setprg32(0x8000,(latch[0]>>2)&1);
+ setchr8(latch[0]&3);
+}
+
+void SA0161M_Init(CartInfo *info)
+{
+ WSync=SA0161MSynco;
+ GameStateRestore=SARestore;
+ info->Power=SAPower;
+ AddExState(&latch[0], 1, 0, "LATC");
+}
+
+void SA72007_Init(CartInfo *info)
+{
+ WSync=SA72007Synco;
+ GameStateRestore=SARestore;
+ info->Power=SAPower;
+ AddExState(&latch[0], 1, 0, "LATC");
+}
+
+void SA72008_Init(CartInfo *info)
+{
+ WSync=SA72008Synco;
+ GameStateRestore=SARestore;
+ info->Power=SAPower;
+ AddExState(&latch[0], 1, 0, "LATC");
+}
+
+void SA0036_Init(CartInfo *info)
+{
+ WSync=SA72007Synco;
+ GameStateRestore=SARestore;
+ info->Power=SADPower;
+ AddExState(&latch[0], 1, 0, "LATC");
+}
+
+void SA0037_Init(CartInfo *info)
+{
+ WSync=SA0161MSynco;
+ GameStateRestore=SARestore;
+ info->Power=SADPower;
+ AddExState(&latch[0], 1, 0, "LATC");
+}
+
+static void TCU01Synco()
+{
+ setprg32(0x8000,(latch[0]>>2)&1);
+ setchr8((latch[0]>>3)&0xF);
+}
+
+static DECLFW(TCWrite)
+{
+ if((A&0x103)==0x102)
+ {
+ latch[0]=V;
+ TCU01Synco();
+ }
+}
+
+static void TCU01Reset(void)
+{
+ latch[0]=0;
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x4100,0xFFFF,TCWrite);
+ TCU01Synco();
+}
+
+static void TCU01Restore(int version)
+{
+ TCU01Synco();
+}
+
+void TCU01_Init(CartInfo *info)
+{
+ GameStateRestore=TCU01Restore;
+ info->Power=TCU01Reset;
+ AddExState(&latch[0], 1, 0, "LATC");
+}
+
+static DECLFR(TCA01Read)
+{
+ uint8 ret;
+ if((A&0x4100)==0x4100)
+ ret=(X.DB&0xC0)|((~A)&0x3F);
+ else
+ ret=X.DB;
+ return ret;
+}
+
+static void TCA01Reset(void)
+{
+ setprg16(0x8000,0);
+ setprg16(0xC000,1);
+ setchr8(0);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetReadHandler(0x4100,0x5FFF,TCA01Read);
+}
+
+void TCA01_Init(CartInfo *info)
+{
+ info->Power=TCA01Reset;
+}
+
diff --git a/boards/sheroes.c b/boards/sheroes.c
new file mode 100644
index 00000000..ac081007
--- /dev/null
+++ b/boards/sheroes.c
@@ -0,0 +1,86 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2006 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+#include "mmc3.h"
+
+static uint8 *CHRRAM;
+static uint8 tekker;
+
+static void MSHCW(uint32 A, uint8 V)
+{
+ if(EXPREGS[0]&0x40)
+ setchr8r(0x10,0);
+ else
+ {
+ if(A<0x800)
+ setchr1(A,V|((EXPREGS[0]&8)<<5));
+ else if(A<0x1000)
+ setchr1(A,V|((EXPREGS[0]&4)<<6));
+ else if(A<0x1800)
+ setchr1(A,V|((EXPREGS[0]&1)<<8));
+ else
+ setchr1(A,V|((EXPREGS[0]&2)<<7));
+ }
+}
+
+static DECLFW(MSHWrite)
+{
+ EXPREGS[0]=V;
+ FixMMC3CHR(MMC3_cmd);
+}
+
+static DECLFR(MSHRead)
+{
+ return(tekker);
+}
+
+static void MSHReset(void)
+{
+ MMC3RegReset();
+ tekker^=0xFF;
+}
+
+static void MSHPower(void)
+{
+ tekker=0x00;
+ GenMMC3Power();
+ SetWriteHandler(0x4100,0x4100,MSHWrite);
+ SetReadHandler(0x4100,0x4100,MSHRead);
+}
+
+static void MSHClose(void)
+{
+ if(CHRRAM)
+ FCEU_gfree(CHRRAM);
+ CHRRAM=NULL;
+}
+
+void UNLSHeroes_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 256, 512, 0, 0);
+ cwrap=MSHCW;
+ info->Power=MSHPower;
+ info->Reset=MSHReset;
+ info->Close=MSHClose;
+ CHRRAM = (uint8*)FCEU_gmalloc(8192);
+ SetupCartCHRMapping(0x10, CHRRAM, 8192, 1);
+ AddExState(EXPREGS, 4, 0, "EXPR");
+}
diff --git a/boards/sl1632.c b/boards/sl1632.c
new file mode 100644
index 00000000..3d0e386a
--- /dev/null
+++ b/boards/sl1632.c
@@ -0,0 +1,159 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint8 chrcmd[8], prg0, prg1, brk, mirr;
+static uint8 reg[8], cmd;
+static uint8 IRQCount,IRQLatch,IRQa;
+static uint8 IRQReload;
+static SFORMAT StateRegs[]=
+{
+ {reg, 8, "MMCREG"},
+ {&cmd, 1, "MMCCMD"},
+ {chrcmd, 8, "CHRCMD"},
+ {&prg0, 1, "PRG0"},
+ {&prg1, 1, "PRG1"},
+ {&brk, 1, "BRK"},
+ {&mirr, 1, "MIRR"},
+ {&IRQReload, 1, "IRQR"},
+ {&IRQCount, 1, "IRQC"},
+ {&IRQLatch, 1, "IRQL"},
+ {&IRQa, 1, "IRQA"},
+ {0}
+};
+
+static void Sync(void)
+{
+// if(brk&2)
+// {
+// setprg16(0x8000,~0);
+// setprg16(0xC000,~0);
+// }
+// else
+ {
+ setprg8(0x8000,prg0);
+ setprg8(0xA000,prg1);
+ }
+ int i;
+ for(i=0; i<8; i++)
+ setchr1(i<<10,chrcmd[i]);
+ setmirror(mirr^1);
+}
+
+static void Sync2(void)
+{
+ setprg8(0x8000,reg[6]&0x3F);
+ setprg8(0xA000,reg[7]&0x3F);
+ setchr2(0x0000,reg[0]>>1);
+ setchr2(0x8000,reg[1]>>1);
+ setchr1(0x1000,reg[2]);
+ setchr1(0x1400,reg[3]);
+ setchr1(0x1800,reg[4]);
+ setchr1(0x1C00,reg[5]);
+ setmirror(mirr^1);
+}
+
+static DECLFW(UNLSL1632CMDWrite)
+{
+ FCEU_printf("bs %04x %02x\n",A,V);
+// if((A&0xA131)==0xA131) brk=V;
+ if((A&0xA131)==0xA131) brk=V;
+ if(brk==2)
+ {
+ switch(A&0xE001)
+ {
+ case 0x8000: cmd=V&7; break;
+ case 0x8001: reg[cmd]=V; Sync(); break;
+ case 0xA000: mirr=V&1; break;
+ case 0xC000: IRQLatch=V; break;
+ case 0xC001: IRQReload=1; break;
+ case 0xE000: X6502_IRQEnd(FCEU_IQEXT); IRQa=0; break;
+ case 0xE001: IRQa=1; break;
+ }
+ Sync2();
+ }
+ else
+ {
+ switch(A&0xF003)
+ {
+ case 0x8000: prg0=V; break;
+ case 0xA000: prg1=V; break;
+ case 0x9000: mirr=V&1; break;
+ case 0xB000: chrcmd[0]=(chrcmd[0]&0xF0)|(V&0x0F); break;
+ case 0xB001: chrcmd[0]=(chrcmd[0]&0x0F)|(V<<4); break;
+ case 0xB002: chrcmd[1]=(chrcmd[1]&0xF0)|(V&0x0F); break;
+ case 0xB003: chrcmd[1]=(chrcmd[1]&0x0F)|(V<<4); break;
+ case 0xC000: chrcmd[2]=(chrcmd[2]&0xF0)|(V&0x0F); break;
+ case 0xC001: chrcmd[2]=(chrcmd[2]&0x0F)|(V<<4); break;
+ case 0xC002: chrcmd[3]=(chrcmd[3]&0xF0)|(V&0x0F); break;
+ case 0xC003: chrcmd[3]=(chrcmd[3]&0x0F)|(V<<4); break;
+ case 0xD000: chrcmd[4]=(chrcmd[4]&0xF0)|(V&0x0F); break;
+ case 0xD001: chrcmd[4]=(chrcmd[4]&0x0F)|(V<<4); break;
+ case 0xD002: chrcmd[5]=(chrcmd[5]&0xF0)|(V&0x0F); break;
+ case 0xD003: chrcmd[5]=(chrcmd[5]&0x0F)|(V<<4); break;
+ case 0xE000: chrcmd[6]=(chrcmd[6]&0xF0)|(V&0x0F); break;
+ case 0xE001: chrcmd[6]=(chrcmd[6]&0x0F)|(V<<4); break;
+ case 0xE002: chrcmd[7]=(chrcmd[7]&0xF0)|(V&0x0F); break;
+ case 0xE003: chrcmd[7]=(chrcmd[7]&0x0F)|(V<<4); break;
+ }
+ Sync();
+ }
+}
+
+static void UNLSL1632IRQHook(void)
+{
+ int count = IRQCount;
+ if((scanline==128)&&IRQa)X6502_IRQBegin(FCEU_IQEXT);
+ if(!count || IRQReload)
+ {
+ IRQCount = IRQLatch;
+ IRQReload = 0;
+ }
+ else
+ IRQCount--;
+ if(!IRQCount)
+ {
+ if(IRQa)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ }
+ }
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+}
+
+static void UNLSL1632Power(void)
+{
+ setprg16(0xC000,~0);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ SetWriteHandler(0x8000,0xFFFF,UNLSL1632CMDWrite);
+}
+
+void UNLSL1632_Init(CartInfo *info)
+{
+ info->Power=UNLSL1632Power;
+ GameHBIRQHook2=UNLSL1632IRQHook;
+ GameStateRestore=StateRestore;
+ AddExState(&StateRegs, ~0, 0, 0);
+}
diff --git a/boards/sonic5.c b/boards/sonic5.c
new file mode 100644
index 00000000..1da341fe
--- /dev/null
+++ b/boards/sonic5.c
@@ -0,0 +1,71 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+#include "mmc3.h"
+
+static uint8 m_perm[8] = {0, 1, 0, 3, 0, 5, 6, 7};
+
+static void UNLSonicPW(uint32 A, uint8 V)
+{
+ if(EXPREGS[0]&0x80)
+ {
+ uint8 bank=EXPREGS[0]&0x1F;
+ if(EXPREGS[0]&0x20)
+ setprg32(0x8000,bank>>2);
+ else
+ {
+ setprg16(0x8000,bank);
+ setprg16(0xC000,bank);
+ }
+ }
+ else
+ setprg8(A,V&0x3F);
+}
+
+static DECLFW(UNLSonicWrite8000)
+{
+ if(V&0x80)
+ MMC3_CMDWrite(A,V);
+ else
+ MMC3_CMDWrite(A,m_perm[V&7]);
+}
+
+static DECLFW(UNLSonicWriteLo)
+{
+ EXPREGS[0]=V;
+ FixMMC3PRG(MMC3_cmd);
+}
+
+static void UNLSonicPower(void)
+{
+ EXPREGS[0]=EXPREGS[1]=EXPREGS[2]=0;
+ GenMMC3Power();
+ SetWriteHandler(0x5000,0x5FFF,UNLSonicWriteLo);
+// SetWriteHandler(0x8000,0x8000,UNLSonicWrite8000);
+}
+
+void UNLSonic_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 256, 256, 0, 0);
+ pwrap=UNLSonicPW;
+ info->Power=UNLSonicPower;
+ AddExState(EXPREGS, 3, 0, "EXPR");
+}
diff --git a/boards/subor.c b/boards/subor.c
new file mode 100644
index 00000000..9f0386db
--- /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
new file mode 100644
index 00000000..745e723e
--- /dev/null
+++ b/boards/super24.c
@@ -0,0 +1,99 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+#include "mmc3.h"
+
+static uint8 *CHRRAM = NULL;
+static int masko8[8]={63,31,15,1,3,0,0,0};
+
+static void Super24PW(uint32 A, uint8 V)
+{
+ uint32 NV=V&masko8[EXPREGS[0]&7];
+ NV|=(EXPREGS[1]<<1);
+ setprg8r((NV>>6)&0xF,A,NV);
+}
+
+static void Super24CW(uint32 A, uint8 V)
+{
+ if(EXPREGS[0]&0x20)
+ setchr1r(0x10,A,V);
+ else
+ {
+ uint32 NV=V|(EXPREGS[2]<<3);
+ setchr1r((NV>>9)&0xF,A,NV);
+ }
+}
+
+static DECLFW(Super24Write)
+{
+ switch(A)
+ {
+ case 0x5FF0: EXPREGS[0]=V;
+ FixMMC3PRG(MMC3_cmd);
+ FixMMC3CHR(MMC3_cmd);
+ break;
+ case 0x5FF1: EXPREGS[1]=V;
+ FixMMC3PRG(MMC3_cmd);
+ break;
+ case 0x5FF2: EXPREGS[2]=V;
+ FixMMC3CHR(MMC3_cmd);
+ break;
+ }
+}
+
+static void Super24Power(void)
+{
+ EXPREGS[0]=0x24;
+ EXPREGS[1]=159;
+ EXPREGS[2]=0;
+ GenMMC3Power();
+ SetWriteHandler(0x5000,0x7FFF,Super24Write);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+}
+
+static void Super24Reset(void)
+{
+ EXPREGS[0]=0x24;
+ EXPREGS[1]=159;
+ EXPREGS[2]=0;
+ MMC3RegReset();
+}
+
+static void Super24Close(void)
+{
+ if(CHRRAM)
+ FCEU_gfree(CHRRAM);
+ CHRRAM = NULL;
+}
+
+void Super24_Init(CartInfo *info)
+{
+ GenMMC3_Init(info, 128, 256, 0, 0);
+ info->Power=Super24Power;
+ info->Reset=Super24Reset;
+ info->Close=Super24Close;
+ cwrap=Super24CW;
+ pwrap=Super24PW;
+ CHRRAM=(uint8*)FCEU_gmalloc(8192);
+ SetupCartCHRMapping(0x10, CHRRAM, 8192, 1);
+ AddExState(CHRRAM, 8192, 0, "CHRR");
+ AddExState(EXPREGS, 3, 0, "BIG2");
+}
diff --git a/boards/supervision.c b/boards/supervision.c
new file mode 100644
index 00000000..61a373d3
--- /dev/null
+++ b/boards/supervision.c
@@ -0,0 +1,74 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint8 cmd0, cmd1;
+
+static void DoSuper(void)
+{
+ setprg8r((cmd0&0xC)>>2,0x6000,((cmd0&0x3)<<4)|0xF);
+ if(cmd0&0x10)
+ {
+ setprg16r((cmd0&0xC)>>2,0x8000,((cmd0&0x3)<<3)|(cmd1&7));
+ setprg16r((cmd0&0xC)>>2,0xc000,((cmd0&0x3)<<3)|7);
+ }
+ else
+ setprg32r(4,0x8000,0);
+ setmirror(((cmd0&0x20)>>5)^1);
+}
+
+static DECLFW(SuperWrite)
+{
+ if(!(cmd0&0x10))
+ {
+ cmd0=V;
+ DoSuper();
+ }
+}
+
+static DECLFW(SuperHi)
+{
+ cmd1=V;
+ DoSuper();
+}
+
+static void SuperReset(void)
+{
+ SetWriteHandler(0x6000,0x7FFF,SuperWrite);
+ SetWriteHandler(0x8000,0xFFFF,SuperHi);
+ SetReadHandler(0x6000,0xFFFF,CartBR);
+ cmd0=cmd1=0;
+ setprg32r(4,0x8000,0);
+ setchr8(0);
+}
+
+static void SuperRestore(int version)
+{
+ DoSuper();
+}
+
+void Supervision16_Init(CartInfo *info)
+{
+ AddExState(&cmd0, 1, 0,"L1");
+ AddExState(&cmd1, 1, 0,"L2");
+ info->Power=SuperReset;
+ GameStateRestore=SuperRestore;
+}
diff --git a/boards/t-262.c b/boards/t-262.c
new file mode 100644
index 00000000..98cc24e5
--- /dev/null
+++ b/boards/t-262.c
@@ -0,0 +1,83 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2005 CaH4e3
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static uint16 addrreg;
+static uint8 datareg;
+static uint8 busy;
+static SFORMAT StateRegs[]=
+{
+ {&addrreg, 2, "ADDRREG"},
+ {&datareg, 1, "DATAREG"},
+ {&busy, 1, "BUSY"},
+ {0}
+};
+
+static void Sync(void)
+{
+ setprg16(0x8000,(datareg&7)|((addrreg&0x60)>>2)|((addrreg&0x100)>>3));
+ setprg16(0xC000,7|((addrreg&0x60)>>2)|((addrreg&0x100)>>3));
+ setmirror(((addrreg&2)>>1)^1);
+}
+
+static DECLFW(BMCT262Write)
+{
+ if(busy||(A==0x8000))
+ datareg=V;
+ else
+ {
+ addrreg=A;
+ busy=1;
+ }
+ Sync();
+}
+
+static void BMCT262Power(void)
+{
+ setchr8(0);
+ SetWriteHandler(0x8000,0xFFFF,BMCT262Write);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ busy=0;
+ addrreg=0;
+ datareg=0;
+ Sync();
+}
+
+static void BMCT262Reset(void)
+{
+ busy=0;
+ addrreg=0;
+ datareg=0;
+ Sync();
+}
+
+static void BMCT262Restore(int version)
+{
+ Sync();
+}
+
+void BMCT262_Init(CartInfo *info)
+{
+ info->Power=BMCT262Power;
+ info->Reset=BMCT262Reset;
+ GameStateRestore=BMCT262Restore;
+ AddExState(&StateRegs, ~0, 0, 0);
+}
diff --git a/boards/tengen.c b/boards/tengen.c
new file mode 100644
index 00000000..a4f33f52
--- /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
new file mode 100644
index 00000000..33aafdfd
--- /dev/null
+++ b/cart.c
@@ -0,0 +1,685 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "types.h"
+#include "fceu.h"
+#include "ppu.h"
+
+#include "cart.h"
+#include "memory.h"
+#include "x6502.h"
+
+#include "general.h"
+
+/*
+ This file contains all code for coordinating the mapping in of the
+ address space external to the NES.
+ It's also (ab)used by the NSF code.
+*/
+
+uint8 *Page[32],*VPage[8];
+uint8 **VPageR=VPage;
+uint8 *VPageG[8];
+uint8 *MMC5SPRVPage[8];
+uint8 *MMC5BGVPage[8];
+
+static uint8 PRGIsRAM[32]; /* This page is/is not PRG RAM. */
+
+/* 16 are (sort of) reserved for UNIF/iNES and 16 to map other stuff. */
+static int CHRram[32];
+static int PRGram[32];
+
+uint8 *PRGptr[32];
+uint8 *CHRptr[32];
+
+uint32 PRGsize[32];
+uint32 CHRsize[32];
+
+uint32 PRGmask2[32];
+uint32 PRGmask4[32];
+uint32 PRGmask8[32];
+uint32 PRGmask16[32];
+uint32 PRGmask32[32];
+
+uint32 CHRmask1[32];
+uint32 CHRmask2[32];
+uint32 CHRmask4[32];
+uint32 CHRmask8[32];
+
+int geniestage=0;
+
+int modcon;
+
+uint8 genieval[3];
+uint8 geniech[3];
+
+uint32 genieaddr[3];
+
+static INLINE void setpageptr(int s, uint32 A, uint8 *p, int ram)
+{
+ uint32 AB=A>>11;
+ int x;
+
+ if(p)
+ for(x=(s>>1)-1;x>=0;x--)
+ {
+ PRGIsRAM[AB+x]=ram;
+ Page[AB+x]=p-A;
+ }
+ else
+ for(x=(s>>1)-1;x>=0;x--)
+ {
+ PRGIsRAM[AB+x]=0;
+ Page[AB+x]=0;
+ }
+}
+
+static uint8 nothing[8192];
+void ResetCartMapping(void)
+{
+ int x;
+
+ for(x=0;x<32;x++)
+ {
+ Page[x]=nothing-x*2048;
+ PRGptr[x]=CHRptr[x]=0;
+ PRGsize[x]=CHRsize[x]=0;
+ }
+ for(x=0;x<8;x++)
+ {
+ MMC5SPRVPage[x]=MMC5BGVPage[x]=VPageR[x]=nothing-0x400*x;
+ }
+
+}
+
+void SetupCartPRGMapping(int chip, uint8 *p, uint32 size, int ram)
+{
+ PRGptr[chip]=p;
+ PRGsize[chip]=size;
+
+ PRGmask2[chip]=(size>>11)-1;
+ PRGmask4[chip]=(size>>12)-1;
+ PRGmask8[chip]=(size>>13)-1;
+ PRGmask16[chip]=(size>>14)-1;
+ PRGmask32[chip]=(size>>15)-1;
+
+ PRGram[chip]=ram?1:0;
+}
+
+void SetupCartCHRMapping(int chip, uint8 *p, uint32 size, int ram)
+{
+ CHRptr[chip]=p;
+ CHRsize[chip]=size;
+
+ CHRmask1[chip]=(size>>10)-1;
+ CHRmask2[chip]=(size>>11)-1;
+ CHRmask4[chip]=(size>>12)-1;
+ CHRmask8[chip]=(size>>13)-1;
+
+ CHRram[chip]=ram;
+}
+
+DECLFR(CartBR)
+{
+ return Page[A>>11][A];
+}
+
+DECLFW(CartBW)
+{
+ //printf("Ok: %04x:%02x, %d\n",A,V,PRGIsRAM[A>>11]);
+ if(PRGIsRAM[A>>11] && Page[A>>11])
+ Page[A>>11][A]=V;
+}
+
+DECLFR(CartBROB)
+{
+ if(!Page[A>>11]) return(X.DB);
+ return Page[A>>11][A];
+}
+
+void FASTAPASS(3) setprg2r(int r, unsigned int A, unsigned int V)
+{
+ V&=PRGmask2[r];
+ setpageptr(2,A,PRGptr[r]?(&PRGptr[r][V<<11]):0,PRGram[r]);
+}
+
+void FASTAPASS(2) setprg2(uint32 A, uint32 V)
+{
+ setprg2r(0,A,V);
+}
+
+void FASTAPASS(3) setprg4r(int r, unsigned int A, unsigned int V)
+{
+ V&=PRGmask4[r];
+ setpageptr(4,A,PRGptr[r]?(&PRGptr[r][V<<12]):0,PRGram[r]);
+}
+
+void FASTAPASS(2) setprg4(uint32 A, uint32 V)
+{
+ setprg4r(0,A,V);
+}
+
+void FASTAPASS(3) setprg8r(int r, unsigned int A, unsigned int V)
+{
+ if(PRGsize[r]>=8192)
+ {
+ V&=PRGmask8[r];
+ setpageptr(8,A,PRGptr[r]?(&PRGptr[r][V<<13]):0,PRGram[r]);
+ }
+ else
+ {
+ uint32 VA=V<<2;
+ int x;
+ for(x=0;x<4;x++)
+ setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
+ }
+}
+
+void FASTAPASS(2) setprg8(uint32 A, uint32 V)
+{
+ setprg8r(0,A,V);
+}
+
+void FASTAPASS(3) setprg16r(int r, unsigned int A, unsigned int V)
+{
+ if(PRGsize[r]>=16384)
+ {
+ V&=PRGmask16[r];
+ setpageptr(16,A,PRGptr[r]?(&PRGptr[r][V<<14]):0,PRGram[r]);
+ }
+ else
+ {
+ uint32 VA=V<<3;
+ int x;
+
+ for(x=0;x<8;x++)
+ setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
+ }
+}
+
+void FASTAPASS(2) setprg16(uint32 A, uint32 V)
+{
+ setprg16r(0,A,V);
+}
+
+void FASTAPASS(3) setprg32r(int r,unsigned int A, unsigned int V)
+{
+ if(PRGsize[r]>=32768)
+ {
+ V&=PRGmask32[r];
+ setpageptr(32,A,PRGptr[r]?(&PRGptr[r][V<<15]):0,PRGram[r]);
+ }
+ else
+ {
+ uint32 VA=V<<4;
+ int x;
+
+ for(x=0;x<16;x++)
+ setpageptr(2,A+(x<<11),PRGptr[r]?(&PRGptr[r][((VA+x)&PRGmask2[r])<<11]):0,PRGram[r]);
+ }
+}
+
+void FASTAPASS(2) setprg32(uint32 A, uint32 V)
+{
+ setprg32r(0,A,V);
+}
+
+void FASTAPASS(3) setchr1r(int r, unsigned int A, unsigned int V)
+{
+ if(!CHRptr[r]) return;
+ FCEUPPU_LineUpdate();
+ V&=CHRmask1[r];
+ if(CHRram[r])
+ PPUCHRRAM|=(1<<(A>>10));
+ else
+ PPUCHRRAM&=~(1<<(A>>10));
+ VPageR[(A)>>10]=&CHRptr[r][(V)<<10]-(A);
+}
+
+void FASTAPASS(3) setchr2r(int r, unsigned int A, unsigned int V)
+{
+ if(!CHRptr[r]) return;
+ FCEUPPU_LineUpdate();
+ V&=CHRmask2[r];
+ VPageR[(A)>>10]=VPageR[((A)>>10)+1]=&CHRptr[r][(V)<<11]-(A);
+ if(CHRram[r])
+ PPUCHRRAM|=(3<<(A>>10));
+ else
+ PPUCHRRAM&=~(3<<(A>>10));
+}
+
+void FASTAPASS(3) setchr4r(int r, unsigned int A, unsigned int V)
+{
+ if(!CHRptr[r]) return;
+ FCEUPPU_LineUpdate();
+ V&=CHRmask4[r];
+ VPageR[(A)>>10]=VPageR[((A)>>10)+1]=
+ VPageR[((A)>>10)+2]=VPageR[((A)>>10)+3]=&CHRptr[r][(V)<<12]-(A);
+ if(CHRram[r])
+ PPUCHRRAM|=(15<<(A>>10));
+ else
+ PPUCHRRAM&=~(15<<(A>>10));
+}
+
+void FASTAPASS(2) setchr8r(int r, unsigned int V)
+{
+ int x;
+
+ if(!CHRptr[r]) return;
+ FCEUPPU_LineUpdate();
+ V&=CHRmask8[r];
+ for(x=7;x>=0;x--)
+ VPageR[x]=&CHRptr[r][V<<13];
+ if(CHRram[r])
+ PPUCHRRAM|=(255);
+ else
+ PPUCHRRAM&=~(255);
+}
+
+void FASTAPASS(2) setchr1(unsigned int A, unsigned int V)
+{
+ setchr1r(0,A,V);
+}
+
+void FASTAPASS(2) setchr2(unsigned int A, unsigned int V)
+{
+ setchr2r(0,A,V);
+}
+
+void FASTAPASS(2) setchr4(unsigned int A, unsigned int V)
+{
+ setchr4r(0,A,V);
+}
+
+void FASTAPASS(1) setchr8(unsigned int V)
+{
+ setchr8r(0,V);
+}
+
+void FASTAPASS(1) setvram8(uint8 *p)
+{
+ int x;
+ for(x=7;x>=0;x--)
+ VPageR[x]=p;
+ PPUCHRRAM|=255;
+}
+
+void FASTAPASS(2) setvram4(uint32 A, uint8 *p)
+{
+ int x;
+ for(x=3;x>=0;x--)
+ VPageR[(A>>10)+x]=p-A;
+ PPUCHRRAM|=(15<<(A>>10));
+}
+
+void FASTAPASS(3) setvramb1(uint8 *p, uint32 A, uint32 b)
+{
+ FCEUPPU_LineUpdate();
+ VPageR[A>>10]=p-A+(b<<10);
+ PPUCHRRAM|=(1<<(A>>10));
+}
+
+void FASTAPASS(3) setvramb2(uint8 *p, uint32 A, uint32 b)
+{
+ FCEUPPU_LineUpdate();
+ VPageR[(A>>10)]=VPageR[(A>>10)+1]=p-A+(b<<11);
+ PPUCHRRAM|=(3<<(A>>10));
+}
+
+void FASTAPASS(3) setvramb4(uint8 *p, uint32 A, uint32 b)
+{
+ int x;
+
+ FCEUPPU_LineUpdate();
+ for(x=3;x>=0;x--)
+ VPageR[(A>>10)+x]=p-A+(b<<12);
+ PPUCHRRAM|=(15<<(A>>10));
+}
+
+void FASTAPASS(2) setvramb8(uint8 *p, uint32 b)
+{
+ int x;
+
+ FCEUPPU_LineUpdate();
+ for(x=7;x>=0;x--)
+ VPageR[x]=p+(b<<13);
+ PPUCHRRAM|=255;
+}
+
+/* This function can be called without calling SetupCartMirroring(). */
+
+void FASTAPASS(3) setntamem(uint8 *p, int ram, uint32 b)
+{
+ FCEUPPU_LineUpdate();
+ vnapage[b]=p;
+ PPUNTARAM&=~(1<<b);
+ if(ram)
+ PPUNTARAM|=1<<b;
+}
+
+static int mirrorhard=0;
+void setmirrorw(int a, int b, int c, int d)
+{
+ FCEUPPU_LineUpdate();
+ vnapage[0]=NTARAM+a*0x400;
+ vnapage[1]=NTARAM+b*0x400;
+ vnapage[2]=NTARAM+c*0x400;
+ vnapage[3]=NTARAM+d*0x400;
+}
+
+void FASTAPASS(1) setmirror(int t)
+{
+ FCEUPPU_LineUpdate();
+ if(!mirrorhard)
+ {
+ switch(t)
+ {
+ case MI_H:
+ vnapage[0]=vnapage[1]=NTARAM;vnapage[2]=vnapage[3]=NTARAM+0x400;
+ break;
+ case MI_V:
+ vnapage[0]=vnapage[2]=NTARAM;vnapage[1]=vnapage[3]=NTARAM+0x400;
+ break;
+ case MI_0:
+ vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=NTARAM;
+ break;
+ case MI_1:
+ vnapage[0]=vnapage[1]=vnapage[2]=vnapage[3]=NTARAM+0x400;
+ break;
+ }
+ PPUNTARAM=0xF;
+ }
+}
+
+void SetupCartMirroring(int m, int hard, uint8 *extra)
+{
+ if(m<4)
+ {
+ mirrorhard = 0;
+ setmirror(m);
+ }
+ else
+ {
+ vnapage[0]=NTARAM;
+ vnapage[1]=NTARAM+0x400;
+ vnapage[2]=extra;
+ vnapage[3]=extra+0x400;
+ PPUNTARAM=0xF;
+ }
+ mirrorhard=hard;
+}
+
+static uint8 *GENIEROM=0;
+
+void FixGenieMap(void);
+
+/* Called when a game(file) is opened successfully. */
+void OpenGenie(void)
+{
+ FILE *fp;
+ int x;
+
+ if(!GENIEROM)
+ {
+ char *fn;
+
+ if(!(GENIEROM=(uint8 *)FCEU_malloc(4096+1024))) return;
+
+ fn=FCEU_MakeFName(FCEUMKF_GGROM,0,0);
+ fp=FCEUD_UTF8fopen(fn,"rb");
+ if(!fp)
+ {
+ FCEU_PrintError("Error opening Game Genie ROM image!");
+ free(GENIEROM);
+ GENIEROM=0;
+ return;
+ }
+ if(fread(GENIEROM,1,16,fp)!=16)
+ {
+ grerr:
+ FCEU_PrintError("Error reading from Game Genie ROM image!");
+ free(GENIEROM);
+ GENIEROM=0;
+ fclose(fp);
+ return;
+ }
+ if(GENIEROM[0]==0x4E) /* iNES ROM image */
+ {
+ if(fread(GENIEROM,1,4096,fp)!=4096)
+ goto grerr;
+ if(fseek(fp,16384-4096,SEEK_CUR))
+ goto grerr;
+ if(fread(GENIEROM+4096,1,256,fp)!=256)
+ goto grerr;
+ }
+ else
+ {
+ if(fread(GENIEROM+16,1,4352-16,fp)!=(4352-16))
+ goto grerr;
+ }
+ fclose(fp);
+
+ /* Workaround for the FCE Ultra CHR page size only being 1KB */
+ for(x=0;x<4;x++)
+ memcpy(GENIEROM+4096+(x<<8),GENIEROM+4096,256);
+ }
+
+ geniestage=1;
+}
+
+/* Called when a game is closed. */
+void CloseGenie(void)
+{
+ /* No good reason to free() the Game Genie ROM image data. */
+ geniestage=0;
+ FlushGenieRW();
+ VPageR=VPage;
+}
+
+void FCEU_KillGenie(void)
+{
+ if(GENIEROM)
+ {
+ free(GENIEROM);
+ GENIEROM=0;
+ }
+}
+
+static DECLFR(GenieRead)
+{
+ return GENIEROM[A&4095];
+}
+
+static DECLFW(GenieWrite)
+{
+ switch(A)
+ {
+ case 0x800c:
+ case 0x8008:
+ case 0x8004:genieval[((A-4)&0xF)>>2]=V;break;
+
+ case 0x800b:
+ case 0x8007:
+ case 0x8003:geniech[((A-3)&0xF)>>2]=V;break;
+
+ case 0x800a:
+ case 0x8006:
+ case 0x8002:genieaddr[((A-2)&0xF)>>2]&=0xFF00;genieaddr[((A-2)&0xF)>>2]|=V;break;
+
+ case 0x8009:
+ case 0x8005:
+ case 0x8001:genieaddr[((A-1)&0xF)>>2]&=0xFF;genieaddr[((A-1)&0xF)>>2]|=(V|0x80)<<8;break;
+
+ case 0x8000:if(!V)
+ FixGenieMap();
+ else
+ {
+ modcon=V^0xFF;
+ if(V==0x71)
+ modcon=0;
+ }
+ break;
+ }
+}
+
+static readfunc GenieBackup[3];
+
+static DECLFR(GenieFix1)
+{
+ uint8 r=GenieBackup[0](A);
+
+ if((modcon>>1)&1) // No check
+ return genieval[0];
+ else if(r==geniech[0])
+ return genieval[0];
+
+ return r;
+}
+
+static DECLFR(GenieFix2)
+{
+ uint8 r=GenieBackup[1](A);
+
+ if((modcon>>2)&1) // No check
+ return genieval[1];
+ else if(r==geniech[1])
+ return genieval[1];
+
+ return r;
+}
+
+static DECLFR(GenieFix3)
+{
+ uint8 r=GenieBackup[2](A);
+
+ if((modcon>>3)&1) // No check
+ return genieval[2];
+ else if(r==geniech[2])
+ return genieval[2];
+
+ return r;
+}
+
+
+void FixGenieMap(void)
+{
+ int x;
+
+ geniestage=2;
+
+ for(x=0;x<8;x++)
+ VPage[x]=VPageG[x];
+
+ VPageR=VPage;
+ FlushGenieRW();
+ //printf("Rightyo\n");
+ for(x=0;x<3;x++)
+ if((modcon>>(4+x))&1)
+ {
+ readfunc tmp[3]={GenieFix1,GenieFix2,GenieFix3};
+ GenieBackup[x]=GetReadHandler(genieaddr[x]);
+ SetReadHandler(genieaddr[x],genieaddr[x],tmp[x]);
+ }
+}
+
+void GeniePower(void)
+{
+ uint32 x;
+
+ if(!geniestage)
+ return;
+
+ geniestage=1;
+ for(x=0;x<3;x++)
+ {
+ genieval[x]=0xFF;
+ geniech[x]=0xFF;
+ genieaddr[x]=0xFFFF;
+ }
+ modcon=0;
+
+ SetWriteHandler(0x8000,0xFFFF,GenieWrite);
+ SetReadHandler(0x8000,0xFFFF,GenieRead);
+
+ for(x=0;x<8;x++)
+ VPage[x]=GENIEROM+4096-0x400*x;
+
+ if(AllocGenieRW())
+ VPageR=VPageG;
+ else
+ geniestage=2;
+}
+
+
+void FCEU_SaveGameSave(CartInfo *LocalHWInfo)
+{
+ if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0])
+ {
+ FILE *sp;
+ char *soot;
+
+ soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
+ if((sp=FCEUD_UTF8fopen(soot,"wb"))==NULL)
+ {
+ FCEU_PrintError("WRAM file \"%s\" cannot be written to.\n",soot);
+ }
+ else
+ {
+ int x;
+
+ for(x=0;x<4;x++)
+ if(LocalHWInfo->SaveGame[x])
+ {
+ fwrite(LocalHWInfo->SaveGame[x],1,
+ LocalHWInfo->SaveGameLen[x],sp);
+ }
+ }
+ free(soot);
+ }
+}
+
+// hack, movie.c has to communicate with this function somehow
+int disableBatteryLoading=0;
+
+void FCEU_LoadGameSave(CartInfo *LocalHWInfo)
+{
+ if(LocalHWInfo->battery && LocalHWInfo->SaveGame[0] && !disableBatteryLoading)
+ {
+ FILE *sp;
+ char *soot;
+
+ soot=FCEU_MakeFName(FCEUMKF_SAV,0,"sav");
+ sp=FCEUD_UTF8fopen(soot,"rb");
+ if(sp!=NULL)
+ {
+ int x;
+ for(x=0;x<4;x++)
+ if(LocalHWInfo->SaveGame[x])
+ fread(LocalHWInfo->SaveGame[x],1,LocalHWInfo->SaveGameLen[x],sp);
+ }
+ free(soot);
+ }
+}
+
+
diff --git a/cart.h b/cart.h
new file mode 100644
index 00000000..771a5026
--- /dev/null
+++ b/cart.h
@@ -0,0 +1,100 @@
+typedef struct {
+ /* Set by mapper/board code: */
+ void (*Power)(void);
+ void (*Reset)(void);
+ void (*Close)(void);
+ uint8 *SaveGame[4]; /* Pointers to memory to save/load. */
+ uint32 SaveGameLen[4]; /* How much memory to save/load. */
+
+ /* Set by iNES/UNIF loading code. */
+ int mirror; /* As set in the header or chunk.
+ iNES/UNIF specific. Intended
+ to help support games like "Karnov"
+ that are not really MMC3 but are
+ set to mapper 4.
+ */
+ int battery; /* Presence of an actual battery. */
+ uint8 MD5[16];
+ uint32 CRC32; /* Should be set by the iNES/UNIF loading
+ code, used by mapper/board code, maybe
+ other code in the future.
+ */
+} CartInfo;
+
+void FCEU_SaveGameSave(CartInfo *LocalHWInfo);
+void FCEU_LoadGameSave(CartInfo *LocalHWInfo);
+
+extern uint8 *Page[32],*VPage[8],*MMC5SPRVPage[8],*MMC5BGVPage[8];
+
+void ResetCartMapping(void);
+void SetupCartPRGMapping(int chip, uint8 *p, uint32 size, int ram);
+void SetupCartCHRMapping(int chip, uint8 *p, uint32 size, int ram);
+void SetupCartMirroring(int m, int hard, uint8 *extra);
+
+DECLFR(CartBROB);
+DECLFR(CartBR);
+DECLFW(CartBW);
+
+extern uint8 *PRGptr[32];
+extern uint8 *CHRptr[32];
+
+extern uint32 PRGsize[32];
+extern uint32 CHRsize[32];
+
+extern uint32 PRGmask2[32];
+extern uint32 PRGmask4[32];
+extern uint32 PRGmask8[32];
+extern uint32 PRGmask16[32];
+extern uint32 PRGmask32[32];
+
+extern uint32 CHRmask1[32];
+extern uint32 CHRmask2[32];
+extern uint32 CHRmask4[32];
+extern uint32 CHRmask8[32];
+
+void FASTAPASS(2) setprg2(uint32 A, uint32 V);
+void FASTAPASS(2) setprg4(uint32 A, uint32 V);
+void FASTAPASS(2) setprg8(uint32 A, uint32 V);
+void FASTAPASS(2) setprg16(uint32 A, uint32 V);
+void FASTAPASS(2) setprg32(uint32 A, uint32 V);
+
+void FASTAPASS(3) setprg2r(int r, unsigned int A, unsigned int V);
+void FASTAPASS(3) setprg4r(int r, unsigned int A, unsigned int V);
+void FASTAPASS(3) setprg8r(int r, unsigned int A, unsigned int V);
+void FASTAPASS(3) setprg16r(int r, unsigned int A, unsigned int V);
+void FASTAPASS(3) setprg32r(int r, unsigned int A, unsigned int V);
+
+void FASTAPASS(3) setchr1r(int r, unsigned int A, unsigned int V);
+void FASTAPASS(3) setchr2r(int r, unsigned int A, unsigned int V);
+void FASTAPASS(3) setchr4r(int r, unsigned int A, unsigned int V);
+void FASTAPASS(2) setchr8r(int r, unsigned int V);
+
+void FASTAPASS(2) setchr1(unsigned int A, unsigned int V);
+void FASTAPASS(2) setchr2(unsigned int A, unsigned int V);
+void FASTAPASS(2) setchr4(unsigned int A, unsigned int V);
+void FASTAPASS(1) setchr8(unsigned int V);
+
+void FASTAPASS(2) setvram4(uint32 A, uint8 *p);
+void FASTAPASS(1) setvram8(uint8 *p);
+
+void FASTAPASS(3) setvramb1(uint8 *p, uint32 A, uint32 b);
+void FASTAPASS(3) setvramb2(uint8 *p, uint32 A, uint32 b);
+void FASTAPASS(3) setvramb4(uint8 *p, uint32 A, uint32 b);
+void FASTAPASS(2) setvramb8(uint8 *p, uint32 b);
+
+void FASTAPASS(1) setmirror(int t);
+void setmirrorw(int a, int b, int c, int d);
+void FASTAPASS(3) setntamem(uint8 *p, int ram, uint32 b);
+
+#define MI_H 0
+#define MI_V 1
+#define MI_0 2
+#define MI_1 3
+
+extern int geniestage;
+
+void GeniePower(void);
+
+void OpenGenie(void);
+void CloseGenie(void);
+void FCEU_KillGenie(void);
diff --git a/cheat.c b/cheat.c
new file mode 100644
index 00000000..c69c1779
--- /dev/null
+++ b/cheat.c
@@ -0,0 +1,855 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include "types.h"
+#include "x6502.h"
+#include "cheat.h"
+#include "fceu.h"
+#include "general.h"
+#include "cart.h"
+#include "memory.h"
+
+static uint8 *CheatRPtrs[64];
+
+void FCEU_CheatResetRAM(void)
+{
+ int x;
+
+ for(x=0;x<64;x++)
+ CheatRPtrs[x]=0;
+}
+
+void FCEU_CheatAddRAM(int s, uint32 A, uint8 *p)
+{
+ uint32 AB=A>>10;
+ int x;
+
+ for(x=s-1;x>=0;x--)
+ CheatRPtrs[AB+x]=p-A;
+}
+
+
+struct CHEATF {
+ struct CHEATF *next;
+ char *name;
+ uint16 addr;
+ uint8 val;
+ int compare; /* -1 for no compare. */
+ int type; /* 0 for replace, 1 for substitute(GG). */
+ int status;
+};
+
+typedef struct {
+ uint16 addr;
+ uint8 val;
+ int compare;
+ readfunc PrevRead;
+} CHEATF_SUBFAST;
+
+
+static CHEATF_SUBFAST SubCheats[256];
+static int numsubcheats=0;
+struct CHEATF *cheats=0,*cheatsl=0;
+
+
+#define CHEATC_NONE 0x8000
+#define CHEATC_EXCLUDED 0x4000
+#define CHEATC_NOSHOW 0xC000
+
+static uint16 *CheatComp=0;
+static int savecheats;
+
+static DECLFR(SubCheatsRead)
+{
+ CHEATF_SUBFAST *s=SubCheats;
+ int x=numsubcheats;
+
+ do
+ {
+ if(s->addr==A)
+ {
+ if(s->compare>=0)
+ {
+ uint8 pv=s->PrevRead(A);
+
+ if(pv==s->compare)
+ return(s->val);
+ else return(pv);
+ }
+ else return(s->val);
+ }
+ s++;
+ } while(--x);
+ return(0); /* We should never get here. */
+}
+
+void RebuildSubCheats(void)
+{
+ int x;
+ struct CHEATF *c=cheats;
+
+ for(x=0;x<numsubcheats;x++)
+ SetReadHandler(SubCheats[x].addr,SubCheats[x].addr,SubCheats[x].PrevRead);
+
+ numsubcheats=0;
+ while(c)
+ {
+ if(c->type==1 && c->status)
+ {
+ if(GetReadHandler(c->addr)==SubCheatsRead)
+ {
+ /* Prevent a catastrophe by this check. */
+ //FCEU_DispMessage("oops");
+ }
+ else
+ {
+ SubCheats[numsubcheats].PrevRead=GetReadHandler(c->addr);
+ SubCheats[numsubcheats].addr=c->addr;
+ SubCheats[numsubcheats].val=c->val;
+ SubCheats[numsubcheats].compare=c->compare;
+ SetReadHandler(c->addr,c->addr,SubCheatsRead);
+ numsubcheats++;
+ }
+ }
+ c=c->next;
+ }
+}
+
+void FCEU_PowerCheats()
+{
+ numsubcheats=0; /* Quick hack to prevent setting of ancient read addresses. */
+ RebuildSubCheats();
+}
+
+static int AddCheatEntry(char *name, uint32 addr, uint8 val, int compare, int status, int type);
+static void CheatMemErr(void)
+{
+ FCEUD_PrintError("Error allocating memory for cheat data.");
+}
+
+/* This function doesn't allocate any memory for "name" */
+static int AddCheatEntry(char *name, uint32 addr, uint8 val, int compare, int status, int type)
+{
+ struct CHEATF *temp;
+ if(!(temp=(struct CHEATF *)malloc(sizeof(struct CHEATF))))
+ {
+ CheatMemErr();
+ return(0);
+ }
+ temp->name=name;
+ temp->addr=addr;
+ temp->val=val;
+ temp->status=status;
+ temp->compare=compare;
+ temp->type=type;
+ temp->next=0;
+
+ if(cheats)
+ {
+ cheatsl->next=temp;
+ cheatsl=temp;
+ }
+ else
+ cheats=cheatsl=temp;
+
+ return(1);
+}
+
+void FCEU_LoadGameCheats(FILE *override)
+{
+ FILE *fp;
+ unsigned int addr;
+ unsigned int val;
+ unsigned int status;
+ unsigned int type;
+ unsigned int compare;
+ int x;
+
+ char linebuf[2048];
+ char *namebuf;
+ int tc=0;
+ char *fn;
+
+ numsubcheats=savecheats=0;
+
+ if(override)
+ fp = override;
+ else
+ {
+ fn=FCEU_MakeFName(FCEUMKF_CHEAT,0,0);
+ fp=FCEUD_UTF8fopen(fn,"rb");
+ free(fn);
+ if(!fp) return;
+ }
+
+ while(fgets(linebuf,2048,fp)>0)
+ {
+ char *tbuf=linebuf;
+ int doc=0;
+
+ addr=val=compare=status=type=0;
+
+ if(tbuf[0]=='S')
+ {
+ tbuf++;
+ type=1;
+ }
+ else type=0;
+
+ if(tbuf[0]=='C')
+ {
+ tbuf++;
+ doc=1;
+ }
+
+ if(tbuf[0]==':')
+ {
+ tbuf++;
+ status=0;
+ }
+ else status=1;
+
+ if(doc)
+ {
+ char *neo=&tbuf[4+2+2+1+1+1];
+ if(sscanf(tbuf,"%04x%*[:]%02x%*[:]%02x",&addr,&val,&compare)!=3)
+ continue;
+ namebuf=malloc(strlen(neo)+1);
+ strcpy(namebuf,neo);
+ }
+ else
+ {
+ char *neo=&tbuf[4+2+1+1];
+ if(sscanf(tbuf,"%04x%*[:]%02x",&addr,&val)!=2)
+ continue;
+ namebuf=malloc(strlen(neo)+1);
+ strcpy(namebuf,neo);
+ }
+
+ for(x=0;x<strlen(namebuf);x++)
+ {
+ if(namebuf[x]==10 || namebuf[x]==13)
+ {
+ namebuf[x]=0;
+ break;
+ }
+ else if(namebuf[x]<0x20) namebuf[x]=' ';
+ }
+
+ AddCheatEntry(namebuf,addr,val,doc?compare:-1,status,type);
+ tc++;
+ }
+ RebuildSubCheats();
+ if(!override)
+ fclose(fp);
+}
+
+void FCEU_FlushGameCheats(FILE *override, int nosave)
+{
+ if(CheatComp)
+ {
+ free(CheatComp);
+ CheatComp=0;
+ }
+ if((!savecheats || nosave) && !override) /* Always save cheats if we're being overridden. */
+ {
+ if(cheats)
+ {
+ struct CHEATF *next=cheats;
+ for(;;)
+ {
+ struct CHEATF *last=next;
+ next=next->next;
+ free(last->name);
+ free(last);
+ if(!next) break;
+ }
+ cheats=cheatsl=0;
+ }
+ }
+ else
+ {
+ char *fn = 0;
+
+ if(!override)
+ fn = FCEU_MakeFName(FCEUMKF_CHEAT,0,0);
+
+ if(cheats)
+ {
+ struct CHEATF *next=cheats;
+ FILE *fp;
+
+ if(override)
+ fp = override;
+ else
+ fp=FCEUD_UTF8fopen(fn,"wb");
+
+ if(fp)
+ {
+ for(;;)
+ {
+ struct CHEATF *t;
+ if(next->type)
+ fputc('S',fp);
+ if(next->compare>=0)
+ fputc('C',fp);
+
+ if(!next->status)
+ fputc(':',fp);
+
+ if(next->compare>=0)
+ fprintf(fp,"%04x:%02x:%02x:%s\n",next->addr,next->val,next->compare,next->name);
+ else
+ fprintf(fp,"%04x:%02x:%s\n",next->addr,next->val,next->name);
+
+ free(next->name);
+ t=next;
+ next=next->next;
+ free(t);
+ if(!next) break;
+ }
+ if(!override)
+ fclose(fp);
+ }
+ else
+ FCEUD_PrintError("Error saving cheats.");
+ cheats=cheatsl=0;
+ }
+ else if(!override)
+ remove(fn);
+ if(!override)
+ free(fn);
+ }
+
+ RebuildSubCheats(); /* Remove memory handlers. */
+
+}
+
+
+int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type)
+{
+ char *t;
+
+ if(!(t=(char *)malloc(strlen(name)+1)))
+ {
+ CheatMemErr();
+ return(0);
+ }
+ strcpy(t,name);
+ if(!AddCheatEntry(t,addr,val,compare,1,type))
+ {
+ free(t);
+ return(0);
+ }
+ savecheats=1;
+ RebuildSubCheats();
+ return(1);
+}
+
+int FCEUI_DelCheat(uint32 which)
+{
+ struct CHEATF *prev;
+ struct CHEATF *cur;
+ uint32 x=0;
+
+ for(prev=0,cur=cheats;;)
+ {
+ if(x==which) // Remove this cheat.
+ {
+ if(prev) // Update pointer to this cheat.
+ {
+ if(cur->next) // More cheats.
+ prev->next=cur->next;
+ else // No more.
+ {
+ prev->next=0;
+ cheatsl=prev; // Set the previous cheat as the last cheat.
+ }
+ }
+ else // This is the first cheat.
+ {
+ if(cur->next) // More cheats
+ cheats=cur->next;
+ else
+ cheats=cheatsl=0; // No (more) cheats.
+ }
+ free(cur->name); // Now that all references to this cheat are removed,
+ free(cur); // free the memory.
+ break;
+ } // *END REMOVE THIS CHEAT*
+
+
+ if(!cur->next) // No more cheats to go through(this shouldn't ever happen...)
+ return(0);
+ prev=cur;
+ cur=prev->next;
+ x++;
+ }
+
+ savecheats=1;
+ RebuildSubCheats();
+
+ return(1);
+}
+
+void FCEU_ApplyPeriodicCheats(void)
+{
+ struct CHEATF *cur=cheats;
+ if(!cur) return;
+
+ for(;;)
+ {
+ if(cur->status && !(cur->type))
+ if(CheatRPtrs[cur->addr>>10])
+ CheatRPtrs[cur->addr>>10][cur->addr]=cur->val;
+ if(cur->next)
+ cur=cur->next;
+ else
+ break;
+ }
+}
+
+
+void FCEUI_ListCheats(int (*callb)(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data), void *data)
+{
+ struct CHEATF *next=cheats;
+
+ while(next)
+ {
+ if(!callb(next->name,next->addr,next->val,next->compare,next->status,next->type,data)) break;
+ next=next->next;
+ }
+}
+
+int FCEUI_GetCheat(uint32 which, char **name, uint32 *a, uint8 *v, int *compare, int *s, int *type)
+{
+ struct CHEATF *next=cheats;
+ uint32 x=0;
+
+ while(next)
+ {
+ if(x==which)
+ {
+ if(name)
+ *name=next->name;
+ if(a)
+ *a=next->addr;
+ if(v)
+ *v=next->val;
+ if(s)
+ *s=next->status;
+ if(compare)
+ *compare=next->compare;
+ if(type)
+ *type=next->type;
+ return(1);
+ }
+ next=next->next;
+ x++;
+ }
+ return(0);
+}
+
+static int GGtobin(char c)
+{
+ static char lets[16]={'A','P','Z','L','G','I','T','Y','E','O','X','U','K','S','V','N'};
+ int x;
+
+ for(x=0;x<16;x++)
+ if(lets[x] == toupper(c)) return(x);
+ return(0);
+}
+
+/* Returns 1 on success, 0 on failure. Sets *a,*v,*c. */
+int FCEUI_DecodeGG(const char *str, uint16 *a, uint8 *v, int *c)
+{
+ uint16 A;
+ uint8 V,C;
+ uint8 t;
+ int s;
+
+ A=0x8000;
+ V=0;
+ C=0;
+
+ s=strlen(str);
+ if(s!=6 && s!=8) return(0);
+
+ t=GGtobin(*str++);
+ V|=(t&0x07);
+ V|=(t&0x08)<<4;
+
+ t=GGtobin(*str++);
+ V|=(t&0x07)<<4;
+ A|=(t&0x08)<<4;
+
+ t=GGtobin(*str++);
+ A|=(t&0x07)<<4;
+ //if(t&0x08) return(0); /* 8-character code?! */
+
+ t=GGtobin(*str++);
+ A|=(t&0x07)<<12;
+ A|=(t&0x08);
+
+ t=GGtobin(*str++);
+ A|=(t&0x07);
+ A|=(t&0x08)<<8;
+
+ if(s==6)
+ {
+ t=GGtobin(*str++);
+ A|=(t&0x07)<<8;
+ V|=(t&0x08);
+
+ *a=A;
+ *v=V;
+ *c=-1;
+ return(1);
+ }
+ else
+ {
+ t=GGtobin(*str++);
+ A|=(t&0x07)<<8;
+ C|=(t&0x08);
+
+ t=GGtobin(*str++);
+ C|=(t&0x07);
+ C|=(t&0x08)<<4;
+
+ t=GGtobin(*str++);
+ C|=(t&0x07)<<4;
+ V|=(t&0x08);
+ *a=A;
+ *v=V;
+ *c=C;
+ return(1);
+ }
+ return(0);
+}
+
+int FCEUI_DecodePAR(const char *str, uint16 *a, uint8 *v, int *c, int *type)
+{
+ int boo[4];
+ if(strlen(str)!=8) return(0);
+
+ sscanf(str,"%02x%02x%02x%02x",boo,boo+1,boo+2,boo+3);
+
+ *c=-1;
+
+ if(1)
+ {
+ *a=(boo[3]<<8)|(boo[2]+0x7F);
+ *v=0;
+ }
+ else
+ {
+ *v=boo[3];
+ *a=boo[2]|(boo[1]<<8);
+ }
+ /* Zero-page addressing modes don't go through the normal read/write handlers in FCEU, so
+ we must do the old hacky method of RAM cheats.
+ */
+ if(*a<0x0100)
+ *type=0;
+ else
+ *type=1;
+ return(1);
+}
+
+/* name can be NULL if the name isn't going to be changed. */
+/* same goes for a, v, and s(except the values of each one must be <0) */
+
+int FCEUI_SetCheat(uint32 which, const char *name, int32 a, int32 v, int compare,int s, int type)
+{
+ struct CHEATF *next=cheats;
+ uint32 x=0;
+
+ while(next)
+ {
+ if(x==which)
+ {
+ if(name)
+ {
+ char *t;
+
+ if((t=(char *)realloc(next->name,strlen(name+1))))
+ {
+ next->name=t;
+ strcpy(next->name,name);
+ }
+ else
+ return(0);
+ }
+ if(a>=0)
+ next->addr=a;
+ if(v>=0)
+ next->val=v;
+ if(s>=0)
+ next->status=s;
+ next->compare=compare;
+ next->type=type;
+
+ savecheats=1;
+ RebuildSubCheats();
+
+ return(1);
+ }
+ next=next->next;
+ x++;
+ }
+ return(0);
+}
+
+/* Convenience function. */
+int FCEUI_ToggleCheat(uint32 which)
+{
+ struct CHEATF *next=cheats;
+ uint32 x=0;
+
+ while(next)
+ {
+ if(x==which)
+ {
+ next->status=!next->status;
+ savecheats=1;
+ RebuildSubCheats();
+ return(next->status);
+ }
+ next=next->next;
+ x++;
+ }
+
+ return(-1);
+}
+
+static int InitCheatComp(void)
+{
+ uint32 x;
+
+ CheatComp=(uint16*)malloc(65536*sizeof(uint16));
+ if(!CheatComp)
+ {
+ CheatMemErr();
+ return(0);
+ }
+ for(x=0;x<65536;x++)
+ CheatComp[x]=CHEATC_NONE;
+
+ return(1);
+}
+
+void FCEUI_CheatSearchSetCurrentAsOriginal(void)
+{
+ uint32 x;
+ for(x=0x000;x<0x10000;x++)
+ if(!(CheatComp[x]&CHEATC_NOSHOW))
+ {
+ if(CheatRPtrs[x>>10])
+ CheatComp[x]=CheatRPtrs[x>>10][x];
+ else
+ CheatComp[x]|=CHEATC_NONE;
+ }
+}
+
+void FCEUI_CheatSearchShowExcluded(void)
+{
+ uint32 x;
+
+ for(x=0x000;x<0x10000;x++)
+ CheatComp[x]&=~CHEATC_EXCLUDED;
+}
+
+
+int32 FCEUI_CheatSearchGetCount(void)
+{
+ uint32 x,c=0;
+
+ if(CheatComp)
+ {
+ for(x=0x0000;x<0x10000;x++)
+ if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
+ c++;
+ }
+
+ return c;
+}
+/* This function will give the initial value of the search and the current value at a location. */
+
+void FCEUI_CheatSearchGet(int (*callb)(uint32 a, uint8 last, uint8 current, void *data),void *data)
+{
+ uint32 x;
+
+ if(!CheatComp)
+ {
+ if(!InitCheatComp())
+ CheatMemErr();
+ return;
+ }
+
+ for(x=0;x<0x10000;x++)
+ if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
+ if(!callb(x,CheatComp[x],CheatRPtrs[x>>10][x],data))
+ break;
+}
+
+void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a, uint8 last, uint8 current))
+{
+ uint32 x;
+ uint32 in=0;
+
+ if(!CheatComp)
+ {
+ if(!InitCheatComp())
+ CheatMemErr();
+ return;
+ }
+
+ for(x=0;x<0x10000;x++)
+ if(!(CheatComp[x]&CHEATC_NOSHOW) && CheatRPtrs[x>>10])
+ {
+ if(in>=first)
+ if(!callb(x,CheatComp[x],CheatRPtrs[x>>10][x]))
+ break;
+ in++;
+ if(in>last) return;
+ }
+}
+
+void FCEUI_CheatSearchBegin(void)
+{
+ uint32 x;
+
+ if(!CheatComp)
+ {
+ if(!InitCheatComp())
+ {
+ CheatMemErr();
+ return;
+ }
+ }
+ for(x=0;x<0x10000;x++)
+ {
+ if(CheatRPtrs[x>>10])
+ CheatComp[x]=CheatRPtrs[x>>10][x];
+ else
+ CheatComp[x]=CHEATC_NONE;
+ }
+}
+
+
+static int INLINE CAbs(int x)
+{
+ if(x<0)
+ return(0-x);
+ return x;
+}
+
+void FCEUI_CheatSearchEnd(int type, uint8 v1, uint8 v2)
+{
+ uint32 x;
+
+ if(!CheatComp)
+ {
+ if(!InitCheatComp())
+ {
+ CheatMemErr();
+ return;
+ }
+ }
+
+
+ if(!type) // Change to a specific value.
+ {
+ for(x=0;x<0x10000;x++)
+ if(!(CheatComp[x]&CHEATC_NOSHOW))
+ {
+ if(CheatComp[x]==v1 && CheatRPtrs[x>>10][x]==v2)
+ {
+
+ }
+ else
+ CheatComp[x]|=CHEATC_EXCLUDED;
+ }
+ }
+ else if(type==1) // Search for relative change(between values).
+ {
+ for(x=0;x<0x10000;x++)
+ if(!(CheatComp[x]&CHEATC_NOSHOW))
+ {
+ if(CheatComp[x]==v1 && CAbs(CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
+ {
+
+ }
+ else
+ CheatComp[x]|=CHEATC_EXCLUDED;
+ }
+ }
+ else if(type==2) // Purely relative change.
+ {
+ for(x=0x000;x<0x10000;x++)
+ if(!(CheatComp[x]&CHEATC_NOSHOW))
+ {
+ if(CAbs(CheatComp[x]-CheatRPtrs[x>>10][x])==v2)
+ {
+
+ }
+ else
+ CheatComp[x]|=CHEATC_EXCLUDED;
+ }
+ }
+ else if(type==3) // Any change.
+ {
+ for(x=0;x<0x10000;x++)
+ if(!(CheatComp[x]&CHEATC_NOSHOW))
+ {
+ if(CheatComp[x]!=CheatRPtrs[x>>10][x])
+ {
+
+ }
+ else
+ CheatComp[x]|=CHEATC_EXCLUDED;
+ }
+ }
+ else if(type==4) // Value decreased.
+ {
+ for(x=0;x<0x10000;x++)
+ if(!(CheatComp[x]&CHEATC_NOSHOW))
+ {
+ if(!(CheatRPtrs[x>>10][x]<CheatComp[x]))
+ CheatComp[x]|=CHEATC_EXCLUDED;
+ }
+ }
+ else if(type==5) // Value increased.
+ {
+ for(x=0;x<0x10000;x++)
+ if(!(CheatComp[x]&CHEATC_NOSHOW))
+ {
+ if(!(CheatRPtrs[x>>10][x]>CheatComp[x]))
+ CheatComp[x]|=CHEATC_EXCLUDED;
+ }
+ }
+ if(type>4)
+ FCEUI_CheatSearchSetCurrentAsOriginal();
+}
diff --git a/cheat.h b/cheat.h
new file mode 100644
index 00000000..295bae79
--- /dev/null
+++ b/cheat.h
@@ -0,0 +1,7 @@
+void FCEU_CheatResetRAM(void);
+void FCEU_CheatAddRAM(int s, uint32 A, uint8 *p);
+
+void FCEU_LoadGameCheats(FILE *override);
+void FCEU_FlushGameCheats(FILE *override, int nosave);
+void FCEU_ApplyPeriodicCheats(void);
+void FCEU_PowerCheats(void);
diff --git a/crc32.c b/crc32.c
new file mode 100644
index 00000000..df15801e
--- /dev/null
+++ b/crc32.c
@@ -0,0 +1,33 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "types.h"
+#include "crc32.h"
+
+#include <zlib.h>
+uint32 CalcCRC32(uint32 crc, uint8 *buf, uint32 len)
+{
+ return(crc32(crc,buf,len));
+}
+
+uint32 FCEUI_CRC32(uint32 crc, uint8 *buf, uint32 len)
+{
+ return(CalcCRC32(crc,buf,len));
+}
diff --git a/crc32.h b/crc32.h
new file mode 100644
index 00000000..9d70b622
--- /dev/null
+++ b/crc32.h
@@ -0,0 +1 @@
+uint32 CalcCRC32(uint32 crc, uint8 *buf, uint32 len);
diff --git a/debug.c b/debug.c
new file mode 100644
index 00000000..c90a6af9
--- /dev/null
+++ b/debug.c
@@ -0,0 +1,535 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2003 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "types.h"
+#include "x6502.h"
+#include "fceu.h"
+#include "debug.h"
+#include "cart.h"
+
+
+void FCEUI_DumpVid(const char *fname, uint32 start, uint32 end)
+{
+ FILE *fp=FCEUD_UTF8fopen(fname,"wb");
+ fceuindbg=1;
+ start&=0x1FFF;
+ end&=0x1FFF;
+ for(;start<=end;start++)
+ fputc(VPage[start>>10][start],fp);
+ fclose(fp);
+ fceuindbg=0;
+}
+
+void FCEUI_DumpMem(const char *fname, uint32 start, uint32 end)
+{
+ FILE *fp=FCEUD_UTF8fopen(fname,"wb");
+ fceuindbg=1;
+ for(;start<=end;start++)
+ fputc(ARead[start](start),fp);
+ fclose(fp);
+ fceuindbg=0;
+}
+
+void FCEUI_LoadMem(const char *fname, uint32 start, int hl)
+{
+ int t;
+
+ FILE *fp=FCEUD_UTF8fopen(fname,"rb");
+ while((t=fgetc(fp))>=0)
+ {
+ if(start>0xFFFF) break;
+ if(hl)
+ {
+ extern uint8 *Page[32];
+ if(Page[start/2048])
+ Page[start/2048][start]=t;
+ }
+ else
+ BWrite[start](start,t);
+ start++;
+ }
+ fclose(fp);
+}
+
+#ifdef FCEUDEF_DEBUGGER
+
+static char *fstrings[12]=
+{
+ "#$%02X", // immediate
+ "$%04X", // RELATIVE(jump)
+ "$%02X", // Z
+ "$%02X,X", // Z,x
+ "$%02X,Y", // Z,y
+ "$%04X", //ABS
+ "$%04X,X", // ABS,x
+ "$%04X,Y", // ABS,y
+ "($%04X)", // IND
+ "($%02X,X)", // INX
+ "($%02X),Y", // INY
+ ""
+};
+static int flengths[12]={1,1,1,1,1,2,2,2,2,1,1,0};
+
+#define IMD(x) ((0<<16)|x)
+#define REL(x) ((1<<16)|x)
+#define ZP(x) ((2<<16)|x)
+#define ZPX(x) ((3<<16)|x)
+#define ZPY(x) ((4<<16)|x)
+#define ABS(x) ((5<<16)|x)
+#define ABX(x) ((6<<16)|x)
+#define ABY(x) ((7<<16)|x)
+#define IND(x) ((8<<16)|x)
+#define INX(x) ((9<<16)|x)
+#define INY(x) ((10<<16)|x)
+#define IMP(x) ((11<<16)|x)
+
+typedef struct {
+ char *name;
+ int type; /* 1 for read, 2 for write, 3 for r then write. */
+ int32 modes[10];
+} OPS;
+#define NUMOPS 56
+static OPS optable[NUMOPS]=
+{
+ {"BRK",0,{IMP(0x00),-1}},
+ {"RTI",0,{IMP(0x40),-1}},
+ {"RTS",0,{IMP(0x60),-1}},
+ {"PHA",2,{IMP(0x48),-1}},
+ {"PHP",2,{IMP(0x08),-1}},
+ {"PLA",1,{IMP(0x68),-1}},
+ {"PLP",1,{IMP(0x28),-1}},
+ {"JMP",0,{ABS(0x4C),IND(0x6C),-1}},
+ {"JSR",0,{ABS(0x20),-1}},
+ {"TAX",0,{IMP(0xAA),-1}},
+ {"TXA",0,{IMP(0x8A),-1}},
+ {"TAY",0,{IMP(0xA8),-1}},
+ {"TYA",0,{IMP(0x98),-1}},
+ {"TSX",0,{IMP(0xBA),-1}},
+ {"TXS",0,{IMP(0x9A),-1}},
+ {"DEX",0,{IMP(0xCA),-1}},
+ {"DEY",0,{IMP(0x88),-1}},
+ {"INX",0,{IMP(0xE8),-1}},
+ {"INY",0,{IMP(0xC8),-1}},
+ {"CLC",0,{IMP(0x18),-1}},
+ {"CLD",0,{IMP(0xD8),-1}},
+ {"CLI",0,{IMP(0x58),-1}},
+ {"CLV",0,{IMP(0xB8),-1}},
+ {"SEC",0,{IMP(0x38),-1}},
+ {"SED",0,{IMP(0xF8),-1}},
+ {"SEI",0,{IMP(0x78),-1}},
+ {"NOP",0,{IMP(0xEA),-1}},
+ {"ASL",1,{IMP(0x0a),ZP(0x06),ZPX(0x16),ABS(0x0E),ABX(0x1E),-1}},
+ {"DEC",3,{ZP(0xc6),ZPX(0xd6),ABS(0xcE),ABX(0xdE),-1}},
+ {"INC",3,{ZP(0xe6),ZPX(0xf6),ABS(0xeE),ABX(0xfE),-1}},
+ {"LSR",3,{IMP(0x4a),ZP(0x46),ZPX(0x56),ABS(0x4E),ABX(0x5E),-1}},
+ {"ROL",3,{IMP(0x2a),ZP(0x26),ZPX(0x36),ABS(0x2E),ABX(0x3E),-1}},
+ {"ROR",3,{IMP(0x6a),ZP(0x66),ZPX(0x76),ABS(0x6E),ABX(0x7E),-1}},
+ {"ADC",1,{IMD(0x69),ZP(0x65),ZPX(0x75),ABS(0x6D),ABX(0x7d),ABY(0x79),
+ INX(0x61),INY(0x71),-1}},
+ {"AND",1,{IMD(0x29),ZP(0x25),ZPX(0x35),ABS(0x2D),ABX(0x3d),ABY(0x39),
+ INX(0x21),INY(0x31),-1}},
+ {"BIT",1,{ZP(0x24),ABS(0x2c),-1}},
+ {"CMP",1,{IMD(0xc9),ZP(0xc5),ZPX(0xd5),ABS(0xcD),ABX(0xdd),ABY(0xd9),
+ INX(0xc1),INY(0xd1),-1}},
+ {"CPX",1,{IMD(0xe0),ZP(0xe4),ABS(0xec),-1}},
+ {"CPY",1,{IMD(0xc0),ZP(0xc4),ABS(0xcc),-1}},
+ {"EOR",1,{IMD(0x49),ZP(0x45),ZPX(0x55),ABS(0x4D),ABX(0x5d),ABY(0x59),
+ INX(0x41),INY(0x51),-1}},
+ {"LDA",1,{IMD(0xa9),ZP(0xa5),ZPX(0xb5),ABS(0xaD),ABX(0xbd),ABY(0xb9),
+ INX(0xa1),INY(0xb1),-1}},
+ {"LDX",1,{IMD(0xa2),ZP(0xa6),ZPY(0xB6),ABS(0xae),ABY(0xbe),-1}},
+ {"LDY",1,{IMD(0xa0),ZP(0xa4),ZPX(0xB4),ABS(0xac),ABX(0xbc),-1}},
+ {"ORA",1,{IMD(0x09),ZP(0x05),ZPX(0x15),ABS(0x0D),ABX(0x1d),ABY(0x19),
+ INX(0x01),INY(0x11),-1}},
+ {"SBC",1,{IMD(0xEB),IMD(0xe9),ZP(0xe5),ZPX(0xf5),ABS(0xeD),ABX(0xfd),ABY(0xf9),
+ INX(0xe1),INY(0xf1),-1}},
+ {"STA",2,{ZP(0x85),ZPX(0x95),ABS(0x8D),ABX(0x9d),ABY(0x99),
+ INX(0x81),INY(0x91),-1}},
+ {"STX",2,{ZP(0x86),ZPY(0x96),ABS(0x8E),-1}},
+ {"STY",2,{ZP(0x84),ZPX(0x94),ABS(0x8C),-1}},
+ {"BCC",1,{REL(0x90),-1}},
+ {"BCS",1,{REL(0xb0),-1}},
+ {"BEQ",1,{REL(0xf0),-1}},
+ {"BNE",1,{REL(0xd0),-1}},
+ {"BMI",1,{REL(0x30),-1}},
+ {"BPL",1,{REL(0x10),-1}},
+ {"BVC",1,{REL(0x50),-1}},
+ {"BVS",1,{REL(0x70),-1}},
+};
+
+uint16 FCEUI_Disassemble(void *XA, uint16 a, char *stringo)
+{
+ X6502 *X=XA;
+ uint8 buf;
+ unsigned int arg;
+ int32 info;
+ int x;
+ int y;
+
+ info=-1;
+ fceuindbg=1;
+
+ buf=ARead[a](a);
+ a++;
+
+ for(x=0;x<NUMOPS;x++)
+ {
+ y=0;
+ while(optable[x].modes[y]>=0)
+ {
+ if((optable[x].modes[y]&0xFF)==buf)
+ {
+ info=optable[x].modes[y];
+ goto endy;
+ }
+ y++;
+ }
+ }
+
+ endy:
+ sprintf(stringo,"%02X ",buf);
+ if(info>=0)
+ {
+ int z=flengths[(info>>16)];
+
+ if(z)
+ {
+ arg=ARead[a](a);
+ sprintf(stringo+strlen(stringo),"%02X ",arg);
+ a++;
+ if(z==2) {arg|=ARead[a](a)<<8;sprintf(stringo+strlen(stringo),"%02X ",arg>>8);a++;}
+ else
+ strcat(stringo," ");
+
+ if((info>>16)==1) /* Relative branch */
+ arg=a+(char)arg;
+ sprintf(stringo+strlen(stringo),"%s ",optable[x].name);
+ sprintf(stringo+strlen(stringo),fstrings[info>>16],arg);
+/*
+ 0 "#$%02X", // immediate
+ 1 "$%04X", // RELATIVE(jump)
+ 2 "$%02X", // Z
+ 3 "$%02X,X", // Z,x
+ 4 "$%02X,Y", // Z,y
+ 5 "$%04X", //ABS
+ 6 "$%04X,X", // ABS,x
+ 7 "$%04X,Y", // ABS,y
+ 8 "($%04X)", // IND
+ 9 "($%02X,X)", // INX
+ 10 "($%02X),Y", // INY
+ 11 #define IMP(x) ((11<<16)|x)
+*/
+ {
+ unsigned int tmp;
+ switch(info>>16)
+ {
+ case 2:tmp=arg;
+ if(optable[x].type&1)
+ {
+ sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
+ sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
+ }
+ break;
+ case 3:tmp=(arg+X->X)&0xff;
+ sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
+ if(optable[x].type&1)
+ sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
+ break;
+ case 4:tmp=(arg+X->Y)&0xff;
+ sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
+ if(optable[x].type&1)
+ sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
+ break;
+ case 5:tmp=arg;
+ if(optable[x].type&1)
+ {
+ sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
+ sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
+ }
+ break;
+ case 6:tmp=(arg+X->X)&0xffff;
+ sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
+ if(optable[x].type&1)
+ sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
+ break;
+ case 7:tmp=(arg+X->Y)&0xffff;
+ sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
+ if(optable[x].type&1)
+ sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
+ break;
+ case 8:tmp=ARead[arg](arg)|(ARead[(arg+1)&0xffff]((arg+1)&0xffff)<<8);
+ sprintf(stringo+strlen(stringo)," $%04X",tmp);
+ break;
+ case 9:tmp=(arg+X->X)&0xFF;
+ tmp=ARead[tmp](tmp) | (ARead[(tmp+1)&0xFF]((tmp+1)&0xFF)<<8);
+ sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
+ if(optable[x].type&1)
+ sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
+ break;
+ case 10:tmp=ARead[arg](arg) | (ARead[(arg+1)&0xFF]((arg+1)&0xFF)<<8);
+ tmp=(tmp+X->Y)&0xFFFF;
+ sprintf(stringo+strlen(stringo)," @ $%04X",tmp);
+ if(optable[x].type&1)
+ sprintf(stringo+strlen(stringo)," = $%02X",ARead[tmp](tmp));
+ break;
+
+ }
+ }
+
+
+ }
+ else
+ {
+ strcat(stringo," ");
+ strcat(stringo,optable[x].name);
+ }
+ }
+ else
+ sprintf(stringo+strlen(stringo)," .db $%02X",buf);
+ fceuindbg=0;
+ return(a);
+}
+
+void FCEUI_MemDump(uint16 a, int32 len, void (*callb)(uint16 a, uint8 v))
+{
+ fceuindbg=1;
+ while(len)
+ {
+ callb(a,ARead[a](a));
+ a++;
+ len--;
+ }
+ fceuindbg=0;
+}
+
+uint8 FCEUI_MemSafePeek(uint16 A)
+{
+ uint8 ret;
+
+ fceuindbg=1;
+ ret=ARead[A](A);
+ fceuindbg=0;
+ return(ret);
+}
+
+void FCEUI_MemPoke(uint16 a, uint8 v, int hl)
+{
+ extern uint8 *Page[32];
+ if(hl)
+ {
+ if(Page[a/2048])
+ Page[a/2048][a]=v;
+ }
+ else
+ BWrite[a](a,v);
+}
+
+typedef struct __BPOINT {
+ struct __BPOINT *next;
+ void (*Handler)(X6502 *X, int type, unsigned int A);
+ unsigned int A[2];
+ int type;
+} BPOINT;
+
+static BPOINT *BreakPoints=NULL;
+static BPOINT *LastBP=NULL;
+
+static void (*CPUHook)(X6502 *)=NULL;
+
+static int FindBPoint(X6502 *X, int who, unsigned int A)
+{
+ BPOINT *tmp;
+
+ tmp=BreakPoints;
+ while(tmp)
+ {
+ if(tmp->type&who)
+ {
+ if(tmp->type&BPOINT_PC)
+ if(X->PC!=A) goto don; /* Doesn't match, so go on. */
+
+ if((A>=tmp->A[0]) && (A<=tmp->A[1])) /* Whee, match. */
+ {
+ tmp->Handler(X,tmp->type,A);
+ return(1);
+ }
+ }
+ don:
+ tmp=tmp->next;
+ }
+ return(0);
+}
+
+static uint8 ReadHandler(X6502 *X, unsigned int A)
+{
+ extern X6502 XSave;
+
+ if(X->preexec)
+ FindBPoint(&XSave,BPOINT_READ,A);
+ return(ARead[A](A));
+}
+
+static void WriteHandler(X6502 *X, unsigned int A, uint8 V)
+{
+ extern X6502 XSave;
+
+ if(X->preexec)
+ FindBPoint(&XSave,BPOINT_WRITE,A);
+ else
+ BWrite[A](A,V);
+}
+
+int FCEUI_AddBreakPoint(int type, unsigned int A1, unsigned int A2,
+ void (*Handler)(X6502 *, int type, unsigned int A))
+{
+ BPOINT *tmp;
+
+ tmp=(BPOINT *)malloc(sizeof(BPOINT));
+
+ tmp->A[0]=A1;
+ tmp->A[1]=A2;
+ tmp->Handler=Handler;
+ tmp->type=type;
+ tmp->next=0;
+
+ if(BreakPoints==NULL)
+ BreakPoints=tmp;
+ else
+ LastBP->next=tmp;
+
+ LastBP=tmp;
+
+ X6502_Debug(CPUHook,ReadHandler,WriteHandler);
+ return(1);
+}
+
+int FCEUI_SetBreakPoint(uint32 w, int type, unsigned int A1, unsigned int A2,
+ void (*Handler)(X6502 *, int type, unsigned int A))
+{
+ uint32 x=0;
+ BPOINT *tmp;
+
+ tmp=BreakPoints;
+
+ while(tmp)
+ {
+ if(w==x)
+ {
+ tmp->type=type;
+ tmp->A[0]=A1;
+ tmp->A[1]=A2;
+ tmp->Handler=Handler;
+ return(1);
+ }
+ x++;
+ tmp=tmp->next;
+ }
+ return(0);
+}
+
+int FCEUI_GetBreakPoint(uint32 w, int *type, unsigned int *A1, unsigned int *A2,
+ void (**Handler)(X6502 *, int type, unsigned int A))
+{
+ uint32 x=0;
+ BPOINT *tmp;
+
+ tmp=BreakPoints;
+
+ while(tmp)
+ {
+ if(w==x)
+ {
+ *type=tmp->type;
+ *A1=tmp->A[0];
+ *A2=tmp->A[1];
+ *Handler=tmp->Handler;
+ return(1);
+ }
+ x++;
+ tmp=tmp->next;
+ }
+ return(0);
+}
+
+int FCEUI_ListBreakPoints(int (*callb)(int type, unsigned int A1, unsigned int A2,
+ void (*Handler)(X6502 *, int type, unsigned int A) ))
+{
+ BPOINT *tmp;
+ tmp=BreakPoints;
+ while(tmp)
+ {
+ callb(tmp->type,tmp->A[0],tmp->A[1],tmp->Handler);
+ tmp=tmp->next;
+ }
+ return(1);
+}
+
+int FCEUI_DeleteBreakPoint(uint32 w)
+{
+ BPOINT *tmp,*prev=NULL;
+ uint32 x=0;
+
+ tmp=BreakPoints;
+
+ while(tmp)
+ {
+ if(w==x)
+ {
+ if(prev) /* Not the first breakpoint. */
+ {
+ if(tmp->next) /* More breakpoints. */
+ prev->next=tmp->next;
+ else /* This is the last breakpoint. */
+ {
+ prev->next=0;
+ LastBP=prev;
+ }
+ }
+ else /* The first breakpoint. */
+ {
+ if(tmp->next) /* More breakpoints. */
+ BreakPoints=tmp->next;
+ else
+ {
+ BreakPoints=LastBP=0; /* No more breakpoints. */
+ /* Update the CPU hooks. */
+ X6502_Debug(CPUHook,BreakPoints?ReadHandler:0,BreakPoints?WriteHandler:0);
+ }
+ }
+ free(tmp);
+ return(1);
+ }
+ prev=tmp;
+ tmp=tmp->next;
+ x++;
+ }
+ return(0);
+}
+
+void FCEUI_SetCPUCallback(void (*callb)(X6502 *X))
+{
+ CPUHook=callb;
+ X6502_Debug(CPUHook,BreakPoints?ReadHandler:0,BreakPoints?WriteHandler:0);
+}
+#endif
diff --git a/debug.h b/debug.h
new file mode 100644
index 00000000..66697fac
--- /dev/null
+++ b/debug.h
@@ -0,0 +1,24 @@
+void FCEUI_DumpMem(const char *fname, uint32 start, uint32 end);
+void FCEUI_DumpVid(const char *fname, uint32 start, uint32 end);
+void FCEUI_LoadMem(const char *fname, uint32 start, int hl);
+
+#ifdef FCEUDEF_DEBUGGER
+
+/* Type attributes, you can OR them together. */
+#define BPOINT_READ 1
+#define BPOINT_WRITE 2
+#define BPOINT_PC 4
+
+#include "x6502struct.h"
+
+void FCEUI_SetCPUCallback(void (*callb)(X6502 *X));
+int FCEUI_DeleteBreakPoint(uint32 w);
+int FCEUI_ListBreakPoints(int (*callb)(int type, unsigned int A1, unsigned int A2,
+ void (*Handler)(X6502 *, int type, unsigned int A) ));
+int FCEUI_GetBreakPoint(uint32 w, int *type, unsigned int *A1, unsigned int *A2,
+ void (**Handler)(X6502 *, int type, unsigned int A));
+int FCEUI_SetBreakPoint(uint32 w, int type, unsigned int A1, unsigned int A2,
+ void (*Handler)(X6502 *, int type, unsigned int A));
+int FCEUI_AddBreakPoint(int type, unsigned int A1, unsigned int A2,
+ void (*Handler)(X6502 *, int type, unsigned int A));
+#endif
diff --git a/drawing.h b/drawing.h
new file mode 100644
index 00000000..0fbcb62a
--- /dev/null
+++ b/drawing.h
@@ -0,0 +1,228 @@
+void DrawTextLineBG(uint8 *dest)
+{
+ int x,y;
+ static int otable[7]={81,49,30,17,8,3,0};
+ //100,40,15,10,7,5,2};
+ for(y=0;y<14;y++)
+ {
+ int offs;
+
+ if(y>=7) offs=otable[13-y];
+ else offs=otable[y];
+
+ for(x=offs;x<(256-offs);x++)
+ dest[y*256+x]=(dest[y*256+x]&0x0f)|0xC0;//&=0xe0; //0x80;
+ }
+}
+
+static void DrawMessage(void)
+{
+ if(howlong)
+ {
+ uint8 *t;
+ howlong--;
+ t=XBuf+(FSettings.LastSLine-20)*256;
+ if(t>=XBuf)
+ {
+ DrawTextLineBG(t);
+ DrawTextTrans(t+256*3+(128-strlen(errmsg)*4),256,(uint8 *)errmsg,4);
+ }
+ }
+}
+
+uint8 fontdata2[2048] =
+{
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x81,0xa5,0x81,0xbd,0x99,0x81,0x7e,0x7e,0xff,0xdb,0xff,0xc3,0xe7,0xff,0x7e,0x36,0x7f,0x7f,0x7f,0x3e,0x1c,0x08,0x00,0x08,0x1c,0x3e,0x7f,0x3e,0x1c,0x08,0x00,0x1c,0x3e,0x1c,0x7f,0x7f,0x3e,0x1c,0x3e,0x08,0x08,0x1c,0x3e,0x7f,0x3e,0x1c,0x3e,0x00,0x00,0x18,0x3c,0x3c,0x18,0x00,0x00,0xff,0xff,0xe7,0xc3,0xc3,0xe7,0xff,0xff,0x00,0x3c,0x66,0x42,0x42,0x66,0x3c,0x00,0xff,0xc3,0x99,0xbd,0xbd,0x99,0xc3,0xff,0xf0,0xe0,0xf0,0xbe,0x33,0x33,0x33,0x1e,0x3c,0x66,0x66,0x66,0x3c,0x18,0x7e,0x18,0xfc,0xcc,0xfc,0x0c,0x0c,0x0e,0x0f,0x07,0xfe,0xc6,0xfe,0xc6,0xc6,0xe6,0x67,0x03,0x99,0x5a,0x3c,0xe7,0xe7,0x3c,0x5a,0x99,0x01,0x07,0x1f,0x7f,0x1f,0x07,0x01,0x00,0x40,0x70,0x7c,0x7f,0x7c,0x70,0x40,0x00,0x18,0x3c,0x7e,0x18,0x18,0x7e,0x3c,0x18,0x66,0x66,0x66,0x66,0x66,0x00,0x66,0x00,0xfe,0xdb,0xdb,0xde,0xd8,0xd8,0xd8,0x00,0x7c,0xc6,0x1c,0x36,0x36,0x1c,0x33,0x1e,0x00,0x00,0x00,0x00,0x7e,0x7e,0x7e,0x00,0x18,0x3c,0x7e,0x18,0x7e,0x3c,0x18,0xff,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x7e,0x3c,0x18,0x00,0x00,0x18,0x30,0x7f,0x30,0x18,0x00,0x00,0x00,0x0c,0x06,0x7f,0x06,0x0c,0x00,0x00,0x00,0x00,0x03,0x03,0x03,0x7f,0x00,0x00,0x00,0x24,0x66,0xff,0x66,0x24,0x00,0x00,0x00,0x18,0x3c,0x7e,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0x7e,0x3c,0x18,0x00,0x00,
+0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x1e,0x1e,0x0c,0x0c,0x00,0x0c,0x00,0x36,0x36,0x36,0x00,0x00,0x00,0x00,0x00,0x36,0x36,0x7f,0x36,0x7f,0x36,0x36,0x00,0x0c,0x3e,0x03,0x1e,0x30,0x1f,0x0c,0x00,0x00,0x63,0x33,0x18,0x0c,0x66,0x63,0x00,0x1c,0x36,0x1c,0x6e,0x3b,0x33,0x6e,0x00,0x06,0x06,0x03,0x00,0x00,0x00,0x00,0x00,0x18,0x0c,0x06,0x06,0x06,0x0c,0x18,0x00,0x06,0x0c,0x18,0x18,0x18,0x0c,0x06,0x00,0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00,0x00,0x0c,0x0c,0x3f,0x0c,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0c,0x06,0x00,0x00,0x00,0x3f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x0c,0x00,0x60,0x30,0x18,0x0c,0x06,0x03,0x01,0x00,0x3e,0x63,0x73,0x7b,0x6f,0x67,0x3e,0x00,0x0c,0x0e,0x0c,0x0c,0x0c,0x0c,0x3f,0x00,0x1e,0x33,0x30,0x1c,0x06,0x33,0x3f,0x00,0x1e,0x33,0x30,0x1c,0x30,0x33,0x1e,0x00,0x38,0x3c,0x36,0x33,0x7f,0x30,0x78,0x00,0x3f,0x03,0x1f,0x30,0x30,0x33,0x1e,0x00,0x1c,0x06,0x03,0x1f,0x33,0x33,0x1e,0x00,0x3f,0x33,0x30,0x18,0x0c,0x0c,0x0c,0x00,0x1e,0x33,0x33,0x1e,0x33,0x33,0x1e,0x00,0x1e,0x33,0x33,0x3e,0x30,0x18,0x0e,0x00,0x00,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x00,0x00,0x0c,0x0c,0x06,0x18,0x0c,0x06,0x03,0x06,0x0c,0x18,0x00,0x00,0x00,0x3f,0x00,0x00,0x3f,0x00,0x00,0x06,0x0c,0x18,0x30,0x18,0x0c,0x06,0x00,0x1e,0x33,0x30,0x18,0x0c,0x00,0x0c,0x00,
+0x3e,0x63,0x7b,0x7b,0x7b,0x03,0x1e,0x00,0x0c,0x1e,0x33,0x33,0x3f,0x33,0x33,0x00,0x3f,0x66,0x66,0x3e,0x66,0x66,0x3f,0x00,0x3c,0x66,0x03,0x03,0x03,0x66,0x3c,0x00,0x1f,0x36,0x66,0x66,0x66,0x36,0x1f,0x00,0x7f,0x46,0x16,0x1e,0x16,0x46,0x7f,0x00,0x7f,0x46,0x16,0x1e,0x16,0x06,0x0f,0x00,0x3c,0x66,0x03,0x03,0x73,0x66,0x7c,0x00,0x33,0x33,0x33,0x3f,0x33,0x33,0x33,0x00,0x1e,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x78,0x30,0x30,0x30,0x33,0x33,0x1e,0x00,0x67,0x66,0x36,0x1e,0x36,0x66,0x67,0x00,0x0f,0x06,0x06,0x06,0x46,0x66,0x7f,0x00,0x63,0x77,0x7f,0x7f,0x6b,0x63,0x63,0x00,0x63,0x67,0x6f,0x7b,0x73,0x63,0x63,0x00,0x1c,0x36,0x63,0x63,0x63,0x36,0x1c,0x00,0x3f,0x66,0x66,0x3e,0x06,0x06,0x0f,0x00,0x1e,0x33,0x33,0x33,0x3b,0x1e,0x38,0x00,0x3f,0x66,0x66,0x3e,0x36,0x66,0x67,0x00,0x1e,0x33,0x07,0x0e,0x38,0x33,0x1e,0x00,0x3f,0x2d,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x33,0x33,0x33,0x33,0x33,0x33,0x3f,0x00,0x33,0x33,0x33,0x33,0x33,0x1e,0x0c,0x00,0x63,0x63,0x63,0x6b,0x7f,0x77,0x63,0x00,0x63,0x63,0x36,0x1c,0x1c,0x36,0x63,0x00,0x33,0x33,0x33,0x1e,0x0c,0x0c,0x1e,0x00,0x7f,0x63,0x31,0x18,0x4c,0x66,0x7f,0x00,0x1e,0x06,0x06,0x06,0x06,0x06,0x1e,0x00,0x03,0x06,0x0c,0x18,0x30,0x60,0x40,0x00,0x1e,0x18,0x18,0x18,0x18,0x18,0x1e,0x00,0x08,0x1c,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,
+0x0c,0x0c,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1e,0x30,0x3e,0x33,0x6e,0x00,0x07,0x06,0x06,0x3e,0x66,0x66,0x3b,0x00,0x00,0x00,0x1e,0x33,0x03,0x33,0x1e,0x00,0x38,0x30,0x30,0x3e,0x33,0x33,0x6e,0x00,0x00,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x1c,0x36,0x06,0x0f,0x06,0x06,0x0f,0x00,0x00,0x00,0x6e,0x33,0x33,0x3e,0x30,0x1f,0x07,0x06,0x36,0x6e,0x66,0x66,0x67,0x00,0x0c,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x30,0x00,0x30,0x30,0x30,0x33,0x33,0x1e,0x07,0x06,0x66,0x36,0x1e,0x36,0x67,0x00,0x0e,0x0c,0x0c,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x00,0x33,0x7f,0x7f,0x6b,0x63,0x00,0x00,0x00,0x1f,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x1e,0x33,0x33,0x33,0x1e,0x00,0x00,0x00,0x3b,0x66,0x66,0x3e,0x06,0x0f,0x00,0x00,0x6e,0x33,0x33,0x3e,0x30,0x78,0x00,0x00,0x3b,0x6e,0x66,0x06,0x0f,0x00,0x00,0x00,0x3e,0x03,0x1e,0x30,0x1f,0x00,0x08,0x0c,0x3e,0x0c,0x0c,0x2c,0x18,0x00,0x00,0x00,0x33,0x33,0x33,0x33,0x6e,0x00,0x00,0x00,0x33,0x33,0x33,0x1e,0x0c,0x00,0x00,0x00,0x63,0x6b,0x7f,0x7f,0x36,0x00,0x00,0x00,0x63,0x36,0x1c,0x36,0x63,0x00,0x00,0x00,0x33,0x33,0x33,0x3e,0x30,0x1f,0x00,0x00,0x3f,0x19,0x0c,0x26,0x3f,0x00,0x38,0x0c,0x0c,0x07,0x0c,0x0c,0x38,0x00,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00,0x07,0x0c,0x0c,0x38,0x0c,0x0c,0x07,0x00,0x6e,0x3b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x1c,0x36,0x63,0x63,0x7f,0x00,
+0x1e,0x33,0x03,0x33,0x1e,0x18,0x30,0x1e,0x00,0x33,0x00,0x33,0x33,0x33,0x7e,0x00,0x38,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x7e,0xc3,0x3c,0x60,0x7c,0x66,0xfc,0x00,0x33,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x07,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x0c,0x0c,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x00,0x00,0x1e,0x03,0x03,0x1e,0x30,0x1c,0x7e,0xc3,0x3c,0x66,0x7e,0x06,0x3c,0x00,0x33,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x07,0x00,0x1e,0x33,0x3f,0x03,0x1e,0x00,0x33,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x3e,0x63,0x1c,0x18,0x18,0x18,0x3c,0x00,0x07,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x63,0x1c,0x36,0x63,0x7f,0x63,0x63,0x00,0x0c,0x0c,0x00,0x1e,0x33,0x3f,0x33,0x00,0x38,0x00,0x3f,0x06,0x1e,0x06,0x3f,0x00,0x00,0x00,0xfe,0x30,0xfe,0x33,0xfe,0x00,0x7c,0x36,0x33,0x7f,0x33,0x33,0x73,0x00,0x1e,0x33,0x00,0x1e,0x33,0x33,0x1e,0x00,0x00,0x33,0x00,0x1e,0x33,0x33,0x1e,0x00,0x00,0x07,0x00,0x1e,0x33,0x33,0x1e,0x00,0x1e,0x33,0x00,0x33,0x33,0x33,0x7e,0x00,0x00,0x07,0x00,0x33,0x33,0x33,0x7e,0x00,0x00,0x33,0x00,0x33,0x33,0x3e,0x30,0x1f,0xc3,0x18,0x3c,0x66,0x66,0x3c,0x18,0x00,0x33,0x00,0x33,0x33,0x33,0x33,0x1e,0x00,0x18,0x18,0x7e,0x03,0x03,0x7e,0x18,0x18,0x1c,0x36,0x26,0x0f,0x06,0x67,0x3f,0x00,0x33,0x33,0x1e,0x3f,0x0c,0x3f,0x0c,0x0c,0x1f,0x33,0x33,0x5f,0x63,0xf3,0x63,0xe3,0x70,0xd8,0x18,0x3c,0x18,0x18,0x1b,0x0e,
+0x38,0x00,0x1e,0x30,0x3e,0x33,0x7e,0x00,0x1c,0x00,0x0e,0x0c,0x0c,0x0c,0x1e,0x00,0x00,0x38,0x00,0x1e,0x33,0x33,0x1e,0x00,0x00,0x38,0x00,0x33,0x33,0x33,0x7e,0x00,0x00,0x1f,0x00,0x1f,0x33,0x33,0x33,0x00,0x3f,0x00,0x33,0x37,0x3f,0x3b,0x33,0x00,0x3c,0x36,0x36,0x7c,0x00,0x7e,0x00,0x00,0x1c,0x36,0x36,0x1c,0x00,0x3e,0x00,0x00,0x0c,0x00,0x0c,0x06,0x03,0x33,0x1e,0x00,0x00,0x00,0x00,0x3f,0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x3f,0x30,0x30,0x00,0x00,0xc3,0x63,0x33,0x7b,0xcc,0x66,0x33,0xf0,0xc3,0x63,0x33,0xdb,0xec,0xf6,0xf3,0xc0,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x00,0x00,0xcc,0x66,0x33,0x66,0xcc,0x00,0x00,0x00,0x33,0x66,0xcc,0x66,0x33,0x00,0x00,0x44,0x11,0x44,0x11,0x44,0x11,0x44,0x11,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xaa,0x55,0xdb,0xee,0xdb,0x77,0xdb,0xee,0xdb,0x77,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x18,0x18,0x18,0x18,0x1f,0x18,0x1f,0x18,0x18,0x18,0x6c,0x6c,0x6c,0x6c,0x6f,0x6c,0x6c,0x6c,0x00,0x00,0x00,0x00,0x7f,0x6c,0x6c,0x6c,0x00,0x00,0x1f,0x18,0x1f,0x18,0x18,0x18,0x6c,0x6c,0x6f,0x60,0x6f,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x00,0x00,0x7f,0x60,0x6f,0x6c,0x6c,0x6c,0x6c,0x6c,0x6f,0x60,0x7f,0x00,0x00,0x00,0x6c,0x6c,0x6c,0x6c,0x7f,0x00,0x00,0x00,0x18,0x18,0x1f,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x18,0x18,0x18,
+0x18,0x18,0x18,0x18,0xf8,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xff,0x00,0x00,0x00,0x18,0x18,0x18,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0xf8,0x18,0xf8,0x18,0x18,0x18,0x6c,0x6c,0x6c,0x6c,0xec,0x6c,0x6c,0x6c,0x6c,0x6c,0xec,0x0c,0xfc,0x00,0x00,0x00,0x00,0x00,0xfc,0x0c,0xec,0x6c,0x6c,0x6c,0x6c,0x6c,0xef,0x00,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xef,0x6c,0x6c,0x6c,0x6c,0x6c,0xec,0x0c,0xec,0x6c,0x6c,0x6c,0x00,0x00,0xff,0x00,0xff,0x00,0x00,0x00,0x6c,0x6c,0xef,0x00,0xef,0x6c,0x6c,0x6c,0x18,0x18,0xff,0x00,0xff,0x00,0x00,0x00,0x6c,0x6c,0x6c,0x6c,0xff,0x00,0x00,0x00,0x00,0x00,0xff,0x00,0xff,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xff,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0xfc,0x00,0x00,0x00,0x18,0x18,0xf8,0x18,0xf8,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0xf8,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0xfc,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0x6c,0xff,0x6c,0x6c,0x6c,0x18,0x18,0xff,0x18,0xff,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x18,0x18,0x18,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0x0f,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xf0,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
+0x00,0x00,0x6e,0x3b,0x13,0x3b,0x6e,0x00,0x00,0x1e,0x33,0x1f,0x33,0x1f,0x03,0x03,0x00,0x3f,0x33,0x03,0x03,0x03,0x03,0x00,0x00,0x7f,0x36,0x36,0x36,0x36,0x36,0x00,0x3f,0x33,0x06,0x0c,0x06,0x33,0x3f,0x00,0x00,0x00,0x7e,0x1b,0x1b,0x1b,0x0e,0x00,0x00,0x66,0x66,0x66,0x66,0x3e,0x06,0x03,0x00,0x6e,0x3b,0x18,0x18,0x18,0x18,0x00,0x3f,0x0c,0x1e,0x33,0x33,0x1e,0x0c,0x3f,0x1c,0x36,0x63,0x7f,0x63,0x36,0x1c,0x00,0x1c,0x36,0x63,0x63,0x36,0x36,0x77,0x00,0x38,0x0c,0x18,0x3e,0x33,0x33,0x1e,0x00,0x00,0x00,0x7e,0xdb,0xdb,0x7e,0x00,0x00,0x60,0x30,0x7e,0xdb,0xdb,0x7e,0x06,0x03,0x1c,0x06,0x03,0x1f,0x03,0x06,0x1c,0x00,0x1e,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x3f,0x00,0x3f,0x00,0x3f,0x00,0x00,0x0c,0x0c,0x3f,0x0c,0x0c,0x00,0x3f,0x00,0x06,0x0c,0x18,0x0c,0x06,0x00,0x3f,0x00,0x18,0x0c,0x06,0x0c,0x18,0x00,0x3f,0x00,0x70,0xd8,0xd8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1b,0x1b,0x0e,0x0c,0x0c,0x00,0x3f,0x00,0x0c,0x0c,0x00,0x00,0x6e,0x3b,0x00,0x6e,0x3b,0x00,0x00,0x1c,0x36,0x36,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0xf0,0x30,0x30,0x30,0x37,0x36,0x3c,0x38,0x1e,0x36,0x36,0x36,0x36,0x00,0x00,0x00,0x0e,0x18,0x0c,0x06,0x1e,0x00,0x00,0x00,0x00,0x00,0x3c,0x3c,0x3c,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
+
+void DrawTextTrans(uint8 *dest, uint32 width, uint8 *textmsg, uint8 fgcolor)
+{
+ uint8 length=strlen((char *)textmsg);
+ uint8 x;
+ uint8 y;
+ uint8 z;
+
+ for(x=0;x<length;x++)
+ for(y=0;y<8;y++)
+ for(z=0;z<8;z++)
+ if((fontdata2[(textmsg[x]<<3)+y]>>z)&1) dest[y*width+(x<<3)+z]=fgcolor;
+}
+
+static uint8 sstat[2541] =
+{
+0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,
+0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x83,0x83,0x83,
+0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x80,0x83,
+0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,
+0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,
+0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x81,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,
+0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,
+0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,
+0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,
+0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x83,0x80,0x80,0x81,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x80,0x83,0x83,0x81,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x81,0x81,0x81,0x83,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80
+};
+
+void FCEU_DrawNumberRow(uint8 *XBuf, int *nstatus, int cur)
+{
+ uint8 *XBaf;
+ int z,x,y;
+
+ XBaf=XBuf - 4 + (FSettings.LastSLine-34)*256;
+ if(XBaf>=XBuf)
+ for(z=1;z<11;z++)
+ {
+ if(nstatus[z%10])
+ {
+ for(y=0;y<13;y++)
+ for(x=0;x<21;x++)
+ XBaf[y*256+x+z*21+z]=sstat[y*21+x+(z-1)*21*12]^0x80;
+ } else {
+ for(y=0;y<13;y++)
+ for(x=0;x<21;x++)
+ if(sstat[y*21+x+(z-1)*21*12]!=0x83)
+ XBaf[y*256+x+z*21+z]=sstat[y*21+x+(z-1)*21*12]^0x80;
+
+ else
+ XBaf[y*256+x+z*21+z]=(XBaf[y*256+x+z*21+z]&0xF)|0xC0;
+ }
+ if(cur==z%10)
+ {
+ for(x=0;x<21;x++)
+ XBaf[x+z*21+z*1]=4;
+ for(x=1;x<12;x++)
+ {
+ XBaf[256*x+z*21+z*1]=
+ XBaf[256*x+z*21+z*1+20]=4;
+ }
+ for(x=0;x<21;x++)
+ XBaf[12*256+x+z*21+z*1]=4;
+ }
+ }
+}
+
+static uint8 play_slines[]=
+{
+ 0, 0, 1,
+ 1, 0, 2,
+ 2, 0, 3,
+ 3, 0, 4,
+ 4, 0, 5,
+ 5, 0, 6,
+ 6, 0, 7,
+ 7, 0, 8,
+ 8, 0, 7,
+ 9, 0, 6,
+ 10, 0, 5,
+ 11, 0, 4,
+ 12, 0, 3,
+ 13, 0, 2,
+ 14, 0, 1,
+ 99,
+};
+
+static uint8 record_slines[]=
+{
+ 0, 5, 9,
+ 1, 3, 11,
+ 2, 2, 12,
+ 3, 1, 13,
+ 4, 1, 13,
+ 5, 0, 14,
+ 6, 0, 14,
+ 7, 0, 14,
+ 8, 0, 14,
+ 9, 0, 14,
+ 10, 1, 13,
+ 11, 1, 13,
+ 12, 2, 12,
+ 13, 3, 11,
+ 14, 5, 9,
+ 99,
+};
+
+static uint8 pause_slines[]=
+{
+ 0, 2, 6,
+ 1, 2, 6,
+ 2, 2, 6,
+ 3, 2, 6,
+ 4, 2, 6,
+ 5, 2, 6,
+ 6, 2, 6,
+ 7, 2, 6,
+ 8, 2, 6,
+ 9, 2, 6,
+ 10, 2, 6,
+ 11, 2, 6,
+ 12, 2, 6,
+ 13, 2, 6,
+ 14, 2, 6,
+
+ 0, 9, 13,
+ 1, 9, 13,
+ 2, 9, 13,
+ 3, 9, 13,
+ 4, 9, 13,
+ 5, 9, 13,
+ 6, 9, 13,
+ 7, 9, 13,
+ 8, 9, 13,
+ 9, 9, 13,
+ 10, 9, 13,
+ 11, 9, 13,
+ 12, 9, 13,
+ 13, 9, 13,
+ 14, 9, 13,
+ 99,
+};
+
+static uint8 no_slines[]=
+{
+ 99
+};
+
+static uint8* sline_icons[4]=
+{
+ no_slines,
+ play_slines,
+ record_slines,
+ pause_slines
+};
+
+void FCEU_DrawRecordingStatusN(uint8* XBuf, int n)
+{
+ uint8* slines=sline_icons[n];
+ int i;
+
+ XBuf += (FSettings.LastSLine-28)*256 + 240 + 255;
+ for(i=0; slines[i]!=99; i+=3)
+ {
+ int y=slines[i];
+ uint8* dest=XBuf+(y*256);
+ int x;
+ for(x=slines[i+1]; x!=slines[i+2]; ++x)
+ dest[x]=0;
+ }
+
+ XBuf -= 255;
+ for(i=0; slines[i]!=99; i+=3)
+ {
+ int y=slines[i];
+ uint8* dest=XBuf+(y*256);
+ int x;
+ for(x=slines[i+1]; x!=slines[i+2]; ++x)
+ dest[x]=4;
+ }
+}
diff --git a/driver.h b/driver.h
new file mode 100644
index 00000000..497cb8e0
--- /dev/null
+++ b/driver.h
@@ -0,0 +1,317 @@
+#ifndef __DRIVER_H_
+#define __DRIVER_H_
+
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "types.h"
+#include "git.h"
+#include "debug.h"
+
+FILE *FCEUD_UTF8fopen(const char *fn, const char *mode);
+
+/* This makes me feel dirty for some reason. */
+void FCEU_printf(char *format, ...);
+#define FCEUI_printf FCEU_printf
+
+/* Video interface */
+void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b);
+void FCEUD_GetPalette(uint8 i,uint8 *r, uint8 *g, uint8 *b);
+
+/* Displays an error. Can block or not. */
+void FCEUD_PrintError(char *s);
+void FCEUD_Message(char *s);
+
+#ifdef NETWORK
+/* Network interface */
+
+/* Call only when a game is loaded. */
+int FCEUI_NetplayStart(int nlocal, int divisor);
+
+/* Call when network play needs to stop. */
+void FCEUI_NetplayStop(void);
+
+/* Note: YOU MUST NOT CALL ANY FCEUI_* FUNCTIONS WHILE IN FCEUD_SendData() or
+ FCEUD_RecvData().
+*/
+
+/* Return 0 on failure, 1 on success. */
+int FCEUD_SendData(void *data, uint32 len);
+int FCEUD_RecvData(void *data, uint32 len);
+
+/* Display text received over the network. */
+void FCEUD_NetplayText(uint8 *text);
+
+/* Encode and send text over the network. */
+void FCEUI_NetplayText(uint8 *text);
+
+/* Called when a fatal error occurred and network play can't continue. This function
+ should call FCEUI_NetplayStop() after it has deinitialized the network on the driver
+ side.
+*/
+void FCEUD_NetworkClose(void);
+#endif
+
+int FCEUI_BeginWaveRecord(char *fn);
+int FCEUI_EndWaveRecord(void);
+
+void FCEUI_ResetNES(void);
+void FCEUI_PowerNES(void);
+
+void FCEUI_NTSCSELHUE(void);
+void FCEUI_NTSCSELTINT(void);
+void FCEUI_NTSCDEC(void);
+void FCEUI_NTSCINC(void);
+void FCEUI_GetNTSCTH(int *tint, int *hue);
+void FCEUI_SetNTSCTH(int n, int tint, int hue);
+
+void FCEUI_SetInput(int port, int type, void *ptr, int attrib);
+void FCEUI_SetInputFC(int type, void *ptr, int attrib);
+void FCEUI_DisableFourScore(int s);
+
+#define SI_NONE 0
+#define SI_GAMEPAD 1
+#define SI_ZAPPER 2
+#define SI_POWERPADA 3
+#define SI_POWERPADB 4
+#define SI_ARKANOID 5
+
+#define SIFC_NONE 0
+#define SIFC_ARKANOID 1
+#define SIFC_SHADOW 2
+#define SIFC_4PLAYER 3
+#define SIFC_FKB 4
+#define SIFC_SUBORKB 5
+#define SIFC_HYPERSHOT 6
+#define SIFC_MAHJONG 7
+#define SIFC_QUIZKING 8
+#define SIFC_FTRAINERA 9
+#define SIFC_FTRAINERB 10
+#define SIFC_OEKAKIDS 11
+#define SIFC_BWORLD 12
+#define SIFC_TOPRIDER 13
+
+#define SIS_NONE 0
+#define SIS_DATACH 1
+#define SIS_NWC 2
+#define SIS_VSUNISYSTEM 3
+#define SIS_NSF 4
+
+/* New interface functions */
+
+/* 0 to order screen snapshots numerically(0.png), 1 to order them file base-numerically(smb3-0.png). */
+void FCEUI_SetSnapName(int a);
+
+/* 0 to keep 8-sprites limitation, 1 to remove it */
+void FCEUI_DisableSpriteLimitation(int a);
+
+/* -1 = no change, 0 = show, 1 = hide, 2 = internal toggle */
+void FCEUI_SetRenderDisable(int sprites, int bg);
+
+/* name=path and file to load. returns 0 on failure, 1 on success */
+FCEUGI *FCEUI_LoadGame(const char *name, int OverwriteVidMode);
+
+/* allocates memory. 0 on failure, 1 on success. */
+int FCEUI_Initialize(void);
+
+/* Emulates a frame. */
+void FCEUI_Emulate(uint8 **, int32 **, int32 *, int);
+
+/* Closes currently loaded game */
+void FCEUI_CloseGame(void);
+
+/* Deallocates all allocated memory. Call after FCEUI_Emulate() returns. */
+void FCEUI_Kill(void);
+
+/* Enable/Disable game genie. a=0 disable, a=1 enable */
+void FCEUI_SetGameGenie(int a);
+
+/* Set video system a=0 NTSC, a=1 PAL */
+void FCEUI_SetVidSystem(int a);
+
+/* Convenience function; returns currently emulated video system(0=NTSC, 1=PAL). */
+int FCEUI_GetCurrentVidSystem(int *slstart, int *slend);
+
+#ifdef FRAMESKIP
+/* Should be called from FCEUD_BlitScreen(). Specifies how many frames
+ to skip until FCEUD_BlitScreen() is called. FCEUD_BlitScreenDummy()
+ will be called instead of FCEUD_BlitScreen() when when a frame is skipped.
+*/
+void FCEUI_FrameSkip(int x);
+#endif
+
+/* First and last scanlines to render, for ntsc and pal emulation. */
+void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall);
+
+/* Sets the base directory(save states, snapshots, etc. are saved in directories
+ below this directory. */
+void FCEUI_SetBaseDirectory(char *dir);
+
+/* Tells FCE Ultra to copy the palette data pointed to by pal and use it.
+ Data pointed to by pal needs to be 64*3 bytes in length.
+*/
+void FCEUI_SetPaletteArray(uint8 *pal);
+
+/* Sets up sound code to render sound at the specified rate, in samples
+ per second. Only sample rates of 44100, 48000, and 96000 are currently
+ supported.
+ If "Rate" equals 0, sound is disabled.
+*/
+void FCEUI_Sound(int Rate);
+void FCEUI_SetSoundVolume(uint32 volume);
+void FCEUI_SetSoundQuality(int quality);
+
+void FCEUD_SoundToggle(void);
+void FCEUD_SoundVolumeAdjust(int);
+
+int FCEUI_SelectState(int, int);
+
+/* "fname" overrides the default save state filename code if non-NULL. */
+void FCEUI_SaveState(char *fname);
+void FCEUI_LoadState(char *fname);
+
+void FCEUD_SaveStateAs(void);
+void FCEUD_LoadStateFrom(void);
+
+#define MOVIE_FLAG_FROM_RESET (1<<1)
+#define MOVIE_FLAG_PAL (1<<2)
+#define MOVIE_FLAG_FROM_POWERON (1<<3) // value is temporary onle, gets converted to reset
+#define MOVIE_MAX_METADATA 512
+
+typedef struct
+{
+ int movie_version; // version of the movie format in the file
+ uint32 num_frames;
+ uint32 rerecord_count;
+ uint8 flags;
+ int read_only;
+ uint32 emu_version_used; // 9813 = 0.98.13
+ char* metadata; // caller-supplied buffer to store metadata. can be NULL.
+ int metadata_size; // size of the buffer pointed to by metadata
+ uint8 md5_of_rom_used[16];
+ int md5_of_rom_used_present; // v1 movies don't have md5 info available
+ char* name_of_rom_used; // caller-supplied buffer to store metadata. can be NULL.
+ int name_of_rom_used_size; // size of the buffer pointer to by name_of_rom_used
+} MOVIE_INFO;
+
+int FCEUI_SelectMovie(int, int);
+void FCEUI_SaveMovie(char *fname, uint8 flags, const char* metadata);
+void FCEUI_LoadMovie(char *fname, int read_only, int _stopframe);
+void FCEUI_StopMovie(void);
+int FCEUI_IsMovieActive(void);
+int FCEUI_MovieGetInfo(const char* fname, MOVIE_INFO* /* [in, out] */ info);
+char* FCEUI_MovieGetCurrentName(int addSlotNumber);
+void FCEUI_MovieToggleReadOnly(void);
+void FCEUI_MovieToggleFrameDisplay(void);
+void FCEUI_ToggleInputDisplay(void);
+
+void FCEUD_MovieRecordTo(void);
+void FCEUD_MovieReplayFrom(void);
+
+int32 FCEUI_GetDesiredFPS(void);
+void FCEUI_SaveSnapshot(void);
+void FCEU_DispMessage(char *format, ...);
+#define FCEUI_DispMessage FCEU_DispMessage
+
+int FCEUI_DecodePAR(const char *code, uint16 *a, uint8 *v, int *c, int *type);
+int FCEUI_DecodeGG(const char *str, uint16 *a, uint8 *v, int *c);
+int FCEUI_AddCheat(const char *name, uint32 addr, uint8 val, int compare, int type);
+int FCEUI_DelCheat(uint32 which);
+int FCEUI_ToggleCheat(uint32 which);
+
+int32 FCEUI_CheatSearchGetCount(void);
+void FCEUI_CheatSearchGetRange(uint32 first, uint32 last, int (*callb)(uint32 a, uint8 last, uint8 current));
+void FCEUI_CheatSearchGet(int (*callb)(uint32 a, uint8 last, uint8 current, void *data), void *data);
+void FCEUI_CheatSearchBegin(void);
+void FCEUI_CheatSearchEnd(int type, uint8 v1, uint8 v2);
+void FCEUI_ListCheats(int (*callb)(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data), void *data);
+
+int FCEUI_GetCheat(uint32 which, char **name, uint32 *a, uint8 *v, int *compare, int *s, int *type);
+int FCEUI_SetCheat(uint32 which, const char *name, int32 a, int32 v, int compare,int s, int type);
+
+void FCEUI_CheatSearchShowExcluded(void);
+void FCEUI_CheatSearchSetCurrentAsOriginal(void);
+
+#define FCEUIOD_STATE 0
+#define FCEUIOD_SNAPS 1
+#define FCEUIOD_NV 2
+#define FCEUIOD_CHEATS 3
+#define FCEUIOD_MISC 4
+
+#define FCEUIOD__COUNT 5
+
+void FCEUI_SetDirOverride(int which, char *n);
+
+void FCEUI_MemDump(uint16 a, int32 len, void (*callb)(uint16 a, uint8 v));
+uint8 FCEUI_MemSafePeek(uint16 A);
+void FCEUI_MemPoke(uint16 a, uint8 v, int hl);
+void FCEUI_NMI(void);
+void FCEUI_IRQ(void);
+uint16 FCEUI_Disassemble(void *XA, uint16 a, char *stringo);
+void FCEUI_GetIVectors(uint16 *reset, uint16 *irq, uint16 *nmi);
+
+uint32 FCEUI_CRC32(uint32 crc, uint8 *buf, uint32 len);
+
+void FCEUI_ToggleTileView(void);
+void FCEUI_SetLowPass(int q);
+
+void FCEUI_NSFSetVis(int mode);
+int FCEUI_NSFChange(int amount);
+int FCEUI_NSFGetInfo(uint8 *name, uint8 *artist, uint8 *copyright, int maxlen);
+
+void FCEUI_VSUniToggleDIPView(void);
+void FCEUI_VSUniToggleDIP(int w);
+uint8 FCEUI_VSUniGetDIPs(void);
+void FCEUI_VSUniSetDIP(int w, int state);
+void FCEUI_VSUniCoin(void);
+
+int FCEUI_FDSInsert(void);
+//int FCEUI_FDSEject(void);
+void FCEUI_FDSSelect(void);
+
+int FCEUI_DatachSet(const uint8 *rcode);
+
+int FCEUI_EmulationPaused(void);
+void FCEUI_ToggleEmulationPause(void);
+void FCEUI_FrameAdvance(void);
+
+/* AVI Output */
+int FCEUI_AviBegin(const char* fname);
+void FCEUI_AviEnd(void);
+void FCEUI_AviVideoUpdate(const unsigned char* buffer);
+void FCEUI_AviSoundUpdate(void* soundData, int soundLen);
+int FCEUI_AviIsRecording(void);
+
+void FCEUD_AviRecordTo(void);
+void FCEUD_AviStop(void);
+
+/* Command input mapping */
+typedef int TestCommandState(int cmd);
+void FCEUI_HandleEmuCommands(TestCommandState* testfn);
+void FCEUD_CmdOpen(void);
+
+/* Emulation speed */
+enum EMUSPEED_SET
+{
+ EMUSPEED_SLOWEST=0,
+ EMUSPEED_SLOWER,
+ EMUSPEED_NORMAL,
+ EMUSPEED_FASTER,
+ EMUSPEED_FASTEST
+};
+void FCEUD_SetEmulationSpeed(int cmd);
+void FCEUD_TurboOn(void);
+void FCEUD_TurboOff(void);
+
+int FCEUD_ShowStatusIcon(void);
+void FCEUD_ToggleStatusIcon(void);
+void FCEUD_HideMenuToggle(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __DRIVER_H_ */
diff --git a/drivers/common/Makefile.am.inc b/drivers/common/Makefile.am.inc
new file mode 100644
index 00000000..bb812e35
--- /dev/null
+++ b/drivers/common/Makefile.am.inc
@@ -0,0 +1 @@
+fceu_SOURCES += drivers/common/args.c drivers/common/cheat.c drivers/common/config.c drivers/common/vidblit.c drivers/common/hq2x.c drivers/common/hq3x.c drivers/common/scale2x.c drivers/common/scale3x.c drivers/common/scalebit.c
diff --git a/drivers/common/args.c b/drivers/common/args.c
new file mode 100644
index 00000000..21d4f475
--- /dev/null
+++ b/drivers/common/args.c
@@ -0,0 +1,98 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/****************************************************************/
+/* FCE Ultra */
+/* */
+/* This file contains code for parsing command-line */
+/* options. */
+/* */
+/****************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../../types.h"
+#include "args.h"
+
+void ParseEA(int x, int argc, char *argv[], ARGPSTRUCT *argsps)
+{
+ int y=0;
+
+ do
+ {
+ if(!argsps[y].name)
+ {
+ ParseEA(x,argc,argv,(ARGPSTRUCT*)argsps[y].var);
+ y++;
+ continue;
+ }
+ if(!strcmp(argv[x],argsps[y].name)) // A match.
+ {
+ if(argsps[y].subs)
+ {
+ if((x+1)>=argc)
+ break;
+ if(argsps[y].substype&0x2000)
+ {
+ ((void (*)(char *))argsps[y].subs)(argv[x+1]);
+ }
+ else if(argsps[y].substype&0x8000)
+ {
+ *(int *)argsps[y].subs&=~(argsps[y].substype&(~0x8000));
+ *(int *)argsps[y].subs|=atoi(argv[x+1])?(argsps[y].substype&(~0x8000)):0;
+ }
+ else
+ switch(argsps[y].substype&(~0x4000))
+ {
+ case 0: // Integer
+ *(int *)argsps[y].subs=atoi(argv[x+1]);
+ break;
+ case 2: // Double float
+ *(double *)argsps[y].subs=atof(argv[x+1]);
+ break;
+ case 1: // String
+ if(argsps[y].substype&0x4000)
+ {
+ if(*(char **)argsps[y].subs)
+ free(*(char **)argsps[y].subs);
+ if(!( *(char **)argsps[y].subs=(char*)malloc(strlen(argv[x+1])+1) ))
+ break;
+ }
+ strcpy(*(char **)argsps[y].subs,argv[x+1]);
+ break;
+ }
+ }
+ if(argsps[y].var)
+ *argsps[y].var=1;
+ }
+ y++;
+ } while(argsps[y].var || argsps[y].subs);
+}
+
+void ParseArguments(int argc, char *argv[], ARGPSTRUCT *argsps)
+{
+ int x;
+
+ for(x=0;x<argc;x++)
+ ParseEA(x,argc,argv,argsps);
+}
+
diff --git a/drivers/common/args.h b/drivers/common/args.h
new file mode 100644
index 00000000..14d760e7
--- /dev/null
+++ b/drivers/common/args.h
@@ -0,0 +1,12 @@
+#ifndef _DRIVERS_ARGH
+typedef struct {
+ char *name;
+ int *var;
+
+ void *subs;
+ int substype;
+} ARGPSTRUCT;
+
+void ParseArguments(int argc, char *argv[], ARGPSTRUCT *argsps);
+#define _DRIVERS_ARGH
+#endif
diff --git a/drivers/common/cheat.c b/drivers/common/cheat.c
new file mode 100644
index 00000000..f678f78b
--- /dev/null
+++ b/drivers/common/cheat.c
@@ -0,0 +1,523 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include "../../driver.h"
+
+static void GetString(char *s, int max)
+{
+ int x;
+ fgets(s,max,stdin);
+
+ for(x=0;x<max;x++)
+ if(s[x]=='\n')
+ {
+ s[x]=0;
+ break;
+ }
+}
+
+/* Get unsigned 16-bit integer from stdin in hex. */
+static uint32 GetH16(unsigned int def)
+{
+ char buf[32];
+
+ fgets(buf,32,stdin);
+ if(buf[0]=='\n')
+ return(def);
+ if(buf[0]=='$')
+ sscanf(buf+1,"%04x",&def);
+ else
+ sscanf(buf,"%04x",&def);
+ return def;
+}
+
+/* Get unsigned 8-bit integer from stdin in decimal. */
+static uint8 Get8(unsigned int def)
+{
+ char buf[32];
+
+ fgets(buf,32,stdin);
+ if(buf[0]=='\n')
+ return(def);
+ sscanf(buf,"%u",&def);
+ return def;
+}
+
+static int GetI(int def)
+{
+ char buf[32];
+
+ fgets(buf,32,stdin);
+ if(buf[0]=='\n')
+ return(def);
+ sscanf(buf,"%d",&def);
+ return def;
+}
+
+static int GetYN(int def)
+{
+ char buf[32];
+ printf("(Y/N)[%s]: ",def?"Y":"N");
+ fgets(buf,32,stdin);
+ if(buf[0]=='y' || buf[0]=='Y')
+ return(1);
+ if(buf[0]=='n' || buf[0]=='N')
+ return(0);
+ return(def);
+}
+
+/*
+** Begin list code.
+**
+*/
+static int listcount;
+static int listids[16];
+static int listsel;
+static int mordoe;
+
+void BeginListShow(void)
+{
+ listcount=0;
+ listsel=-1;
+ mordoe=0;
+}
+
+/* Hmm =0 for in list choices, hmm=1 for end of list choices. */
+/* Return equals 0 to continue, -1 to stop, otherwise a number. */
+int ListChoice(int hmm)
+{
+ char buf[32];
+
+ if(!hmm)
+ {
+ int num=0;
+
+ tryagain:
+ printf(" <'Enter' to continue, (S)top, or enter a number.> ");
+ fgets(buf,32,stdin);
+ if(buf[0]=='s' || buf[0]=='S') return(-1);
+ if(buf[0]=='\n') return(0);
+ if(!sscanf(buf,"%d",&num))
+ return(0);
+ if(num<1) goto tryagain;
+ return(num);
+ }
+ else
+ {
+ int num=0;
+
+ tryagain2:
+ printf(" <'Enter' to make no selection or enter a number.> ");
+ fgets(buf,32,stdin);
+ if(buf[0]=='\n') return(0);
+ if(!sscanf(buf,"%d",&num))
+ return(0);
+ if(num<1) goto tryagain2;
+ return(num);
+ }
+}
+
+int EndListShow(void)
+{
+ if(mordoe)
+ {
+ int r=ListChoice(1);
+ if(r>0 && r<=listcount)
+ listsel=listids[r-1];
+ }
+ return(listsel);
+}
+
+/* Returns 0 to stop listing, 1 to continue. */
+int AddToList(char *text, uint32 id)
+{
+ if(listcount==16)
+ {
+ int t=ListChoice(0);
+ mordoe=0;
+ if(t==-1) return(0); // Stop listing.
+ else if(t>0 && t<17)
+ {
+ listsel=listids[t-1];
+ return(0);
+ }
+ listcount=0;
+ }
+ mordoe=1;
+ listids[listcount]=id;
+ printf("%2d) %s\n",listcount+1,text);
+ listcount++;
+ return(1);
+}
+
+/*
+**
+** End list code.
+**/
+
+typedef struct MENU {
+ char *text;
+ void *action;
+ int type; // 0 for menu, 1 for function.
+} MENU;
+
+static void SetOC(void)
+{
+ FCEUI_CheatSearchSetCurrentAsOriginal();
+}
+
+static void UnhideEx(void)
+{
+ FCEUI_CheatSearchShowExcluded();
+}
+
+static void ToggleCheat(int num)
+{
+ printf("Cheat %d %sabled.\n",1+num,
+ FCEUI_ToggleCheat(num)?"en":"dis");
+}
+
+static void ModifyCheat(int num)
+{
+ char *name;
+ char buf[256];
+ uint32 A;
+ uint8 V;
+ int compare;
+ int type;
+
+ int s;
+ int t;
+
+ FCEUI_GetCheat(num, &name, &A, &V, &compare, &s, &type);
+
+ printf("Name [%s]: ",name);
+ GetString(buf,256);
+
+ /* This obviously doesn't allow for cheats with no names. Bah. Who wants
+ nameless cheats anyway...
+ */
+
+ if(buf[0])
+ name=buf; // Change name when FCEUI_SetCheat() is called.
+ else
+ name=0; // Don't change name when FCEUI_SetCheat() is called.
+
+ printf("Address [$%04x]: ",(unsigned int)A);
+ A=GetH16(A);
+
+ printf("Value [%03d]: ",(unsigned int)V);
+ V=Get8(V);
+
+ printf("Compare [%3d]: ",compare);
+ compare=GetI(compare);
+
+ printf("Type(0=Old Style, 1=Read Substitute) [%1d]: ",type);
+ type=GetI(type)?1:0;
+
+ printf("Enable [%s]: ",s?"Y":"N");
+ t=getchar();
+ if(t=='Y' || t=='y') s=1;
+ else if(t=='N' || t=='n') s=0;
+
+ FCEUI_SetCheat(num,name,A,V,compare,s,type);
+}
+
+
+static void AddCheatGGPAR(int which)
+{
+ uint16 A;
+ uint8 V;
+ int C;
+ int type;
+ char name[256],code[256];
+
+ printf("Name: ");
+ GetString(name,256);
+
+ printf("Code: ");
+ GetString(code,256);
+
+ printf("Add cheat \"%s\" for code \"%s\"?",name,code);
+ if(GetYN(0))
+ {
+ if(which)
+ {
+ if(!FCEUI_DecodePAR(code,&A,&V,&C,&type))
+ {
+ puts("Invalid Game Genie code.");
+ return;
+ }
+ }
+ else
+ {
+ if(!FCEUI_DecodeGG(code,&A,&V,&C))
+ {
+ puts("Invalid Game Genie code.");
+ return;
+ }
+ type=1;
+ }
+
+ if(FCEUI_AddCheat(name,A,V,C,type))
+ puts("Cheat added.");
+ else
+ puts("Error adding cheat.");
+ }
+}
+
+static void AddCheatGG(void)
+{
+ AddCheatGGPAR(0);
+}
+
+static void AddCheatPAR(void)
+{
+ AddCheatGGPAR(1);
+}
+
+static void AddCheatParam(uint32 A, uint8 V)
+{
+ char name[256];
+
+ printf("Name: ");
+ GetString(name,256);
+ printf("Address [$%04x]: ",(unsigned int)A);
+ A=GetH16(A);
+ printf("Value [%03d]: ",(unsigned int)V);
+ V=Get8(V);
+ printf("Add cheat \"%s\" for address $%04x with value %03d?",name,(unsigned int)A,(unsigned int)V);
+ if(GetYN(0))
+ {
+ if(FCEUI_AddCheat(name,A,V,-1,0))
+ puts("Cheat added.");
+ else
+ puts("Error adding cheat.");
+ }
+}
+
+static void AddCheat(void)
+{
+ AddCheatParam(0,0);
+}
+
+static int lid;
+static int clistcallb(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data)
+{
+ char tmp[512];
+ int ret;
+
+ if(compare>=0)
+ sprintf(tmp,"%s $%04x:%03d:%03d - %s",s?"*":" ",(unsigned int)a,(unsigned int)v,compare,name);
+ else
+ sprintf(tmp,"%s $%04x:%03d - %s",s?"*":" ",(unsigned int)a,(unsigned int)v,name);
+ if(type==1)
+ tmp[2]='S';
+ ret=AddToList(tmp,lid);
+ lid++;
+ return(ret);
+}
+
+static void ListCheats(void)
+{
+ int which;
+ lid=0;
+
+ BeginListShow();
+ FCEUI_ListCheats(clistcallb,0);
+ which=EndListShow();
+ if(which>=0)
+ {
+ char tmp[32];
+ printf(" <(T)oggle status, (M)odify, or (D)elete this cheat.> ");
+ fgets(tmp,32,stdin);
+ switch(tolower(tmp[0]))
+ {
+ case 't':ToggleCheat(which);
+ break;
+ case 'd':if(!FCEUI_DelCheat(which))
+ puts("Error deleting cheat!");
+ else
+ puts("Cheat has been deleted.");
+ break;
+ case 'm':ModifyCheat(which);
+ break;
+ }
+ }
+}
+
+static void ResetSearch(void)
+{
+ FCEUI_CheatSearchBegin();
+ puts("Done.");
+}
+
+static int srescallb(uint32 a, uint8 last, uint8 current, void *data)
+{
+ char tmp[13];
+ sprintf(tmp, "$%04x:%03d:%03d",(unsigned int)a,(unsigned int)last,(unsigned int)current);
+ return(AddToList(tmp,a));
+}
+
+static void ShowRes(void)
+{
+ int n=FCEUI_CheatSearchGetCount();
+ printf(" %d results:\n",n);
+ if(n)
+ {
+ int which;
+ BeginListShow();
+ FCEUI_CheatSearchGet(srescallb,0);
+ which=EndListShow();
+ if(which>=0)
+ AddCheatParam(which,0);
+ }
+}
+
+static int ShowShortList(char *moe[], int n, int def)
+{
+ int x,c;
+ unsigned int baa;
+ char tmp[16];
+
+ red:
+ for(x=0;x<n;x++)
+ printf("%d) %s\n",x+1,moe[x]);
+ puts("D) Display List");
+ clo:
+
+ printf("\nSelection [%d]> ",def+1);
+ fgets(tmp,256,stdin);
+ if(tmp[0]=='\n')
+ return def;
+ c=tolower(tmp[0]);
+ baa=c-'1';
+
+ if(baa<n)
+ return baa;
+ else if(c=='d')
+ goto red;
+ else
+ {
+ puts("Invalid selection.");
+ goto clo;
+ }
+}
+
+static void DoSearch(void)
+{
+ static int v1=0,v2=0;
+ static int method=0;
+ char *m[6]={"O==V1 && C==V2","O==V1 && |O-C|==V2","|O-C|==V2","O!=C","Value decreased","Value increased"};
+ printf("\nSearch Filter:\n");
+
+ method=ShowShortList(m,6,method);
+ if(method<=1)
+ {
+ printf("V1 [%03d]: ",v1);
+ v1=Get8(v1);
+ }
+ if(method<=2)
+ {
+ printf("V2 [%03d]: ",v2);
+ v2=Get8(v2);
+ }
+ FCEUI_CheatSearchEnd(method,v1,v2);
+ puts("Search completed.\n");
+}
+
+
+static MENU NewCheatsMenu[]={
+ {"Add Cheat",(void *)AddCheat,1},
+ {"Reset Search",(void *)ResetSearch,1},
+ {"Do Search",(void *)DoSearch,1},
+ {"Set Original to Current",(void *)SetOC,1},
+ {"Unhide Excluded",(void *)UnhideEx,1},
+ {"Show Results",(void *)ShowRes,1},
+ {"Add Game Genie Cheat",(void *)AddCheatGG,1},
+ {"Add PAR Cheat",(void *)AddCheatPAR,1},
+ {0}
+};
+
+static MENU MainMenu[]={
+ {"List Cheats",(void *)ListCheats,1},
+ {"New Cheats...",(void *)NewCheatsMenu,0},
+ {0}
+};
+
+static void DoMenu(MENU *men)
+{
+ int x=0;
+
+ redisplay:
+ x=0;
+ puts("");
+ while(men[x].text)
+ {
+ printf("%d) %s\n",x+1,men[x].text);
+ x++;
+ }
+ puts("D) Display Menu\nX) Return to Previous\n");
+ {
+ char buf[32];
+ int c;
+
+ recommand:
+ printf("Command> ");
+ fgets(buf,32,stdin);
+ c=tolower(buf[0]);
+ if(c=='\n')
+ goto recommand;
+ else if(c=='d')
+ goto redisplay;
+ else if(c=='x')
+ {
+ return;
+ }
+ else if(sscanf(buf,"%d",&c))
+ {
+ if(c>x) goto invalid;
+ if(men[c-1].type)
+ {
+ void (*func)(void)=(void(*)())men[c-1].action;
+ func();
+ }
+ else
+ DoMenu((MENU*)men[c-1].action); /* Mmm...recursivey goodness. */
+ goto redisplay;
+ }
+ else
+ {
+ invalid:
+ puts("Invalid command.\n");
+ goto recommand;
+ }
+
+ }
+}
+
+void DoConsoleCheatConfig(void)
+{
+ MENU *curmenu=MainMenu;
+
+ DoMenu(curmenu);
+}
diff --git a/drivers/common/cheat.h b/drivers/common/cheat.h
new file mode 100644
index 00000000..77963872
--- /dev/null
+++ b/drivers/common/cheat.h
@@ -0,0 +1,21 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+void DoConsoleCheatConfig(void);
diff --git a/drivers/common/config.c b/drivers/common/config.c
new file mode 100644
index 00000000..00ed9852
--- /dev/null
+++ b/drivers/common/config.c
@@ -0,0 +1,152 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/****************************************************************/
+/* FCE Ultra */
+/* */
+/* This file contains routines for reading/writing the */
+/* configuration file. */
+/* */
+/****************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../../types.h"
+#include "config.h"
+
+static int FReadString(FILE *fp, char *str, int n)
+{
+ int x=0,z;
+ for(;;)
+ {
+ z=fgetc(fp);
+ str[x]=z;
+ x++;
+ if(z<=0) break;
+ if(x>=n) return 0;
+ }
+ if(z<0) return 0;
+ return 1;
+}
+
+static void GetValueR(FILE *fp, char *str, void *v, int c)
+{
+ char buf[256];
+ int s;
+
+ while(FReadString(fp,buf,256))
+ {
+ fread(&s,1,4,fp);
+ if(!strcmp(str, buf))
+ {
+ if(!c) // String, allocate some memory.
+ {
+ if(!(*(char **)v=(char*)malloc(s)))
+ goto gogl;
+ fread(*(char **)v,1,s,fp);
+ continue;
+ }
+ else if(s>c || s<c)
+ {
+ gogl:
+ fseek(fp,s,SEEK_CUR);
+ continue;
+ }
+ fread((uint8*)v,1,c,fp);
+ }
+ else
+ fseek(fp,s,SEEK_CUR);
+ }
+ fseek(fp,4,SEEK_SET);
+}
+
+static void SetValueR(FILE *fp, char *str, void *v, int c)
+{
+ fwrite(str,1,strlen(str)+1,fp);
+ fwrite((uint8*)&c,1,4,fp);
+ fwrite((uint8*)v,1,c,fp);
+}
+
+static void SaveParse(CFGSTRUCT *cfgst, FILE *fp)
+{
+ int x=0;
+
+ while(cfgst[x].ptr)
+ {
+ if(!cfgst[x].name) // Link to new config structure
+ {
+ SaveParse((CFGSTRUCT*)cfgst[x].ptr,fp); // Recursion is sexy. I could
+ // save a little stack space if I made
+ // the file pointer a non-local
+ // variable...
+ x++;
+ continue;
+ }
+
+ if(cfgst[x].len) // Plain data
+ SetValueR(fp,cfgst[x].name,cfgst[x].ptr,cfgst[x].len);
+ else // String
+ if(*(char **)cfgst[x].ptr) // Only save it if there IS a string.
+ SetValueR(fp,cfgst[x].name,*(char **)cfgst[x].ptr,
+ strlen(*(char **)cfgst[x].ptr)+1);
+ x++;
+ }
+}
+
+void SaveFCEUConfig(char *filename, CFGSTRUCT *cfgst)
+{
+ FILE *fp;
+
+ fp=fopen(filename,"wb");
+ if(fp==NULL) return;
+
+ SaveParse(cfgst,fp);
+
+ fclose(fp);
+}
+
+static void LoadParse(CFGSTRUCT *cfgst, FILE *fp)
+{
+ int x=0;
+
+ while(cfgst[x].ptr)
+ {
+ if(!cfgst[x].name) // Link to new config structure
+ {
+ LoadParse((CFGSTRUCT*)cfgst[x].ptr,fp);
+ x++;
+ continue;
+ }
+ GetValueR(fp,cfgst[x].name,cfgst[x].ptr,cfgst[x].len);
+ x++;
+ }
+}
+
+void LoadFCEUConfig(char *filename, CFGSTRUCT *cfgst)
+{
+ FILE *fp;
+
+ fp=fopen(filename,"rb");
+ if(fp==NULL) return;
+ LoadParse(cfgst,fp);
+ fclose(fp);
+}
diff --git a/drivers/common/config.h b/drivers/common/config.h
new file mode 100644
index 00000000..74486ce0
--- /dev/null
+++ b/drivers/common/config.h
@@ -0,0 +1,40 @@
+#ifndef _DRIVERS_CONFIGH
+typedef struct {
+ char *name;
+ void *ptr;
+ int len;
+} CFGSTRUCT;
+
+void SaveFCEUConfig(char *filename, CFGSTRUCT *cfgst);
+void LoadFCEUConfig(char *filename, CFGSTRUCT *cfgst);
+
+/* Macros for building CFGSTRUCT structures. */
+
+/* CFGSTRUCT structures must always end with ENDCFGSTRUCT */
+#define ENDCFGSTRUCT { 0,0,0 }
+
+/* When this macro is used, the config loading/saving code will parse
+ the new config structure until the end of it is detected, then it
+ will continue parsing the original config structure.
+*/
+#define ADDCFGSTRUCT(x) { 0,&x,0 }
+
+/* Oops. The NAC* macros shouldn't have the # in front of the w, but
+ fixing this would break configuration files of previous versions and it
+ isn't really hurting much.
+*/
+
+/* Single piece of data(integer). */
+#define AC(x) { #x,&x,sizeof(x)}
+#define NAC(w,x) { #w,&x,sizeof(x)}
+
+/* Array. */
+#define ACA(x) {#x,x,sizeof(x)}
+#define NACA(w,x) {#w,x,sizeof(x)}
+
+/* String(pointer) with automatic memory allocation. */
+#define ACS(x) {#x,&x,0}
+#define NACS(w,x) {#w,&x,0}
+
+#define _DRIVERS_CONFIGH
+#endif
diff --git a/drivers/common/hq2x.c b/drivers/common/hq2x.c
new file mode 100644
index 00000000..3b69ed64
--- /dev/null
+++ b/drivers/common/hq2x.c
@@ -0,0 +1,2991 @@
+//hq2x filter demo program
+//----------------------------------------------------------
+//Copyright (C) 2003 MaxSt ( maxst@hiend3d.com )
+
+//This program is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 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
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser 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
+
+/* Modified for usage in FCE Ultra */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "hq2x.h"
+
+static int *LUT16to32=NULL;
+static int *RGBtoYUV=NULL;
+static const int Ymask = 0x00FF0000;
+static const int Umask = 0x0000FF00;
+static const int Vmask = 0x000000FF;
+static const int trY = 0x00300000;
+static const int trU = 0x00000700;
+static const int trV = 0x00000006;
+
+static inline void Interp1(unsigned char * pc, int c1, int c2)
+{
+ *((int*)pc) = (c1*3+c2) >> 2;
+}
+
+static inline void Interp2(unsigned char * pc, int c1, int c2, int c3)
+{
+ *((int*)pc) = (c1*2+c2+c3) >> 2;
+}
+
+static inline void Interp5(unsigned char * pc, int c1, int c2)
+{
+ *((int*)pc) = (c1+c2) >> 1;
+}
+
+static inline void Interp6(unsigned char * pc, int c1, int c2, int c3)
+{
+ //*((int*)pc) = (c1*5+c2*2+c3)/8;
+
+ *((int*)pc) = ((((c1 & 0x00FF00)*5 + (c2 & 0x00FF00)*2 + (c3 & 0x00FF00) ) & 0x0007F800) +
+ (((c1 & 0xFF00FF)*5 + (c2 & 0xFF00FF)*2 + (c3 & 0xFF00FF) ) & 0x07F807F8)) >> 3;
+}
+
+static inline void Interp7(unsigned char * pc, int c1, int c2, int c3)
+{
+ //*((int*)pc) = (c1*6+c2+c3)/8;
+
+ *((int*)pc) = ((((c1 & 0x00FF00)*6 + (c2 & 0x00FF00) + (c3 & 0x00FF00) ) & 0x0007F800) +
+ (((c1 & 0xFF00FF)*6 + (c2 & 0xFF00FF) + (c3 & 0xFF00FF) ) & 0x07F807F8)) >> 3;
+}
+
+static inline void Interp9(unsigned char * pc, int c1, int c2, int c3)
+{
+ //*((int*)pc) = (c1*2+(c2+c3)*3)/8;
+
+ *((int*)pc) = ((((c1 & 0x00FF00)*2 + ((c2 & 0x00FF00) + (c3 & 0x00FF00))*3 ) & 0x0007F800) +
+ (((c1 & 0xFF00FF)*2 + ((c2 & 0xFF00FF) + (c3 & 0xFF00FF))*3 ) & 0x07F807F8)) >> 3;
+}
+
+static inline void Interp10(unsigned char * pc, int c1, int c2, int c3)
+{
+ //*((int*)pc) = (c1*14+c2+c3)/16;
+
+ *((int*)pc) = ((((c1 & 0x00FF00)*14 + (c2 & 0x00FF00) + (c3 & 0x00FF00) ) & 0x000FF000) +
+ (((c1 & 0xFF00FF)*14 + (c2 & 0xFF00FF) + (c3 & 0xFF00FF) ) & 0x0FF00FF0)) >> 4;
+}
+
+
+#define PIXEL00_0 *((int*)(pOut)) = c[5];
+#define PIXEL00_10 Interp1(pOut, c[5], c[1]);
+#define PIXEL00_11 Interp1(pOut, c[5], c[4]);
+#define PIXEL00_12 Interp1(pOut, c[5], c[2]);
+#define PIXEL00_20 Interp2(pOut, c[5], c[4], c[2]);
+#define PIXEL00_21 Interp2(pOut, c[5], c[1], c[2]);
+#define PIXEL00_22 Interp2(pOut, c[5], c[1], c[4]);
+#define PIXEL00_60 Interp6(pOut, c[5], c[2], c[4]);
+#define PIXEL00_61 Interp6(pOut, c[5], c[4], c[2]);
+#define PIXEL00_70 Interp7(pOut, c[5], c[4], c[2]);
+#define PIXEL00_90 Interp9(pOut, c[5], c[4], c[2]);
+#define PIXEL00_100 Interp10(pOut, c[5], c[4], c[2]);
+#define PIXEL01_0 *((int*)(pOut+4)) = c[5];
+#define PIXEL01_10 Interp1(pOut+4, c[5], c[3]);
+#define PIXEL01_11 Interp1(pOut+4, c[5], c[2]);
+#define PIXEL01_12 Interp1(pOut+4, c[5], c[6]);
+#define PIXEL01_20 Interp2(pOut+4, c[5], c[2], c[6]);
+#define PIXEL01_21 Interp2(pOut+4, c[5], c[3], c[6]);
+#define PIXEL01_22 Interp2(pOut+4, c[5], c[3], c[2]);
+#define PIXEL01_60 Interp6(pOut+4, c[5], c[6], c[2]);
+#define PIXEL01_61 Interp6(pOut+4, c[5], c[2], c[6]);
+#define PIXEL01_70 Interp7(pOut+4, c[5], c[2], c[6]);
+#define PIXEL01_90 Interp9(pOut+4, c[5], c[2], c[6]);
+#define PIXEL01_100 Interp10(pOut+4, c[5], c[2], c[6]);
+#define PIXEL10_0 *((int*)(pOut+BpL)) = c[5];
+#define PIXEL10_10 Interp1(pOut+BpL, c[5], c[7]);
+#define PIXEL10_11 Interp1(pOut+BpL, c[5], c[8]);
+#define PIXEL10_12 Interp1(pOut+BpL, c[5], c[4]);
+#define PIXEL10_20 Interp2(pOut+BpL, c[5], c[8], c[4]);
+#define PIXEL10_21 Interp2(pOut+BpL, c[5], c[7], c[4]);
+#define PIXEL10_22 Interp2(pOut+BpL, c[5], c[7], c[8]);
+#define PIXEL10_60 Interp6(pOut+BpL, c[5], c[4], c[8]);
+#define PIXEL10_61 Interp6(pOut+BpL, c[5], c[8], c[4]);
+#define PIXEL10_70 Interp7(pOut+BpL, c[5], c[8], c[4]);
+#define PIXEL10_90 Interp9(pOut+BpL, c[5], c[8], c[4]);
+#define PIXEL10_100 Interp10(pOut+BpL, c[5], c[8], c[4]);
+#define PIXEL11_0 *((int*)(pOut+BpL+4)) = c[5];
+#define PIXEL11_10 Interp1(pOut+BpL+4, c[5], c[9]);
+#define PIXEL11_11 Interp1(pOut+BpL+4, c[5], c[6]);
+#define PIXEL11_12 Interp1(pOut+BpL+4, c[5], c[8]);
+#define PIXEL11_20 Interp2(pOut+BpL+4, c[5], c[6], c[8]);
+#define PIXEL11_21 Interp2(pOut+BpL+4, c[5], c[9], c[8]);
+#define PIXEL11_22 Interp2(pOut+BpL+4, c[5], c[9], c[6]);
+#define PIXEL11_60 Interp6(pOut+BpL+4, c[5], c[8], c[6]);
+#define PIXEL11_61 Interp6(pOut+BpL+4, c[5], c[6], c[8]);
+#define PIXEL11_70 Interp7(pOut+BpL+4, c[5], c[6], c[8]);
+#define PIXEL11_90 Interp9(pOut+BpL+4, c[5], c[6], c[8]);
+#define PIXEL11_100 Interp10(pOut+BpL+4, c[5], c[6], c[8]);
+
+
+
+static inline int Diff(unsigned int w1, unsigned int w2)
+{
+ int YUV1;
+ int YUV2;
+
+ YUV1 = RGBtoYUV[w1];
+ YUV2 = RGBtoYUV[w2];
+ return ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) ||
+ ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) ||
+ ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) );
+// return(
+//((0-abs((YUV1 & Ymask) - (YUV2 & Ymask)))>>31) |
+//((0-abs((YUV1 & Umask) - (YUV2 & Umask)))>>31) |
+//((0-abs((YUV1 & Vmask) - (YUV2 & Vmask)))>>31)
+// );
+
+}
+
+void hq2x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL )
+{
+ int i, j, k;
+ int prevline, nextline;
+ int w[10];
+ int c[10];
+
+ // +----+----+----+
+ // | | | |
+ // | w1 | w2 | w3 |
+ // +----+----+----+
+ // | | | |
+ // | w4 | w5 | w6 |
+ // +----+----+----+
+ // | | | |
+ // | w7 | w8 | w9 |
+ // +----+----+----+
+
+ for (j=0; j<Yres; j++)
+ {
+ if (j>0) prevline = -Xres*2; else prevline = 0;
+ if (j<Yres-1) nextline = Xres*2; else nextline = 0;
+
+ for (i=0; i<Xres; i++)
+ {
+ int pattern;
+ int flag;
+ int YUV1Y,YUV1U,YUV1V;
+
+ w[2] = *((unsigned short*)(pIn + prevline));
+ w[5] = *((unsigned short*)pIn);
+ w[8] = *((unsigned short*)(pIn + nextline));
+
+ if (i>0)
+ {
+ w[1] = *((unsigned short*)(pIn + prevline - 2));
+ w[4] = *((unsigned short*)(pIn - 2));
+ w[7] = *((unsigned short*)(pIn + nextline - 2));
+ }
+ else
+ {
+ w[1] = w[2];
+ w[4] = w[5];
+ w[7] = w[8];
+ }
+
+ if (i<Xres-1)
+ {
+ w[3] = *((unsigned short*)(pIn + prevline + 2));
+ w[6] = *((unsigned short*)(pIn + 2));
+ w[9] = *((unsigned short*)(pIn + nextline + 2));
+ }
+ else
+ {
+ w[3] = w[2];
+ w[6] = w[5];
+ w[9] = w[8];
+ }
+
+ pattern = 0;
+ flag = 1;
+
+ YUV1Y = YUV1U = YUV1V = RGBtoYUV[w[5]];
+
+ YUV1Y &= Ymask;
+ YUV1U &= Umask;
+ YUV1V &= Vmask;
+
+ for (k=1; k<=9; k++)
+ {
+ if (k==5) continue;
+
+ if ( w[k] != w[5] )
+ {
+ int YUV2 = RGBtoYUV[w[k]];
+ //int tmp;
+ //tmp =
+ //((unsigned int)(0-abs(YUV1Y - (YUV2 & Ymask)))>>31) |
+ //((unsigned int)(0-abs(YUV1U - (YUV2 & Umask)))>>31) |
+ //((unsigned int)(0-abs(YUV1V - (YUV2 & Vmask)))>>31);
+
+ //pattern|=tmp*flag;
+
+ if ( ( abs(YUV1Y - (YUV2 & Ymask)) > trY ) ||
+ ( abs(YUV1U - (YUV2 & Umask)) > trU ) ||
+ ( abs(YUV1V - (YUV2 & Vmask)) > trV ) )
+ pattern |= flag;
+ }
+ flag <<= 1;
+ }
+
+ for (k=1; k<=9; k++)
+ c[k] = LUT16to32[w[k]];
+
+ switch (pattern)
+ {
+ case 0:
+ case 1:
+ case 4:
+ case 32:
+ case 128:
+ case 5:
+ case 132:
+ case 160:
+ case 33:
+ case 129:
+ case 36:
+ case 133:
+ case 164:
+ case 161:
+ case 37:
+ case 165:
+ {
+ PIXEL00_20
+ PIXEL01_20
+ PIXEL10_20
+ PIXEL11_20
+ break;
+ }
+ case 2:
+ case 34:
+ case 130:
+ case 162:
+ {
+ PIXEL00_22
+ PIXEL01_21
+ PIXEL10_20
+ PIXEL11_20
+ break;
+ }
+ case 16:
+ case 17:
+ case 48:
+ case 49:
+ {
+ PIXEL00_20
+ PIXEL01_22
+ PIXEL10_20
+ PIXEL11_21
+ break;
+ }
+ case 64:
+ case 65:
+ case 68:
+ case 69:
+ {
+ PIXEL00_20
+ PIXEL01_20
+ PIXEL10_21
+ PIXEL11_22
+ break;
+ }
+ case 8:
+ case 12:
+ case 136:
+ case 140:
+ {
+ PIXEL00_21
+ PIXEL01_20
+ PIXEL10_22
+ PIXEL11_20
+ break;
+ }
+ case 3:
+ case 35:
+ case 131:
+ case 163:
+ {
+ PIXEL00_11
+ PIXEL01_21
+ PIXEL10_20
+ PIXEL11_20
+ break;
+ }
+ case 6:
+ case 38:
+ case 134:
+ case 166:
+ {
+ PIXEL00_22
+ PIXEL01_12
+ PIXEL10_20
+ PIXEL11_20
+ break;
+ }
+ case 20:
+ case 21:
+ case 52:
+ case 53:
+ {
+ PIXEL00_20
+ PIXEL01_11
+ PIXEL10_20
+ PIXEL11_21
+ break;
+ }
+ case 144:
+ case 145:
+ case 176:
+ case 177:
+ {
+ PIXEL00_20
+ PIXEL01_22
+ PIXEL10_20
+ PIXEL11_12
+ break;
+ }
+ case 192:
+ case 193:
+ case 196:
+ case 197:
+ {
+ PIXEL00_20
+ PIXEL01_20
+ PIXEL10_21
+ PIXEL11_11
+ break;
+ }
+ case 96:
+ case 97:
+ case 100:
+ case 101:
+ {
+ PIXEL00_20
+ PIXEL01_20
+ PIXEL10_12
+ PIXEL11_22
+ break;
+ }
+ case 40:
+ case 44:
+ case 168:
+ case 172:
+ {
+ PIXEL00_21
+ PIXEL01_20
+ PIXEL10_11
+ PIXEL11_20
+ break;
+ }
+ case 9:
+ case 13:
+ case 137:
+ case 141:
+ {
+ PIXEL00_12
+ PIXEL01_20
+ PIXEL10_22
+ PIXEL11_20
+ break;
+ }
+ case 18:
+ case 50:
+ {
+ PIXEL00_22
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_10
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ PIXEL10_20
+ PIXEL11_21
+ break;
+ }
+ case 80:
+ case 81:
+ {
+ PIXEL00_20
+ PIXEL01_22
+ PIXEL10_21
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 72:
+ case 76:
+ {
+ PIXEL00_21
+ PIXEL01_20
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_10
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ PIXEL11_22
+ break;
+ }
+ case 10:
+ case 138:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ PIXEL01_21
+ PIXEL10_22
+ PIXEL11_20
+ break;
+ }
+ case 66:
+ {
+ PIXEL00_22
+ PIXEL01_21
+ PIXEL10_21
+ PIXEL11_22
+ break;
+ }
+ case 24:
+ {
+ PIXEL00_21
+ PIXEL01_22
+ PIXEL10_22
+ PIXEL11_21
+ break;
+ }
+ case 7:
+ case 39:
+ case 135:
+ {
+ PIXEL00_11
+ PIXEL01_12
+ PIXEL10_20
+ PIXEL11_20
+ break;
+ }
+ case 148:
+ case 149:
+ case 180:
+ {
+ PIXEL00_20
+ PIXEL01_11
+ PIXEL10_20
+ PIXEL11_12
+ break;
+ }
+ case 224:
+ case 228:
+ case 225:
+ {
+ PIXEL00_20
+ PIXEL01_20
+ PIXEL10_12
+ PIXEL11_11
+ break;
+ }
+ case 41:
+ case 169:
+ case 45:
+ {
+ PIXEL00_12
+ PIXEL01_20
+ PIXEL10_11
+ PIXEL11_20
+ break;
+ }
+ case 22:
+ case 54:
+ {
+ PIXEL00_22
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ PIXEL10_20
+ PIXEL11_21
+ break;
+ }
+ case 208:
+ case 209:
+ {
+ PIXEL00_20
+ PIXEL01_22
+ PIXEL10_21
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 104:
+ case 108:
+ {
+ PIXEL00_21
+ PIXEL01_20
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ PIXEL11_22
+ break;
+ }
+ case 11:
+ case 139:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ PIXEL01_21
+ PIXEL10_22
+ PIXEL11_20
+ break;
+ }
+ case 19:
+ case 51:
+ {
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL00_11
+ PIXEL01_10
+ }
+ else
+ {
+ PIXEL00_60
+ PIXEL01_90
+ }
+ PIXEL10_20
+ PIXEL11_21
+ break;
+ }
+ case 146:
+ case 178:
+ {
+ PIXEL00_22
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_10
+ PIXEL11_12
+ }
+ else
+ {
+ PIXEL01_90
+ PIXEL11_61
+ }
+ PIXEL10_20
+ break;
+ }
+ case 84:
+ case 85:
+ {
+ PIXEL00_20
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL01_11
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL01_60
+ PIXEL11_90
+ }
+ PIXEL10_21
+ break;
+ }
+ case 112:
+ case 113:
+ {
+ PIXEL00_20
+ PIXEL01_22
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL10_12
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL10_61
+ PIXEL11_90
+ }
+ break;
+ }
+ case 200:
+ case 204:
+ {
+ PIXEL00_21
+ PIXEL01_20
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_10
+ PIXEL11_11
+ }
+ else
+ {
+ PIXEL10_90
+ PIXEL11_60
+ }
+ break;
+ }
+ case 73:
+ case 77:
+ {
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL00_12
+ PIXEL10_10
+ }
+ else
+ {
+ PIXEL00_61
+ PIXEL10_90
+ }
+ PIXEL01_20
+ PIXEL11_22
+ break;
+ }
+ case 42:
+ case 170:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ PIXEL10_11
+ }
+ else
+ {
+ PIXEL00_90
+ PIXEL10_60
+ }
+ PIXEL01_21
+ PIXEL11_20
+ break;
+ }
+ case 14:
+ case 142:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ PIXEL01_12
+ }
+ else
+ {
+ PIXEL00_90
+ PIXEL01_61
+ }
+ PIXEL10_22
+ PIXEL11_20
+ break;
+ }
+ case 67:
+ {
+ PIXEL00_11
+ PIXEL01_21
+ PIXEL10_21
+ PIXEL11_22
+ break;
+ }
+ case 70:
+ {
+ PIXEL00_22
+ PIXEL01_12
+ PIXEL10_21
+ PIXEL11_22
+ break;
+ }
+ case 28:
+ {
+ PIXEL00_21
+ PIXEL01_11
+ PIXEL10_22
+ PIXEL11_21
+ break;
+ }
+ case 152:
+ {
+ PIXEL00_21
+ PIXEL01_22
+ PIXEL10_22
+ PIXEL11_12
+ break;
+ }
+ case 194:
+ {
+ PIXEL00_22
+ PIXEL01_21
+ PIXEL10_21
+ PIXEL11_11
+ break;
+ }
+ case 98:
+ {
+ PIXEL00_22
+ PIXEL01_21
+ PIXEL10_12
+ PIXEL11_22
+ break;
+ }
+ case 56:
+ {
+ PIXEL00_21
+ PIXEL01_22
+ PIXEL10_11
+ PIXEL11_21
+ break;
+ }
+ case 25:
+ {
+ PIXEL00_12
+ PIXEL01_22
+ PIXEL10_22
+ PIXEL11_21
+ break;
+ }
+ case 26:
+ case 31:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ PIXEL10_22
+ PIXEL11_21
+ break;
+ }
+ case 82:
+ case 214:
+ {
+ PIXEL00_22
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ PIXEL10_21
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 88:
+ case 248:
+ {
+ PIXEL00_21
+ PIXEL01_22
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 74:
+ case 107:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ PIXEL01_21
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ PIXEL11_22
+ break;
+ }
+ case 27:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ PIXEL01_10
+ PIXEL10_22
+ PIXEL11_21
+ break;
+ }
+ case 86:
+ {
+ PIXEL00_22
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ PIXEL10_21
+ PIXEL11_10
+ break;
+ }
+ case 216:
+ {
+ PIXEL00_21
+ PIXEL01_22
+ PIXEL10_10
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 106:
+ {
+ PIXEL00_10
+ PIXEL01_21
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ PIXEL11_22
+ break;
+ }
+ case 30:
+ {
+ PIXEL00_10
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ PIXEL10_22
+ PIXEL11_21
+ break;
+ }
+ case 210:
+ {
+ PIXEL00_22
+ PIXEL01_10
+ PIXEL10_21
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 120:
+ {
+ PIXEL00_21
+ PIXEL01_22
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ PIXEL11_10
+ break;
+ }
+ case 75:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ PIXEL01_21
+ PIXEL10_10
+ PIXEL11_22
+ break;
+ }
+ case 29:
+ {
+ PIXEL00_12
+ PIXEL01_11
+ PIXEL10_22
+ PIXEL11_21
+ break;
+ }
+ case 198:
+ {
+ PIXEL00_22
+ PIXEL01_12
+ PIXEL10_21
+ PIXEL11_11
+ break;
+ }
+ case 184:
+ {
+ PIXEL00_21
+ PIXEL01_22
+ PIXEL10_11
+ PIXEL11_12
+ break;
+ }
+ case 99:
+ {
+ PIXEL00_11
+ PIXEL01_21
+ PIXEL10_12
+ PIXEL11_22
+ break;
+ }
+ case 57:
+ {
+ PIXEL00_12
+ PIXEL01_22
+ PIXEL10_11
+ PIXEL11_21
+ break;
+ }
+ case 71:
+ {
+ PIXEL00_11
+ PIXEL01_12
+ PIXEL10_21
+ PIXEL11_22
+ break;
+ }
+ case 156:
+ {
+ PIXEL00_21
+ PIXEL01_11
+ PIXEL10_22
+ PIXEL11_12
+ break;
+ }
+ case 226:
+ {
+ PIXEL00_22
+ PIXEL01_21
+ PIXEL10_12
+ PIXEL11_11
+ break;
+ }
+ case 60:
+ {
+ PIXEL00_21
+ PIXEL01_11
+ PIXEL10_11
+ PIXEL11_21
+ break;
+ }
+ case 195:
+ {
+ PIXEL00_11
+ PIXEL01_21
+ PIXEL10_21
+ PIXEL11_11
+ break;
+ }
+ case 102:
+ {
+ PIXEL00_22
+ PIXEL01_12
+ PIXEL10_12
+ PIXEL11_22
+ break;
+ }
+ case 153:
+ {
+ PIXEL00_12
+ PIXEL01_22
+ PIXEL10_22
+ PIXEL11_12
+ break;
+ }
+ case 58:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ }
+ else
+ {
+ PIXEL00_70
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_10
+ }
+ else
+ {
+ PIXEL01_70
+ }
+ PIXEL10_11
+ PIXEL11_21
+ break;
+ }
+ case 83:
+ {
+ PIXEL00_11
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_10
+ }
+ else
+ {
+ PIXEL01_70
+ }
+ PIXEL10_21
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL11_70
+ }
+ break;
+ }
+ case 92:
+ {
+ PIXEL00_21
+ PIXEL01_11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_10
+ }
+ else
+ {
+ PIXEL10_70
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL11_70
+ }
+ break;
+ }
+ case 202:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ }
+ else
+ {
+ PIXEL00_70
+ }
+ PIXEL01_21
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_10
+ }
+ else
+ {
+ PIXEL10_70
+ }
+ PIXEL11_11
+ break;
+ }
+ case 78:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ }
+ else
+ {
+ PIXEL00_70
+ }
+ PIXEL01_12
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_10
+ }
+ else
+ {
+ PIXEL10_70
+ }
+ PIXEL11_22
+ break;
+ }
+ case 154:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ }
+ else
+ {
+ PIXEL00_70
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_10
+ }
+ else
+ {
+ PIXEL01_70
+ }
+ PIXEL10_22
+ PIXEL11_12
+ break;
+ }
+ case 114:
+ {
+ PIXEL00_22
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_10
+ }
+ else
+ {
+ PIXEL01_70
+ }
+ PIXEL10_12
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL11_70
+ }
+ break;
+ }
+ case 89:
+ {
+ PIXEL00_12
+ PIXEL01_22
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_10
+ }
+ else
+ {
+ PIXEL10_70
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL11_70
+ }
+ break;
+ }
+ case 90:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ }
+ else
+ {
+ PIXEL00_70
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_10
+ }
+ else
+ {
+ PIXEL01_70
+ }
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_10
+ }
+ else
+ {
+ PIXEL10_70
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL11_70
+ }
+ break;
+ }
+ case 55:
+ case 23:
+ {
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL00_11
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL00_60
+ PIXEL01_90
+ }
+ PIXEL10_20
+ PIXEL11_21
+ break;
+ }
+ case 182:
+ case 150:
+ {
+ PIXEL00_22
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ PIXEL11_12
+ }
+ else
+ {
+ PIXEL01_90
+ PIXEL11_61
+ }
+ PIXEL10_20
+ break;
+ }
+ case 213:
+ case 212:
+ {
+ PIXEL00_20
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL01_11
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL01_60
+ PIXEL11_90
+ }
+ PIXEL10_21
+ break;
+ }
+ case 241:
+ case 240:
+ {
+ PIXEL00_20
+ PIXEL01_22
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL10_12
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL10_61
+ PIXEL11_90
+ }
+ break;
+ }
+ case 236:
+ case 232:
+ {
+ PIXEL00_21
+ PIXEL01_20
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ PIXEL11_11
+ }
+ else
+ {
+ PIXEL10_90
+ PIXEL11_60
+ }
+ break;
+ }
+ case 109:
+ case 105:
+ {
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL00_12
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL00_61
+ PIXEL10_90
+ }
+ PIXEL01_20
+ PIXEL11_22
+ break;
+ }
+ case 171:
+ case 43:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ PIXEL10_11
+ }
+ else
+ {
+ PIXEL00_90
+ PIXEL10_60
+ }
+ PIXEL01_21
+ PIXEL11_20
+ break;
+ }
+ case 143:
+ case 15:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ PIXEL01_12
+ }
+ else
+ {
+ PIXEL00_90
+ PIXEL01_61
+ }
+ PIXEL10_22
+ PIXEL11_20
+ break;
+ }
+ case 124:
+ {
+ PIXEL00_21
+ PIXEL01_11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ PIXEL11_10
+ break;
+ }
+ case 203:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ PIXEL01_21
+ PIXEL10_10
+ PIXEL11_11
+ break;
+ }
+ case 62:
+ {
+ PIXEL00_10
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ PIXEL10_11
+ PIXEL11_21
+ break;
+ }
+ case 211:
+ {
+ PIXEL00_11
+ PIXEL01_10
+ PIXEL10_21
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 118:
+ {
+ PIXEL00_22
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ PIXEL10_12
+ PIXEL11_10
+ break;
+ }
+ case 217:
+ {
+ PIXEL00_12
+ PIXEL01_22
+ PIXEL10_10
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 110:
+ {
+ PIXEL00_10
+ PIXEL01_12
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ PIXEL11_22
+ break;
+ }
+ case 155:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ PIXEL01_10
+ PIXEL10_22
+ PIXEL11_12
+ break;
+ }
+ case 188:
+ {
+ PIXEL00_21
+ PIXEL01_11
+ PIXEL10_11
+ PIXEL11_12
+ break;
+ }
+ case 185:
+ {
+ PIXEL00_12
+ PIXEL01_22
+ PIXEL10_11
+ PIXEL11_12
+ break;
+ }
+ case 61:
+ {
+ PIXEL00_12
+ PIXEL01_11
+ PIXEL10_11
+ PIXEL11_21
+ break;
+ }
+ case 157:
+ {
+ PIXEL00_12
+ PIXEL01_11
+ PIXEL10_22
+ PIXEL11_12
+ break;
+ }
+ case 103:
+ {
+ PIXEL00_11
+ PIXEL01_12
+ PIXEL10_12
+ PIXEL11_22
+ break;
+ }
+ case 227:
+ {
+ PIXEL00_11
+ PIXEL01_21
+ PIXEL10_12
+ PIXEL11_11
+ break;
+ }
+ case 230:
+ {
+ PIXEL00_22
+ PIXEL01_12
+ PIXEL10_12
+ PIXEL11_11
+ break;
+ }
+ case 199:
+ {
+ PIXEL00_11
+ PIXEL01_12
+ PIXEL10_21
+ PIXEL11_11
+ break;
+ }
+ case 220:
+ {
+ PIXEL00_21
+ PIXEL01_11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_10
+ }
+ else
+ {
+ PIXEL10_70
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 158:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ }
+ else
+ {
+ PIXEL00_70
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ PIXEL10_22
+ PIXEL11_12
+ break;
+ }
+ case 234:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ }
+ else
+ {
+ PIXEL00_70
+ }
+ PIXEL01_21
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ PIXEL11_11
+ break;
+ }
+ case 242:
+ {
+ PIXEL00_22
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_10
+ }
+ else
+ {
+ PIXEL01_70
+ }
+ PIXEL10_12
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 59:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_10
+ }
+ else
+ {
+ PIXEL01_70
+ }
+ PIXEL10_11
+ PIXEL11_21
+ break;
+ }
+ case 121:
+ {
+ PIXEL00_12
+ PIXEL01_22
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL11_70
+ }
+ break;
+ }
+ case 87:
+ {
+ PIXEL00_11
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ PIXEL10_21
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL11_70
+ }
+ break;
+ }
+ case 79:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ PIXEL01_12
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_10
+ }
+ else
+ {
+ PIXEL10_70
+ }
+ PIXEL11_22
+ break;
+ }
+ case 122:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ }
+ else
+ {
+ PIXEL00_70
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_10
+ }
+ else
+ {
+ PIXEL01_70
+ }
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL11_70
+ }
+ break;
+ }
+ case 94:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ }
+ else
+ {
+ PIXEL00_70
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_10
+ }
+ else
+ {
+ PIXEL10_70
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL11_70
+ }
+ break;
+ }
+ case 218:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ }
+ else
+ {
+ PIXEL00_70
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_10
+ }
+ else
+ {
+ PIXEL01_70
+ }
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_10
+ }
+ else
+ {
+ PIXEL10_70
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 91:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_10
+ }
+ else
+ {
+ PIXEL01_70
+ }
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_10
+ }
+ else
+ {
+ PIXEL10_70
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL11_70
+ }
+ break;
+ }
+ case 229:
+ {
+ PIXEL00_20
+ PIXEL01_20
+ PIXEL10_12
+ PIXEL11_11
+ break;
+ }
+ case 167:
+ {
+ PIXEL00_11
+ PIXEL01_12
+ PIXEL10_20
+ PIXEL11_20
+ break;
+ }
+ case 173:
+ {
+ PIXEL00_12
+ PIXEL01_20
+ PIXEL10_11
+ PIXEL11_20
+ break;
+ }
+ case 181:
+ {
+ PIXEL00_20
+ PIXEL01_11
+ PIXEL10_20
+ PIXEL11_12
+ break;
+ }
+ case 186:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ }
+ else
+ {
+ PIXEL00_70
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_10
+ }
+ else
+ {
+ PIXEL01_70
+ }
+ PIXEL10_11
+ PIXEL11_12
+ break;
+ }
+ case 115:
+ {
+ PIXEL00_11
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_10
+ }
+ else
+ {
+ PIXEL01_70
+ }
+ PIXEL10_12
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL11_70
+ }
+ break;
+ }
+ case 93:
+ {
+ PIXEL00_12
+ PIXEL01_11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_10
+ }
+ else
+ {
+ PIXEL10_70
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL11_70
+ }
+ break;
+ }
+ case 206:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ }
+ else
+ {
+ PIXEL00_70
+ }
+ PIXEL01_12
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_10
+ }
+ else
+ {
+ PIXEL10_70
+ }
+ PIXEL11_11
+ break;
+ }
+ case 205:
+ case 201:
+ {
+ PIXEL00_12
+ PIXEL01_20
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_10
+ }
+ else
+ {
+ PIXEL10_70
+ }
+ PIXEL11_11
+ break;
+ }
+ case 174:
+ case 46:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_10
+ }
+ else
+ {
+ PIXEL00_70
+ }
+ PIXEL01_12
+ PIXEL10_11
+ PIXEL11_20
+ break;
+ }
+ case 179:
+ case 147:
+ {
+ PIXEL00_11
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_10
+ }
+ else
+ {
+ PIXEL01_70
+ }
+ PIXEL10_20
+ PIXEL11_12
+ break;
+ }
+ case 117:
+ case 116:
+ {
+ PIXEL00_20
+ PIXEL01_11
+ PIXEL10_12
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_10
+ }
+ else
+ {
+ PIXEL11_70
+ }
+ break;
+ }
+ case 189:
+ {
+ PIXEL00_12
+ PIXEL01_11
+ PIXEL10_11
+ PIXEL11_12
+ break;
+ }
+ case 231:
+ {
+ PIXEL00_11
+ PIXEL01_12
+ PIXEL10_12
+ PIXEL11_11
+ break;
+ }
+ case 126:
+ {
+ PIXEL00_10
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ PIXEL11_10
+ break;
+ }
+ case 219:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ PIXEL01_10
+ PIXEL10_10
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 125:
+ {
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL00_12
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL00_61
+ PIXEL10_90
+ }
+ PIXEL01_11
+ PIXEL11_10
+ break;
+ }
+ case 221:
+ {
+ PIXEL00_12
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL01_11
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL01_60
+ PIXEL11_90
+ }
+ PIXEL10_10
+ break;
+ }
+ case 207:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ PIXEL01_12
+ }
+ else
+ {
+ PIXEL00_90
+ PIXEL01_61
+ }
+ PIXEL10_10
+ PIXEL11_11
+ break;
+ }
+ case 238:
+ {
+ PIXEL00_10
+ PIXEL01_12
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ PIXEL11_11
+ }
+ else
+ {
+ PIXEL10_90
+ PIXEL11_60
+ }
+ break;
+ }
+ case 190:
+ {
+ PIXEL00_10
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ PIXEL11_12
+ }
+ else
+ {
+ PIXEL01_90
+ PIXEL11_61
+ }
+ PIXEL10_11
+ break;
+ }
+ case 187:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ PIXEL10_11
+ }
+ else
+ {
+ PIXEL00_90
+ PIXEL10_60
+ }
+ PIXEL01_10
+ PIXEL11_12
+ break;
+ }
+ case 243:
+ {
+ PIXEL00_11
+ PIXEL01_10
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL10_12
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL10_61
+ PIXEL11_90
+ }
+ break;
+ }
+ case 119:
+ {
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL00_11
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL00_60
+ PIXEL01_90
+ }
+ PIXEL10_12
+ PIXEL11_10
+ break;
+ }
+ case 237:
+ case 233:
+ {
+ PIXEL00_12
+ PIXEL01_20
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_100
+ }
+ PIXEL11_11
+ break;
+ }
+ case 175:
+ case 47:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_100
+ }
+ PIXEL01_12
+ PIXEL10_11
+ PIXEL11_20
+ break;
+ }
+ case 183:
+ case 151:
+ {
+ PIXEL00_11
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_100
+ }
+ PIXEL10_20
+ PIXEL11_12
+ break;
+ }
+ case 245:
+ case 244:
+ {
+ PIXEL00_20
+ PIXEL01_11
+ PIXEL10_12
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_100
+ }
+ break;
+ }
+ case 250:
+ {
+ PIXEL00_10
+ PIXEL01_10
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 123:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ PIXEL01_10
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ PIXEL11_10
+ break;
+ }
+ case 95:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ PIXEL10_10
+ PIXEL11_10
+ break;
+ }
+ case 222:
+ {
+ PIXEL00_10
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ PIXEL10_10
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 252:
+ {
+ PIXEL00_21
+ PIXEL01_11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_100
+ }
+ break;
+ }
+ case 249:
+ {
+ PIXEL00_12
+ PIXEL01_22
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_100
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 235:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ PIXEL01_21
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_100
+ }
+ PIXEL11_11
+ break;
+ }
+ case 111:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_100
+ }
+ PIXEL01_12
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ PIXEL11_22
+ break;
+ }
+ case 63:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_100
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ PIXEL10_11
+ PIXEL11_21
+ break;
+ }
+ case 159:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_100
+ }
+ PIXEL10_22
+ PIXEL11_12
+ break;
+ }
+ case 215:
+ {
+ PIXEL00_11
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_100
+ }
+ PIXEL10_21
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 246:
+ {
+ PIXEL00_22
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ PIXEL10_12
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_100
+ }
+ break;
+ }
+ case 254:
+ {
+ PIXEL00_10
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_100
+ }
+ break;
+ }
+ case 253:
+ {
+ PIXEL00_12
+ PIXEL01_11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_100
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_100
+ }
+ break;
+ }
+ case 251:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ PIXEL01_10
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_100
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 239:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_100
+ }
+ PIXEL01_12
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_100
+ }
+ PIXEL11_11
+ break;
+ }
+ case 127:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_100
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_20
+ }
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_20
+ }
+ PIXEL11_10
+ break;
+ }
+ case 191:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_100
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_100
+ }
+ PIXEL10_11
+ PIXEL11_12
+ break;
+ }
+ case 223:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_20
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_100
+ }
+ PIXEL10_10
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_20
+ }
+ break;
+ }
+ case 247:
+ {
+ PIXEL00_11
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_100
+ }
+ PIXEL10_12
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_100
+ }
+ break;
+ }
+ case 255:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_0
+ }
+ else
+ {
+ PIXEL00_100
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_0
+ }
+ else
+ {
+ PIXEL01_100
+ }
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_0
+ }
+ else
+ {
+ PIXEL10_100
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL11_0
+ }
+ else
+ {
+ PIXEL11_100
+ }
+ break;
+ }
+ }
+ pIn+=2;
+ pOut+=8;
+ }
+ pOut+=BpL+(BpL-Xres*2*4);
+ }
+}
+
+int hq2x_InitLUTs(void)
+{
+ int i, j, k, r, g, b, Y, u, v;
+
+ if(!(LUT16to32 = malloc(65536*sizeof(int)))) return(0);
+ if(!(RGBtoYUV = malloc(65536*sizeof(int)))) { free(LUT16to32); return(0); }
+
+ for (i=0; i<65536; i++)
+ LUT16to32[i] = ((i & 0xF800) << 8) + ((i & 0x07E0) << 5) + ((i & 0x001F) << 3);
+
+ for (i=0; i<32; i++)
+ for (j=0; j<64; j++)
+ for (k=0; k<32; k++)
+ {
+ r = i << 3;
+ g = j << 2;
+ b = k << 3;
+ Y = (r + g + b) >> 2;
+ u = 128 + ((r - b) >> 2);
+ v = 128 + ((-r + 2*g -b)>>3);
+ RGBtoYUV[ (i << 11) + (j << 5) + k ] = (Y<<16) + (u<<8) + v;
+ }
+ return(1);
+}
+
+void hq2x_Kill(void)
+{
+ free(LUT16to32);
+ free(RGBtoYUV);
+
+// LUT16to32=RGBtoYUV=NULL;
+}
+
+#ifdef FIFINONO
+int main(int argc, char* argv[])
+{
+ int nRes;
+ CImage ImageIn;
+ CImage ImageOut;
+ char * szFilenameIn;
+ char * szFilenameOut;
+
+ if (argc <= 2)
+ {
+ printf("\nUsage: hq2x.exe input.bmp output.bmp\n");
+ printf("supports .bmp and .tga formats\n");
+ return 1;
+ }
+
+ szFilenameIn = argv[1];
+ szFilenameOut = argv[2];
+
+ if ( GetFileAttributes( szFilenameIn ) == -1 )
+ {
+ printf( "ERROR: file '%s'\n not found", szFilenameIn );
+ return 1;
+ }
+
+ if ( ImageIn.Load( szFilenameIn ) != 0 )
+ {
+ printf( "ERROR: can't load '%s'\n", szFilenameIn );
+ return 1;
+ }
+
+ if ( ImageIn.m_BitPerPixel != 16 )
+ {
+ if ( ImageIn.ConvertTo16() != 0 )
+ {
+ printf( "ERROR: '%s' conversion to 16 bit failed\n", szFilenameIn );
+ return 1;
+ }
+ }
+
+ printf( "\n%s is %ix%ix%i\n", szFilenameIn, ImageIn.m_Xres, ImageIn.m_Yres, ImageIn.m_BitPerPixel );
+
+ if ( ImageOut.Init( ImageIn.m_Xres*2, ImageIn.m_Yres*2, 32 ) != 0 )
+ {
+ printf( "ERROR: ImageOut.Init()\n" );
+ return 1;
+ };
+
+ InitLUTs();
+
+ hq2x_32( ImageIn.m_pBitmap, ImageOut.m_pBitmap, ImageIn.m_Xres, ImageIn.m_Yres, ImageOut.m_Xres*4 );
+
+ nRes = ImageOut.Save( szFilenameOut );
+ if ( nRes != 0 )
+ {
+ printf( "ERROR %i: ImageOut.Save(\"%s\")\n", nRes, szFilenameOut );
+ return nRes;
+ }
+ printf( "%s is %ix%ix%i\n", szFilenameOut, ImageOut.m_Xres, ImageOut.m_Yres, ImageOut.m_BitPerPixel );
+
+ printf( "\nOK\n" );
+ return 0;
+}
+#endif
diff --git a/drivers/common/hq2x.h b/drivers/common/hq2x.h
new file mode 100644
index 00000000..90298d45
--- /dev/null
+++ b/drivers/common/hq2x.h
@@ -0,0 +1,4 @@
+void hq2x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL);
+int hq2x_InitLUTs(void);
+void hq2x_Kill(void);
+
diff --git a/drivers/common/hq3x.c b/drivers/common/hq3x.c
new file mode 100644
index 00000000..9c946afd
--- /dev/null
+++ b/drivers/common/hq3x.c
@@ -0,0 +1,3865 @@
+//hq3x filter demo program
+//----------------------------------------------------------
+//Copyright (C) 2003 MaxSt ( maxst@hiend3d.com )
+
+//This program is free software; you can redistribute it and/or
+//modify it under the terms of the GNU Lesser General Public
+//License as published by the Free Software Foundation; either
+//version 2.1 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
+//Lesser General Public License for more details.
+//
+//You should have received a copy of the GNU Lesser 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
+
+/* Modified for usage in FCE Ultra */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "hq3x.h"
+
+static int *LUT16to32 = NULL;
+static int *RGBtoYUV = NULL;
+static int YUV1, YUV2;
+static const int Ymask = 0x00FF0000;
+static const int Umask = 0x0000FF00;
+static const int Vmask = 0x000000FF;
+static const int trY = 0x00300000;
+static const int trU = 0x00000700;
+static const int trV = 0x00000006;
+
+inline void Interp1(unsigned char * pc, int c1, int c2)
+{
+ *((int*)pc) = (c1*3+c2) >> 2;
+}
+
+inline void Interp2(unsigned char * pc, int c1, int c2, int c3)
+{
+ *((int*)pc) = (c1*2+c2+c3) >> 2;
+}
+
+inline void Interp3(unsigned char * pc, int c1, int c2)
+{
+ //*((int*)pc) = (c1*7+c2)/8;
+
+ *((int*)pc) = ((((c1 & 0x00FF00)*7 + (c2 & 0x00FF00) ) & 0x0007F800) +
+ (((c1 & 0xFF00FF)*7 + (c2 & 0xFF00FF) ) & 0x07F807F8)) >> 3;
+}
+
+inline void Interp4(unsigned char * pc, int c1, int c2, int c3)
+{
+ //*((int*)pc) = (c1*2+(c2+c3)*7)/16;
+
+ *((int*)pc) = ((((c1 & 0x00FF00)*2 + ((c2 & 0x00FF00) + (c3 & 0x00FF00))*7 ) & 0x000FF000) +
+ (((c1 & 0xFF00FF)*2 + ((c2 & 0xFF00FF) + (c3 & 0xFF00FF))*7 ) & 0x0FF00FF0)) >> 4;
+}
+
+inline void Interp5(unsigned char * pc, int c1, int c2)
+{
+ *((int*)pc) = (c1+c2) >> 1;
+}
+
+#define PIXEL00_1M Interp1(pOut, c[5], c[1]);
+#define PIXEL00_1U Interp1(pOut, c[5], c[2]);
+#define PIXEL00_1L Interp1(pOut, c[5], c[4]);
+#define PIXEL00_2 Interp2(pOut, c[5], c[4], c[2]);
+#define PIXEL00_4 Interp4(pOut, c[5], c[4], c[2]);
+#define PIXEL00_5 Interp5(pOut, c[4], c[2]);
+#define PIXEL00_C *((int*)(pOut)) = c[5];
+
+#define PIXEL01_1 Interp1(pOut+4, c[5], c[2]);
+#define PIXEL01_3 Interp3(pOut+4, c[5], c[2]);
+#define PIXEL01_6 Interp1(pOut+4, c[2], c[5]);
+#define PIXEL01_C *((int*)(pOut+4)) = c[5];
+
+#define PIXEL02_1M Interp1(pOut+8, c[5], c[3]);
+#define PIXEL02_1U Interp1(pOut+8, c[5], c[2]);
+#define PIXEL02_1R Interp1(pOut+8, c[5], c[6]);
+#define PIXEL02_2 Interp2(pOut+8, c[5], c[2], c[6]);
+#define PIXEL02_4 Interp4(pOut+8, c[5], c[2], c[6]);
+#define PIXEL02_5 Interp5(pOut+8, c[2], c[6]);
+#define PIXEL02_C *((int*)(pOut+8)) = c[5];
+
+#define PIXEL10_1 Interp1(pOut+BpL, c[5], c[4]);
+#define PIXEL10_3 Interp3(pOut+BpL, c[5], c[4]);
+#define PIXEL10_6 Interp1(pOut+BpL, c[4], c[5]);
+#define PIXEL10_C *((int*)(pOut+BpL)) = c[5];
+
+#define PIXEL11 *((int*)(pOut+BpL+4)) = c[5];
+
+#define PIXEL12_1 Interp1(pOut+BpL+8, c[5], c[6]);
+#define PIXEL12_3 Interp3(pOut+BpL+8, c[5], c[6]);
+#define PIXEL12_6 Interp1(pOut+BpL+8, c[6], c[5]);
+#define PIXEL12_C *((int*)(pOut+BpL+8)) = c[5];
+
+#define PIXEL20_1M Interp1(pOut+BpL+BpL, c[5], c[7]);
+#define PIXEL20_1D Interp1(pOut+BpL+BpL, c[5], c[8]);
+#define PIXEL20_1L Interp1(pOut+BpL+BpL, c[5], c[4]);
+#define PIXEL20_2 Interp2(pOut+BpL+BpL, c[5], c[8], c[4]);
+#define PIXEL20_4 Interp4(pOut+BpL+BpL, c[5], c[8], c[4]);
+#define PIXEL20_5 Interp5(pOut+BpL+BpL, c[8], c[4]);
+#define PIXEL20_C *((int*)(pOut+BpL+BpL)) = c[5];
+
+#define PIXEL21_1 Interp1(pOut+BpL+BpL+4, c[5], c[8]);
+#define PIXEL21_3 Interp3(pOut+BpL+BpL+4, c[5], c[8]);
+#define PIXEL21_6 Interp1(pOut+BpL+BpL+4, c[8], c[5]);
+#define PIXEL21_C *((int*)(pOut+BpL+BpL+4)) = c[5];
+
+#define PIXEL22_1M Interp1(pOut+BpL+BpL+8, c[5], c[9]);
+#define PIXEL22_1D Interp1(pOut+BpL+BpL+8, c[5], c[8]);
+#define PIXEL22_1R Interp1(pOut+BpL+BpL+8, c[5], c[6]);
+#define PIXEL22_2 Interp2(pOut+BpL+BpL+8, c[5], c[6], c[8]);
+#define PIXEL22_4 Interp4(pOut+BpL+BpL+8, c[5], c[6], c[8]);
+#define PIXEL22_5 Interp5(pOut+BpL+BpL+8, c[6], c[8]);
+#define PIXEL22_C *((int*)(pOut+BpL+BpL+8)) = c[5];
+
+static inline int Diff(unsigned int w1, unsigned int w2)
+{
+ YUV1 = RGBtoYUV[w1];
+ YUV2 = RGBtoYUV[w2];
+ return ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) ||
+ ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) ||
+ ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) );
+}
+
+void hq3x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL )
+{
+ int i, j, k;
+ int prevline, nextline;
+ int w[10];
+ int c[10];
+
+ // +----+----+----+
+ // | | | |
+ // | w1 | w2 | w3 |
+ // +----+----+----+
+ // | | | |
+ // | w4 | w5 | w6 |
+ // +----+----+----+
+ // | | | |
+ // | w7 | w8 | w9 |
+ // +----+----+----+
+
+ for (j=0; j<Yres; j++)
+ {
+ if (j>0) prevline = -Xres*2; else prevline = 0;
+ if (j<Yres-1) nextline = Xres*2; else nextline = 0;
+
+ for (i=0; i<Xres; i++)
+ {
+ int pattern;
+ int flag;
+
+ w[2] = *((unsigned short*)(pIn + prevline));
+ w[5] = *((unsigned short*)pIn);
+ w[8] = *((unsigned short*)(pIn + nextline));
+
+ if (i>0)
+ {
+ w[1] = *((unsigned short*)(pIn + prevline - 2));
+ w[4] = *((unsigned short*)(pIn - 2));
+ w[7] = *((unsigned short*)(pIn + nextline - 2));
+ }
+ else
+ {
+ w[1] = w[2];
+ w[4] = w[5];
+ w[7] = w[8];
+ }
+
+ if (i<Xres-1)
+ {
+ w[3] = *((unsigned short*)(pIn + prevline + 2));
+ w[6] = *((unsigned short*)(pIn + 2));
+ w[9] = *((unsigned short*)(pIn + nextline + 2));
+ }
+ else
+ {
+ w[3] = w[2];
+ w[6] = w[5];
+ w[9] = w[8];
+ }
+
+ pattern = 0;
+ flag = 1;
+
+ YUV1 = RGBtoYUV[w[5]];
+
+ for (k=1; k<=9; k++)
+ {
+ if (k==5) continue;
+
+ if ( w[k] != w[5] )
+ {
+ YUV2 = RGBtoYUV[w[k]];
+ if ( ( abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY ) ||
+ ( abs((YUV1 & Umask) - (YUV2 & Umask)) > trU ) ||
+ ( abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV ) )
+ pattern |= flag;
+ }
+ flag <<= 1;
+ }
+
+ for (k=1; k<=9; k++)
+ c[k] = LUT16to32[w[k]];
+
+ switch (pattern)
+ {
+ case 0:
+ case 1:
+ case 4:
+ case 32:
+ case 128:
+ case 5:
+ case 132:
+ case 160:
+ case 33:
+ case 129:
+ case 36:
+ case 133:
+ case 164:
+ case 161:
+ case 37:
+ case 165:
+ {
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 2:
+ case 34:
+ case 130:
+ case 162:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 16:
+ case 17:
+ case 48:
+ case 49:
+ {
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 64:
+ case 65:
+ case 68:
+ case 69:
+ {
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 8:
+ case 12:
+ case 136:
+ case 140:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 3:
+ case 35:
+ case 131:
+ case 163:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 6:
+ case 38:
+ case 134:
+ case 166:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 20:
+ case 21:
+ case 52:
+ case 53:
+ {
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 144:
+ case 145:
+ case 176:
+ case 177:
+ {
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 192:
+ case 193:
+ case 196:
+ case 197:
+ {
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 96:
+ case 97:
+ case 100:
+ case 101:
+ {
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 40:
+ case 44:
+ case 168:
+ case 172:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 9:
+ case 13:
+ case 137:
+ case 141:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 18:
+ case 50:
+ {
+ PIXEL00_1M
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL01_3
+ PIXEL02_4
+ PIXEL12_3
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 80:
+ case 81:
+ {
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_1M
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL21_C
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL12_3
+ PIXEL21_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 72:
+ case 76:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL11
+ PIXEL12_1
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_1M
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL10_3
+ PIXEL20_4
+ PIXEL21_3
+ }
+ PIXEL22_1M
+ break;
+ }
+ case 10:
+ case 138:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL01_3
+ PIXEL10_3
+ }
+ PIXEL02_1M
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 66:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 24:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 7:
+ case 39:
+ case 135:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 148:
+ case 149:
+ case 180:
+ {
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 224:
+ case 228:
+ case 225:
+ {
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 41:
+ case 169:
+ case 45:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 22:
+ case 54:
+ {
+ PIXEL00_1M
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL01_3
+ PIXEL02_4
+ PIXEL12_3
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 208:
+ case 209:
+ {
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_1M
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_3
+ PIXEL21_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 104:
+ case 108:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL11
+ PIXEL12_1
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL10_3
+ PIXEL20_4
+ PIXEL21_3
+ }
+ PIXEL22_1M
+ break;
+ }
+ case 11:
+ case 139:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL01_3
+ PIXEL10_3
+ }
+ PIXEL02_1M
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 19:
+ case 51:
+ {
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL00_2
+ PIXEL01_6
+ PIXEL02_5
+ PIXEL12_1
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 146:
+ case 178:
+ {
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL12_C
+ PIXEL22_1D
+ }
+ else
+ {
+ PIXEL01_1
+ PIXEL02_5
+ PIXEL12_6
+ PIXEL22_2
+ }
+ PIXEL00_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_2
+ PIXEL21_1
+ break;
+ }
+ case 84:
+ case 85:
+ {
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL02_1U
+ PIXEL12_C
+ PIXEL21_C
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL02_2
+ PIXEL12_6
+ PIXEL21_1
+ PIXEL22_5
+ }
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_1M
+ break;
+ }
+ case 112:
+ case 113:
+ {
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL12_1
+ PIXEL20_2
+ PIXEL21_6
+ PIXEL22_5
+ }
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ break;
+ }
+ case 200:
+ case 204:
+ {
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1R
+ }
+ else
+ {
+ PIXEL10_1
+ PIXEL20_5
+ PIXEL21_6
+ PIXEL22_2
+ }
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL11
+ PIXEL12_1
+ break;
+ }
+ case 73:
+ case 77:
+ {
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL00_1U
+ PIXEL10_C
+ PIXEL20_1M
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL00_2
+ PIXEL10_6
+ PIXEL20_5
+ PIXEL21_1
+ }
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL11
+ PIXEL12_1
+ PIXEL22_1M
+ break;
+ }
+ case 42:
+ case 170:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL10_C
+ PIXEL20_1D
+ }
+ else
+ {
+ PIXEL00_5
+ PIXEL01_1
+ PIXEL10_6
+ PIXEL20_2
+ }
+ PIXEL02_1M
+ PIXEL11
+ PIXEL12_1
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 14:
+ case 142:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_5
+ PIXEL01_6
+ PIXEL02_2
+ PIXEL10_1
+ }
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 67:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 70:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 28:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 152:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 194:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 98:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 56:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 25:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 26:
+ case 31:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL10_3
+ }
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL02_4
+ PIXEL12_3
+ }
+ PIXEL11
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 82:
+ case 214:
+ {
+ PIXEL00_1M
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ }
+ else
+ {
+ PIXEL01_3
+ PIXEL02_4
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL21_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 88:
+ case 248:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ }
+ else
+ {
+ PIXEL10_3
+ PIXEL20_4
+ }
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 74:
+ case 107:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL01_3
+ }
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL20_4
+ PIXEL21_3
+ }
+ PIXEL22_1M
+ break;
+ }
+ case 27:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL01_3
+ PIXEL10_3
+ }
+ PIXEL02_1M
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 86:
+ {
+ PIXEL00_1M
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL01_3
+ PIXEL02_4
+ PIXEL12_3
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 216:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL20_1M
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_3
+ PIXEL21_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 106:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL11
+ PIXEL12_1
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL10_3
+ PIXEL20_4
+ PIXEL21_3
+ }
+ PIXEL22_1M
+ break;
+ }
+ case 30:
+ {
+ PIXEL00_1M
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL01_3
+ PIXEL02_4
+ PIXEL12_3
+ }
+ PIXEL10_C
+ PIXEL11
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 210:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_1M
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_3
+ PIXEL21_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 120:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL11
+ PIXEL12_C
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL10_3
+ PIXEL20_4
+ PIXEL21_3
+ }
+ PIXEL22_1M
+ break;
+ }
+ case 75:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL01_3
+ PIXEL10_3
+ }
+ PIXEL02_1M
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 29:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 198:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 184:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 99:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 57:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 71:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 156:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 226:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 60:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 195:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 102:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 153:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 58:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_1M
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 83:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_1M
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 92:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_1M
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 202:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_1M
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 78:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_1M
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 154:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_1M
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 114:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_1M
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1L
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 89:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_1M
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 90:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_1M
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_1M
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 55:
+ case 23:
+ {
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL00_2
+ PIXEL01_6
+ PIXEL02_5
+ PIXEL12_1
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 182:
+ case 150:
+ {
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ PIXEL12_C
+ PIXEL22_1D
+ }
+ else
+ {
+ PIXEL01_1
+ PIXEL02_5
+ PIXEL12_6
+ PIXEL22_2
+ }
+ PIXEL00_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_2
+ PIXEL21_1
+ break;
+ }
+ case 213:
+ case 212:
+ {
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL02_1U
+ PIXEL12_C
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL02_2
+ PIXEL12_6
+ PIXEL21_1
+ PIXEL22_5
+ }
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_1M
+ break;
+ }
+ case 241:
+ case 240:
+ {
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_1
+ PIXEL20_2
+ PIXEL21_6
+ PIXEL22_5
+ }
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ break;
+ }
+ case 236:
+ case 232:
+ {
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ PIXEL21_C
+ PIXEL22_1R
+ }
+ else
+ {
+ PIXEL10_1
+ PIXEL20_5
+ PIXEL21_6
+ PIXEL22_2
+ }
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL11
+ PIXEL12_1
+ break;
+ }
+ case 109:
+ case 105:
+ {
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL00_1U
+ PIXEL10_C
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL00_2
+ PIXEL10_6
+ PIXEL20_5
+ PIXEL21_1
+ }
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL11
+ PIXEL12_1
+ PIXEL22_1M
+ break;
+ }
+ case 171:
+ case 43:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ PIXEL10_C
+ PIXEL20_1D
+ }
+ else
+ {
+ PIXEL00_5
+ PIXEL01_1
+ PIXEL10_6
+ PIXEL20_2
+ }
+ PIXEL02_1M
+ PIXEL11
+ PIXEL12_1
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 143:
+ case 15:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_5
+ PIXEL01_6
+ PIXEL02_2
+ PIXEL10_1
+ }
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 124:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL11
+ PIXEL12_C
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL10_3
+ PIXEL20_4
+ PIXEL21_3
+ }
+ PIXEL22_1M
+ break;
+ }
+ case 203:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL01_3
+ PIXEL10_3
+ }
+ PIXEL02_1M
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 62:
+ {
+ PIXEL00_1M
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL01_3
+ PIXEL02_4
+ PIXEL12_3
+ }
+ PIXEL10_C
+ PIXEL11
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 211:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_1M
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_3
+ PIXEL21_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 118:
+ {
+ PIXEL00_1M
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL01_3
+ PIXEL02_4
+ PIXEL12_3
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 217:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL20_1M
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_3
+ PIXEL21_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 110:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL11
+ PIXEL12_1
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL10_3
+ PIXEL20_4
+ PIXEL21_3
+ }
+ PIXEL22_1M
+ break;
+ }
+ case 155:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL01_3
+ PIXEL10_3
+ }
+ PIXEL02_1M
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 188:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 185:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 61:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 157:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 103:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 227:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 230:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 199:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 220:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_C
+ PIXEL11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_1M
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_3
+ PIXEL21_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 158:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL01_3
+ PIXEL02_4
+ PIXEL12_3
+ }
+ PIXEL10_C
+ PIXEL11
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 234:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL11
+ PIXEL12_1
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL10_3
+ PIXEL20_4
+ PIXEL21_3
+ }
+ PIXEL22_1R
+ break;
+ }
+ case 242:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_1M
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_1L
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_3
+ PIXEL21_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 59:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL01_3
+ PIXEL10_3
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_1M
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 121:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL11
+ PIXEL12_C
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL10_3
+ PIXEL20_4
+ PIXEL21_3
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 87:
+ {
+ PIXEL00_1L
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL01_3
+ PIXEL02_4
+ PIXEL12_3
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_1M
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 79:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL01_3
+ PIXEL10_3
+ }
+ PIXEL02_1R
+ PIXEL11
+ PIXEL12_1
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_1M
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 122:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_1M
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL11
+ PIXEL12_C
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL10_3
+ PIXEL20_4
+ PIXEL21_3
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 94:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL01_3
+ PIXEL02_4
+ PIXEL12_3
+ }
+ PIXEL10_C
+ PIXEL11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_1M
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 218:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_1M
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL10_C
+ PIXEL11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_1M
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_3
+ PIXEL21_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 91:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL01_3
+ PIXEL10_3
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_1M
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL11
+ PIXEL12_C
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_1M
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 229:
+ {
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 167:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 173:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 181:
+ {
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 186:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_1M
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 115:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_1M
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1L
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 93:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_1M
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 206:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_1M
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 205:
+ case 201:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_1M
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 174:
+ case 46:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_1M
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 179:
+ case 147:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_1M
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 117:
+ case 116:
+ {
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1L
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_1M
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 189:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 231:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 126:
+ {
+ PIXEL00_1M
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL01_3
+ PIXEL02_4
+ PIXEL12_3
+ }
+ PIXEL11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL10_3
+ PIXEL20_4
+ PIXEL21_3
+ }
+ PIXEL22_1M
+ break;
+ }
+ case 219:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL01_3
+ PIXEL10_3
+ }
+ PIXEL02_1M
+ PIXEL11
+ PIXEL20_1M
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_3
+ PIXEL21_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 125:
+ {
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL00_1U
+ PIXEL10_C
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL00_2
+ PIXEL10_6
+ PIXEL20_5
+ PIXEL21_1
+ }
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL11
+ PIXEL12_C
+ PIXEL22_1M
+ break;
+ }
+ case 221:
+ {
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL02_1U
+ PIXEL12_C
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL02_2
+ PIXEL12_6
+ PIXEL21_1
+ PIXEL22_5
+ }
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL10_C
+ PIXEL11
+ PIXEL20_1M
+ break;
+ }
+ case 207:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_5
+ PIXEL01_6
+ PIXEL02_2
+ PIXEL10_1
+ }
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 238:
+ {
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ PIXEL21_C
+ PIXEL22_1R
+ }
+ else
+ {
+ PIXEL10_1
+ PIXEL20_5
+ PIXEL21_6
+ PIXEL22_2
+ }
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL11
+ PIXEL12_1
+ break;
+ }
+ case 190:
+ {
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ PIXEL12_C
+ PIXEL22_1D
+ }
+ else
+ {
+ PIXEL01_1
+ PIXEL02_5
+ PIXEL12_6
+ PIXEL22_2
+ }
+ PIXEL00_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL20_1D
+ PIXEL21_1
+ break;
+ }
+ case 187:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ PIXEL10_C
+ PIXEL20_1D
+ }
+ else
+ {
+ PIXEL00_5
+ PIXEL01_1
+ PIXEL10_6
+ PIXEL20_2
+ }
+ PIXEL02_1M
+ PIXEL11
+ PIXEL12_C
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 243:
+ {
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_1
+ PIXEL20_2
+ PIXEL21_6
+ PIXEL22_5
+ }
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL10_1
+ PIXEL11
+ break;
+ }
+ case 119:
+ {
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL00_2
+ PIXEL01_6
+ PIXEL02_5
+ PIXEL12_1
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL20_1L
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 237:
+ case 233:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_2
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_C
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 175:
+ case 47:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_2
+ break;
+ }
+ case 183:
+ case 151:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_C
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_2
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 245:
+ case 244:
+ {
+ PIXEL00_2
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1L
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 250:
+ {
+ PIXEL00_1M
+ PIXEL01_C
+ PIXEL02_1M
+ PIXEL11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ }
+ else
+ {
+ PIXEL10_3
+ PIXEL20_4
+ }
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 123:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL01_3
+ }
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL20_4
+ PIXEL21_3
+ }
+ PIXEL22_1M
+ break;
+ }
+ case 95:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL10_3
+ }
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL02_4
+ PIXEL12_3
+ }
+ PIXEL11
+ PIXEL20_1M
+ PIXEL21_C
+ PIXEL22_1M
+ break;
+ }
+ case 222:
+ {
+ PIXEL00_1M
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ }
+ else
+ {
+ PIXEL01_3
+ PIXEL02_4
+ }
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL21_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 252:
+ {
+ PIXEL00_1M
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL11
+ PIXEL12_C
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ }
+ else
+ {
+ PIXEL10_3
+ PIXEL20_4
+ }
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 249:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_C
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 235:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL01_3
+ }
+ PIXEL02_1M
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_C
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 111:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL20_4
+ PIXEL21_3
+ }
+ PIXEL22_1M
+ break;
+ }
+ case 63:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL02_4
+ PIXEL12_3
+ }
+ PIXEL10_C
+ PIXEL11
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_1M
+ break;
+ }
+ case 159:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL10_3
+ }
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_C
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 215:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_C
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1M
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL21_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 246:
+ {
+ PIXEL00_1M
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ }
+ else
+ {
+ PIXEL01_3
+ PIXEL02_4
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1L
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 254:
+ {
+ PIXEL00_1M
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ }
+ else
+ {
+ PIXEL01_3
+ PIXEL02_4
+ }
+ PIXEL11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ }
+ else
+ {
+ PIXEL10_3
+ PIXEL20_4
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_3
+ PIXEL21_3
+ PIXEL22_2
+ }
+ break;
+ }
+ case 253:
+ {
+ PIXEL00_1U
+ PIXEL01_1
+ PIXEL02_1U
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_C
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 251:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL01_3
+ }
+ PIXEL02_1M
+ PIXEL11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL10_C
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL10_3
+ PIXEL20_2
+ PIXEL21_3
+ }
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL12_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL12_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 239:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ PIXEL02_1R
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_1
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_C
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ PIXEL22_1R
+ break;
+ }
+ case 127:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL01_C
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_2
+ PIXEL01_3
+ PIXEL10_3
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL02_4
+ PIXEL12_3
+ }
+ PIXEL11
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_C
+ PIXEL21_C
+ }
+ else
+ {
+ PIXEL20_4
+ PIXEL21_3
+ }
+ PIXEL22_1M
+ break;
+ }
+ case 191:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_C
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1D
+ PIXEL21_1
+ PIXEL22_1D
+ break;
+ }
+ case 223:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ PIXEL10_C
+ }
+ else
+ {
+ PIXEL00_4
+ PIXEL10_3
+ }
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL01_C
+ PIXEL02_C
+ PIXEL12_C
+ }
+ else
+ {
+ PIXEL01_3
+ PIXEL02_2
+ PIXEL12_3
+ }
+ PIXEL11
+ PIXEL20_1M
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL21_C
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL21_3
+ PIXEL22_4
+ }
+ break;
+ }
+ case 247:
+ {
+ PIXEL00_1L
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_C
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL10_1
+ PIXEL11
+ PIXEL12_C
+ PIXEL20_1L
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ case 255:
+ {
+ if (Diff(w[4], w[2]))
+ {
+ PIXEL00_C
+ }
+ else
+ {
+ PIXEL00_2
+ }
+ PIXEL01_C
+ if (Diff(w[2], w[6]))
+ {
+ PIXEL02_C
+ }
+ else
+ {
+ PIXEL02_2
+ }
+ PIXEL10_C
+ PIXEL11
+ PIXEL12_C
+ if (Diff(w[8], w[4]))
+ {
+ PIXEL20_C
+ }
+ else
+ {
+ PIXEL20_2
+ }
+ PIXEL21_C
+ if (Diff(w[6], w[8]))
+ {
+ PIXEL22_C
+ }
+ else
+ {
+ PIXEL22_2
+ }
+ break;
+ }
+ }
+ pIn+=2;
+ pOut+=12;
+ }
+ pOut+=BpL - Xres * 3 * 4;
+ pOut+=BpL;
+ pOut+=BpL;
+ }
+}
+
+int hq3x_InitLUTs(void)
+{
+ int i, j, k, r, g, b, Y, u, v;
+
+ if(!(LUT16to32 = malloc(65536*sizeof(int)))) return(0);
+ if(!(RGBtoYUV = malloc(65536*sizeof(int)))) { free(LUT16to32); return(0); }
+
+ for (i=0; i<65536; i++)
+ LUT16to32[i] = ((i & 0xF800) << 8) + ((i & 0x07E0) << 5) + ((i & 0x001F) << 3);
+
+ for (i=0; i<32; i++)
+ for (j=0; j<64; j++)
+ for (k=0; k<32; k++)
+ {
+ r = i << 3;
+ g = j << 2;
+ b = k << 3;
+ Y = (r + g + b) >> 2;
+ u = 128 + ((r - b) >> 2);
+ v = 128 + ((-r + 2*g -b)>>3);
+ RGBtoYUV[ (i << 11) + (j << 5) + k ] = (Y<<16) + (u<<8) + v;
+ }
+ return(1);
+}
+
+void hq3x_Kill(void)
+{
+ free(LUT16to32);
+ free(RGBtoYUV);
+}
+
diff --git a/drivers/common/hq3x.h b/drivers/common/hq3x.h
new file mode 100644
index 00000000..48b379fa
--- /dev/null
+++ b/drivers/common/hq3x.h
@@ -0,0 +1,4 @@
+void hq3x_32( unsigned char * pIn, unsigned char * pOut, int Xres, int Yres, int BpL);
+int hq3x_InitLUTs(void);
+void hq3x_Kill(void);
+
diff --git a/drivers/common/scale2x.c b/drivers/common/scale2x.c
new file mode 100644
index 00000000..09d3632d
--- /dev/null
+++ b/drivers/common/scale2x.c
@@ -0,0 +1,923 @@
+/*
+ * This file is part of the Scale2x project.
+ *
+ * Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * This file contains a C and MMX implementation of the Scale2x effect.
+ *
+ * You can find an high level description of the effect at :
+ *
+ * http://scale2x.sourceforge.net/
+ *
+ * Alternatively at the previous license terms, you are allowed to use this
+ * code in your program with these conditions:
+ * - the program is not used in commercial activities.
+ * - the whole source code of the program is released with the binary.
+ * - derivative works of the program are allowed.
+ */
+
+#include "scale2x.h"
+
+#include <assert.h>
+
+/***************************************************************************/
+/* Scale2x C implementation */
+
+static inline void scale2x_8_def_single(scale2x_uint8* __restrict__ dst, const scale2x_uint8* __restrict__ src0, const scale2x_uint8* __restrict__ src1, const scale2x_uint8* __restrict__ src2, unsigned count)
+{
+ assert(count >= 2);
+
+ /* first pixel */
+ dst[0] = src1[0];
+ if (src1[1] == src0[0] && src2[0] != src0[0])
+ dst[1] = src0[0];
+ else
+ dst[1] = src1[0];
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 2;
+
+ /* central pixels */
+ count -= 2;
+ while (count) {
+ if (src0[0] != src2[0] && src1[-1] != src1[1]) {
+ dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
+ dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
+ } else {
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ }
+
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 2;
+ --count;
+ }
+
+ /* last pixel */
+ if (src1[-1] == src0[0] && src2[0] != src0[0])
+ dst[0] = src0[0];
+ else
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+}
+
+static inline void scale2x_16_def_single(scale2x_uint16* __restrict__ dst, const scale2x_uint16* __restrict__ src0, const scale2x_uint16* __restrict__ src1, const scale2x_uint16* __restrict__ src2, unsigned count)
+{
+ assert(count >= 2);
+
+ /* first pixel */
+ dst[0] = src1[0];
+ if (src1[1] == src0[0] && src2[0] != src0[0])
+ dst[1] = src0[0];
+ else
+ dst[1] = src1[0];
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 2;
+
+ /* central pixels */
+ count -= 2;
+ while (count) {
+ if (src0[0] != src2[0] && src1[-1] != src1[1]) {
+ dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
+ dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
+ } else {
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ }
+
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 2;
+ --count;
+ }
+
+ /* last pixel */
+ if (src1[-1] == src0[0] && src2[0] != src0[0])
+ dst[0] = src0[0];
+ else
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+}
+
+static inline void scale2x_32_def_single(scale2x_uint32* __restrict__ dst, const scale2x_uint32* __restrict__ src0, const scale2x_uint32* __restrict__ src1, const scale2x_uint32* __restrict__ src2, unsigned count)
+{
+ assert(count >= 2);
+
+ /* first pixel */
+ dst[0] = src1[0];
+ if (src1[1] == src0[0] && src2[0] != src0[0])
+ dst[1] = src0[0];
+ else
+ dst[1] = src1[0];
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 2;
+
+ /* central pixels */
+ count -= 2;
+ while (count) {
+ if (src0[0] != src2[0] && src1[-1] != src1[1]) {
+ dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0];
+ dst[1] = src1[1] == src0[0] ? src0[0] : src1[0];
+ } else {
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ }
+
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 2;
+ --count;
+ }
+
+ /* last pixel */
+ if (src1[-1] == src0[0] && src2[0] != src0[0])
+ dst[0] = src0[0];
+ else
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+}
+
+/**
+ * Scale by a factor of 2 a row of pixels of 8 bits.
+ * The function is implemented in C.
+ * The pixels over the left and right borders are assumed of the same color of
+ * the pixels on the border.
+ * \param src0 Pointer at the first pixel of the previous row.
+ * \param src1 Pointer at the first pixel of the current row.
+ * \param src2 Pointer at the first pixel of the next row.
+ * \param count Length in pixels of the src0, src1 and src2 rows.
+ * It must be at least 2.
+ * \param dst0 First destination row, double length in pixels.
+ * \param dst1 Second destination row, double length in pixels.
+ */
+void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)
+{
+ assert(count >= 2);
+
+ scale2x_8_def_single(dst0, src0, src1, src2, count);
+ scale2x_8_def_single(dst1, src2, src1, src0, count);
+}
+
+/**
+ * Scale by a factor of 2 a row of pixels of 16 bits.
+ * This function operates like scale2x_8_def() but for 16 bits pixels.
+ * \param src0 Pointer at the first pixel of the previous row.
+ * \param src1 Pointer at the first pixel of the current row.
+ * \param src2 Pointer at the first pixel of the next row.
+ * \param count Length in pixels of the src0, src1 and src2 rows.
+ * It must be at least 2.
+ * \param dst0 First destination row, double length in pixels.
+ * \param dst1 Second destination row, double length in pixels.
+ */
+void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)
+{
+ assert(count >= 2);
+
+ scale2x_16_def_single(dst0, src0, src1, src2, count);
+ scale2x_16_def_single(dst1, src2, src1, src0, count);
+}
+
+/**
+ * Scale by a factor of 2 a row of pixels of 32 bits.
+ * This function operates like scale2x_8_def() but for 32 bits pixels.
+ * \param src0 Pointer at the first pixel of the previous row.
+ * \param src1 Pointer at the first pixel of the current row.
+ * \param src2 Pointer at the first pixel of the next row.
+ * \param count Length in pixels of the src0, src1 and src2 rows.
+ * It must be at least 2.
+ * \param dst0 First destination row, double length in pixels.
+ * \param dst1 Second destination row, double length in pixels.
+ */
+void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)
+{
+ assert(count >= 2);
+
+ scale2x_32_def_single(dst0, src0, src1, src2, count);
+ scale2x_32_def_single(dst1, src2, src1, src0, count);
+}
+
+/***************************************************************************/
+/* Scale2x MMX implementation */
+
+#if defined(__GNUC__) && defined(__i386__)
+
+/*
+ * Apply the Scale2x effect at a single row.
+ * This function must be called only by the other scale2x functions.
+ *
+ * Considering the pixel map :
+ *
+ * ABC (src0)
+ * DEF (src1)
+ * GHI (src2)
+ *
+ * this functions compute 2 new pixels in substitution of the source pixel E
+ * like this map :
+ *
+ * ab (dst)
+ *
+ * with these variables :
+ *
+ * &current -> E
+ * &current_left -> D
+ * &current_right -> F
+ * &current_upper -> B
+ * &current_lower -> H
+ *
+ * %0 -> current_upper
+ * %1 -> current
+ * %2 -> current_lower
+ * %3 -> dst
+ * %4 -> counter
+ *
+ * %mm0 -> *current_left
+ * %mm1 -> *current_next
+ * %mm2 -> tmp0
+ * %mm3 -> tmp1
+ * %mm4 -> tmp2
+ * %mm5 -> tmp3
+ * %mm6 -> *current_upper
+ * %mm7 -> *current
+ */
+static inline void scale2x_8_mmx_single(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)
+{
+ assert(count >= 16);
+ assert(count % 8 == 0);
+
+ /* always do the first and last run */
+ count -= 2*8;
+
+ __asm__ __volatile__(
+/* first run */
+ /* set the current, current_pre, current_next registers */
+ "movq 0(%1), %%mm0\n"
+ "movq 0(%1), %%mm7\n"
+ "movq 8(%1), %%mm1\n"
+ "psllq $56, %%mm0\n"
+ "psllq $56, %%mm1\n"
+ "psrlq $56, %%mm0\n"
+ "movq %%mm7, %%mm2\n"
+ "movq %%mm7, %%mm3\n"
+ "psllq $8, %%mm2\n"
+ "psrlq $8, %%mm3\n"
+ "por %%mm2, %%mm0\n"
+ "por %%mm3, %%mm1\n"
+
+ /* current_upper */
+ "movq (%0), %%mm6\n"
+
+ /* compute the upper-left pixel for dst on %%mm2 */
+ /* compute the upper-right pixel for dst on %%mm4 */
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "movq %%mm0, %%mm3\n"
+ "movq %%mm1, %%mm5\n"
+ "pcmpeqb %%mm6, %%mm2\n"
+ "pcmpeqb %%mm6, %%mm4\n"
+ "pcmpeqb (%2), %%mm3\n"
+ "pcmpeqb (%2), %%mm5\n"
+ "pandn %%mm2, %%mm3\n"
+ "pandn %%mm4, %%mm5\n"
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "pcmpeqb %%mm1, %%mm2\n"
+ "pcmpeqb %%mm0, %%mm4\n"
+ "pandn %%mm3, %%mm2\n"
+ "pandn %%mm5, %%mm4\n"
+ "movq %%mm2, %%mm3\n"
+ "movq %%mm4, %%mm5\n"
+ "pand %%mm6, %%mm2\n"
+ "pand %%mm6, %%mm4\n"
+ "pandn %%mm7, %%mm3\n"
+ "pandn %%mm7, %%mm5\n"
+ "por %%mm3, %%mm2\n"
+ "por %%mm5, %%mm4\n"
+
+ /* set *dst */
+ "movq %%mm2, %%mm3\n"
+ "punpcklbw %%mm4, %%mm2\n"
+ "punpckhbw %%mm4, %%mm3\n"
+ "movq %%mm2, (%3)\n"
+ "movq %%mm3, 8(%3)\n"
+
+ /* next */
+ "addl $8, %0\n"
+ "addl $8, %1\n"
+ "addl $8, %2\n"
+ "addl $16, %3\n"
+
+/* central runs */
+ "shrl $3, %4\n"
+ "jz 1f\n"
+
+ "0:\n"
+
+ /* set the current, current_pre, current_next registers */
+ "movq -8(%1), %%mm0\n"
+ "movq (%1), %%mm7\n"
+ "movq 8(%1), %%mm1\n"
+ "psrlq $56, %%mm0\n"
+ "psllq $56, %%mm1\n"
+ "movq %%mm7, %%mm2\n"
+ "movq %%mm7, %%mm3\n"
+ "psllq $8, %%mm2\n"
+ "psrlq $8, %%mm3\n"
+ "por %%mm2, %%mm0\n"
+ "por %%mm3, %%mm1\n"
+
+ /* current_upper */
+ "movq (%0), %%mm6\n"
+
+ /* compute the upper-left pixel for dst on %%mm2 */
+ /* compute the upper-right pixel for dst on %%mm4 */
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "movq %%mm0, %%mm3\n"
+ "movq %%mm1, %%mm5\n"
+ "pcmpeqb %%mm6, %%mm2\n"
+ "pcmpeqb %%mm6, %%mm4\n"
+ "pcmpeqb (%2), %%mm3\n"
+ "pcmpeqb (%2), %%mm5\n"
+ "pandn %%mm2, %%mm3\n"
+ "pandn %%mm4, %%mm5\n"
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "pcmpeqb %%mm1, %%mm2\n"
+ "pcmpeqb %%mm0, %%mm4\n"
+ "pandn %%mm3, %%mm2\n"
+ "pandn %%mm5, %%mm4\n"
+ "movq %%mm2, %%mm3\n"
+ "movq %%mm4, %%mm5\n"
+ "pand %%mm6, %%mm2\n"
+ "pand %%mm6, %%mm4\n"
+ "pandn %%mm7, %%mm3\n"
+ "pandn %%mm7, %%mm5\n"
+ "por %%mm3, %%mm2\n"
+ "por %%mm5, %%mm4\n"
+
+ /* set *dst */
+ "movq %%mm2, %%mm3\n"
+ "punpcklbw %%mm4, %%mm2\n"
+ "punpckhbw %%mm4, %%mm3\n"
+ "movq %%mm2, (%3)\n"
+ "movq %%mm3, 8(%3)\n"
+
+ /* next */
+ "addl $8, %0\n"
+ "addl $8, %1\n"
+ "addl $8, %2\n"
+ "addl $16, %3\n"
+
+ "decl %4\n"
+ "jnz 0b\n"
+ "1:\n"
+
+/* final run */
+ /* set the current, current_pre, current_next registers */
+ "movq (%1), %%mm1\n"
+ "movq (%1), %%mm7\n"
+ "movq -8(%1), %%mm0\n"
+ "psrlq $56, %%mm1\n"
+ "psrlq $56, %%mm0\n"
+ "psllq $56, %%mm1\n"
+ "movq %%mm7, %%mm2\n"
+ "movq %%mm7, %%mm3\n"
+ "psllq $8, %%mm2\n"
+ "psrlq $8, %%mm3\n"
+ "por %%mm2, %%mm0\n"
+ "por %%mm3, %%mm1\n"
+
+ /* current_upper */
+ "movq (%0), %%mm6\n"
+
+ /* compute the upper-left pixel for dst on %%mm2 */
+ /* compute the upper-right pixel for dst on %%mm4 */
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "movq %%mm0, %%mm3\n"
+ "movq %%mm1, %%mm5\n"
+ "pcmpeqb %%mm6, %%mm2\n"
+ "pcmpeqb %%mm6, %%mm4\n"
+ "pcmpeqb (%2), %%mm3\n"
+ "pcmpeqb (%2), %%mm5\n"
+ "pandn %%mm2, %%mm3\n"
+ "pandn %%mm4, %%mm5\n"
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "pcmpeqb %%mm1, %%mm2\n"
+ "pcmpeqb %%mm0, %%mm4\n"
+ "pandn %%mm3, %%mm2\n"
+ "pandn %%mm5, %%mm4\n"
+ "movq %%mm2, %%mm3\n"
+ "movq %%mm4, %%mm5\n"
+ "pand %%mm6, %%mm2\n"
+ "pand %%mm6, %%mm4\n"
+ "pandn %%mm7, %%mm3\n"
+ "pandn %%mm7, %%mm5\n"
+ "por %%mm3, %%mm2\n"
+ "por %%mm5, %%mm4\n"
+
+ /* set *dst */
+ "movq %%mm2, %%mm3\n"
+ "punpcklbw %%mm4, %%mm2\n"
+ "punpckhbw %%mm4, %%mm3\n"
+ "movq %%mm2, (%3)\n"
+ "movq %%mm3, 8(%3)\n"
+
+ : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
+ :
+ : "cc"
+ );
+}
+
+static inline void scale2x_16_mmx_single(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)
+{
+ assert(count >= 8);
+ assert(count % 4 == 0);
+
+ /* always do the first and last run */
+ count -= 2*4;
+
+ __asm__ __volatile__(
+/* first run */
+ /* set the current, current_pre, current_next registers */
+ "movq 0(%1), %%mm0\n"
+ "movq 0(%1), %%mm7\n"
+ "movq 8(%1), %%mm1\n"
+ "psllq $48, %%mm0\n"
+ "psllq $48, %%mm1\n"
+ "psrlq $48, %%mm0\n"
+ "movq %%mm7, %%mm2\n"
+ "movq %%mm7, %%mm3\n"
+ "psllq $16, %%mm2\n"
+ "psrlq $16, %%mm3\n"
+ "por %%mm2, %%mm0\n"
+ "por %%mm3, %%mm1\n"
+
+ /* current_upper */
+ "movq (%0), %%mm6\n"
+
+ /* compute the upper-left pixel for dst on %%mm2 */
+ /* compute the upper-right pixel for dst on %%mm4 */
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "movq %%mm0, %%mm3\n"
+ "movq %%mm1, %%mm5\n"
+ "pcmpeqw %%mm6, %%mm2\n"
+ "pcmpeqw %%mm6, %%mm4\n"
+ "pcmpeqw (%2), %%mm3\n"
+ "pcmpeqw (%2), %%mm5\n"
+ "pandn %%mm2, %%mm3\n"
+ "pandn %%mm4, %%mm5\n"
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "pcmpeqw %%mm1, %%mm2\n"
+ "pcmpeqw %%mm0, %%mm4\n"
+ "pandn %%mm3, %%mm2\n"
+ "pandn %%mm5, %%mm4\n"
+ "movq %%mm2, %%mm3\n"
+ "movq %%mm4, %%mm5\n"
+ "pand %%mm6, %%mm2\n"
+ "pand %%mm6, %%mm4\n"
+ "pandn %%mm7, %%mm3\n"
+ "pandn %%mm7, %%mm5\n"
+ "por %%mm3, %%mm2\n"
+ "por %%mm5, %%mm4\n"
+
+ /* set *dst */
+ "movq %%mm2, %%mm3\n"
+ "punpcklwd %%mm4, %%mm2\n"
+ "punpckhwd %%mm4, %%mm3\n"
+ "movq %%mm2, (%3)\n"
+ "movq %%mm3, 8(%3)\n"
+
+ /* next */
+ "addl $8, %0\n"
+ "addl $8, %1\n"
+ "addl $8, %2\n"
+ "addl $16, %3\n"
+
+/* central runs */
+ "shrl $2, %4\n"
+ "jz 1f\n"
+
+ "0:\n"
+
+ /* set the current, current_pre, current_next registers */
+ "movq -8(%1), %%mm0\n"
+ "movq (%1), %%mm7\n"
+ "movq 8(%1), %%mm1\n"
+ "psrlq $48, %%mm0\n"
+ "psllq $48, %%mm1\n"
+ "movq %%mm7, %%mm2\n"
+ "movq %%mm7, %%mm3\n"
+ "psllq $16, %%mm2\n"
+ "psrlq $16, %%mm3\n"
+ "por %%mm2, %%mm0\n"
+ "por %%mm3, %%mm1\n"
+
+ /* current_upper */
+ "movq (%0), %%mm6\n"
+
+ /* compute the upper-left pixel for dst on %%mm2 */
+ /* compute the upper-right pixel for dst on %%mm4 */
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "movq %%mm0, %%mm3\n"
+ "movq %%mm1, %%mm5\n"
+ "pcmpeqw %%mm6, %%mm2\n"
+ "pcmpeqw %%mm6, %%mm4\n"
+ "pcmpeqw (%2), %%mm3\n"
+ "pcmpeqw (%2), %%mm5\n"
+ "pandn %%mm2, %%mm3\n"
+ "pandn %%mm4, %%mm5\n"
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "pcmpeqw %%mm1, %%mm2\n"
+ "pcmpeqw %%mm0, %%mm4\n"
+ "pandn %%mm3, %%mm2\n"
+ "pandn %%mm5, %%mm4\n"
+ "movq %%mm2, %%mm3\n"
+ "movq %%mm4, %%mm5\n"
+ "pand %%mm6, %%mm2\n"
+ "pand %%mm6, %%mm4\n"
+ "pandn %%mm7, %%mm3\n"
+ "pandn %%mm7, %%mm5\n"
+ "por %%mm3, %%mm2\n"
+ "por %%mm5, %%mm4\n"
+
+ /* set *dst */
+ "movq %%mm2, %%mm3\n"
+ "punpcklwd %%mm4, %%mm2\n"
+ "punpckhwd %%mm4, %%mm3\n"
+ "movq %%mm2, (%3)\n"
+ "movq %%mm3, 8(%3)\n"
+
+ /* next */
+ "addl $8, %0\n"
+ "addl $8, %1\n"
+ "addl $8, %2\n"
+ "addl $16, %3\n"
+
+ "decl %4\n"
+ "jnz 0b\n"
+ "1:\n"
+
+/* final run */
+ /* set the current, current_pre, current_next registers */
+ "movq (%1), %%mm1\n"
+ "movq (%1), %%mm7\n"
+ "movq -8(%1), %%mm0\n"
+ "psrlq $48, %%mm1\n"
+ "psrlq $48, %%mm0\n"
+ "psllq $48, %%mm1\n"
+ "movq %%mm7, %%mm2\n"
+ "movq %%mm7, %%mm3\n"
+ "psllq $16, %%mm2\n"
+ "psrlq $16, %%mm3\n"
+ "por %%mm2, %%mm0\n"
+ "por %%mm3, %%mm1\n"
+
+ /* current_upper */
+ "movq (%0), %%mm6\n"
+
+ /* compute the upper-left pixel for dst on %%mm2 */
+ /* compute the upper-right pixel for dst on %%mm4 */
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "movq %%mm0, %%mm3\n"
+ "movq %%mm1, %%mm5\n"
+ "pcmpeqw %%mm6, %%mm2\n"
+ "pcmpeqw %%mm6, %%mm4\n"
+ "pcmpeqw (%2), %%mm3\n"
+ "pcmpeqw (%2), %%mm5\n"
+ "pandn %%mm2, %%mm3\n"
+ "pandn %%mm4, %%mm5\n"
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "pcmpeqw %%mm1, %%mm2\n"
+ "pcmpeqw %%mm0, %%mm4\n"
+ "pandn %%mm3, %%mm2\n"
+ "pandn %%mm5, %%mm4\n"
+ "movq %%mm2, %%mm3\n"
+ "movq %%mm4, %%mm5\n"
+ "pand %%mm6, %%mm2\n"
+ "pand %%mm6, %%mm4\n"
+ "pandn %%mm7, %%mm3\n"
+ "pandn %%mm7, %%mm5\n"
+ "por %%mm3, %%mm2\n"
+ "por %%mm5, %%mm4\n"
+
+ /* set *dst */
+ "movq %%mm2, %%mm3\n"
+ "punpcklwd %%mm4, %%mm2\n"
+ "punpckhwd %%mm4, %%mm3\n"
+ "movq %%mm2, (%3)\n"
+ "movq %%mm3, 8(%3)\n"
+
+ : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
+ :
+ : "cc"
+ );
+}
+
+static inline void scale2x_32_mmx_single(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)
+{
+ assert(count >= 4);
+ assert(count % 2 == 0);
+
+ /* always do the first and last run */
+ count -= 2*2;
+
+ __asm__ __volatile__(
+/* first run */
+ /* set the current, current_pre, current_next registers */
+ "movq 0(%1), %%mm0\n"
+ "movq 0(%1), %%mm7\n"
+ "movq 8(%1), %%mm1\n"
+ "psllq $32, %%mm0\n"
+ "psllq $32, %%mm1\n"
+ "psrlq $32, %%mm0\n"
+ "movq %%mm7, %%mm2\n"
+ "movq %%mm7, %%mm3\n"
+ "psllq $32, %%mm2\n"
+ "psrlq $32, %%mm3\n"
+ "por %%mm2, %%mm0\n"
+ "por %%mm3, %%mm1\n"
+
+ /* current_upper */
+ "movq (%0), %%mm6\n"
+
+ /* compute the upper-left pixel for dst on %%mm2 */
+ /* compute the upper-right pixel for dst on %%mm4 */
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "movq %%mm0, %%mm3\n"
+ "movq %%mm1, %%mm5\n"
+ "pcmpeqd %%mm6, %%mm2\n"
+ "pcmpeqd %%mm6, %%mm4\n"
+ "pcmpeqd (%2), %%mm3\n"
+ "pcmpeqd (%2), %%mm5\n"
+ "pandn %%mm2, %%mm3\n"
+ "pandn %%mm4, %%mm5\n"
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "pcmpeqd %%mm1, %%mm2\n"
+ "pcmpeqd %%mm0, %%mm4\n"
+ "pandn %%mm3, %%mm2\n"
+ "pandn %%mm5, %%mm4\n"
+ "movq %%mm2, %%mm3\n"
+ "movq %%mm4, %%mm5\n"
+ "pand %%mm6, %%mm2\n"
+ "pand %%mm6, %%mm4\n"
+ "pandn %%mm7, %%mm3\n"
+ "pandn %%mm7, %%mm5\n"
+ "por %%mm3, %%mm2\n"
+ "por %%mm5, %%mm4\n"
+
+ /* set *dst */
+ "movq %%mm2, %%mm3\n"
+ "punpckldq %%mm4, %%mm2\n"
+ "punpckhdq %%mm4, %%mm3\n"
+ "movq %%mm2, (%3)\n"
+ "movq %%mm3, 8(%3)\n"
+
+ /* next */
+ "addl $8, %0\n"
+ "addl $8, %1\n"
+ "addl $8, %2\n"
+ "addl $16, %3\n"
+
+/* central runs */
+ "shrl $1, %4\n"
+ "jz 1f\n"
+
+ "0:\n"
+
+ /* set the current, current_pre, current_next registers */
+ "movq -8(%1), %%mm0\n"
+ "movq (%1), %%mm7\n"
+ "movq 8(%1), %%mm1\n"
+ "psrlq $32, %%mm0\n"
+ "psllq $32, %%mm1\n"
+ "movq %%mm7, %%mm2\n"
+ "movq %%mm7, %%mm3\n"
+ "psllq $32, %%mm2\n"
+ "psrlq $32, %%mm3\n"
+ "por %%mm2, %%mm0\n"
+ "por %%mm3, %%mm1\n"
+
+ /* current_upper */
+ "movq (%0), %%mm6\n"
+
+ /* compute the upper-left pixel for dst on %%mm2 */
+ /* compute the upper-right pixel for dst on %%mm4 */
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "movq %%mm0, %%mm3\n"
+ "movq %%mm1, %%mm5\n"
+ "pcmpeqd %%mm6, %%mm2\n"
+ "pcmpeqd %%mm6, %%mm4\n"
+ "pcmpeqd (%2), %%mm3\n"
+ "pcmpeqd (%2), %%mm5\n"
+ "pandn %%mm2, %%mm3\n"
+ "pandn %%mm4, %%mm5\n"
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "pcmpeqd %%mm1, %%mm2\n"
+ "pcmpeqd %%mm0, %%mm4\n"
+ "pandn %%mm3, %%mm2\n"
+ "pandn %%mm5, %%mm4\n"
+ "movq %%mm2, %%mm3\n"
+ "movq %%mm4, %%mm5\n"
+ "pand %%mm6, %%mm2\n"
+ "pand %%mm6, %%mm4\n"
+ "pandn %%mm7, %%mm3\n"
+ "pandn %%mm7, %%mm5\n"
+ "por %%mm3, %%mm2\n"
+ "por %%mm5, %%mm4\n"
+
+ /* set *dst */
+ "movq %%mm2, %%mm3\n"
+ "punpckldq %%mm4, %%mm2\n"
+ "punpckhdq %%mm4, %%mm3\n"
+ "movq %%mm2, (%3)\n"
+ "movq %%mm3, 8(%3)\n"
+
+ /* next */
+ "addl $8, %0\n"
+ "addl $8, %1\n"
+ "addl $8, %2\n"
+ "addl $16, %3\n"
+
+ "decl %4\n"
+ "jnz 0b\n"
+ "1:\n"
+
+/* final run */
+ /* set the current, current_pre, current_next registers */
+ "movq (%1), %%mm1\n"
+ "movq (%1), %%mm7\n"
+ "movq -8(%1), %%mm0\n"
+ "psrlq $32, %%mm1\n"
+ "psrlq $32, %%mm0\n"
+ "psllq $32, %%mm1\n"
+ "movq %%mm7, %%mm2\n"
+ "movq %%mm7, %%mm3\n"
+ "psllq $32, %%mm2\n"
+ "psrlq $32, %%mm3\n"
+ "por %%mm2, %%mm0\n"
+ "por %%mm3, %%mm1\n"
+
+ /* current_upper */
+ "movq (%0), %%mm6\n"
+
+ /* compute the upper-left pixel for dst on %%mm2 */
+ /* compute the upper-right pixel for dst on %%mm4 */
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "movq %%mm0, %%mm3\n"
+ "movq %%mm1, %%mm5\n"
+ "pcmpeqd %%mm6, %%mm2\n"
+ "pcmpeqd %%mm6, %%mm4\n"
+ "pcmpeqd (%2), %%mm3\n"
+ "pcmpeqd (%2), %%mm5\n"
+ "pandn %%mm2, %%mm3\n"
+ "pandn %%mm4, %%mm5\n"
+ "movq %%mm0, %%mm2\n"
+ "movq %%mm1, %%mm4\n"
+ "pcmpeqd %%mm1, %%mm2\n"
+ "pcmpeqd %%mm0, %%mm4\n"
+ "pandn %%mm3, %%mm2\n"
+ "pandn %%mm5, %%mm4\n"
+ "movq %%mm2, %%mm3\n"
+ "movq %%mm4, %%mm5\n"
+ "pand %%mm6, %%mm2\n"
+ "pand %%mm6, %%mm4\n"
+ "pandn %%mm7, %%mm3\n"
+ "pandn %%mm7, %%mm5\n"
+ "por %%mm3, %%mm2\n"
+ "por %%mm5, %%mm4\n"
+
+ /* set *dst */
+ "movq %%mm2, %%mm3\n"
+ "punpckldq %%mm4, %%mm2\n"
+ "punpckhdq %%mm4, %%mm3\n"
+ "movq %%mm2, (%3)\n"
+ "movq %%mm3, 8(%3)\n"
+
+ : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count)
+ :
+ : "cc"
+ );
+}
+
+/**
+ * Scale by a factor of 2 a row of pixels of 8 bits.
+ * This is a very fast MMX implementation.
+ * The implementation uses a combination of cmp/and/not operations to
+ * completly remove the need of conditional jumps. This trick give the
+ * major speed improvement.
+ * Also, using the 8 bytes MMX registers more than one pixel are computed
+ * at the same time.
+ * Before calling this function you must ensure that the currenct CPU supports
+ * the MMX instruction set. After calling it you must be sure to call the EMMS
+ * instruction before any floating-point operation.
+ * The pixels over the left and right borders are assumed of the same color of
+ * the pixels on the border.
+ * \param src0 Pointer at the first pixel of the previous row.
+ * \param src1 Pointer at the first pixel of the current row.
+ * \param src2 Pointer at the first pixel of the next row.
+ * \param count Length in pixels of the src0, src1 and src2 rows. It must
+ * be at least 16 and a multiple of 8.
+ * \param dst0 First destination row, double length in pixels.
+ * \param dst1 Second destination row, double length in pixels.
+ */
+void scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count)
+{
+ if (count % 8 != 0 || count < 16) {
+ scale2x_8_def(dst0, dst1, src0, src1, src2, count);
+ } else {
+ assert(count >= 16);
+ assert(count % 8 == 0);
+
+ scale2x_8_mmx_single(dst0, src0, src1, src2, count);
+ scale2x_8_mmx_single(dst1, src2, src1, src0, count);
+ }
+}
+
+/**
+ * Scale by a factor of 2 a row of pixels of 16 bits.
+ * This function operates like scale2x_8_mmx() but for 16 bits pixels.
+ * \param src0 Pointer at the first pixel of the previous row.
+ * \param src1 Pointer at the first pixel of the current row.
+ * \param src2 Pointer at the first pixel of the next row.
+ * \param count Length in pixels of the src0, src1 and src2 rows. It must
+ * be at least 8 and a multiple of 4.
+ * \param dst0 First destination row, double length in pixels.
+ * \param dst1 Second destination row, double length in pixels.
+ */
+void scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count)
+{
+ if (count % 4 != 0 || count < 8) {
+ scale2x_16_def(dst0, dst1, src0, src1, src2, count);
+ } else {
+ assert(count >= 8);
+ assert(count % 4 == 0);
+
+ scale2x_16_mmx_single(dst0, src0, src1, src2, count);
+ scale2x_16_mmx_single(dst1, src2, src1, src0, count);
+ }
+}
+
+/**
+ * Scale by a factor of 2 a row of pixels of 32 bits.
+ * This function operates like scale2x_8_mmx() but for 32 bits pixels.
+ * \param src0 Pointer at the first pixel of the previous row.
+ * \param src1 Pointer at the first pixel of the current row.
+ * \param src2 Pointer at the first pixel of the next row.
+ * \param count Length in pixels of the src0, src1 and src2 rows. It must
+ * be at least 4 and a multiple of 2.
+ * \param dst0 First destination row, double length in pixels.
+ * \param dst1 Second destination row, double length in pixels.
+ */
+void scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count)
+{
+ if (count % 2 != 0 || count < 4) {
+ scale2x_32_def(dst0, dst1, src0, src1, src2, count);
+ } else {
+ assert(count >= 4);
+ assert(count % 2 == 0);
+
+ scale2x_32_mmx_single(dst0, src0, src1, src2, count);
+ scale2x_32_mmx_single(dst1, src2, src1, src0, count);
+ }
+}
+
+#endif
+
diff --git a/drivers/common/scale2x.h b/drivers/common/scale2x.h
new file mode 100644
index 00000000..fa6d152e
--- /dev/null
+++ b/drivers/common/scale2x.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of the Scale2x project.
+ *
+ * Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __SCALE2X_H
+#define __SCALE2X_H
+
+typedef unsigned char scale2x_uint8;
+typedef unsigned short scale2x_uint16;
+typedef unsigned scale2x_uint32;
+
+void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);
+void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);
+void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);
+
+#if defined(__GNUC__) && defined(__i386__)
+
+void scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count);
+void scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count);
+void scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count);
+
+/**
+ * End the use of the MMX instructions.
+ * This function must be called before using any floating-point operations.
+ */
+static inline void scale2x_mmx_emms(void)
+{
+ __asm__ __volatile__ (
+ "emms"
+ );
+}
+
+#endif
+
+#endif
+
diff --git a/drivers/common/scale3x.c b/drivers/common/scale3x.c
new file mode 100644
index 00000000..b155fd07
--- /dev/null
+++ b/drivers/common/scale3x.c
@@ -0,0 +1,382 @@
+/*
+ * This file is part of the Scale2x project.
+ *
+ * Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * This file contains a C and MMX implementation of the Scale2x effect.
+ *
+ * You can find an high level description of the effect at :
+ *
+ * http://scale2x.sourceforge.net/
+ *
+ * Alternatively at the previous license terms, you are allowed to use this
+ * code in your program with these conditions:
+ * - the program is not used in commercial activities.
+ * - the whole source code of the program is released with the binary.
+ * - derivative works of the program are allowed.
+ */
+
+#include "scale3x.h"
+
+#include <assert.h>
+
+/***************************************************************************/
+/* Scale3x C implementation */
+
+static inline void scale3x_8_def_border(scale3x_uint8* __restrict__ dst, const scale3x_uint8* __restrict__ src0, const scale3x_uint8* __restrict__ src1, const scale3x_uint8* __restrict__ src2, unsigned count)
+{
+ assert(count >= 2);
+
+ /* first pixel */
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ if (src1[1] == src0[0] && src2[0] != src0[0])
+ dst[2] = src0[0];
+ else
+ dst[2] = src1[0];
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 3;
+
+ /* central pixels */
+ count -= 2;
+ while (count) {
+ if (src0[0] != src2[0] && src1[-1] != src1[1]) {
+ dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
+ dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
+ dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
+ } else {
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ dst[2] = src1[0];
+ }
+
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 3;
+ --count;
+ }
+
+ /* last pixel */
+ if (src1[-1] == src0[0] && src2[0] != src0[0])
+ dst[0] = src0[0];
+ else
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ dst[2] = src1[0];
+}
+
+static inline void scale3x_8_def_center(scale3x_uint8* __restrict__ dst, const scale3x_uint8* __restrict__ src0, const scale3x_uint8* __restrict__ src1, const scale3x_uint8* __restrict__ src2, unsigned count)
+{
+ assert(count >= 2);
+
+ /* first pixel */
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ if (src0[0] != src2[0]) {
+ dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
+ } else {
+ dst[2] = src1[0];
+ }
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 3;
+
+ /* central pixels */
+ count -= 2;
+ while (count) {
+ if (src0[0] != src2[0] && src1[-1] != src1[1]) {
+ dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
+ dst[1] = src1[0];
+ dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
+ } else {
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ dst[2] = src1[0];
+ }
+
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 3;
+ --count;
+ }
+
+ /* last pixel */
+ if (src0[0] != src2[0]) {
+ dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
+ } else {
+ dst[0] = src1[0];
+ }
+ dst[1] = src1[0];
+ dst[2] = src1[0];
+}
+
+static inline void scale3x_16_def_border(scale3x_uint16* __restrict__ dst, const scale3x_uint16* __restrict__ src0, const scale3x_uint16* __restrict__ src1, const scale3x_uint16* __restrict__ src2, unsigned count)
+{
+ assert(count >= 2);
+
+ /* first pixel */
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ if (src1[1] == src0[0] && src2[0] != src0[0])
+ dst[2] = src0[0];
+ else
+ dst[2] = src1[0];
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 3;
+
+ /* central pixels */
+ count -= 2;
+ while (count) {
+ if (src0[0] != src2[0] && src1[-1] != src1[1]) {
+ dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
+ dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
+ dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
+ } else {
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ dst[2] = src1[0];
+ }
+
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 3;
+ --count;
+ }
+
+ /* last pixel */
+ if (src1[-1] == src0[0] && src2[0] != src0[0])
+ dst[0] = src0[0];
+ else
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ dst[2] = src1[0];
+}
+
+static inline void scale3x_16_def_center(scale3x_uint16* __restrict__ dst, const scale3x_uint16* __restrict__ src0, const scale3x_uint16* __restrict__ src1, const scale3x_uint16* __restrict__ src2, unsigned count)
+{
+ assert(count >= 2);
+
+ /* first pixel */
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ if (src0[0] != src2[0]) {
+ dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
+ } else {
+ dst[2] = src1[0];
+ }
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 3;
+
+ /* central pixels */
+ count -= 2;
+ while (count) {
+ if (src0[0] != src2[0] && src1[-1] != src1[1]) {
+ dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
+ dst[1] = src1[0];
+ dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
+ } else {
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ dst[2] = src1[0];
+ }
+
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 3;
+ --count;
+ }
+
+ /* last pixel */
+ if (src0[0] != src2[0]) {
+ dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
+ } else {
+ dst[0] = src1[0];
+ }
+ dst[1] = src1[0];
+ dst[2] = src1[0];
+}
+
+static inline void scale3x_32_def_border(scale3x_uint32* __restrict__ dst, const scale3x_uint32* __restrict__ src0, const scale3x_uint32* __restrict__ src1, const scale3x_uint32* __restrict__ src2, unsigned count)
+{
+ assert(count >= 2);
+
+ /* first pixel */
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ if (src1[1] == src0[0] && src2[0] != src0[0])
+ dst[2] = src0[0];
+ else
+ dst[2] = src1[0];
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 3;
+
+ /* central pixels */
+ count -= 2;
+ while (count) {
+ if (src0[0] != src2[0] && src1[-1] != src1[1]) {
+ dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
+ dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
+ dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
+ } else {
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ dst[2] = src1[0];
+ }
+
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 3;
+ --count;
+ }
+
+ /* last pixel */
+ if (src1[-1] == src0[0] && src2[0] != src0[0])
+ dst[0] = src0[0];
+ else
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ dst[2] = src1[0];
+}
+
+static inline void scale3x_32_def_center(scale3x_uint32* __restrict__ dst, const scale3x_uint32* __restrict__ src0, const scale3x_uint32* __restrict__ src1, const scale3x_uint32* __restrict__ src2, unsigned count)
+{
+ assert(count >= 2);
+
+ /* first pixel */
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ if (src0[0] != src2[0]) {
+ dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
+ } else {
+ dst[2] = src1[0];
+ }
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 3;
+
+ /* central pixels */
+ count -= 2;
+ while (count) {
+ if (src0[0] != src2[0] && src1[-1] != src1[1]) {
+ dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
+ dst[1] = src1[0];
+ dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
+ } else {
+ dst[0] = src1[0];
+ dst[1] = src1[0];
+ dst[2] = src1[0];
+ }
+
+ ++src0;
+ ++src1;
+ ++src2;
+ dst += 3;
+ --count;
+ }
+
+ /* last pixel */
+ if (src0[0] != src2[0]) {
+ dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
+ } else {
+ dst[0] = src1[0];
+ }
+ dst[1] = src1[0];
+ dst[2] = src1[0];
+}
+
+/**
+ * Scale by a factor of 3 a row of pixels of 8 bits.
+ * The function is implemented in C.
+ * The pixels over the left and right borders are assumed of the same color of
+ * the pixels on the border.
+ * \param src0 Pointer at the first pixel of the previous row.
+ * \param src1 Pointer at the first pixel of the current row.
+ * \param src2 Pointer at the first pixel of the next row.
+ * \param count Length in pixels of the src0, src1 and src2 rows.
+ * It must be at least 2.
+ * \param dst0 First destination row, triple length in pixels.
+ * \param dst1 Second destination row, triple length in pixels.
+ * \param dst2 Third destination row, triple length in pixels.
+ */
+void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count)
+{
+ assert(count >= 2);
+
+ scale3x_8_def_border(dst0, src0, src1, src2, count);
+ scale3x_8_def_center(dst1, src0, src1, src2, count);
+ scale3x_8_def_border(dst2, src2, src1, src0, count);
+}
+
+/**
+ * Scale by a factor of 3 a row of pixels of 16 bits.
+ * This function operates like scale3x_8_def() but for 16 bits pixels.
+ * \param src0 Pointer at the first pixel of the previous row.
+ * \param src1 Pointer at the first pixel of the current row.
+ * \param src2 Pointer at the first pixel of the next row.
+ * \param count Length in pixels of the src0, src1 and src2 rows.
+ * It must be at least 2.
+ * \param dst0 First destination row, triple length in pixels.
+ * \param dst1 Second destination row, triple length in pixels.
+ * \param dst2 Third destination row, triple length in pixels.
+ */
+void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count)
+{
+ assert(count >= 2);
+
+ scale3x_16_def_border(dst0, src0, src1, src2, count);
+ scale3x_16_def_center(dst1, src0, src1, src2, count);
+ scale3x_16_def_border(dst2, src2, src1, src0, count);
+}
+
+/**
+ * Scale by a factor of 3 a row of pixels of 32 bits.
+ * This function operates like scale3x_8_def() but for 32 bits pixels.
+ * \param src0 Pointer at the first pixel of the previous row.
+ * \param src1 Pointer at the first pixel of the current row.
+ * \param src2 Pointer at the first pixel of the next row.
+ * \param count Length in pixels of the src0, src1 and src2 rows.
+ * It must be at least 2.
+ * \param dst0 First destination row, triple length in pixels.
+ * \param dst1 Second destination row, triple length in pixels.
+ * \param dst2 Third destination row, triple length in pixels.
+ */
+void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count)
+{
+ assert(count >= 2);
+
+ scale3x_32_def_border(dst0, src0, src1, src2, count);
+ scale3x_32_def_center(dst1, src0, src1, src2, count);
+ scale3x_32_def_border(dst2, src2, src1, src0, count);
+}
+
diff --git a/drivers/common/scale3x.h b/drivers/common/scale3x.h
new file mode 100644
index 00000000..cb108ee7
--- /dev/null
+++ b/drivers/common/scale3x.h
@@ -0,0 +1,33 @@
+/*
+ * This file is part of the Scale2x project.
+ *
+ * Copyright (C) 2001, 2002, 2003, 2004 Andrea Mazzoleni
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __SCALE3X_H
+#define __SCALE3X_H
+
+typedef unsigned char scale3x_uint8;
+typedef unsigned short scale3x_uint16;
+typedef unsigned scale3x_uint32;
+
+void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count);
+void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count);
+void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count);
+
+#endif
+
diff --git a/drivers/common/scalebit.c b/drivers/common/scalebit.c
new file mode 100644
index 00000000..5eef618b
--- /dev/null
+++ b/drivers/common/scalebit.c
@@ -0,0 +1,385 @@
+/*
+ * This file is part of the Scale2x project.
+ *
+ * Copyright (C) 2003 Andrea Mazzoleni
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * This file contains an example implementation of the Scale effect
+ * applyed to a generic bitmap.
+ *
+ * You can find an high level description of the effect at :
+ *
+ * http://scale2x.sourceforge.net/
+ *
+ * Alternatively at the previous license terms, you are allowed to use this
+ * code in your program with these conditions:
+ * - the program is not used in commercial activities.
+ * - the whole source code of the program is released with the binary.
+ * - derivative works of the program are allowed.
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "scale2x.h"
+#include "scale3x.h"
+
+#if HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+
+/**
+ * Apply the Scale2x effect on a group of rows. Used internally.
+ */
+static inline void stage_scale2x(void* dst0, void* dst1, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)
+{
+ switch (pixel) {
+#if defined(__GNUC__) && defined(__i386__)
+ case 1 : scale2x_8_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break;
+ case 2 : scale2x_16_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break;
+ case 4 : scale2x_32_mmx(dst0, dst1, src0, src1, src2, pixel_per_row); break;
+#else
+ case 1 : scale2x_8_def(dst0, dst1, src0, src1, src2, pixel_per_row); break;
+ case 2 : scale2x_16_def(dst0, dst1, src0, src1, src2, pixel_per_row); break;
+ case 4 : scale2x_32_def(dst0, dst1, src0, src1, src2, pixel_per_row); break;
+#endif
+ }
+}
+
+/**
+ * Apply the Scale3x effect on a group of rows. Used internally.
+ */
+static inline void stage_scale3x(void* dst0, void* dst1, void* dst2, const void* src0, const void* src1, const void* src2, unsigned pixel, unsigned pixel_per_row)
+{
+ switch (pixel) {
+ case 1 : scale3x_8_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break;
+ case 2 : scale3x_16_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break;
+ case 4 : scale3x_32_def(dst0, dst1, dst2, src0, src1, src2, pixel_per_row); break;
+ }
+}
+
+/**
+ * Apply the Scale4x effect on a group of rows. Used internally.
+ */
+static inline void stage_scale4x(void* dst0, void* dst1, void* dst2, void* dst3, const void* src0, const void* src1, const void* src2, const void* src3, unsigned pixel, unsigned pixel_per_row)
+{
+ stage_scale2x(dst0, dst1, src0, src1, src2, pixel, 2 * pixel_per_row);
+ stage_scale2x(dst2, dst3, src1, src2, src3, pixel, 2 * pixel_per_row);
+}
+
+#define SCDST(i) (dst+(i)*dst_slice)
+#define SCSRC(i) (src+(i)*src_slice)
+#define SCMID(i) (mid[(i)])
+
+/**
+ * Apply the Scale2x effect on a bitmap.
+ * The destination bitmap is filled with the scaled version of the source bitmap.
+ * The source bitmap isn't modified.
+ * The destination bitmap must be manually allocated before calling the function,
+ * note that the resulting size is exactly 2x2 times the size of the source bitmap.
+ * \param void_dst Pointer at the first pixel of the destination bitmap.
+ * \param dst_slice Size in bytes of a destination bitmap row.
+ * \param void_src Pointer at the first pixel of the source bitmap.
+ * \param src_slice Size in bytes of a source bitmap row.
+ * \param pixel Bytes per pixel of the source and destination bitmap.
+ * \param width Horizontal size in pixels of the source bitmap.
+ * \param height Vertical size in pixels of the source bitmap.
+ */
+static void scale2x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
+{
+ unsigned char* dst = (unsigned char*)void_dst;
+ const unsigned char* src = (unsigned char*)void_src;
+ unsigned count;
+
+ assert(height >= 2);
+
+ count = height;
+
+ stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
+
+ dst = SCDST(2);
+
+ count -= 2;
+ while (count) {
+ stage_scale2x(SCDST(0), SCDST(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
+
+ dst = SCDST(2);
+ src = SCSRC(1);
+
+ --count;
+ }
+
+ stage_scale2x(SCDST(0), SCDST(1), SCSRC(1-1), SCSRC(2-1), SCSRC(2-1), pixel, width);
+
+#if defined(__GNUC__) && defined(__i386__)
+ scale2x_mmx_emms();
+#endif
+}
+
+/**
+ * Apply the Scale32x effect on a bitmap.
+ * The destination bitmap is filled with the scaled version of the source bitmap.
+ * The source bitmap isn't modified.
+ * The destination bitmap must be manually allocated before calling the function,
+ * note that the resulting size is exactly 3x3 times the size of the source bitmap.
+ * \param void_dst Pointer at the first pixel of the destination bitmap.
+ * \param dst_slice Size in bytes of a destination bitmap row.
+ * \param void_src Pointer at the first pixel of the source bitmap.
+ * \param src_slice Size in bytes of a source bitmap row.
+ * \param pixel Bytes per pixel of the source and destination bitmap.
+ * \param width Horizontal size in pixels of the source bitmap.
+ * \param height Vertical size in pixels of the source bitmap.
+ */
+static void scale3x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
+{
+ unsigned char* dst = (unsigned char*)void_dst;
+ const unsigned char* src = (unsigned char*)void_src;
+ unsigned count;
+
+ assert(height >= 2);
+
+ count = height;
+
+ stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
+
+ dst = SCDST(3);
+
+ count -= 2;
+ while (count) {
+ stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
+
+ dst = SCDST(3);
+ src = SCSRC(1);
+
+ --count;
+ }
+
+ stage_scale3x(SCDST(0), SCDST(1), SCDST(2), SCSRC(1-1), SCSRC(2-1), SCSRC(2-1), pixel, width);
+}
+
+/**
+ * Apply the Scale4x effect on a bitmap.
+ * The destination bitmap is filled with the scaled version of the source bitmap.
+ * The source bitmap isn't modified.
+ * The destination bitmap must be manually allocated before calling the function,
+ * note that the resulting size is exactly 4x4 times the size of the source bitmap.
+ * \note This function requires also a small buffer bitmap used internally to store
+ * intermediate results. This bitmap must have at least an horizontal size in bytes of 2*width*pixel,
+ * and a vertical size of 6 rows. The memory of this buffer must not be allocated
+ * in video memory because it's also read and not only written. Generally
+ * a heap (malloc) or a stack (alloca) buffer is the best choices.
+ * \param void_dst Pointer at the first pixel of the destination bitmap.
+ * \param dst_slice Size in bytes of a destination bitmap row.
+ * \param void_mid Pointer at the first pixel of the buffer bitmap.
+ * \param mid_slice Size in bytes of a buffer bitmap row.
+ * \param void_src Pointer at the first pixel of the source bitmap.
+ * \param src_slice Size in bytes of a source bitmap row.
+ * \param pixel Bytes per pixel of the source and destination bitmap.
+ * \param width Horizontal size in pixels of the source bitmap.
+ * \param height Vertical size in pixels of the source bitmap.
+ */
+static void scale4x_buf(void* void_dst, unsigned dst_slice, void* void_mid, unsigned mid_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
+{
+ unsigned char* dst = (unsigned char*)void_dst;
+ const unsigned char* src = (unsigned char*)void_src;
+ unsigned count;
+ unsigned char* mid[6];
+
+ assert(height >= 4);
+
+ count = height;
+
+ /* set the 6 buffer pointers */
+ mid[0] = (unsigned char*)void_mid;
+ mid[1] = mid[0] + mid_slice;
+ mid[2] = mid[1] + mid_slice;
+ mid[3] = mid[2] + mid_slice;
+ mid[4] = mid[3] + mid_slice;
+ mid[5] = mid[4] + mid_slice;
+
+ stage_scale2x(SCMID(-2+6), SCMID(-1+6), SCSRC(0), SCSRC(0), SCSRC(1), pixel, width);
+ stage_scale2x(SCMID(0), SCMID(1), SCSRC(0), SCSRC(1), SCSRC(2), pixel, width);
+ stage_scale2x(SCMID(2), SCMID(3), SCSRC(1), SCSRC(2), SCSRC(3), pixel, width);
+ stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-2+6), SCMID(-2+6), SCMID(-1+6), SCMID(0), pixel, width);
+
+ dst = SCDST(4);
+
+ stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(-1+6), SCMID(0), SCMID(1), SCMID(2), pixel, width);
+
+ dst = SCDST(4);
+
+ count -= 4;
+ while (count) {
+ unsigned char* tmp;
+
+ stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(4), pixel, width);
+ stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);
+
+ dst = SCDST(4);
+ src = SCSRC(1);
+
+ tmp = SCMID(0); /* shift by 2 position */
+ SCMID(0) = SCMID(2);
+ SCMID(2) = SCMID(4);
+ SCMID(4) = tmp;
+ tmp = SCMID(1);
+ SCMID(1) = SCMID(3);
+ SCMID(3) = SCMID(5);
+ SCMID(5) = tmp;
+
+ --count;
+ }
+
+ stage_scale2x(SCMID(4), SCMID(5), SCSRC(2), SCSRC(3), SCSRC(3), pixel, width);
+ stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(1), SCMID(2), SCMID(3), SCMID(4), pixel, width);
+
+ dst = SCDST(4);
+
+ stage_scale4x(SCDST(0), SCDST(1), SCDST(2), SCDST(3), SCMID(3), SCMID(4), SCMID(5), SCMID(5), pixel, width);
+
+#if defined(__GNUC__) && defined(__i386__)
+ scale2x_mmx_emms();
+#endif
+}
+
+/**
+ * Apply the Scale4x effect on a bitmap.
+ * The destination bitmap is filled with the scaled version of the source bitmap.
+ * The source bitmap isn't modified.
+ * The destination bitmap must be manually allocated before calling the function,
+ * note that the resulting size is exactly 4x4 times the size of the source bitmap.
+ * \note This function operates like ::scale4x_buf() but the intermediate buffer is
+ * automatically allocated in the stack.
+ * \param void_dst Pointer at the first pixel of the destination bitmap.
+ * \param dst_slice Size in bytes of a destination bitmap row.
+ * \param void_src Pointer at the first pixel of the source bitmap.
+ * \param src_slice Size in bytes of a source bitmap row.
+ * \param pixel Bytes per pixel of the source and destination bitmap.
+ * \param width Horizontal size in pixels of the source bitmap.
+ * \param height Vertical size in pixels of the source bitmap.
+ */
+static void scale4x(void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
+{
+ unsigned mid_slice;
+ void* mid;
+
+ mid_slice = 2 * pixel * width; /* required space for 1 row buffer */
+
+ mid_slice = (mid_slice + 0x7) & ~0x7; /* align to 8 bytes */
+
+#if HAVE_ALLOCA
+ mid = alloca(6 * mid_slice); /* allocate space for 6 row buffers */
+
+ assert(mid != 0); /* alloca should never fails */
+#else
+ mid = malloc(6 * mid_slice); /* allocate space for 6 row buffers */
+
+ if (!mid)
+ return;
+#endif
+
+ scale4x_buf(void_dst, dst_slice, mid, mid_slice, void_src, src_slice, pixel, width, height);
+
+#if !HAVE_ALLOCA
+ free(mid);
+#endif
+}
+
+/**
+ * Check if the scale implementation is applicable at the given arguments.
+ * \param scale Scale factor. 2, 3 or 4.
+ * \param pixel Bytes per pixel of the source and destination bitmap.
+ * \param width Horizontal size in pixels of the source bitmap.
+ * \param height Vertical size in pixels of the source bitmap.
+ * \return
+ * - -1 on precondition violated.
+ * - 0 on success.
+ */
+int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height)
+{
+ if (scale != 2 && scale != 3 && scale != 4)
+ return -1;
+
+ if (pixel != 1 && pixel != 2 && pixel != 4)
+ return -1;
+
+ switch (scale) {
+ case 2 :
+ case 3 :
+ if (height < 2)
+ return -1;
+ break;
+ case 4 :
+ if (height < 4)
+ return -1;
+ break;
+ }
+
+#if defined(__GNUC__) && defined(__i386__)
+ switch (scale) {
+ case 2 :
+ case 4 :
+ if (width < (16 / pixel))
+ return -1;
+ if (width % (8 / pixel) != 0)
+ return -1;
+ break;
+ case 3 :
+ if (width < 2)
+ return -1;
+ break;
+ }
+#else
+ if (width < 2)
+ return -1;
+#endif
+
+ return 0;
+}
+
+/**
+ * Apply the Scale effect on a bitmap.
+ * This function is simply a common interface for ::scale2x(), ::scale3x() and ::scale4x().
+ * \param scale Scale factor. 2, 3 or 4.
+ * \param void_dst Pointer at the first pixel of the destination bitmap.
+ * \param dst_slice Size in bytes of a destination bitmap row.
+ * \param void_src Pointer at the first pixel of the source bitmap.
+ * \param src_slice Size in bytes of a source bitmap row.
+ * \param pixel Bytes per pixel of the source and destination bitmap.
+ * \param width Horizontal size in pixels of the source bitmap.
+ * \param height Vertical size in pixels of the source bitmap.
+ */
+void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height)
+{
+ switch (scale) {
+ case 2 :
+ scale2x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
+ break;
+ case 3 :
+ scale3x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
+ break;
+ case 4 :
+ scale4x(void_dst, dst_slice, void_src, src_slice, pixel, width, height);
+ break;
+ }
+}
+
diff --git a/drivers/common/scalebit.h b/drivers/common/scalebit.h
new file mode 100644
index 00000000..19d987df
--- /dev/null
+++ b/drivers/common/scalebit.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the Scale2x project.
+ *
+ * Copyright (C) 2003 Andrea Mazzoleni
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * This file contains an example implementation of the Scale effect
+ * applyed to a generic bitmap.
+ *
+ * You can find an high level description of the effect at :
+ *
+ * http://scale2x.sourceforge.net/
+ *
+ * Alternatively at the previous license terms, you are allowed to use this
+ * code in your program with these conditions:
+ * - the program is not used in commercial activities.
+ * - the whole source code of the program is released with the binary.
+ * - derivative works of the program are allowed.
+ */
+
+#ifndef __SCALEBIT_H
+#define __SCALEBIT_H
+
+int scale_precondition(unsigned scale, unsigned pixel, unsigned width, unsigned height);
+void scale(unsigned scale, void* void_dst, unsigned dst_slice, const void* void_src, unsigned src_slice, unsigned pixel, unsigned width, unsigned height);
+
+#endif
+
diff --git a/drivers/common/vidblit.c b/drivers/common/vidblit.c
new file mode 100644
index 00000000..ac828ddf
--- /dev/null
+++ b/drivers/common/vidblit.c
@@ -0,0 +1,843 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdlib.h>
+#include "scalebit.h"
+#include "hq2x.h"
+#include "hq3x.h"
+
+#include "../../types.h"
+
+static uint32 CBM[3];
+static uint32 *palettetranslate=0;
+
+static uint16 *specbuf=NULL; // 8bpp -> 16bpp, pre hq2x/hq3x
+static uint32 *specbuf32bpp = NULL; // Buffer to hold output
+ // of hq2x/hq3x when converting
+ // to 16bpp and 24bpp
+static int backBpp, backshiftr[3], backshiftl[3];
+//static uint32 backmask[3];
+
+static uint8 *specbuf8bpp = NULL; // For 2xscale, 3xscale.
+
+
+static int silt;
+
+static int Bpp; // BYTES per pixel
+static int highefx;
+
+#define BLUR_RED 20
+#define BLUR_GREEN 20
+#define BLUR_BLUE 10
+
+#define FVB_SCANLINES 1
+
+/* The blur effect is only available for bpp>=16. It could be easily modified
+ to look like what happens on the real NES and TV, but lack of decent
+ synchronization to the vertical retrace period makes it look rather
+ blah.
+*/
+#define FVB_BLUR 2
+
+static void CalculateShift(uint32 *CBM, int *cshiftr, int *cshiftl)
+{
+ int a,x,z,y;
+ cshiftl[0]=cshiftl[1]=cshiftl[2]=-1;
+ for(a=0;a<3;a++)
+ {
+ for(x=0,y=-1,z=0;x<32;x++)
+ {
+ if(CBM[a]&(1<<x))
+ {
+ if(cshiftl[a]==-1) cshiftl[a]=x;
+ z++;
+ }
+ }
+ cshiftr[a]=(8-z);
+ }
+}
+
+
+int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int efx, int specfilt)
+{
+ if(specfilt == 2 || specfilt == 4) // scale2x and scale3x
+ {
+ int multi;
+
+ if(specfilt == 2) multi = 2 * 2;
+ else if(specfilt == 4) multi = 3 * 3;
+
+ specbuf8bpp = malloc(256*240*multi);
+
+ }
+ else if(specfilt == 1 || specfilt == 3) // hq2x and hq3x
+ {
+ if(b == 1)
+ return(0);
+
+ if(b == 2 || b == 3) // 8->16->(hq2x)->32-> 24 or 16. YARGH.
+ {
+ uint32 tmpCBM[3];
+ backBpp = b;
+ tmpCBM[0]=rmask;
+ tmpCBM[1]=gmask;
+ tmpCBM[2]=bmask;
+
+ CalculateShift(tmpCBM, backshiftr, backshiftl);
+
+ if(b == 2)
+ {
+ // ark
+ backshiftr[0] += 16;
+ backshiftr[1] += 8;
+ backshiftr[2] += 0;
+
+ // Begin iffy code(requires 16bpp and 32bpp to have same RGB order)
+ //backmask[0] = (rmask>>backshiftl[0]) << (backshiftr[0]);
+ //backmask[1] = (gmask>>backshiftl[1]) << (backshiftr[1]);
+ //backmask[2] = (bmask>>backshiftl[2]) << (backshiftr[2]);
+
+ //int x;
+ //for(x=0;x<3;x++)
+ // backshiftr[x] -= backshiftl[x];
+ // End iffy code
+ }
+ if(specfilt == 1) specbuf32bpp = malloc(256*240*4*sizeof(uint32));
+ else if(specfilt == 3) specbuf32bpp = malloc(256*240*9*sizeof(uint32));
+ }
+
+ efx=0;
+ b=2;
+ rmask=0x1F<<11;
+ gmask=0x3F<<5;
+ bmask=0x1F;
+
+ if(specfilt == 3)
+ hq3x_InitLUTs();
+ else
+ hq2x_InitLUTs();
+
+ specbuf=malloc(256*240*sizeof(uint16));
+ }
+
+ silt = specfilt;
+
+ Bpp=b;
+
+ highefx=efx;
+
+ if(Bpp<=1 || Bpp>4)
+ return(0);
+
+ if(efx&FVB_BLUR)
+ {
+ if(Bpp==2)
+ palettetranslate=(uint32 *)malloc(65536*4);
+ else if(Bpp>=3)
+ palettetranslate=(uint32 *)malloc(65536*4);
+ }
+ else
+ {
+ if(Bpp==2)
+ palettetranslate=(uint32*)malloc(65536*4);
+ else if(Bpp>=3)
+ palettetranslate=(uint32*)malloc(256*4);
+ }
+
+ if(!palettetranslate)
+ return(0);
+
+
+ CBM[0]=rmask;
+ CBM[1]=gmask;
+ CBM[2]=bmask;
+ return(1);
+}
+
+void KillBlitToHigh(void)
+{
+ if(palettetranslate)
+ {
+ free(palettetranslate);
+ palettetranslate=NULL;
+ }
+
+ if(specbuf8bpp)
+ {
+ free(specbuf8bpp);
+ specbuf8bpp = NULL;
+ }
+ if(specbuf32bpp)
+ {
+ free(specbuf32bpp);
+ specbuf32bpp = NULL;
+ }
+ if(specbuf)
+ {
+ if(silt == 3)
+ hq3x_Kill();
+ else
+ hq2x_Kill();
+ specbuf=NULL;
+ }
+}
+
+
+void SetPaletteBlitToHigh(uint8 *src)
+{
+ int cshiftr[3];
+ int cshiftl[3];
+ int x,y;
+
+ CalculateShift(CBM, cshiftr, cshiftl);
+
+ switch(Bpp)
+ {
+ case 2:
+ if(highefx&FVB_BLUR)
+ {
+ for(x=0;x<256;x++)
+ {
+ uint32 r,g,b;
+ for(y=0;y<256;y++)
+ {
+ r=src[x<<2]*(100-BLUR_RED);
+ g=src[(x<<2)+1]*(100-BLUR_GREEN);
+ b=src[(x<<2)+2]*(100-BLUR_BLUE);
+
+ r+=src[y<<2]*BLUR_RED;
+ g+=src[(y<<2)+1]*BLUR_GREEN;
+ b+=src[(y<<2)+2]*BLUR_BLUE;
+ r/=100;
+ g/=100;
+ b/=100;
+
+ if(r>255) r=255; if(g>255) g=255; if(b>255) b=255;
+ palettetranslate[x|(y<<8)]=((r>>cshiftr[0])<<cshiftl[0])|
+ ((g>>cshiftr[1])<<cshiftl[1])|
+ ((b>>cshiftr[2])<<cshiftl[2]);
+ }
+ }
+ }
+ else
+ for(x=0;x<65536;x++)
+ {
+ uint16 lower,upper;
+
+ lower=(src[((x&255)<<2)]>>cshiftr[0])<<cshiftl[0];
+ lower|=(src[((x&255)<<2)+1]>>cshiftr[1])<<cshiftl[1];
+ lower|=(src[((x&255)<<2)+2]>>cshiftr[2])<<cshiftl[2];
+ upper=(src[((x>>8)<<2)]>>cshiftr[0])<<cshiftl[0];
+ upper|=(src[((x>>8)<<2)+1]>>cshiftr[1])<<cshiftl[1];
+ upper|=(src[((x>>8)<<2)+2]>>cshiftr[2])<<cshiftl[2];
+
+ palettetranslate[x]=lower|(upper<<16);
+ }
+ break;
+ case 3:
+ case 4:
+ for(x=0;x<256;x++)
+ {
+ uint32 r,g,b;
+
+ if(!(highefx&FVB_BLUR))
+ {
+ r=src[x<<2];
+ g=src[(x<<2)+1];
+ b=src[(x<<2)+2];
+ palettetranslate[x]=(r<<cshiftl[0])|(g<<cshiftl[1])|(b<<cshiftl[2]);
+ }
+ else
+ for(y=0;y<256;y++)
+ {
+ r=src[x<<2]*(100-BLUR_RED);
+ g=src[(x<<2)+1]*(100-BLUR_GREEN);
+ b=src[(x<<2)+2]*(100-BLUR_BLUE);
+
+ r+=src[y<<2]*BLUR_RED;
+ g+=src[(y<<2)+1]*BLUR_GREEN;
+ b+=src[(y<<2)+2]*BLUR_BLUE;
+
+ r/=100;
+ g/=100;
+ b/=100;
+ if(r>255) r=255; if(g>255) g=255; if(b>255) b=255;
+
+ palettetranslate[x|(y<<8)]=(r<<cshiftl[0])|(g<<cshiftl[1])|(b<<cshiftl[2]);
+ }
+ }
+ break;
+ }
+}
+
+static void Blit32to24(uint32 *src, uint8 *dest, int xr, int yr, int dpitch)
+{
+ int x,y;
+
+ for(y=yr;y;y--)
+ {
+ for(x=xr;x;x--)
+ {
+ uint32 tmp = *src;
+ *dest = tmp;
+ dest++;
+ *dest = tmp>>8;
+ dest++;
+ *dest = tmp>>16;
+ dest++;
+ src++;
+ }
+ dest += dpitch / 3 - xr;
+ }
+}
+
+
+static void Blit32to16(uint32 *src, uint16 *dest, int xr, int yr, int dpitch,
+ int shiftr[3], int shiftl[3])
+{
+ int x,y;
+ //printf("%d\n",shiftl[1]);
+ for(y=yr;y;y--)
+ {
+ for(x=xr;x;x--)
+ {
+ uint32 tmp = *src;
+ uint16 dtmp;
+
+ // Begin iffy code
+ //dtmp = (tmp & backmask[2]) >> shiftr[2];
+ //dtmp |= (tmp & backmask[1]) >> shiftr[1];
+ //dtmp |= (tmp & backmask[0]) >> shiftr[0];
+ // End iffy code
+
+ // Begin non-iffy code
+ dtmp = ((tmp&0x0000FF) >> shiftr[2]) << shiftl[2];
+ dtmp |= ((tmp&0x00FF00) >> shiftr[1]) << shiftl[1];
+ dtmp |= ((tmp&0xFF0000) >> shiftr[0]) << shiftl[0];
+ // End non-iffy code
+
+ //dtmp = ((tmp&0x0000FF) >> 3);
+ //dtmp |= ((tmp&0x00FC00) >>5);
+ //dtmp |= ((tmp&0xF80000) >>8);
+
+ *dest = dtmp;
+ src++;
+ dest++;
+ }
+ dest += dpitch / 2 - xr;
+ }
+}
+
+
+void Blit8To8(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale, int efx, int special)
+{
+ int x,y;
+ int pinc;
+
+ if(special==2)
+ {
+ if(xscale!=2 || yscale!=2) return;
+
+ scale(2,dest,pitch,src,256,1,xr,yr);
+ return;
+ }
+
+ if(special==4)
+ {
+ if(xscale!=3 || yscale!=3) return;
+ scale(3,dest,pitch,src,256,1,xr,yr);
+ return;
+ }
+
+ pinc=pitch-(xr*xscale);
+ if(xscale!=1 || yscale!=1)
+ {
+ if(efx&FVB_SCANLINES)
+ {
+ for(y=yr;y;y--,src+=256-xr)
+ {
+ int doo=yscale-(yscale>>1);
+ do
+ {
+ for(x=xr;x;x--,src++)
+ {
+ int too=xscale;
+ do
+ {
+ *(uint8 *)dest=*(uint8 *)src;
+ dest++;
+ } while(--too);
+ }
+ src-=xr;
+ dest+=pinc;
+ } while(--doo);
+ //src-=xr*(yscale-(yscale>>1));
+ dest+=pitch*(yscale>>1);
+
+ src+=xr;
+ }
+
+ }
+ else
+ {
+ for(y=yr;y;y--,src+=256-xr)
+ {
+ int doo=yscale;
+ do
+ {
+ for(x=xr;x;x--,src++)
+ {
+ int too=xscale;
+ do
+ {
+ *(uint8 *)dest=*(uint8 *)src;
+ dest++;
+ } while(--too);
+ }
+ src-=xr;
+ dest+=pinc;
+ } while(--doo);
+ src+=xr;
+ }
+ }
+
+ }
+ else
+ {
+ for(y=yr;y;y--,dest+=pinc,src+=256-xr)
+ for(x=xr;x;x-=4,dest+=4,src+=4)
+ *(uint32 *)dest=*(uint32 *)src;
+ }
+}
+
+/* Todo: Make sure 24bpp code works right with big-endian cpus */
+
+void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch,
+ int xscale, int yscale)
+{
+ int x,y;
+ int pinc;
+ uint8 *destbackup = NULL; /* For hq2x */
+ int pitchbackup = 0;
+
+ //static int google=0;
+ //google^=1;
+
+ if(specbuf8bpp) // 2xscale/3xscale
+ {
+ int mult;
+ int base;
+
+ if(silt == 2) mult = 2;
+ else mult = 3;
+
+ Blit8To8(src, specbuf8bpp, xr, yr, 256*mult, xscale, yscale, 0, silt);
+
+ xr *= mult;
+ yr *= mult;
+ xscale=yscale=1;
+ src = specbuf8bpp;
+ base = 256*mult;
+
+ switch(Bpp)
+ {
+ case 4:
+ pinc=pitch-(xr<<2);
+ for(y=yr;y;y--,src+=base-xr)
+ {
+ for(x=xr;x;x--)
+ {
+ *(uint32 *)dest=palettetranslate[(uint32)*src];
+ dest+=4;
+ src++;
+ }
+ dest+=pinc;
+ }
+ break;
+ case 3:
+ pinc=pitch-(xr+xr+xr);
+ for(y=yr;y;y--,src+=base-xr)
+ {
+ for(x=xr;x;x--)
+ {
+ uint32 tmp=palettetranslate[(uint32)*src];
+ *(uint8 *)dest=tmp;
+ *((uint8 *)dest+1)=tmp>>8;
+ *((uint8 *)dest+2)=tmp>>16;
+ dest+=3;
+ src++;
+ src++;
+ }
+ dest+=pinc;
+ }
+ break;
+ case 2:
+ pinc=pitch-(xr<<1);
+
+ for(y=yr;y;y--,src+=base-xr)
+ {
+ for(x=xr>>1;x;x--)
+ {
+ *(uint32 *)dest=palettetranslate[*(uint16 *)src];
+ dest+=4;
+ src+=2;
+ }
+ dest+=pinc;
+ }
+ break;
+ }
+ return;
+ }
+ else if(specbuf)
+ {
+ destbackup=dest;
+ dest=(uint8 *)specbuf;
+ pitchbackup=pitch;
+
+ pitch=xr*sizeof(uint16);
+ xscale=1;
+ yscale=1;
+ }
+
+ if(highefx&FVB_BLUR) // DONE
+ {
+ if(xscale!=1 || yscale!=1 || (highefx&FVB_SCANLINES)) // DONE
+ {
+ switch(Bpp)
+ {
+ case 4:
+ pinc=pitch-((xr*xscale)<<2);
+ for(y=yr;y;y--,src+=256-xr)
+ {
+ int doo=yscale;
+
+ if(highefx&FVB_SCANLINES)
+ doo-=yscale>>1;
+ do
+ {
+ uint8 last=0x00;
+
+ //if(doo == 1 && google) dest+=4;
+ for(x=xr;x;x--,src++)
+ {
+ int too=xscale;
+ do
+ {
+ *(uint32 *)dest=palettetranslate[*src|(last<<8)];
+ dest+=4;
+ } while(--too);
+ last=*src;
+ }
+ //if(doo == 1 && google) dest-=4;
+ src-=xr;
+ dest+=pinc;
+ } while(--doo);
+ src+=xr;
+ if(highefx&FVB_SCANLINES)
+ dest+=pitch*(yscale>>1);
+ }
+ break;
+ case 3:
+ pinc=pitch-((xr*xscale)*3);
+ for(y=yr;y;y--,src+=256-xr)
+ {
+ int doo=yscale;
+
+ if(highefx&FVB_SCANLINES)
+ doo-=yscale>>1;
+ do
+ {
+ uint8 last=0x00;
+ for(x=xr;x;x--,src++)
+ {
+ int too=xscale;
+ do
+ {
+ *(uint32 *)dest=palettetranslate[*src|(last<<8)];
+ dest+=3;
+ } while(--too);
+ last=*src;
+ }
+ src-=xr;
+ dest+=pinc;
+ } while(--doo);
+ src+=xr;
+ if(highefx&FVB_SCANLINES)
+ dest+=pitch*(yscale>>1);
+ }
+ break;
+
+ case 2:
+ pinc=pitch-((xr*xscale)<<1);
+
+ for(y=yr;y;y--,src+=256-xr)
+ {
+ int doo=yscale;
+
+ if(highefx& FVB_SCANLINES)
+ doo-=yscale>>1;
+ do
+ {
+ uint8 last=0x00;
+ for(x=xr;x;x--,src++)
+ {
+ int too=xscale;
+ do
+ {
+ *(uint16 *)dest=palettetranslate[*src|(last<<8)];
+ dest+=2;
+ } while(--too);
+ last=*src;
+ }
+ src-=xr;
+ dest+=pinc;
+ } while(--doo);
+ src+=xr;
+ if(highefx&FVB_SCANLINES)
+ dest+=pitch*(yscale>>1);
+ }
+ break;
+ }
+ }
+ else // No scaling, no scanlines, just blurring. - DONE
+ switch(Bpp)
+ {
+ case 4:
+ pinc=pitch-(xr<<2);
+ for(y=yr;y;y--,src+=256-xr)
+ {
+ uint8 last=0x00;
+ for(x=xr;x;x--)
+ {
+ *(uint32 *)dest=palettetranslate[*src|(last<<8)];
+ last=*src;
+ dest+=4;
+ src++;
+ }
+ dest+=pinc;
+ }
+ break;
+ case 3:
+ pinc=pitch-(xr+xr+xr);
+ for(y=yr;y;y--,src+=256-xr)
+ {
+ uint8 last=0x00;
+ for(x=xr;x;x--)
+ {
+ uint32 tmp=palettetranslate[*src|(last<<8)];
+ last=*src;
+ *(uint8 *)dest=tmp;
+ *((uint8 *)dest+1)=tmp>>8;
+ *((uint8 *)dest+2)=tmp>>16;
+ dest+=3;
+ src++;
+ }
+ dest+=pinc;
+ }
+ break;
+ case 2:
+ pinc=pitch-(xr<<1);
+ for(y=yr;y;y--,src+=256-xr)
+ {
+ uint8 last=0x00;
+ for(x=xr;x;x--)
+ {
+ *(uint16 *)dest=palettetranslate[*src|(last<<8)];
+ last=*src;
+ dest+=2;
+ src++;
+ }
+ dest+=pinc;
+ }
+ break;
+ }
+ }
+ else // No blur effects.
+ {
+ if(xscale!=1 || yscale!=1 || (highefx&FVB_SCANLINES))
+ {
+ switch(Bpp)
+ {
+ case 4:
+ pinc=pitch-((xr*xscale)<<2);
+ for(y=yr;y;y--,src+=256-xr)
+ {
+ int doo=yscale;
+
+ if(highefx& FVB_SCANLINES)
+ doo-=yscale>>1;
+ do
+ {
+ for(x=xr;x;x--,src++)
+ {
+ int too=xscale;
+ do
+ {
+ *(uint32 *)dest=palettetranslate[*src];
+ dest+=4;
+ } while(--too);
+ }
+ src-=xr;
+ dest+=pinc;
+ } while(--doo);
+ src+=xr;
+ if(highefx&FVB_SCANLINES)
+ dest+=pitch*(yscale>>1);
+ }
+ break;
+
+ case 3:
+ pinc=pitch-((xr*xscale)*3);
+ for(y=yr;y;y--,src+=256-xr)
+ {
+ int doo=yscale;
+
+ if(highefx& FVB_SCANLINES)
+ doo-=yscale>>1;
+ do
+ {
+ for(x=xr;x;x--,src++)
+ {
+ int too=xscale;
+ do
+ {
+ uint32 tmp=palettetranslate[(uint32)*src];
+ *(uint8 *)dest=tmp;
+ *((uint8 *)dest+1)=tmp>>8;
+ *((uint8 *)dest+2)=tmp>>16;
+ dest+=3;
+
+ //*(uint32 *)dest=palettetranslate[*src];
+ //dest+=4;
+ } while(--too);
+ }
+ src-=xr;
+ dest+=pinc;
+ } while(--doo);
+ src+=xr;
+ if(highefx&FVB_SCANLINES)
+ dest+=pitch*(yscale>>1);
+ }
+ break;
+
+ case 2:
+ pinc=pitch-((xr*xscale)<<1);
+
+ for(y=yr;y;y--,src+=256-xr)
+ {
+ int doo=yscale;
+
+ if(highefx& FVB_SCANLINES)
+ doo-=yscale>>1;
+ do
+ {
+ for(x=xr;x;x--,src++)
+ {
+ int too=xscale;
+ do
+ {
+ *(uint16 *)dest=palettetranslate[*src];
+ dest+=2;
+ } while(--too);
+ }
+ src-=xr;
+ dest+=pinc;
+ } while(--doo);
+ src+=xr;
+ if(highefx&FVB_SCANLINES)
+ dest+=pitch*(yscale>>1);
+ }
+ break;
+ }
+ }
+ else
+ switch(Bpp)
+ {
+ case 4:
+ pinc=pitch-(xr<<2);
+ for(y=yr;y;y--,src+=256-xr)
+ {
+ for(x=xr;x;x--)
+ {
+ *(uint32 *)dest=palettetranslate[(uint32)*src];
+ dest+=4;
+ src++;
+ }
+ dest+=pinc;
+ }
+ break;
+ case 3:
+ pinc=pitch-(xr+xr+xr);
+ for(y=yr;y;y--,src+=256-xr)
+ {
+ for(x=xr;x;x--)
+ {
+ uint32 tmp=palettetranslate[(uint32)*src];
+ *(uint8 *)dest=tmp;
+ *((uint8 *)dest+1)=tmp>>8;
+ *((uint8 *)dest+2)=tmp>>16;
+ dest+=3;
+ src++;
+ }
+ dest+=pinc;
+ }
+ break;
+ case 2:
+ pinc=pitch-(xr<<1);
+
+ for(y=yr;y;y--,src+=256-xr)
+ {
+ for(x=xr>>1;x;x--)
+ {
+ *(uint32 *)dest=palettetranslate[*(uint16 *)src];
+ dest+=4;
+ src+=2;
+ }
+ dest+=pinc;
+ }
+ break;
+ }
+ }
+
+ if(specbuf)
+ {
+ if(specbuf32bpp)
+ {
+ int mult = (silt == 3)?3:2;
+
+ if(silt == 3)
+ hq3x_32((uint8 *)specbuf,(uint8*)specbuf32bpp,xr,yr,xr*3*sizeof(uint32));
+ else
+ hq2x_32((uint8 *)specbuf,(uint8*)specbuf32bpp,xr,yr,xr*2*sizeof(uint32));
+
+ if(backBpp == 2)
+ Blit32to16(specbuf32bpp, (uint16*)destbackup, xr*mult, yr*mult, pitchbackup, backshiftr,backshiftl);
+ else // == 3
+ Blit32to24(specbuf32bpp, (uint8*)destbackup, xr*mult, yr*mult, pitchbackup);
+ }
+ else
+ {
+ if(silt == 3)
+ hq3x_32((uint8 *)specbuf,destbackup,xr,yr,pitchbackup);
+ else
+ hq2x_32((uint8 *)specbuf,destbackup,xr,yr,pitchbackup);
+ }
+ }
+}
diff --git a/drivers/common/vidblit.h b/drivers/common/vidblit.h
new file mode 100644
index 00000000..1fc05a5b
--- /dev/null
+++ b/drivers/common/vidblit.h
@@ -0,0 +1,25 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+int InitBlitToHigh(int b, uint32 rmask, uint32 gmask, uint32 bmask, int eefx, int specfilt);
+void SetPaletteBlitToHigh(uint8 *src);
+void KillBlitToHigh(void);
+void Blit8ToHigh(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale);
+void Blit8To8(uint8 *src, uint8 *dest, int xr, int yr, int pitch, int xscale, int yscale, int efx, int special);
diff --git a/drivers/pc/dface.h b/drivers/pc/dface.h
new file mode 100644
index 00000000..9981bd08
--- /dev/null
+++ b/drivers/pc/dface.h
@@ -0,0 +1,72 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "../common/args.h"
+#include "../common/config.h"
+
+#include "input.h"
+
+extern FCEUGI *CurGame;
+
+extern CFGSTRUCT DriverConfig[];
+extern ARGPSTRUCT DriverArgs[];
+extern char *DriverUsage;
+
+void DoDriverArgs(void);
+uint8 *GetBaseDirectory(void);
+
+int InitSound(FCEUGI *gi);
+void WriteSound(int32 *Buffer, int Count);
+int KillSound(void);
+uint32 GetMaxSound(void);
+uint32 GetWriteSound(void);
+
+void SilenceSound(int s); /* DOS and SDL */
+
+
+int InitMouse(void);
+void KillMouse(void);
+void GetMouseData(uint32 *MouseData);
+
+int InitJoysticks(void);
+int KillJoysticks(void);
+uint32 *GetJSOr(void);
+
+int InitKeyboard(void);
+int UpdateKeyboard(void);
+char *GetKeyboard(void);
+void KillKeyboard(void);
+
+int InitVideo(FCEUGI *gi);
+int KillVideo(void);
+void BlitScreen(uint8 *XBuf);
+void LockConsole(void);
+void UnlockConsole(void);
+void ToggleFS(); /* SDL */
+
+int LoadGame(const char *path);
+int CloseGame(void);
+int GUI_Init(int argc, char **argv, int (*dofunc)(void));
+int GUI_Idle(void);
+int GUI_Update(void);
+void GUI_Hide(int);
+void GUI_RequestExit(void);
+int GUI_SetVideo(int fullscreen, int width, int height);
+char *GUI_GetKeyboard(void);
+void GUI_GetMouseState(uint32 *b, int *x, int *y);
+
+void UpdatePhysicalInput(void);
+int DTestButton(ButtConfig *bc);
+int DWaitButton(const uint8 *text, ButtConfig *bc, int wb);
+int ButtonConfigBegin(void);
+void ButtonConfigEnd(void);
+
+void Giggles(int);
+void DoFun(void);
+
+int FCEUD_NetworkConnect(void);
+#ifdef __cplusplus
+}
+#endif
+
+
diff --git a/drivers/pc/dos-joystick.c b/drivers/pc/dos-joystick.c
new file mode 100644
index 00000000..05e18177
--- /dev/null
+++ b/drivers/pc/dos-joystick.c
@@ -0,0 +1,200 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <dpmi.h>
+#include <sys/farptr.h>
+#include <go32.h>
+#include <pc.h>
+
+#include "dos.h"
+#include "dos-joystick.h"
+
+#define JOY_A 1
+#define JOY_B 2
+#define JOY_SELECT 4
+#define JOY_START 8
+#define JOY_UP 0x10
+#define JOY_DOWN 0x20
+#define JOY_LEFT 0x40
+#define JOY_RIGHT 0x80
+
+int joy=0;
+int joyBMap[6];
+
+static int32 joybuttons=0;
+static uint32 joyx=0;
+static uint32 joyy=0;
+static uint32 joyxcenter;
+static uint32 joyycenter;
+
+static void ConfigJoystick(void);
+volatile int soundjoyer=0;
+volatile int soundjoyeron=0;
+
+/* Crude method to detect joystick. */
+static int DetectJoystick(void)
+{
+ uint8 b;
+
+ outportb(0x201,0);
+ b=inportb(0x201);
+ sleep(1);
+ if((inportb(0x201)&3)==(b&3))
+ return 0;
+ else
+ return 1;
+}
+
+void UpdateJoyData(void)
+{
+ uint32 xc,yc;
+
+
+ joybuttons=((inportb(0x201)&0xF0)^0xF0)>>4;
+
+ xc=yc=0;
+
+ {
+ outportb(0x201,0);
+
+ for(;;)
+ {
+ uint8 b;
+
+ b=inportb(0x201);
+ if(!(b&3))
+ break;
+ if(b&1) xc++;
+ if(b&2) yc++;
+ }
+ }
+
+ joyx=xc;
+ joyy=yc;
+}
+
+uint32 GetJSOr(void)
+{
+ int y;
+ unsigned long ret;
+ static int rtoggle=0;
+ ret=0;
+
+ rtoggle^=1;
+ if(!soundo)
+ UpdateJoyData();
+ for(y=0;y<6;y++)
+ if((y>=4 && rtoggle) || y<4)
+ if(joybuttons&joyBMap[y]) ret|=(1<<y&3)<<((joy-1)<<3);
+
+ if(joyx<=joyxcenter*.25) ret|=JOY_LEFT<<((joy-1)<<3);
+ else if(joyx>=joyxcenter*1.75) ret|=JOY_RIGHT<<((joy-1)<<3);
+ if(joyy<=joyycenter*.25) ret|=JOY_UP<<((joy-1)<<3);
+ else if(joyy>=joyycenter*1.75) ret|=JOY_DOWN<<((joy-1)<<3);
+
+ return ret;
+}
+
+int InitJoysticks(void)
+{
+ if(!joy) return(0);
+ if(!DetectJoystick())
+ {
+ printf("Joystick not detected!\n");
+ joy=0;
+ return 0;
+ }
+ if(soundo)
+ {
+ soundjoyeron=1;
+ while(!soundjoyer);
+ }
+ else
+ UpdateJoyData();
+
+ joyxcenter=joyx;
+ joyycenter=joyy;
+
+ if(!(joyBMap[0]|joyBMap[1]|joyBMap[2]|joyBMap[3]))
+ ConfigJoystick();
+ return(1);
+}
+
+static void BConfig(int b)
+{
+ int c=0;
+ uint32 st=time(0);
+
+ while(time(0)< (st+4) )
+ {
+ if(!soundo)
+ UpdateJoyData();
+ if(joybuttons) c=joybuttons;
+ else if(c && !joybuttons)
+ {
+ joyBMap[b]=c;
+ break;
+ }
+
+ }
+}
+
+void KillJoysticks(void)
+{
+
+}
+
+static void ConfigJoystick(void)
+{
+ static char *genb="** Press button for ";
+
+ printf("\n\n Joystick button configuration:\n\n");
+ printf(" Push and release the button to map to the virtual joystick.\n");
+ printf(" If you do not wish to assign a button, wait a few seconds\n");
+ printf(" and the configuration will continue.\n\n");
+ printf(" Press enter to continue...\n");
+ getchar();
+
+ printf("%s\"Select\".\n",genb);
+ BConfig(2);
+
+ printf("%s\"Start\".\n",genb);
+ BConfig(3);
+
+ printf("%s\"B\".\n",genb);
+ BConfig(1);
+
+ printf("%s\"A\".\n",genb);
+ BConfig(0);
+
+ printf("%s\"Rapid fire B\".\n",genb);
+ BConfig(5);
+
+ printf("%s\"Rapid fire A\".\n",genb);
+ BConfig(4);
+
+}
+
diff --git a/drivers/pc/dos-joystick.h b/drivers/pc/dos-joystick.h
new file mode 100644
index 00000000..8c50c6b2
--- /dev/null
+++ b/drivers/pc/dos-joystick.h
@@ -0,0 +1,27 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+void UpdateJoyData(void);
+uint32 GetJSOr(void);
+int InitJoysticks(void);
+
+/* Variables to save in config file. */
+extern int joy;
+extern int joyBMap[6];
diff --git a/drivers/pc/dos-keyboard.c b/drivers/pc/dos-keyboard.c
new file mode 100644
index 00000000..b5926c3c
--- /dev/null
+++ b/drivers/pc/dos-keyboard.c
@@ -0,0 +1,131 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <signal.h>
+#include <string.h>
+#include <pc.h>
+#include <dpmi.h>
+#include <go32.h>
+#include "keyscan.h"
+
+static unsigned char lastsc;
+static char keybuf[256];
+int newk;
+
+/* Read scan code from port $60 */
+/* Acknowledge interrupt( output $20 to port $20) */
+
+static void ihandler(_go32_dpmi_registers *r)
+{
+ unsigned char scode=inp(0x60); /* Get scan code. */
+
+
+ if(scode!=0xE0)
+ {
+ int offs=0;
+
+ /* I'm only interested in preserving the independent status of the
+ right ALT and CONTROL keys.
+ */
+ if(lastsc==0xE0)
+ if((scode&0x7F)==SCAN_LEFTALT || (scode&0x7F)==SCAN_LEFTCONTROL)
+ offs=0x80;
+
+
+ keybuf[(scode&0x7f)|offs]=((scode&0x80)^0x80);
+ newk++;
+ }
+ lastsc=scode;
+
+ outp(0x20,0x20); /* Acknowledge interrupt. */
+}
+
+static _go32_dpmi_seginfo KBIBack,KBIBackRM;
+static _go32_dpmi_seginfo KBI,KBIRM;
+static _go32_dpmi_registers KBIRMRegs;
+static int initdone=0;
+
+int InitKeyboard(void)
+{
+ /* I'll assume that the keyboard is in the correct scancode mode(translated
+ mode 2, I think).
+ */
+ newk=0;
+ memset(keybuf,0,sizeof(keybuf));
+ KBIRM.pm_offset=KBI.pm_offset=(int)ihandler;
+ KBIRM.pm_selector=KBI.pm_selector=_my_cs();
+
+ _go32_dpmi_get_real_mode_interrupt_vector(9,&KBIBackRM);
+ _go32_dpmi_allocate_real_mode_callback_iret(&KBIRM, &KBIRMRegs);
+ _go32_dpmi_set_real_mode_interrupt_vector(9,&KBIRM);
+
+ _go32_dpmi_get_protected_mode_interrupt_vector(9,&KBIBack);
+ _go32_dpmi_allocate_iret_wrapper(&KBI);
+ _go32_dpmi_set_protected_mode_interrupt_vector(9,&KBI);
+ lastsc=0;
+ initdone=1;
+ return(1);
+}
+
+void KillKeyboard(void)
+{
+ if(initdone)
+ {
+ _go32_dpmi_set_protected_mode_interrupt_vector(9,&KBIBack);
+ _go32_dpmi_free_iret_wrapper(&KBI);
+
+ _go32_dpmi_set_real_mode_interrupt_vector(9,&KBIBackRM);
+ _go32_dpmi_free_real_mode_callback(&KBIRM);
+ initdone=0;
+ }
+}
+
+/* In FCE Ultra, it doesn't matter if the key states change
+ in the middle of the keyboard handling code. If you want
+ to use this code elsewhere, you may want to memcpy() keybuf
+ to another buffer and return that when GetKeyboard() is
+ called.
+*/
+
+char *GetKeyboard(void)
+{
+ return keybuf;
+}
+
+/* Returns 1 on new scan codes generated, 0 on no new scan codes. */
+int UpdateKeyboard(void)
+{
+ int t=newk;
+
+ if(t)
+ {
+ asm volatile(
+ "subl %%eax,_newk\n\t"
+ :
+ : "a" (t)
+ );
+
+ if(keybuf[SCAN_LEFTCONTROL] && keybuf[SCAN_C])
+ raise(SIGINT);
+ return(1);
+ }
+ return(0);
+}
diff --git a/drivers/pc/dos-mouse.c b/drivers/pc/dos-mouse.c
new file mode 100644
index 00000000..3e0d1142
--- /dev/null
+++ b/drivers/pc/dos-mouse.c
@@ -0,0 +1,80 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <dpmi.h>
+#include <string.h>
+
+#include "dos.h"
+
+int InitMouse(void)
+{
+ __dpmi_regs regs;
+
+ memset(&regs,0,sizeof(regs));
+ regs.x.ax=0;
+ __dpmi_int(0x33,&regs);
+ if(regs.x.ax!=0xFFFF)
+ return(0);
+
+ memset(&regs,0,sizeof(regs));
+ regs.x.ax=0x7;
+ regs.x.cx=0; // Min X
+ regs.x.dx=260; // Max X
+ __dpmi_int(0x33,&regs);
+
+ memset(&regs,0,sizeof(regs));
+ regs.x.ax=0x8;
+ regs.x.cx=0; // Min Y
+ regs.x.dx=260; // Max Y
+ __dpmi_int(0x33,&regs);
+
+ memset(&regs,0,sizeof(regs));
+ regs.x.ax=0xF;
+ regs.x.cx=8; // Mickey X
+ regs.x.dx=8; // Mickey Y
+ __dpmi_int(0x33,&regs);
+
+ memset(&regs,0,sizeof(regs));
+ regs.x.ax=0x2;
+ __dpmi_int(0x33,&regs);
+
+ return(1);
+}
+
+uint32 GetMouseData(uint32 *x, uint32 *y)
+{
+ if(FCEUI_IsMovieActive()<0)
+ return;
+
+ __dpmi_regs regs;
+
+ memset(&regs,0,sizeof(regs));
+ regs.x.ax=0x3;
+ __dpmi_int(0x33,&regs);
+
+ *x=regs.x.cx;
+ *y=regs.x.dx;
+ return(regs.x.bx&3);
+}
+
+void KillMouse(void)
+{
+
+}
diff --git a/drivers/pc/dos-sound.c b/drivers/pc/dos-sound.c
new file mode 100644
index 00000000..e1a21fc1
--- /dev/null
+++ b/drivers/pc/dos-sound.c
@@ -0,0 +1,567 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/farptr.h>
+#include <pc.h>
+#include <dos.h>
+#include <dpmi.h>
+#include <go32.h>
+#include <ctype.h>
+
+#include "dos.h"
+#include "dos-sound.h"
+#include "dos-joystick.h"
+
+
+static void SBIRQHandler(_go32_dpmi_registers *r);
+static uint32 LMBuffer; /* Address of low memory DMA playback buffer. */
+static int LMSelector;
+
+static uint8 *WaveBuffer;
+static unsigned int IVector, SBIRQ, SBDMA, SBDMA16, SBPort;
+static int DSPV,hsmode;
+static int format;
+static int frags, fragsize, fragtotal;
+static volatile int WritePtr, ReadPtr;
+static volatile int hbusy;
+static volatile int whichbuf;
+
+
+static uint8 PICMask;
+/* Protected mode interrupt vector info. */
+static _go32_dpmi_seginfo SBIH,SBIHOld;
+
+/* Real mode interrupt vector info. */
+static _go32_dpmi_seginfo SBIHRM,SBIHRMOld;
+static _go32_dpmi_registers SBIHRMRegs;
+
+static int WriteDSP(uint8 V)
+{
+ int x;
+
+ for(x=65536;x;x--)
+ {
+ if(!(inportb(SBPort+0xC)&0x80))
+ {
+ outportb(SBPort+0xC,V);
+ return(1);
+ }
+ }
+ return(0);
+}
+
+static int ReadDSP(uint8 *V)
+{
+ int x;
+
+ for(x=65536;x;x--) /* Should be more than enough time... */
+ {
+ if(inportb(SBPort+0xE)&0x80)
+ {
+ *V=inportb(SBPort+0xA);
+ return(1);
+ }
+ }
+ return(0);
+}
+
+
+static int SetVectors(void)
+{
+ SBIH.pm_offset=SBIHRM.pm_offset=(int)SBIRQHandler;
+ SBIH.pm_selector=SBIHRM.pm_selector=_my_cs();
+
+ /* Get and set real mode interrupt vector. */
+ _go32_dpmi_get_real_mode_interrupt_vector(IVector,&SBIHRMOld);
+ _go32_dpmi_allocate_real_mode_callback_iret(&SBIHRM, &SBIHRMRegs);
+ _go32_dpmi_set_real_mode_interrupt_vector(IVector,&SBIHRM);
+
+ /* Get and set protected mode interrupt vector. */
+ _go32_dpmi_get_protected_mode_interrupt_vector(IVector,&SBIHOld);
+ _go32_dpmi_allocate_iret_wrapper(&SBIH);
+ _go32_dpmi_set_protected_mode_interrupt_vector(IVector,&SBIH);
+
+ return(1);
+}
+
+static void ResetVectors(void)
+{
+ _go32_dpmi_set_protected_mode_interrupt_vector(IVector,&SBIHOld);
+ _go32_dpmi_free_iret_wrapper(&SBIH);
+ _go32_dpmi_set_real_mode_interrupt_vector(IVector,&SBIHRMOld);
+ _go32_dpmi_free_real_mode_callback(&SBIHRM);
+}
+
+int GetBLASTER(void)
+{
+ int check=0;
+ char *s;
+
+ if(!(s=getenv("BLASTER")))
+ {
+ puts(" Error getting BLASTER environment variable.");
+ return(0);
+ }
+
+ while(*s)
+ {
+ switch(toupper(*s))
+ {
+ case 'A': check|=(sscanf(s+1,"%x",&SBPort)==1)?1:0;break;
+ case 'I': check|=(sscanf(s+1,"%d",&SBIRQ)==1)?2:0;break;
+ case 'D': check|=(sscanf(s+1,"%d",&SBDMA)==1)?4:0;break;
+ case 'H': check|=(sscanf(s+1,"%d",&SBDMA16)==1)?8:0;break;
+ }
+ s++;
+ }
+
+ if((check^7)&7 || SBDMA>=4 || (SBDMA16<=4 && check&8) || SBIRQ>15)
+ {
+ puts(" Invalid or incomplete BLASTER environment variable.");
+ return(0);
+ }
+ if(!(check&8))
+ format=0;
+ return(1);
+}
+
+static int ResetDSP(void)
+{
+ uint8 b;
+
+ outportb(SBPort+0x6,0x1);
+ delay(10);
+ outportb(SBPort+0x6,0x0);
+ delay(10);
+
+ if(ReadDSP(&b))
+ if(b==0xAA)
+ return(1);
+ return(0);
+}
+
+static int GetDSPVersion(void)
+{
+ int ret;
+ uint8 t;
+
+ if(!WriteDSP(0xE1))
+ return(0);
+ if(!ReadDSP(&t))
+ return(0);
+ ret=t<<8;
+ if(!ReadDSP(&t))
+ return(0);
+ ret|=t;
+
+ return(ret);
+}
+
+static void KillDMABuffer(void)
+{
+ __dpmi_free_dos_memory(LMSelector);
+}
+
+static int MakeDMABuffer(void)
+{
+ uint32 size;
+ int32 tmp;
+
+ size=fragsize*2; /* Two buffers in the DMA buffer. */
+ size<<=format; /* Twice the size for 16-bit than for 8-bit. */
+
+ size<<=1; /* Double the size in case the first 2 buffers
+ cross a 64KB or 128KB page boundary.
+ */
+ size=(size+15)>>4; /* Convert to paragraphs */
+
+ if((tmp=__dpmi_allocate_dos_memory(size,&LMSelector))<0)
+ return(0);
+
+ LMBuffer=tmp<<=4;
+
+ if(format) /* Check for and fix 128KB page boundary crossing. */
+ {
+ if((LMBuffer&0x20000) != ((LMBuffer+fragsize*2*2-1)&0x20000))
+ LMBuffer+=fragsize*2*2;
+ }
+ else /* Check for and fix 64KB page boundary crossing. */
+ {
+ if((LMBuffer&0x10000) != ((LMBuffer+fragsize*2-1)&0x10000))
+ LMBuffer+=fragsize*2;
+ }
+
+ DOSMemSet(LMBuffer, format?0:128, (fragsize*2)<<format);
+
+ return(1);
+}
+
+static void ProgramDMA(void)
+{
+ static int PPorts[8]={0x87,0x83,0x81,0x82,0,0x8b,0x89,0x8a};
+ uint32 tmp;
+
+ if(format)
+ {
+ outportb(0xd4,(SBDMA16&0x3)|0x4);
+ outportb(0xd8,0x0);
+ outportb(0xd6,(SBDMA16&0x3)|0x58);
+ tmp=((SBDMA16&3)<<2)+0xC2;
+ }
+ else
+ {
+ outportb(0xA,SBDMA|0x4);
+ outportb(0xC,0x0);
+ outportb(0xB,SBDMA|0x58);
+ tmp=(SBDMA<<1)+1;
+ }
+
+ /* Size of entire buffer. */
+ outportb(tmp,(fragsize*2-1));
+ outportb(tmp,(fragsize*2-1)>>8);
+
+ /* Page of buffer. */
+ outportb(PPorts[format?SBDMA16:SBDMA],LMBuffer>>16);
+
+ /* Offset of buffer within page. */
+ if(format)
+ tmp=((SBDMA16&3)<<2)+0xc0;
+ else
+ tmp=SBDMA<<1;
+
+ outportb(tmp,(LMBuffer>>format));
+ outportb(tmp,(LMBuffer>>(8+format)));
+}
+
+int InitSB(int Rate, int bittage)
+{
+ hsmode=hbusy=0;
+ whichbuf=1;
+ puts("Initializing Sound Blaster...");
+
+ format=bittage?1:0;
+ frags=8;
+
+ if(Rate<=11025)
+ fragsize=1<<5;
+ else if(Rate<=22050)
+ fragsize=1<<6;
+ else
+ fragsize=1<<7;
+
+ fragtotal=frags*fragsize;
+ WaveBuffer=malloc(fragtotal<<format);
+
+ if(format)
+ memset(WaveBuffer,0,fragtotal*2);
+ else
+ memset(WaveBuffer,128,fragtotal);
+
+ WritePtr=ReadPtr=0;
+
+ if((Rate<8192) || (Rate>65535))
+ {
+ printf(" Unsupported playback rate: %d samples per second\n",Rate);
+ return(0);
+ }
+
+ if(!GetBLASTER())
+ return(0);
+
+ /* Disable IRQ line in PIC0 or PIC1 */
+ if(SBIRQ>7)
+ {
+ PICMask=inportb(0xA1);
+ outportb(0xA1,PICMask|(1<<(SBIRQ&7)));
+ }
+ else
+ {
+ PICMask=inportb(0x21);
+ outportb(0x21,PICMask|(1<<SBIRQ));
+ }
+ if(!ResetDSP())
+ {
+ puts(" Error resetting the DSP.");
+ return(0);
+ }
+
+ if(!(DSPV=GetDSPVersion()))
+ {
+ puts(" Error getting the DSP version.");
+ return(0);
+ }
+
+ printf(" DSP Version: %d.%d\n",DSPV>>8,DSPV&0xFF);
+ if(DSPV<0x201)
+ {
+ printf(" DSP version number is too low.\n");
+ return(0);
+ }
+
+ if(DSPV<0x400)
+ format=0;
+ if(!MakeDMABuffer())
+ {
+ puts(" Error creating low-memory DMA buffer.");
+ return(0);
+ }
+
+ if(SBIRQ>7) IVector=SBIRQ+0x68;
+ else IVector=SBIRQ+0x8;
+
+ if(!SetVectors())
+ {
+ puts(" Error setting interrupt vectors.");
+ KillDMABuffer();
+ return(0);
+ }
+
+ /* Reenable IRQ line. */
+ if(SBIRQ>7)
+ outportb(0xA1,PICMask&(~(1<<(SBIRQ&7))));
+ else
+ outportb(0x21,PICMask&(~(1<<SBIRQ)));
+
+ ProgramDMA();
+
+ /* Note that the speaker must always be turned on before the mode transfer
+ byte is sent to the DSP if we're going into high-speed mode, since
+ a real Sound Blaster(at least my SBPro) won't accept DSP commands(except
+ for the reset "command") after it goes into high-speed mode.
+ */
+ WriteDSP(0xD1); // Turn on DAC speaker
+
+ if(DSPV>=0x400)
+ {
+ WriteDSP(0x41); // Set sampling rate
+ WriteDSP(Rate>>8); // High byte
+ WriteDSP(Rate&0xFF); // Low byte
+ if(!format)
+ {
+ WriteDSP(0xC6); // 8-bit output
+ WriteDSP(0x00); // 8-bit mono unsigned PCM
+ }
+ else
+ {
+ WriteDSP(0xB6); // 16-bit output
+ WriteDSP(0x10); // 16-bit mono signed PCM
+ }
+ WriteDSP((fragsize-1)&0xFF);// Low byte of size
+ WriteDSP((fragsize-1)>>8); // High byte of size
+ }
+ else
+ {
+ int tc,command;
+ if(Rate>22050)
+ {
+ tc=(65536-(256000000/Rate))>>8;
+ Rate=256000000/(65536-(tc<<8));
+ command=0x90; // High-speed auto-initialize DMA mode transfer
+ hsmode=1;
+ }
+ else
+ {
+ tc=256-(1000000/Rate);
+ Rate=1000000/(256-tc);
+ command=0x1c; // Auto-initialize DMA mode transfer
+ }
+ WriteDSP(0x40); // Set DSP time constant
+ WriteDSP(tc); // time constant
+ WriteDSP(0x48); // Set DSP block transfer size
+ WriteDSP((fragsize-1)&0xFF);
+ WriteDSP((fragsize-1)>>8);
+
+ WriteDSP(command);
+ }
+
+ /* Enable DMA */
+ if(format)
+ outportb(0xd4,SBDMA16&3);
+ else
+ outportb(0xa,SBDMA);
+
+ printf(" %d hz, %d-bit\n",Rate,8<<format);
+ return(Rate);
+}
+
+extern volatile int soundjoyer;
+extern volatile int soundjoyeron;
+static int ssilence=0;
+
+static void SBIRQHandler(_go32_dpmi_registers *r)
+{
+ uint32 *src;
+ uint32 dest;
+ int32 x;
+
+
+ if(format)
+ {
+ uint8 status;
+
+ outportb(SBPort+4,0x82);
+ status=inportb(SBPort+5);
+ if(status&2)
+ inportb(SBPort+0x0F);
+ }
+ else
+ inportb(SBPort+0x0E);
+
+ #ifdef OLD
+ {
+ uint8 status;
+
+ outportb(SBPort+4,0x82);
+ status=inportb(SBPort+5);
+ if(status&1)
+ inportb(SBPort+0x0E);
+ else if(status&2)
+ inportb(SBPort+0x0F);
+ else
+ return; // Mysterious interrupt source! *eerie music*
+ }
+ #endif
+
+ if(hbusy)
+ {
+ outportb(0x20,0x20);
+ if(SBIRQ>=8)
+ outportb(0xA0,0x20);
+ whichbuf^=1;
+ return;
+ }
+ hbusy=1;
+
+ {
+ /* This code seems to fail on many SB emulators. Bah.
+ SCREW SB EMULATORS. ^_^ */
+ uint32 count;
+ uint32 block;
+ uint32 port;
+
+ if(format)
+ port=((SBDMA16&3)*4)+0xc2;
+ else
+ port=(SBDMA*2)+1;
+
+ count=inportb(port);
+ count|=inportb(port)<<8;
+
+ if(count>=fragsize)
+ block=1;
+ else
+ block=0;
+ dest=LMBuffer+((block*fragsize)<<format);
+
+ #ifdef MOO
+ dest=LMBuffer+((whichbuf*fragsize)<<format);
+ whichbuf^=1;
+ #endif
+ }
+
+ _farsetsel(_dos_ds);
+
+ src=(uint32 *)(WaveBuffer+(ReadPtr<<format));
+
+ if(ssilence)
+ {
+ uint32 sby;
+ if(format) sby=0; /* 16-bit silence. */
+ else sby=0x80808080; /* 8-bit silence. */
+
+ for(x=(fragsize<<format)>>2;x;x--,dest+=4)
+ {
+ _farnspokel(dest,sby);
+ }
+ }
+ else
+ {
+ for(x=(fragsize<<format)>>2;x;x--,dest+=4,src++)
+ {
+ _farnspokel(dest,*src);
+ }
+ ReadPtr=(ReadPtr+fragsize)&(fragtotal-1);
+ }
+
+ if(soundjoyeron)
+ {
+ static int coot=0;
+ if(!coot)
+ {
+ UpdateJoyData();
+ soundjoyer=1;
+ }
+ coot=(coot+1)&3;
+ }
+ hbusy=0;
+ outportb(0x20,0x20);
+ if(SBIRQ>=8)
+ outportb(0xA0,0x20);
+}
+
+void SilenceSound(int s)
+{
+ ssilence=s;
+}
+
+void WriteSBSound(int32 *Buffer, int Count, int NoBlocking)
+{
+ int x;
+
+ if(!format)
+ {
+ for(x=0;x<Count;x++)
+ {
+ while(WritePtr==ReadPtr)
+ if(NoBlocking)
+ return;
+ WaveBuffer[WritePtr]=(uint8)((Buffer[x])>>8)^128;
+ WritePtr=(WritePtr+1)&(fragtotal-1);
+ }
+ }
+ else // 16 bit
+ {
+ for(x=0;x<Count;x++)
+ {
+ while(WritePtr==ReadPtr)
+ if(NoBlocking)
+ return;
+ ((int16 *)WaveBuffer)[WritePtr]=Buffer[x];
+ WritePtr=(WritePtr+1)&(fragtotal-1);
+ }
+ }
+}
+
+void KillSB(void)
+{
+ if(hsmode)
+ ResetDSP(); /* High-speed mode requires a DSP reset. */
+ else
+ WriteDSP(format?0xD9:0xDA); /* Exit auto-init DMA transfer mode. */
+ WriteDSP(0xD3); /* Turn speaker off. */
+
+ outportb((SBIRQ>7)?0xA1:0x21,PICMask|(1<<(SBIRQ&7)));
+ ResetVectors();
+ outportb((SBIRQ>7)?0xA1:0x21,PICMask);
+ KillDMABuffer();
+}
diff --git a/drivers/pc/dos-sound.h b/drivers/pc/dos-sound.h
new file mode 100644
index 00000000..c0e261b5
--- /dev/null
+++ b/drivers/pc/dos-sound.h
@@ -0,0 +1,26 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+int InitSB(int Rate, int bittage);
+void KillSB(void);
+
+void WriteSBSound(int32 *Buffer, int Count, int NoBlocking);
+void SilenceSound(int s);
+
diff --git a/drivers/pc/dos-video.c b/drivers/pc/dos-video.c
new file mode 100644
index 00000000..6c9a3682
--- /dev/null
+++ b/drivers/pc/dos-video.c
@@ -0,0 +1,246 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 1998 \Firebug\
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <dpmi.h>
+#include <sys/farptr.h>
+#include <go32.h>
+#include <pc.h>
+
+#include "dos.h"
+#include "dos-video.h"
+
+#define TEXT 3
+#define G320x200x256 0x13
+
+static void vga_waitretrace(void)
+{
+ while(inp(0x3da)&0x8);
+ while(!(inp(0x3da)&0x8));
+}
+
+static void vga_setmode(int mode)
+{
+ __dpmi_regs regs;
+
+ memset(&regs,0,sizeof(regs));
+ regs.x.ax=mode;
+
+ __dpmi_int(0x10,&regs);
+}
+
+void vga_setpalette(int i, int r, int g, int b)
+{
+ outp(0x3c8,i);
+ outp(0x3c9,r);
+ outp(0x3c9,g);
+ outp(0x3c9,b);
+}
+
+int FCEUDvmode=1;
+
+static int vidready=0;
+
+/* Part of the VGA low-level mass register setting code derived from
+ code by \Firebug\.
+*/
+
+#include "vgatweak.c"
+
+void SetBorder(void)
+{
+ inportb(0x3da);
+ outportb(0x3c0,(0x11|0x20));
+ outportb(0x3c0,0x80);
+}
+
+void TweakVGA(int VGAMode)
+{
+ int I;
+
+ vga_waitretrace();
+
+ outportb(0x3C8,0x00);
+ for(I=0;I<768;I++) outportb(0x3C9,0x00);
+
+ outportb(0x3D4,0x11);
+ I=inportb(0x3D5)&0x7F;
+ outportb(0x3D4,0x11);
+ outportb(0x3D5,I);
+
+ switch(VGAMode)
+ {
+ case 1: for(I=0;I<25;I++) VGAPortSet(v256x240[I]);break;
+ case 2: for(I=0;I<25;I++) VGAPortSet(v256x256[I]);break;
+ case 3: for(I=0;I<25;I++) VGAPortSet(v256x256S[I]);break;
+ case 6: for(I=0;I<25;I++) VGAPortSet(v256x224S[I]);break;
+ case 8: for(I=0;I<25;I++) VGAPortSet(v256x224_103[I]);break;
+ default: break;
+ }
+
+ outportb(0x3da,0);
+}
+
+
+static uint8 palettedbr[256],palettedbg[256],palettedbb[256];
+
+static void FlushPalette(void)
+{
+ int x;
+ for(x=0;x<256;x++)
+ {
+ int z=x;
+ vga_setpalette(z,palettedbr[x]>>2,palettedbg[x]>>2,palettedbb[x]>>2);
+ }
+}
+
+void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b)
+{
+ palettedbr[index]=r;
+ palettedbg[index]=g;
+ palettedbb[index]=b;
+ if(vidready)
+ {
+ vga_setpalette(index,r>>2,g>>2,b>>2);
+ }
+}
+
+
+void FCEUD_GetPalette(uint8 i, uint8 *r, uint8 *g, uint8 *b)
+{
+ *r=palettedbr[i];
+ *g=palettedbg[i];
+ *b=palettedbb[i];
+}
+
+static uint32 ScreenLoc;
+
+int InitVideo(void)
+{
+ vidready=0;
+ switch(FCEUDvmode)
+ {
+ default:
+ case 1:
+ case 2:
+ case 3:
+ case 6:
+ case 8:
+ vga_setmode(G320x200x256);
+ vidready|=1;
+ ScreenLoc=0xa0000;
+ TweakVGA(FCEUDvmode);
+ SetBorder();
+ DOSMemSet(ScreenLoc, 128, 256*256);
+ break;
+ }
+ vidready|=2;
+ FlushPalette();
+ return 1;
+}
+
+void KillVideo(void)
+{
+ if(vidready)
+ {
+ vga_setmode(TEXT);
+ vidready=0;
+ }
+}
+void LockConsole(void){}
+void UnlockConsole(void){}
+void BlitScreen(uint8 *XBuf)
+{
+ uint32 dest;
+ int tlines;
+
+ if(eoptions&4 && !NoWaiting)
+ vga_waitretrace();
+
+ tlines=erendline-srendline+1;
+
+ dest=ScreenLoc;
+
+ switch(FCEUDvmode)
+ {
+ case 1:dest+=(((240-tlines)>>1)<<8);break;
+ case 2:
+ case 3:dest+=(((256-tlines)>>1)<<8);break;
+ case 4:
+ case 5:dest+=(((240-tlines)>>1)*640+((640-512)>>1));break;
+ case 8:
+ case 6:if(tlines>224) tlines=224;dest+=(((224-tlines)>>1)<<8);break;
+ }
+
+ XBuf+=(srendline<<8)+(srendline<<4);
+
+ _farsetsel(_dos_ds);
+ if(eoptions&DO_CLIPSIDES)
+ {
+ asm volatile(
+ "agoop1:\n\t"
+ "movl $30,%%eax\n\t"
+ "agoop2:\n\t"
+ "movl (%%esi),%%edx\n\t"
+ "movl 4(%%esi),%%ecx\n\t"
+ ".byte 0x64 \n\t"
+ "movl %%edx,(%%edi)\n\t"
+ ".byte 0x64 \n\t"
+ "movl %%ecx,4(%%edi)\n\t"
+ "addl $8,%%esi\n\t"
+ "addl $8,%%edi\n\t"
+ "decl %%eax\n\t"
+ "jne agoop2\n\t"
+ "addl $32,%%esi\n\t"
+ "addl $16,%%edi\n\t"
+ "decb %%bl\n\t"
+ "jne agoop1\n\t"
+ :
+ : "S" (XBuf+8), "D" (dest+8), "b" (tlines)
+ : "%eax","%cc","%edx","%ecx" );
+ }
+ else
+ {
+ asm volatile(
+ "goop1:\n\t"
+ "movl $32,%%eax\n\t"
+ "goop2:\n\t"
+ "movl (%%esi),%%edx\n\t"
+ "movl 4(%%esi),%%ecx\n\t"
+ ".byte 0x64 \n\t"
+ "movl %%edx,(%%edi)\n\t"
+ ".byte 0x64 \n\t"
+ "movl %%ecx,4(%%edi)\n\t"
+ "addl $8,%%esi\n\t"
+ "addl $8,%%edi\n\t"
+ "decl %%eax\n\t"
+ "jne goop2\n\t"
+ "addl $16,%%esi\n\t"
+ "decb %%bl\n\t"
+ "jne goop1\n\t"
+ :
+ : "S" (XBuf), "D" (dest), "b" (tlines)
+ : "%eax","%cc","%edx","%ecx" );
+ }
+}
+
+
diff --git a/drivers/pc/dos-video.h b/drivers/pc/dos-video.h
new file mode 100644
index 00000000..75b1a1b8
--- /dev/null
+++ b/drivers/pc/dos-video.h
@@ -0,0 +1,22 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+extern int FCEUDvmode;
+
diff --git a/drivers/pc/dos.c b/drivers/pc/dos.c
new file mode 100644
index 00000000..bd34b058
--- /dev/null
+++ b/drivers/pc/dos.c
@@ -0,0 +1,128 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <crt0.h>
+#include <sys/farptr.h>
+#include <go32.h>
+
+#include "dos.h"
+#include "dos-joystick.h"
+#include "dos-video.h"
+#include "dos-sound.h"
+#include "../common/args.h"
+#include "../common/config.h"
+
+/* _CRT0_FLAG_LOCK_MEMORY might not always result in all memory being locked.
+ Bummer. I'll add code to explicitly lock the data touched by the sound
+ interrupt handler(and the handler itself), if necessary(though that might
+ be tricky...). I'll also to cover the data the keyboard
+ interrupt handler touches.
+*/
+
+int _crt0_startup_flags = _CRT0_FLAG_FILL_SBRK_MEMORY | _CRT0_FLAG_LOCK_MEMORY | _CRT0_FLAG_USE_DOS_SLASHES;
+
+static int f8bit=0;
+int soundo=44100;
+int doptions=0;
+
+
+CFGSTRUCT DriverConfig[]={
+ NAC("sound",soundo),
+ AC(doptions),
+ AC(f8bit),
+ AC(FCEUDvmode),
+ NACA("joybmap",joyBMap),
+ AC(joy),
+ ENDCFGSTRUCT
+};
+
+char *DriverUsage=
+"-vmode x Select video mode(all are 8 bpp).\n\
+ 1 = 256x240 6 = 256x224(with scanlines)\n\
+ 2 = 256x256 8 = 256x224\n\
+ 3 = 256x256(with scanlines)\n\
+-vsync x Wait for the screen's vertical retrace before updating the\n\
+ screen. Refer to the documentation for caveats.\n\
+ 0 = Disabled.\n\
+ 1 = Enabled.\n\
+-sound x Sound.\n\
+ 0 = Disabled.\n\
+ Otherwise, x = playback rate.\n\
+-f8bit x Force 8-bit sound.\n\
+ 0 = Disabled.\n\
+ 1 = Enabled.";
+
+ARGPSTRUCT DriverArgs[]={
+ {"-vmode",0,&FCEUDvmode,0},
+ {"-sound",0,&soundo,0},
+ {"-f8bit",0,&f8bit,0},
+ {"-vsync",0,&doptions,DO_VSYNC},
+ {0,0,0,0}
+};
+
+void DoDriverArgs(void)
+{
+ if(!joy) memset(joyBMap,0,sizeof(joyBMap));
+}
+
+int InitSound(void)
+{
+ if(soundo)
+ {
+ if(soundo==1)
+ soundo=44100;
+ soundo=InitSB(soundo,f8bit?0:1);
+ FCEUI_Sound(soundo);
+ }
+ return(soundo);
+}
+
+void WriteSound(int32 *Buffer, int Count, int NoWaiting)
+{
+ WriteSBSound(Buffer,Count,NoWaiting);
+}
+
+void KillSound(void)
+{
+ if(soundo)
+ KillSB();
+}
+
+void DOSMemSet(uint32 A, uint8 V, uint32 count)
+{
+ uint32 x;
+
+ _farsetsel(_dos_ds);
+ for(x=0;x<count;x++)
+ _farnspokeb(A+x,V);
+}
+
+static char *arg0;
+uint8 *GetBaseDirectory(void)
+{
+ int x=0;
+ uint8 *ret = 0;
+
+ if(arg0)
+ for(x=strlen(arg0);x>=0;x--)
+ {
+ if(arg0[x]=='/' || arg0[x]=='\\')
+ {
+ ret = malloc(x + 1);
+ strncpy(ret,arg0,x);
+ break;
+ }
+ }
+
+ if(!ret) { x=0; ret = malloc(1); }
+
+ BaseDirectory[x]=0;
+}
+
+int main(int argc, char *argv[])
+{
+ puts("\nStarting FCE Ultra "VERSION_STRING"...\n");
+ arg0=argv[0];
+ return(CLImain(argc,argv));
+}
+
diff --git a/drivers/pc/dos.h b/drivers/pc/dos.h
new file mode 100644
index 00000000..b6814800
--- /dev/null
+++ b/drivers/pc/dos.h
@@ -0,0 +1,27 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "main.h"
+#include "dface.h"
+#include "input.h"
+
+void DOSMemSet(uint32 A, uint8 V, uint32 count);
+#define DO_VSYNC 1
+
diff --git a/drivers/pc/input.c b/drivers/pc/input.c
new file mode 100644
index 00000000..35fe0350
--- /dev/null
+++ b/drivers/pc/input.c
@@ -0,0 +1,720 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string.h>
+
+#include "main.h"
+#include "dface.h"
+#include "input.h"
+
+#include "../common/cheat.h"
+
+/* UsrInputType[] is user-specified. InputType[] is current
+ (game loading can override user settings)
+*/
+int UsrInputType[3]={SI_GAMEPAD,SI_GAMEPAD,SIFC_NONE};
+int InputType[3]={0,0,0};
+static int cspec=0;
+
+int gametype=0;
+
+/* Necessary for proper GUI functioning(configuring when a game isn't loaded). */
+void InputUserActiveFix(void)
+{
+ int x;
+ for(x=0;x<3;x++) InputType[x]=UsrInputType[x];
+}
+
+void ParseGIInput(FCEUGI *gi)
+{
+ gametype=gi->type;
+
+ InputType[0]=UsrInputType[0];
+ InputType[1]=UsrInputType[1];
+ InputType[2]=UsrInputType[2];
+
+ if(gi->input[0]>=0)
+ InputType[0]=gi->input[0];
+ if(gi->input[1]>=0)
+ InputType[1]=gi->input[1];
+ if(gi->inputfc>=0)
+ InputType[2]=gi->inputfc;
+ cspec = gi->cspecial;
+
+ #ifdef EXTGUI
+ Giggles(gi->cspecial);
+ #endif
+}
+
+
+static uint8 QuizKingData=0;
+static uint8 HyperShotData=0;
+static uint32 MahjongData=0;
+static uint32 FTrainerData=0;
+static uint8 TopRiderData=0;
+
+static uint8 BWorldData[1+13+1];
+
+static void UpdateFKB(void);
+static void UpdateGamepad(void);
+static void UpdateQuizKing(void);
+static void UpdateHyperShot(void);
+static void UpdateMahjong(void);
+static void UpdateFTrainer(void);
+static void UpdateTopRider(void);
+
+static uint32 JSreturn=0;
+int NoWaiting=1;
+
+#ifndef EXTGUI
+static void DoCheatSeq(void)
+{
+ #if defined(DOS) || defined(SDL)
+ SilenceSound(1);
+ #endif
+ KillKeyboard();
+ KillVideo();
+
+ DoConsoleCheatConfig();
+ InitVideo(CurGame);
+ InitKeyboard();
+ #if defined(DOS) || defined(SDL)
+ SilenceSound(0);
+ #endif
+}
+#endif
+
+#include "keyscan.h"
+static char *keys=0;
+static int DIPS=0;
+
+static uint8 keyonce[MKK_COUNT];
+#define KEY(__a) keys[MKK(__a)]
+
+static int _keyonly(int a)
+{
+ if(keys[a])
+ {
+ if(!keyonce[a])
+ {
+ keyonce[a]=1;
+ return(1);
+ }
+ }
+ else
+ keyonce[a]=0;
+ return(0);
+}
+
+#define keyonly(__a) _keyonly(MKK(__a))
+
+static int cidisabled=0;
+
+static void KeyboardCommands(void)
+{
+ int is_shift, is_alt;
+
+ keys=GetKeyboard();
+
+ if(InputType[2]==SIFC_FKB)
+ {
+ if(keyonly(SCROLLLOCK))
+ {
+ cidisabled^=1;
+ FCEUI_DispMessage("Family Keyboard %sabled.",cidisabled?"en":"dis");
+ }
+ #ifdef SDL
+ SDL_WM_GrabInput(cidisabled?SDL_GRAB_ON:SDL_GRAB_OFF);
+ #endif
+ if(cidisabled) return;
+ }
+
+ is_shift = KEY(LEFTSHIFT) | KEY(RIGHTSHIFT);
+ is_alt = KEY(LEFTALT) | KEY(RIGHTALT);
+
+ if(keyonly(F4))
+ {
+ if(is_shift) FCEUI_SetRenderDisable(-1, 2);
+ else FCEUI_SetRenderDisable(2, -1);
+ }
+ #ifdef SDL
+ if(keyonly(ENTER) && is_alt) ToggleFS();
+ #endif
+
+ NoWaiting&=~1;
+ if(KEY(GRAVE))
+ NoWaiting|=1;
+
+ if(gametype==GIT_FDS)
+ {
+ if(keyonly(F6)) FCEUI_FDSSelect();
+ if(keyonly(F8)) FCEUI_FDSInsert();
+ }
+
+ if(keyonly(F9)) FCEUI_SaveSnapshot();
+ if(gametype!=GIT_NSF)
+ {
+ #ifndef EXTGUI
+ if(keyonly(F2)) DoCheatSeq();
+ #endif
+ if(keyonly(F5))
+ {
+ if(is_shift)
+ FCEUI_SaveMovie(NULL,0,NULL);
+ else
+ FCEUI_SaveState(NULL);
+ }
+ if(keyonly(F7))
+ {
+ if(is_shift)
+ FCEUI_LoadMovie(NULL,0);
+ else
+ FCEUI_LoadState(NULL);
+ }
+ }
+
+ if(keyonly(F1)) FCEUI_ToggleTileView();
+
+ if(keyonly(MINUS)) DecreaseEmulationSpeed();
+ if(keyonly(EQUAL)) IncreaseEmulationSpeed();
+ if(keyonly(BACKSPACE)) FCEUI_MovieToggleFrameDisplay();
+ if(keyonly(BACKSLASH)) FCEUI_ToggleEmulationPause();
+ if(keyonly(RIGHTCONTROL)) FCEUI_FrameAdvance();
+
+ if(keyonly(F10)) FCEUI_ResetNES();
+ if(keyonly(F11)) FCEUI_PowerNES();
+
+ #ifdef EXTGUI
+ if(keyonly(F3)) GUI_Hide(-1);
+ if(KEY(F12)) GUI_RequestExit();
+ if(KEY(ESCAPE)) CloseGame();
+ #else
+ if(KEY(F12) || KEY(ESCAPE)) CloseGame();
+ #endif
+
+ if(gametype==GIT_VSUNI)
+ {
+ if(keyonly(F8)) FCEUI_VSUniCoin();
+ if(keyonly(F6))
+ {
+ DIPS^=1;
+ FCEUI_VSUniToggleDIPView();
+ }
+ if(!(DIPS&1)) goto DIPSless;
+ if(keyonly(1)) FCEUI_VSUniToggleDIP(0);
+ if(keyonly(2)) FCEUI_VSUniToggleDIP(1);
+ if(keyonly(3)) FCEUI_VSUniToggleDIP(2);
+ if(keyonly(4)) FCEUI_VSUniToggleDIP(3);
+ if(keyonly(5)) FCEUI_VSUniToggleDIP(4);
+ if(keyonly(6)) FCEUI_VSUniToggleDIP(5);
+ if(keyonly(7)) FCEUI_VSUniToggleDIP(6);
+ if(keyonly(8)) FCEUI_VSUniToggleDIP(7);
+ }
+ else
+ {
+ static uint8 bbuf[32];
+ static int bbuft;
+ static int barcoder = 0;
+
+ if(keyonly(H)) FCEUI_NTSCSELHUE();
+ if(keyonly(T)) FCEUI_NTSCSELTINT();
+ if(KEY(KP_MINUS) || KEY(MINUS)) FCEUI_NTSCDEC();
+ if(KEY(KP_PLUS) || KEY(EQUAL)) FCEUI_NTSCINC();
+
+ if((InputType[2] == SIFC_BWORLD) || (cspec == SIS_DATACH))
+ {
+ if(keyonly(F8))
+ {
+ barcoder ^= 1;
+ if(!barcoder)
+ {
+ if(InputType[2] == SIFC_BWORLD)
+ {
+ strcpy(&BWorldData[1],bbuf);
+ BWorldData[0]=1;
+ }
+ else
+ FCEUI_DatachSet(bbuf);
+ FCEUI_DispMessage("Barcode Entered");
+ }
+ else { bbuft = 0; FCEUI_DispMessage("Enter Barcode");}
+ }
+ } else barcoder = 0;
+
+ #define SSM(x) \
+ { if(barcoder) { if(bbuft < 13) {bbuf[bbuft++] = '0' + x; bbuf[bbuft] = 0;} FCEUI_DispMessage("Barcode: %s",bbuf);} \
+ else { \
+ if(is_shift) FCEUI_SelectMovie(x,1); \
+ else FCEUI_SelectState(x,1); \
+ } }
+
+ DIPSless:
+ if(keyonly(0)) SSM(0);
+ if(keyonly(1)) SSM(1);
+ if(keyonly(2)) SSM(2);
+ if(keyonly(3)) SSM(3);
+ if(keyonly(4)) SSM(4);
+ if(keyonly(5)) SSM(5);
+ if(keyonly(6)) SSM(6);
+ if(keyonly(7)) SSM(7);
+ if(keyonly(8)) SSM(8);
+ if(keyonly(9)) SSM(9);
+ #undef SSM
+ }
+}
+
+#define MK(x) {{BUTTC_KEYBOARD},{0},{MKK(x)},1}
+#define MK2(x1,x2) {{BUTTC_KEYBOARD},{0},{MKK(x1),MKK(x2)},2}
+
+#define MKZ() {{0},{0},{0},0}
+
+#define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()}
+
+ButtConfig GamePadConfig[4][10]={
+ /* Gamepad 1 */
+ {
+ MK(KP3), MK(KP2), MK(TAB), MK(ENTER), MK(W),MK(Z),
+ MK(A), MK(S), MKZ(), MKZ()
+ },
+
+ /* Gamepad 2 */
+ GPZ(),
+
+ /* Gamepad 3 */
+ GPZ(),
+
+ /* Gamepad 4 */
+ GPZ()
+};
+
+
+static void UpdateGamepad(void)
+{
+ if(FCEUI_IsMovieActive()<0)
+ return;
+
+ static int rapid=0;
+ uint32 JS=0;
+ int x;
+ int wg;
+
+ rapid^=1;
+
+ for(wg=0;wg<4;wg++)
+ {
+ for(x=0;x<8;x++)
+ if(DTestButton(&GamePadConfig[wg][x]))
+ JS|=(1<<x)<<(wg<<3);
+
+ if(rapid)
+ for(x=0;x<2;x++)
+ if(DTestButton(&GamePadConfig[wg][8+x]))
+ JS|=(1<<x)<<(wg<<3);
+ }
+
+// for(x=0;x<32;x+=8) /* Now, test to see if anything weird(up+down at same time)
+// is happening, and correct */
+// {
+// if((JS & (0xC0<<x) ) == (0xC0<<x) ) JS&=~(0xC0<<x);
+// if((JS & (0x30<<x) ) == (0x30<<x) ) JS&=~(0x30<<x);
+// }
+
+ JSreturn=JS;
+}
+
+ButtConfig powerpadsc[2][12]={
+ {
+ MK(O),MK(P),MK(BRACKET_LEFT),
+ MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
+ MK(APOSTROPHE),
+ MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
+ },
+ {
+ MK(O),MK(P),MK(BRACKET_LEFT),
+ MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
+ MK(APOSTROPHE),
+ MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
+ }
+ };
+
+static uint32 powerpadbuf[2]={0,0};
+
+static uint32 UpdatePPadData(int w)
+{
+ if(FCEUI_IsMovieActive()<0)
+ return;
+
+ uint32 r=0;
+ ButtConfig *ppadtsc=powerpadsc[w];
+ int x;
+
+ for(x=0;x<12;x++)
+ if(DTestButton(&ppadtsc[x])) r|=1<<x;
+
+ return r;
+}
+
+static uint32 MouseData[3]={0,0,0};
+static uint8 fkbkeys[0x48];
+
+void FCEUD_UpdateInput(void)
+{
+ int x;
+ int t=0;
+
+ UpdatePhysicalInput();
+ KeyboardCommands();
+
+ for(x=0;x<2;x++)
+ switch(InputType[x])
+ {
+ case SI_GAMEPAD:t|=1;break;
+ case SI_ARKANOID:t|=2;break;
+ case SI_ZAPPER:t|=2;break;
+ case SI_POWERPADA:
+ case SI_POWERPADB:powerpadbuf[x]=UpdatePPadData(x);break;
+ }
+
+ switch(InputType[2])
+ {
+ case SIFC_ARKANOID:t|=2;break;
+ case SIFC_SHADOW:t|=2;break;
+ case SIFC_FKB:if(cidisabled) UpdateFKB();break;
+ case SIFC_HYPERSHOT: UpdateHyperShot();break;
+ case SIFC_MAHJONG: UpdateMahjong();break;
+ case SIFC_QUIZKING: UpdateQuizKing();break;
+ case SIFC_FTRAINERB:
+ case SIFC_FTRAINERA: UpdateFTrainer();break;
+ case SIFC_TOPRIDER: UpdateTopRider();break;
+ case SIFC_OEKAKIDS:t|=2;break;
+
+ }
+
+ if(t&1)
+ UpdateGamepad();
+
+ if(t&2)
+ GetMouseData(MouseData);
+}
+
+void InitOtherInput(void)
+{
+ void *InputDPtr;
+
+ int t;
+ int x;
+ int attrib;
+
+ for(t=0,x=0;x<2;x++)
+ {
+ attrib=0;
+ InputDPtr=0;
+ switch(InputType[x])
+ {
+ case SI_POWERPADA:
+ case SI_POWERPADB:InputDPtr=&powerpadbuf[x];break;
+ case SI_GAMEPAD:InputDPtr=&JSreturn;break;
+ case SI_ARKANOID:InputDPtr=MouseData;t|=1;break;
+ case SI_ZAPPER:InputDPtr=MouseData;
+ t|=1;
+ attrib=1;
+ break;
+ }
+ FCEUI_SetInput(x,InputType[x],InputDPtr,attrib);
+ }
+
+ attrib=0;
+ InputDPtr=0;
+ switch(InputType[2])
+ {
+ case SIFC_SHADOW:InputDPtr=MouseData;t|=1;attrib=1;break;
+ case SIFC_OEKAKIDS:InputDPtr=MouseData;t|=1;attrib=1;break;
+ case SIFC_ARKANOID:InputDPtr=MouseData;t|=1;break;
+ case SIFC_FKB:InputDPtr=fkbkeys;break;
+ case SIFC_HYPERSHOT:InputDPtr=&HyperShotData;break;
+ case SIFC_MAHJONG:InputDPtr=&MahjongData;break;
+ case SIFC_QUIZKING:InputDPtr=&QuizKingData;break;
+ case SIFC_TOPRIDER:InputDPtr=&TopRiderData;break;
+ case SIFC_BWORLD:InputDPtr=BWorldData;break;
+ case SIFC_FTRAINERA:
+ case SIFC_FTRAINERB:InputDPtr=&FTrainerData;break;
+ }
+
+ FCEUI_SetInputFC(InputType[2],InputDPtr,attrib);
+ FCEUI_DisableFourScore(eoptions&EO_NOFOURSCORE);
+
+ if(t)
+ InitMouse();
+}
+
+
+ButtConfig fkbmap[0x48]=
+{
+ MK(F1),MK(F2),MK(F3),MK(F4),MK(F5),MK(F6),MK(F7),MK(F8),
+ MK(1),MK(2),MK(3),MK(4),MK(5),MK(6),MK(7),MK(8),MK(9),MK(0),
+ MK(MINUS),MK(EQUAL),MK(BACKSLASH),MK(BACKSPACE),
+ MK(ESCAPE),MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y),MK(U),MK(I),MK(O),
+ MK(P),MK(GRAVE),MK(BRACKET_LEFT),MK(ENTER),
+ MK(LEFTCONTROL),MK(A),MK(S),MK(D),MK(F),MK(G),MK(H),MK(J),MK(K),
+ MK(L),MK(SEMICOLON),MK(APOSTROPHE),MK(BRACKET_RIGHT),MK(INSERT),
+ MK(LEFTSHIFT),MK(Z),MK(X),MK(C),MK(V),MK(B),MK(N),MK(M),MK(COMMA),
+ MK(PERIOD),MK(SLASH),MK(RIGHTALT),MK(RIGHTSHIFT),MK(LEFTALT),MK(SPACE),
+ MK(DELETE),MK(END),MK(PAGEDOWN),
+ MK(CURSORUP),MK(CURSORLEFT),MK(CURSORRIGHT),MK(CURSORDOWN)
+};
+
+static void UpdateFKB(void)
+{
+ int x;
+
+ for(x=0;x<0x48;x++)
+ {
+ fkbkeys[x]=0;
+
+ if(DTestButton(&fkbmap[x]))
+ fkbkeys[x]=1;
+ }
+}
+
+static ButtConfig HyperShotButtons[4]=
+{
+ MK(Q),MK(W),MK(E),MK(R)
+};
+
+static void UpdateHyperShot(void)
+{
+ int x;
+
+ HyperShotData=0;
+ for(x=0;x<0x4;x++)
+ {
+ if(DTestButton(&HyperShotButtons[x]))
+ HyperShotData|=1<<x;
+ }
+}
+
+static ButtConfig MahjongButtons[21]=
+{
+ MK(Q),MK(W),MK(E),MK(R),MK(T),
+ MK(A),MK(S),MK(D),MK(F),MK(G),MK(H),MK(J),MK(K),MK(L),
+ MK(Z),MK(X),MK(C),MK(V),MK(B),MK(N),MK(M)
+};
+
+static void UpdateMahjong(void)
+{
+ int x;
+
+ MahjongData=0;
+ for(x=0;x<21;x++)
+ {
+ if(DTestButton(&MahjongButtons[x]))
+ MahjongData|=1<<x;
+ }
+}
+
+ButtConfig QuizKingButtons[6]=
+{
+ MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y)
+};
+
+static void UpdateQuizKing(void)
+{
+ int x;
+
+ QuizKingData=0;
+
+ for(x=0;x<6;x++)
+ {
+ if(DTestButton(&QuizKingButtons[x]))
+ QuizKingData|=1<<x;
+ }
+
+}
+
+ButtConfig TopRiderButtons[8]=
+{
+ MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y),MK(U),MK(I)
+};
+
+static void UpdateTopRider(void)
+{
+ int x;
+ TopRiderData=0;
+ for(x=0;x<8;x++)
+ if(DTestButton(&TopRiderButtons[x]))
+ TopRiderData|=1<<x;
+}
+
+ButtConfig FTrainerButtons[12]=
+{
+ MK(O),MK(P),MK(BRACKET_LEFT),
+ MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
+ MK(APOSTROPHE),
+ MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
+};
+
+static void UpdateFTrainer(void)
+{
+ int x;
+
+ FTrainerData=0;
+
+ for(x=0;x<12;x++)
+ {
+ if(DTestButton(&FTrainerButtons[x]))
+ FTrainerData|=1<<x;
+ }
+}
+
+static void subcon(char *text, ButtConfig *bc)
+{
+ uint8 buf[256];
+ int wc;
+
+ for(wc=0;wc<MAXBUTTCONFIG;wc++)
+ {
+ sprintf(buf,"%s (%d)",text,wc+1);
+ DWaitButton(buf,bc,wc);
+
+ if(wc && bc->ButtType[wc]==bc->ButtType[wc-1] && bc->DeviceNum[wc]==bc->DeviceNum[wc-1] &&
+ bc->ButtonNum[wc]==bc->ButtonNum[wc-1])
+ break;
+ }
+ bc->NumC=wc;
+}
+
+void ConfigDevice(int which, int arg)
+{
+ uint8 buf[256];
+ int x;
+
+ ButtonConfigBegin();
+ switch(which)
+ {
+ case FCFGD_QUIZKING:
+ for(x=0;x<6;x++)
+ {
+ sprintf(buf,"Quiz King Buzzer #%d", x+1);
+ subcon(buf,&QuizKingButtons[x]);
+ }
+ break;
+ case FCFGD_HYPERSHOT:
+ for(x=0;x<4;x++)
+ {
+ sprintf(buf,"Hyper Shot %d: %s",((x&2)>>1)+1,(x&1)?"JUMP":"RUN");
+ subcon(buf,&HyperShotButtons[x]);
+ }
+ break;
+ case FCFGD_POWERPAD:
+ for(x=0;x<12;x++)
+ {
+ sprintf(buf,"PowerPad %d: %d", (arg&1)+1,x+11);
+ subcon(buf,&powerpadsc[arg&1][x]);
+ }
+ break;
+
+ case FCFGD_GAMEPAD:
+ {
+ char *str[10]={"A","B","SELECT","START","UP","DOWN","LEFT","RIGHT","Rapid A","Rapid B"};
+ for(x=0;x<10;x++)
+ {
+ sprintf(buf,"GamePad #%d: %s",arg+1,str[x]);
+ subcon(buf,&GamePadConfig[arg][x]);
+ }
+ }
+ break;
+ }
+
+ ButtonConfigEnd();
+}
+
+
+CFGSTRUCT InputConfig[]={
+ ACA(UsrInputType),
+ AC(powerpadsc),
+ AC(QuizKingButtons),
+ AC(FTrainerButtons),
+ AC(HyperShotButtons),
+ AC(MahjongButtons),
+ AC(GamePadConfig),
+ AC(fkbmap),
+ ENDCFGSTRUCT
+};
+
+
+static void InputCfg(char *text)
+{
+ if(!strncasecmp(text,"gamepad",strlen("gamepad")))
+ {
+ ConfigDevice(FCFGD_GAMEPAD,(text[strlen("gamepad")]-'1')&3);
+ }
+ else if(!strncasecmp(text,"powerpad",strlen("powerpad")))
+ {
+ ConfigDevice(FCFGD_POWERPAD,(text[strlen("powerpad")]-'1')&1);
+ }
+ else if(!strcasecmp(text,"hypershot"))
+ ConfigDevice(FCFGD_HYPERSHOT,0);
+ else if(!strcasecmp(text,"quizking"))
+ ConfigDevice(FCFGD_QUIZKING,0);
+}
+
+static void FCExp(char *text)
+{
+ static char *fccortab[11]={"none","arkanoid","shadow","4player","fkb","hypershot",
+ "mahjong","quizking","ftrainera","ftrainerb","oekakids"};
+
+ static int fccortabi[11]={SIFC_NONE,SIFC_ARKANOID,SIFC_SHADOW,
+ SIFC_4PLAYER,SIFC_FKB,SIFC_HYPERSHOT,SIFC_MAHJONG,SIFC_QUIZKING,
+ SIFC_FTRAINERA,SIFC_FTRAINERB,SIFC_OEKAKIDS};
+ int y;
+ for(y=0;y<11;y++)
+ if(!strcmp(fccortab[y],text))
+ UsrInputType[2]=fccortabi[y];
+}
+
+static char *cortab[6]={"none","gamepad","zapper","powerpada","powerpadb","arkanoid"};
+static int cortabi[6]={SI_NONE,SI_GAMEPAD,
+ SI_ZAPPER,SI_POWERPADA,SI_POWERPADB,SI_ARKANOID};
+
+static void Input1(char *text)
+{
+ int y;
+
+ for(y=0;y<6;y++)
+ if(!strcmp(cortab[y],text))
+ UsrInputType[0]=cortabi[y];
+}
+
+static void Input2(char *text)
+{
+ int y;
+
+ for(y=0;y<6;y++)
+ if(!strcmp(cortab[y],text))
+ UsrInputType[1]=cortabi[y];
+}
+
+ARGPSTRUCT InputArgs[]={
+ {"-inputcfg",0,(void *)InputCfg,0x2000},
+ {"-fcexp",0,(void *)FCExp,0x2000},
+ {"-input1",0,(void *)Input1,0x2000},
+ {"-input2",0,(void *)Input2,0x2000},
+ {0,0,0,0}
+};
diff --git a/drivers/pc/input.h b/drivers/pc/input.h
new file mode 100644
index 00000000..f9fbf36e
--- /dev/null
+++ b/drivers/pc/input.h
@@ -0,0 +1,38 @@
+#ifndef _aosdfjk02fmasf
+#define _aosdfjk02fmasf
+#define MAXBUTTCONFIG 4
+typedef struct {
+ uint8 ButtType[MAXBUTTCONFIG];
+ uint8 DeviceNum[MAXBUTTCONFIG];
+ uint16 ButtonNum[MAXBUTTCONFIG];
+ uint32 NumC;
+ //uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */
+} ButtConfig;
+
+extern CFGSTRUCT InputConfig[];
+extern ARGPSTRUCT InputArgs[];
+void ParseGIInput(FCEUGI *GI);
+
+#define BUTTC_KEYBOARD 0x00
+#define BUTTC_JOYSTICK 0x01
+#define BUTTC_MOUSE 0x02
+
+#define FCFGD_GAMEPAD 1
+#define FCFGD_POWERPAD 2
+#define FCFGD_HYPERSHOT 3
+#define FCFGD_QUIZKING 4
+
+void InitOtherInput(void);
+void InputUserActiveFix(void);
+#ifdef EXTGUI
+extern ButtConfig GamePadConfig[4][10];
+extern ButtConfig powerpadsc[2][12];
+extern ButtConfig QuizKingButtons[6];
+extern ButtConfig FTrainerButtons[12];
+#endif
+
+void IncreaseEmulationSpeed(void);
+void DecreaseEmulationSpeed(void);
+
+void FCEUD_UpdateInput(void);
+#endif
diff --git a/drivers/pc/keyscan.h b/drivers/pc/keyscan.h
new file mode 100644
index 00000000..09c20a1b
--- /dev/null
+++ b/drivers/pc/keyscan.h
@@ -0,0 +1,161 @@
+#ifdef SDL
+#include <SDL.h>
+#define SDLK_A SDLK_a
+#define SDLK_B SDLK_b
+#define SDLK_C SDLK_c
+#define SDLK_D SDLK_d
+#define SDLK_E SDLK_e
+#define SDLK_F SDLK_f
+#define SDLK_G SDLK_g
+#define SDLK_H SDLK_h
+#define SDLK_I SDLK_i
+#define SDLK_J SDLK_j
+#define SDLK_K SDLK_k
+#define SDLK_L SDLK_l
+#define SDLK_M SDLK_m
+#define SDLK_N SDLK_n
+#define SDLK_O SDLK_o
+#define SDLK_P SDLK_p
+#define SDLK_Q SDLK_q
+#define SDLK_R SDLK_r
+#define SDLK_S SDLK_s
+#define SDLK_T SDLK_t
+#define SDLK_U SDLK_u
+#define SDLK_V SDLK_v
+#define SDLK_W SDLK_w
+#define SDLK_X SDLK_x
+#define SDLK_Y SDLK_y
+#define SDLK_Z SDLK_z
+#define SDLK_LEFTCONTROL SDLK_LCTRL
+#define SDLK_RIGHTCONTROL SDLK_RCTRL
+#define SDLK_LEFTALT SDLK_LALT
+#define SDLK_RIGHTALT SDLK_RALT
+#define SDLK_LEFTSHIFT SDLK_LSHIFT
+#define SDLK_RIGHTSHIFT SDLK_RSHIFT
+#define SDLK_CURSORDOWN SDLK_DOWN
+#define SDLK_CURSORUP SDLK_UP
+#define SDLK_CURSORLEFT SDLK_LEFT
+#define SDLK_CURSORRIGHT SDLK_RIGHT
+#define SDLK_ENTER SDLK_RETURN
+#define SDLK_EQUAL SDLK_EQUALS
+#define SDLK_APOSTROPHE SDLK_QUOTE
+#define SDLK_BRACKET_LEFT SDLK_LEFTBRACKET
+#define SDLK_BRACKET_RIGHT SDLK_RIGHTBRACKET
+#define SDLK_SCROLLLOCK SDLK_SCROLLOCK /* I guess the SDL people don't like lots of Ls... */
+#define SDLK_GRAVE SDLK_BACKQUOTE
+#define MKK(k) SDLK_##k
+#define MKK_COUNT (SDLK_LAST+1)
+
+#elif DOS
+
+#define SCAN_GRAVE 0x29
+#define SCAN_1 0x02
+#define SCAN_2 0x03
+#define SCAN_3 0x04
+#define SCAN_4 0x05
+#define SCAN_5 0x06
+#define SCAN_6 0x07
+#define SCAN_7 0x08
+#define SCAN_8 0x09
+#define SCAN_9 0x0A
+#define SCAN_0 0x0B
+#define SCAN_MINUS 0x0C
+#define SCAN_EQUAL 0x0D
+#define SCAN_BACKSLASH 0x2B
+#define SCAN_BACKSPACE 0x0E
+#define SCAN_TAB 0x0F
+#define SCAN_Q 0x10
+#define SCAN_W 0x11
+#define SCAN_E 0x12
+#define SCAN_R 0x13
+#define SCAN_T 0x14
+#define SCAN_Y 0x15
+#define SCAN_U 0x16
+#define SCAN_I 0x17
+#define SCAN_O 0x18
+#define SCAN_P 0x19
+#define SCAN_BRACKET_LEFT 0x1A
+#define SCAN_BRACKET_RIGHT 0x1B
+#define SCAN_LOWBACKSLASH 0x2B
+#define SCAN_CAPSLOCK 0x3A
+#define SCAN_A 0x1E
+#define SCAN_S 0x1F
+#define SCAN_D 0x20
+#define SCAN_F 0x21
+#define SCAN_G 0x22
+#define SCAN_H 0x23
+#define SCAN_J 0x24
+#define SCAN_K 0x25
+#define SCAN_L 0x26
+#define SCAN_SEMICOLON 0x27
+#define SCAN_APOSTROPHE 0x28
+#define SCAN_ENTER 0x1C
+#define SCAN_LEFTSHIFT 0x2A
+#define SCAN_Z 0x2C
+#define SCAN_X 0x2D
+#define SCAN_C 0x2E
+#define SCAN_V 0x2F
+#define SCAN_B 0x30
+#define SCAN_N 0x31
+#define SCAN_M 0x32
+#define SCAN_COMMA 0x33
+#define SCAN_PERIOD 0x34
+#define SCAN_SLASH 0x35
+#define SCAN_RIGHTSHIFT 0x36
+#define SCAN_LEFTCONTROL 0x1D
+#define SCAN_LEFTALT 0x38
+#define SCAN_SPACE 0x39
+
+/* Extended keys. */
+#define SCAN_RIGHTALT (0x38|0x80)
+#define SCAN_RIGHTCONTROL (0x1D|0x80)
+#define SCAN_BL_INSERT (0x52|0x80)
+#define SCAN_BL_DELETE (0x53|0x80)
+#define SCAN_BL_CURSORLEFT (0x4B|0x80)
+#define SCAN_BL_HOME (0x47|0x80)
+#define SCAN_BL_END (0x4F|0x80)
+#define SCAN_BL_CURSORUP (0x48|0x80)
+#define SCAN_BL_CURSORDOWN (0x50|0x80)
+#define SCAN_BL_PAGEUP (0x49|0x80)
+#define SCAN_BL_PAGEDOWN (0x51|0x80)
+#define SCAN_BL_CURSORRIGHT (0x4D|0x80)
+
+#define SCAN_SCROLLLOCK 0x46
+/* Keys often found in the key pad area. */
+#define SCAN_NUMLOCK 0x45
+#define SCAN_HOME 0x47
+#define SCAN_CURSORLEFT 0x4B
+#define SCAN_END 0x4F
+#define SCAN_SLASH 0x35
+#define SCAN_CURSORUP 0x48
+#define SCAN_CENTER 0x4C
+#define SCAN_CURSORDOWN 0x50
+#define SCAN_INSERT 0x52
+#define SCAN_PAUSE 0xC5
+#define SCAN_ASTERISK 0x37
+#define SCAN_PAGEUP 0x49
+#define SCAN_CURSORRIGHT 0x4D
+#define SCAN_PAGEDOWN 0x51
+#define SCAN_DELETE 0x53
+#define SCAN_KP_MINUS 0x4A
+#define SCAN_KP_PLUS 0x4E
+#define SCAN_KP_ENTER 0x1C
+
+#define SCAN_ESCAPE 0x01
+#define SCAN_F1 0x3B
+#define SCAN_F2 0x3C
+#define SCAN_F3 0x3D
+#define SCAN_F4 0x3E
+#define SCAN_F5 0x3F
+#define SCAN_F6 0x40
+#define SCAN_F7 0x41
+#define SCAN_F8 0x42
+#define SCAN_F9 0x43
+#define SCAN_F10 0x44
+#define SCAN_F11 0x57
+#define SCAN_F12 0x58
+
+#define MK_COUNT 256
+#define MK(k) SCAN_##k
+
+#endif
diff --git a/drivers/pc/main.c b/drivers/pc/main.c
new file mode 100644
index 00000000..6bdd7ce7
--- /dev/null
+++ b/drivers/pc/main.c
@@ -0,0 +1,553 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "main.h"
+#include "throttle.h"
+
+#include "../common/cheat.h"
+
+#include "input.h"
+#include "dface.h"
+
+extern int32 fps_scale;
+
+int CloseGame(void);
+
+static char *soundrecfn=0; /* File name of sound recording. */
+
+static int ntsccol=0,ntschue=0,ntsctint=0;
+int soundvol=100;
+long soundq=0;
+int _sound=1;
+long soundrate=48000;
+#ifdef WIN32
+long soundbufsize=52;
+#else
+long soundbufsize=24;
+#endif
+
+#ifdef FRAMESKIP
+static int frameskip=0;
+#endif
+static int inited=0;
+static int isloaded=0; // Is game loaded?
+
+int srendlinev[2]={8,0};
+int erendlinev[2]={231,239};
+
+
+static uint8 *DrBaseDirectory;
+
+int eoptions=0;
+
+static void DriverKill(void);
+static int DriverInitialize(FCEUGI *gi);
+int gametype;
+
+FCEUGI *CurGame=NULL;
+
+static void ParseGI(FCEUGI *gi)
+{
+ ParseGIInput(gi);
+ gametype=gi->type;
+}
+
+#ifndef EXTGUI
+void FCEUD_PrintError(char *s)
+{
+ puts(s);
+}
+
+void FCEUD_Message(char *s)
+{
+ fputs(s,stdout);
+}
+#endif
+
+static char *cpalette=0;
+static void LoadCPalette(void)
+{
+ uint8 tmpp[192];
+ FILE *fp;
+
+ if(!(fp=FCEUD_UTF8fopen(cpalette,"rb")))
+ {
+ printf(" Error loading custom palette from file: %s\n",cpalette);
+ return;
+ }
+ fread(tmpp,1,192,fp);
+ FCEUI_SetPaletteArray(tmpp);
+ fclose(fp);
+}
+#ifdef EXTGUI
+extern CFGSTRUCT GUIConfig;
+#endif
+static CFGSTRUCT fceuconfig[]={
+ AC(soundrate),
+ AC(soundq),
+ AC(_sound),
+ AC(soundvol),
+ AC(soundbufsize),
+ ACS(cpalette),
+ AC(ntsctint),
+ AC(ntschue),
+ AC(ntsccol),
+ AC(eoptions),
+ ACA(srendlinev),
+ ACA(erendlinev),
+ ADDCFGSTRUCT(InputConfig),
+ ADDCFGSTRUCT(DriverConfig),
+ #ifdef EXTGUI
+ ADDCFGSTRUCT(GUIConfig),
+ #endif
+ ENDCFGSTRUCT
+};
+
+static void SaveConfig(void)
+{
+ char tdir[2048];
+ sprintf(tdir,"%s"PSS"fceu98.cfg",DrBaseDirectory);
+ FCEUI_GetNTSCTH(&ntsctint, &ntschue);
+ SaveFCEUConfig(tdir,fceuconfig);
+}
+
+static void LoadConfig(void)
+{
+ char tdir[2048];
+ sprintf(tdir,"%s"PSS"fceu98.cfg",DrBaseDirectory);
+ FCEUI_GetNTSCTH(&ntsctint, &ntschue); /* Get default settings for if
+ no config file exists. */
+ LoadFCEUConfig(tdir,fceuconfig);
+ InputUserActiveFix();
+}
+
+static void CreateDirs(void)
+{
+ char *subs[7]={"fcs","fcm","snaps","gameinfo","sav","cheats","movie"};
+ char tdir[2048];
+ int x;
+
+ #ifdef WIN32
+ mkdir(DrBaseDirectory);
+ for(x=0;x<6;x++)
+ {
+ sprintf(tdir,"%s"PSS"%s",DrBaseDirectory,subs[x]);
+ mkdir(tdir);
+ }
+ #else
+ mkdir(DrBaseDirectory,S_IRWXU);
+ for(x=0;x<6;x++)
+ {
+ sprintf(tdir,"%s"PSS"%s",DrBaseDirectory,subs[x]);
+ mkdir(tdir,S_IRWXU);
+ }
+ #endif
+}
+
+#ifndef WIN32
+static void SetSignals(void (*t)(int))
+{
+ int sigs[11]={SIGINT,SIGTERM,SIGHUP,SIGPIPE,SIGSEGV,SIGFPE,SIGKILL,SIGALRM,SIGABRT,SIGUSR1,SIGUSR2};
+ int x;
+ for(x=0;x<11;x++)
+ signal(sigs[x],t);
+}
+
+static void CloseStuff(int signum)
+{
+ DriverKill();
+ printf("\nSignal %d has been caught and dealt with...\n",signum);
+ switch(signum)
+ {
+ case SIGINT:printf("How DARE you interrupt me!\n");break;
+ case SIGTERM:printf("MUST TERMINATE ALL HUMANS\n");break;
+ case SIGHUP:printf("Reach out and hang-up on someone.\n");break;
+ case SIGPIPE:printf("The pipe has broken! Better watch out for floods...\n");break;
+ case SIGSEGV:printf("Iyeeeeeeeee!!! A segmentation fault has occurred. Have a fluffy day.\n");break;
+ /* So much SIGBUS evil. */
+ #ifdef SIGBUS
+ #if(SIGBUS!=SIGSEGV)
+ case SIGBUS:printf("I told you to be nice to the driver.\n");break;
+ #endif
+ #endif
+ case SIGFPE:printf("Those darn floating points. Ne'er know when they'll bite!\n");break;
+ case SIGALRM:printf("Don't throw your clock at the meowing cats!\n");break;
+ case SIGABRT:printf("Abort, Retry, Ignore, Fail?\n");break;
+ case SIGUSR1:
+ case SIGUSR2:printf("Killing your processes is not nice.\n");break;
+ }
+ exit(1);
+}
+#endif
+
+static void DoArgs(int argc, char *argv[])
+{
+ int x;
+
+ static ARGPSTRUCT FCEUArgs[]={
+ {"-soundbufsize",0,&soundbufsize,0},
+ {"-soundrate",0,&soundrate,0},
+ {"-soundq",0,&soundq,0},
+#ifdef FRAMESKIP
+ {"-frameskip",0,&frameskip,0},
+#endif
+ {"-sound",0,&_sound,0},
+ {"-soundvol",0,&soundvol,0},
+ {"-cpalette",0,&cpalette,0x4001},
+ {"-soundrecord",0,&soundrecfn,0x4001},
+
+ {"-ntsccol",0,&ntsccol,0},
+ {"-pal",0,&eoptions,0x8000|EO_PAL},
+
+ {"-lowpass",0,&eoptions,0x8000|EO_LOWPASS},
+ {"-gg",0,&eoptions,0x8000|EO_GAMEGENIE},
+ {"-no8lim",0,&eoptions,0x8001},
+ {"-snapname",0,&eoptions,0x8000|EO_SNAPNAME},
+ {"-nofs",0,&eoptions,0x8000|EO_NOFOURSCORE},
+ {"-clipsides",0,&eoptions,0x8000|EO_CLIPSIDES},
+ {"-nothrottle",0,&eoptions,0x8000|EO_NOTHROTTLE},
+ {"-slstart",0,&srendlinev[0],0},{"-slend",0,&erendlinev[0],0},
+ {"-slstartp",0,&srendlinev[1],0},{"-slendp",0,&erendlinev[1],0},
+ {0,(int *)InputArgs,0,0},
+ {0,(int *)DriverArgs,0,0},
+ {0,0,0,0}
+ };
+
+ ParseArguments(argc, argv, FCEUArgs);
+ if(cpalette)
+ {
+ if(cpalette[0]=='0')
+ if(cpalette[1]==0)
+ {
+ free(cpalette);
+ cpalette=0;
+ }
+ }
+ FCEUI_SetVidSystem((eoptions&EO_PAL)?1:0);
+ FCEUI_SetGameGenie((eoptions&EO_GAMEGENIE)?1:0);
+ FCEUI_SetLowPass((eoptions&EO_LOWPASS)?1:0);
+
+ FCEUI_DisableSpriteLimitation(eoptions&1);
+ FCEUI_SetSnapName(eoptions&EO_SNAPNAME);
+
+ for(x=0;x<2;x++)
+ {
+ if(srendlinev[x]<0 || srendlinev[x]>239) srendlinev[x]=0;
+ if(erendlinev[x]<srendlinev[x] || erendlinev[x]>239) erendlinev[x]=239;
+ }
+
+ FCEUI_SetRenderedLines(srendlinev[0],erendlinev[0],srendlinev[1],erendlinev[1]);
+ DoDriverArgs();
+}
+
+#include "usage.h"
+
+/* Loads a game, given a full path/filename. The driver code must be
+ initialized after the game is loaded, because the emulator code
+ provides data necessary for the driver code(number of scanlines to
+ render, what virtual input devices to use, etc.).
+*/
+int LoadGame(const char *path)
+{
+ FCEUGI *tmp;
+
+ CloseGame();
+ if(!(tmp=FCEUI_LoadGame(path,1)))
+ return 0;
+ CurGame=tmp;
+ ParseGI(tmp);
+ RefreshThrottleFPS();
+
+ if(!DriverInitialize(tmp))
+ return(0);
+ if(soundrecfn)
+ {
+ if(!FCEUI_BeginWaveRecord(soundrecfn))
+ {
+ free(soundrecfn);
+ soundrecfn=0;
+ }
+ }
+ isloaded=1;
+ #ifdef EXTGUI
+ if(eoptions&EO_AUTOHIDE) GUI_Hide(1);
+ #endif
+
+ FCEUD_NetworkConnect();
+ return 1;
+}
+
+/* Closes a game. Frees memory, and deinitializes the drivers. */
+int CloseGame(void)
+{
+ if(!isloaded) return(0);
+ FCEUI_CloseGame();
+ DriverKill();
+ isloaded=0;
+ CurGame=0;
+
+ if(soundrecfn)
+ FCEUI_EndWaveRecord();
+
+ #ifdef EXTGUI
+ GUI_Hide(0);
+ #endif
+ InputUserActiveFix();
+ return(1);
+}
+
+void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count);
+
+void DoFun(void)
+{
+ uint8 *gfx;
+ int32 *sound;
+ int32 ssize;
+ static int fskipc=0;
+ static int opause=0;
+
+ #ifdef FRAMESKIP
+ fskipc=(fskipc+1)%(frameskip+1);
+ #endif
+
+ if(NoWaiting) {gfx=0;}
+ FCEUI_Emulate(&gfx, &sound, &ssize, fskipc);
+ FCEUD_Update(gfx, sound, ssize);
+
+ if(opause!=FCEUI_EmulationPaused())
+ {
+ opause=FCEUI_EmulationPaused();
+ SilenceSound(opause);
+ }
+}
+
+int CLImain(int argc, char *argv[])
+{
+ int ret;
+
+ if(!(ret=FCEUI_Initialize()))
+ return(0);
+
+ DrBaseDirectory=GetBaseDirectory();
+ FCEUI_SetBaseDirectory(DrBaseDirectory);
+
+ CreateDirs();
+
+ #ifdef EXTGUI
+ if(argc==2 && !strcmp(argv[1],"-help")) // I hope no one has a game named "-help" :b
+ #else
+ if(argc<=1)
+ #endif
+ {
+ ShowUsage(argv[0]);
+ return(0);
+ }
+
+ LoadConfig();
+ DoArgs(argc-2,&argv[1]);
+ FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
+ if(cpalette)
+ LoadCPalette();
+
+ /* All the config files and arguments are parsed now. */
+ #ifdef EXTGUI
+ return(1);
+
+ #else
+ if(!LoadGame(argv[argc-1]))
+ {
+ DriverKill();
+ return(0);
+ }
+
+ while(CurGame)
+ DoFun();
+
+ #if(0)
+ {
+ int x;
+ for(x=1;x<argc;x++)
+ { LoadGame(argv[x]); while(CurGame) DoFun(); }
+ }
+ #endif
+
+ CloseGame();
+
+ SaveConfig();
+
+ FCEUI_Kill();
+
+ #endif
+ return(1);
+}
+
+static int DriverInitialize(FCEUGI *gi)
+{
+ #ifndef WIN32
+ SetSignals(CloseStuff);
+ #endif
+
+ /* Initialize video before all else, due to some wacko dependencies
+ in the SexyAL code(DirectSound) that need to be fixed.
+ */
+
+ if(!InitVideo(gi)) return 0;
+ inited|=4;
+
+ if(InitSound(gi))
+ inited|=1;
+
+ if(InitJoysticks())
+ inited|=2;
+
+ if(!InitKeyboard()) return 0;
+ inited|=8;
+
+ InitOtherInput();
+ return 1;
+}
+
+static void DriverKill(void)
+{
+ SaveConfig();
+
+ #ifndef WIN32
+ SetSignals(SIG_IGN);
+ #endif
+
+ if(inited&2)
+ KillJoysticks();
+ if(inited&8)
+ KillKeyboard();
+ if(inited&4)
+ KillVideo();
+ if(inited&1)
+ KillSound();
+ if(inited&16)
+ KillMouse();
+ inited=0;
+}
+
+void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count)
+{
+ #ifdef NETWORK
+ extern int FCEUDnetplay;
+ #endif
+
+ int ocount = Count;
+ // apply frame scaling to Count
+ Count = (Count<<8)/fps_scale;
+ if(Count)
+ {
+ int32 can=GetWriteSound();
+ static int uflow=0;
+ int32 tmpcan;
+
+ // don't underflow when scaling fps
+ if(can >= GetMaxSound() && fps_scale<=256) uflow=1; /* Go into massive underflow mode. */
+
+ if(can > Count) can=Count;
+ else uflow=0;
+
+ WriteSound(Buffer,can);
+
+ //if(uflow) puts("Underflow");
+ tmpcan = GetWriteSound();
+ // don't underflow when scaling fps
+ if(fps_scale>256 || ((tmpcan < Count*0.90) && !uflow))
+ {
+ if(XBuf && (inited&4) && !(NoWaiting & 2))
+ BlitScreen(XBuf);
+ Buffer+=can;
+ Count-=can;
+ if(Count)
+ {
+ if(NoWaiting)
+ {
+ can=GetWriteSound();
+ if(Count>can) Count=can;
+ WriteSound(Buffer,Count);
+ }
+ else
+ {
+ while(Count>0)
+ {
+ WriteSound(Buffer,(Count<ocount) ? Count : ocount);
+ Count -= ocount;
+ }
+ }
+ }
+ } //else puts("Skipped");
+ #ifdef NETWORK
+ else if(!NoWaiting && FCEUDnetplay && (uflow || tmpcan >= (Count * 1.8)))
+ {
+ if(Count > tmpcan) Count=tmpcan;
+ while(tmpcan > 0)
+ {
+// printf("Overwrite: %d\n", (Count <= tmpcan)?Count : tmpcan);
+ WriteSound(Buffer, (Count <= tmpcan)?Count : tmpcan);
+ tmpcan -= Count;
+ }
+ }
+ #endif
+
+ }
+ else
+ {
+ if(!NoWaiting && (!(eoptions&EO_NOTHROTTLE) || FCEUI_EmulationPaused()))
+ SpeedThrottle();
+ if(XBuf && (inited&4))
+ {
+ BlitScreen(XBuf);
+ }
+ }
+ FCEUD_UpdateInput();
+ //if(!Count && !NoWaiting && !(eoptions&EO_NOTHROTTLE))
+ // SpeedThrottle();
+ //if(XBuf && (inited&4))
+ //{
+ // BlitScreen(XBuf);
+ //}
+ //if(Count)
+ // WriteSound(Buffer,Count,NoWaiting);
+ //FCEUD_UpdateInput();
+}
+
+
+/* Maybe ifndef WXWINDOWS would be better? ^_^ */
+#ifndef EXTGUI
+FILE *FCEUD_UTF8fopen(const char *fn, const char *mode)
+{
+ return(fopen(fn,mode));
+}
+
+
+#endif
diff --git a/drivers/pc/main.h b/drivers/pc/main.h
new file mode 100644
index 00000000..505eaf04
--- /dev/null
+++ b/drivers/pc/main.h
@@ -0,0 +1,55 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../../driver.h"
+#include "../common/config.h"
+#include "../common/args.h"
+
+extern int eoptions;
+#define EO_NO8LIM 1
+#define EO_SUBASE 2
+#define EO_CLIPSIDES 8
+#define EO_SNAPNAME 16
+#define EO_NOFOURSCORE 32
+#define EO_NOTHROTTLE 64
+#define EO_GAMEGENIE 128
+#define EO_PAL 256
+#define EO_LOWPASS 512
+#define EO_AUTOHIDE 1024
+
+extern int srendlinev[2],erendlinev[2];
+extern int NoWaiting;
+
+extern int soundvol;
+extern long soundq;
+extern int _sound;
+extern long soundrate;
+extern long soundbufsize;
+
+int CLImain(int argc, char *argv[]);
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/drivers/pc/sdl-icon.h b/drivers/pc/sdl-icon.h
new file mode 100644
index 00000000..3a563d0b
--- /dev/null
+++ b/drivers/pc/sdl-icon.h
@@ -0,0 +1,134 @@
+static const struct {
+ unsigned int width;
+ unsigned int height;
+ unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */
+ uint8 pixel_data[32 * 32 * 3 + 1];
+} fceu_playicon = {
+ 32, 32, 3,
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223"
+ "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
+ "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
+ "\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
+ "\373\\\223\373\\\223\373\0\0\0\0\0\0\0\0\0\\\223\373\\\223\373\267\317\373"
+ "\246\304\373\260\312\373\222\267\373\246\304\373\\\223\373\\\223\373\\\223"
+ "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
+ "\267\317\373\246\304\373\260\312\373\210\261\373\246\304\373\\\223\373\\"
+ "\223\373\210\261\373\222\267\373\267\317\373\241\301\373\\\223\373\\\223"
+ "\373\0\0\0\0\0\0\\\223\373\\\223\373\227\272\373\227\272\373\227\272\373"
+ "\227\272\373\227\272\373\227\272\373\\\223\373\\\223\373z`sr\242\373\227"
+ "\272\373\227\272\373\\\223\373\\\223\373\\\223\373\\\223\373\213\261\373"
+ "z\247\373\213\261\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
+ "\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\"
+ "\223\373\\\223\373\313i=\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40"
+ "\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40"
+ "\315Z\40\315Z\40\315Z\40\315Z\40\315Z\40\257T*\\\223\373\\\223\373\\\223"
+ "\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40"
+ "\355\235\203\355\235\203\341\232\205\341\232\205\365\255\233\355\235\203"
+ "\355\235\203\350\250\232\365\255\233\355\235\203\307L\14\307L\14\307L\14"
+ "\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256B\12\\\223\373"
+ "\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373"
+ "\\\223\373\315Z\40\273zc\233l_\325\225\205\325\225\205\325\225\205\273\212"
+ "\201\325\225\205\237qd\325\225\205\317\231\216\307L\14\307L\14\307L\14\307"
+ "L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256B\12\\\223\373\\"
+ "\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\"
+ "\223\373\315Z\40\344\232\203\301\215\201\344\232\203\273\212\201\325\225"
+ "\205\2114\10\344\232\203\350\250\232\325\225\205\333\230\205\307L\14\307"
+ "L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\256"
+ "B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223"
+ "\373\\\223\373\\\223\373\315Z\40\2259\11}0\10\2259\11}0\10}0\10\307L\14\225"
+ "9\11d&\6}0\10}0\10\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14\307L\14"
+ "\307L\14\307L\14\307L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373"
+ "\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40\355\235\203"
+ "\355\233\201\355\235\203\355\235\203\355\235\203\365\255\233\355\235\203"
+ "\341\232\205\355\235\203\355\235\203\307L\14\365\255\233\355\235\203\365"
+ "\255\233\355\235\203\355\235\203\355\235\203\355\235\203\355\235\203\307"
+ "L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373"
+ "\\\223\373\\\223\373\\\223\373\315Z\40\325\225\205\311\221\204\311\221\204"
+ "\325\225\205\311\221\204\325\225\205\311\221\204\325\225\205\325\225\205"
+ "\311\221\204\307L\14\325\225\205\311\221\204\325\225\205\311\221\204\325"
+ "\225\205\311\221\204\325\225\205\311\221\204\307L\14\256B\12\\\223\373\\"
+ "\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\"
+ "\223\373\315Z\40\325\225\205\325\225\205\325\225\205\325\225\205\325\225"
+ "\205\325\225\205\317\231\216\325\225\205\325\225\205\325\225\205\307L\14"
+ "\325\225\205\317\231\216\325\225\205\317\231\216\325\225\205\325\225\205"
+ "\273zc\241n_\307L\14\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0"
+ "\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\315Z\40\325\225\205\325"
+ "\225\205\325\225\205\365\255\233\333\243\231\325\225\205\333\230\205\325"
+ "\225\205\325\225\205\325\225\205\307L\14\325\225\205\317\223\204\325\225"
+ "\205\333\230\205\325\225\205\325\225\205\333\230\205\317\223\204\307L\14"
+ "\256B\12\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\"
+ "\223\373\\\223\373\\\223\373\315Z\40\325\225\205\325\225\205\325\225\205"
+ "\325\225\205\311\221\204\325\225\205\325\225\205\325\225\205\344\232\203"
+ "\273\212\201\307L\14\325\225\205\273\212\201\325\225\205\325\225\205\344"
+ "\232\203\273\212\201\344\232\203\273\212\201\341\232\205\256B\12\\\223\373"
+ "\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373"
+ "\\\223\373\257T*d&\6d&\6d&\6d&\6d&\6d&\6d&\6d&\6}0\10d&\6\256B\12d&\6p+\7"
+ "d&\6d&\6}0\10d&\6}0\10d&\6d&\6\223@\26\\\223\373\\\223\373\\\223\373\\\223"
+ "\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
+ "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\234\243"
+ "\335\213\237\344\237\244\333\251\247\326\237\244\333\\\223\373\267\252\317"
+ "\222\241\341\267\252\317\210\237\346\241\245\332\267\252\317\246\246\327"
+ "\246\246\327\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373"
+ "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
+ "\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
+ "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
+ "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0"
+ "\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
+ "\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
+ "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
+ "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
+ "\223\373\\\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\"
+ "\223\373\\\223\373\\\223\373\\\223\373\257hT\\\223\373\213\261\373\\\223"
+ "\373\241\301\373\210\261\373\246\304\373\222\267\373\241\301\373\260\312"
+ "\373\\\223\373\237\277\373\246\304\373\267\317\373\241\301\373\\\223\373"
+ "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0"
+ "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
+ "\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
+ "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
+ "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
+ "\223\373\0\0\0\0\0\0\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
+ "\223\373\\\223\373\\\223\373\\\223\373\\\223\373\246\304\373\\\223\373\241"
+ "\301\373\210\261\373\246\304\373\222\267\373\241\301\373\260\312\373\\\223"
+ "\373\237\277\373\246\304\373\267\317\373\241\301\373\\\223\373\\\223\373"
+ "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0\0\0\0\0\\\223\373"
+ "\\\223\373\\\223\373D\203\270D\203\270\\\223\373\\\223\373\\\223\373\\\223"
+ "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
+ "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
+ "\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\0\0"
+ "\0\0\0\0\\\223\373\\\223\373(\211n\0\247\0\0n\0(\211n\\\223\373\\\223\373"
+ "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
+ "\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223"
+ "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
+ "\0\0\0\0\0\0\\\223\373(\211n\0\247\0\0\247\0\0\247\0\0\247\0(\211n\\\223"
+ "\373\\\223\373\\\223\373\\\223\373\210\261\373\246\304\373\241\301\373z\247"
+ "\373\\\223\373\227\272\373\227\272\373\227\272\373\227\272\373\227\272\373"
+ "\227\272\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
+ "\\\223\373\\\223\373\0\0\0\0\0\0(\211n\0\247\0\0n\0\0\247\0\\\215\12fs\16"
+ "\0\247\0(\211n\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
+ "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\"
+ "\223\373\\\223\373Z\231Z[\230SZ\231Z[\230SZ\231Z[\230S\\\223\373\0\0\0\0"
+ "\0\0\0\247\0\0\247\0\0\247\0\0\247\0vy\7p|\7\0\247\0\0\247\0(\211n\\\223"
+ "\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373"
+ "\\\223\373\\\223\373\\\223\373\\\223\373\\\223\373b\237L\200\317\20\200\317"
+ "\20\200\317\20\200\317\20\200\317\20\200\317\20[\223H\0\0\0\0\0\0\230P.\323"
+ "d0\230P.\323d0\221M&\313`%\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323"
+ "d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323d0\230P.\323"
+ "d0\230P.\323d0\230P.\323d0\0\0\0\0\0\0\0\0\0\237N(\225E\35\237N(\225E\35"
+ "\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237"
+ "N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N(\225E\35\237N("
+ "\225E\35\237N(\225E\35\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
+ "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0",
+};
+
diff --git a/drivers/pc/sdl-joystick.c b/drivers/pc/sdl-joystick.c
new file mode 100644
index 00000000..97f121f1
--- /dev/null
+++ b/drivers/pc/sdl-joystick.c
@@ -0,0 +1,99 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ * Copyright (C) 2002 Paul Kuliniewicz
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* PK: SDL joystick input stuff */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include "sdl.h"
+
+#define MAX_JOYSTICKS 32
+static SDL_Joystick *Joysticks[MAX_JOYSTICKS] = {NULL};
+
+int DTestButtonJoy(ButtConfig *bc)
+{
+ int x;
+
+ for(x=0;x<bc->NumC;x++)
+ {
+ if(bc->ButtonNum[x]&0x8000) /* Axis "button" */
+ {
+ int pos;
+ pos = SDL_JoystickGetAxis(Joysticks[bc->DeviceNum[x]], bc->ButtonNum[x]&16383);
+ if ((bc->ButtonNum[x]&0x4000) && pos <= -16383)
+ return(1);
+ else if (!(bc->ButtonNum[x]&0x4000) && pos >= 16363)
+ return(1);
+ }
+ else if(bc->ButtonNum[x]&0x2000) /* Hat "button" */
+ {
+ if( SDL_JoystickGetHat(Joysticks[bc->DeviceNum[x]],(bc->ButtonNum[x]>>8)&0x1F) & (bc->ButtonNum[x]&0xFF))
+ return(1);
+ }
+ else
+ if(SDL_JoystickGetButton(Joysticks[bc->DeviceNum[x]], bc->ButtonNum[x] ))
+ return(1);
+ }
+ return(0);
+}
+
+static int jinited=0;
+
+/* Cleanup opened joysticks. */
+int KillJoysticks (void)
+{
+ int n; /* joystick index */
+
+ if(!jinited) return(0);
+ for (n = 0; n < MAX_JOYSTICKS; n++)
+ {
+ if (Joysticks[n] != 0)
+ SDL_JoystickClose(Joysticks[n]);
+ Joysticks[n]=0;
+ }
+ SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
+ return(1);
+}
+
+/* Initialize joysticks. */
+int InitJoysticks (void)
+{
+ int n; /* joystick index */
+ int total;
+
+ SDL_InitSubSystem(SDL_INIT_JOYSTICK);
+ total=SDL_NumJoysticks();
+ if(total>MAX_JOYSTICKS) total=MAX_JOYSTICKS;
+
+ for (n = 0; n < total; n++)
+ {
+ /* Open the joystick under SDL. */
+ Joysticks[n] = SDL_JoystickOpen(n);
+ //printf("Could not open joystick %d: %s.\n",
+ //joy[n] - 1, SDL_GetError());
+ continue;
+ }
+ jinited=1;
+ return(1);
+}
diff --git a/drivers/pc/sdl-netplay.c b/drivers/pc/sdl-netplay.c
new file mode 100644
index 00000000..83de4ba5
--- /dev/null
+++ b/drivers/pc/sdl-netplay.c
@@ -0,0 +1,224 @@
+#include "sdl.h"
+#include <SDL/SDL_net.h>
+#include "sdl-netplay.h"
+
+char *ServerHost;
+
+static int LocalPortTCP=0xFCE;
+static int LocalPortUDP=0xFCE;
+static int RemotePortTCP=0xFCE;
+
+static int RemotePortUDP; /* Not configurable, figured out during handshake. */
+
+static TCPsocket Socket;
+static UDPsocket UDPSocket;
+static SDLNet_SocketSet set;
+
+
+static void en32(uint8 *buf, uint32 morp)
+{
+ buf[0]=morp;
+ buf[1]=morp>>8;
+ buf[2]=morp>>16;
+ buf[3]=morp>>24;
+}
+
+static uint32 de32(uint8 *morp)
+{
+ return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24));
+}
+
+
+
+int FCEUD_NetworkConnect(void)
+{
+ IPaddress rip;
+
+ SDLNet_Init();
+
+ if(netplay==1) /* Be a server. */
+ {
+ TCPsocket tmp;
+ Uint16 p=LocalPortUDP;
+
+ SDLNet_ResolveHost(&rip,NULL,LocalPortTCP);
+
+ UDPSocket=SDLNet_UDP_Open(&p);
+
+ tmp=SDLNet_TCP_Open(&rip);
+ Socket=SDLNet_TCP_Accept(&tmp);
+
+ memcpy(&rip,SDLNet_TCP_GetPeerAddress(Socket),sizeof(IPaddress));
+
+ {
+ uint8 buf[12];
+ uint32 player=1;
+
+ magic=SDL_GetTicks();
+
+ SDLNet_Write32(buf,uport);
+ SDLNet_Write32(buf+4,1);
+ SDLNet_Write32(buf+8,magic);
+
+ SDLNet_TCP_Send(Socket, buf, 12);
+
+ /* Get the UDP port the client is waiting for data on. */
+ SDLNet_TCP_Recv(Socket, buf, 2);
+ RemotePortUDP=de32(buf);
+ }
+ }
+ else /* Be a client */
+ {
+ SDLNet_ResolveHost(&rip,ServerHost,RemotePortTCP);
+ Socket=SDLNet_TCP_Open(&rip);
+
+ {
+ Uint16 p=LocalPortUDP;
+ uint8 buf[12];
+
+ UDPSocket=SDLNet_UDP_Open(&p);
+
+ /* Now, tell the server what local UDP port it should send to. */
+ en32(buf,p);
+ SDLNet_TCP_Send(Socket, buf, 4);
+
+ /* Get the UDP port from the server we should send data to. */
+ SDLNet_TCP_Recv(Socket, buf, 12);
+ RemotePortUDP=de32(buf);
+ magic=de32(buf+8);
+ }
+ set=SDLNet_AllocSocketSet(1);
+ SDLNet_TCP_AddSocket(set,TCPSocket);
+ SDLNet_UDP_AddSocket(set,UDPSocket);
+ } // End client connect code.
+
+ rip.port=RemotePortUDP;
+ SDLNet_UDP_Bind(UDPSocket, 0, &rip);
+}
+
+
+
+
+static int CheckUDP(uint8 *packet, int32 len, int32 alt)
+{
+ uint32 crc;
+ uint32 repcrc;
+
+ crc=FCEUI_CRC32(0,packet+4,len+8);
+ repcrc=de32(packet);
+
+ if(crc!=repcrc) return(0); /* CRC32 mismatch, bad packet. */
+ packet+=4;
+
+ if(de32(packet)!=magic) /* Magic number mismatch, bad or spoofed packet. */
+ return(0);
+
+ packet+=4;
+ if(alt)
+ {
+ if(de32(packet)<incounter) /* Time warped packet. */
+ return(0);
+ }
+ else
+ if(de32(packet)!=incounter) /* Time warped packet. */
+ return(0);
+ return(1);
+}
+
+
+/* Be careful where these MakeXXX() functions are used. */
+static uint8 *MakeUDP(uint8 *data, int32 len)
+{
+ /* UDP packet data header is 12 bytes in length. */
+ static uint8 buf[12+32]; // arbitrary 32.
+
+ en32(buf+4,magic);
+ en32(buf+8,outcounter);
+ memcpy(buf+12,data,len);
+ en32(buf,FCEUI_CRC32(0,buf+4,8+len));
+ return(buf);
+}
+
+static uint8 *MakeTCP(uint8 *data, int32 len)
+{
+ /* TCP packet data header is 4 bytes in length. */
+ static uint8 buf[4+32]; // arbitrary 32.
+
+ en32(buf,outcounter);
+ memcpy(buf+4,data,len);
+ return(buf);
+}
+
+#define UDPHEADSIZE 12
+#define TCPHEADSIZE 4
+
+void FCEUD_NetworkClose(void)
+{
+ SDLNet_Quit();
+}
+
+/* 1 byte to server */
+int FCEUD_SendDataToServer(uint8 v,uint8 cmd)
+{
+ UDPpacket upack;
+
+ upack.channel=0;
+ upack.data=MakeUDP(data,1);
+ upack.len=upack.maxlen=UDPHEADSIZE+1;
+ upack.status=0;
+
+ SDLNet_UDP_Send(UDPSocket,0,&upack);
+
+ outcounter++;
+ return(1);
+}
+
+void FCEUD_SendDataToClients(uint8 *data)
+{
+ UDPpacket upack;
+
+ SDLNet_TCP_Send(Socket,MakeTCP(data,5),TCPHEADSIZE+5);
+
+ upack.channel=0;
+ upack.data=MakeUDP(data,5);
+ upack.len=upack.maxlen=UDPHEADSIZE+5;
+ upack.status=0;
+
+ SDLNet_UDP_Send(UDPSocket,0,&upack);
+
+ outcounter++;
+ return(1);
+}
+
+int FCEUD_GetDataFromServer(uint8 *data)
+{
+ uint8 buf[128];
+ NoWaiting&=~2;
+
+ while(SDLNet_CheckSockets(set,1)==0)
+ {
+ // do something here.
+ }
+ if(SDLNet_SocketReady(Socket))
+ {
+ SDLNet_TCP_Recv
+ if(de32(buf)==incounter) /* New packet, keep. */
+ {
+ unsigned long beefie;
+ memcpy(data,buf+TCPHEADSIZE,5);
+ incounter++;
+
+ if(!ioctl(Socket,FIONREAD,&beefie))
+ if(beefie)
+ NoWaiting|=2;
+
+ return(1);
+ }
+
+ }
+ if(SDLNet_SocketReady(UDPSocket)
+ {
+
+
+ }
+}
diff --git a/drivers/pc/sdl-netplay.h b/drivers/pc/sdl-netplay.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/drivers/pc/sdl-netplay.h
diff --git a/drivers/pc/sdl-opengl.c b/drivers/pc/sdl-opengl.c
new file mode 100644
index 00000000..3a780a88
--- /dev/null
+++ b/drivers/pc/sdl-opengl.c
@@ -0,0 +1,241 @@
+#define GL_GLEXT_LEGACY
+#ifdef APPLEOPENGL
+#include <OpenGL/gl.h>
+#include <OpenGL/glu.h>
+#include <OpenGL/glext.h>
+#else
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glext.h>
+#endif
+#include <string.h>
+#include <stdlib.h>
+
+#include "sdl.h"
+#include "sdl-opengl.h"
+#include "../common/vidblit.h"
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+
+static GLuint textures[2]={0,0}; // Normal image, scanline overlay.
+
+static int left,right,top,bottom; // right and bottom are not inclusive.
+static int scanlines;
+static void *HiBuffer;
+
+void APIENTRY (*p_glBindTexture)(GLenum target,GLuint texture);
+void APIENTRY (*p_glColorTableEXT)(GLenum target, GLenum internalformat, GLsizei width, GLenum format, GLenum type, const GLvoid *table);
+void APIENTRY (*p_glTexImage2D)( GLenum target, GLint level,
+ GLint internalFormat,
+ GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type,
+ const GLvoid *pixels );
+void APIENTRY (*p_glBegin)(GLenum mode);
+void APIENTRY (*p_glVertex2f)(GLfloat x, GLfloat y);
+void APIENTRY (*p_glTexCoord2f)(GLfloat s, GLfloat t);
+void APIENTRY (*p_glEnd)(void);
+void APIENTRY (*p_glEnable)(GLenum cap);
+void APIENTRY (*p_glBlendFunc)(GLenum sfactor, GLenum dfactor);
+const GLubyte* APIENTRY (*p_glGetString)(GLenum name);
+void APIENTRY (*p_glViewport)(GLint x, GLint y,GLsizei width, GLsizei height);
+void APIENTRY (*p_glGenTextures)(GLsizei n, GLuint *textures);
+void APIENTRY (*p_glDeleteTextures)(GLsizei n,const GLuint *textures);
+void APIENTRY (*p_glTexParameteri)(GLenum target, GLenum pname, GLint param);
+void APIENTRY (*p_glClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+void APIENTRY (*p_glLoadIdentity)(void);
+void APIENTRY (*p_glClear)(GLbitfield mask);
+void APIENTRY (*p_glMatrixMode)(GLenum mode);
+void APIENTRY (*p_glDisable)(GLenum cap);
+
+void SetOpenGLPalette(uint8 *data)
+{
+ if(!HiBuffer)
+ {
+ p_glBindTexture(GL_TEXTURE_2D, textures[0]);
+ p_glColorTableEXT(GL_TEXTURE_2D,GL_RGB,256,GL_RGBA,GL_UNSIGNED_BYTE,data);
+ }
+ else
+ SetPaletteBlitToHigh((uint8*)data);
+}
+
+void BlitOpenGL(uint8 *buf)
+{
+ p_glBindTexture(GL_TEXTURE_2D, textures[0]);
+ if(HiBuffer)
+ {
+ static int xo=0;
+ xo=(xo+1)&3;
+ Blit8ToHigh(buf,(uint8*)HiBuffer,256,240,256*4,1,1);
+ if(!xo)
+ p_glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,256,256, 0, GL_RGBA,GL_UNSIGNED_BYTE,
+ HiBuffer);
+ }
+ else
+ {
+ //glPixelStorei(GL_UNPACK_ROW_LENGTH, 256);
+ p_glTexImage2D(GL_TEXTURE_2D, 0, GL_COLOR_INDEX8_EXT, 256, 256, 0,
+ GL_COLOR_INDEX,GL_UNSIGNED_BYTE,buf);
+ }
+
+ p_glBegin(GL_QUADS);
+ p_glTexCoord2f(1.0f*left/256, 1.0f*bottom/256); // Bottom left of our picture.
+ p_glVertex2f(-1.0f, -1.0f); // Bottom left of target.
+
+ p_glTexCoord2f(1.0f*right/256, 1.0f*bottom/256); // Bottom right of our picture.
+ p_glVertex2f( 1.0f, -1.0f); // Bottom right of target.
+
+ p_glTexCoord2f(1.0f*right/256, 1.0f*top/256); // Top right of our picture.
+ p_glVertex2f( 1.0f, 1.0f); // Top right of target.
+
+ p_glTexCoord2f(1.0f*left/256, 1.0f*top/256); // Top left of our picture.
+ p_glVertex2f(-1.0f, 1.0f); // Top left of target.
+ p_glEnd();
+
+ //glDisable(GL_BLEND);
+ if(scanlines)
+ {
+ p_glEnable(GL_BLEND);
+
+ p_glBindTexture(GL_TEXTURE_2D, textures[1]);
+ p_glBlendFunc(GL_DST_COLOR, GL_SRC_ALPHA);
+
+ p_glBegin(GL_QUADS);
+
+ p_glTexCoord2f(1.0f*left/256, 1.0f*bottom/256); // Bottom left of our picture.
+ p_glVertex2f(-1.0f, -1.0f); // Bottom left of target.
+
+ p_glTexCoord2f(1.0f*right/256, 1.0f*bottom/256); // Bottom right of our picture.
+ p_glVertex2f( 1.0f, -1.0f); // Bottom right of target.
+
+ p_glTexCoord2f(1.0f*right/256, 1.0f*top/256); // Top right of our picture.
+ p_glVertex2f( 1.0f, 1.0f); // Top right of target.
+
+ p_glTexCoord2f(1.0f*left/256, 1.0f*top/256); // Top left of our picture.
+ p_glVertex2f(-1.0f, 1.0f); // Top left of target.
+
+ p_glEnd();
+ p_glDisable(GL_BLEND);
+ }
+ SDL_GL_SwapBuffers();
+}
+
+void KillOpenGL(void)
+{
+ if(textures[0])
+ p_glDeleteTextures(2, &textures[0]);
+ textures[0]=0;
+ if(HiBuffer)
+ {
+ free(HiBuffer);
+ HiBuffer=0;
+ }
+}
+/* Rectangle, left, right(not inclusive), top, bottom(not inclusive). */
+
+int InitOpenGL(int l, int r, int t, int b, double xscale,double yscale, int efx, int ipolate,
+ int stretchx, int stretchy, SDL_Surface *screen)
+{
+ const char *extensions;
+
+ #define LFG(x) if(!(p_##x = SDL_GL_GetProcAddress(#x))) return(0);
+
+ #define LFGN(x) p_##x = SDL_GL_GetProcAddress(#x)
+
+ LFG(glBindTexture);
+ LFGN(glColorTableEXT);
+ LFG(glTexImage2D);
+ LFG(glBegin);
+ LFG(glVertex2f);
+ LFG(glTexCoord2f);
+ LFG(glEnd);
+ LFG(glEnable);
+ LFG(glBlendFunc);
+ LFG(glGetString);
+ LFG(glViewport);
+ LFG(glGenTextures);
+ LFG(glDeleteTextures);
+ LFG(glTexParameteri);
+ LFG(glClearColor);
+ LFG(glLoadIdentity);
+ LFG(glClear);
+ LFG(glMatrixMode);
+ LFG(glDisable);
+
+ left=l;
+ right=r;
+ top=t;
+ bottom=b;
+
+ HiBuffer=0;
+
+ extensions=(const char*)p_glGetString(GL_EXTENSIONS);
+
+ if((efx&2) || !extensions || !p_glColorTableEXT || !strstr(extensions,"GL_EXT_paletted_texture"))
+ {
+ if(!(efx&2)) // Don't want to print out a warning message in this case...
+ FCEU_printf("Paletted texture extension not found. Using slower texture format...");
+ HiBuffer=malloc(4*256*256);
+ memset(HiBuffer,0x00,4*256*256);
+ #ifndef LSB_FIRST
+ InitBlitToHigh(4,0xFF000000,0xFF0000,0xFF00,efx&2,0);
+ #else
+ InitBlitToHigh(4,0xFF,0xFF00,0xFF0000,efx&2,0);
+ #endif
+ }
+
+ {
+ int rw=(r-l)*xscale;
+ int rh=(b-t)*yscale;
+ int sx=(screen->w-rw)/2; // Start x
+ int sy=(screen->h-rh)/2; // Start y
+
+ if(stretchx) { sx=0; rw=screen->w; }
+ if(stretchy) { sy=0; rh=screen->h; }
+ p_glViewport(sx, sy, rw, rh);
+ }
+ p_glGenTextures(2, &textures[0]);
+ scanlines=0;
+
+ if(efx&1)
+ {
+ uint8 *buf;
+ int x,y;
+
+ scanlines=1;
+
+ p_glBindTexture(GL_TEXTURE_2D, textures[1]);
+ p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
+ p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
+
+ buf=(uint8*)malloc(256*(256*2)*4);
+
+ for(y=0;y<(256*2);y++)
+ for(x=0;x<256;x++)
+ {
+ buf[y*256*4+x*4]=0;
+ buf[y*256*4+x*4+1]=0;
+ buf[y*256*4+x*4+2]=0;
+ buf[y*256*4+x*4+3]=(y&1)?0x00:0xFF; //?0xa0:0xFF; // <-- Pretty
+ //buf[y*256+x]=(y&1)?0x00:0xFF;
+ }
+ p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, (scanlines==2)?256*4:512, 0,
+ GL_RGBA,GL_UNSIGNED_BYTE,buf);
+ free(buf);
+ }
+ p_glBindTexture(GL_TEXTURE_2D, textures[0]);
+
+ p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
+ p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,ipolate?GL_LINEAR:GL_NEAREST);
+ p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP);
+ p_glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP);
+ p_glEnable(GL_TEXTURE_2D);
+ p_glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // Background color to black.
+ p_glMatrixMode(GL_MODELVIEW);
+
+ p_glClear(GL_COLOR_BUFFER_BIT);
+ p_glLoadIdentity();
+
+ return(1);
+}
diff --git a/drivers/pc/sdl-opengl.h b/drivers/pc/sdl-opengl.h
new file mode 100644
index 00000000..ca786f53
--- /dev/null
+++ b/drivers/pc/sdl-opengl.h
@@ -0,0 +1,6 @@
+void SetOpenGLPalette(uint8 *data);
+void BlitOpenGL(uint8 *buf);
+void KillOpenGL(void);
+int InitOpenGL(int l, int r, int t, int b, double xscale,double yscale, int efx, int ipolate,
+ int stretchx, int stretchy, SDL_Surface *screen);
+
diff --git a/drivers/pc/sdl-sound.c b/drivers/pc/sdl-sound.c
new file mode 100644
index 00000000..f0b522c1
--- /dev/null
+++ b/drivers/pc/sdl-sound.c
@@ -0,0 +1,373 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "sdl.h"
+
+#ifdef USE_SEXYAL
+
+#include "../sexyal/sexyal.h"
+
+static SexyAL *Interface;
+static SexyAL_device *Output;
+static SexyAL_format format;
+static SexyAL_buffering buffering;
+
+uint32 GetMaxSound(void)
+{
+ return(buffering.totalsize);
+}
+
+uint32 GetWriteSound(void)
+{
+ return(Output->CanWrite(Output));
+}
+
+void WriteSound(int32 *Buffer, int Count)
+{
+ //printf("%d\n",Output->CanWrite(Output));
+ Output->Write(Output, Buffer, Count);
+}
+
+int InitSound(FCEUGI *gi)
+{
+ if(!_sound) return(0);
+
+ memset(&format,0,sizeof(format));
+ memset(&buffering,0,sizeof(buffering));
+
+ FCEUI_SetSoundVolume(soundvol);
+ FCEUI_SetSoundQuality(soundq);
+
+ Interface=SexyAL_Init(0);
+
+ format.sampformat=SEXYAL_FMT_PCMS32S16;
+ format.channels=gi->soundchan?gi->soundchan:1;
+ format.rate=gi->soundrate?gi->soundrate:soundrate;
+ buffering.fragcount=buffering.fragsize=0;
+ buffering.ms=soundbufsize;
+
+ FCEUI_printf("\nInitializing sound...");
+ if(!(Output=Interface->Open(Interface,SEXYAL_ID_UNUSED,&format,&buffering)))
+ {
+ FCEUD_PrintError("Error opening a sound device.");
+ Interface->Destroy(Interface);
+ Interface=0;
+ return(0);
+ }
+
+ if(soundq && format.rate!=48000 && format.rate!=44100 && format.rate!=96000)
+ {
+ FCEUD_PrintError("Set sound playback rate neither 44100, 48000, nor 96000, but needs to be when in high-quality sound mode.");
+ KillSound();
+ return(0);
+ }
+
+ if(format.rate<8192 || format.rate > 96000)
+ {
+ FCEUD_PrintError("Set rate is out of range [8192-96000]");
+ KillSound();
+ return(0);
+ }
+ FCEUI_printf("\n Bits: %u\n Rate: %u\n Channels: %u\n Byte order: CPU %s\n Buffer size: %u sample frames(%f ms)\n",(format.sampformat>>4)*8,format.rate,format.channels,format.byteorder?"Reversed":"Native",buffering.totalsize,(double)buffering.totalsize*1000/format.rate);
+
+ format.sampformat=SEXYAL_FMT_PCMS32S16;
+ format.channels=gi->soundchan?gi->soundchan:1;
+ format.byteorder=0;
+
+ //format.rate=gi->soundrate?gi->soundrate:soundrate;
+
+ Output->SetConvert(Output,&format);
+
+ FCEUI_Sound(format.rate);
+ return(1);
+}
+
+void SilenceSound(int n)
+{
+
+}
+
+int KillSound(void)
+{
+ FCEUI_Sound(0);
+ if(Output)
+ Output->Close(Output);
+ if(Interface)
+ Interface->Destroy(Interface);
+ Interface=0;
+ if(!Output) return(0);
+ Output=0;
+ return(1);
+}
+
+#elif USE_JACKACK /* Use JACK Audio Connection Kit */
+
+#include <jack/jack.h>
+#include <jack/ringbuffer.h>
+
+static jack_port_t *output_port = NULL;
+static jack_client_t *client = NULL;
+static jack_ringbuffer_t *tmpbuf = NULL;
+static unsigned int BufferSize;
+
+static int process(jack_nframes_t nframes, void *arg)
+{
+ jack_default_audio_sample_t *out = (jack_default_audio_sample_t *) jack_port_get_buffer(output_port, nframes);
+ size_t canread;
+
+ canread = jack_ringbuffer_read_space(tmpbuf) / sizeof(jack_default_audio_sample_t);
+
+ if(canread > nframes)
+ canread = nframes;
+
+ jack_ringbuffer_read(tmpbuf, out,canread * sizeof(jack_default_audio_sample_t));
+ nframes -= canread;
+
+ if(nframes) /* Buffer underflow. Hmm. */
+ {
+
+ }
+
+}
+
+uint32 GetMaxSound(void)
+{
+ return(BufferSize);
+}
+
+uint32 GetWriteSound(void)
+{
+ return(jack_readbuffer_write_space / sizeof(jack_default_audio_sample_t));
+}
+
+
+static void DeadSound(void *arg)
+{
+ puts("AGH! Sound server hates us! Let's go on a rampage.");
+}
+
+int InitSound(FCEUGI *gi)
+{
+ const char **ports;
+
+ client = jack_client_new("FCE Ultra");
+
+ jack_set_process_callback(client, process, 0);
+ jack_on_shutdown(client, DeadSound, 0);
+
+ printf("%ld\n",jack_get_sample_rate(client));
+
+ output_port = jack_port_register(client, "output", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0);
+
+ BufferSize = soundbufsize * soundrate / 1000;
+
+ tmpbuf = jack_ringbuffer_create(BufferSize * sizeof(jack_default_audio_sample_t));
+
+ jack_activate(client);
+
+
+ ports = jack_get_ports(client, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
+ jack_connect(client, jack_port_name(output_port), ports[0]);
+ free(ports);
+}
+
+void WriteSound(int32 *buf, int Count)
+{
+ jack_default_audio_sample_t jbuf[Count];
+ int x;
+
+ for(x=0;x<Count;x++,buf++)
+ jbuf[x] = *buf;
+
+ jack_ringbuffer_write(tmpbuf, jbuf, sizeof(jack_default_audio_sample_t) * Count);
+}
+
+void SilenceSound(int n)
+{
+
+
+}
+
+int KillSound(void)
+{
+ if(tmpbuf)
+ {
+ jack_ringbuffer_free(tmpbuf);
+ tmpbuf = NULL;
+ }
+ if(client)
+ {
+ jack_client_close(client);
+ client = NULL;
+ }
+ return(1);
+}
+
+#else /* So we'll use SDL's evil sound support. Ok. */
+static volatile int *Buffer = 0;
+static unsigned int BufferSize;
+static unsigned int BufferRead;
+static unsigned int BufferWrite;
+static volatile unsigned int BufferIn;
+
+static void fillaudio(void *udata, uint8 *stream, int len)
+{
+ int16 *tmps = (int16*)stream;
+ len >>= 1;
+
+ while(len)
+ {
+ int16 sample = 0;
+ if(BufferIn)
+ {
+ sample = Buffer[BufferRead];
+ BufferRead = (BufferRead + 1) % BufferSize;
+ BufferIn--;
+ }
+ else sample = 0;
+
+ *tmps = sample;
+ tmps++;
+ len--;
+ }
+}
+
+int InitSound(FCEUGI *gi)
+{
+ SDL_AudioSpec spec;
+ if(!_sound) return(0);
+
+ memset(&spec,0,sizeof(spec));
+ if(SDL_InitSubSystem(SDL_INIT_AUDIO)<0)
+ {
+ puts(SDL_GetError());
+ KillSound();
+ return(0);
+ }
+
+ spec.freq = soundrate;
+ spec.format = AUDIO_S16SYS;
+ spec.channels = 1;
+ spec.samples = 256;
+ spec.callback = fillaudio;
+ spec.userdata = 0;
+
+ BufferSize = soundbufsize * soundrate / 1000;
+
+ BufferSize -= spec.samples * 2; /* SDL uses at least double-buffering, so
+ multiply by 2. */
+
+ if(BufferSize < spec.samples) BufferSize = spec.samples;
+
+ Buffer = malloc(sizeof(int) * BufferSize);
+ BufferRead = BufferWrite = BufferIn = 0;
+
+ //printf("SDL Size: %d, Internal size: %d\n",spec.samples,BufferSize);
+
+ if(SDL_OpenAudio(&spec,0)<0)
+ {
+ puts(SDL_GetError());
+ KillSound();
+ return(0);
+ }
+ SDL_PauseAudio(0);
+ FCEUI_Sound(soundrate);
+ return(1);
+}
+
+
+uint32 GetMaxSound(void)
+{
+ return(BufferSize);
+}
+
+uint32 GetWriteSound(void)
+{
+ return(BufferSize - BufferIn);
+}
+
+void WriteSound(int32 *buf, int Count)
+{
+ while(Count)
+ {
+ while(BufferIn == BufferSize) SDL_Delay(1);
+ Buffer[BufferWrite] = *buf;
+ Count--;
+ BufferWrite = (BufferWrite + 1) % BufferSize;
+ BufferIn++;
+ buf++;
+ }
+}
+
+void SilenceSound(int n)
+{
+ SDL_PauseAudio(n);
+}
+
+int KillSound(void)
+{
+ FCEUI_Sound(0);
+ SDL_CloseAudio();
+ SDL_QuitSubSystem(SDL_INIT_AUDIO);
+ if(Buffer)
+ {
+ free(Buffer);
+ Buffer = 0;
+ }
+ return(0);
+}
+
+
+#endif
+
+
+static int mute=0;
+static int soundvolume=100;
+void FCEUD_SoundVolumeAdjust(int n)
+{
+ switch(n)
+ {
+ case -1: soundvolume-=10; if(soundvolume<0) soundvolume=0; break;
+ case 0: soundvolume=100; break;
+ case 1: soundvolume+=10; if(soundvolume>150) soundvolume=150; break;
+ }
+ mute=0;
+ FCEUI_SetSoundVolume(soundvolume);
+ FCEU_DispMessage("Sound volume %d.", soundvolume);
+}
+void FCEUD_SoundToggle(void)
+{
+ if(mute)
+ {
+ mute=0;
+ FCEUI_SetSoundVolume(soundvolume);
+ FCEU_DispMessage("Sound mute off.");
+ }
+ else
+ {
+ mute=1;
+ FCEUI_SetSoundVolume(0);
+ FCEU_DispMessage("Sound mute on.");
+ }
+}
diff --git a/drivers/pc/sdl-throttle.c b/drivers/pc/sdl-throttle.c
new file mode 100644
index 00000000..253ad885
--- /dev/null
+++ b/drivers/pc/sdl-throttle.c
@@ -0,0 +1,86 @@
+#include "sdl.h"
+#include "throttle.h"
+
+static uint64 tfreq;
+static uint64 desiredfps;
+
+static int32 fps_scale_table[]=
+{ 3, 3, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 2048 };
+int32 fps_scale = 256;
+
+#define fps_table_size (sizeof(fps_scale_table)/sizeof(fps_scale_table[0]))
+
+void RefreshThrottleFPS(void)
+{
+ desiredfps=FCEUI_GetDesiredFPS()>>8;
+ desiredfps=(desiredfps*fps_scale)>>8;
+ tfreq=10000000;
+ tfreq<<=16; /* Adjustment for fps returned from FCEUI_GetDesiredFPS(). */
+}
+
+void SpeedThrottle(void)
+{
+ static uint64 ttime,ltime=0;
+
+ waiter:
+
+ ttime=SDL_GetTicks();
+ ttime*=10000;
+
+ if( (ttime-ltime) < (tfreq/desiredfps) )
+ {
+ int64 delay;
+ delay=(tfreq/desiredfps)-(ttime-ltime);
+ if(delay>0)
+ SDL_Delay(delay/10000);
+ //printf("%d\n",(tfreq/desiredfps)-(ttime-ltime));
+ //SDL_Delay((tfreq/desiredfps)-(ttime-ltime));
+ goto waiter;
+ }
+ if( (ttime-ltime) >= (tfreq*4/desiredfps))
+ ltime=ttime;
+ else
+ ltime+=tfreq/desiredfps;
+}
+
+void IncreaseEmulationSpeed(void)
+{
+ int i;
+ for(i=1; fps_scale_table[i]<fps_scale; i++)
+ ;
+ fps_scale = fps_scale_table[i+1];
+
+ RefreshThrottleFPS();
+
+ FCEU_DispMessage("emulation speed %d%%",(fps_scale*100)>>8);
+}
+
+void DecreaseEmulationSpeed(void)
+{
+ int i;
+ for(i=1; fps_scale_table[i]<fps_scale; i++)
+ ;
+ fps_scale = fps_scale_table[i-1];
+
+ RefreshThrottleFPS();
+
+ FCEU_DispMessage("emulation speed %d%%",(fps_scale*100)>>8);
+}
+
+void FCEUD_SetEmulationSpeed(int cmd)
+{
+ switch(cmd)
+ {
+ case EMUSPEED_SLOWEST: fps_scale=fps_scale_table[0]; break;
+ case EMUSPEED_SLOWER: DecreaseEmulationSpeed(); break;
+ case EMUSPEED_NORMAL: fps_scale=256; break;
+ case EMUSPEED_FASTER: IncreaseEmulationSpeed(); break;
+ case EMUSPEED_FASTEST: fps_scale=fps_scale_table[fps_table_size-1]; break;
+ default:
+ return;
+ }
+
+ RefreshThrottleFPS();
+
+ FCEU_DispMessage("emulation speed %d%%",(fps_scale*100)>>8);
+}
diff --git a/drivers/pc/sdl-video.c b/drivers/pc/sdl-video.c
new file mode 100644
index 00000000..5886f0fb
--- /dev/null
+++ b/drivers/pc/sdl-video.c
@@ -0,0 +1,432 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "sdl.h"
+#include "sdl-opengl.h"
+#include "../common/vidblit.h"
+
+#include "sdl-icon.h"
+#include "dface.h"
+
+SDL_Surface *screen;
+SDL_Surface *BlitBuf; // Used as a buffer when using hardware-accelerated blits.
+SDL_Surface *IconSurface=NULL;
+
+static int curbpp;
+static int srendline,erendline;
+static int tlines;
+static int inited=0;
+
+#ifdef OPENGL
+extern int sdlhaveogl;
+static int usingogl;
+static double exs,eys;
+#else
+static int exs,eys;
+#endif
+static int eefx;
+
+#define NWIDTH (256-((eoptions&EO_CLIPSIDES)?16:0))
+#define NOFFSET (eoptions&EO_CLIPSIDES?8:0)
+
+
+static int paletterefresh;
+
+/* Return 1 if video was killed, 0 otherwise(video wasn't initialized). */
+int KillVideo(void)
+{
+ if(IconSurface)
+ {
+ SDL_FreeSurface(IconSurface);
+ IconSurface=0;
+ }
+
+ if(inited&1)
+ {
+ #ifdef OPENGL
+ if(usingogl)
+ KillOpenGL();
+ else
+ #endif
+ if(curbpp>8)
+ KillBlitToHigh();
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
+ inited&=~1;
+ return(1);
+ }
+ inited=0;
+ return(0);
+}
+
+static int sponge;
+
+int InitVideo(FCEUGI *gi)
+{
+ const SDL_VideoInfo *vinf;
+ int flags=0;
+
+ FCEUI_printf("Initializing video...");
+
+ FCEUI_GetCurrentVidSystem(&srendline,&erendline);
+
+ if(_fullscreen) sponge=Settings.specialfs;
+ else sponge=Settings.special;
+
+
+ #ifdef OPENGL
+ usingogl=0;
+ if(_opengl && sdlhaveogl && !sponge)
+ {
+ flags=SDL_OPENGL;
+ usingogl=1;
+ }
+ #endif
+
+ #ifdef EXTGUI
+ GUI_SetVideo(_fullscreen, 0, 0);
+ #endif
+
+ if(!(SDL_WasInit(SDL_INIT_VIDEO)&SDL_INIT_VIDEO))
+ if(SDL_InitSubSystem(SDL_INIT_VIDEO)==-1)
+ {
+ FCEUD_PrintError(SDL_GetError());
+ return(0);
+ }
+ inited|=1;
+
+ SDL_ShowCursor(0);
+ tlines=erendline-srendline+1;
+
+ vinf=SDL_GetVideoInfo();
+
+ if(vinf->hw_available)
+ flags|=SDL_HWSURFACE;
+
+ if(_fullscreen)
+ flags|=SDL_FULLSCREEN;
+
+ flags|=SDL_HWPALETTE;
+
+ //flags|=SDL_DOUBLEBUF;
+ #ifdef OPENGL
+ if(usingogl)
+ {
+ FCEU_printf("\n Initializing with OpenGL(Use \"-opengl 0\" to disable).\n");
+ if(_doublebuf)
+ SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
+ }
+ else
+ #endif
+ if(_doublebuf && (flags&SDL_HWSURFACE))
+ flags|=SDL_DOUBLEBUF;
+
+ if(_fullscreen)
+ {
+ int desbpp=_bpp;
+
+ exs=_xscalefs;
+ eys=_yscalefs;
+ eefx=_efxfs;
+
+ #ifdef OPENGL
+ if(!usingogl) {exs=(int)exs;eys=(int)eys;}
+ else desbpp=0;
+
+ if(sponge)
+ {
+ exs=eys=2;
+ if(sponge == 3 || sponge == 4) exs = eys = 3;
+ eefx=0;
+ if(sponge == 1 || sponge == 3) desbpp = 32;
+ }
+
+
+ if( (usingogl && !_stretchx) || !usingogl)
+ #endif
+ if(_xres<NWIDTH*exs || exs <= 0.01)
+ {
+ FCEUD_PrintError("xscale out of bounds.");
+ KillVideo();
+ return(0);
+ }
+
+ #ifdef OPENGL
+ if( (usingogl && !_stretchy) || !usingogl)
+ #endif
+ if(_yres<tlines*eys || eys <= 0.01)
+ {
+ FCEUD_PrintError("yscale out of bounds.");
+ KillVideo();
+ return(0);
+ }
+
+ #ifdef EXTGUI
+ GUI_SetVideo(_fullscreen, _xres, _yres);
+ #endif
+
+ #ifdef OPENGL
+ if(!(screen = SDL_SetVideoMode(_xres, _yres, desbpp, flags)))
+ #else
+ if(!(screen = SDL_SetVideoMode(_xres, _yres, desbpp, flags)))
+ #endif
+ {
+ FCEUD_PrintError(SDL_GetError());
+ return(0);
+ }
+ }
+ else
+ {
+ int desbpp=0;
+
+ exs=_xscale;
+ eys=_yscale;
+ eefx=_efx;
+
+ if(sponge)
+ {
+ exs=eys=2;
+ if(sponge >= 3) exs=eys=3;
+ eefx=0;
+ // SDL's 32bpp->16bpp code is slighty faster than mine, at least :/
+ if(sponge == 1 || sponge == 3) desbpp=32;
+ }
+
+ #ifdef OPENGL
+ if(!usingogl) {exs=(int)exs;eys=(int)eys;}
+ if(exs <= 0.01)
+ {
+ FCEUD_PrintError("xscale out of bounds.");
+ KillVideo();
+ return(0);
+ }
+ if(eys <= 0.01)
+ {
+ FCEUD_PrintError("yscale out of bounds.");
+ KillVideo();
+ return(0);
+ }
+ #endif
+
+ #ifdef EXTGUI
+ GUI_SetVideo(_fullscreen, (NWIDTH*exs), tlines*eys);
+ #endif
+
+ screen = SDL_SetVideoMode((NWIDTH*exs), tlines*eys, desbpp, flags);
+ }
+ curbpp=screen->format->BitsPerPixel;
+ if(!screen)
+ {
+ FCEUD_PrintError(SDL_GetError());
+ KillVideo();
+ return(0);
+ }
+ //BlitBuf=SDL_CreateRGBSurface(SDL_HWSURFACE,256,240,screen->format->BitsPerPixel,screen->format->Rmask,screen->format->Gmask,screen->format->Bmask,0);
+
+ inited=1;
+
+ FCEU_printf(" Video Mode: %d x %d x %d bpp %s\n",screen->w,screen->h,screen->format->BitsPerPixel,_fullscreen?"full screen":"");
+ if(curbpp!=16 && curbpp!=24 && curbpp!=8 && curbpp!=32)
+ {
+ FCEU_printf(" Sorry, %dbpp modes are not supported by FCE Ultra. Supported bit depths are 8bpp, 16bpp, and 32bpp.\n",curbpp);
+ KillVideo();
+ return(0);
+ }
+
+ if(gi->name)
+ SDL_WM_SetCaption(gi->name,gi->name);
+ else
+ SDL_WM_SetCaption("FCE Ultra","FCE Ultra");
+
+ #ifdef LSB_FIRST
+ IconSurface=SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,32,32,24,32*3,0xFF,0xFF00,0xFF0000,0x00);
+ #else
+ IconSurface=SDL_CreateRGBSurfaceFrom((void *)fceu_playicon.pixel_data,32,32,24,32*3,0xFF0000,0xFF00,0xFF,0x00);
+ #endif
+
+ SDL_WM_SetIcon(IconSurface,0);
+
+ paletterefresh=1;
+
+ if(curbpp>8)
+ #ifdef OPENGL
+ if(!usingogl)
+ #endif
+ InitBlitToHigh(curbpp>>3,screen->format->Rmask,screen->format->Gmask,screen->format->Bmask,eefx,sponge);
+ #ifdef OPENGL
+ if(usingogl)
+ if(!InitOpenGL((eoptions&EO_CLIPSIDES)?8:0,256-((eoptions&EO_CLIPSIDES)?8:0),srendline,erendline+1,exs,eys,eefx,_openglip,_stretchx,_stretchy,screen))
+ {
+ FCEUD_PrintError("Error initializing OpenGL.");
+ KillVideo();
+ return(0);
+ }
+ #endif
+ return 1;
+}
+
+void ToggleFS(void)
+{
+ extern FCEUGI *CurGame;
+ KillVideo();
+ _fullscreen=!_fullscreen;
+
+ if(!InitVideo(CurGame))
+ {
+ _fullscreen=!_fullscreen;
+ InitVideo(CurGame);
+ }
+}
+
+static SDL_Color psdl[256];
+void FCEUD_SetPalette(uint8 index, uint8 r, uint8 g, uint8 b)
+{
+ psdl[index].r=r;
+ psdl[index].g=g;
+ psdl[index].b=b;
+
+ paletterefresh=1;
+}
+
+void FCEUD_GetPalette(uint8 index, uint8 *r, uint8 *g, uint8 *b)
+{
+ *r=psdl[index].r;
+ *g=psdl[index].g;
+ *b=psdl[index].b;
+}
+
+static void RedoPalette(void)
+{
+ #ifdef OPENGL
+ if(usingogl)
+ SetOpenGLPalette((uint8*)psdl);
+ else
+ #endif
+ {
+ if(curbpp>8)
+ SetPaletteBlitToHigh((uint8*)psdl);
+ else
+ {
+ SDL_SetPalette(screen,SDL_PHYSPAL,psdl,0,256);
+ }
+ }
+}
+
+void LockConsole(){}
+void UnlockConsole(){}
+void BlitScreen(uint8 *XBuf)
+{
+ SDL_Surface *TmpScreen;
+ uint8 *dest;
+ int xo=0,yo=0;
+
+ if(!screen) return;
+
+ if(paletterefresh)
+ {
+ RedoPalette();
+ paletterefresh=0;
+ }
+
+ #ifdef OPENGL
+ if(usingogl)
+ {
+ BlitOpenGL(XBuf);
+ return;
+ }
+ #endif
+
+ XBuf+=srendline*256;
+
+ if(BlitBuf) TmpScreen=BlitBuf;
+ else TmpScreen=screen;
+
+ if(SDL_MUSTLOCK(TmpScreen))
+ if(SDL_LockSurface(TmpScreen))
+ {
+ return;
+ }
+
+ dest=(uint8*)TmpScreen->pixels;
+
+ if(_fullscreen)
+ {
+ xo=(((TmpScreen->w-NWIDTH*exs))/2);
+ dest+=xo*(curbpp>>3);
+ if(TmpScreen->h>(tlines*eys))
+ {
+ yo=((TmpScreen->h-tlines*eys)/2);
+ dest+=yo*TmpScreen->pitch;
+ }
+ }
+
+ if(curbpp>8)
+ {
+ if(BlitBuf)
+ Blit8ToHigh(XBuf+NOFFSET,dest, NWIDTH, tlines, TmpScreen->pitch,1,1);
+ else
+ Blit8ToHigh(XBuf+NOFFSET,dest, NWIDTH, tlines, TmpScreen->pitch,exs,eys);
+ }
+ else
+ {
+ if(BlitBuf)
+ Blit8To8(XBuf+NOFFSET,dest, NWIDTH, tlines, TmpScreen->pitch,1,1,0,sponge);
+ else
+ Blit8To8(XBuf+NOFFSET,dest, NWIDTH, tlines, TmpScreen->pitch,exs,eys,eefx,sponge);
+ }
+ if(SDL_MUSTLOCK(TmpScreen))
+ SDL_UnlockSurface(TmpScreen);
+
+ if(BlitBuf)
+ {
+ SDL_Rect srect;
+ SDL_Rect drect;
+
+ srect.x=0;
+ srect.y=0;
+ srect.w=NWIDTH;
+ srect.h=tlines;
+
+ drect.x=0;
+ drect.y=0;
+ drect.w=exs*NWIDTH;
+ drect.h=eys*tlines;
+
+ SDL_BlitSurface(BlitBuf, &srect,screen,&drect);
+ }
+
+ SDL_UpdateRect(screen, xo, yo, NWIDTH*exs, tlines*eys);
+
+ if(screen->flags&SDL_DOUBLEBUF)
+ SDL_Flip(screen);
+}
+
+uint32 PtoV(uint16 x, uint16 y)
+{
+ y=(double)y/eys;
+ x=(double)x/exs;
+ if(eoptions&EO_CLIPSIDES)
+ x+=8;
+ y+=srendline;
+ return(x|(y<<16));
+}
diff --git a/drivers/pc/sdl-video.h b/drivers/pc/sdl-video.h
new file mode 100644
index 00000000..4a4f056d
--- /dev/null
+++ b/drivers/pc/sdl-video.h
@@ -0,0 +1 @@
+uint32 PtoV(uint16 x, uint16 y);
diff --git a/drivers/pc/sdl.c b/drivers/pc/sdl.c
new file mode 100644
index 00000000..c2e939fc
--- /dev/null
+++ b/drivers/pc/sdl.c
@@ -0,0 +1,429 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "sdl.h"
+#include "sdl-video.h"
+#ifdef NETWORK
+#include "unix-netplay.h"
+#endif
+
+DSETTINGS Settings;
+CFGSTRUCT DriverConfig[]={
+ #ifdef OPENGL
+ AC(_stretchx),
+ AC(_stretchy),
+ AC(_opengl),
+ AC(_openglip),
+ #endif
+ AC(Settings.special),
+ AC(Settings.specialfs),
+ AC(_doublebuf),
+ AC(_xscale),
+ AC(_yscale),
+ AC(_xscalefs),
+ AC(_yscalefs),
+ AC(_bpp),
+ AC(_efx),
+ AC(_efxfs),
+ AC(_fullscreen),
+ AC(_xres),
+ AC(_yres),
+ #ifdef NETWORK
+ ACS(netplaynick),
+ AC(netlocalplayers),
+ AC(tport),
+ ACS(netpassword),
+ ACS(netgamekey),
+ #endif
+ ENDCFGSTRUCT
+};
+
+//-fshack x Set the environment variable SDL_VIDEODRIVER to \"x\" when
+// entering full screen mode and x is not \"0\".
+
+char *DriverUsage=
+"-xres x Set horizontal resolution to x for full screen mode.\n\
+-yres x Set vertical resolution to x for full screen mode.\n\
+-xscale(fs) x Multiply width by x(Real numbers >0 with OpenGL, otherwise integers >0).\n\
+-yscale(fs) x Multiply height by x(Real numbers >0 with OpenGL, otherwise integers >0).\n\
+-bpp(fs) x Bits per pixel for SDL surface(and video mode in fs). 8, 16, 32.\n\
+-opengl x Enable OpenGL support if x is 1.\n\
+-openglip x Enable OpenGL linear interpolation if x is 1.\n\
+-doublebuf x \n\
+-special(fs) x Specify special scaling filter.\n\
+-stretch(x/y) x Stretch to fill surface on x or y axis(fullscreen, only with OpenGL).\n\
+-efx(fs) x Enable special effects. Logically OR the following together:\n\
+ 1 = scanlines(for yscale>=2).\n\
+ 2 = TV blur(for bpp of 16 or 32).\n\
+-fs x Select full screen mode if x is non zero.\n\
+-connect s Connect to server 's' for TCP/IP network play.\n\
+-netnick s Set the nickname to use in network play.\n\
+-netgamekey s Use key 's' to create a unique session for the game loaded.\n\
+-netpassword s Password to use for connecting to the server.\n\
+-netlocalplayers x Set the number of local players.\n\
+-netport x Use TCP/IP port x for network play.";
+
+ARGPSTRUCT DriverArgs[]={
+ #ifdef OPENGL
+ {"-opengl",0,&_opengl,0},
+ {"-openglip",0,&_openglip,0},
+ {"-stretchx",0,&_stretchx,0},
+ {"-stretchy",0,&_stretchy,0},
+ #endif
+ {"-special",0,&Settings.special,0},
+ {"-specialfs",0,&Settings.specialfs,0},
+ {"-doublebuf",0,&_doublebuf,0},
+ {"-bpp",0,&_bpp,0},
+ {"-xscale",0,&_xscale,2},
+ {"-yscale",0,&_yscale,2},
+ {"-efx",0,&_efx,0},
+ {"-xscalefs",0,&_xscalefs,2},
+ {"-yscalefs",0,&_yscalefs,2},
+ {"-efxfs",0,&_efxfs,0},
+ {"-xres",0,&_xres,0},
+ {"-yres",0,&_yres,0},
+ {"-fs",0,&_fullscreen,0},
+ //{"-fshack",0,&_fshack,0x4001},
+ #ifdef NETWORK
+ {"-connect",0,&netplayhost,0x4001},
+ {"-netport",0,&tport,0},
+ {"-netlocalplayers",0,&netlocalplayers,0},
+ {"-netnick",0,&netplaynick,0x4001},
+ {"-netpassword",0,&netpassword,0x4001},
+ #endif
+ {0,0,0,0}
+};
+
+static void SetDefaults(void)
+{
+ Settings.special=Settings.specialfs=0;
+ _bpp=8;
+ _xres=640;
+ _yres=480;
+ _fullscreen=0;
+ _xscale=2.50;
+ _yscale=2;
+ _xscalefs=_yscalefs=2;
+ _efx=_efxfs=0;
+ //_fshack=_fshacksave=0;
+#ifdef OPENGL
+ _opengl=1;
+ _stretchx=1;
+ _stretchy=0;
+ _openglip=1;
+#endif
+}
+
+void DoDriverArgs(void)
+{
+ #ifdef BROKEN
+ if(_fshack)
+ {
+ if(_fshack[0]=='0')
+ if(_fshack[1]==0)
+ {
+ free(_fshack);
+ _fshack=0;
+ }
+ }
+ #endif
+}
+
+int InitMouse(void)
+{
+ return(0);
+}
+
+void KillMouse(void){}
+
+void GetMouseData(uint32 *d)
+{
+ if(FCEUI_IsMovieActive()<0)
+ return;
+
+ int x,y;
+ uint32 t;
+
+ t=SDL_GetMouseState(&x,&y);
+ #ifdef EXTGUI
+ GUI_GetMouseState(&t,&x,&y);
+ #endif
+
+ d[2]=0;
+ if(t&SDL_BUTTON(1))
+ d[2]|=1;
+ if(t&SDL_BUTTON(3))
+ d[2]|=2;
+ t=PtoV(x,y);
+ d[0]=t&0xFFFF;
+ d[1]=(t>>16)&0xFFFF;
+}
+
+int InitKeyboard(void)
+{
+ return(1);
+}
+
+int UpdateKeyboard(void)
+{
+ return(1);
+}
+
+void KillKeyboard(void)
+{
+
+}
+
+
+void UpdatePhysicalInput(void)
+{
+ SDL_Event event;
+
+ while(SDL_PollEvent(&event))
+ {
+ switch(event.type)
+ {
+ //case SDL_SYSWMEVENT: puts("Nifty keen");break;
+ //case SDL_VIDEORESIZE: puts("Okie dokie");break;
+ case SDL_QUIT: CloseGame();puts("Quit");break;
+ }
+ //printf("Event: %d\n",event.type);
+ //fflush(stdout);
+ }
+ //SDL_PumpEvents();
+}
+
+static uint8 *KeyState=NULL;
+char *GetKeyboard(void)
+{
+ KeyState=SDL_GetKeyState(0);
+ #ifdef EXTGUI
+ { char *tmp=GUI_GetKeyboard(); if(tmp) KeyState=tmp; }
+ #endif
+ return((char *)KeyState);
+}
+
+#ifdef WIN32
+#include <windows.h>
+
+ /* Stupid SDL */
+ #ifdef main
+ #undef main
+ #endif
+#endif
+
+#ifndef EXTGUI
+uint8 *GetBaseDirectory(void)
+{
+ uint8 *ol;
+ uint8 *ret;
+
+ ol=getenv("HOME");
+
+ if(ol)
+ {
+ ret=malloc(strlen(ol)+1+strlen("./fceultra"));
+ strcpy(ret,ol);
+ strcat(ret,"/.fceultra");
+ }
+ else
+ {
+ #ifdef WIN32
+ char *sa;
+
+ ret=malloc(MAX_PATH+1);
+ GetModuleFileName(NULL,ret,MAX_PATH+1);
+
+ sa=strrchr(ret,'\\');
+ if(sa)
+ *sa = 0;
+ #else
+ ret=malloc(1);
+ ret[0]=0;
+ #endif
+ printf("%s\n",ret);
+ }
+ return(ret);
+}
+#endif
+
+#ifdef OPENGL
+int sdlhaveogl;
+#endif
+
+
+int DTestButton(ButtConfig *bc)
+{
+ int x;
+
+ for(x=0;x<bc->NumC;x++)
+ {
+ if(bc->ButtType[x]==BUTTC_KEYBOARD)
+ {
+ if(KeyState[bc->ButtonNum[x]])
+ return(1);
+ }
+ else if(bc->ButtType[x]==BUTTC_JOYSTICK)
+ {
+ if(DTestButtonJoy(bc))
+ return(1);
+ }
+ }
+ return(0);
+}
+
+static int bcpv,bcpj;
+
+int ButtonConfigBegin(void)
+{
+ SDL_Surface *screen;
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
+ bcpv=KillVideo();
+ bcpj=KillJoysticks();
+
+ if(!(SDL_WasInit(SDL_INIT_VIDEO)&SDL_INIT_VIDEO))
+ if(SDL_InitSubSystem(SDL_INIT_VIDEO)==-1)
+ {
+ FCEUD_Message(SDL_GetError());
+ return(0);
+ }
+
+ screen = SDL_SetVideoMode(300, 1, 8, 0);
+ SDL_WM_SetCaption("Button Config",0);
+ InitJoysticks();
+
+ return(1);
+}
+
+void ButtonConfigEnd(void)
+{
+ extern FCEUGI *CurGame;
+ KillJoysticks();
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
+ if(bcpv) InitVideo(CurGame);
+ if(bcpj) InitJoysticks();
+}
+
+int DWaitButton(const uint8 *text, ButtConfig *bc, int wb)
+{
+ SDL_Event event;
+ static int32 LastAx[64][64];
+ int x,y;
+
+ SDL_WM_SetCaption(text,0);
+ #ifndef EXTGUI
+ puts(text);
+ #endif
+ for(x=0;x<64;x++)
+ for(y=0;y<64;y++)
+ LastAx[x][y]=0x100000;
+
+ while(SDL_WaitEvent(&event))
+ {
+ switch(event.type)
+ {
+ case SDL_KEYDOWN:bc->ButtType[wb]=BUTTC_KEYBOARD;
+ bc->DeviceNum[wb]=0;
+ bc->ButtonNum[wb]=event.key.keysym.sym;
+ return(1);
+ case SDL_JOYBUTTONDOWN:bc->ButtType[wb]=BUTTC_JOYSTICK;
+ bc->DeviceNum[wb]=event.jbutton.which;
+ bc->ButtonNum[wb]=event.jbutton.button;
+ return(1);
+ case SDL_JOYHATMOTION:if(event.jhat.value != SDL_HAT_CENTERED)
+ {
+ bc->ButtType[wb]=BUTTC_JOYSTICK;
+ bc->DeviceNum[wb]=event.jhat.which;
+ bc->ButtonNum[wb]=0x2000|((event.jhat.hat&0x1F)<<8)|event.jhat.value;
+ return(1);
+ }
+ break;
+ case SDL_JOYAXISMOTION:
+ if(LastAx[event.jaxis.which][event.jaxis.axis]==0x100000)
+ {
+ if(abs(event.jaxis.value)<1000)
+ LastAx[event.jaxis.which][event.jaxis.axis]=event.jaxis.value;
+ }
+ else
+ {
+ if(abs(LastAx[event.jaxis.which][event.jaxis.axis]-event.jaxis.value)>=8192)
+ {
+ bc->ButtType[wb]=BUTTC_JOYSTICK;
+ bc->DeviceNum[wb]=event.jaxis.which;
+ bc->ButtonNum[wb]=0x8000|(event.jaxis.axis)|((event.jaxis.value<0)?0x4000:0);
+ return(1);
+ }
+ }
+ break;
+ }
+ }
+
+ return(0);
+}
+
+#ifdef EXTGUI
+int FCEUSDLmain(int argc, char *argv[])
+#else
+int main(int argc, char *argv[])
+#endif
+{
+ FCEUD_Message("\nStarting FCE Ultra "FCEU_VERSION"...\n");
+
+ #ifdef WIN32
+ /* Taken from win32 sdl_main.c */
+ SDL_SetModuleHandle(GetModuleHandle(NULL));
+ #endif
+
+ if(SDL_Init(SDL_INIT_VIDEO)) /* SDL_INIT_VIDEO Needed for (joystick config) event processing? */
+ {
+ printf("Could not initialize SDL: %s.\n", SDL_GetError());
+ return(-1);
+ }
+
+ #ifdef OPENGL
+ #ifdef APPLEOPENGL
+ sdlhaveogl = 1; /* Stupid something... Hack. */
+ #else
+ if(!SDL_GL_LoadLibrary(0)) sdlhaveogl=1;
+ else sdlhaveogl=0;
+ #endif
+ #endif
+
+ SetDefaults();
+
+ {
+ int ret=CLImain(argc,argv);
+ SDL_Quit();
+ return(ret?0:-1);
+ }
+}
+
+
+uint64 FCEUD_GetTime(void)
+{
+ return(SDL_GetTicks());
+}
+
+uint64 FCEUD_GetTimeFreq(void)
+{
+ return(1000);
+}
+
+// dummy functions
+
+#define DUMMY(f) void f(void) {FCEU_DispMessage("Not implemented.");}
+DUMMY(FCEUD_HideMenuToggle)
+DUMMY(FCEUD_TurboOn)
+DUMMY(FCEUD_TurboOff)
+DUMMY(FCEUD_SaveStateAs)
+DUMMY(FCEUD_LoadStateFrom)
+DUMMY(FCEUD_MovieRecordTo)
+DUMMY(FCEUD_MovieReplayFrom)
+DUMMY(FCEUD_ToggleStatusIcon)
+DUMMY(FCEUD_AviRecordTo)
+DUMMY(FCEUD_AviStop)
+void FCEUI_AviVideoUpdate(const unsigned char* buffer) {FCEU_DispMessage("Not implemented.");}
+int FCEUD_ShowStatusIcon(void) {FCEU_DispMessage("Not implemented."); return 0; }
+int FCEUI_AviIsRecording(void) {return 0;}
+
diff --git a/drivers/pc/sdl.h b/drivers/pc/sdl.h
new file mode 100644
index 00000000..791316a8
--- /dev/null
+++ b/drivers/pc/sdl.h
@@ -0,0 +1,50 @@
+#include <SDL.h>
+#include "main.h"
+#include "dface.h"
+#include "input.h"
+
+int DTestButtonJoy(ButtConfig *bc);
+
+typedef struct {
+ int xres;
+ int yres;
+ double xscale,yscale;
+ double xscalefs,yscalefs;
+ int efx,efxfs;
+ int bpp;
+ int fullscreen;
+ int doublebuf;
+ char *fshack;
+ char *fshacksave;
+ #ifdef OPENGL
+ int opengl;
+ int openglip;
+ int stretchx,stretchy;
+ #endif
+ int special,specialfs;
+} DSETTINGS;
+
+extern DSETTINGS Settings;
+
+#define _doublebuf Settings.doublebuf
+#define _bpp Settings.bpp
+#define _xres Settings.xres
+#define _yres Settings.yres
+#define _fullscreen Settings.fullscreen
+#define _xscale Settings.xscale
+#define _yscale Settings.yscale
+#define _xscalefs Settings.xscalefs
+#define _yscalefs Settings.yscalefs
+#define _efx Settings.efx
+#define _efxfs Settings.efxfs
+#define _ebufsize Settings.ebufsize
+#define _fshack Settings.fshack
+#define _fshacksave Settings.fshacksave
+
+#ifdef OPENGL
+#define _opengl Settings.opengl
+#define _openglip Settings.openglip
+#define _stretchx Settings.stretchx
+#define _stretchy Settings.stretchy
+#endif
+
diff --git a/drivers/pc/throttle.c b/drivers/pc/throttle.c
new file mode 100644
index 00000000..422dad79
--- /dev/null
+++ b/drivers/pc/throttle.c
@@ -0,0 +1,41 @@
+#include <sys/time.h>
+#include "main.h"
+#include "throttle.h"
+
+static uint64 tfreq;
+static uint64 desiredfps;
+
+void RefreshThrottleFPS(void)
+{
+ desiredfps=FCEUI_GetDesiredFPS()>>8;
+ tfreq=1000000;
+ tfreq<<=16; /* Adjustment for fps returned from FCEUI_GetDesiredFPS(). */
+}
+
+static uint64 GetCurTime(void)
+{
+ uint64 ret;
+ struct timeval tv;
+
+ gettimeofday(&tv,0);
+ ret=(uint64)tv.tv_sec*1000000;
+ ret+=tv.tv_usec;
+ return(ret);
+}
+
+void SpeedThrottle(void)
+{
+ static uint64 ttime,ltime=0;
+
+ waiter:
+
+ ttime=GetCurTime();
+
+ if( (ttime-ltime) < (tfreq/desiredfps) )
+ goto waiter;
+ if( (ttime-ltime) >= (tfreq*4/desiredfps))
+ ltime=ttime;
+ else
+ ltime+=tfreq/desiredfps;
+}
+
diff --git a/drivers/pc/throttle.h b/drivers/pc/throttle.h
new file mode 100644
index 00000000..d6ca2aa8
--- /dev/null
+++ b/drivers/pc/throttle.h
@@ -0,0 +1,2 @@
+void RefreshThrottleFPS(void);
+void SpeedThrottle(void);
diff --git a/drivers/pc/unix-netplay.c b/drivers/pc/unix-netplay.c
new file mode 100644
index 00000000..5bef56e2
--- /dev/null
+++ b/drivers/pc/unix-netplay.c
@@ -0,0 +1,292 @@
+#ifdef NETWORK
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <errno.h>
+#include <fcntl.h>
+#include "main.h"
+#include "dface.h"
+#include "unix-netplay.h"
+
+#include "../../md5.h"
+
+#ifndef socklen_t
+#define socklen_t int
+#endif
+
+#ifndef SOL_TCP
+#define SOL_TCP IPPROTO_TCP
+#endif
+
+
+char *netplayhost=0;
+char *netplaynick=0;
+char *netgamekey = 0;
+char *netpassword = 0;
+int netlocalplayers = 1;
+
+int Port=0xFCE;
+int FCEUDnetplay=0;
+
+int tport=0xFCE;
+
+static int Socket=-1;
+
+static void en32(uint8 *buf, uint32 morp)
+{
+ buf[0]=morp;
+ buf[1]=morp>>8;
+ buf[2]=morp>>16;
+ buf[3]=morp>>24;
+}
+/*
+static uint32 de32(uint8 *morp)
+{
+ return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24));
+}
+*/
+int FCEUD_NetworkConnect(void)
+{
+ struct sockaddr_in sockin; /* I want to play with fighting robots. */
+ struct hostent *phostentb;
+ unsigned long hadr;
+ int TSocket;
+ int netdivisor;
+
+ if(!netplayhost) return(0);
+
+ if( (TSocket=socket(AF_INET,SOCK_STREAM,0))==-1)
+ {
+ puts("Error creating stream socket.");
+ FCEUD_NetworkClose();
+ return(0);
+ }
+
+ {
+ int tcpopt = 1;
+ #ifdef BEOS
+ if(setsockopt(TSocket, SOL_SOCKET, TCP_NODELAY, &tcpopt, sizeof(int)))
+ #else
+ if(setsockopt(TSocket, SOL_TCP, TCP_NODELAY, &tcpopt, sizeof(int)))
+ #endif
+ puts("Nodelay fail");
+ }
+
+ memset(&sockin,0,sizeof(sockin));
+ sockin.sin_family=AF_INET;
+
+ hadr=inet_addr(netplayhost);
+
+ if(hadr!=INADDR_NONE)
+ sockin.sin_addr.s_addr=hadr;
+ else
+ {
+ puts("*** Looking up host name...");
+ if(!(phostentb=gethostbyname((const char *)netplayhost)))
+ {
+ puts("Error getting host network information.");
+ close(TSocket);
+ FCEUD_NetworkClose();
+ return(0);
+ }
+ memcpy(&sockin.sin_addr,phostentb->h_addr,phostentb->h_length);
+ }
+
+ sockin.sin_port=htons(tport);
+ puts("*** Connecting to remote host...");
+ if(connect(TSocket,(struct sockaddr *)&sockin,sizeof(sockin))==-1)
+ {
+ puts("Error connecting to remote host.");
+ close(TSocket);
+ FCEUD_NetworkClose();
+ return(0);
+ }
+ Socket=TSocket;
+ puts("*** Sending initialization data to server...");
+ {
+ uint8 *sendbuf;
+ uint8 buf[5];
+ uint32 sblen;
+
+ sblen = 4 + 16 + 16 + 64 + 1 + (netplaynick?strlen(netplaynick):0);
+ sendbuf = malloc(sblen);
+ memset(sendbuf, 0, sblen);
+
+ en32(sendbuf, sblen - 4);
+
+ if(netgamekey)
+ {
+ struct md5_context md5;
+ uint8 md5out[16];
+
+ md5_starts(&md5);
+ md5_update(&md5, CurGame->MD5, 16);
+ md5_update(&md5, netgamekey, strlen(netgamekey));
+ md5_finish(&md5, md5out);
+ memcpy(sendbuf + 4, md5out, 16);
+ }
+ else
+ memcpy(sendbuf + 4, CurGame->MD5, 16);
+
+ if(netpassword)
+ {
+ struct md5_context md5;
+ uint8 md5out[16];
+
+ md5_starts(&md5);
+ md5_update(&md5, netpassword, strlen(netpassword));
+ md5_finish(&md5, md5out);
+ memcpy(sendbuf + 4 + 16, md5out, 16);
+ }
+
+ memset(sendbuf + 4 + 16 + 16, 0, 64);
+
+ sendbuf[4 + 16 + 16 + 64] = netlocalplayers;
+
+ if(netplaynick)
+ memcpy(sendbuf + 4 + 16 + 16 + 64 + 1,netplaynick,strlen(netplaynick));
+
+ send(Socket, sendbuf, sblen, 0);
+ free(sendbuf);
+
+ recv(Socket, buf, 1, MSG_WAITALL);
+ netdivisor = buf[0];
+ }
+
+ puts("*** Connection established.");
+
+ FCEUDnetplay = 1;
+ FCEUI_NetplayStart(netlocalplayers, netdivisor);
+ return(1);
+}
+
+
+int FCEUD_SendData(void *data, uint32 len)
+{
+ int check;
+ if(!ioctl(fileno(stdin),FIONREAD,&check))
+ if(check)
+ {
+ char buf[1024];
+ char *f;
+ fgets(buf,1024,stdin);
+ if((f=strrchr(buf,'\n')))
+ *f=0;
+ FCEUI_NetplayText(buf);
+ }
+ send(Socket, data, len ,0);
+ return(1);
+}
+
+int FCEUD_RecvData(void *data, uint32 len)
+{
+ NoWaiting&=~2;
+
+ for(;;)
+ {
+ fd_set funfun;
+ struct timeval popeye;
+
+ popeye.tv_sec=0;
+ popeye.tv_usec=100000;
+
+ FD_ZERO(&funfun);
+ FD_SET(Socket,&funfun);
+
+ switch(select(Socket + 1,&funfun,0,0,&popeye))
+ {
+ case 0: continue;
+ case -1:return(0);
+ }
+
+ if(FD_ISSET(Socket,&funfun))
+ {
+ if(recv(Socket,data,len,MSG_WAITALL) == len)
+ {
+ //unsigned long beefie;
+
+ FD_ZERO(&funfun);
+ FD_SET(Socket, &funfun);
+
+ popeye.tv_sec = popeye.tv_usec = 0;
+ if(select(Socket + 1, &funfun, 0, 0, &popeye) == 1)
+ //if(!ioctl(Socket,FIONREAD,&beefie))
+ // if(beefie)
+ {
+ NoWaiting|=2;
+ //puts("Yaya");
+ }
+ return(1);
+ }
+ else
+ return(0);
+ }
+
+ }
+ return 0;
+}
+
+void FCEUD_NetworkClose(void)
+{
+ if(Socket>0)
+ {
+ #ifdef BEOS
+ closesocket(Socket);
+ #else
+ close(Socket);
+ #endif
+ }
+ Socket=-1;
+
+ if(FCEUDnetplay)
+ FCEUI_NetplayStop();
+ FCEUDnetplay = 0;
+}
+
+
+void FCEUD_NetplayText(uint8 *text)
+{
+ char *tot = malloc(strlen(text) + 1);
+ char *tmp;
+ strcpy(tot, text);
+ tmp = tot;
+
+ while(*tmp)
+ {
+ if(*tmp < 0x20) *tmp = ' ';
+ tmp++;
+ }
+ puts(tot);
+ free(tot);
+}
+#endif
+
diff --git a/drivers/pc/unix-netplay.h b/drivers/pc/unix-netplay.h
new file mode 100644
index 00000000..dd6ed18a
--- /dev/null
+++ b/drivers/pc/unix-netplay.h
@@ -0,0 +1,9 @@
+#ifdef NETWORK
+extern char *netplaynick;
+extern char *netplayhost;
+extern char *netpassword;
+extern char *netgamekey;
+extern int tport;
+extern int netlocalplayers;
+
+#endif
diff --git a/drivers/pc/usage.h b/drivers/pc/usage.h
new file mode 100644
index 00000000..b8833200
--- /dev/null
+++ b/drivers/pc/usage.h
@@ -0,0 +1,60 @@
+/* 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 ShowUsage(char *prog)
+{
+printf("\nUsage is as follows:\n%s <options> filename\n\n",prog);
+puts("Options:");
+puts(DriverUsage);
+puts("-cpalette x Load a custom global palette from file x.\n\
+-ntsccol x Emulate an NTSC's TV's colors.\n\
+ 0 = Disabled.\n\
+ 1 = Enabled.\n\
+-pal x Emulate a PAL NES if x is 1.\n\
+-sound x Sound.\n\
+ 0 = Disabled.\n\
+ Otherwise, x = playback rate.\n\
+-soundvol x Sound volume. x is an integral percentage value.\n\
+-soundq x Sets sound quality.\n\
+ 0 = Low quality.\n\
+ 1 = High quality.\n\
+-inputx str Select device mapped to virtual input port x(1-2).\n\
+ str may be: none, gamepad, zapper, powerpada, powerpadb,\n\
+ arkanoid\n\
+-fcexp str Select Famicom expansion port device.\n\
+ str may be: none, shadow, arkanoid, 4player, fkb\n\
+-inputcfg s Configure virtual input device \"s\".\n\
+-nofs x Disables Four-Score emulation if x is 1.\n\
+-gg x Enable Game Genie emulation if x is 1.\n\
+-no8lim x Disables the 8 sprites per scanline limitation.\n\
+ 0 = Limitation enabled.\n\
+ 1 = Limitation disabled.\n\
+-snapname x Selects what type of file name snapshots will have.\n\
+ 0 = Numeric(0.png)\n\
+ 1 = File base and numeric(mario-0.png)\n\
+-nothrottle x Disable artificial speed throttling if x is non-zero.\n\
+-clipsides x Clip leftmost and rightmost 8 columns of pixels of video output.\n\
+ 0 = No clipping.\n\
+ 1 = Clipping.\n\
+-slstart x Set the first drawn emulated scanline. Valid values for x are\n\
+ 0 through 239.\n\
+-slend x Set the last drawn emulated scanline. Valid values for x are\n\
+ 0 through 239.");
+}
diff --git a/drivers/pc/vgatweak.c b/drivers/pc/vgatweak.c
new file mode 100644
index 00000000..a04cf94e
--- /dev/null
+++ b/drivers/pc/vgatweak.c
@@ -0,0 +1,168 @@
+/* This file is "#include"d from dos-video.c and svga-video.c */
+
+typedef struct {
+ uint8 p;
+ uint8 i;
+ uint8 v;
+} vgareg;
+
+vgareg v256x224_103[25] =
+{
+ { 0xc2, 0x0, 0xe7},
+ { 0xd4, 0x0, 0x45},
+ { 0xd4, 0x1, 0x3f},
+ { 0xd4, 0x2, 0x40},
+ { 0xd4, 0x3, 0x86},
+ { 0xd4, 0x4, 0x3f},
+ { 0xd4, 0x5, 0x10},
+ { 0xd4, 0x6, 0xcd},
+ { 0xd4, 0x7, 0x1f},
+ { 0xd4, 0x8, 0x0},
+ { 0xd4, 0x9, 0x41},
+ { 0xd4, 0x10, 0xc0},
+ { 0xd4, 0x11, 0xac},
+ { 0xd4, 0x12, 0xbf},
+ { 0xd4, 0x13, 0x20},
+ { 0xd4, 0x14, 0x40}, //
+ { 0xd4, 0x15, 0xe7},
+ { 0xd4, 0x16, 0x06}, //
+ { 0xd4, 0x17, 0xa3},
+ { 0xc4, 0x1, 0x1},
+ { 0xc4, 0x4, 0xe}, //
+ { 0xce, 0x5, 0x40},
+ { 0xce, 0x6, 0x5},
+ { 0xc0, 0x10, 0x41},
+ { 0xc0, 0x13, 0x0},
+};
+
+vgareg v256x240[25] =
+{
+ { 0xc2, 0x0, 0xe3},
+ { 0xd4, 0x0, 0x4f},
+ { 0xd4, 0x1, 0x3f},
+ { 0xd4, 0x2, 0x40},
+ { 0xd4, 0x3, 0x92},
+ { 0xd4, 0x4, 0x44},
+ { 0xd4, 0x5, 0x10},
+ { 0xd4, 0x6, 0x0a},
+ { 0xd4, 0x7, 0x3e},
+ { 0xd4, 0x8, 0x00},
+ { 0xd4, 0x9, 0x41},
+ { 0xd4, 0x10, 0xea},
+ { 0xd4, 0x11, 0xac},
+ { 0xd4, 0x12, 0xdf},
+ { 0xd4, 0x13, 0x20},
+ { 0xd4, 0x14, 0x40},
+ { 0xd4, 0x15, 0xe7},
+ { 0xd4, 0x16, 0x06},
+ { 0xd4, 0x17, 0xa3},
+ { 0xc4, 0x1, 0x1},
+ { 0xc4, 0x4, 0xe},
+ { 0xce, 0x5, 0x40},
+ { 0xce, 0x6, 0x5},
+ { 0xc0, 0x10, 0x41},
+ { 0xc0, 0x13, 0x0}
+};
+
+vgareg v256x224S[25] =
+{
+ { 0xc2, 0x0, 0xe3},
+ { 0xd4, 0x0, 0x5f},
+ { 0xd4, 0x1, 0x3f},
+ { 0xd4, 0x2, 0x40},
+ { 0xd4, 0x3, 0x82},
+ { 0xd4, 0x4, 0x4e},
+ { 0xd4, 0x5, 0x96},
+ { 0xd4, 0x6, 0x5},
+ { 0xd4, 0x7, 0x1},
+ { 0xd4, 0x8, 0x0},
+ { 0xd4, 0x9, 0x40},
+ { 0xd4, 0x10, 0xea},
+ { 0xd4, 0x11, 0xac},
+ { 0xd4, 0x12, 0xdf},
+ { 0xd4, 0x13, 0x20},
+ { 0xd4, 0x14, 0x40},
+ { 0xd4, 0x15, 0xe7},
+ { 0xd4, 0x16, 0x0},
+ { 0xd4, 0x17, 0xe3},
+ { 0xc4, 0x1, 0x1},
+ { 0xc4, 0x4, 0xe},
+ { 0xce, 0x5, 0x40},
+ { 0xce, 0x6, 0x5},
+ { 0xc0, 0x10, 0x41},
+ { 0xc0, 0x13, 0x0}
+};
+
+vgareg v256x256[25] =
+{
+ { 0xc2, 0x0, 0xe7},
+ { 0xd4, 0x0, 0x5f},
+ { 0xd4, 0x1, 0x3f},
+ { 0xd4, 0x2, 0x40},
+ { 0xd4, 0x3, 0x82},
+ { 0xd4, 0x4, 0x4a},
+ { 0xd4, 0x5, 0x9a},
+ { 0xd4, 0x6, 0x23},
+ { 0xd4, 0x7, 0xb2},
+ { 0xd4, 0x8, 0x0},
+ { 0xd4, 0x9, 0x61},
+ { 0xd4, 0x10, 0xa},
+ { 0xd4, 0x11, 0xac},
+ { 0xd4, 0x12, 0xff},
+ { 0xd4, 0x13, 0x20},
+ { 0xd4, 0x14, 0x40},
+ { 0xd4, 0x15, 0x7},
+ { 0xd4, 0x16, 0x1a},
+ { 0xd4, 0x17, 0xa3},
+ { 0xc4, 0x1, 0x1},
+ { 0xc4, 0x4, 0xe},
+ { 0xce, 0x5, 0x40},
+ { 0xce, 0x6, 0x5},
+ { 0xc0, 0x10, 0x41},
+ { 0xc0, 0x13, 0x0}
+};
+
+vgareg v256x256S[25] =
+{
+ { 0xc2, 0x00, 0xe7},{ 0xd4, 0x00, 0x5F},{ 0xd4, 0x01, 0x3f},
+ { 0xd4, 0x02, 0x40},{ 0xd4, 0x03, 0x82},{ 0xd4, 0x04, 0x4a},
+ { 0xd4, 0x05, 0x9a},{ 0xd4, 0x06, 0x25},{ 0xd4, 0x07, 0x15},
+ { 0xd4, 0x08, 0x00},{ 0xd4, 0x09, 0x60},{ 0xd4, 0x10, 0x0a},
+ { 0xd4, 0x11, 0xac},{ 0xd4, 0x12, 0xff},{ 0xd4, 0x13, 0x20},
+ { 0xd4, 0x14, 0x40},{ 0xd4, 0x15, 0x07},{ 0xd4, 0x16, 0x1a},
+ { 0xd4, 0x17, 0xa3},{ 0xc4, 0x01, 0x01},{ 0xc4, 0x04, 0x0e},
+ { 0xce, 0x05, 0x40},{ 0xce, 0x06, 0x05},{ 0xc0, 0x10, 0x41},
+ { 0xc0, 0x13, 0x00}
+};
+
+static void VGAPortSet(vgareg R)
+{
+ int p,i,v;
+
+ p=0x300|R.p;
+ i=R.i;
+ v=R.v;
+
+ switch(p)
+ {
+ case 0x3C0: inportb(0x3DA);
+ outportb(0x3C0,i);
+ outportb(0x3C0,v);
+ break;
+ case 0x3C2:
+ case 0x3C3:
+ default: outportb(p, v);
+ break;
+ case 0x3C4: if(i==1)
+ {
+ outportw(0x3c4,0x100);
+ outportw(0x3c4,(v<<8)|1);
+ outportw(0x3c4,0x300);
+ break;
+ }
+ case 0x3CE:
+ case 0x3D4: outportw(p,i|(v<<8));
+ break;
+ }
+}
+
diff --git a/drivers/sexyal/convert.c b/drivers/sexyal/convert.c
new file mode 100644
index 00000000..8fc4d626
--- /dev/null
+++ b/drivers/sexyal/convert.c
@@ -0,0 +1,14 @@
+#include "sexyal.h"
+#include "convert.h"
+
+static inline uint16_t FLIP16(uint16_t b)
+{
+ return((b<<8)|((b>>8)&0xFF));
+}
+
+static inline uint32_t FLIP32(uint32_t b)
+{
+ return( (b<<24) | ((b>>8)&0xFF00) | ((b<<8)&0xFF0000) | ((b>>24)&0xFF) );
+}
+
+#include "convert.inc"
diff --git a/drivers/sexyal/convert.h b/drivers/sexyal/convert.h
new file mode 100644
index 00000000..ac364bb3
--- /dev/null
+++ b/drivers/sexyal/convert.h
@@ -0,0 +1,2 @@
+void SexiALI_Convert(SexyAL_format *srcformat, SexyAL_format *destformat, void *vdest, void *vsrc, uint32_t frames);
+
diff --git a/drivers/sexyal/convert.inc b/drivers/sexyal/convert.inc
new file mode 100644
index 00000000..2c895bf1
--- /dev/null
+++ b/drivers/sexyal/convert.inc
@@ -0,0 +1,20387 @@
+void SexiALI_Convert(SexyAL_format *srcformat, SexyAL_format *destformat, void *vdest, void *vsrc, uint32_t frames)
+{
+if(srcformat->sampformat == SEXYAL_FMT_PCMS8)
+{
+int8_t* src=vsrc;
+if(destformat->sampformat == SEXYAL_FMT_PCMS8)
+{
+int8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU8)
+{
+uint8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp2+=128;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp2+=128;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp2+=128;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp2+=128;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp2+=128;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp2+=128;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp2+=128;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp2+=128;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS16)
+{
+int16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU16)
+{
+uint16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S16)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U16)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp <<= 8;
+ tmp2+=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S24)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 16;
+ tmp2 <<= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 16;
+ tmp2 <<= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 16;
+ tmp2 <<= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 16;
+ tmp2 <<= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 16;
+ tmp2 <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 16;
+ tmp2 <<= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 16;
+ tmp2 <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 16;
+ tmp2 <<= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U24)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=128;
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 16;
+ tmp2+=128;
+ tmp2 <<= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 16;
+ tmp2+=128;
+ tmp2 <<= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp <<= 16;
+ tmp2+=128;
+ tmp2 <<= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp <<= 16;
+ tmp2+=128;
+ tmp2 <<= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 16;
+ tmp2+=128;
+ tmp2 <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=128;
+ tmp <<= 16;
+ tmp2+=128;
+ tmp2 <<= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp <<= 16;
+ tmp2+=128;
+ tmp2 <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=128;
+ tmp <<= 16;
+ tmp2+=128;
+ tmp2 <<= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+}
+if(srcformat->sampformat == SEXYAL_FMT_PCMU8)
+{
+uint8_t* src=vsrc;
+if(destformat->sampformat == SEXYAL_FMT_PCMS8)
+{
+int8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp2-=128;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp2-=128;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp2-=128;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp2-=128;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp2-=128;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp2-=128;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp2-=128;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp2-=128;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU8)
+{
+uint8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS16)
+{
+int16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU16)
+{
+uint16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S16)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp <<= 8;
+ tmp2-=128;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U16)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S24)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=128;
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 16;
+ tmp2-=128;
+ tmp2 <<= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 16;
+ tmp2-=128;
+ tmp2 <<= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp <<= 16;
+ tmp2-=128;
+ tmp2 <<= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp <<= 16;
+ tmp2-=128;
+ tmp2 <<= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 16;
+ tmp2-=128;
+ tmp2 <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=128;
+ tmp <<= 16;
+ tmp2-=128;
+ tmp2 <<= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp <<= 16;
+ tmp2-=128;
+ tmp2 <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=128;
+ tmp <<= 16;
+ tmp2-=128;
+ tmp2 <<= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U24)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 16;
+ tmp2 <<= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 16;
+ tmp2 <<= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 16;
+ tmp2 <<= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 16;
+ tmp2 <<= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 16;
+ tmp2 <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 16;
+ tmp2 <<= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 16;
+ tmp2 <<= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 16;
+ tmp2 <<= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+}
+if(srcformat->sampformat == SEXYAL_FMT_PCMS16)
+{
+int16_t* src=vsrc;
+if(destformat->sampformat == SEXYAL_FMT_PCMS8)
+{
+int8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU8)
+{
+uint8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS16)
+{
+int16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU16)
+{
+uint16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp2+=32768;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp2+=32768;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp2+=32768;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp2+=32768;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp2+=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp2+=32768;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp2+=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp2+=32768;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S16)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U16)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S24)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U24)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp+=32768;
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+}
+if(srcformat->sampformat == SEXYAL_FMT_PCMU16)
+{
+uint16_t* src=vsrc;
+if(destformat->sampformat == SEXYAL_FMT_PCMS8)
+{
+int8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU8)
+{
+uint8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp >>= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS16)
+{
+int16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp2-=32768;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp2-=32768;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp2-=32768;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp2-=32768;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp2-=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp2-=32768;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp2-=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp2-=32768;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU16)
+{
+uint16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S16)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U16)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 0;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S24)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp-=32768;
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U24)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+ tmp <<= 8;
+FLIP16(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP16(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP16(tmp);
+tmp2=*src;
+ src++;
+FLIP16(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP16(tmp);
+FLIP16(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+}
+if(srcformat->sampformat == SEXYAL_FMT_PCMS32S16)
+{
+int32_t* src=vsrc;
+if(destformat->sampformat == SEXYAL_FMT_PCMS8)
+{
+int8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU8)
+{
+uint8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp >>= 8;
+ tmp2+=32768;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS16)
+{
+int16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU16)
+{
+uint16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp <<= 0;
+ tmp2+=32768;
+ tmp2 <<= 0;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S16)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U16)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp2+=32768;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp2+=32768;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp2+=32768;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp2+=32768;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp2+=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp2+=32768;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp2+=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp2+=32768;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S24)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U24)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=32768;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=32768;
+ tmp <<= 8;
+ tmp2+=32768;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+}
+if(srcformat->sampformat == SEXYAL_FMT_PCMU32U16)
+{
+uint32_t* src=vsrc;
+if(destformat->sampformat == SEXYAL_FMT_PCMS8)
+{
+int8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp >>= 8;
+ tmp2-=32768;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU8)
+{
+uint8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS16)
+{
+int16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp <<= 0;
+ tmp2-=32768;
+ tmp2 <<= 0;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU16)
+{
+uint16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 0;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 0;
+ tmp2 <<= 0;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S16)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp2-=32768;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp2-=32768;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp2-=32768;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp2-=32768;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp2-=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp2-=32768;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp2-=32768;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp2-=32768;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U16)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S24)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=32768;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=32768;
+ tmp <<= 8;
+ tmp2-=32768;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U24)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp <<= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp <<= 8;
+ tmp2 <<= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+}
+if(srcformat->sampformat == SEXYAL_FMT_PCMS32S24)
+{
+int32_t* src=vsrc;
+if(destformat->sampformat == SEXYAL_FMT_PCMS8)
+{
+int8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 16;
+ tmp2 >>= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 16;
+ tmp2 >>= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 16;
+ tmp2 >>= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 16;
+ tmp2 >>= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 16;
+ tmp2 >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 16;
+ tmp2 >>= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 16;
+ tmp2 >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 16;
+ tmp2 >>= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU8)
+{
+uint8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 16;
+ tmp2+=(1<<23);
+ tmp2 >>= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 16;
+ tmp2+=(1<<23);
+ tmp2 >>= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp >>= 16;
+ tmp2+=(1<<23);
+ tmp2 >>= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp >>= 16;
+ tmp2+=(1<<23);
+ tmp2 >>= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 16;
+ tmp2+=(1<<23);
+ tmp2 >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 16;
+ tmp2+=(1<<23);
+ tmp2 >>= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp >>= 16;
+ tmp2+=(1<<23);
+ tmp2 >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp >>= 16;
+ tmp2+=(1<<23);
+ tmp2 >>= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS16)
+{
+int16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU16)
+{
+uint16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S16)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U16)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp >>= 8;
+ tmp2+=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S24)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U24)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp+=(1<<23);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp+=(1<<23);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp2+=(1<<23);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp2+=(1<<23);
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp2+=(1<<23);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp2+=(1<<23);
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp2+=(1<<23);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp+=(1<<23);
+ tmp2+=(1<<23);
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp2+=(1<<23);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp+=(1<<23);
+ tmp2+=(1<<23);
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+}
+if(srcformat->sampformat == SEXYAL_FMT_PCMU32U24)
+{
+uint32_t* src=vsrc;
+if(destformat->sampformat == SEXYAL_FMT_PCMS8)
+{
+int8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 16;
+ tmp2-=(1<<23);
+ tmp2 >>= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 16;
+ tmp2-=(1<<23);
+ tmp2 >>= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp >>= 16;
+ tmp2-=(1<<23);
+ tmp2 >>= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp >>= 16;
+ tmp2-=(1<<23);
+ tmp2 >>= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 16;
+ tmp2-=(1<<23);
+ tmp2 >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 16;
+ tmp2-=(1<<23);
+ tmp2 >>= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp >>= 16;
+ tmp2-=(1<<23);
+ tmp2 >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp >>= 16;
+ tmp2-=(1<<23);
+ tmp2 >>= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU8)
+{
+uint8_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 16;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 16;
+ tmp2 >>= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 16;
+ tmp2 >>= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 16;
+ tmp2 >>= 16;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 16;
+ tmp2 >>= 16;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 16;
+ tmp2 >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 16;
+ tmp2 >>= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 16;
+ tmp2 >>= 16;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 16;
+ tmp2 >>= 16;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS16)
+{
+int16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU16)
+{
+uint16_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S16)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp >>= 8;
+ tmp2-=(1<<23);
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U16)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp >>= 8;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp >>= 8;
+ tmp2 >>= 8;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMS32S24)
+{
+int32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ tmp-=(1<<23);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ tmp-=(1<<23);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp2-=(1<<23);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp2-=(1<<23);
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp2-=(1<<23);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp2-=(1<<23);
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp2-=(1<<23);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ tmp-=(1<<23);
+ tmp2-=(1<<23);
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp2-=(1<<23);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ tmp-=(1<<23);
+ tmp2-=(1<<23);
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+if(destformat->sampformat == SEXYAL_FMT_PCMU32U24)
+{
+uint32_t* dest=vdest;
+if(srcformat->channels == 1)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp);
+ *dest=tmp;
+ dest++;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+}
+if(srcformat->channels == 2)
+{
+if(destformat->channels == 1)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+FLIP32(tmp);
+tmp = (tmp+tmp2)>>1;
+ *dest=tmp;
+ dest++;
+}
+}
+}
+}
+if(destformat->channels == 2)
+{
+if(srcformat->byteorder == 0)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+tmp2=*src;
+ src++;
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+if(srcformat->byteorder == 1)
+{
+if(destformat->byteorder == 0)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+if(destformat->byteorder == 1)
+{
+while(frames--)
+{
+int32_t tmp;
+int32_t tmp2;
+tmp=*src;
+ src++;
+FLIP32(tmp);
+tmp2=*src;
+ src++;
+FLIP32(tmp2);
+FLIP32(tmp);
+FLIP32(tmp2);
+ *dest=tmp;
+ dest++;
+ *dest=tmp2;
+ dest++;
+}
+}
+}
+}
+}
+}
+}
+}
diff --git a/drivers/sexyal/convertgen b/drivers/sexyal/convertgen
new file mode 100644
index 00000000..d4420fda
--- /dev/null
+++ b/drivers/sexyal/convertgen
Binary files differ
diff --git a/drivers/sexyal/convertgen.c b/drivers/sexyal/convertgen.c
new file mode 100644
index 00000000..83e59083
--- /dev/null
+++ b/drivers/sexyal/convertgen.c
@@ -0,0 +1,155 @@
+#include <stdio.h>
+
+char *check[]={"SEXYAL_FMT_PCMS8","SEXYAL_FMT_PCMU8","SEXYAL_FMT_PCMS16",
+"SEXYAL_FMT_PCMU16","SEXYAL_FMT_PCMS32S16","SEXYAL_FMT_PCMU32U16","SEXYAL_FMT_PCMS32S24","SEXYAL_FMT_PCMU32U24"};
+char *str[]={"int8_t","uint8_t","int16_t","uint16_t","int32_t","uint32_t","int32_t","uint32_t"};
+
+int bitss[]={8,8,16,16,16,16,24,24};
+int bitsreal[]={8,8,16,16,32,32,32,32};
+
+void Fetch(int x,char *wt)
+{
+ //printf(" int32_t tmp%s=*src;\n",wt);
+ printf("tmp%s=*src;\n",wt);
+ printf(" src++;\n");
+}
+
+void BitConv(int src, int dest, char *wt)
+{
+ if((src^dest)&1) /* signed/unsigned change. */
+ if(src&1) /* Source unsigned, dest signed. */
+ {
+ if(src==1) printf(" tmp%s-=128;\n",wt);
+ else if(src==3) printf(" tmp%s-=32768;\n",wt);
+ else if(src==5) printf(" tmp%s-=32768;\n",wt);
+ else if(src==7) printf(" tmp%s-=(1<<23);\n",wt);
+ }
+ else /* Source signed, dest unsigned */
+ {
+ if(src==0) printf(" tmp%s+=128;\n",wt);
+ else if(src==2) printf(" tmp%s+=32768;\n",wt);
+ else if(src==4) printf(" tmp%s+=32768;\n",wt);
+ else if(src==6) printf(" tmp%s+=(1<<23);\n",wt);
+ }
+ if((src>>1) != (dest>>1))
+ {
+ int shifty=bitss[src]-bitss[dest];
+ if(shifty>0)
+ printf(" tmp%s >>= %d;\n",wt,shifty);
+ else
+ printf(" tmp%s <<= %d;\n",wt,-shifty);
+ }
+}
+
+void Save(int x, char *wt)
+{
+ printf(" *dest=tmp%s;\n",wt);
+ printf(" dest++;\n");
+}
+
+main()
+{
+ int srcbits,destbits,srcchannels,destchannels;
+ int srcbo,destbo;
+
+ puts("void SexiALI_Convert(SexyAL_format *srcformat, SexyAL_format *destformat, void *vdest, void *vsrc, uint32_t frames)");
+ puts("{");
+
+ for(srcbits=0;srcbits<8;srcbits++)
+ {
+ printf("if(srcformat->sampformat == %s)\n{\n",check[srcbits]);
+
+ printf("%s* src=vsrc;\n",str[srcbits]);
+
+ for(destbits=0;destbits<8;destbits++)
+ {
+ printf("if(destformat->sampformat == %s)\n{\n",check[destbits]);
+
+ printf("%s* dest=vdest;\n",str[destbits]);
+
+ for(srcchannels=0;srcchannels<2;srcchannels++)
+ {
+ printf("if(srcformat->channels == %c)\n{\n",'1'+srcchannels);
+ for(destchannels=0;destchannels<2;destchannels++)
+ {
+ printf("if(destformat->channels == %c)\n{\n",'1'+destchannels);
+ for(srcbo=0;srcbo<2;srcbo++)
+ {
+ printf("if(srcformat->byteorder == %d)\n{\n",srcbo);
+ for(destbo=0;destbo<2;destbo++)
+ {
+ printf("if(destformat->byteorder == %d)\n{\n",destbo);
+ //printf("if(srcformat->sampformat==%s && destformat->sameck[srcbits],check[destbits]);
+ printf("while(frames--)\n{\n");
+
+ puts("int32_t tmp;");
+ if(srcchannels)
+ puts("int32_t tmp2;");
+
+ Fetch(srcbits,"");
+
+ if(srcbo)
+ {
+ if(bitsreal[srcbits]==16)
+ puts("FLIP16(tmp);");
+ else
+ puts("FLIP32(tmp);");
+ }
+
+ if(srcchannels)
+ {
+ Fetch(srcbits,"2");
+ if(srcbo)
+ {
+ if(bitsreal[srcbits]==16)
+ puts("FLIP16(tmp2);");
+ else
+ puts("FLIP32(tmp2);");
+ }
+ }
+
+ BitConv(srcbits,destbits,"");
+
+ if(srcchannels) BitConv(srcbits,destbits,"2");
+
+ if(destbo)
+ {
+ if(bitsreal[srcbits]==16)
+ puts("FLIP16(tmp);");
+ else
+ puts("FLIP32(tmp);");
+ if(srcchannels && destchannels && destbo)
+ {
+ if(bitsreal[srcbits]==16)
+ puts("FLIP16(tmp2);");
+ else
+ puts("FLIP32(tmp2);");
+ }
+ }
+
+ if(srcchannels && !destchannels)
+ printf("tmp = (tmp+tmp2)>>1;\n");
+
+ Save(destbits,"");
+ if(!srcchannels && destchannels)
+ Save(destbits,"");
+
+ if(srcchannels && destchannels)
+ Save(destbits,"2");
+
+ puts("}");
+ puts("}");
+ } // destbo
+ puts("}");
+ } // srcbo
+ puts("}");
+ }
+ puts("}");
+ }
+ puts("}");
+ }
+ puts("}");
+ }
+
+ puts("}");
+}
diff --git a/drivers/sexyal/drivers/dsound.c b/drivers/sexyal/drivers/dsound.c
new file mode 100644
index 00000000..b6569ce6
--- /dev/null
+++ b/drivers/sexyal/drivers/dsound.c
@@ -0,0 +1,276 @@
+#include <windows.h>
+#include <windowsx.h>
+#include <stdio.h>
+
+#undef WINNT
+#define NONAMELESSUNION
+
+#define DIRECTSOUND_VERSION 0x0300
+
+#include <dsound.h>
+#include "../sexyal.h"
+
+typedef struct
+{
+ LPDIRECTSOUND ppDS; /* DirectSound interface object. */
+ LPDIRECTSOUNDBUFFER ppbuf; /* Primary buffer. */
+ LPDIRECTSOUNDBUFFER ppbufsec; /* Secondary buffer. */
+ LPDIRECTSOUNDBUFFER ppbufw; /* Buffer to do writes to. */
+ WAVEFORMATEX wf; /* Format of the primary and secondary buffers. */
+ long DSBufferSize; /* The size of the buffer that we can write to, in bytes. */
+
+ long BufHowMuch; /* How many bytes we should try to buffer. */
+ DWORD ToWritePos; /* Position which the next write to the buffer
+ should write to.
+ */
+} DSFobby;
+
+static void CheckStatus(DSFobby *tmp)
+{
+ DWORD status=0;
+
+ IDirectSoundBuffer_GetStatus(tmp->ppbufw, &status);
+ if(status&DSBSTATUS_BUFFERLOST)
+ IDirectSoundBuffer_Restore(tmp->ppbufw);
+
+ if(!(status&DSBSTATUS_PLAYING))
+ {
+ tmp->ToWritePos=0;
+ IDirectSoundBuffer_SetCurrentPosition(tmp->ppbufsec,0);
+ IDirectSoundBuffer_SetFormat(tmp->ppbufw,&tmp->wf);
+ IDirectSoundBuffer_Play(tmp->ppbufw,0,0,DSBPLAY_LOOPING);
+ }
+}
+
+SexyAL_device *SexyALI_DSound_Open(uint64_t id, SexyAL_format *format, SexyAL_buffering *buffering)
+{
+ SexyAL_device *dev;
+ DSFobby *fobby;
+
+ DSBUFFERDESC DSBufferDesc;
+ DSCAPS dscaps;
+ DSBCAPS dsbcaps;
+
+ dev=malloc(sizeof(SexyAL_device));
+ fobby=malloc(sizeof(DSFobby));
+ memset(fobby,0,sizeof(DSFobby));
+
+ memset(&fobby->wf,0,sizeof(WAVEFORMATEX));
+ fobby->wf.wFormatTag = WAVE_FORMAT_PCM;
+ fobby->wf.nChannels = format->channels;
+ fobby->wf.nSamplesPerSec = format->rate;
+
+ if(DirectSoundCreate(0,&fobby->ppDS,0) != DS_OK)
+ {
+ free(dev);
+ free(fobby);
+ return(0);
+ }
+
+ {
+ //HWND hWnd = GetForegroundWindow(); // Ugly.
+ //if(!hWnd)
+ //{ hWnd=GetDesktopWindow(); exit(1); }
+ HWND hWnd;
+ hWnd=GetDesktopWindow();
+ IDirectSound_SetCooperativeLevel(fobby->ppDS,hWnd,DSSCL_PRIORITY);
+ }
+ memset(&dscaps,0x00,sizeof(dscaps));
+ dscaps.dwSize=sizeof(dscaps);
+ IDirectSound_GetCaps(fobby->ppDS,&dscaps);
+ IDirectSound_Compact(fobby->ppDS);
+
+ /* Create primary buffer */
+ memset(&DSBufferDesc,0x00,sizeof(DSBUFFERDESC));
+ DSBufferDesc.dwSize=sizeof(DSBufferDesc);
+ DSBufferDesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
+
+ if(IDirectSound_CreateSoundBuffer(fobby->ppDS,&DSBufferDesc,&fobby->ppbuf,0) != DS_OK)
+ {
+ IDirectSound_Release(fobby->ppDS);
+ free(dev);
+ free(fobby);
+ return(0);
+ }
+
+ /* Set primary buffer format. */
+ if(format->sampformat == SEXYAL_FMT_PCMU8)
+ fobby->wf.wBitsPerSample=8;
+ else // if(format->sampformat == SEXYAL_FMT_PCMS16)
+ {
+ fobby->wf.wBitsPerSample=16;
+ format->sampformat=SEXYAL_FMT_PCMS16;
+ }
+
+ fobby->wf.nBlockAlign=fobby->wf.wBitsPerSample>>3;
+ fobby->wf.nAvgBytesPerSec=fobby->wf.nSamplesPerSec*fobby->wf.nBlockAlign;
+ if(IDirectSoundBuffer_SetFormat(fobby->ppbuf,&fobby->wf) != DS_OK)
+ {
+ IDirectSound_Release(fobby->ppbuf);
+ IDirectSound_Release(fobby->ppDS);
+ free(dev);
+ free(fobby);
+ return(0);
+ }
+
+ /* Create secondary sound buffer */
+ IDirectSoundBuffer_GetFormat(fobby->ppbuf,&fobby->wf,sizeof(WAVEFORMATEX),0);
+ memset(&DSBufferDesc,0x00,sizeof(DSBUFFERDESC));
+ DSBufferDesc.dwSize=sizeof(DSBufferDesc);
+ DSBufferDesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
+ DSBufferDesc.dwFlags|=DSBCAPS_GLOBALFOCUS;
+ DSBufferDesc.dwBufferBytes=65536;
+ DSBufferDesc.lpwfxFormat=&fobby->wf;
+ if(IDirectSound_CreateSoundBuffer(fobby->ppDS, &DSBufferDesc, &fobby->ppbufsec, 0) != DS_OK)
+ {
+ IDirectSound_Release(fobby->ppbuf);
+ IDirectSound_Release(fobby->ppDS);
+ free(dev);
+ free(fobby);
+ return(0);
+ }
+
+ fobby->DSBufferSize=65536;
+ IDirectSoundBuffer_SetCurrentPosition(fobby->ppbufsec,0);
+ fobby->ppbufw=fobby->ppbufsec;
+
+ memcpy(&dev->format,format,sizeof(SexyAL_format));
+
+ if(!buffering->ms)
+ buffering->ms=53;
+
+ buffering->totalsize=(int64_t)format->rate*buffering->ms/1000;
+ fobby->BufHowMuch=buffering->totalsize* format->channels * (format->sampformat>>4);
+ //printf("%d\n",fobby->BufHowMuch);
+ //fflush(stdout);
+
+ dev->private=fobby;
+ timeBeginPeriod(1);
+
+ return(dev);
+}
+
+uint32_t SexyALI_DSound_RawCanWrite(SexyAL_device *device)
+{
+ DSFobby *tmp=device->private;
+ DWORD CurWritePos,CurPlayPos=0;
+ CheckStatus(tmp);
+
+ CurWritePos=0;
+
+ if(IDirectSoundBuffer_GetCurrentPosition(tmp->ppbufw,&CurPlayPos,&CurWritePos)==DS_OK)
+ {
+ //FCEU_DispMessage("%d",CurWritePos-CurPlayPos);
+ }
+ CurWritePos=(CurPlayPos+tmp->BufHowMuch)%tmp->DSBufferSize;
+
+ /* If the current write pos is >= half the buffer size less than the to write pos,
+ assume DirectSound has wrapped around.
+ */
+
+ if(((int32_t)tmp->ToWritePos-(int32_t)CurWritePos) >= (tmp->DSBufferSize/2))
+ {
+ CurWritePos+=tmp->DSBufferSize;
+ //printf("Fixit: %d,%d,%d\n",tmp->ToWritePos,CurWritePos,CurWritePos-tmp->DSBufferSize);
+ }
+ if(tmp->ToWritePos<CurWritePos)
+ {
+ int32_t howmuch=(int32_t)CurWritePos-(int32_t)tmp->ToWritePos;
+ if(howmuch > tmp->BufHowMuch) /* Oopsie. Severe buffer overflow... */
+ {
+ tmp->ToWritePos=CurWritePos%tmp->DSBufferSize;
+ //IDirectSoundBuffer_Stop(tmp->ppbufsec);
+ //IDirectSoundBuffer_SetCurrentPosition(tmp->ppbufsec,tmp->ToWritePos);
+ //puts("Oops");
+ //fflush(stdout);
+ //return(0);
+ }
+ return(CurWritePos-tmp->ToWritePos);
+ }
+ else
+ return(0);
+}
+
+int SexyALI_DSound_RawWrite(SexyAL_device *device, void *data, uint32_t len)
+{
+ DSFobby *tmp=device->private;
+// uint32_t cw;
+
+ //printf("Pre: %d\n",SexyALI_DSound_RawCanWrite(device));
+ //fflush(stdout);
+
+ CheckStatus(tmp);
+ /* In this block, we write as much data as we can, then we write
+ the rest of it in >=1ms chunks.
+ */
+ while(len)
+ {
+ VOID *LockPtr[2]={0,0};
+ DWORD LockLen[2]={0,0};
+ int32_t curlen;
+
+ while(!(curlen=SexyALI_DSound_RawCanWrite(device)))
+ {
+ Sleep(1);
+ }
+
+ if(curlen>len) curlen=len;
+
+ if(DS_OK == IDirectSoundBuffer_Lock(tmp->ppbufw,tmp->ToWritePos,curlen,&LockPtr[0],&LockLen[0],&LockPtr[1],&LockLen[1],0))
+ {
+ }
+
+ if(LockPtr[1] != 0 && LockPtr[1] != LockPtr[0])
+ {
+ memcpy(LockPtr[0],data,LockLen[0]);
+ memcpy(LockPtr[1],data+LockLen[0],len-LockLen[0]);
+ }
+ else if(LockPtr[0])
+ {
+ memcpy(LockPtr[0],data,curlen);
+ }
+ IDirectSoundBuffer_Unlock(tmp->ppbufw,LockPtr[0],LockLen[0],LockPtr[1],LockLen[1]);
+ tmp->ToWritePos=(tmp->ToWritePos+curlen)%tmp->DSBufferSize;
+
+ len-=curlen;
+ (uint8_t *) data+=curlen;
+ if(len)
+ Sleep(1);
+ } // end while(len) loop
+
+
+ return(1);
+}
+
+
+
+int SexyALI_DSound_Close(SexyAL_device *device)
+{
+ if(device)
+ {
+ if(device->private)
+ {
+ DSFobby *tmp=device->private;
+ if(tmp->ppbufsec)
+ {
+ IDirectSoundBuffer_Stop(tmp->ppbufsec);
+ IDirectSoundBuffer_Release(tmp->ppbufsec);
+ }
+ if(tmp->ppbuf)
+ {
+ IDirectSoundBuffer_Stop(tmp->ppbuf);
+ IDirectSoundBuffer_Release(tmp->ppbuf);
+ }
+ if(tmp->ppDS)
+ {
+ IDirectSound_Release(tmp->ppDS);
+ }
+ free(device->private);
+ }
+ free(device);
+ timeEndPeriod(1);
+ return(1);
+ }
+ return(0);
+}
+
diff --git a/drivers/sexyal/drivers/oss.c b/drivers/sexyal/drivers/oss.c
new file mode 100644
index 00000000..68d9a8c8
--- /dev/null
+++ b/drivers/sexyal/drivers/oss.c
@@ -0,0 +1,241 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sched.h>
+#include <sys/soundcard.h>
+
+#include "../sexyal.h"
+#include "../md5.h"
+#include "../smallc.h"
+
+#include "oss.h"
+
+#define IDBASE 0x1000
+
+void SexyALI_OSS_Enumerate(int (*func)(uint8_t *name, uint64_t id, void *udata), void *udata)
+{
+ struct stat buf;
+ char fn[64];
+ unsigned int n;
+
+ n=0;
+
+ do
+ {
+ sal_strcpy(fn,"/dev/dsp");
+ sal_strcat(fn,sal_uinttos(n));
+ if(stat(fn,&buf)!=0) break;
+ } while(func(fn,n+IDBASE,udata));
+}
+
+static int FODevice(uint64_t id)
+{
+ char fn[64];
+
+ if(id==SEXYAL_ID_DEFAULT)
+ {
+ sal_strcpy(fn,"/dev/dsp");
+ return(open(fn,O_WRONLY));
+ }
+ else if(id==SEXYAL_ID_UNUSED)
+ {
+ int x=-1;
+ int dspfd;
+ do
+ {
+ sal_strcpy(fn,"/dev/dsp");
+ if(x!=-1)
+ sal_strcat(fn,sal_uinttos(x));
+ dspfd=open(fn,O_WRONLY|O_NONBLOCK);
+ if(dspfd!=-1) break;
+ x++;
+ } while(errno!=ENOENT);
+ if(dspfd==-1) return(0);
+ fcntl(dspfd,F_SETFL,fcntl(dspfd,F_GETFL)&~O_NONBLOCK);
+ return(dspfd);
+ }
+ else
+ {
+ sal_strcpy(fn,"/dev/dsp");
+ sal_strcat(fn,sal_uinttos(id-IDBASE));
+ return(open(fn,O_WRONLY));
+ }
+}
+
+unsigned int Log2(unsigned int value)
+{
+ int x=0;
+
+ value>>=1;
+ while(value)
+ {
+ value>>=1;
+ x++;
+ }
+ return(x?x:1);
+}
+
+SexyAL_device *SexyALI_OSS_Open(uint64_t id, SexyAL_format *format, SexyAL_buffering *buffering)
+{
+ SexyAL_device *device;
+ int fd;
+ unsigned int temp;
+
+ if(!(fd=FODevice(id))) return(0);
+
+ /* Set sample format. */
+ /* TODO: Handle devices with byte order different from native byte order. */
+ /* TODO: Fix fragment size calculation to work well with lower/higher playback rates,
+ as reported by OSS.
+ */
+
+ if(format->sampformat == SEXYAL_FMT_PCMU8)
+ temp=AFMT_U8;
+ else if(format->sampformat == SEXYAL_FMT_PCMS8)
+ temp=AFMT_S8;
+ else if(format->sampformat == SEXYAL_FMT_PCMU16)
+ temp=AFMT_U16_LE;
+ else
+ temp=AFMT_S16_NE;
+
+ format->byteorder=0;
+
+ ioctl(fd,SNDCTL_DSP_SETFMT,&temp);
+ switch(temp)
+ {
+ case AFMT_U8: format->sampformat = SEXYAL_FMT_PCMU8;break;
+ case AFMT_S8: format->sampformat = SEXYAL_FMT_PCMS8;break;
+ case AFMT_U16_LE:
+ #ifndef LSB_FIRST
+ format->byteorder=1;
+ #endif
+ format->sampformat = SEXYAL_FMT_PCMU16;break;
+ case AFMT_U16_BE:
+ #ifdef LSB_FIRST
+ format->byteorder=1;
+ #endif
+ format->sampformat = SEXYAL_FMT_PCMU16;break;
+ case AFMT_S16_LE:
+ #ifndef LSB_FIRST
+ format->byteorder=1;
+ #endif
+ format->sampformat = SEXYAL_FMT_PCMS16;break;
+ case AFMT_S16_BE:
+ #ifdef LSB_FIRST
+ format->byteorder=1;
+ #endif
+ format->sampformat = SEXYAL_FMT_PCMS16;break;
+ default: close(fd); return(0);
+ }
+
+ /* Set number of channels. */
+ temp=format->channels;
+ if(ioctl(fd,SNDCTL_DSP_CHANNELS,&temp)==-1)
+ {
+ close(fd);
+ return(0);
+ }
+
+ if(temp<1 || temp>2)
+ {
+ close(fd);
+ return(0);
+ }
+
+ format->channels=temp;
+
+ /* Set frame rate. */
+ temp=format->rate;
+ if(ioctl(fd,SNDCTL_DSP_SPEED,&temp)==-1)
+ {
+ close(fd);
+ return(0);
+ }
+ format->rate=temp;
+ device=malloc(sizeof(SexyAL_device));
+ sal_memcpy(&device->format,format,sizeof(SexyAL_format));
+ sal_memcpy(&device->buffering,buffering,sizeof(SexyAL_buffering));
+
+ if(buffering->fragcount == 0 || buffering->fragsize == 0)
+ {
+ buffering->fragcount=16;
+ buffering->fragsize=64;
+ }
+ else
+ {
+ if(buffering->fragsize<32) buffering->fragsize=32;
+ if(buffering->fragcount<2) buffering->fragcount=2;
+ }
+
+ if(buffering->ms)
+ {
+ int64_t tc;
+
+ //printf("%d\n",buffering->ms);
+
+ /* 2*, >>1, |1 for crude rounding(it will always round 0.5 up, so it is a bit biased). */
+
+ tc=2*buffering->ms * format->rate / 1000 / buffering->fragsize;
+ //printf("%f\n",(double)buffering->ms * format->rate / 1000 / buffering->fragsize);
+ buffering->fragcount=(tc>>1)+(tc&1); //1<<Log2(tc);
+ //printf("%d\n",buffering->fragcount);
+ }
+
+ temp=Log2(buffering->fragsize*(format->sampformat>>4)*format->channels);
+ temp|=buffering->fragcount<<16;
+ ioctl(fd,SNDCTL_DSP_SETFRAGMENT,&temp);
+
+ {
+ audio_buf_info info;
+ ioctl(fd,SNDCTL_DSP_GETOSPACE,&info);
+ buffering->fragsize=info.fragsize/(format->sampformat>>4)/format->channels;
+ buffering->fragcount=info.fragments;
+ buffering->totalsize=buffering->fragsize*buffering->fragcount;
+ //printf("Actual: %d, %d\n",buffering->fragsize,buffering->fragcount);
+ }
+ device->private=malloc(sizeof(int));
+ *(int*)device->private=fd;
+ return(device);
+}
+
+int SexyALI_OSS_Close(SexyAL_device *device)
+{
+ if(device)
+ {
+ if(device->private)
+ {
+ close(*(int*)device->private);
+ free(device->private);
+ }
+ free(device);
+ return(1);
+ }
+ return(0);
+}
+
+uint32_t SexyALI_OSS_RawWrite(SexyAL_device *device, void *data, uint32_t len)
+{
+ ssize_t bytes;
+
+ bytes = write(*(int *)device->private,data,len);
+ if(bytes <= 0) return(0); /* FIXME: What to do on -1? */
+ return(bytes);
+}
+
+uint32_t SexyALI_OSS_RawCanWrite(SexyAL_device *device)
+{
+ struct audio_buf_info ai;
+ if(!ioctl(*(int *)device->private,SNDCTL_DSP_GETOSPACE,&ai))
+ return(ai.bytes);
+ else
+ return(0);
+}
+
diff --git a/drivers/sexyal/drivers/oss.h b/drivers/sexyal/drivers/oss.h
new file mode 100644
index 00000000..b6927508
--- /dev/null
+++ b/drivers/sexyal/drivers/oss.h
@@ -0,0 +1,6 @@
+void SexyALI_OSS_Enumerate(int (*func)(uint8_t *name, uint64_t id, void *udata), void *udata);
+SexyAL_device *SexyALI_OSS_Open(uint64_t id, SexyAL_format *format, SexyAL_buffering *buffering);
+int SexyALI_OSS_Close(SexyAL_device *device);
+uint32_t SexyALI_OSS_RawWrite(SexyAL_device *device, void *data, uint32_t len);
+uint32_t SexyALI_OSS_RawCanWrite(SexyAL_device *device);
+
diff --git a/drivers/sexyal/drivers/osxcoreaudio.c b/drivers/sexyal/drivers/osxcoreaudio.c
new file mode 100644
index 00000000..b2c39a93
--- /dev/null
+++ b/drivers/sexyal/drivers/osxcoreaudio.c
@@ -0,0 +1,5 @@
+#include <AudioHardware.h>
+#include <CoreAudioTypes.h>
+#include <HostTime.h>
+
+
diff --git a/drivers/sexyal/md5.c b/drivers/sexyal/md5.c
new file mode 100644
index 00000000..50299f7f
--- /dev/null
+++ b/drivers/sexyal/md5.c
@@ -0,0 +1,229 @@
+/*
+ * RFC 1321 compliant MD5 implementation,
+ * by Christophe Devine <devine@cr0.net>;
+ * this program is licensed under the GPL.
+ */
+
+/* Modified October 3, 2003, to remove testing code, and add
+ include of "types.h".
+
+ -Xodnizel
+*/
+
+#include <string.h>
+#include "inttypes.h"
+#include "md5.h"
+
+#define GET_UINT32(n,b,i) \
+{ \
+ (n) = ( (uint32_t) (b)[(i) + 3] << 24 ) \
+ | ( (uint32_t) (b)[(i) + 2] << 16 ) \
+ | ( (uint32_t) (b)[(i) + 1] << 8 ) \
+ | ( (uint32_t) (b)[(i) ] ); \
+}
+
+#define PUT_UINT32(n,b,i) \
+{ \
+ (b)[(i) ] = (uint8_t) ( (n) ); \
+ (b)[(i) + 1] = (uint8_t) ( (n) >> 8 ); \
+ (b)[(i) + 2] = (uint8_t) ( (n) >> 16 ); \
+ (b)[(i) + 3] = (uint8_t) ( (n) >> 24 ); \
+}
+
+void sal_md5_starts( struct sal_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 sal_md5_process( struct sal_md5_context *ctx, uint8_t data[64] )
+{
+ uint32_t 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 sal_md5_update( struct sal_md5_context *ctx, uint8_t *input, uint32_t length )
+{
+ uint32_t 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 );
+ sal_md5_process( ctx, ctx->buffer );
+ length -= fill;
+ input += fill;
+ left = 0;
+ }
+
+ while( length >= 64 )
+ {
+ sal_md5_process( ctx, input );
+ length -= 64;
+ input += 64;
+ }
+
+ if( length )
+ {
+ memcpy( (void *) (ctx->buffer + left), (void *) input, length );
+ }
+}
+
+static uint8_t 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 sal_md5_finish( struct sal_md5_context *ctx, uint8_t digest[16] )
+{
+ uint32_t last, padn;
+ uint8_t 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 );
+
+ sal_md5_update( ctx, md5_padding, padn );
+ sal_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 );
+}
diff --git a/drivers/sexyal/md5.h b/drivers/sexyal/md5.h
new file mode 100644
index 00000000..e06e356c
--- /dev/null
+++ b/drivers/sexyal/md5.h
@@ -0,0 +1,15 @@
+#ifndef _MD5_H
+#define _MD5_H
+
+struct sal_md5_context
+{
+ uint32_t total[2];
+ uint32_t state[4];
+ uint8_t buffer[64];
+};
+
+void sal_md5_starts( struct sal_md5_context *ctx );
+void sal_md5_update( struct sal_md5_context *ctx, uint8_t *input, uint32_t length );
+void sal_md5_finish( struct sal_md5_context *ctx, uint8_t digest[16] );
+
+#endif /* md5.h */
diff --git a/drivers/sexyal/sexyal.c b/drivers/sexyal/sexyal.c
new file mode 100644
index 00000000..fc1594c3
--- /dev/null
+++ b/drivers/sexyal/sexyal.c
@@ -0,0 +1,115 @@
+#include <stdlib.h>
+#include <string.h>
+#include "sexyal.h"
+#include "convert.h"
+
+#ifdef WIN32
+
+#else
+#include "drivers/oss.h"
+#endif
+
+static uint32_t FtoB(const SexyAL_format *format, uint32_t frames)
+{
+ return(frames*format->channels*(format->sampformat>>4));
+}
+/*
+static uint32_t BtoF(const SexyAL_format *format, uint32_t bytes)
+{
+ return(bytes / (format->channels * (format->sampformat>>4)));
+}
+*/
+static uint32_t CanWrite(SexyAL_device *device)
+{
+ uint32_t bytes,frames;
+
+ #ifdef WIN32
+ bytes=SexyALI_DSound_RawCanWrite(device);
+ #else
+ bytes=SexyALI_OSS_RawCanWrite(device);
+ #endif
+ frames=bytes / device->format.channels / (device->format.sampformat>>4);
+
+ return(frames);
+}
+
+static uint32_t Write(SexyAL_device *device, void *data, uint32_t frames)
+{
+ uint8_t buffer[2048*4];
+
+ while(frames)
+ {
+ int32_t tmp;
+
+ tmp=frames;
+ if(tmp>2048)
+ {
+ tmp=2048;
+ frames-=2048;
+ }
+ else frames-=tmp;
+
+ SexiALI_Convert(&device->srcformat, &device->format, buffer, data, tmp);
+ //printf("%02x, %02x, %02x\n", device->srcformat.sampformat, device->srcformat.byteorder, device->srcformat.channels);
+ //printf("buffer: %d\n",buffer[0]);
+ /* FIXME: Return the actual number of frame written. It should always equal
+ the number of frames requested to be written, except in cases of sound device
+ failures.
+ */
+ #ifdef WIN32
+ SexyALI_DSound_RawWrite(device,buffer,FtoB(&device->format,tmp));
+ #else
+ SexyALI_OSS_RawWrite(device,buffer,FtoB(&device->format,tmp));
+ #endif
+ }
+ return(frames);
+}
+
+static int Close(SexyAL_device *device)
+{
+ #ifdef WIN32
+ return(SexyALI_DSound_Close(device));
+ #else
+ return(SexyALI_OSS_Close(device));
+ #endif
+}
+
+int SetConvert(struct __SexyAL_device *device, SexyAL_format *format)
+{
+ memcpy(&device->srcformat,format,sizeof(SexyAL_format));
+ return(1);
+}
+
+static SexyAL_device *Open(SexyAL *iface, uint64_t id, SexyAL_format *format, SexyAL_buffering *buffering)
+{
+ SexyAL_device *ret;
+
+ #ifdef WIN32
+ if(!(ret=SexyALI_DSound_Open(id,format,buffering))) return(0);
+ #else
+ if(!(ret=SexyALI_OSS_Open(id,format,buffering))) return(0);
+ #endif
+
+ ret->Write=Write;
+ ret->Close=Close;
+ ret->CanWrite=CanWrite;
+ ret->SetConvert=SetConvert;
+ return(ret);
+}
+
+void Destroy(SexyAL *iface)
+{
+ free(iface);
+}
+
+void *SexyAL_Init(int version)
+{
+ SexyAL *iface;
+ if(!version != 1) return(0);
+
+ iface=malloc(sizeof(SexyAL));
+
+ iface->Open=Open;
+ iface->Destroy=Destroy;
+ return((void *)iface);
+}
diff --git a/drivers/sexyal/sexyal.h b/drivers/sexyal/sexyal.h
new file mode 100644
index 00000000..c2e28884
--- /dev/null
+++ b/drivers/sexyal/sexyal.h
@@ -0,0 +1,52 @@
+#include <inttypes.h>
+
+typedef struct
+{
+ uint32_t sampformat;
+ uint32_t channels; /* 1 = mono, 2 = stereo */
+ uint32_t rate; /* Number of frames per second, 22050, 44100, etc. */
+ uint32_t byteorder; /* 0 = Native(to CPU), 1 = Reversed. PDP can go to hell. */
+} SexyAL_format;
+
+typedef struct
+{
+ uint32_t fragcount;
+ uint32_t fragsize;
+ uint32_t totalsize; /* Shouldn't be filled in by application code. */
+ uint32_t ms; /* Milliseconds of buffering, approximate. */
+} SexyAL_buffering;
+
+#define SEXYAL_ID_DEFAULT 0
+#define SEXYAL_ID_UNUSED 1
+
+#define SEXYAL_FMT_PCMU8 0x10
+#define SEXYAL_FMT_PCMS8 0x11
+
+#define SEXYAL_FMT_PCMU16 0x20
+#define SEXYAL_FMT_PCMS16 0x21
+
+#define SEXYAL_FMT_PCMU32U24 0x40
+#define SEXYAL_FMT_PCMS32S24 0x41
+
+#define SEXYAL_FMT_PCMU32U16 0x42
+#define SEXYAL_FMT_PCMS32S16 0x43
+
+typedef struct __SexyAL_device {
+ int (*SetConvert)(struct __SexyAL_device *, SexyAL_format *);
+ uint32_t (*Write)(struct __SexyAL_device *, void *data, uint32_t frames);
+ uint32_t (*CanWrite)(struct __SexyAL_device *);
+ int (*Close)(struct __SexyAL_device *);
+ SexyAL_format format;
+ SexyAL_format srcformat;
+ SexyAL_buffering buffering;
+ void *private;
+} SexyAL_device;
+
+typedef struct __SexyAL {
+ SexyAL_device * (*Open)(struct __SexyAL *, uint64_t id, SexyAL_format *, SexyAL_buffering *buffering);
+ void (*Enumerate)(struct __SexyAL *, int (*func)(uint8_t *name, uint64_t id, void *udata));
+ void (*Destroy)(struct __SexyAL *);
+} SexyAL;
+
+/* Initializes the library, requesting the interface of the version specified. */
+void *SexyAL_Init(int version);
diff --git a/drivers/sexyal/smallc.c b/drivers/sexyal/smallc.c
new file mode 100644
index 00000000..4aa95091
--- /dev/null
+++ b/drivers/sexyal/smallc.c
@@ -0,0 +1,63 @@
+#include "smallc.h"
+
+void sal_memcpy(void *dest, const void *src, uint32_t n)
+{
+ while(n--)
+ {
+ *(uint8_t*)dest=*(uint8_t *)src;
+ (uint8_t*)dest++;
+ (uint8_t*)src++;
+ }
+}
+
+uint32_t sal_strlen(const char *buf)
+{
+ uint32_t size=0;
+
+ while(*buf++) size++;
+
+ return(size);
+}
+
+void sal_strcpy(char *dest, const char *src)
+{
+ while(*src)
+ *dest++ = *src++;
+ *dest=0;
+}
+
+void sal_strcat(char *dest, const char *src)
+{
+ while(*dest)
+ dest++;
+ while(*src)
+ *dest++ = *src++;
+ *dest=0;
+}
+
+const char *sal_uinttos(int value)
+{
+ static char buf[64],buf2[64];
+ char *tmp;
+ int len=0;
+
+ tmp=buf;
+
+ while(value)
+ {
+ *tmp='0'+(value%10);
+ len++;
+ tmp++;
+ value/=10;
+ }
+
+ tmp=buf2;
+ while(len-- >= 0)
+ {
+ *tmp=buf[len];
+ tmp++;
+ }
+
+ *tmp=0;
+ return(buf2);
+}
diff --git a/drivers/sexyal/smallc.h b/drivers/sexyal/smallc.h
new file mode 100644
index 00000000..86856b1e
--- /dev/null
+++ b/drivers/sexyal/smallc.h
@@ -0,0 +1,7 @@
+#include <inttypes.h>
+
+void sal_memcpy(void *dest, const void *src, uint32_t n);
+void sal_strcpy(char *dest, const char *src);
+const char *sal_uinttos(int value);
+void sal_strcat(char *dest, const char *src);
+
diff --git a/drivers/win/Makefile.am.inc b/drivers/win/Makefile.am.inc
new file mode 100644
index 00000000..fdfdb758
--- /dev/null
+++ b/drivers/win/Makefile.am.inc
@@ -0,0 +1,5 @@
+.res.o:
+ windres -o $@ $<
+
+fceud_SOURCES = drivers/win/cheat.c drivers/win/debug.c drivers/win/input.c drivers/win/joystick.c drivers/win/keyboard.c drivers/win/log.c drivers/win/main.c drivers/win/netplay.c drivers/win/ppuview.c drivers/win/aviout.c drivers/win/memwatch.c drivers/win/basicbot.c drivers/win/res.res
+
diff --git a/drivers/win/args.c b/drivers/win/args.c
new file mode 100644
index 00000000..d462a760
--- /dev/null
+++ b/drivers/win/args.c
@@ -0,0 +1,40 @@
+/* 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 "../common/args.h"
+
+char *ParseArgies(int argc, char *argv[])
+{
+ int x;
+ static ARGPSTRUCT FCEUArgs[]={
+ {"-pal",0,&palyo,0},
+ {"-noicon",0,&status_icon,0},
+ {"-gg",0,&genie,0},
+ {"-no8lim",0,&eoptions,0x8000|EO_NOSPRLIM},
+ //{"-nofs",0,&eoptions,0},
+ {"-clipsides",0,&eoptions,0x8000|EO_CLIPSIDES},
+ {"-nothrottle",0,&eoptions,0x8000|EO_NOTHROTTLE},
+ };
+
+ if(argc<=1) return(0);
+
+ ParseArguments(argc-2, &argv[1], FCEUArgs);
+ return(argv[argc-1]);
+}
diff --git a/drivers/win/aviout.c b/drivers/win/aviout.c
new file mode 100644
index 00000000..f24ec50c
--- /dev/null
+++ b/drivers/win/aviout.c
@@ -0,0 +1,412 @@
+#include <windows.h>
+#include <vfw.h>
+#include <stdio.h>
+
+#include "common.h"
+
+extern PALETTEENTRY color_palette[256];
+extern WAVEFORMATEX wf;
+extern int soundo;
+
+#define VIDEO_STREAM 0
+#define AUDIO_STREAM 1
+
+#define VIDEO_WIDTH 256
+
+static struct AVIFile
+{
+ int valid;
+ int fps;
+ int fps_scale;
+
+ int video_added;
+ BITMAPINFOHEADER bitmap_format;
+
+ int sound_added;
+ WAVEFORMATEX wave_format;
+
+ AVISTREAMINFO avi_video_header;
+ AVISTREAMINFO avi_sound_header;
+ PAVIFILE avi_file;
+ PAVISTREAM streams[2];
+ PAVISTREAM compressed_streams[2];
+
+ AVICOMPRESSOPTIONS compress_options[2];
+ AVICOMPRESSOPTIONS* compress_options_ptr[2];
+
+ int video_frames;
+ int sound_samples;
+
+ uint8* convert_buffer;
+ int start_scanline;
+ int end_scanline;
+
+ long tBytes, ByteBuffer;
+} *avi_file = NULL;
+
+struct VideoSystemInfo
+{
+ int start_scanline;
+ int end_scanline;
+ int fps;
+};
+
+
+static char saved_cur_avi_fnameandext[MAX_PATH];
+static char saved_avi_fname[MAX_PATH];
+static char saved_avi_ext[MAX_PATH];
+static int avi_segnum=0;
+//static FILE* avi_check_file=0;
+static struct AVIFile saved_avi_info;
+static int use_prev_options=0;
+
+
+
+static int truncate_existing(const char* filename)
+{
+ // this is only here because AVIFileOpen doesn't seem to do it for us
+ FILE* fd = FCEUD_UTF8fopen(filename, "wb");
+ if(fd)
+ {
+ fclose(fd);
+ return 1;
+ }
+
+ return 0;
+}
+
+static void avi_create(struct AVIFile** avi_out)
+{
+ *avi_out = (struct AVIFile*)malloc(sizeof(struct AVIFile));
+ memset(*avi_out, 0, sizeof(struct AVIFile));
+ AVIFileInit();
+}
+
+static void avi_destroy(struct AVIFile** avi_out)
+{
+ if(!(*avi_out))
+ return;
+
+ if((*avi_out)->sound_added)
+ {
+ if((*avi_out)->compressed_streams[AUDIO_STREAM])
+ {
+ AVIStreamClose((*avi_out)->compressed_streams[AUDIO_STREAM]);
+ (*avi_out)->compressed_streams[AUDIO_STREAM] = NULL;
+ (*avi_out)->streams[AUDIO_STREAM] = NULL; // compressed_streams[AUDIO_STREAM] is just a copy of streams[AUDIO_STREAM]
+ }
+ }
+
+ if((*avi_out)->video_added)
+ {
+ if((*avi_out)->compressed_streams[VIDEO_STREAM])
+ {
+ AVIStreamClose((*avi_out)->compressed_streams[VIDEO_STREAM]);
+ (*avi_out)->compressed_streams[VIDEO_STREAM] = NULL;
+ }
+
+ if((*avi_out)->streams[VIDEO_STREAM])
+ {
+ AVIStreamClose((*avi_out)->streams[VIDEO_STREAM]);
+ (*avi_out)->streams[VIDEO_STREAM] = NULL;
+ }
+ }
+
+ if((*avi_out)->avi_file)
+ {
+ AVIFileClose((*avi_out)->avi_file);
+ (*avi_out)->avi_file = NULL;
+ }
+
+ free((*avi_out)->convert_buffer);
+ free(*avi_out);
+ *avi_out = NULL;
+}
+
+static void set_video_format(const BITMAPINFOHEADER* bitmap_format, struct AVIFile* avi_out)
+{
+ memcpy(&((*avi_out).bitmap_format), bitmap_format, sizeof(BITMAPINFOHEADER));
+ (*avi_out).video_added = 1;
+}
+
+static void set_sound_format(const WAVEFORMATEX* wave_format, struct AVIFile* avi_out)
+{
+ memcpy(&((*avi_out).wave_format), wave_format, sizeof(WAVEFORMATEX));
+ (*avi_out).sound_added = 1;
+}
+
+static int avi_open(const char* filename, const BITMAPINFOHEADER* pbmih, const WAVEFORMATEX* pwfex, const struct VideoSystemInfo* vsi)
+{
+ int error = 1;
+ int result = 0;
+
+ do
+ {
+ // close existing first
+ FCEUI_AviEnd();
+
+ if(!truncate_existing(filename))
+ break;
+
+ if(!pbmih)
+ break;
+
+ // create the object
+ avi_create(&avi_file);
+
+ // set video size and framerate
+ avi_file->start_scanline = vsi->start_scanline;
+ avi_file->end_scanline = vsi->end_scanline;
+ avi_file->fps = vsi->fps;
+ avi_file->fps_scale = 16777216-1;
+ avi_file->convert_buffer = (uint8*)malloc(VIDEO_WIDTH*(vsi->end_scanline-vsi->start_scanline)*3);
+
+ // open the file
+ if(FAILED(AVIFileOpen(&avi_file->avi_file, filename, OF_CREATE | OF_WRITE, NULL)))
+ break;
+
+ // create the video stream
+ set_video_format(pbmih, avi_file);
+
+ memset(&avi_file->avi_video_header, 0, sizeof(AVISTREAMINFO));
+ avi_file->avi_video_header.fccType = streamtypeVIDEO;
+ avi_file->avi_video_header.dwScale = avi_file->fps_scale;
+ avi_file->avi_video_header.dwRate = avi_file->fps;
+ avi_file->avi_video_header.dwSuggestedBufferSize = avi_file->bitmap_format.biSizeImage;
+ if(FAILED(AVIFileCreateStream(avi_file->avi_file, &avi_file->streams[VIDEO_STREAM], &avi_file->avi_video_header)))
+ break;
+
+ if(use_prev_options)
+ {
+ avi_file->compress_options[VIDEO_STREAM] = saved_avi_info.compress_options[VIDEO_STREAM];
+ avi_file->compress_options_ptr[VIDEO_STREAM] = &avi_file->compress_options[0];
+ }
+ else
+ {
+ // get compression options
+ memset(&avi_file->compress_options[VIDEO_STREAM], 0, sizeof(AVICOMPRESSOPTIONS));
+ avi_file->compress_options_ptr[VIDEO_STREAM] = &avi_file->compress_options[0];
+retryAviSaveOptions:
+ error = 0;
+ if(!AVISaveOptions(hAppWnd, 0, 1, &avi_file->streams[VIDEO_STREAM], &avi_file->compress_options_ptr[VIDEO_STREAM]))
+ break;
+ error = 1;
+ }
+
+ // create compressed stream
+ if(FAILED(AVIMakeCompressedStream(&avi_file->compressed_streams[VIDEO_STREAM], avi_file->streams[VIDEO_STREAM], &avi_file->compress_options[VIDEO_STREAM], NULL)))
+ break;
+
+ // set the stream format
+ if(FAILED(AVIStreamSetFormat(avi_file->compressed_streams[VIDEO_STREAM], 0, (void*)&avi_file->bitmap_format, avi_file->bitmap_format.biSize)))
+ break;
+
+ // add sound (if requested)
+ if(pwfex)
+ {
+ // add audio format
+ set_sound_format(pwfex, avi_file);
+
+ // create the audio stream
+ memset(&avi_file->avi_sound_header, 0, sizeof(AVISTREAMINFO));
+ avi_file->avi_sound_header.fccType = streamtypeAUDIO;
+ avi_file->avi_sound_header.dwQuality = (DWORD)-1;
+ avi_file->avi_sound_header.dwScale = avi_file->wave_format.nBlockAlign;
+ avi_file->avi_sound_header.dwRate = avi_file->wave_format.nAvgBytesPerSec;
+ avi_file->avi_sound_header.dwSampleSize = avi_file->wave_format.nBlockAlign;
+ avi_file->avi_sound_header.dwInitialFrames = 1;
+ if(FAILED(AVIFileCreateStream(avi_file->avi_file, &avi_file->streams[AUDIO_STREAM], &avi_file->avi_sound_header)))
+ break;
+
+ // AVISaveOptions doesn't seem to work for audio streams
+ // so here we just copy the pointer for the compressed stream
+ avi_file->compressed_streams[AUDIO_STREAM] = avi_file->streams[AUDIO_STREAM];
+
+ // set the stream format
+ if(FAILED(AVIStreamSetFormat(avi_file->compressed_streams[AUDIO_STREAM], 0, (void*)&avi_file->wave_format, sizeof(WAVEFORMATEX))))
+ break;
+ }
+
+ // initialize counters
+ avi_file->video_frames = 0;
+ avi_file->sound_samples = 0;
+ avi_file->tBytes = 0;
+ avi_file->ByteBuffer = 0;
+
+ // success
+ error = 0;
+ result = 1;
+ avi_file->valid = 1;
+
+ } while(0);
+
+ if(!result)
+ {
+ avi_destroy(&avi_file);
+ if(error)
+ FCEUD_PrintError("Error writing AVI file");
+ }
+
+ return result;
+}
+
+static void do_video_conversion(const unsigned char* buffer)
+{
+#define BPP (3) // 24-bit
+// memset(avi_file->convert_buffer, 0, VIDEO_WIDTH*(avi_file->end_scanline-avi_file->start_scanline)*BPP);
+
+ buffer += avi_file->start_scanline * VIDEO_WIDTH;
+
+ int y;
+ for(y=avi_file->start_scanline; y<avi_file->end_scanline; ++y)
+ {
+ uint8* pix = avi_file->convert_buffer + (avi_file->end_scanline-1-y)*VIDEO_WIDTH*BPP;
+ const uint8* prevbuf = buffer;
+
+ register int x;
+ for(x=0; x<VIDEO_WIDTH; ++x)
+ {
+ register const char* cp = (const char*)(color_palette + *buffer++)+2;
+ *pix++ = *cp--;
+ *pix++ = *cp--;
+ *pix++ = *cp;
+ }
+
+ buffer = prevbuf + VIDEO_WIDTH;
+ }
+}
+
+//------------------------------------
+//
+// Interface implementation
+//
+//------------------------------------
+
+
+
+static int FCEUI_AviNextSegment()
+{
+ char avi_fname[MAX_PATH];
+ strcpy(avi_fname,saved_avi_fname);
+ char avi_fname_temp[MAX_PATH];
+ sprintf(avi_fname_temp, "%s_part%d%s", avi_fname, avi_segnum+2, saved_avi_ext);
+ saved_avi_info=*avi_file;
+ use_prev_options=1;
+ avi_segnum++;
+ int ret = FCEUI_AviBegin(avi_fname_temp);
+ use_prev_options=0;
+ strcpy(saved_avi_fname,avi_fname);
+ return ret;
+}
+
+
+int FCEUI_AviBegin(const char* fname)
+{
+ FCEUI_AviEnd();
+
+ struct VideoSystemInfo vsi;
+ BITMAPINFOHEADER bi;
+ const WAVEFORMATEX* wfex = NULL;
+ int is_pal;
+
+ is_pal=FCEUI_GetCurrentVidSystem(&vsi.start_scanline, &vsi.end_scanline);
+ vsi.fps = FCEUI_GetDesiredFPS();//is_pal ? 50 : 60;
+ vsi.end_scanline++;
+
+ memset(&bi, 0, sizeof(bi));
+ bi.biSize = 0x28;
+ bi.biPlanes = 1;
+ bi.biBitCount = 24;
+ bi.biWidth = VIDEO_WIDTH;
+ bi.biHeight = vsi.end_scanline-vsi.start_scanline;
+ bi.biSizeImage = 3 * bi.biWidth * bi.biHeight;
+
+ if(soundo)
+ wfex = &wf;
+
+ saved_avi_ext[0]='\0';
+
+ if(!avi_open(fname, &bi, wfex, &vsi))
+ {
+ saved_avi_fname[0]='\0';
+ return 0;
+ }
+
+ // Don't display at file splits
+ if(!avi_segnum)
+ FCEU_DispMessage("AVI recording started.");
+
+ strncpy(saved_cur_avi_fnameandext,fname,MAX_PATH);
+ strncpy(saved_avi_fname,fname,MAX_PATH);
+ char* dot = strrchr(saved_avi_fname, '.');
+ if(dot && dot > strrchr(saved_avi_fname, '/') && dot > strrchr(saved_avi_fname, '\\'))
+ {
+ strcpy(saved_avi_ext,dot);
+ dot[0]='\0';
+ }
+ return 1;
+}
+
+void FCEUI_AviVideoUpdate(const unsigned char* buffer)
+{
+ if(!avi_file || !avi_file->valid)
+ return;
+
+ do_video_conversion(buffer);
+
+ if(FAILED(AVIStreamWrite(avi_file->compressed_streams[VIDEO_STREAM],
+ avi_file->video_frames, 1, avi_file->convert_buffer,
+ avi_file->bitmap_format.biSizeImage, AVIIF_KEYFRAME,
+ NULL, &avi_file->ByteBuffer)))
+ {
+ avi_file->valid = 0;
+ return;
+ }
+
+ avi_file->video_frames++;
+ avi_file->tBytes += avi_file->ByteBuffer;
+
+ // segment / split AVI when it's almost 2 GB (2000MB, to be precise)
+ if(!(avi_file->video_frames % 60) && avi_file->tBytes > 2097152000)
+ FCEUI_AviNextSegment();
+}
+
+void FCEUI_AviSoundUpdate(void* soundData, int soundLen)
+{
+ int nBytes;
+
+ if(!avi_file || !avi_file->valid || !avi_file->sound_added)
+ return;
+
+ nBytes = soundLen * avi_file->wave_format.nBlockAlign;
+ if(FAILED(AVIStreamWrite(avi_file->compressed_streams[AUDIO_STREAM],
+ avi_file->sound_samples, soundLen,
+ soundData, nBytes, 0, NULL, &avi_file->ByteBuffer)))
+ {
+ avi_file->valid = 0;
+ return;
+ }
+
+ avi_file->sound_samples += soundLen;
+ avi_file->tBytes += avi_file->ByteBuffer;
+}
+
+void FCEUI_AviEnd()
+{
+ if(!avi_file)
+ return;
+
+ // Don't display if we're just starting another segment
+ if(avi_file->tBytes <= 2097152000)
+ FCEU_DispMessage("AVI recording ended.");
+
+ avi_destroy(&avi_file);
+}
+
+int FCEUI_AviIsRecording()
+{
+ if(avi_file)
+ return 1;
+
+ return 0;
+}
diff --git a/drivers/win/basicbot.c b/drivers/win/basicbot.c
new file mode 100644
index 00000000..d16af8f3
--- /dev/null
+++ b/drivers/win/basicbot.c
@@ -0,0 +1,933 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2006 Luke Gustafson
+ *
+ * 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 "common.h"
+
+#include "basicbot.h"
+
+static HWND hwndBasicBot=0;
+static int BotRunning = 0;
+static uint32 rand1=1, rand2=0x1337EA75, rand3=0x0BADF00D;
+static char Formula[24][1024];
+static int BotCounter[256];
+static int EditPlayer = 1, BotFrame, BotLoopVar = 0;
+static int BotAttempts, BotFrames, BotBestScore[4], NewAttempt;
+static int CurrentAttempt[1024], BestAttempt[1024], AttemptPointer;
+static int DoAddCounter = 1;
+char *BasicBotDir = 0;
+
+static void SeedRandom(uint32 seed)
+{
+ rand1 = seed;
+ if(rand1 == 0) rand1 = 1; //I forget if this is necessary.
+}
+
+//Simulation-quality random numbers: taus88 algorithm
+static unsigned int NextRandom(void)
+{
+ uint32 b;
+ b = (((rand1 << 13) ^ rand1) >> 19);
+ rand1 = (((rand1 & 4294967294U) << 12) ^ b);
+ b = (((rand2 << 2) ^ rand2) >> 25);
+ rand2 = (((rand2 & 4294967288U) << 4) ^ b);
+ b = (((rand3 << 3) ^ rand3) >> 11);
+ rand3 = (((rand3 & 4294967280U) << 17) ^ b);
+ return (rand1 ^ rand2 ^ rand3);
+}
+
+//Should do something to notify user of an error... eh
+//void BotError()
+//{
+//
+//}
+
+//recursively evaluate the formula
+//horribly hacky, not meant to be a real expression evaluator!
+int EvaluateFormula(char * formula, char **nextposition)
+{
+ char *currentchar = formula;
+ int value=0;
+ int hexmode = 0;
+ while(1)
+ {
+ switch(*currentchar)
+ {
+ case 0:
+ *nextposition = currentchar;
+ return value;
+ case '(':
+ value = EvaluateFormula(currentchar + 1, &currentchar);
+ break;
+ case ')':
+ case ':':
+ *nextposition = currentchar + 1;
+ return value;
+ case 'x':
+ hexmode=1;
+ currentchar++;
+ break;
+ case '+':
+ return (value + EvaluateFormula(currentchar+1, nextposition));
+ case '-':
+ return (value - EvaluateFormula(currentchar+1, nextposition));
+ case '*':
+ return (value * EvaluateFormula(currentchar+1, nextposition));
+ case '/':
+ return (value / EvaluateFormula(currentchar+1, nextposition));
+ case '%':
+ return (value % EvaluateFormula(currentchar+1, nextposition));
+ case '&':
+ return (value & EvaluateFormula(currentchar+1, nextposition));
+ case '|':
+ return (value | EvaluateFormula(currentchar+1, nextposition));
+ case '^':
+ return (value ^ EvaluateFormula(currentchar+1, nextposition));
+ case '=':
+ return (value == EvaluateFormula(currentchar+1, nextposition) ? 1000: 0);
+ case '>':
+ if(*(currentchar + 1) == '=')
+ return (value >= EvaluateFormula(currentchar+2, nextposition) ? 1000: 0);
+ else
+ return (value > EvaluateFormula(currentchar+1, nextposition) ? 1000: 0);
+ case '<':
+ if(*(currentchar + 1) == '=')
+ return (value <= EvaluateFormula(currentchar+2, nextposition) ? 1000: 0);
+ else
+ return (value < EvaluateFormula(currentchar+1, nextposition) ? 1000: 0);
+ case '!':
+ if(*(currentchar + 1) == '=')
+ {
+ return (value != EvaluateFormula(currentchar+2, nextposition) ? 1000: 0);
+ }
+ else
+ {
+ //BotError();
+ currentchar++;
+ }
+ case '?':
+ {
+ int temp,temp2=DoAddCounter;
+ if(value)
+ {
+ temp = EvaluateFormula(currentchar+1,&currentchar);
+ DoAddCounter = 0;
+ EvaluateFormula(currentchar,&currentchar);
+ DoAddCounter = temp2;
+ value= temp;
+ }
+ else
+ {
+ DoAddCounter = 0;
+ EvaluateFormula(currentchar+1,&currentchar);
+ DoAddCounter = temp2;
+ temp = EvaluateFormula(currentchar,&currentchar);
+ value= temp;
+ }
+ }
+ case ' ':
+ currentchar++;
+ break;
+ case 'a':
+ if(*(currentchar+1) == 't'
+ &&*(currentchar+2) == 't'
+ &&*(currentchar+3) == 'e'
+ &&*(currentchar+4) == 'm'
+ &&*(currentchar+5) == 'p'
+ &&*(currentchar+6) == 't')
+ {
+ currentchar+=7;
+ value = BotAttempts;
+ }
+ else if(*(currentchar+1) == 'd'
+ &&*(currentchar+2) == 'd'
+ &&*(currentchar+3) == 'c'
+ &&*(currentchar+4) == 'o'
+ &&*(currentchar+5) == 'u'
+ &&*(currentchar+6) == 'n'
+ &&*(currentchar+7) == 't'
+ &&*(currentchar+8) == 'e'
+ &&*(currentchar+9) == 'r'
+ &&*(currentchar+10)== '(')
+ {
+ currentchar += 11;
+ if(DoAddCounter)
+ {
+ value = (BotCounter[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 256] += value);
+ }
+ }
+ else if(*(currentchar+1) == 'b'
+ &&*(currentchar+2) == 's'
+ &&*(currentchar+3) == '(')
+ {
+ currentchar += 4;
+ value = EvaluateFormula(currentchar, &currentchar);
+ if(value < 0) value = -value;
+ }
+ else if(*(currentchar+1) == 'c'
+ &&*(currentchar+2) == '(')
+ {
+ currentchar += 3;
+ if(DoAddCounter)
+ {
+ value = (BotCounter[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 256] += value);
+ }
+ }
+ else
+ {
+ value = 1;
+ currentchar++;
+ }
+ break;
+ case 'b':
+ if(*(currentchar+1) == 'u'
+ &&*(currentchar+2) == 't'
+ &&*(currentchar+3) == 't'
+ &&*(currentchar+4) == 'o'
+ &&*(currentchar+5) == 'n')
+ {
+ currentchar += 6;
+ value &= BotInput[1];
+ }
+ else
+ {
+ value = 2;
+ currentchar++;
+ }
+ break;
+ case 'c':
+ if(*(currentchar+1) == 'o'
+ && *(currentchar+2) == 'u'
+ && *(currentchar+3) == 'n'
+ && *(currentchar+4) == 't'
+ && *(currentchar+5) == 'e'
+ && *(currentchar+6) == 'r'
+ && *(currentchar+7) == '(')
+ {
+ currentchar += 8;
+ value = BotCounter[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 256];
+ }
+ else if(*(currentchar+1) == '(')
+ {
+ currentchar += 2;
+ value = BotCounter[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 256];
+ }
+ else
+ {
+ //BotError();
+ currentchar++;
+ }
+ break;
+ case 'd':
+ if(*(currentchar+1) == 'o'
+ &&*(currentchar+2) == 'w'
+ &&*(currentchar+3) == 'n')
+ {
+ currentchar += 4;
+ value = 32;
+ }
+ else
+ {
+ currentchar++;
+ }
+ break;
+ case 'f':
+ if(*(currentchar+1) == 'r'
+ && *(currentchar+2) == 'a'
+ && *(currentchar+3) == 'm'
+ && *(currentchar+4) == 'e')
+ {
+ currentchar+= 5;
+ value = BotFrame;
+ }
+ else
+ {
+ //BotError();
+ currentchar++;
+ }
+ break;
+ case 'i':
+ value = BotLoopVar;
+ currentchar++;
+ break;
+ case 'l':
+ if(*(currentchar+1) == 'e'
+ &&*(currentchar+2) == 'f'
+ &&*(currentchar+3) == 't')
+ {
+ currentchar += 4;
+ value = 64;
+ }
+ else if(*(currentchar+1) == 'o'
+ &&*(currentchar+2) == 'o'
+ &&*(currentchar+3) == 'p'
+ &&*(currentchar+4) == '(')
+ {
+ if(value > 0)
+ {
+ currentchar += 5;
+ if(BotLoopVar == 0)
+ {
+ for(BotLoopVar = 1; BotLoopVar < value && BotLoopVar < 65536; BotLoopVar++)
+ {
+ EvaluateFormula(currentchar, nextposition);
+ }
+ BotLoopVar = 0;
+ EvaluateFormula(currentchar, &currentchar);
+ }
+ else
+ {
+ //BotError();
+ }
+ }
+ else
+ {
+ int temp = DoAddCounter;
+ currentchar += 5;
+ DoAddCounter = 0;
+ EvaluateFormula(currentchar, &currentchar);
+ DoAddCounter = temp;
+ }
+ }
+ else
+ {
+ currentchar++;
+ }
+ break;
+ case 'm':
+ if(*(currentchar+1) == 'e'
+ &&*(currentchar+2) == 'm'
+ &&*(currentchar+3) == '(')
+ {
+ currentchar += 4;
+ int temp = (EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 65536;
+ value = ARead[temp](temp);
+ }
+ else
+ {
+ currentchar++;
+ }
+ break;
+ case 'r':
+ if(*(currentchar+1) == 'a'
+ &&*(currentchar+2) == 'm'
+ &&*(currentchar+3) == '(')
+ {
+ currentchar += 4;
+ value = RAM[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 2048];
+ }
+ else if(*(currentchar+1) == 'i'
+ &&*(currentchar+2) == 'g'
+ &&*(currentchar+3) == 'h'
+ &&*(currentchar+4) == 't')
+ {
+ currentchar += 5;
+ value = 128;
+ }
+ else if(*(currentchar+1) == 'e'
+ &&*(currentchar+2) == 's'
+ &&*(currentchar+3) == 'e'
+ &&*(currentchar+4) == 't'
+ &&*(currentchar+5) == 'c'
+ &&*(currentchar+6) == 'o'
+ &&*(currentchar+7) == 'u'
+ &&*(currentchar+8) == 'n'
+ &&*(currentchar+9) == 't'
+ &&*(currentchar+10) == 'e'
+ &&*(currentchar+11) == 'r'
+ &&*(currentchar+12) == '(')
+ {
+ currentchar += 13;
+ if(DoAddCounter) BotCounter[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 256] = 0;
+ value = 0;
+ }
+ else if(*(currentchar+1) == 'c'
+ &&*(currentchar+2) == '(')
+ {
+ currentchar += 3;
+ if(DoAddCounter) BotCounter[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 256] = 0;
+ value = 0;
+ }
+ else
+ {
+ currentchar++;
+ }
+ break;
+ case 's':
+ if(*(currentchar+1) == 't'
+ &&*(currentchar+2) == 'a'
+ &&*(currentchar+3) == 'r'
+ &&*(currentchar+4) == 't')
+ {
+ currentchar += 5;
+ value = 8;
+ }
+ else if(*(currentchar+1) == 'e'
+ &&*(currentchar+2) == 'l'
+ &&*(currentchar+3) == 'e'
+ &&*(currentchar+4) == 'c'
+ &&*(currentchar+5) == 't')
+ {
+ currentchar += 6;
+ value = 4;
+ }
+ else if(*(currentchar+1) == 'e'
+ &&*(currentchar+2) == 't'
+ &&*(currentchar+3) == 'c'
+ &&*(currentchar+4) == 'o'
+ &&*(currentchar+5) == 'u'
+ &&*(currentchar+6) == 'n'
+ &&*(currentchar+7) == 't'
+ &&*(currentchar+8) == 'e'
+ &&*(currentchar+9) == 'r'
+ &&*(currentchar+10) == '(')
+ {
+ currentchar += 11;
+ if(DoAddCounter) BotCounter[(EvaluateFormula(currentchar, &currentchar) & 0x7FFFFFFF) % 256] = value;
+ }
+ else
+ {
+ currentchar++;
+ }
+ break;
+ case 'u':
+ if(*(currentchar+1) == 'p')
+ {
+ currentchar += 2;
+ value = 16;
+ }
+ else
+ {
+ currentchar++;
+ }
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ value *= hexmode?16:10;
+ value += *currentchar - '0';
+ currentchar++;
+ break;
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ if(hexmode)
+ {
+ value *= 16;
+ value += *currentchar - 'A' + 10;
+ }
+ else
+ {
+ // BotError();
+ }
+ currentchar++;
+ break;
+ default:
+ currentchar++;
+ break;
+ }
+ }
+ return 0;
+}
+
+//Update BasicBot input
+void UpdateBasicBot()
+{
+ if(hwndBasicBot && BotRunning)
+ {
+ int i,j,k;
+ char *dummy = "dum";
+
+ if(BotInput[0])
+ return;
+
+ //Create the bot output...
+ BotInput[0] = 1;
+ if(NewAttempt)
+ {
+ BotInput[1] = 65536;
+ NewAttempt = 0;
+ AttemptPointer = 0;
+ BotFrame = 0;
+ memset(BotCounter, 0, 1024);
+ }
+ else
+ {
+ //Check if goal is met
+ if(BotFrame > 1020 || (int) (NextRandom() % 1000) < EvaluateFormula(Formula[20], &dummy))
+ {
+ int currentscore[4];
+ int better = 0;
+
+ NewAttempt = 1;
+
+ //Check if better score
+ for(i=0; i < 4; i++)
+ {
+ currentscore[i] = EvaluateFormula(Formula[16+i], &dummy);
+ }
+ for(i=0; i < 4; i++)
+ {
+ if(currentscore[i] > BotBestScore[i])
+ {
+ better = 1;
+ break;
+ }
+ else if(currentscore[i] < BotBestScore[i])
+ {
+ break;
+ }
+ }
+ //Update best
+ if(better)
+ {
+ char tempstring[4096];
+ char symbols[16] = "ABET^v<>ABET^v<>";
+ int seenplayer2=0;
+ for(i = 0; i < 4; i++)
+ {
+ BotBestScore[i] = currentscore[i];
+ }
+ for(i = 0; i < AttemptPointer; i++)
+ {
+ BestAttempt[i] = CurrentAttempt[i];
+ }
+ for(; i < 1024; i++)
+ {
+ BestAttempt[i] = -1;
+ }
+ sprintf(tempstring, "%d %d %d %d (%d attempt)", BotBestScore[0], BotBestScore[1], BotBestScore[2], BotBestScore[3], BotAttempts);
+ SetDlgItemText(hwndBasicBot,1018,tempstring);
+ memset(tempstring, 0, 4096);
+ k = 0;
+
+ //Make output as text
+ for(i = 0; i < 1024 && BestAttempt[i] != -1 && k < 4095; i++)
+ {
+ tempstring[k] = '0' + ((i/10) % 10);
+ k++;
+ tempstring[k] = '0' + (i%10);
+ k++;
+ tempstring[k] = '.';
+ k++;
+ seenplayer2=0;
+ for(j = 0; j < 16; j++)
+ {
+ if(BestAttempt[i] & (1 << j))
+ {
+ if(j >= 8 && seenplayer2==0)
+ {
+ seenplayer2=1;
+ tempstring[k]=',';
+ k++;
+ }
+ tempstring[k] = symbols[j];
+ k++;
+ }
+ }
+ tempstring[k] = ' ';
+ k++;
+ }
+ SetDlgItemText(hwndBasicBot,1019,tempstring);
+ }
+ }
+ else //Goal not met
+ {
+ //Generate 1 frame of output
+ BotInput[1] = 0;
+
+ for(i=0;i<16;i++)
+ {
+ if((int) (NextRandom() % 1000) < EvaluateFormula(Formula[i], &dummy))
+ {
+ BotInput[1] |= 1 << i;
+ }
+ }
+
+ //Save what we've done
+ if(AttemptPointer < 1024)
+ {
+ CurrentAttempt[AttemptPointer] = BotInput[1];
+ AttemptPointer++;
+ }
+
+ //Run extra commands
+ EvaluateFormula(Formula[21],&dummy);
+ EvaluateFormula(Formula[22],&dummy);
+ }
+ }
+
+ //Update statistics
+ if(BotInput[1] == 65536)
+ {
+ BotAttempts++;
+ }
+ else
+ {
+ BotFrames++;
+ BotFrame++;
+ }
+ if(BotFrames % 100 == 0)
+ {
+ SetDlgItemInt(hwndBasicBot,1037,BotAttempts,FALSE);
+ SetDlgItemInt(hwndBasicBot,1017,BotFrames,FALSE);
+ }
+ }
+}
+
+static void SaveBasicBot()
+{
+ const char filter[]="Basic Bot(*.bot)\0*.bot\0";
+ char nameo[2048];
+ OPENFILENAME ofn;
+ memset(&ofn,0,sizeof(ofn));
+ ofn.lStructSize=sizeof(ofn);
+ ofn.hInstance=fceu_hInstance;
+ ofn.lpstrTitle="Save Basic Bot As...";
+ ofn.lpstrFilter=filter;
+ nameo[0]=0;
+ ofn.lpstrFile=nameo;
+ ofn.nMaxFile=256;
+ ofn.Flags=OFN_EXPLORER|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT;
+ ofn.lpstrInitialDir=BasicBotDir;
+ if(GetSaveFileName(&ofn))
+ {
+ int i,j;
+
+ //Save the directory
+ if(ofn.nFileOffset < 1024)
+ {
+ free(BasicBotDir);
+ BasicBotDir=malloc(strlen(ofn.lpstrFile)+1);
+ strcpy(BasicBotDir,ofn.lpstrFile);
+ BasicBotDir[ofn.nFileOffset]=0;
+ }
+
+ //quick get length of nameo
+ for(i=0;i<2048;i++)
+ {
+ if(nameo[i] == 0)
+ {
+ break;
+ }
+ }
+
+ //add .bot if nameo doesn't have it
+ if((i < 4 || nameo[i-4] != '.') && i < 2040)
+ {
+ nameo[i] = '.';
+ nameo[i+1] = 'b';
+ nameo[i+2] = 'o';
+ nameo[i+3] = 't';
+ nameo[i+4] = 0;
+ }
+
+ FILE *fp=FCEUD_UTF8fopen(nameo,"wb");
+ fputc('b',fp);
+ fputc('o',fp);
+ fputc('t',fp);
+ fputc(0,fp);
+ for(i=0;i<23;i++)
+ {
+ for(j=0;j<1024;j++)
+ {
+ fputc(Formula[i][j],fp);
+ }
+ }
+ fclose(fp);
+ }
+}
+
+//Loads a previously saved file
+static void LoadBasicBot()
+{
+ const char filter[]="Basic Bot (*.bot)\0*.bot\0";
+ char nameo[2048];
+ OPENFILENAME ofn;
+ memset(&ofn,0,sizeof(ofn));
+ ofn.lStructSize=sizeof(ofn);
+ ofn.hInstance=fceu_hInstance;
+ ofn.lpstrTitle="Load Basic Bot...";
+ ofn.lpstrFilter=filter;
+ nameo[0]=0;
+ ofn.lpstrFile=nameo;
+ ofn.nMaxFile=256;
+ ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
+ ofn.lpstrInitialDir=BasicBotDir;
+
+ if(GetOpenFileName(&ofn))
+ {
+ int i,j;
+
+ //Save the directory
+ if(ofn.nFileOffset < 1024)
+ {
+ free(BasicBotDir);
+ BasicBotDir=malloc(strlen(ofn.lpstrFile)+1);
+ strcpy(BasicBotDir,ofn.lpstrFile);
+ BasicBotDir[ofn.nFileOffset]=0;
+ }
+
+ FILE *fp=FCEUD_UTF8fopen(nameo,"rb");
+ if(fgetc(fp) != 'b'
+ || fgetc(fp) != 'o'
+ || fgetc(fp) != 't'
+ || fgetc(fp) != 0)
+ {
+ fclose(fp);
+ return;
+ }
+
+ for(i=0;i<23;i++)
+ {
+ for(j=0;j<1024;j++)
+ {
+ Formula[i][j] = fgetc(fp);
+ if(Formula[i][j] & 128)
+ {
+ Formula[i][j] = 0;
+ }
+ }
+ }
+ fclose(fp);
+ }
+}
+
+
+static BOOL CALLBACK BasicBotCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ int i;
+ DSMFix(uMsg);
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ break;
+ case WM_CLOSE:
+ case WM_QUIT:
+ for(i = 0; i < 8; i++)
+ {
+ GetDlgItemText(hwndBasicBot,1000+i,Formula[i + (EditPlayer?0:8)],1024);
+ }
+ for(i = 0; i < 4; i++)
+ {
+ GetDlgItemText(hwndBasicBot,1010+i,Formula[16+i],1024);
+ }
+ GetDlgItemText(hwndBasicBot, 1009, Formula[20],1024);
+ GetDlgItemText(hwndBasicBot, 1020, Formula[21],1024);
+ GetDlgItemText(hwndBasicBot, 1022, Formula[22],1024);
+ DestroyWindow(hwndBasicBot);
+ hwndBasicBot=0;
+ break;
+ case WM_COMMAND:
+ switch(HIWORD(wParam))
+ {
+ case BN_CLICKED:
+ switch(LOWORD(wParam))
+ {
+ case 1008: //change player button clicked
+ EditPlayer ^= 1;
+ SetDlgItemText(hwndBasicBot,1008,(LPTSTR)(EditPlayer?"Edit Player 2":"Edit Player 1"));
+ SetDlgItemText(hwndBasicBot,2000,(LPTSTR)(EditPlayer?"Player 1":"Player 2"));
+ for(i = 0; i < 8; i++)
+ {
+ GetDlgItemText(hwndBasicBot,1000+i,Formula[i + (EditPlayer?8:0)],1024);
+ SetDlgItemText(hwndBasicBot,1000+i,Formula[i + (EditPlayer?0:8)]);
+ }
+ break;
+ case 1014: //Save button clicked
+ for(i = 0; i < 8; i++)
+ {
+ GetDlgItemText(hwndBasicBot,1000+i,Formula[i + (EditPlayer?0:8)],1024);
+ }
+ for(i = 0; i < 4; i++)
+ {
+ GetDlgItemText(hwndBasicBot,1010+i,Formula[16+i],1024);
+ }
+ GetDlgItemText(hwndBasicBot, 1009, Formula[20],1024);
+ GetDlgItemText(hwndBasicBot, 1020, Formula[21],1024);
+ GetDlgItemText(hwndBasicBot, 1022, Formula[22],1024);
+ StopSound();
+ SaveBasicBot();
+ break;
+ case 1015: //Load button clicked
+ StopSound();
+ LoadBasicBot();
+ for(i = 0; i < 8; i++)
+ {
+ SetDlgItemText(hwndBasicBot,1000+i,Formula[i + (EditPlayer?0:8)]);
+ }
+ for(i = 0; i < 4; i++)
+ {
+ SetDlgItemText(hwndBasicBot,1010+i,Formula[16+i]);
+ }
+ SetDlgItemText(hwndBasicBot, 1009, Formula[20]);
+ SetDlgItemText(hwndBasicBot, 1020, Formula[21]);
+ SetDlgItemText(hwndBasicBot, 1022, Formula[22]);
+ break;
+ case 1021: //Play best button clicked
+ if(BotRunning == 0 && BotInput[0] == 0)
+ {
+ for(i = 0; i < 1022 && BestAttempt[i] != -1; i++)
+ {
+ BotInput[i+2] = BestAttempt[i];
+ }
+ BotInput[0] = i+1;
+ BotInput[1] = 65536;
+ }
+ break;
+ case 1016: //Run button clicked
+ BotRunning ^= 1;
+ if(BotRunning)
+ {
+ BotAttempts = BotFrames = 0;
+ BotBestScore[0] = BotBestScore[1] = BotBestScore[2] = BotBestScore[3] = -999999999;
+ NewAttempt = 1;
+ }
+ for(i = 0; i < 8; i++)
+ {
+ GetDlgItemText(hwndBasicBot,1000+i,Formula[i + (EditPlayer?0:8)],1024);
+ }
+ for(i = 0; i < 4; i++)
+ {
+ GetDlgItemText(hwndBasicBot,1010+i,Formula[16+i],1024);
+ }
+ GetDlgItemText(hwndBasicBot, 1009, Formula[20],1024);
+ GetDlgItemText(hwndBasicBot, 1020, Formula[21],1024);
+ GetDlgItemText(hwndBasicBot, 1022, Formula[22],1024);
+ SetDlgItemText(hwndBasicBot,1016,(LPTSTR)(BotRunning?"Stop":"Run!"));
+ break;
+ case 1036: //Clear button clicked
+ StopSound();
+ if(MessageBox(hwndBasicBot, "Clear all text?", "Confirm clear", MB_YESNO)==IDYES)
+ {
+ memset(Formula,0, 24*1024);
+ for(i = 0; i < 24; i++)
+ {
+ Formula[i][0] = '0';
+ }
+ Formula[20][0] = 'f';
+ Formula[20][1] = 'r';
+ Formula[20][2] = 'a';
+ Formula[20][3] = 'm';
+ Formula[20][4] = 'e';
+ Formula[20][5] = '=';
+ Formula[20][6] = '1';
+ for(i = 0; i < 8; i++)
+ {
+ SetDlgItemText(hwndBasicBot,1000+i,Formula[i+(EditPlayer?0:8)]);
+ }
+ for(i = 0; i < 4; i++)
+ {
+ SetDlgItemText(hwndBasicBot,1010+i,Formula[16+i]);
+ }
+ SetDlgItemText(hwndBasicBot, 1009, Formula[20]);
+ SetDlgItemText(hwndBasicBot, 1020, Formula[21]);
+ SetDlgItemText(hwndBasicBot, 1022, Formula[22]);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if(!(wParam>>16)) //Close button clicked
+ {
+ switch(wParam&0xFFFF)
+ {
+ case 1:
+ for(i = 0; i < 8; i++)
+ {
+ GetDlgItemText(hwndBasicBot,1000+i,Formula[i + (EditPlayer?0:8)],1024);
+ }
+ for(i = 0; i < 4; i++)
+ {
+ GetDlgItemText(hwndBasicBot,1010+i,Formula[16+i],1024);
+ }
+ GetDlgItemText(hwndBasicBot, 1009, Formula[20],1024);
+ GetDlgItemText(hwndBasicBot, 1020, Formula[21],1024);
+ GetDlgItemText(hwndBasicBot, 1022, Formula[22],1024);
+ DestroyWindow(hwndBasicBot);
+ hwndBasicBot=0;
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+void CreateBasicBot()
+{
+ static int BotNeedsInit = 1;
+ int i;
+ if(BotNeedsInit)
+ {
+ BotNeedsInit = 0;
+ SeedRandom(rand());
+ memset(Formula,0, 24*1024);
+ for(i = 0; i < 24; i++)
+ {
+ Formula[i][0] = '0';
+ }
+ Formula[20][0] = 'f';
+ Formula[20][1] = 'r';
+ Formula[20][2] = 'a';
+ Formula[20][3] = 'm';
+ Formula[20][4] = 'e';
+ Formula[20][5] = '=';
+ Formula[20][6] = '1';
+ }
+
+ if(hwndBasicBot) //If already open, give focus
+ {
+ SetFocus(hwndBasicBot);
+ return;
+ }
+
+ //Create
+ hwndBasicBot=CreateDialog(fceu_hInstance,"BASICBOT",NULL,BasicBotCallB);
+ EditPlayer = 1;
+ BotRunning = 0;
+ for(i = 0; i < 8; i++)
+ {
+ SetDlgItemText(hwndBasicBot,1000+i,Formula[i]);
+ }
+ for(i = 0; i < 4; i++)
+ {
+ SetDlgItemText(hwndBasicBot,1010+i,Formula[16+i]);
+ }
+ SetDlgItemText(hwndBasicBot, 1009, Formula[20]);
+ SetDlgItemText(hwndBasicBot, 1020, Formula[21]);
+ SetDlgItemText(hwndBasicBot, 1022, Formula[22]);
+}
+
diff --git a/drivers/win/basicbot.h b/drivers/win/basicbot.h
new file mode 100644
index 00000000..1c8a636e
--- /dev/null
+++ b/drivers/win/basicbot.h
@@ -0,0 +1,3 @@
+void UpdateBasicBot();
+void CreateBasicBot();
+extern char *BasicBotDir;
diff --git a/drivers/win/cheat.c b/drivers/win/cheat.c
new file mode 100644
index 00000000..cff14a83
--- /dev/null
+++ b/drivers/win/cheat.c
@@ -0,0 +1,487 @@
+/* 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 "common.h"
+
+#include "cheat.h"
+
+static HWND acwin=0;
+
+static int selcheat;
+static int scheatmethod=0;
+static uint8 cheatval1=0;
+static uint8 cheatval2=0;
+
+#define CSTOD 24
+
+static uint16 StrToU16(char *s)
+{
+ unsigned int ret=0;
+ sscanf(s,"%4x",&ret);
+ return ret;
+}
+
+static uint8 StrToU8(char *s)
+{
+ unsigned int ret=0;
+ sscanf(s,"%d",&ret);
+ return ret;
+}
+
+static int StrToI(char *s)
+{
+ int ret=0;
+ sscanf(s,"%d",&ret);
+ return ret;
+}
+
+
+//This is slow
+static char *U16ToStr(uint16 a)
+{
+ static char TempArray[16];
+ sprintf(TempArray,"%04X",a);
+ return TempArray;
+}
+
+//Rewritten to be fast for MemWatch (--Luke)
+static char *U8ToStr(uint8 a)
+{
+ static char TempArray[8];
+ TempArray[0] = '0' + a/100;
+ TempArray[1] = '0' + (a%100)/10;
+ TempArray[2] = '0' + (a%10);
+ TempArray[3] = 0;
+ return TempArray;
+}
+
+static char *IToStr(int a)
+{
+ static char TempArray[32];
+ sprintf(TempArray,"%d",a);
+ return TempArray;
+}
+
+static HWND RedoCheatsWND;
+static int RedoCheatsCallB(char *name, uint32 a, uint8 v, int compare, int s, int type, void *data)
+{
+ char tmp[512];
+ sprintf(tmp,"%s %s",s?"+":"-",name);
+ SendDlgItemMessage(RedoCheatsWND,300,LB_ADDSTRING,0,(LPARAM)(LPSTR)tmp);
+ return(1);
+}
+
+static void RedoCheatsLB(HWND hwndDlg)
+{
+ SendDlgItemMessage(hwndDlg,300,LB_RESETCONTENT,0,0);
+ RedoCheatsWND=hwndDlg;
+ FCEUI_ListCheats(RedoCheatsCallB, 0);
+}
+
+int cfcallb(uint32 a, uint8 last, uint8 current)
+{
+ char temp[16];
+
+ sprintf(temp,"%04X:%03d:%03d",(unsigned int)a,last,current);
+ SendDlgItemMessage(acwin,108,LB_ADDSTRING,0,(LPARAM)(LPSTR)temp);
+ return(1);
+}
+
+static int scrollindex;
+static int scrollnum;
+static int scrollmax;
+
+int cfcallbinsert(uint32 a, uint8 last, uint8 current)
+{
+ char temp[16];
+
+ sprintf(temp,"%04X:%03d:%03d",(unsigned int)a,last,current);
+ SendDlgItemMessage(acwin,108,LB_INSERTSTRING,(CSTOD-1),(LPARAM)(LPSTR)temp);
+ return(1);
+}
+
+int cfcallbinsertt(uint32 a, uint8 last, uint8 current)
+{
+ char temp[16];
+
+ sprintf(temp,"%04X:%03d:%03d",(unsigned int)a,last,current);
+ SendDlgItemMessage(acwin,108,LB_INSERTSTRING,0,(LPARAM)(LPSTR)temp);
+ return(1);
+}
+
+
+void AddTheThing(HWND hwndDlg, char *s, int a, int v)
+{
+ if(FCEUI_AddCheat(s,a,v,-1,0))
+ MessageBox(hwndDlg,"Cheat Added","Cheat Added",MB_OK);
+}
+
+
+static void DoGet(void)
+{
+ int n=FCEUI_CheatSearchGetCount();
+ int t;
+ scrollnum=n;
+ scrollindex=-32768;
+
+ SendDlgItemMessage(acwin,108,LB_RESETCONTENT,0,0);
+ FCEUI_CheatSearchGetRange(0,(CSTOD-1),cfcallb);
+
+ t=-32768+n-1-(CSTOD-1);
+ if(t<-32768)
+ t=-32768;
+ scrollmax=t;
+ SendDlgItemMessage(acwin,120,SBM_SETRANGE,-32768,t);
+ SendDlgItemMessage(acwin,120,SBM_SETPOS,-32768,1);
+}
+
+static void FixCheatSelButtons(HWND hwndDlg, int how)
+{
+ /* Update Cheat Button */
+ EnableWindow(GetDlgItem(hwndDlg,251),how);
+
+ /* Delete Cheat Button */
+ EnableWindow(GetDlgItem(hwndDlg,252),how);
+}
+
+static BOOL CALLBACK AddCheatCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ static int lbfocus;
+ static HWND hwndLB;
+
+ switch(uMsg)
+ {
+ case WM_VSCROLL:
+ if(scrollnum>(CSTOD-1))
+ {
+ switch((int)LOWORD(wParam))
+ {
+ case SB_TOP:
+ scrollindex=-32768;
+ SendDlgItemMessage(hwndDlg,120,SBM_SETPOS,scrollindex,1);
+ SendDlgItemMessage(hwndDlg,108,LB_RESETCONTENT,(CSTOD-1),0);
+ FCEUI_CheatSearchGetRange(scrollindex+32768,scrollindex+32768+(CSTOD-1),cfcallb);
+ break;
+ case SB_BOTTOM:
+ scrollindex=scrollmax;
+ SendDlgItemMessage(hwndDlg,120,SBM_SETPOS,scrollindex,1);
+ SendDlgItemMessage(hwndDlg,108,LB_RESETCONTENT,(CSTOD-1),0);
+ FCEUI_CheatSearchGetRange(scrollindex+32768,scrollindex+32768+(CSTOD-1),cfcallb);
+ break;
+ case SB_LINEUP:
+ if(scrollindex>-32768)
+ {
+ scrollindex--;
+ SendDlgItemMessage(hwndDlg,120,SBM_SETPOS,scrollindex,1);
+ SendDlgItemMessage(hwndDlg,108,LB_DELETESTRING,(CSTOD-1),0);
+ FCEUI_CheatSearchGetRange(scrollindex+32768,scrollindex+32768,cfcallbinsertt);
+ }
+ break;
+
+ case SB_PAGEUP:
+ scrollindex-=CSTOD;
+ if(scrollindex<-32768) scrollindex=-32768;
+ SendDlgItemMessage(hwndDlg,120,SBM_SETPOS,scrollindex,1);
+ SendDlgItemMessage(hwndDlg,108,LB_RESETCONTENT,(CSTOD-1),0);
+ FCEUI_CheatSearchGetRange(scrollindex+32768,scrollindex+32768+(CSTOD-1),cfcallb);
+ break;
+
+ case SB_LINEDOWN:
+ if(scrollindex<scrollmax)
+ {
+ scrollindex++;
+ SendDlgItemMessage(hwndDlg,120,SBM_SETPOS,scrollindex,1);
+ SendDlgItemMessage(hwndDlg,108,LB_DELETESTRING,0,0);
+ FCEUI_CheatSearchGetRange(scrollindex+32768+(CSTOD-1),scrollindex+32768+(CSTOD-1),cfcallbinsert);
+ }
+ break;
+
+ case SB_PAGEDOWN:
+ scrollindex+=CSTOD;
+ if(scrollindex>scrollmax)
+ scrollindex=scrollmax;
+ SendDlgItemMessage(hwndDlg,120,SBM_SETPOS,scrollindex,1);
+ SendDlgItemMessage(hwndDlg,108,LB_RESETCONTENT,0,0);
+ FCEUI_CheatSearchGetRange(scrollindex+32768,scrollindex+32768+(CSTOD-1),cfcallb);
+ break;
+
+ case SB_THUMBPOSITION:
+ case SB_THUMBTRACK:
+ scrollindex=(short int)HIWORD(wParam);
+ SendDlgItemMessage(hwndDlg,120,SBM_SETPOS,scrollindex,1);
+ SendDlgItemMessage(hwndDlg,108,LB_RESETCONTENT,0,0);
+ FCEUI_CheatSearchGetRange(32768+scrollindex,32768+scrollindex+(CSTOD-1),cfcallb);
+ break;
+ }
+
+ }
+ break;
+
+ case WM_INITDIALOG:
+ selcheat = -1;
+ FixCheatSelButtons(hwndDlg, 0);
+ acwin=hwndDlg;
+ SetDlgItemText(hwndDlg,110,(LPTSTR)U8ToStr(cheatval1));
+ SetDlgItemText(hwndDlg,111,(LPTSTR)U8ToStr(cheatval2));
+ DoGet();
+ CheckRadioButton(hwndDlg,115,120,scheatmethod+115);
+ lbfocus=0;
+ hwndLB=0;
+
+ RedoCheatsLB(hwndDlg);
+ break;
+
+ case WM_VKEYTOITEM:
+ if(lbfocus)
+ {
+ int real;
+
+ real=SendDlgItemMessage(hwndDlg,108,LB_GETCURSEL,0,(LPARAM)(LPSTR)0);
+ switch((int)LOWORD(wParam))
+ {
+ case VK_UP:
+ /* mmmm....recursive goodness */
+ if(!real)
+ SendMessage(hwndDlg,WM_VSCROLL,SB_LINEUP,0);
+ return(-1);
+ break;
+ case VK_DOWN:
+ if(real==(CSTOD-1))
+ SendMessage(hwndDlg,WM_VSCROLL,SB_LINEDOWN,0);
+ return(-1);
+ break;
+ case VK_PRIOR:
+ SendMessage(hwndDlg,WM_VSCROLL,SB_PAGEUP,0);
+ break;
+ case VK_NEXT:
+ SendMessage(hwndDlg,WM_VSCROLL,SB_PAGEDOWN,0);
+ break;
+ case VK_HOME:
+ SendMessage(hwndDlg,WM_VSCROLL,SB_TOP,0);
+ break;
+ case VK_END:
+ SendMessage(hwndDlg,WM_VSCROLL,SB_BOTTOM,0);
+ break;
+ }
+ return(-2);
+ }
+ break;
+
+ case WM_CLOSE:
+ case WM_QUIT: goto gornk;
+ case WM_COMMAND:
+ switch(LOWORD(wParam))
+ {
+ case 300: /* List box selection changed. */
+ if(HIWORD(wParam)==LBN_SELCHANGE)
+ {
+ char *s;
+ uint32 a;
+ uint8 v;
+ int status;
+ int c,type;
+
+ selcheat=SendDlgItemMessage(hwndDlg,300,LB_GETCURSEL,0,(LPARAM)(LPSTR)0);
+ if(selcheat<0)
+ {
+ FixCheatSelButtons(hwndDlg,0);
+ break;
+ }
+ FixCheatSelButtons(hwndDlg, 1);
+
+ FCEUI_GetCheat(selcheat,&s,&a,&v,&c,&status,&type);
+ SetDlgItemText(hwndDlg,200,(LPTSTR)s);
+ SetDlgItemText(hwndDlg,201,(LPTSTR)U16ToStr(a));
+ SetDlgItemText(hwndDlg,202,(LPTSTR)U8ToStr(v));
+ SetDlgItemText(hwndDlg,203,(c==-1)?(LPTSTR)"":(LPTSTR)IToStr(c));
+ CheckDlgButton(hwndDlg,204,type?BST_CHECKED:BST_UNCHECKED);
+ }
+ break;
+ case 108:
+ switch(HIWORD(wParam))
+ {
+ case LBN_SELCHANGE:
+ {
+ char TempArray[32];
+ SendDlgItemMessage(hwndDlg,108,LB_GETTEXT,SendDlgItemMessage(hwndDlg,108,LB_GETCURSEL,0,(LPARAM)(LPSTR)0),(LPARAM)(LPCTSTR)TempArray);
+ TempArray[4]=0;
+ SetDlgItemText(hwndDlg,201,(LPTSTR)TempArray);
+ }
+ break;
+ case LBN_SETFOCUS:
+ lbfocus=1;
+ break;
+ case LBN_KILLFOCUS:
+ lbfocus=0;
+ break;
+ }
+ break;
+ }
+
+ switch(HIWORD(wParam))
+ {
+ case LBN_DBLCLK:
+ if(selcheat>=0)
+ {
+ if(LOWORD(wParam)==300)
+ FCEUI_ToggleCheat(selcheat);
+ RedoCheatsLB(hwndDlg);
+ SendDlgItemMessage(hwndDlg,300,LB_SETCURSEL,selcheat,0);
+ }
+ break;
+
+ case BN_CLICKED:
+ if(LOWORD(wParam)>=115 && LOWORD(wParam)<=120)
+ scheatmethod=LOWORD(wParam)-115;
+ else switch(LOWORD(wParam))
+ {
+ case 112:
+ FCEUI_CheatSearchBegin();
+ DoGet();
+ break;
+ case 113:
+ FCEUI_CheatSearchEnd(scheatmethod,cheatval1,cheatval2);
+ DoGet();
+ break;
+ case 114:
+ FCEUI_CheatSearchSetCurrentAsOriginal();
+ DoGet();
+ break;
+ case 107:
+ FCEUI_CheatSearchShowExcluded();
+ DoGet();
+ break;
+ case 250: /* Add Cheat Button */
+ {
+ int a,v,c,t;
+ char name[257];
+ char temp[16];
+
+ GetDlgItemText(hwndDlg,200,name,256+1);
+ GetDlgItemText(hwndDlg,201,temp,4+1);
+ a=StrToU16(temp);
+ GetDlgItemText(hwndDlg,202,temp,3+1);
+ v=StrToU8(temp);
+ GetDlgItemText(hwndDlg,203,temp,3+1);
+ if(temp[0]==0)
+ c=-1;
+ else
+ c=StrToI(temp);
+ t=(IsDlgButtonChecked(hwndDlg,204)==BST_CHECKED)?1:0;
+ FCEUI_AddCheat(name,a,v,c,t);
+ RedoCheatsLB(hwndDlg);
+ SendDlgItemMessage(hwndDlg,300,LB_SETCURSEL,selcheat,0);
+ }
+ break;
+ case 253: /* Add GG Cheat Button */
+ {
+ uint16 a;
+ int c;
+ uint8 v;
+ char name[257];
+
+ GetDlgItemText(hwndDlg,200,name,256+1);
+
+ if(FCEUI_DecodeGG(name,&a,&v,&c))
+ {
+ FCEUI_AddCheat(name,a,v,c,1);
+ RedoCheatsLB(hwndDlg);
+ SendDlgItemMessage(hwndDlg,300,LB_SETCURSEL,selcheat,0);
+ }
+ }
+ break;
+
+ case 251: /* Update Cheat Button */
+ if(selcheat>=0)
+ {
+ int a,v,c,t;
+ char name[257];
+ char temp[16];
+
+ GetDlgItemText(hwndDlg,200,name,256+1);
+ GetDlgItemText(hwndDlg,201,temp,4+1);
+ a=StrToU16(temp);
+ GetDlgItemText(hwndDlg,202,temp,3+1);
+ v=StrToU8(temp);
+ GetDlgItemText(hwndDlg,203,temp,3+1);
+ if(temp[0]==0)
+ c=-1;
+ else
+ c=StrToI(temp);
+ t=(IsDlgButtonChecked(hwndDlg,204)==BST_CHECKED)?1:0;
+ FCEUI_SetCheat(selcheat,name,a,v,c,-1,t);
+ RedoCheatsLB(hwndDlg);
+ SendDlgItemMessage(hwndDlg,300,LB_SETCURSEL,selcheat,0);
+ }
+ break;
+ case 252: /* Delete cheat button */
+ if(selcheat>=0)
+ {
+ FCEUI_DelCheat(selcheat);
+ SendDlgItemMessage(hwndDlg,300,LB_DELETESTRING,selcheat,0);
+ FixCheatSelButtons(hwndDlg, 0);
+ selcheat=-1;
+ SetDlgItemText(hwndDlg,200,(LPTSTR)"");
+ SetDlgItemText(hwndDlg,201,(LPTSTR)"");
+ SetDlgItemText(hwndDlg,202,(LPTSTR)"");
+ SetDlgItemText(hwndDlg,203,(LPTSTR)"");
+ CheckDlgButton(hwndDlg,204,BST_UNCHECKED);
+ }
+ break;
+ case 106:
+ gornk:
+ EndDialog(hwndDlg,0);
+ acwin=0;
+ break;
+ }
+ break;
+ case EN_CHANGE:
+ {
+ char TempArray[256];
+ GetDlgItemText(hwndDlg,LOWORD(wParam),TempArray,256);
+ switch(LOWORD(wParam))
+ {
+ case 110:cheatval1=StrToU8(TempArray);break;
+ case 111:cheatval2=StrToU8(TempArray);break;
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+void ConfigAddCheat(HWND wnd)
+{
+ if(!GI)
+ {
+ FCEUD_PrintError("You must have a game loaded before you can manipulate cheats.");
+ return;
+ }
+
+ if(GI->type==GIT_NSF)
+ {
+ FCEUD_PrintError("Sorry, you can't cheat with NSFs.");
+ return;
+ }
+
+ DialogBox(fceu_hInstance,"ADDCHEAT",wnd,AddCheatCallB);
+}
+
diff --git a/drivers/win/cheat.h b/drivers/win/cheat.h
new file mode 100644
index 00000000..d6aa7302
--- /dev/null
+++ b/drivers/win/cheat.h
@@ -0,0 +1,2 @@
+void ConfigCheats(HWND hParent);
+void ConfigAddCheat(HWND wnd);
diff --git a/drivers/win/common.h b/drivers/win/common.h
new file mode 100644
index 00000000..bbf6bb8d
--- /dev/null
+++ b/drivers/win/common.h
@@ -0,0 +1,46 @@
+#include <stdio.h>
+#include <windows.h>
+#include <windowsx.h>
+
+#ifndef WIN32
+#define WIN32
+#endif
+#undef WINNT
+#define NONAMELESSUNION
+
+#define DIRECTSOUND_VERSION 0x0700
+#define DIRECTDRAW_VERSION 0x0700
+#define DIRECTINPUT_VERSION 0x700
+#define FCEUDEF_DEBUGGER
+#include "../../types.h"
+#include "../../general.h"
+#include "../../driver.h"
+#include "../common/config.h"
+
+/* Message logging(non-netplay messages, usually) for all. */
+#include "log.h"
+extern HWND hAppWnd;
+extern HINSTANCE fceu_hInstance;
+
+extern int NoWaiting;
+extern FCEUGI *GI;
+void DSMFix(UINT msg);
+void StopSound(void);
+
+extern int eoptions;
+
+#define EO_BGRUN 1
+
+#define EO_CPALETTE 4
+#define EO_NOSPRLIM 8
+#define EO_FSAFTERLOAD 32
+#define EO_FOAFTERSTART 64
+#define EO_NOTHROTTLE 128
+#define EO_CLIPSIDES 256
+#define EO_SNAPNAME 512
+#define EO_HIDEMENU 2048
+#define EO_HIGHPRIO 4096
+#define EO_FORCEASPECT 8192
+#define EO_FORCEISCALE 16384
+#define EO_NOFOURSCORE 32768
+
diff --git a/drivers/win/config.c b/drivers/win/config.c
new file mode 100644
index 00000000..f03ec78f
--- /dev/null
+++ b/drivers/win/config.c
@@ -0,0 +1,137 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/****************************************************************/
+/* FCE Ultra */
+/* */
+/* This file contains code to interface to the standard */
+/* FCE Ultra configuration file saving/loading code. */
+/* */
+/****************************************************************/
+
+static CFGSTRUCT fceuconfig[]={
+
+ ACS(rfiles[0]),
+ ACS(rfiles[1]),
+ ACS(rfiles[2]),
+ ACS(rfiles[3]),
+ ACS(rfiles[4]),
+ ACS(rfiles[5]),
+ ACS(rfiles[6]),
+ ACS(rfiles[7]),
+ ACS(rfiles[8]),
+ ACS(rfiles[9]),
+
+ ACS(rdirs[0]),
+ ACS(rdirs[1]),
+ ACS(rdirs[2]),
+ ACS(rdirs[3]),
+ ACS(rdirs[4]),
+ ACS(rdirs[5]),
+ ACS(rdirs[6]),
+ ACS(rdirs[7]),
+ ACS(rdirs[8]),
+ ACS(rdirs[9]),
+
+ AC(ntsccol),AC(ntsctint),AC(ntschue),
+
+ NAC("palyo",palyo),
+ NAC("genie",genie),
+ NAC("fs",fullscreen),
+ NAC("vgamode",vmod),
+ NAC("sound",soundo),
+ NAC("sicon",status_icon),
+
+ ACS(gfsdir),
+
+ NACS("odcheats",DOvers[0]),
+ NACS("odmisc",DOvers[1]),
+ NACS("odnonvol",DOvers[2]),
+ NACS("odstates",DOvers[3]),
+ NACS("odsnaps",DOvers[4]),
+ NACS("odbase",DOvers[5]),
+ NACS("odbase",DOvers[6]),
+
+ AC(winspecial),
+ AC(winsizemulx),
+ AC(winsizemuly),
+ NAC("saspectw987",saspectw),
+ NAC("saspecth987",saspecth),
+
+ AC(soundrate),
+ AC(soundbuftime),
+ AC(soundoptions),
+ AC(soundquality),
+ AC(soundvolume),
+
+ AC(goptions),
+ NAC("eoptions",eoptions),
+ NACA("cpalette",cpalette),
+
+ NACA("InputType",UsrInputType),
+
+ NAC("vmcx",vmodes[0].x),
+ NAC("vmcy",vmodes[0].y),
+ NAC("vmcb",vmodes[0].bpp),
+ NAC("vmcf",vmodes[0].flags),
+ NAC("vmcxs",vmodes[0].xscale),
+ NAC("vmcys",vmodes[0].yscale),
+ NAC("vmspecial",vmodes[0].special),
+
+ NAC("srendline",srendlinen),
+ NAC("erendline",erendlinen),
+ NAC("srendlinep",srendlinep),
+ NAC("erendlinep",erendlinep),
+
+ AC(disvaccel),
+ AC(winsync),
+ NAC("988fssync",fssync),
+
+ AC(ismaximized),
+ AC(maxconbskip),
+ AC(ffbskip),
+
+ ADDCFGSTRUCT(NetplayConfig),
+ ADDCFGSTRUCT(InputConfig),
+ ADDCFGSTRUCT(HotkeyConfig),
+
+ AC(moviereadonly),
+ AC(autoHoldKey),
+ AC(autoHoldClearKey),
+ AC(frame_display),
+ AC(input_display),
+ ACS(MemWatchDir),
+ ACS(BasicBotDir),
+ AC(EnableBackgroundInput),
+ ENDCFGSTRUCT
+};
+
+static void SaveConfig(char *filename)
+{
+ SaveFCEUConfig(filename,fceuconfig);
+}
+
+static void LoadConfig(char *filename)
+{
+ FCEUI_GetNTSCTH(&ntsctint,&ntschue);
+ LoadFCEUConfig(filename,fceuconfig);
+ FCEUI_SetNTSCTH(ntsccol,ntsctint,ntschue);
+}
+
diff --git a/drivers/win/debug.c b/drivers/win/debug.c
new file mode 100644
index 00000000..ad2a459b
--- /dev/null
+++ b/drivers/win/debug.c
@@ -0,0 +1,707 @@
+#include "common.h"
+#ifdef FCEUDEF_DEBUGGER
+#include "../../x6502.h"
+#include "../../debug.h"
+#include "debug.h"
+
+void UpdateDebugger(void);
+static int discallb(uint16 a, char *s);
+static void crs(HWND hParent);
+static void Disyou(uint16 a);
+static void UpdateDMem(uint16 a);
+
+static HWND mwin=0;
+static int32 cmsi;
+static int instep=-1;
+static X6502 *Xsave;
+
+HWND dwin;
+
+static uint16 StrToU16(char *s)
+{
+ unsigned int ret=0;
+ sscanf(s,"%4x",&ret);
+ return ret;
+}
+
+static uint8 StrToU8(char *s)
+{
+ unsigned int ret=0;
+ sscanf(s,"%2x",&ret);
+ return ret;
+}
+
+/* Need to be careful where these functions are used. */
+static char *U16ToStr(uint16 a)
+{
+ static char TempArray[16];
+ sprintf(TempArray,"%04X",a);
+ return TempArray;
+}
+
+static char *U8ToStr(uint8 a)
+{
+ static char TempArray[16];
+ sprintf(TempArray,"%02X",a);
+ return TempArray;
+}
+
+static uint16 asavers[27];
+
+
+static void crs(HWND hParent)
+{
+// SetDlgItemText(hParent,320,(LPTSTR)(instep>=0)?"Stopped.":"Running...");
+ EnableWindow( GetDlgItem(hParent,301),(instep>=0)?1:0);
+}
+
+static void Disyou(uint16 a)
+{
+ int discount;
+
+ SendDlgItemMessage(dwin,100,LB_RESETCONTENT,0,0);
+
+ discount = 0;
+ while(discount < 25)
+ {
+ char buffer[256];
+ uint16 prea = a;
+
+ asavers[discount]=a;
+ sprintf(buffer,"%04x: ",a);
+
+ a = FCEUI_Disassemble(Xsave,a,buffer + strlen(buffer));
+ if(prea==Xsave->PC)
+ SendDlgItemMessage(dwin,100,LB_SETCURSEL,discount,0);
+
+ SendDlgItemMessage(dwin,100,LB_ADDSTRING,0,(LPARAM)(LPSTR)buffer);
+ discount++;
+ }
+ //FCEUI_Disassemble(Xsave,a,discallb);
+}
+
+static void SSI(X6502 *X)
+{
+ SCROLLINFO si;
+
+ memset(&si,0,sizeof(si));
+ si.cbSize=sizeof(si);
+ si.fMask=SIF_ALL;
+ si.nMin=-32768;
+ si.nMax=32767;
+ si.nPage=27;
+ si.nPos=X->PC-32768;
+ SetScrollInfo(GetDlgItem(dwin,101),SB_CTL,&si,1);
+}
+
+static void RFlags(X6502 *X)
+{
+ int x;
+
+ SetDlgItemText(dwin,202,(LPTSTR)U8ToStr(X->P&~0x30));
+ for(x=0;x<8;x++)
+ {
+ if(x!=4 && x!=5)
+ CheckDlgButton(dwin,400+x,((X->P>>x)&1)?BST_CHECKED:BST_UNCHECKED);
+ }
+}
+
+static void RRegs(X6502 *X)
+{
+ SetDlgItemText(dwin,200,(LPTSTR)U16ToStr(X->PC));
+ SetDlgItemText(dwin,201,(LPTSTR)U8ToStr(X->S));
+ SetDlgItemText(dwin,210,(LPTSTR)U8ToStr(X->A));
+ SetDlgItemText(dwin,211,(LPTSTR)U8ToStr(X->X));
+ SetDlgItemText(dwin,212,(LPTSTR)U8ToStr(X->Y));
+}
+
+static void DoVecties(HWND hParent)
+{
+ uint16 m[3];
+ int x;
+
+ FCEUI_GetIVectors(&m[2],&m[0],&m[1]);
+ for(x=0;x<3;x++)
+ SetDlgItemText(hParent,220+x,(LPTSTR)U16ToStr(m[x]));
+}
+
+static void Redrawsy(X6502 *X)
+{
+ SSI(X);
+ RFlags(X);
+ RRegs(X);
+
+ Disyou(X->PC);
+
+ DoVecties(dwin);
+}
+
+static void MultiCB(X6502 *X)
+{
+ Xsave=X;
+ if(instep>=0)
+ {
+ Redrawsy(X);
+ if(mwin)
+ UpdateDMem(cmsi);
+ }
+
+ while(instep>=0)
+ {
+ if(instep>=1)
+ {
+ instep--;
+ return;
+ }
+ StopSound();
+ if(!BlockingCheck()) /* Whoops, need to exit for some reason. */
+ {
+ instep=-1;
+ FCEUI_SetCPUCallback(0);
+ return;
+ }
+ Sleep(50);
+ }
+}
+
+static int multistep=0;
+static void cpucb(X6502 *X)
+{
+ multistep=0;
+ MultiCB(X);
+}
+
+static void BPointHandler(X6502 *X, int type, unsigned int A)
+{
+ if(multistep) return; /* To handle instructions that can cause multiple
+ breakpoints per instruction.
+ */
+ if(!dwin) return; /* Window is closed, don't do breakpoints. */
+ multistep=1;
+ instep=0;
+ crs(dwin);
+ MultiCB(X);
+}
+
+static HWND hWndCallB;
+static int RBPCallBack(int type, unsigned int A1, unsigned int A2,
+ void (*Handler)(X6502 *, int type, unsigned int A) )
+{
+ char buf[128];
+ sprintf(buf,"%s%s%s $%04x - $%04x",(type&BPOINT_READ)?"R":" ",
+ (type&BPOINT_WRITE)?"W":" ",(type&BPOINT_PC)?"P":" ",A1,A2);
+ SendDlgItemMessage(hWndCallB,510,LB_ADDSTRING,0,(LPARAM)(LPSTR)buf);
+ return(1);
+}
+
+static void RebuildBPointList(HWND hwndDlg)
+{
+ SendDlgItemMessage(hwndDlg,510,LB_RESETCONTENT,0,0);
+ hWndCallB=hwndDlg;
+ FCEUI_ListBreakPoints(RBPCallBack);
+}
+
+static void FetchBPDef(HWND hwndDlg, uint16 *A1, uint16 *A2, int *type)
+{
+ char tmp[256];
+
+ GetDlgItemText(hwndDlg,520,tmp,256);
+ *A1=StrToU16(tmp);
+ GetDlgItemText(hwndDlg,521,tmp,256);
+ if(tmp[0]==0)
+ *A2=*A1;
+ else
+ *A2=StrToU16(tmp);
+
+ *type=0;
+ *type|=(IsDlgButtonChecked(hwndDlg,530)==BST_CHECKED)?BPOINT_READ:0;
+ *type|=(IsDlgButtonChecked(hwndDlg,531)==BST_CHECKED)?BPOINT_WRITE:0;
+ *type|=(IsDlgButtonChecked(hwndDlg,532)==BST_CHECKED)?BPOINT_PC:0;
+}
+
+static void SetBPDef(HWND hwndDlg, int32 A1, int32 A2, int type)
+{
+ if(A1>=0)
+ SetDlgItemText(hwndDlg,520,(LPTSTR)U16ToStr(A1));
+ if(A2>=0)
+ SetDlgItemText(hwndDlg,521,(LPTSTR)U16ToStr(A2));
+ if(type>=0)
+ {
+ // CheckDlgButton(hwndDlg,123,(soundoptions&SO_SECONDARY)?BST_CHECKED:BST_UNCHECKED);
+ }
+}
+
+static BOOL CALLBACK DebugCon(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ int32 scrollindex=0,ced=0;
+ DSMFix(uMsg);
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ crs(hwndDlg);
+ DoVecties(hwndDlg);
+ FCEUI_SetCPUCallback(cpucb);
+ RebuildBPointList(hwndDlg);
+ break;
+ case WM_VSCROLL:
+ if(0!=instep) break;
+ switch((int)LOWORD(wParam))
+ {
+ case SB_TOP:
+ scrollindex=-32768;
+ ced=1;
+ break;
+ case SB_BOTTOM:
+ scrollindex=32767;
+ ced=1;
+ break;
+ case SB_LINEUP:
+ scrollindex=GetScrollPos(GetDlgItem(hwndDlg,101),SB_CTL);
+ if(scrollindex>-32768)
+ {
+ scrollindex--;
+ ced=1;
+ }
+ break;
+
+ case SB_PAGEUP:
+ scrollindex=GetScrollPos(GetDlgItem(hwndDlg,101),SB_CTL);
+ scrollindex-=27;
+ if(scrollindex<-32768)
+ scrollindex=-32768;
+ ced=1;
+ break;
+
+ case SB_LINEDOWN:
+ scrollindex=GetScrollPos(GetDlgItem(hwndDlg,101),SB_CTL);
+ if(scrollindex<32767)
+ {
+ scrollindex++;
+ ced=1;
+ }
+ break;
+
+ case SB_PAGEDOWN:
+ scrollindex=GetScrollPos(GetDlgItem(hwndDlg,101),SB_CTL);
+ scrollindex+=27;
+ if(scrollindex>32767)
+ {
+ scrollindex=32767;
+ }
+ ced=1;
+ break;
+
+ case SB_THUMBPOSITION:
+ case SB_THUMBTRACK:
+ scrollindex=(int16)(wParam>>16);
+ ced=1;
+ break;
+ }
+ if(ced)
+ {
+ SendDlgItemMessage(hwndDlg,101,SBM_SETPOS,scrollindex,1);
+ Disyou(scrollindex+32768);
+ }
+ break;
+
+
+ case WM_CLOSE:
+ case WM_QUIT: goto gornk;
+ case WM_COMMAND:
+ switch(HIWORD(wParam))
+ {
+ case LBN_DBLCLK:
+ if(0==instep)
+ {
+ Xsave->PC=asavers[SendDlgItemMessage(hwndDlg,100,LB_GETCURSEL,0,0)];
+ RRegs(Xsave);
+ Disyou(Xsave->PC);
+ }
+ break;
+ case EN_KILLFOCUS:
+ {
+ char TempArray[64];
+ int id=LOWORD(wParam);
+ GetDlgItemText(hwndDlg,id,TempArray,64);
+
+ if(0==instep)
+ {
+ int tscroll=32768+SendDlgItemMessage(hwndDlg,101,SBM_GETPOS,0,0);
+
+ switch(id)
+ {
+ case 200:
+ if(Xsave->PC!=StrToU16(TempArray))
+ {
+ Xsave->PC=StrToU16(TempArray);
+ Disyou(Xsave->PC);
+ RRegs(Xsave);
+ }
+ break;
+ case 201:Xsave->S=StrToU8(TempArray);
+ RRegs(Xsave);
+ Disyou(tscroll);
+ break;
+ case 202:Xsave->P&=0x30;
+ Xsave->P|=StrToU8(TempArray)&~0x30;
+ RFlags(Xsave);
+ Disyou(tscroll);
+ break;
+ case 210:Xsave->A=StrToU8(TempArray);
+ RRegs(Xsave);
+ Disyou(tscroll);
+ break;
+ case 211:Xsave->X=StrToU8(TempArray);
+ RRegs(Xsave);
+ Disyou(tscroll);
+ break;
+ case 212:Xsave->Y=StrToU8(TempArray);
+ RRegs(Xsave);
+ Disyou(tscroll);
+ break;
+ }
+ }
+ }
+ break;
+
+ case BN_CLICKED:
+ if(LOWORD(wParam)>=400 && LOWORD(wParam)<=407)
+ {
+ if(0==instep)
+ {
+ Xsave->P^=1<<(LOWORD(wParam)&7);
+ RFlags(Xsave);
+ }
+ }
+ else switch(LOWORD(wParam))
+ {
+ case 300:
+ instep=1;
+ crs(hwndDlg);
+ break;
+ case 301:
+ instep=-1;
+ crs(hwndDlg);
+ break;
+ case 302:FCEUI_NMI();break;
+ case 303:FCEUI_IRQ();break;
+ case 310:FCEUI_ResetNES();
+ if(instep>=0)
+ instep=1;
+ crs(hwndDlg);
+ break;
+ case 311:DoMemmo(hwndDlg);break;
+
+ case 540:
+ {
+ LONG t;
+ t=SendDlgItemMessage(hwndDlg,510,LB_GETCURSEL,0,0);
+ if(t!=LB_ERR)
+ {
+ FCEUI_DeleteBreakPoint(t);
+ SendDlgItemMessage(hWndCallB,510,LB_DELETESTRING,t,(LPARAM)(LPSTR)0);
+ }
+ }
+ break;
+ case 541:
+ {
+ uint16 A1,A2;
+ int type;
+ FetchBPDef(hwndDlg, &A1, &A2, &type);
+ FCEUI_AddBreakPoint(type, A1,A2,BPointHandler);
+ hWndCallB=hwndDlg; /* Hacky hacky. */
+ RBPCallBack(type, A1,A2,0);
+ }
+ break;
+ }
+ break;
+ }
+
+
+ if(!(wParam>>16))
+ switch(wParam&0xFFFF)
+ {
+ case 1:
+ gornk:
+ instep=-1;
+ FCEUI_SetCPUCallback(0);
+ DestroyWindow(dwin);
+ dwin=0;
+ break;
+ }
+ }
+ return 0;
+}
+
+void BeginDSeq(HWND hParent)
+{
+ if(dwin)
+ {
+ SetFocus(dwin);
+ return;
+ }
+ if(!GI)
+ {
+ FCEUD_PrintError("You must have a game loaded before you can screw up a game.");
+ return;
+ }
+
+ dwin=CreateDialog(fceu_hInstance,"DEBUGGER",0,DebugCon);
+}
+
+/* 16 numbers per line times 3 then minus one(no space at end) and plus
+ 6 for "8000: "-like string and plus 2 for crlf. *16 for 16 lines, and
+ +1 for a null.
+*/
+static uint8 kbuf[(16*3-1+6+2)*16+1];
+static void sexycallb(uint16 a, uint8 v)
+{
+ if((a&15)==15)
+ sprintf(kbuf+strlen(kbuf),"%02X\r\n",v);
+ else if((a&15)==0)
+ sprintf(kbuf+strlen(kbuf),"%03xx: %02X ",a>>4,v);
+ else
+ sprintf(kbuf+strlen(kbuf),"%02X ",v);
+}
+
+static void MDSSI(void)
+{
+ SCROLLINFO si;
+
+ memset(&si,0,sizeof(si));
+ si.cbSize=sizeof(si);
+ si.fMask=SIF_ALL;
+ si.nMin=0;
+ si.nMax=0xFFFF>>4;
+ si.nPage=16;
+ cmsi=si.nPos=0;
+ SetScrollInfo(GetDlgItem(mwin,103),SB_CTL,&si,1);
+}
+
+static void UpdateDMem(uint16 a)
+{
+ kbuf[0]=0;
+ FCEUI_MemDump(a<<4,256,sexycallb);
+ SetDlgItemText(mwin,100,kbuf);
+}
+
+int CreateDumpSave(uint32 a1, uint32 a2)
+{
+ const char filter[]="Raw dump(*.dmp)\0*.dmp\0";
+ char nameo[2048];
+ OPENFILENAME ofn;
+
+ memset(&ofn,0,sizeof(ofn));
+ ofn.lStructSize=sizeof(ofn);
+ ofn.hInstance=fceu_hInstance;
+ ofn.lpstrTitle="Dump Memory As...";
+ ofn.lpstrFilter=filter;
+ nameo[0]=0;
+ ofn.lpstrFile=nameo;
+ ofn.nMaxFile=256;
+ ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
+ if(GetSaveFileName(&ofn))
+ {
+ FCEUI_DumpMem(nameo,a1,a2);
+ return(1);
+ }
+ return 0;
+}
+
+int LoadSave(uint32 a)
+{
+ const char filter[]="Raw dump(*.dmp)\0*.dmp\0";
+ char nameo[2048];
+ OPENFILENAME ofn;
+
+ memset(&ofn,0,sizeof(ofn));
+ ofn.lStructSize=sizeof(ofn);
+ ofn.hInstance=fceu_hInstance;
+ ofn.lpstrTitle="Load Memory...";
+ ofn.lpstrFilter=filter;
+ nameo[0]=0;
+ ofn.lpstrFile=nameo;
+ ofn.nMaxFile=256;
+ ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
+ if(GetOpenFileName(&ofn))
+ {
+ FCEUI_LoadMem(nameo,a,0); /* LL Load */
+ return(1);
+ }
+ return 0;
+}
+
+static BOOL CALLBACK MemCon(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ int32 scrollindex=0,ced=0;
+ char TempArray[64];
+
+ DSMFix(uMsg);
+
+ switch(uMsg)
+ {
+ case WM_CLOSE:
+ case WM_QUIT: goto gornk;
+
+ case WM_COMMAND:
+ switch(HIWORD(wParam))
+ {
+ case BN_CLICKED:
+ switch(LOWORD(wParam))
+ {
+ case 203:
+ case 202:
+ {
+ uint16 a;
+ uint8 v;
+ GetDlgItemText(hwndDlg,200,TempArray,64);
+ a=StrToU16(TempArray);
+ GetDlgItemText(hwndDlg,201,TempArray,64);
+ v=StrToU8(TempArray);
+ FCEUI_MemPoke(a,v,LOWORD(wParam)&1);
+ UpdateDMem(cmsi);
+
+ if(dwin && 0==instep)
+ {
+ int tscroll=32768+SendDlgItemMessage(dwin,101,SBM_GETPOS,0,0);
+ Disyou(tscroll);
+ }
+ }
+ break;
+ case 212:
+ {
+ uint16 a1;
+ uint16 a2;
+ GetDlgItemText(hwndDlg,210,TempArray,64);
+ a1=StrToU16(TempArray);
+ GetDlgItemText(hwndDlg,211,TempArray,64);
+ a2=StrToU16(TempArray);
+ CreateDumpSave(a1,a2);
+ }
+ break;
+ case 222:
+ {
+ uint16 a;
+ GetDlgItemText(hwndDlg,220,TempArray,64);
+ a=StrToU16(TempArray);
+ LoadSave(a);
+ UpdateDMem(cmsi);
+ if(dwin && 0==instep)
+ {
+ int tscroll=32768+SendDlgItemMessage(dwin,101,SBM_GETPOS,0,0);
+ Disyou(tscroll);
+ }
+ }
+ break;
+
+ }
+ break;
+ }
+
+ if(!(wParam>>16))
+ switch(wParam&0xFFFF)
+ {
+ case 1:
+ gornk:
+ DestroyWindow(mwin);
+ mwin=0;
+ break;
+ }
+ break;
+ case WM_INITDIALOG:
+ return(1);
+ case WM_VSCROLL:
+ switch((int)LOWORD(wParam))
+ {
+ case SB_TOP:
+ scrollindex=0;
+ ced=1;
+ break;
+ case SB_BOTTOM:
+ scrollindex=0xffff>>4;
+ ced=1;
+ break;
+ case SB_LINEUP:
+ scrollindex=GetScrollPos(GetDlgItem(hwndDlg,103),SB_CTL);
+ if(scrollindex>0)
+ {
+ scrollindex--;
+ ced=1;
+ }
+ break;
+
+ case SB_PAGEUP:
+ scrollindex=GetScrollPos(GetDlgItem(hwndDlg,103),SB_CTL);
+ scrollindex-=16;
+ if(scrollindex<0)
+ scrollindex=0;
+ ced=1;
+ break;
+
+ case SB_LINEDOWN:
+ scrollindex=GetScrollPos(GetDlgItem(hwndDlg,103),SB_CTL);
+ if(scrollindex<(0xFFFF>>4))
+ {
+ scrollindex++;
+ ced=1;
+ }
+ break;
+
+ case SB_PAGEDOWN:
+ scrollindex=GetScrollPos(GetDlgItem(hwndDlg,103),SB_CTL);
+ scrollindex+=16;
+ if(scrollindex>(0xFFFF>>4))
+ {
+ scrollindex=(65535>>4);
+ }
+ ced=1;
+ break;
+
+ case SB_THUMBPOSITION:
+ case SB_THUMBTRACK:
+ scrollindex=HIWORD(wParam);
+ ced=1;
+ break;
+ }
+ if(ced)
+ {
+ SendDlgItemMessage(hwndDlg,103,SBM_SETPOS,scrollindex,1);
+ UpdateDMem(scrollindex);
+ cmsi=scrollindex;
+ }
+ break;
+
+
+
+ }
+
+ return 0;
+}
+
+void DoMemmo(HWND hParent)
+{
+ if(mwin)
+ {
+ SetFocus(mwin);
+ return;
+ }
+ mwin=CreateDialog(fceu_hInstance,"MEMVIEW",0,MemCon);
+ MDSSI();
+ UpdateDMem(0);
+}
+
+void UpdateDebugger(void)
+{
+ if(mwin)
+ UpdateDMem(cmsi);
+}
+
+void KillDebugger(void)
+{
+ if(mwin)
+ DestroyWindow(mwin);
+ if(dwin)
+ DestroyWindow(dwin);
+ dwin=mwin=0;
+}
+#endif
diff --git a/drivers/win/debug.h b/drivers/win/debug.h
new file mode 100644
index 00000000..0ae7846f
--- /dev/null
+++ b/drivers/win/debug.h
@@ -0,0 +1,6 @@
+#ifdef FCEUDEF_DEBUGGER
+void KillDebugger(void);
+void UpdateDebugger(void);
+void BeginDSeq(HWND hParent);
+void DoMemmo(HWND hParent);
+#endif
diff --git a/drivers/win/input.c b/drivers/win/input.c
new file mode 100644
index 00000000..6a4327e1
--- /dev/null
+++ b/drivers/win/input.c
@@ -0,0 +1,1823 @@
+/* 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
+ */
+
+// For commctrl.h below
+#define _WIN32_IE 0x0300
+
+#include "common.h"
+#include <dinput.h>
+#include <windows.h>
+#include <commctrl.h>
+
+#include "input.h"
+#include "keyboard.h"
+#include "joystick.h"
+
+#include "keyscan.h"
+
+LPDIRECTINPUT7 lpDI=0;
+
+/* UsrInputType[] is user-specified. InputType[] is current
+ (game loading can override user settings)
+*/
+
+int UsrInputType[3]={SI_GAMEPAD,SI_GAMEPAD,SIFC_NONE};
+int InputType[3]={0,0,0};
+int cspec=0;
+
+int gametype=0;
+
+int InitDInput(void)
+{
+ HRESULT ddrval;
+
+ ddrval=DirectInputCreateEx(fceu_hInstance,DIRECTINPUT_VERSION,&IID_IDirectInput7,(LPVOID *)&lpDI,0);
+ if(ddrval!=DI_OK)
+ {
+ FCEUD_PrintError("DirectInput: Error creating DirectInput object.");
+ return 0;
+ }
+ return 1;
+}
+
+static uint32 MouseData[3];
+static int screenmode=0;
+void InputScreenChanged(int fs)
+{
+ int x;
+ if(GI)
+ {
+ for(x=0;x<2;x++)
+ if(InputType[x]==SI_ZAPPER)
+ FCEUI_SetInput(x,SI_ZAPPER,MouseData,fs);
+ if(InputType[2]==SIFC_SHADOW)
+ FCEUI_SetInputFC(SIFC_SHADOW,MouseData,fs);
+ }
+ screenmode=fs;
+}
+
+/* Necessary for proper GUI functioning(configuring when a game isn't loaded). */
+void InputUserActiveFix(void)
+{
+ int x;
+ for(x=0;x<3;x++) InputType[x]=UsrInputType[x];
+}
+
+void ParseGIInput(FCEUGI *gi)
+{
+ InputType[0]=UsrInputType[0];
+ InputType[1]=UsrInputType[1];
+ InputType[2]=UsrInputType[2];
+
+ if(gi)
+ {
+ if(gi->input[0]>=0)
+ InputType[0]=gi->input[0];
+ if(gi->input[1]>=0)
+ InputType[1]=gi->input[1];
+ if(gi->inputfc>=0)
+ InputType[2]=gi->inputfc;
+ cspec = gi->cspecial;
+ gametype=gi->type;
+
+ InitOtherInput();
+ }
+ else cspec=gametype=0;
+}
+
+
+static uint8 QuizKingData=0;
+static uint8 HyperShotData=0;
+static uint32 MahjongData=0;
+static uint32 FTrainerData=0;
+static uint8 TopRiderData=0;
+
+static uint8 BWorldData[1+13+1];
+
+static void UpdateFKB(void);
+static void UpdateSuborKB(void);
+ void UpdateGamepad(void);
+static void UpdateQuizKing(void);
+static void UpdateHyperShot(void);
+static void UpdateMahjong(void);
+static void UpdateFTrainer(void);
+static void UpdateTopRider(void);
+
+static uint32 JSreturn=0;
+int NoWaiting=0;
+
+#include "keyscan.h"
+static unsigned char *keys=0;
+static unsigned char *keys_nr=0;
+static int DIPS=0;
+
+static uint8 keyonce[MKK_COUNT];
+//#define KEY(__a) keys_nr[MKK(__a)]
+
+static int _keyonly(int a)
+{
+ if(keys_nr[a])
+ {
+ if(!keyonce[a])
+ {
+ keyonce[a]=1;
+ return(1);
+ }
+ }
+ else
+ keyonce[a]=0;
+ return(0);
+}
+
+int cidisabled=0;
+
+#define MK(x) {{BUTTC_KEYBOARD},{0},{MKK(x)},1}
+#define MC(x) {{BUTTC_KEYBOARD},{0},{x},1}
+#define MK2(x1,x2) {{BUTTC_KEYBOARD},{0},{MKK(x1),MKK(x2)},2}
+
+#define MKZ() {{0},{0},{0},0}
+
+#define GPZ() {MKZ(), MKZ(), MKZ(), MKZ()}
+
+ButtConfig GamePadConfig[4][10]={
+ /* Gamepad 1 */
+ {
+ MK(LEFTALT), MK(LEFTCONTROL), MK(TAB), MK(ENTER), MK(BL_CURSORUP),
+ MK(BL_CURSORDOWN),MK(BL_CURSORLEFT),MK(BL_CURSORRIGHT)
+ },
+
+ /* Gamepad 2 */
+ GPZ(),
+
+ /* Gamepad 3 */
+ GPZ(),
+
+ /* Gamepad 4 */
+ GPZ()
+};
+
+extern int rapidAlternator; // for auto-fire / autofire
+int DesynchAutoFire=0; // A and B not at same time
+uint32 JSAutoHeld=0, JSAutoHeldAffected=0; // for auto-hold
+uint8 autoHoldOn=0, autoHoldReset=0, autoHoldRefire=0; // for auto-hold
+
+void SetAutoFireDesynch(int DesynchOn)
+{
+ if(DesynchOn)
+ {
+ DesynchAutoFire = 1;
+ }
+ else
+ {
+ DesynchAutoFire = 0;
+ }
+}
+
+int GetAutoFireDesynch()
+{
+ return DesynchAutoFire;
+}
+
+void UpdateGamepad()
+{
+ if(FCEUI_IsMovieActive()<0)
+ return;
+
+ uint32 JS=0;
+ int x;
+ int wg;
+ if(FCEUI_IsMovieActive()>0)
+ AutoFire();
+
+ for(wg=0;wg<4;wg++)
+ {
+ for(x=0;x<8;x++)
+ if(DTestButton(&GamePadConfig[wg][x]))
+ JS|=(1<<x)<<(wg<<3);
+
+// if(rapidAlternator)
+ for(x=0;x<2;x++)
+ if(DTestButton(&GamePadConfig[wg][8+x]))
+ JS|=((1<<x)<<(wg<<3))*(rapidAlternator^(x*DesynchAutoFire));
+ }
+
+ if(autoHoldOn)
+ {
+ if(autoHoldRefire)
+ {
+ autoHoldRefire--;
+ if(!autoHoldRefire)
+ JSAutoHeldAffected = 0;
+ }
+
+ for(wg=0;wg<4;wg++)
+ for(x=0;x<8;x++)
+ if(DTestButton(&GamePadConfig[wg][x]))
+ {
+ if(!autoHoldRefire || !(JSAutoHeldAffected&(1<<x)<<(wg<<3)))
+ {
+ JSAutoHeld^=(1<<x)<<(wg<<3);
+ JSAutoHeldAffected|=(1<<x)<<(wg<<3);
+ autoHoldRefire = 192;
+ }
+ }
+
+ char inputstr [32];
+ {
+ uint32 c = JSAutoHeld;
+ sprintf(inputstr, "%c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
+ (c&0x40)?'<':' ', (c&0x10)?'^':' ', (c&0x80)?'>':' ', (c&0x20)?'v':' ',
+ (c&0x01)?'A':' ', (c&0x02)?'B':' ', (c&0x08)?'S':' ', (c&0x04)?'s':' ',
+ (c&0x4000)?'<':' ', (c&0x1000)?'^':' ', (c&0x8000)?'>':' ', (c&0x2000)?'v':' ',
+ (c&0x0100)?'A':' ', (c&0x0200)?'B':' ', (c&0x0800)?'S':' ', (c&0x0400)?'s':' ');
+ if(!(c&0xff00))
+ inputstr[8] = '\0';
+ }
+ FCEU_DispMessage("Held: %s", inputstr);
+ }
+ else
+ {
+ JSAutoHeldAffected = 0;
+ autoHoldRefire = 0;
+ }
+
+ if(autoHoldReset)
+ {
+ FCEU_DispMessage("Held: ");
+ JSAutoHeld = 0;
+ JSAutoHeldAffected = 0;
+ autoHoldRefire = 0;
+ }
+
+ // apply auto-hold
+ if(JSAutoHeld)
+ JS ^= JSAutoHeld;
+
+ JSreturn=JS;
+}
+
+ButtConfig powerpadsc[2][12]={
+ {
+ MK(O),MK(P),MK(BRACKET_LEFT),
+ MK(BRACKET_RIGHT),
+
+ MK(K),MK(L),MK(SEMICOLON),
+ MK(APOSTROPHE),
+ MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
+ },
+ {
+ MK(O),MK(P),MK(BRACKET_LEFT),
+ MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
+ MK(APOSTROPHE),
+ MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
+ }
+ };
+
+static uint32 powerpadbuf[2];
+
+static uint32 UpdatePPadData(int w)
+{
+ uint32 r=0;
+ ButtConfig *ppadtsc=powerpadsc[w];
+ int x;
+
+ for(x=0;x<12;x++)
+ if(DTestButton(&ppadtsc[x])) r|=1<<x;
+
+ return r;
+}
+
+
+static uint8 fkbkeys[0x48];
+static uint8 suborkbkeys[0x60];
+
+void FCEUD_UpdateInput()
+{
+ int x;
+ int t=0;
+
+ KeyboardUpdateState();
+ UpdateJoysticks();
+
+ //UpdatePhysicalInput();
+ //KeyboardCommands();
+ FCEUI_HandleEmuCommands(FCEUD_TestCommandState);
+
+ {
+ for(x=0;x<2;x++)
+ switch(InputType[x])
+ {
+ case SI_GAMEPAD:t|=1;break;
+ case SI_ARKANOID:t|=2;break;
+ case SI_ZAPPER:t|=2;break;
+ case SI_POWERPADA:
+ case SI_POWERPADB:powerpadbuf[x]=UpdatePPadData(x);break;
+ }
+
+ switch(InputType[2])
+ {
+ case SIFC_ARKANOID:t|=2;break;
+ case SIFC_SHADOW:t|=2;break;
+ case SIFC_FKB:if(cidisabled) UpdateFKB();break;
+ case SIFC_SUBORKB:if(cidisabled) UpdateSuborKB();break;
+ case SIFC_HYPERSHOT: UpdateHyperShot();break;
+ case SIFC_MAHJONG: UpdateMahjong();break;
+ case SIFC_QUIZKING: UpdateQuizKing();break;
+ case SIFC_FTRAINERB:
+ case SIFC_FTRAINERA: UpdateFTrainer();break;
+ case SIFC_TOPRIDER: UpdateTopRider();break;
+ case SIFC_OEKAKIDS:t|=2;break;
+ }
+
+ if(t&1)
+ UpdateGamepad();
+
+ if(t&2)
+ GetMouseData(MouseData);
+ }
+}
+
+void InitOtherInput(void)
+{
+ void *InputDPtr;
+
+ int t;
+ int x;
+ int attrib;
+
+ for(t=0,x=0;x<2;x++)
+ {
+ attrib=0;
+ InputDPtr=0;
+ switch(InputType[x])
+ {
+ case SI_POWERPADA:
+ case SI_POWERPADB:InputDPtr=&powerpadbuf[x];break;
+ case SI_GAMEPAD:InputDPtr=&JSreturn;break;
+ case SI_ARKANOID:InputDPtr=MouseData;t|=1;break;
+ case SI_ZAPPER:InputDPtr=MouseData;
+ t|=1;
+ attrib=screenmode;
+ break;
+ }
+ FCEUI_SetInput(x,InputType[x],InputDPtr,attrib);
+ }
+
+ attrib=0;
+ InputDPtr=0;
+ switch(InputType[2])
+ {
+ case SIFC_SHADOW:InputDPtr=MouseData;t|=1;attrib=screenmode;break;
+ case SIFC_OEKAKIDS:InputDPtr=MouseData;t|=1;attrib=screenmode;break;
+ case SIFC_ARKANOID:InputDPtr=MouseData;t|=1;break;
+ case SIFC_FKB:InputDPtr=fkbkeys;break;
+ case SIFC_SUBORKB:InputDPtr=suborkbkeys;break;
+ case SIFC_HYPERSHOT:InputDPtr=&HyperShotData;break;
+ case SIFC_MAHJONG:InputDPtr=&MahjongData;break;
+ case SIFC_QUIZKING:InputDPtr=&QuizKingData;break;
+ case SIFC_TOPRIDER:InputDPtr=&TopRiderData;break;
+ case SIFC_BWORLD:InputDPtr=BWorldData;break;
+ case SIFC_FTRAINERA:
+ case SIFC_FTRAINERB:InputDPtr=&FTrainerData;break;
+ }
+
+ FCEUI_SetInputFC(InputType[2],InputDPtr,attrib);
+ FCEUI_DisableFourScore(eoptions&EO_NOFOURSCORE);
+}
+
+ButtConfig fkbmap[0x48]=
+{
+ MK(F1),MK(F2),MK(F3),MK(F4),MK(F5),MK(F6),MK(F7),MK(F8),
+ MK(1),MK(2),MK(3),MK(4),MK(5),MK(6),MK(7),MK(8),MK(9),MK(0),
+ MK(MINUS),MK(EQUAL),MK(BACKSLASH),MK(BACKSPACE),
+ MK(ESCAPE),MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y),MK(U),MK(I),MK(O),
+ MK(P),MK(GRAVE),MK(BRACKET_LEFT),MK(ENTER),
+ MK(LEFTCONTROL),MK(A),MK(S),MK(D),MK(F),MK(G),MK(H),MK(J),MK(K),
+ MK(L),MK(SEMICOLON),MK(APOSTROPHE),MK(BRACKET_RIGHT),MK(INSERT),
+ MK(LEFTSHIFT),MK(Z),MK(X),MK(C),MK(V),MK(B),MK(N),MK(M),MK(COMMA),
+ MK(PERIOD),MK(SLASH),MK(RIGHTALT),MK(RIGHTSHIFT),MK(LEFTALT),MK(SPACE),
+ MK(BL_DELETE),
+ MK(BL_END),
+ MK(BL_PAGEDOWN),
+ MK(BL_CURSORUP),MK(BL_CURSORLEFT),MK(BL_CURSORRIGHT),MK(BL_CURSORDOWN)
+};
+
+ButtConfig suborkbmap[0x60]=
+{
+ MC(0x01),MC(0x3b),MC(0x3c),MC(0x3d),MC(0x3e),MC(0x3f),MC(0x40),MC(0x41),MC(0x42),MC(0x43),
+ MC(0x44),MC(0x57),MC(0x58),MC(0x45),MC(0x29),MC(0x02),MC(0x03),MC(0x04),MC(0x05),MC(0x06),
+ MC(0x07),MC(0x08),MC(0x09),MC(0x0a),MC(0x0b),MC(0x0c),MC(0x0d),MC(0x0e),MC(0xd2),MC(0xc7),
+ MC(0xc9),MC(0xc5),MC(0xb5),MC(0x37),MC(0x4a),MC(0x0f),MC(0x10),MC(0x11),MC(0x12),MC(0x13),
+ MC(0x14),MC(0x15),MC(0x16),MC(0x17),MC(0x18),MC(0x19),MC(0x1a),MC(0x1b),MC(0x1c),MC(0xd3),
+ MC(0xca),MC(0xd1),MC(0x47),MC(0x48),MC(0x49),MC(0x4e),MC(0x3a),MC(0x1e),MC(0x1f),MC(0x20),
+ MC(0x21),MC(0x22),MC(0x23),MC(0x24),MC(0x25),MC(0x26),MC(0x27),MC(0x28),MC(0x4b),MC(0x4c),
+ MC(0x4d),MC(0x2a),MC(0x2c),MC(0x2d),MC(0x2e),MC(0x2f),MC(0x30),MC(0x31),MC(0x32),MC(0x33),
+ MC(0x34),MC(0x35),MC(0x2b),MC(0xc8),MC(0x4f),MC(0x50),MC(0x51),MC(0x1d),MC(0x38),MC(0x39),
+ MC(0xcb),MC(0xd0),MC(0xcd),MC(0x52),MC(0x53)
+};
+
+
+static void UpdateFKB(void)
+{
+ int x;
+
+ for(x=0;x<0x48;x++)
+ {
+ fkbkeys[x]=0;
+
+ if(DTestButton(&fkbmap[x]))
+ fkbkeys[x]=1;
+ }
+}
+
+static void UpdateSuborKB(void)
+{
+ int x;
+
+ for(x=0;x<0x60;x++)
+ {
+ suborkbkeys[x]=0;
+
+ if(DTestButton(&suborkbmap[x]))
+ suborkbkeys[x]=1;
+ }
+}
+
+static ButtConfig HyperShotButtons[4]=
+{
+ MK(Q),MK(W),MK(E),MK(R)
+};
+
+static void UpdateHyperShot(void)
+{
+ int x;
+
+ HyperShotData=0;
+ for(x=0;x<0x4;x++)
+ {
+ if(DTestButton(&HyperShotButtons[x]))
+ HyperShotData|=1<<x;
+ }
+}
+
+static ButtConfig MahjongButtons[21]=
+{
+ MK(Q),MK(W),MK(E),MK(R),MK(T),
+ MK(A),MK(S),MK(D),MK(F),MK(G),MK(H),MK(J),MK(K),MK(L),
+ MK(Z),MK(X),MK(C),MK(V),MK(B),MK(N),MK(M)
+};
+
+static void UpdateMahjong(void)
+{
+ int x;
+
+ MahjongData=0;
+ for(x=0;x<21;x++)
+ {
+ if(DTestButton(&MahjongButtons[x]))
+ MahjongData|=1<<x;
+ }
+}
+
+ButtConfig QuizKingButtons[6]=
+{
+ MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y)
+};
+
+static void UpdateQuizKing(void)
+{
+ int x;
+
+ QuizKingData=0;
+
+ for(x=0;x<6;x++)
+ {
+ if(DTestButton(&QuizKingButtons[x]))
+ QuizKingData|=1<<x;
+ }
+
+}
+
+ButtConfig TopRiderButtons[8]=
+{
+ MK(Q),MK(W),MK(E),MK(R),MK(T),MK(Y),MK(U),MK(I)
+};
+
+static void UpdateTopRider(void)
+{
+ int x;
+ TopRiderData=0;
+ for(x=0;x<8;x++)
+ if(DTestButton(&TopRiderButtons[x]))
+ TopRiderData|=1<<x;
+}
+
+ButtConfig FTrainerButtons[12]=
+{
+ MK(O),MK(P),MK(BRACKET_LEFT),
+ MK(BRACKET_RIGHT),MK(K),MK(L),MK(SEMICOLON),
+ MK(APOSTROPHE),
+ MK(M),MK(COMMA),MK(PERIOD),MK(SLASH)
+};
+
+static void UpdateFTrainer(void)
+{
+ int x;
+
+ FTrainerData=0;
+
+ for(x=0;x<12;x++)
+ {
+ if(DTestButton(&FTrainerButtons[x]))
+ FTrainerData|=1<<x;
+ }
+}
+
+int DWaitButton(HWND hParent, const uint8 *text, ButtConfig *bc);
+int DWaitSimpleButton(HWND hParent, const uint8 *text);
+
+CFGSTRUCT InputConfig[]={
+ ACA(UsrInputType),
+ AC(powerpadsc),
+ AC(QuizKingButtons),
+ AC(FTrainerButtons),
+ AC(HyperShotButtons),
+ AC(MahjongButtons),
+ AC(GamePadConfig),
+ AC(fkbmap),
+ AC(suborkbmap),
+ ENDCFGSTRUCT
+};
+
+void InitInputStuff(void)
+{
+ int x,y;
+
+ KeyboardInitialize();
+ InitJoysticks(hAppWnd);
+
+ for(x=0; x<4; x++)
+ for(y=0; y<10; y++)
+ JoyClearBC(&GamePadConfig[x][y]);
+
+ for(x=0; x<2; x++)
+ for(y=0; y<12; y++)
+ JoyClearBC(&powerpadsc[x][y]);
+
+ for(x=0; x<0x48; x++)
+ JoyClearBC(&fkbmap[x]);
+ for(x=0; x<0x60; x++)
+ JoyClearBC(&suborkbmap[x]);
+
+ for(x=0; x<6; x++)
+ JoyClearBC(&QuizKingButtons[x]);
+ for(x=0; x<12; x++)
+ JoyClearBC(&FTrainerButtons[x]);
+ for(x=0; x<21; x++)
+ JoyClearBC(&MahjongButtons[x]);
+ for(x=0; x<4; x++)
+ JoyClearBC(&HyperShotButtons[x]);
+}
+
+
+
+static void FCExp(char *text)
+{
+ static char *fccortab[12]={"none","arkanoid","shadow","4player","fkb","suborkb",
+ "hypershot","mahjong","quizking","ftrainera","ftrainerb","oekakids"};
+
+ static int fccortabi[12]={SIFC_NONE,SIFC_ARKANOID,SIFC_SHADOW,
+ SIFC_4PLAYER,SIFC_FKB,SIFC_SUBORKB,SIFC_HYPERSHOT,SIFC_MAHJONG,SIFC_QUIZKING,
+ SIFC_FTRAINERA,SIFC_FTRAINERB,SIFC_OEKAKIDS};
+ int y;
+ for(y=0;y<12;y++)
+ if(!strcmp(fccortab[y],text))
+ UsrInputType[2]=fccortabi[y];
+}
+
+static char *cortab[6]={"none","gamepad","zapper","powerpada","powerpadb","arkanoid"};
+static int cortabi[6]={SI_NONE,SI_GAMEPAD,
+ SI_ZAPPER,SI_POWERPADA,SI_POWERPADB,SI_ARKANOID};
+
+static void Input1(char *text)
+{
+ int y;
+
+ for(y=0;y<6;y++)
+ if(!strcmp(cortab[y],text))
+ UsrInputType[0]=cortabi[y];
+}
+
+static void Input2(char *text)
+{
+ int y;
+
+ for(y=0;y<6;y++)
+ if(!strcmp(cortab[y],text))
+ UsrInputType[1]=cortabi[y];
+}
+
+ARGPSTRUCT InputArgs[]={
+ {"-fcexp",0,(void *)FCExp,0x2000},
+ {"-input1",0,(void *)Input1,0x2000},
+ {"-input2",0,(void *)Input2,0x2000},
+ {0,0,0,0}
+};
+
+int DTestButton(ButtConfig *bc)
+{
+ int x;
+
+ for(x=0;x<bc->NumC;x++)
+ {
+ if(bc->ButtType[x]==BUTTC_KEYBOARD)
+ {
+ if(keys_nr[bc->ButtonNum[x]])
+ {
+ return(1);
+ }
+ }
+ }
+ if(DTestButtonJoy(bc)) return(1);
+ return(0);
+}
+
+static char *MakeButtString(ButtConfig *bc)
+{
+ int x;
+ char tmpstr[512];
+ char *astr;
+
+ tmpstr[0] = 0;
+
+ for(x=0;x<bc->NumC;x++)
+ {
+ if(x) strcat(tmpstr, ", ");
+
+ if(bc->ButtType[x] == BUTTC_KEYBOARD)
+ {
+ strcat(tmpstr,"KB: ");
+ if(!GetKeyNameText(bc->ButtonNum[x]<<16,tmpstr+strlen(tmpstr),16))
+ {
+ switch(bc->ButtonNum[x])
+ {
+ case 200: strcpy(tmpstr+strlen(tmpstr),"Up Arrow"); break;
+ case 203: strcpy(tmpstr+strlen(tmpstr),"Left Arrow"); break;
+ case 205: strcpy(tmpstr+strlen(tmpstr),"Right Arrow"); break;
+ case 208: strcpy(tmpstr+strlen(tmpstr),"Down Arrow"); break;
+ default: sprintf(tmpstr+strlen(tmpstr),"%03d",bc->ButtonNum[x]); break;
+ }
+ }
+ }
+ else if(bc->ButtType[x] == BUTTC_JOYSTICK)
+ {
+ strcat(tmpstr,"JS ");
+ sprintf(tmpstr+strlen(tmpstr), "%d ", bc->DeviceNum[x]);
+ if(bc->ButtonNum[x] & 0x8000)
+ {
+ char *asel[3]={"x","y","z"};
+ sprintf(tmpstr+strlen(tmpstr), "axis %s%s", asel[bc->ButtonNum[x] & 3],(bc->ButtonNum[x]&0x4000)?"-":"+");
+ }
+ else if(bc->ButtonNum[x] & 0x2000)
+ {
+ sprintf(tmpstr+strlen(tmpstr), "hat %d:%d", (bc->ButtonNum[x] >> 4)&3,
+ bc->ButtonNum[x]&3);
+ }
+ else
+ {
+ sprintf(tmpstr+strlen(tmpstr), "button %d", bc->ButtonNum[x] & 127);
+ }
+
+ }
+ }
+
+ astr=malloc(strlen(tmpstr) + 1);
+ strcpy(astr,tmpstr);
+ return(astr);
+}
+
+
+static int DWBStarted;
+static ButtConfig *DWBButtons;
+static const uint8 *DWBText;
+
+static HWND die;
+
+static BOOL CALLBACK DWBCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+
+ switch(uMsg) {
+ case WM_DESTROY:
+ die = NULL;
+ return(0);
+ case WM_TIMER:
+ {
+ uint8 devicenum;
+ uint16 buttonnum;
+ GUID guid;
+
+ if(DoJoyWaitTest(&guid, &devicenum, &buttonnum))
+ {
+ ButtConfig *bc = DWBButtons;
+ char *nstr;
+ int wc;
+ if(DWBStarted)
+ {
+ ButtConfig *bc = DWBButtons;
+ bc->NumC = 0;
+ DWBStarted = 0;
+ }
+ wc = bc->NumC;
+ //FCEU_printf("%d: %d\n",devicenum,buttonnum);
+ bc->ButtType[wc]=BUTTC_JOYSTICK;
+ bc->DeviceNum[wc]=devicenum;
+ bc->ButtonNum[wc]=buttonnum;
+ bc->DeviceInstance[wc] = guid;
+
+ /* Stop config if the user pushes the same button twice in a row. */
+ if(wc && bc->ButtType[wc]==bc->ButtType[wc-1] && bc->DeviceNum[wc]==bc->DeviceNum[wc-1] &&
+ bc->ButtonNum[wc]==bc->ButtonNum[wc-1])
+ goto gornk;
+
+ bc->NumC++;
+
+ /* Stop config if we reached our maximum button limit. */
+ if(bc->NumC >= MAXBUTTCONFIG)
+ goto gornk;
+ nstr = MakeButtString(bc);
+ SetDlgItemText(hwndDlg, 100, nstr);
+ free(nstr);
+ }
+ }
+ break;
+ case WM_USER + 666:
+ //SetFocus(GetDlgItem(hwndDlg,100));
+ if(DWBStarted)
+ {
+ char *nstr;
+ ButtConfig *bc = DWBButtons;
+ bc->NumC = 0;
+ DWBStarted = 0;
+ nstr = MakeButtString(bc);
+ SetDlgItemText(hwndDlg, 100, nstr);
+ free(nstr);
+ }
+
+ {
+ ButtConfig *bc = DWBButtons;
+ int wc = bc->NumC;
+ char *nstr;
+
+ bc->ButtType[wc]=BUTTC_KEYBOARD;
+ bc->DeviceNum[wc]=0;
+ bc->ButtonNum[wc]=lParam&255;
+
+ /* Stop config if the user pushes the same button twice in a row. */
+ if(wc && bc->ButtType[wc]==bc->ButtType[wc-1] && bc->DeviceNum[wc]==bc->DeviceNum[wc-1] &&
+ bc->ButtonNum[wc]==bc->ButtonNum[wc-1])
+ goto gornk;
+
+ bc->NumC++;
+ /* Stop config if we reached our maximum button limit. */
+ if(bc->NumC >= MAXBUTTCONFIG)
+ goto gornk;
+
+ nstr = MakeButtString(bc);
+ SetDlgItemText(hwndDlg, 100, nstr);
+ free(nstr);
+ }
+ break;
+ case WM_INITDIALOG:
+ SetWindowText(hwndDlg, DWBText);
+ BeginJoyWait(hwndDlg);
+ SetTimer(hwndDlg,666,25,0); /* Every 25ms.*/
+ {
+ char *nstr = MakeButtString(DWBButtons);
+ SetDlgItemText(hwndDlg, 100, nstr);
+ free(nstr);
+ }
+ break;
+ case WM_CLOSE:
+ case WM_QUIT: goto gornk;
+
+ case WM_COMMAND:
+ switch(wParam&0xFFFF)
+ {
+ case 200:
+ {
+ ButtConfig *bc = DWBButtons;
+ char *nstr;
+ bc->NumC = 0;
+ nstr = MakeButtString(bc);
+ SetDlgItemText(hwndDlg, 100, nstr);
+ free(nstr);
+ }
+ break;
+ case 201:
+ gornk:
+ KillTimer(hwndDlg,666);
+ EndJoyWait(hAppWnd);
+ SetForegroundWindow(GetParent(hwndDlg));
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ }
+ return 0;
+}
+
+int DWaitButton(HWND hParent, const uint8 *text, ButtConfig *bc)
+{
+ DWBText=text;
+ DWBButtons = bc;
+ DWBStarted = 1;
+
+ die = CreateDialog(fceu_hInstance, "DWBDIALOG", hParent, DWBCallB);
+
+ EnableWindow(hParent, 0);
+
+ ShowWindow(die, 1);
+
+ while(die)
+ {
+ MSG msg;
+ while(PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE))
+ {
+ if(GetMessage(&msg, 0, 0, 0) > 0)
+ {
+ if(msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN)
+ {
+ LPARAM tmpo;
+
+ tmpo=((msg.lParam>>16)&0x7F)|((msg.lParam>>17)&0x80);
+ PostMessage(die,WM_USER+666,0,tmpo);
+ continue;
+ }
+ if(msg.message == WM_SYSCOMMAND) continue;
+ if(!IsDialogMessage(die, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ }
+ Sleep(10);
+ }
+
+ EnableWindow(hParent, 1);
+}
+
+int DWaitSimpleButton(HWND hParent, const uint8 *text)
+{
+ DWBStarted = 1;
+ int ret = 0;
+
+ die = CreateDialog(fceu_hInstance, "DWBDIALOGSIMPLE", hParent, NULL);
+ SetWindowText(die, text);
+ EnableWindow(hParent, 0);
+
+ ShowWindow(die, 1);
+
+ while(die)
+ {
+ MSG msg;
+ while(PeekMessage(&msg, 0, 0, 0, PM_NOREMOVE))
+ {
+ if(GetMessage(&msg, 0, 0, 0) > 0)
+ {
+ if(msg.message == WM_KEYDOWN || msg.message == WM_SYSKEYDOWN)
+ {
+ LPARAM tmpo;
+
+ tmpo=((msg.lParam>>16)&0x7F)|((msg.lParam>>17)&0x80);
+ ret = tmpo;
+ goto done;
+ }
+ if(msg.message == WM_SYSCOMMAND) continue;
+ if(!IsDialogMessage(die, &msg))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ }
+ Sleep(10);
+ }
+done:
+ EndDialog(die,0);
+ EnableWindow(hParent, 1);
+
+ if(ret == 1) // convert Esc to nothing (why is it 1 and not VK_ESCAPE?)
+ ret = 0;
+ return ret;
+}
+
+
+static ButtConfig *DoTBButtons=0;
+static const char *DoTBTitle=0;
+static int DoTBMax=0;
+static int DoTBType=0,DoTBPort=0;
+
+static BOOL CALLBACK DoTBCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ if(DoTBType == SI_GAMEPAD)
+ {
+ char buf[32];
+ sprintf(buf,"Virtual Gamepad %d",DoTBPort+1);
+ SetDlgItemText(hwndDlg, 100,buf);
+
+ sprintf(buf,"Virtual Gamepad %d",DoTBPort+3);
+ SetDlgItemText(hwndDlg, 101, buf);
+
+ CheckDlgButton(hwndDlg,400,(eoptions & EO_NOFOURSCORE)?BST_CHECKED:BST_UNCHECKED);
+ }
+ SetWindowText(hwndDlg, DoTBTitle);
+ break;
+ case WM_CLOSE:
+ case WM_QUIT: goto gornk;
+
+ case WM_COMMAND:
+ {
+ int b;
+ b=wParam&0xFFFF;
+ if(b>= 300 && b < (300 + DoTBMax))
+ {
+ char btext[128];
+ btext[0]=0;
+ GetDlgItemText(hwndDlg, b, btext, 128);
+ DWaitButton(hwndDlg, btext,&DoTBButtons[b - 300]);
+ }
+ else switch(wParam&0xFFFF)
+ {
+ case 1:
+ gornk:
+
+ if(DoTBType == SI_GAMEPAD)
+ {
+ eoptions &= ~EO_NOFOURSCORE;
+ if(IsDlgButtonChecked(hwndDlg,400)==BST_CHECKED)
+ eoptions|=EO_NOFOURSCORE;
+ }
+ EndDialog(hwndDlg,0);
+ break;
+ }
+ }
+ }
+ return 0;
+
+}
+
+static void DoTBConfig(HWND hParent, const char *text, char *template, ButtConfig *buttons, int max)
+{
+ DoTBTitle=text;
+ DoTBButtons = buttons;
+ DoTBMax = max;
+ DialogBox(fceu_hInstance,template,hParent,DoTBCallB);
+}
+
+static BOOL CALLBACK InputConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ static const char *strn[6]={"<none>","Gamepad","Zapper","Power Pad A","Power Pad B","Arkanoid Paddle"};
+ static const char *strf[14]=
+ {"<none>","Arkanoid Paddle","Hyper Shot gun","4-Player Adapter",
+ "Family Keyboard","Subor Keyboard","HyperShot Pads", "Mahjong", "Quiz King Buzzers",
+ "Family Trainer A","Family Trainer B", "Oeka Kids Tablet", "Barcode World",
+ "Top Rider"};
+ static const int haven[6]={0,1,0,1,1,0};
+ static const int havef[14]={0,0,0,0, 1,1,0,0, 1,1,1,0, 0,0};
+ int x;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ for(x=0;x<2;x++)
+ {
+ int y;
+
+ for(y=0;y<6;y++)
+ SendDlgItemMessage(hwndDlg,104+x,CB_ADDSTRING,0,(LPARAM)(LPSTR)strn[y]);
+
+ SendDlgItemMessage(hwndDlg,104+x,CB_SETCURSEL,UsrInputType[x],(LPARAM)(LPSTR)0);
+ EnableWindow(GetDlgItem(hwndDlg,106+x),haven[InputType[x]]);
+ SetDlgItemText(hwndDlg,200+x,(LPTSTR)strn[InputType[x]]);
+ }
+
+
+ {
+ int y;
+ for(y=0;y<13;y++)
+ SendDlgItemMessage(hwndDlg,110,CB_ADDSTRING,0,(LPARAM)(LPSTR)strf[y]);
+ SendDlgItemMessage(hwndDlg,110,CB_SETCURSEL,UsrInputType[2],(LPARAM)(LPSTR)0);
+ EnableWindow(GetDlgItem(hwndDlg,111),havef[InputType[2]]);
+ SetDlgItemText(hwndDlg,202,(LPTSTR)strf[InputType[2]]);
+ }
+
+ extern int autoHoldKey, autoHoldClearKey;
+ char btext[128];
+ if(autoHoldKey)
+ {
+ if(!GetKeyNameText(autoHoldKey<<16,btext,128))
+ sprintf(btext, "KB: %d", autoHoldKey);
+ }
+ else
+ sprintf(btext, "not assigned");
+ SetDlgItemText(hwndDlg, 115, btext);
+
+ if(autoHoldClearKey)
+ {
+ if(!GetKeyNameText(autoHoldClearKey<<16,btext,128))
+ sprintf(btext, "KB: %d", autoHoldClearKey);
+ }
+ else
+ sprintf(btext, "not assigned");
+ SetDlgItemText(hwndDlg, 116, btext);
+
+ break;
+ case WM_CLOSE:
+ case WM_QUIT: goto gornk;
+ case WM_COMMAND:
+ if(HIWORD(wParam)==CBN_SELENDOK)
+ {
+ switch(LOWORD(wParam))
+ {
+ case 104:
+ case 105:UsrInputType[LOWORD(wParam)-104]=InputType[LOWORD(wParam)-104]=SendDlgItemMessage(hwndDlg,LOWORD(wParam),CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
+ EnableWindow( GetDlgItem(hwndDlg,LOWORD(wParam)+2),haven[InputType[LOWORD(wParam)-104]]);
+ SetDlgItemText(hwndDlg,200+LOWORD(wParam)-104,(LPTSTR)strn[InputType[LOWORD(wParam)-104]]);
+ break;
+ case 110:UsrInputType[2]=InputType[2]=SendDlgItemMessage(hwndDlg,110,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
+ EnableWindow(GetDlgItem(hwndDlg,111),havef[InputType[2]]);
+ SetDlgItemText(hwndDlg,202,(LPTSTR)strf[InputType[2]]);
+ break;
+
+ }
+
+ }
+ if(!(wParam>>16))
+ switch(wParam&0xFFFF)
+ {
+ case 111:
+ {
+ const char *text = strf[InputType[2]];
+ DoTBType=DoTBPort=0;
+
+ switch(InputType[2])
+ {
+ case SIFC_FTRAINERA:
+ case SIFC_FTRAINERB:DoTBConfig(hwndDlg, text, "POWERPADDIALOG", FTrainerButtons, 12); break;
+ case SIFC_FKB:DoTBConfig(hwndDlg, text, "FKBDIALOG",fkbmap,0x48);break;
+ case SIFC_SUBORKB:DoTBConfig(hwndDlg, text, "SUBORKBDIALOG",suborkbmap,0x60);break;
+ case SIFC_QUIZKING:DoTBConfig(hwndDlg, text, "QUIZKINGDIALOG",QuizKingButtons,6);break;
+ }
+ }
+ break;
+
+ case 107:
+ case 106:
+ {
+ int which=(wParam&0xFFFF)-106;
+ const char *text = strn[InputType[which]];
+
+ DoTBType=DoTBPort=0;
+ switch(InputType[which])
+ {
+ case SI_GAMEPAD:
+ {
+ ButtConfig tmp[10 + 10];
+
+ memcpy(tmp, GamePadConfig[which], 10 * sizeof(ButtConfig));
+ memcpy(&tmp[10], GamePadConfig[which+2], 10 * sizeof(ButtConfig));
+
+ DoTBType=SI_GAMEPAD;
+ DoTBPort=which;
+ DoTBConfig(hwndDlg, text, "GAMEPADDIALOG", tmp, 10 + 10);
+
+ memcpy(GamePadConfig[which], tmp, 10 * sizeof(ButtConfig));
+ memcpy(GamePadConfig[which+2], &tmp[10], 10 * sizeof(ButtConfig));
+ }
+ break;
+
+ case SI_POWERPADA:
+ case SI_POWERPADB:
+ DoTBConfig(hwndDlg, text, "POWERPADDIALOG",powerpadsc[which],12);
+ break;
+ }
+ }
+ break;
+
+ case 112: // auto-hold button
+ {
+ char btext[128];
+ btext[0]=0;
+ GetDlgItemText(hwndDlg, 112, btext, 128);
+ int button = DWaitSimpleButton(hwndDlg, btext);
+ if(button)
+ {
+ if(!GetKeyNameText(button<<16,btext,128))
+ sprintf(btext, "KB: %d", button);
+ }
+ else
+ sprintf(btext, "not assigned");
+ extern int autoHoldKey;
+ autoHoldKey = button;
+ SetDlgItemText(hwndDlg, 115, btext);
+ }
+ break;
+ case 114: // auto-hold clear button
+ {
+ char btext[128];
+ btext[0]=0;
+ GetDlgItemText(hwndDlg, 114, btext, 128);
+ int button = DWaitSimpleButton(hwndDlg, btext);
+ if(button)
+ {
+ if(!GetKeyNameText(button<<16,btext,128))
+ sprintf(btext, "KB: %d", button);
+ }
+ else
+ sprintf(btext, "not assigned");
+ extern int autoHoldClearKey;
+ autoHoldClearKey = button;
+ SetDlgItemText(hwndDlg, 116, btext);
+ }
+ break;
+
+ case 1:
+ gornk:
+ EndDialog(hwndDlg,0);
+ break;
+ }
+ }
+ return 0;
+}
+
+void ConfigInput(HWND hParent)
+{
+ DialogBox(fceu_hInstance,"INPUTCONFIG",hParent,InputConCallB);
+ if(GI)
+ InitOtherInput();
+}
+
+
+
+void DestroyInput(void)
+{
+ if(lpDI)
+ {
+ KillJoysticks();
+ KeyboardClose();
+ IDirectInput7_Release(lpDI);
+ }
+}
+
+#define CMD_KEY_MASK 0xff
+#define CMD_KEY_LSHIFT (1<<16)
+#define CMD_KEY_RSHIFT (1<<17)
+#define CMD_KEY_SHIFT (CMD_KEY_LSHIFT|CMD_KEY_RSHIFT)
+#define CMD_KEY_LCTRL (1<<18)
+#define CMD_KEY_RCTRL (1<<19)
+#define CMD_KEY_CTRL (CMD_KEY_LCTRL|CMD_KEY_RCTRL)
+#define CMD_KEY_LALT (1<<20)
+#define CMD_KEY_RALT (1<<21)
+#define CMD_KEY_ALT (CMD_KEY_LALT|CMD_KEY_RALT)
+
+int FCEUD_CommandMapping[EMUCMD_MAX];
+
+CFGSTRUCT HotkeyConfig[]={
+ AC(FCEUD_CommandMapping),
+ ENDCFGSTRUCT
+};
+
+static struct
+{
+ int cmd;
+ int key;
+} DefaultCommandMapping[]=
+{
+ { EMUCMD_RESET, SCAN_R | CMD_KEY_CTRL, },
+ { EMUCMD_PAUSE, SCAN_PAUSE, },
+ { EMUCMD_FRAME_ADVANCE, SCAN_BACKSLASH, },
+ { EMUCMD_SCREENSHOT, SCAN_F12 },
+ { EMUCMD_HIDE_MENU_TOGGLE, SCAN_ESCAPE },
+ { EMUCMD_SPEED_SLOWER, SCAN_MINUS, },
+ { EMUCMD_SPEED_FASTER, SCAN_EQUAL, },
+ { EMUCMD_SPEED_TURBO, SCAN_TAB, },
+ { EMUCMD_SAVE_SLOT_0, SCAN_0, },
+ { EMUCMD_SAVE_SLOT_1, SCAN_1, },
+ { EMUCMD_SAVE_SLOT_2, SCAN_2, },
+ { EMUCMD_SAVE_SLOT_3, SCAN_3, },
+ { EMUCMD_SAVE_SLOT_4, SCAN_4, },
+ { EMUCMD_SAVE_SLOT_5, SCAN_5, },
+ { EMUCMD_SAVE_SLOT_6, SCAN_6, },
+ { EMUCMD_SAVE_SLOT_7, SCAN_7, },
+ { EMUCMD_SAVE_SLOT_8, SCAN_8, },
+ { EMUCMD_SAVE_SLOT_9, SCAN_9, },
+ { EMUCMD_SAVE_STATE, SCAN_F5 | CMD_KEY_CTRL, },
+ { EMUCMD_LOAD_STATE, SCAN_F7 | CMD_KEY_CTRL, },
+ { EMUCMD_SAVE_STATE_SLOT_0, SCAN_F10 | CMD_KEY_SHIFT, },
+ { EMUCMD_SAVE_STATE_SLOT_1, SCAN_F1 | CMD_KEY_SHIFT, },
+ { EMUCMD_SAVE_STATE_SLOT_2, SCAN_F2 | CMD_KEY_SHIFT, },
+ { EMUCMD_SAVE_STATE_SLOT_3, SCAN_F3 | CMD_KEY_SHIFT, },
+ { EMUCMD_SAVE_STATE_SLOT_4, SCAN_F4 | CMD_KEY_SHIFT, },
+ { EMUCMD_SAVE_STATE_SLOT_5, SCAN_F5 | CMD_KEY_SHIFT, },
+ { EMUCMD_SAVE_STATE_SLOT_6, SCAN_F6 | CMD_KEY_SHIFT, },
+ { EMUCMD_SAVE_STATE_SLOT_7, SCAN_F7 | CMD_KEY_SHIFT, },
+ { EMUCMD_SAVE_STATE_SLOT_8, SCAN_F8 | CMD_KEY_SHIFT, },
+ { EMUCMD_SAVE_STATE_SLOT_9, SCAN_F9 | CMD_KEY_SHIFT, },
+ { EMUCMD_LOAD_STATE_SLOT_0, SCAN_F10, },
+ { EMUCMD_LOAD_STATE_SLOT_1, SCAN_F1, },
+ { EMUCMD_LOAD_STATE_SLOT_2, SCAN_F2, },
+ { EMUCMD_LOAD_STATE_SLOT_3, SCAN_F3, },
+ { EMUCMD_LOAD_STATE_SLOT_4, SCAN_F4, },
+ { EMUCMD_LOAD_STATE_SLOT_5, SCAN_F5, },
+ { EMUCMD_LOAD_STATE_SLOT_6, SCAN_F6, },
+ { EMUCMD_LOAD_STATE_SLOT_7, SCAN_F7, },
+ { EMUCMD_LOAD_STATE_SLOT_8, SCAN_F8, },
+ { EMUCMD_LOAD_STATE_SLOT_9, SCAN_F9, },
+/* { EMUCMD_MOVIE_SLOT_0, SCAN_0 | CMD_KEY_ALT, },
+ { EMUCMD_MOVIE_SLOT_1, SCAN_1 | CMD_KEY_ALT, },
+ { EMUCMD_MOVIE_SLOT_2, SCAN_2 | CMD_KEY_ALT, },
+ { EMUCMD_MOVIE_SLOT_3, SCAN_3 | CMD_KEY_ALT, },
+ { EMUCMD_MOVIE_SLOT_4, SCAN_4 | CMD_KEY_ALT, },
+ { EMUCMD_MOVIE_SLOT_5, SCAN_5 | CMD_KEY_ALT, },
+ { EMUCMD_MOVIE_SLOT_6, SCAN_6 | CMD_KEY_ALT, },
+ { EMUCMD_MOVIE_SLOT_7, SCAN_7 | CMD_KEY_ALT, },
+ { EMUCMD_MOVIE_SLOT_8, SCAN_8 | CMD_KEY_ALT, },
+ { EMUCMD_MOVIE_SLOT_9, SCAN_9 | CMD_KEY_ALT, },
+ { EMUCMD_MOVIE_RECORD, SCAN_F5 | CMD_KEY_ALT, },
+ { EMUCMD_MOVIE_REPLAY, SCAN_F7 | CMD_KEY_ALT, },*/
+ { EMUCMD_MOVIE_FRAME_DISPLAY_TOGGLE, SCAN_PERIOD, },
+ { EMUCMD_FDS_EJECT_INSERT, SCAN_F8 | CMD_KEY_CTRL, },
+ { EMUCMD_FDS_SIDE_SELECT, SCAN_F6 | CMD_KEY_CTRL, },
+ { EMUCMD_MOVIE_INPUT_DISPLAY_TOGGLE, SCAN_COMMA, },
+ { EMUCMD_MOVIE_READONLY_TOGGLE, SCAN_8 | CMD_KEY_SHIFT, },
+ { EMUCMD_MISC_REWIND, SCAN_R, },
+};
+
+#define NUM_DEFAULT_MAPPINGS (sizeof(DefaultCommandMapping)/sizeof(DefaultCommandMapping[0]))
+
+void ApplyDefaultCommandMapping(void)
+{
+ int i;
+
+ memset(FCEUD_CommandMapping, 0, sizeof(FCEUD_CommandMapping));
+ for(i=0; i<NUM_DEFAULT_MAPPINGS; ++i)
+ FCEUD_CommandMapping[DefaultCommandMapping[i].cmd] = DefaultCommandMapping[i].key;
+}
+
+int FCEUD_TestCommandState(int c)
+{
+ int cmd=FCEUD_CommandMapping[c];
+ int cmdmask=cmd&CMD_KEY_MASK;
+
+ // allow certain commands be affected by key repeat
+ if(c == EMUCMD_FRAME_ADVANCE/*
+ || c == EMUCMD_SOUND_VOLUME_UP
+ || c == EMUCMD_SOUND_VOLUME_DOWN
+ || c == EMUCMD_SPEED_SLOWER
+ || c == EMUCMD_SPEED_FASTER*/)
+ {
+ keys=GetKeyboard();
+/* if((cmdmask & CMD_KEY_LALT) == CMD_KEY_LALT
+ || (cmdmask & CMD_KEY_RALT) == CMD_KEY_RALT
+ || (cmdmask & CMD_KEY_LALT) == CMD_KEY_LALT
+ || (cmdmask & CMD_KEY_LCTRL) == CMD_KEY_LCTRL
+ || (cmdmask & CMD_KEY_RCTRL) == CMD_KEY_RCTRL
+ || (cmdmask & CMD_KEY_LSHIFT) == CMD_KEY_LSHIFT
+ || (cmdmask & CMD_KEY_RSHIFT) == CMD_KEY_RSHIFT)*/
+ keys_nr=GetKeyboard();
+// else
+// keys_nr=GetKeyboard_nr();
+ }
+ else if(c != EMUCMD_SPEED_TURBO) // TODO: this should be made more general by detecting if the command has an "off" function, but right now Turbo is the only command that has it
+ {
+ keys=GetKeyboard_jd();
+ keys_nr=GetKeyboard_nr();
+ }
+ else
+ {
+ keys=GetKeyboard_nr();
+ keys_nr=GetKeyboard_nr();
+ }
+
+ /* test CTRL, SHIFT, ALT */
+ if (cmd & CMD_KEY_ALT)
+ {
+ int ctlstate = (cmd & CMD_KEY_LALT) ? keys_nr[SCAN_LEFTALT] : 0;
+ ctlstate |= (cmd & CMD_KEY_RALT) ? keys_nr[SCAN_RIGHTALT] : 0;
+ if (!ctlstate)
+ return 0;
+ }
+ else if((cmdmask != SCAN_LEFTALT && keys_nr[SCAN_LEFTALT]) || (cmdmask != SCAN_RIGHTALT && keys_nr[SCAN_RIGHTALT]))
+ return 0;
+
+ if (cmd & CMD_KEY_CTRL)
+ {
+ int ctlstate = (cmd & CMD_KEY_LCTRL) ? keys_nr[SCAN_LEFTCONTROL] : 0;
+ ctlstate |= (cmd & CMD_KEY_RCTRL) ? keys_nr[SCAN_RIGHTCONTROL] : 0;
+ if (!ctlstate)
+ return 0;
+ }
+ else if((cmdmask != SCAN_LEFTCONTROL && keys_nr[SCAN_LEFTCONTROL]) || (cmdmask != SCAN_RIGHTCONTROL && keys_nr[SCAN_RIGHTCONTROL]))
+ return 0;
+
+ if (cmd & CMD_KEY_SHIFT)
+ {
+ int ctlstate = (cmd & CMD_KEY_LSHIFT) ? keys_nr[SCAN_LEFTSHIFT] : 0;
+ ctlstate |= (cmd & CMD_KEY_RSHIFT) ? keys_nr[SCAN_RIGHTSHIFT] : 0;
+ if (!ctlstate)
+ return 0;
+ }
+ else if((cmdmask != SCAN_LEFTSHIFT && keys_nr[SCAN_LEFTSHIFT]) || (cmdmask != SCAN_RIGHTSHIFT && keys_nr[SCAN_RIGHTSHIFT]))
+ return 0;
+
+ return keys[cmdmask] ? 1 : 0;
+}
+
+static const char* ScanNames[256]=
+{
+ /* 0x00-0x0f */ 0, "Escape", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "Minus", "Equals", "Backspace", "Tab",
+ /* 0x10-0x1f */ "Q", "W", "E", "R", "T", "Y", "U", "I", "O", "P", "[", "]", "Enter", "Left Ctrl", "A", "S",
+ /* 0x20-0x2f */ "D", "F", "G", "H", "J", "K", "L", "Semicolon", "Apostrophe", "Grave", "Left Shift", "Backslash", "Z", "X", "C", "V",
+ /* 0x30-0x3f */ "B", "N", "M", "Comma", "Period", "Slash", "Right Shift", "Numpad *", "Left Alt", "Space", "Caps Lock", "F1", "F2", "F3", "F4", "F5",
+ /* 0x40-0x4f */ "F6", "F7", "F8", "F9", "F10", "NumLock", "ScrollLock", "Numpad 7", "Numpad 8", "Numpad 9", "Numpad Minus", "Numpad 4", "Numpad 5", "Numpad 6", "Numpad Plus", "Numpad 1",
+ /* 0x50-0x5f */ "Numpad 2", "Numpad 3", "Numpad 0", "Numpad Period", 0, 0, "Backslash", "F11", "F12", 0, 0, 0, 0, 0, 0, 0,
+ /* 0x60-0x6f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x70-0x7f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x80-0x8f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x90-0x9f */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, "Numpad Enter", "Right Ctrl", 0, 0,
+ /* 0xa0-0xaf */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xb0-0xbf */ 0, 0, 0, 0, 0, "Numpad Divide", 0, "PrintScrn", "Right Alt", 0, 0, 0, 0, 0, 0, 0,
+ /* 0xc0-0xcf */ 0, 0, 0, 0, 0, "Pause", 0, "Home", "Up Arrow", "PgUp", 0, "Left Arrow", 0, "Right Arrow", 0, "End",
+ /* 0xd0-0xdf */ "Down Arrow", "PgDn", "Ins", "Del", 0, 0, 0, 0, 0, 0, 0, "Left Win", "Right Win", "AppMenu", 0, 0,
+ /* 0xe0-0xef */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xf0-0xff */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static const char* GetKeyName(int code)
+{
+ static char name[16];
+
+ code &= 0xff;
+ if(ScanNames[code])
+ return ScanNames[code];
+
+ sprintf(name, "Key 0x%.2x", code);
+ return name;
+}
+
+static char* GetKeyComboName(int c)
+{
+ static char text[80];
+
+ text[0]='\0';
+ if(!c)
+ return text;
+
+ if ((c & CMD_KEY_CTRL) == CMD_KEY_CTRL) strcat(text, "Ctrl + ");
+ else if ((c & CMD_KEY_CTRL) == CMD_KEY_LCTRL) strcat(text, "Left Ctrl + ");
+ else if ((c & CMD_KEY_CTRL) == CMD_KEY_RCTRL) strcat(text, "Right Ctrl + ");
+ if ((c & CMD_KEY_ALT) == CMD_KEY_ALT) strcat(text, "Alt + ");
+ else if ((c & CMD_KEY_ALT) == CMD_KEY_LALT) strcat(text, "Left Alt + ");
+ else if ((c & CMD_KEY_ALT) == CMD_KEY_RALT) strcat(text, "Right Alt + ");
+ if ((c & CMD_KEY_SHIFT) == CMD_KEY_SHIFT) strcat(text, "Shift + ");
+ else if ((c & CMD_KEY_SHIFT) == CMD_KEY_LSHIFT) strcat(text, "Left Shift + ");
+ else if ((c & CMD_KEY_SHIFT) == CMD_KEY_RSHIFT) strcat(text, "Right Shift + ");
+
+ strcat(text, GetKeyName(c & CMD_KEY_MASK));
+
+ return text;
+}
+
+struct INPUTDLGTHREADARGS
+{
+ HANDLE hThreadExit;
+ HWND hwndDlg;
+};
+
+static DWORD WINAPI NewInputDialogThread(LPVOID lpvArg)
+{
+ struct INPUTDLGTHREADARGS* args = (struct INPUTDLGTHREADARGS*)lpvArg;
+
+ while (args->hThreadExit)
+ {
+ if (WaitForSingleObject(args->hThreadExit, 20) == WAIT_OBJECT_0)
+ break;
+
+ // Poke our owner dialog periodically.
+ PostMessage(args->hwndDlg, WM_USER, 0, 0);
+ }
+
+ return 0;
+}
+
+static int GetKeyPressed()
+{
+ int key=0;
+ int i;
+
+ keys_nr=GetKeyboard_nr();
+
+ for(i=0; i<256 && !key; ++i)
+ {
+ if(_keyonly(i))
+ key=i;
+ }
+ return key;
+}
+
+static int NothingPressed()
+{
+ int i;
+
+ keys_nr=GetKeyboard_nr();
+
+ for(i=0; i<256; ++i)
+ {
+ if(keys_nr[i])
+ return 0;
+ }
+ return 1;
+}
+
+static int GetKeyMeta(int key)
+{
+ int meta = key & (~CMD_KEY_MASK);
+ switch(key & CMD_KEY_MASK)
+ {
+ case SCAN_LEFTCONTROL:
+ case SCAN_RIGHTCONTROL: return CMD_KEY_CTRL | meta;
+ case SCAN_LEFTALT:
+ case SCAN_RIGHTALT: return CMD_KEY_ALT | meta;
+ case SCAN_LEFTSHIFT:
+ case SCAN_RIGHTSHIFT: return CMD_KEY_SHIFT | meta;
+ default:
+ break;
+ }
+
+ return meta;
+}
+
+static void ClearExtraMeta(int* key)
+{
+ switch((*key)&0xff)
+ {
+ case SCAN_LEFTCONTROL:
+ case SCAN_RIGHTCONTROL: *key &= ~(CMD_KEY_CTRL); break;
+ case SCAN_LEFTALT:
+ case SCAN_RIGHTALT: *key &= ~(CMD_KEY_ALT); break;
+ case SCAN_LEFTSHIFT:
+ case SCAN_RIGHTSHIFT: *key &= ~(CMD_KEY_SHIFT); break;
+ default:
+ break;
+ }
+}
+
+static BOOL CALLBACK ChangeInputDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ static HANDLE hThread = NULL;
+ static DWORD dwThreadId = 0;
+ static struct INPUTDLGTHREADARGS threadargs;
+ static int key=0;
+
+ switch (uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ // Start the message thread.
+ threadargs.hThreadExit = CreateEvent(NULL, TRUE, FALSE, NULL);
+ threadargs.hwndDlg = hwndDlg;
+ hThread = CreateThread(NULL, 0, NewInputDialogThread, (LPVOID)&threadargs, 0, &dwThreadId);
+ key=0;
+ memset(keyonce, 0, sizeof(keyonce));
+ KeyboardSetBackgroundAccess(1);
+ SetFocus(GetDlgItem(hwndDlg, 100));
+ }
+ return FALSE;
+
+ case WM_COMMAND:
+ if(LOWORD(wParam) == 202 && HIWORD(wParam) == BN_CLICKED)
+ {
+ key=0;
+ PostMessage(hwndDlg, WM_USER+1, 0, 0); // Send quit message.
+ }
+ else if(LOWORD(wParam) == 200 && HIWORD(wParam) == BN_CLICKED)
+ {
+ key=-1;
+ PostMessage(hwndDlg, WM_USER+1, 0, 0); // Send quit message.
+ }
+
+ break;
+
+ case WM_USER:
+ {
+ // Our thread sent us a timer signal.
+ int newkey;
+ int meta=GetKeyMeta(key);
+
+ KeyboardUpdateState();
+
+ if((newkey=GetKeyPressed()) != 0)
+ {
+ key = newkey | meta;
+ ClearExtraMeta(&key);
+ SetDlgItemText(hwndDlg, 100, GetKeyComboName(key));
+ }
+ else if(NothingPressed() && key)
+ PostMessage(hwndDlg, WM_USER+1, 0, 0); // Send quit message.
+ }
+ break;
+
+ case WM_USER+1:
+ {
+ // Done with keyboard.
+ KeyboardSetBackgroundAccess(0);
+
+ // Kill the thread.
+ SetEvent(threadargs.hThreadExit);
+ WaitForSingleObject(hThread, INFINITE);
+ CloseHandle(hThread);
+ CloseHandle(threadargs.hThreadExit);
+
+ // End the dialog.
+ EndDialog(hwndDlg, key);
+ return TRUE;
+ }
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+static int* ConflictTable=0;
+
+static int ShouldDisplayMapping(int mapn, int filter)
+{
+ switch(filter)
+ {
+ case 0: return 1; /* No filter */
+ case 1 ... EMUCMDTYPE_MAX: return (FCEUI_CommandTable[mapn].type == filter-1); /* Filter by type */
+ case EMUCMDTYPE_MAX+1: return FCEUD_CommandMapping[mapn]; /* Assigned */
+ case EMUCMDTYPE_MAX+2: return !(FCEUD_CommandMapping[mapn]); /* Unassigned */
+ case EMUCMDTYPE_MAX+3: return ConflictTable[mapn]; /* Conflicts */
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static void PopulateMappingDisplay(HWND hwndDlg)
+{
+ LVITEM lvi;
+ int i;
+ int idx;
+ HWND hwndListView = GetDlgItem(hwndDlg, 1003);
+ int num=SendMessage(hwndListView, LVM_GETITEMCOUNT, 0, 0);
+ int filter = (int)SendDlgItemMessage(hwndDlg, 300, CB_GETCURSEL, 0, 0);
+
+ // Delete everything in the current display.
+ for(i=num; i>0; --i)
+ SendMessage(hwndListView, LVM_DELETEITEM, (WPARAM)i-1, 0);
+
+ // Get the filter type.
+ ConflictTable=0;
+ if (filter == EMUCMDTYPE_MAX+3)
+ {
+ // Set up the conflict table.
+ ConflictTable=(int*)malloc(sizeof(int)*EMUCMD_MAX);
+ memset(ConflictTable, 0, sizeof(int)*EMUCMD_MAX);
+ for(i=0; i<EMUCMD_MAX-1; ++i)
+ {
+ int j;
+ for(j=i+1; j<EMUCMD_MAX; ++j)
+ {
+ if(FCEUD_CommandMapping[i] &&
+ FCEUD_CommandMapping[i] == FCEUD_CommandMapping[j])
+ {
+ ConflictTable[i]=1;
+ ConflictTable[j]=1;
+ }
+ }
+ }
+ }
+
+ // Populate display.
+ for(i=0, idx=0; i<EMUCMD_MAX; ++i)
+ {
+ if(ShouldDisplayMapping(i, filter))
+ {
+ memset(&lvi, 0, sizeof(lvi));
+ lvi.mask = LVIF_TEXT | LVIF_PARAM;
+ lvi.iItem = idx;
+ lvi.iSubItem = 0;
+ lvi.pszText = (char*)FCEUI_CommandTypeNames[FCEUI_CommandTable[i].type];
+ lvi.lParam = (LPARAM)i;
+
+ SendMessage(hwndListView, LVM_INSERTITEM, (WPARAM)0, (LPARAM)&lvi);
+
+ memset(&lvi, 0, sizeof(lvi));
+ lvi.mask = LVIF_TEXT;
+ lvi.iItem = idx;
+ lvi.iSubItem = 1;
+ lvi.pszText = FCEUI_CommandTable[i].name;
+
+ SendMessage(hwndListView, LVM_SETITEM, (WPARAM)0, (LPARAM)&lvi);
+
+ memset(&lvi, 0, sizeof(lvi));
+ lvi.mask = LVIF_TEXT;
+ lvi.iItem = idx;
+ lvi.iSubItem = 2;
+ lvi.pszText = GetKeyComboName(FCEUD_CommandMapping[i]);
+
+ SendMessage(hwndListView, LVM_SETITEM, (WPARAM)0, (LPARAM)&lvi);
+
+ idx++;
+ }
+ }
+
+ if(ConflictTable)
+ free(ConflictTable);
+}
+
+static BOOL CALLBACK MapInputDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ HWND hwndListView = GetDlgItem(hwndDlg, 1003);
+ LVCOLUMN lv;
+ LVITEM lvi;
+ int i;
+
+ // Set full row select.
+ SendMessage(hwndListView, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
+
+ // Init ListView columns.
+ memset(&lv, 0, sizeof(lv));
+ lv.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
+ lv.fmt = LVCFMT_LEFT;
+ lv.pszText = "Type";
+ lv.cx = 40;
+
+ SendMessage(hwndListView, LVM_INSERTCOLUMN, (WPARAM)0, (LPARAM)&lv);
+
+ memset(&lv, 0, sizeof(lv));
+ lv.mask = LVCF_FMT | LVCF_TEXT | LVCF_WIDTH;
+ lv.fmt = LVCFMT_LEFT;
+ lv.pszText = "Command";
+ lv.cx = 180;
+
+ SendMessage(hwndListView, LVM_INSERTCOLUMN, (WPARAM)1, (LPARAM)&lv);
+
+ memset(&lv, 0, sizeof(lv));
+ lv.mask = LVCF_FMT | LVCF_TEXT;
+ lv.fmt = LVCFMT_LEFT;
+ lv.pszText = "Input";
+
+ SendMessage(hwndListView, LVM_INSERTCOLUMN, (WPARAM)2, (LPARAM)&lv);
+
+ // Populate the filter combobox.
+ SendDlgItemMessage(hwndDlg, 300, CB_INSERTSTRING, 0, (LPARAM)"None");
+ for(i=0; i<EMUCMDTYPE_MAX; ++i)
+ SendDlgItemMessage(hwndDlg, 300, CB_INSERTSTRING, i+1, (LPARAM)FCEUI_CommandTypeNames[i]);
+ SendDlgItemMessage(hwndDlg, 300, CB_INSERTSTRING, ++i, (LPARAM)"Assigned");
+ SendDlgItemMessage(hwndDlg, 300, CB_INSERTSTRING, ++i, (LPARAM)"Unassigned");
+ SendDlgItemMessage(hwndDlg, 300, CB_INSERTSTRING, ++i, (LPARAM)"Conflicts");
+
+ SendDlgItemMessage(hwndDlg, 300, CB_SETCURSEL, 0, 0); // Default filter is "none".
+
+ // Now populate the mapping display.
+ PopulateMappingDisplay(hwndDlg);
+
+ // Autosize last column.
+ SendMessage(hwndListView, LVM_SETCOLUMNWIDTH, (WPARAM)2, MAKELPARAM(LVSCW_AUTOSIZE_USEHEADER, 0));
+
+ }
+ return FALSE;
+
+ case WM_COMMAND:
+ if(HIWORD(wParam) == CBN_SELCHANGE)
+ {
+ PopulateMappingDisplay(hwndDlg);
+ break;
+ }
+
+ switch(LOWORD(wParam))
+ {
+ case IDOK:
+ EndDialog(hwndDlg, 1);
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+
+ case 200:
+ ApplyDefaultCommandMapping();
+ PopulateMappingDisplay(hwndDlg);
+ return TRUE;
+
+ default:
+ break;
+ }
+ break;
+
+ case WM_NOTIFY:
+ switch(LOWORD(wParam))
+ {
+ case 1003:
+ if (lParam)
+ {
+ HWND hwndListView = GetDlgItem(hwndDlg, 1003);
+ NMHDR* pnm = (NMHDR*)lParam;
+ if (pnm->code == LVN_ITEMACTIVATE)
+ {
+ int nSel = SendMessage(hwndListView, LVM_GETNEXTITEM, (WPARAM)-1, LVNI_SELECTED);
+ if (nSel != -1)
+ {
+ int nCmd;
+ int nRet;
+ LVITEM lvi;
+
+ // Get the corresponding input
+ memset(&lvi, 0, sizeof(lvi));
+ lvi.mask = LVIF_PARAM;
+ lvi.iItem = nSel;
+ lvi.iSubItem = 0;
+ SendMessage(hwndListView, LVM_GETITEM, 0, (LPARAM)&lvi);
+ nCmd = lvi.lParam;
+
+ nRet = DialogBox(fceu_hInstance,"NEWINPUT",hwndListView,ChangeInputDialogProc);
+ if (nRet)
+ {
+ // nRet will be -1 when the user selects "clear".
+ FCEUD_CommandMapping[nCmd] = (nRet<0) ? 0 : nRet;
+
+ memset(&lvi, 0, sizeof(lvi));
+ lvi.mask = LVIF_TEXT;
+ lvi.iItem = nSel;
+ lvi.iSubItem = 2;
+ lvi.pszText = GetKeyComboName(FCEUD_CommandMapping[nCmd]);
+ SendMessage(hwndListView, LVM_SETITEM, (WPARAM)0, (LPARAM)&lvi);
+ }
+ }
+ }
+ return TRUE;
+ }
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}
+
+void MapInput(void)
+{
+ // Make a backup of the current mappings, in case the user changes their mind.
+ int* backupmapping = (int*)malloc(sizeof(FCEUD_CommandMapping));
+ memcpy(backupmapping, FCEUD_CommandMapping, sizeof(FCEUD_CommandMapping));
+
+ if(!DialogBox(fceu_hInstance,"MAPINPUT",hAppWnd,MapInputDialogProc))
+ memcpy(FCEUD_CommandMapping, backupmapping, sizeof(FCEUD_CommandMapping));
+
+ free(backupmapping);
+}
+
+void FCEUD_TurboOn(void)
+{
+ NoWaiting|=1;
+}
+
+void FCEUD_TurboOff(void)
+{
+ NoWaiting&=~1;
+}
+
diff --git a/drivers/win/input.h b/drivers/win/input.h
new file mode 100644
index 00000000..560c4a9b
--- /dev/null
+++ b/drivers/win/input.h
@@ -0,0 +1,53 @@
+void ConfigInput(HWND hParent);
+int InitDInput(void);
+void CreateInputStuff(void);
+void InitInputStuff(void);
+void DestroyInput(void);
+void InputScreenChanged(int fs);
+void SetAutoFireDesynch(int DesynchOn);
+int GetAutoFireDesynch();
+
+extern LPDIRECTINPUT7 lpDI;
+
+extern int InputType[3];
+extern int UsrInputType[3];
+extern int cidisabled;
+#ifndef _aosdfjk02fmasf
+#define _aosdfjk02fmasf
+
+#include "../common/args.h"
+#include "../common/config.h"
+#include "../../input.h"
+
+#define MAXBUTTCONFIG 4
+typedef struct {
+ uint8 ButtType[MAXBUTTCONFIG];
+ uint8 DeviceNum[MAXBUTTCONFIG];
+ uint16 ButtonNum[MAXBUTTCONFIG];
+ uint32 NumC;
+ GUID DeviceInstance[MAXBUTTCONFIG];
+ //uint64 DeviceID[MAXBUTTCONFIG]; /* TODO */
+} ButtConfig;
+
+extern CFGSTRUCT InputConfig[];
+extern ARGPSTRUCT InputArgs[];
+void ParseGIInput(FCEUGI *GI);
+
+#define BUTTC_KEYBOARD 0x00
+#define BUTTC_JOYSTICK 0x01
+#define BUTTC_MOUSE 0x02
+
+#define FCFGD_GAMEPAD 1
+#define FCFGD_POWERPAD 2
+#define FCFGD_HYPERSHOT 3
+#define FCFGD_QUIZKING 4
+
+void InitOtherInput(void);
+void SetEmulationSpeed(int type);
+int FCEUD_TestCommandState(int c);
+void FCEUD_UpdateInput();
+
+extern const char* ScanNames[];
+extern CFGSTRUCT HotkeyConfig[];
+#endif
+
diff --git a/drivers/win/joystick.c b/drivers/win/joystick.c
new file mode 100644
index 00000000..9a6f24da
--- /dev/null
+++ b/drivers/win/joystick.c
@@ -0,0 +1,426 @@
+/* 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 "common.h"
+#include <dinput.h>
+
+#include "input.h"
+#include "joystick.h"
+
+
+#define MAX_JOYSTICKS 32
+static LPDIRECTINPUTDEVICE7 Joysticks[MAX_JOYSTICKS]={0};
+static GUID JoyGUID[MAX_JOYSTICKS];
+
+static int numjoysticks = 0;
+static int HavePolled[MAX_JOYSTICKS];
+
+static DIJOYSTATE2 StatusSave[MAX_JOYSTICKS];
+
+static int FindByGUID(GUID how)
+{
+ int x;
+
+ for(x=0; x<numjoysticks; x++)
+ if(!memcmp(&JoyGUID[x], &how, sizeof(GUID)))
+ return(x);
+
+ return(0xFF);
+}
+
+#define FPOV_CENTER 16
+
+static int POVFix(long pov, int roundpos)
+{
+ long lowpov;
+
+ if(LOWORD(pov) == 65535)
+ return(FPOV_CENTER);
+
+ if(roundpos == -1) /* Special case for button configuration */
+ {
+ pov /= 4500;
+ pov = (pov >> 1) + (pov & 1);
+ pov &= 3;
+ return(pov);
+ }
+
+ lowpov = pov % 9000;
+ if(lowpov < (4500 - 4500 / 2))
+ {
+ pov /= 9000;
+ }
+ else if(lowpov > (4500 + 4500/2))
+ {
+ pov /= 9000;
+ pov = (pov + 1) % 4;
+ }
+ else
+ {
+ if(!roundpos) pov /= 9000;
+ else { pov /= 9000; pov = (pov + 1) % 4; }
+ }
+ return(pov);
+}
+
+
+typedef struct
+{
+ LONG MinX;
+ LONG MaxX;
+ LONG MinY;
+ LONG MaxY;
+ LONG MinZ;
+ LONG MaxZ;
+} POWER_RANGER;
+
+static POWER_RANGER ranges[MAX_JOYSTICKS];
+
+// r=diprg.lMax-diprg.lMin;
+// JoyXMax[w]=diprg.lMax-(r>>2);
+// JoyXMin[w]=diprg.lMin+(r>>2);
+
+static int JoyAutoRestore(HRESULT dival,LPDIRECTINPUTDEVICE7 lpJJoy)
+{
+ switch(dival)
+ {
+ case DIERR_INPUTLOST:
+ case DIERR_NOTACQUIRED:
+ return(IDirectInputDevice7_Acquire(lpJJoy)==DI_OK);
+ }
+ return(0);
+}
+
+/* Called during normal emulator operation, not during button configuration. */
+/* Call before DTestButtonJoy */
+void UpdateJoysticks(void)
+{
+ memset(HavePolled, 0, sizeof(HavePolled));
+}
+
+int DTestButtonJoy(ButtConfig *bc)
+{
+ int x;
+
+ for(x=0;x<bc->NumC;x++)
+ {
+ HRESULT dival;
+ int n = bc->DeviceNum[x];
+
+ if(n == 0xFF)
+ continue;
+
+ if(bc->ButtType[x] != BUTTC_JOYSTICK) continue;
+ if(n >= numjoysticks) continue;
+
+ if(!HavePolled[n])
+ {
+ while((dival = IDirectInputDevice7_Poll(Joysticks[n])) != DI_OK)
+ {
+ if(dival == DI_NOEFFECT) break;
+
+ if(!JoyAutoRestore(dival,Joysticks[n]))
+ {
+ return(0);
+ }
+ }
+
+ IDirectInputDevice7_GetDeviceState(Joysticks[n],sizeof(DIJOYSTATE2),&StatusSave[n]);
+ HavePolled[n] = 1;
+ }
+
+ if(bc->ButtonNum[x]&0x8000) /* Axis "button" */
+ {
+ int sa = bc->ButtonNum[x]&3;
+ long source;
+
+ if(sa == 0) source=((int64)StatusSave[n].lX - ranges[n].MinX) * 262144 /
+ (ranges[n].MaxX - ranges[n].MinX) - 131072;
+ else if(sa == 1) source=((int64)StatusSave[n].lY - ranges[n].MinY) * 262144 /
+ (ranges[n].MaxY - ranges[n].MinY) - 131072;
+ else if(sa == 2) source=((int64)StatusSave[n].lZ - ranges[n].MinZ) * 262144 /
+ (ranges[n].MaxZ - ranges[n].MinZ) - 131072;
+
+ /* Now, source is of the range -131072 to 131071. Good enough. */
+ if(bc->ButtonNum[x] & 0x4000)
+ {
+ if(source <= (0 - 262144/4))
+ return(1);
+ }
+ else
+ {
+ if(source >= (262144/4))
+ return(1);
+ }
+ }
+ else if(bc->ButtonNum[x]&0x2000) /* Hat "button" */
+ {
+ int wpov = StatusSave[n].rgdwPOV[(bc->ButtonNum[x] >> 4) &3];
+ int tpov = bc->ButtonNum[x] & 3;
+
+ if(POVFix(wpov, 0) == tpov || POVFix(wpov, 1) == tpov)
+ return(1);
+ }
+ else /* Normal button */
+ {
+ if(StatusSave[n].rgbButtons[bc->ButtonNum[x] & 127]&0x80)
+ return(1);
+ }
+
+ }
+
+ return(0);
+}
+
+static int canax[MAX_JOYSTICKS][3];
+
+/* Now the fun configuration test begins. */
+void BeginJoyWait(HWND hwnd)
+{
+ int n;
+
+ //StatusSave = malloc(sizeof(DIJOYSTATE2) * numjoysticks);
+ memset(canax, 0, sizeof(canax));
+
+ for(n=0; n<numjoysticks; n++)
+ {
+ IDirectInputDevice7_Unacquire(Joysticks[n]);
+ IDirectInputDevice7_SetCooperativeLevel(Joysticks[n],hwnd,DISCL_FOREGROUND|DISCL_NONEXCLUSIVE);
+ IDirectInputDevice7_Acquire(Joysticks[n]);
+ IDirectInputDevice7_Poll(Joysticks[n]);
+ IDirectInputDevice7_GetDeviceState(Joysticks[n],sizeof(DIJOYSTATE2),&StatusSave[n]);
+ }
+}
+
+int DoJoyWaitTest(GUID *guid, uint8 *devicenum, uint16 *buttonnum)
+{
+ int n;
+ int x;
+
+ for(n=0; n<numjoysticks; n++)
+ {
+ HRESULT dival;
+ DIJOYSTATE2 JoyStatus;
+ int ba;
+
+ while((dival = IDirectInputDevice7_Poll(Joysticks[n])) != DI_OK)
+ {
+ if(dival == DI_NOEFFECT) break;
+ if(!JoyAutoRestore(dival,Joysticks[n])) return(0);
+ }
+ dival = IDirectInputDevice7_GetDeviceState(Joysticks[n],sizeof(DIJOYSTATE2),&JoyStatus);
+
+ for(ba = 0; ba < 128; ba++)
+ if((JoyStatus.rgbButtons[ba]&0x80) && !(StatusSave[n].rgbButtons[ba]&0x80))
+ {
+ *devicenum = n;
+ *buttonnum = ba;
+ *guid = JoyGUID[n];
+ //memcpy(&StatusSave[n], &JoyStatus, sizeof(DIJOYSTATE2));
+ memcpy(StatusSave[n].rgbButtons, JoyStatus.rgbButtons, 128);
+ return(1);
+ }
+
+ memcpy(StatusSave[n].rgbButtons, JoyStatus.rgbButtons, 128);
+
+ // lX, lY, lZ
+ long dax, day, daz;
+ long source,psource;
+
+ dax = ranges[n].MaxX - ranges[n].MinX;
+ day = ranges[n].MaxY - ranges[n].MinY;
+ daz = ranges[n].MaxZ - ranges[n].MinZ;
+
+ if(dax)
+ {
+ source=((int64)JoyStatus.lX - ranges[n].MinX) * 262144 / dax - 131072;
+ psource=((int64)StatusSave[n].lX - ranges[n].MinX) * 262144 / dax - 131072;
+
+ if(abs(source) >= 65536 && canax[n][0])
+ {
+ *guid = JoyGUID[n];
+ *devicenum = n;
+ *buttonnum = 0x8000 | (0) | ((source < 0) ? 0x4000 : 0);
+ memcpy(&StatusSave[n], &JoyStatus, sizeof(DIJOYSTATE2));
+ canax[n][0] = 0;
+ return(1);
+ } else if(abs(source) <= 32768) canax[n][0] = 1;
+ }
+
+ if(day)
+ {
+ source=((int64)JoyStatus.lY - ranges[n].MinY) * 262144 / day - 131072;
+ psource=((int64)StatusSave[n].lY - ranges[n].MinY) * 262144 / day - 131072;
+
+ if(abs(source) >= 65536 && canax[n][1])
+ {
+ *guid = JoyGUID[n];
+ *devicenum = n;
+ *buttonnum = 0x8000 | (1) | ((source < 0) ? 0x4000 : 0);
+ memcpy(&StatusSave[n], &JoyStatus, sizeof(DIJOYSTATE2));
+ canax[n][1] = 0;
+ return(1);
+ } else if(abs(source) <= 32768) canax[n][1] = 1;
+ }
+
+ if(daz)
+ {
+
+
+ }
+
+ for(x=0; x<4; x++)
+ {
+ if(POVFix(JoyStatus.rgdwPOV[x],-1) != FPOV_CENTER && POVFix(StatusSave[n].rgdwPOV[x],-1) == FPOV_CENTER)
+ {
+ *guid = JoyGUID[n];
+ *devicenum = n;
+ *buttonnum = 0x2000 | (x<<4) | POVFix(JoyStatus.rgdwPOV[x], -1);
+ memcpy(&StatusSave[n], &JoyStatus, sizeof(DIJOYSTATE2));
+ return(1);
+ }
+ }
+ memcpy(&StatusSave[n], &JoyStatus, sizeof(DIJOYSTATE2));
+ }
+
+ return(0);
+}
+
+void EndJoyWait(HWND hwnd)
+{
+ int n;
+
+ for(n=0; n<numjoysticks; n++)
+ {
+ IDirectInputDevice7_Unacquire(Joysticks[n]);
+ IDirectInputDevice7_SetCooperativeLevel(Joysticks[n],hwnd,DISCL_FOREGROUND|DISCL_NONEXCLUSIVE);
+ }
+}
+
+int KillJoysticks (void)
+{
+ int x;
+
+ for(x=0; x<numjoysticks; x++)
+ {
+ IDirectInputDevice7_Unacquire(Joysticks[x]);
+ IDirectInputDevice7_Release(Joysticks[x]);
+ Joysticks[x] = NULL;
+ }
+
+ numjoysticks = 0;
+
+ return(1);
+}
+
+void JoyClearBC(ButtConfig *bc)
+{
+ int x;
+ for(x=0; x<bc->NumC; x++)
+ if(bc->ButtType[x] == BUTTC_JOYSTICK)
+ bc->DeviceNum[x] = FindByGUID(bc->DeviceInstance[x]);
+}
+
+static int GetARange(LPDIRECTINPUTDEVICE7 dev, LONG which, LONG *min, LONG *max)
+{
+ HRESULT dival;
+ DIPROPRANGE diprg;
+ int r;
+
+ memset(&diprg,0,sizeof(DIPROPRANGE));
+ diprg.diph.dwSize=sizeof(DIPROPRANGE);
+ diprg.diph.dwHeaderSize=sizeof(DIPROPHEADER);
+ diprg.diph.dwHow=DIPH_BYOFFSET;
+ diprg.diph.dwObj=which;
+ dival=IDirectInputDevice7_GetProperty(dev,DIPROP_RANGE,&diprg.diph);
+ if(dival!=DI_OK)
+ {
+ *min = *max = 0;
+ return(1);
+ }
+ *min = diprg.lMin;
+ *max = diprg.lMax;
+ return(1);
+}
+
+static BOOL CALLBACK JoystickFound(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef)
+{
+ HRESULT dival;
+ int n = numjoysticks;
+
+ if(DI_OK != IDirectInput7_CreateDeviceEx(lpDI,&lpddi->guidInstance,&IID_IDirectInputDevice7,(LPVOID *)&Joysticks[n],0))
+ {
+ FCEU_printf("Device creation of a joystick failed during init.\n");
+ return(DIENUM_CONTINUE);
+ }
+
+ if(DI_OK != IDirectInputDevice7_SetCooperativeLevel(Joysticks[n],*(HWND *)pvRef, DISCL_FOREGROUND|DISCL_NONEXCLUSIVE))
+ {
+ FCEU_printf("Cooperative level set of a joystick failed during init.\n");
+ IDirectInputDevice7_Release(Joysticks[n]);
+ return(DIENUM_CONTINUE);
+ }
+
+ if(DI_OK != IDirectInputDevice7_SetDataFormat(Joysticks[n], &c_dfDIJoystick2))
+ {
+ FCEU_printf("Data format set of a joystick failed during init.\n");
+ IDirectInputDevice7_Release(Joysticks[n]);
+ return(DIENUM_CONTINUE);
+ }
+
+ GetARange(Joysticks[n], DIJOFS_X, &ranges[n].MinX, &ranges[n].MaxX);
+ GetARange(Joysticks[n], DIJOFS_Y, &ranges[n].MinY, &ranges[n].MaxY);
+ GetARange(Joysticks[n], DIJOFS_Z, &ranges[n].MinZ, &ranges[n].MaxZ);
+
+ JoyGUID[numjoysticks] = lpddi->guidInstance;
+
+ if(DI_OK != IDirectInputDevice7_Acquire(Joysticks[n]))
+ {
+ //FCEU_printf("Acquire of a joystick failed during init.\n");
+ }
+
+ numjoysticks++;
+
+ if(numjoysticks > MAX_JOYSTICKS) return(0);
+
+ return(DIENUM_CONTINUE);
+}
+
+int InitJoysticks(HWND hwnd)
+{
+ IDirectInput7_EnumDevices(lpDI, DIDEVTYPE_JOYSTICK, JoystickFound, (LPVOID *)&hwnd, DIEDFL_ATTACHEDONLY);
+ return(1);
+}
+
+void SetJoystickBackgroundAccess(int background)
+{
+ int n;
+ for(n=0; n<numjoysticks; n++)
+ {
+ IDirectInputDevice7_Unacquire(Joysticks[n]);
+ if(background)
+ IDirectInputDevice7_SetCooperativeLevel(Joysticks[n],hAppWnd,DISCL_BACKGROUND|DISCL_NONEXCLUSIVE);
+ else
+ IDirectInputDevice7_SetCooperativeLevel(Joysticks[n],hAppWnd,DISCL_FOREGROUND|DISCL_NONEXCLUSIVE);
+ IDirectInputDevice7_Acquire(Joysticks[n]);
+ }
+}
+
+
diff --git a/drivers/win/joystick.h b/drivers/win/joystick.h
new file mode 100644
index 00000000..3b2735a3
--- /dev/null
+++ b/drivers/win/joystick.h
@@ -0,0 +1,11 @@
+int InitJoysticks(HWND wnd);
+int KillJoysticks(void);
+
+void BeginJoyWait(HWND hwnd);
+int DoJoyWaitTest(GUID *guid, uint8 *devicenum, uint16 *buttonnum);
+void EndJoyWait(HWND hwnd);
+
+void JoyClearBC(ButtConfig *bc);
+
+void UpdateJoysticks(void);
+int DTestButtonJoy(ButtConfig *bc);
diff --git a/drivers/win/keyboard.c b/drivers/win/keyboard.c
new file mode 100644
index 00000000..c6986f61
--- /dev/null
+++ b/drivers/win/keyboard.c
@@ -0,0 +1,187 @@
+/* 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 "common.h"
+#include <dinput.h>
+
+#include "input.h"
+#include "keyboard.h"
+
+HRESULT ddrval;
+
+static LPDIRECTINPUTDEVICE7 lpdid=0;
+
+void KeyboardClose(void)
+{
+ if(lpdid) IDirectInputDevice7_Unacquire(lpdid);
+ lpdid=0;
+}
+
+static unsigned char keys[256] = {0,}; // with repeat
+static unsigned char keys_nr[256] = {0,}; // non-repeating
+static unsigned char keys_jd[256] = {0,}; // just-down
+static unsigned char keys_jd_lock[256] = {0,}; // just-down released lock
+int autoHoldKey = 0, autoHoldClearKey = 0;
+void KeyboardUpdateState(void)
+{
+ unsigned char tk[256];
+
+ ddrval=IDirectInputDevice7_GetDeviceState(lpdid,256,tk);
+
+ // HACK because DirectInput is totally wacky about recognizing the PAUSE/BREAK key
+ if(GetAsyncKeyState(VK_PAUSE)) // normally this should have & 0x8000, but apparently this key is too special for that to work
+ tk[0xC5] = 0x80;
+
+ switch(ddrval)
+ {
+ case DI_OK: //memcpy(keys,tk,256);break;
+ {
+ extern int soundoptions;
+ #define SO_OLDUP 32
+
+ extern int soundo;
+ extern int32 fps_scale;
+ int notAlternateThrottle = !(soundoptions&SO_OLDUP) && soundo && ((NoWaiting&1)?(256*16):fps_scale) >= 64;
+ #define KEY_REPEAT_INITIAL_DELAY ((!notAlternateThrottle) ? (16) : (64)) // must be >= 0 and <= 255
+ #define KEY_REPEAT_REPEATING_DELAY (6) // must be >= 1 and <= 255
+ #define KEY_JUST_DOWN_DURATION (4) // must be >= 1 and <= 255
+
+ int i;
+ for(i = 0 ; i < 256 ; i++)
+ if(tk[i])
+ if(keys_nr[i] < 255)
+ keys_nr[i]++; // activate key, and count up for repeat
+ else
+ keys_nr[i] = 255 - KEY_REPEAT_REPEATING_DELAY; // oscillate for repeat
+ else
+ keys_nr[i] = 0; // deactivate key
+
+ memcpy(keys,keys_nr,256);
+
+ // key-down detection
+ for(i = 0 ; i < 256 ; i++)
+ if(!keys_nr[i])
+ {
+ keys_jd[i] = 0;
+ keys_jd_lock[i] = 0;
+ }
+ else if(keys_jd_lock[i])
+ {}
+ else if(keys_jd[i]
+ /*&& (i != 0x2A && i != 0x36 && i != 0x1D && i != 0x38)*/)
+ {
+ if(++keys_jd[i] > KEY_JUST_DOWN_DURATION)
+ {
+ keys_jd[i] = 0;
+ keys_jd_lock[i] = 1;
+ }
+ }
+ else
+ keys_jd[i] = 1;
+
+ // key repeat
+ for(i = 0 ; i < 256 ; i++)
+ if(keys[i] >= KEY_REPEAT_INITIAL_DELAY && !(keys[i]%KEY_REPEAT_REPEATING_DELAY))
+ keys[i] = 0;
+ }
+ break;
+
+
+ case DIERR_INPUTLOST:
+ case DIERR_NOTACQUIRED:
+ memset(keys,0,256);
+ IDirectInputDevice7_Acquire(lpdid);
+ break;
+ }
+
+ extern uint8 autoHoldOn, autoHoldReset;
+ autoHoldOn = autoHoldKey && keys[autoHoldKey] != 0;
+ autoHoldReset = autoHoldClearKey && keys[autoHoldClearKey] != 0;
+}
+
+unsigned char *GetKeyboard(void)
+{
+ return(keys);
+}
+unsigned char *GetKeyboard_nr(void)
+{
+ return(keys_nr);
+}
+unsigned char *GetKeyboard_jd(void)
+{
+ return(keys_jd);
+}
+
+int KeyboardInitialize(void)
+{
+ if(lpdid)
+ return(1);
+
+ ddrval=IDirectInput7_CreateDeviceEx(lpDI, &GUID_SysKeyboard,&IID_IDirectInputDevice7, (LPVOID *)&lpdid,0);
+ if(ddrval != DI_OK)
+ {
+ FCEUD_PrintError("DirectInput: Error creating keyboard device.");
+ return 0;
+ }
+
+ ddrval=IDirectInputDevice7_SetCooperativeLevel(lpdid, hAppWnd,DISCL_FOREGROUND|DISCL_NONEXCLUSIVE);
+ if(ddrval != DI_OK)
+ {
+ FCEUD_PrintError("DirectInput: Error setting keyboard cooperative level.");
+ return 0;
+ }
+
+ ddrval=IDirectInputDevice7_SetDataFormat(lpdid,&c_dfDIKeyboard);
+ if(ddrval != DI_OK)
+ {
+ FCEUD_PrintError("DirectInput: Error setting keyboard data format.");
+ return 0;
+ }
+
+ ddrval=IDirectInputDevice7_Acquire(lpdid);
+ /* Not really a fatal error. */
+ //if(ddrval != DI_OK)
+ //{
+ // FCEUD_PrintError("DirectInput: Error acquiring keyboard.");
+ // return 0;
+ //}
+ return 1;
+}
+
+int KeyboardSetBackgroundAccess(int on)
+{
+ if(!lpdid)
+ return(0);
+
+ ddrval=IDirectInputDevice7_Unacquire(lpdid);
+
+ if(on)
+ ddrval=IDirectInputDevice7_SetCooperativeLevel(lpdid, hAppWnd,DISCL_BACKGROUND|DISCL_NONEXCLUSIVE);
+ else
+ ddrval=IDirectInputDevice7_SetCooperativeLevel(lpdid, hAppWnd,DISCL_FOREGROUND|DISCL_NONEXCLUSIVE);
+ if(ddrval != DI_OK)
+ {
+ FCEUD_PrintError("DirectInput: Error setting keyboard cooperative level.");
+ return 0;
+ }
+
+ ddrval=IDirectInputDevice7_Acquire(lpdid);
+ return 1;
+}
diff --git a/drivers/win/keyboard.h b/drivers/win/keyboard.h
new file mode 100644
index 00000000..1db8d556
--- /dev/null
+++ b/drivers/win/keyboard.h
@@ -0,0 +1,7 @@
+void KeyboardClose(void);
+int KeyboardInitialize(void);
+void KeyboardUpdate(void);
+unsigned char *GetKeyboard(void);
+unsigned char *GetKeyboard_nr(void);
+unsigned char *GetKeyboard_jd(void);
+int KeyboardSetBackgroundAccess(int on);
diff --git a/drivers/win/keyscan.h b/drivers/win/keyscan.h
new file mode 100644
index 00000000..dade4c19
--- /dev/null
+++ b/drivers/win/keyscan.h
@@ -0,0 +1,128 @@
+/* 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
+ */
+
+#define SCAN_GRAVE 0x29
+#define SCAN_1 0x02
+#define SCAN_2 0x03
+#define SCAN_3 0x04
+#define SCAN_4 0x05
+#define SCAN_5 0x06
+#define SCAN_6 0x07
+#define SCAN_7 0x08
+#define SCAN_8 0x09
+#define SCAN_9 0x0A
+#define SCAN_0 0x0B
+#define SCAN_MINUS 0x0C
+#define SCAN_EQUAL 0x0D
+#define SCAN_BACKSLASH 0x2B
+#define SCAN_BACKSPACE 0x0E
+#define SCAN_TAB 0x0F
+#define SCAN_Q 0x10
+#define SCAN_W 0x11
+#define SCAN_E 0x12
+#define SCAN_R 0x13
+#define SCAN_T 0x14
+#define SCAN_Y 0x15
+#define SCAN_U 0x16
+#define SCAN_I 0x17
+#define SCAN_O 0x18
+#define SCAN_P 0x19
+#define SCAN_BRACKET_LEFT 0x1A
+#define SCAN_BRACKET_RIGHT 0x1B
+#define SCAN_LOWBACKSLASH 0x2B
+#define SCAN_CAPSLOCK 0x3A
+#define SCAN_A 0x1E
+#define SCAN_S 0x1F
+#define SCAN_D 0x20
+#define SCAN_F 0x21
+#define SCAN_G 0x22
+#define SCAN_H 0x23
+#define SCAN_J 0x24
+#define SCAN_K 0x25
+#define SCAN_L 0x26
+#define SCAN_SEMICOLON 0x27
+#define SCAN_APOSTROPHE 0x28
+#define SCAN_ENTER 0x1C
+#define SCAN_LEFTSHIFT 0x2A
+#define SCAN_Z 0x2C
+#define SCAN_X 0x2D
+#define SCAN_C 0x2E
+#define SCAN_V 0x2F
+#define SCAN_B 0x30
+#define SCAN_N 0x31
+#define SCAN_M 0x32
+#define SCAN_COMMA 0x33
+#define SCAN_PERIOD 0x34
+#define SCAN_SLASH 0x35
+#define SCAN_RIGHTSHIFT 0x36
+#define SCAN_LEFTCONTROL 0x1D
+#define SCAN_LEFTALT 0x38
+#define SCAN_SPACE 0x39
+
+#define SCAN_RIGHTALT (0x38|0x80)
+#define SCAN_RIGHTCONTROL (0x1D|0x80)
+#define SCAN_BL_INSERT (0x52|0x80)
+#define SCAN_BL_DELETE (0x53|0x80)
+#define SCAN_BL_CURSORLEFT (0x4B|0x80)
+#define SCAN_BL_HOME (0x47|0x80)
+#define SCAN_BL_END (0x4F|0x80)
+#define SCAN_BL_CURSORUP (0x48|0x80)
+#define SCAN_BL_CURSORDOWN (0x50|0x80)
+#define SCAN_BL_PAGEUP (0x49|0x80)
+#define SCAN_BL_PAGEDOWN (0x51|0x80)
+#define SCAN_BL_CURSORRIGHT (0x4D|0x80)
+
+#define SCAN_SCROLLLOCK 0x46
+/* Keys often found in the key pad area. */
+#define SCAN_NUMLOCK 0x45
+#define SCAN_HOME 0x47
+#define SCAN_CURSORLEFT 0x4B
+#define SCAN_END 0x4F
+#define SCAN_SLASH 0x35
+#define SCAN_CURSORUP 0x48
+#define SCAN_CENTER 0x4C
+#define SCAN_CURSORDOWN 0x50
+#define SCAN_INSERT 0x52
+#define SCAN_PAUSE 0xC5
+#define SCAN_ASTERISK 0x37
+#define SCAN_PAGEUP 0x49
+#define SCAN_CURSORRIGHT 0x4D
+#define SCAN_PAGEDOWN 0x51
+#define SCAN_KP_DELETE 0x53
+#define SCAN_KP_MINUS 0x4A
+#define SCAN_KP_PLUS 0x4E
+#define SCAN_KP_ENTER 0x1C
+
+#define SCAN_ESCAPE 0x01
+#define SCAN_F1 0x3B
+#define SCAN_F2 0x3C
+#define SCAN_F3 0x3D
+#define SCAN_F4 0x3E
+#define SCAN_F5 0x3F
+#define SCAN_F6 0x40
+#define SCAN_F7 0x41
+#define SCAN_F8 0x42
+#define SCAN_F9 0x43
+#define SCAN_F10 0x44
+#define SCAN_F11 0x57
+#define SCAN_F12 0x58
+
+#define MKK(k) SCAN_##k
+#define MKK_COUNT (256)
diff --git a/drivers/win/log.c b/drivers/win/log.c
new file mode 100644
index 00000000..732f387c
--- /dev/null
+++ b/drivers/win/log.c
@@ -0,0 +1,106 @@
+#include <stdlib.h>
+#include "common.h"
+
+static HWND logwin=0;
+
+static char *logtext[64];
+static int logcount=0;
+
+static void RedoText(void)
+{
+ char textbuf[65536];
+ int x;
+
+ textbuf[0]=0;
+ if(logcount>=64)
+ {
+ x=logcount&63;
+ for(;;)
+ {
+ strcat(textbuf,logtext[x]);
+ x=(x+1)&63;
+ if(x==(logcount&63)) break;
+ }
+ }
+ else
+ for(x=0;x<logcount;x++)
+ {
+ strcat(textbuf,logtext[x]);
+ }
+ SetDlgItemText(logwin,100,textbuf);
+ SendDlgItemMessage(logwin,100,EM_LINESCROLL,0,200);
+}
+
+static BOOL CALLBACK LogCon(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ DSMFix(uMsg);
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:logwin=hwndDlg;
+ RedoText();break;
+ case WM_COMMAND:
+ if(HIWORD(wParam)==BN_CLICKED)
+ {
+ DestroyWindow(hwndDlg);
+ logwin=0;
+ }
+ break;
+
+ }
+ return 0;
+}
+
+void MakeLogWindow(void)
+{
+ if(!logwin)
+ CreateDialog(fceu_hInstance,"MESSAGELOG",0,LogCon);
+}
+
+void AddLogText(char *text,int newline)
+{
+ int x;
+ char *t;
+
+ if(logcount>=64) free(logtext[logcount&63]);
+
+ x=0;
+ t=text;
+ while(*t)
+ {
+ if(*t=='\n') x++;
+ t++;
+ }
+
+ if(!(logtext[logcount&63]=malloc(strlen(text)+1+x+newline*2)))
+ return;
+
+ t=logtext[logcount&63];
+
+ while(*text)
+ {
+ if(*text=='\n')
+ {
+ *t='\r';
+ t++;
+ }
+ *t=*text;
+ t++;
+ text++;
+ }
+ if(newline)
+ {
+ *t='\r';
+ t++;
+ *t='\n';
+ t++;
+ }
+ *t=0;
+ logcount++;
+ if(logwin)
+ RedoText();
+}
+
+void FCEUD_Message(char *text)
+{
+ AddLogText(text,0);
+}
diff --git a/drivers/win/log.h b/drivers/win/log.h
new file mode 100644
index 00000000..b801ad71
--- /dev/null
+++ b/drivers/win/log.h
@@ -0,0 +1,2 @@
+void MakeLogWindow(void);
+void AddLogText(char *text,int newline);
diff --git a/drivers/win/main.c b/drivers/win/main.c
new file mode 100644
index 00000000..1759625e
--- /dev/null
+++ b/drivers/win/main.c
@@ -0,0 +1,684 @@
+/* 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 "common.h"
+
+// I like hacks.
+#define uint8 __UNO492032
+#include <winsock.h>
+#include <ddraw.h>
+#undef LPCWAVEFORMATEX
+#include <dsound.h>
+#include <dinput.h>
+#include <dir.h>
+#include <commctrl.h>
+#include <shlobj.h> // For directories configuration dialog.
+#undef uint8
+
+#include "input.h"
+#include "netplay.h"
+#include "joystick.h"
+#include "keyboard.h"
+#include "cheat.h"
+#include "debug.h"
+
+#include "memwatch.h"
+#include "basicbot.h"
+
+#define VNSCLIP ((eoptions&EO_CLIPSIDES)?8:0)
+#define VNSWID ((eoptions&EO_CLIPSIDES)?240:256)
+
+uint8 *xbsave=NULL;
+int eoptions=EO_BGRUN | EO_FORCEISCALE;
+
+void ResetVideo(void);
+void ShowCursorAbs(int w);
+void HideFWindow(int h);
+void FixWXY(int pref);
+int SetMainWindowStuff(void);
+int GetClientAbsRect(LPRECT lpRect);
+void UpdateFCEUWindow(void);
+
+
+HWND hAppWnd=0;
+HINSTANCE fceu_hInstance;
+
+HRESULT ddrval;
+
+FCEUGI *GI=0;
+
+// cheats, misc, nonvol, states, snaps, ..., base
+static char *DOvers[6]={0,0,0,0,0,0};
+static char *defaultds[5]={"cheats","sav","fcs","snaps","movie"};
+
+static char TempArray[2048];
+static char BaseDirectory[2048];
+
+void SetDirs(void)
+{
+ int x;
+ static int jlist[6]=
+ {FCEUIOD_CHEATS,FCEUIOD_MISC,FCEUIOD_NV,FCEUIOD_STATE,FCEUIOD_SNAPS, FCEUIOD__COUNT};
+
+ FCEUI_SetSnapName(eoptions&EO_SNAPNAME);
+
+ for(x=0;x<6;x++)
+ {
+ FCEUI_SetDirOverride(jlist[x], DOvers[x]);
+ }
+ if(DOvers[5])
+ FCEUI_SetBaseDirectory(DOvers[5]);
+ else
+ FCEUI_SetBaseDirectory(BaseDirectory);
+}
+/* Remove empty, unused directories. */
+void RemoveDirs(void)
+{
+ int x;
+
+ for(x=0;x<5;x++)
+ if(!DOvers[x])
+ {
+ sprintf(TempArray,"%s\\%s",DOvers[5]?DOvers[5]:BaseDirectory,defaultds[x]);
+ RemoveDirectory(TempArray);
+ }
+}
+
+void CreateDirs(void)
+{
+ int x;
+
+ for(x=0;x<5;x++)
+ if(!DOvers[x])
+ {
+ sprintf(TempArray,"%s\\%s",DOvers[5]?DOvers[5]:BaseDirectory,defaultds[x]);
+ CreateDirectory(TempArray,0);
+ }
+}
+
+static char *gfsdir=0;
+void GetBaseDirectory(void)
+{
+ int x;
+ BaseDirectory[0]=0;
+ GetModuleFileName(0,(LPTSTR)BaseDirectory,2047);
+
+ for(x=strlen(BaseDirectory);x>=0;x--)
+ {
+ if(BaseDirectory[x]=='\\' || BaseDirectory[x]=='/')
+ {BaseDirectory[x]=0;break;}
+ }
+}
+
+static int exiting=0;
+static volatile int moocow = 0;
+int BlockingCheck(void)
+{
+ MSG msg;
+ moocow = 1;
+ while( PeekMessage( &msg, 0, 0, 0, PM_NOREMOVE ) ) {
+ if( GetMessage( &msg, 0, 0, 0)>0 )
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+ }
+ moocow = 0;
+ if(exiting) return(0);
+ return(1);
+}
+
+/* Some timing-related variables (now ignored). */
+static int maxconbskip = 32; /* Maximum consecutive blit skips. */
+static int ffbskip = 32; /* Blit skips per blit when FF-ing */
+
+static int moviereadonly=1;
+
+static int fullscreen=0;
+static int soundflush=0;
+static int genie=0;
+static int palyo=0;
+static int status_icon=1;
+static int windowedfailed;
+static double saspectw=1, saspecth=1;
+static double winsizemulx=1, winsizemuly=1;
+static int winwidth,winheight;
+static int ismaximized = 0;
+
+static volatile int nofocus=0;
+static volatile int userpause=0;
+
+#define SO_FORCE8BIT 1
+#define SO_SECONDARY 2
+#define SO_GFOCUS 4
+#define SO_D16VOL 8
+#define SO_MUTEFA 16
+#define SO_OLDUP 32
+
+#define GOO_DISABLESS 1 /* Disable screen saver when game is loaded. */
+#define GOO_CONFIRMEXIT 2 /* Confirmation before exiting. */
+#define GOO_POWERRESET 4 /* Confirm on power/reset. */
+
+static uint32 goptions = GOO_DISABLESS;
+
+static int soundrate=44100;
+static int soundbuftime=50;
+/*static*/ int soundoptions=SO_SECONDARY|SO_GFOCUS;
+static int soundvolume=100;
+static int soundquality=0;
+extern int autoHoldKey, autoHoldClearKey;
+extern int frame_display, input_display;
+
+static unsigned int srendline,erendline;
+static unsigned int srendlinen=8;
+static unsigned int erendlinen=231;
+static unsigned int srendlinep=0;
+static unsigned int erendlinep=239;
+
+
+static unsigned int totallines;
+
+static void FixFL(void)
+{
+ FCEUI_GetCurrentVidSystem(&srendline,&erendline);
+ totallines=erendline-srendline+1;
+}
+
+static void UpdateRendBounds(void)
+{
+ FCEUI_SetRenderedLines(srendlinen,erendlinen,srendlinep,erendlinep);
+ FixFL();
+}
+
+static uint8 cpalette[192];
+static int vmod = 0;
+int soundo=1;
+static int ntsccol=0,ntsctint,ntschue;
+
+void FCEUD_PrintError(char *s)
+{
+ AddLogText(s,1);
+ if(fullscreen) ShowCursorAbs(1);
+ MessageBox(0,s,"FCE Ultra Error",MB_ICONERROR|MB_OK|MB_SETFOREGROUND|MB_TOPMOST);
+ if(fullscreen)ShowCursorAbs(0);
+}
+
+void ShowAboutBox(void)
+{
+ sprintf(TempArray,"FCE Ultra "FCEU_VERSION"\n\nhttp://fceultra.sourceforge.net\nlukeg.50webs.com/fceu.html\n\n"__TIME__"\n"__DATE__"\n""gcc "__VERSION__);
+ MessageBox(hAppWnd,TempArray,"About FCE Ultra",MB_OK);
+}
+
+
+void DoFCEUExit(void)
+{
+ /* Wolfenstein 3D had cute exit messages. */
+ char *emsg[4]={"Are you sure you want to leave? I'll become lonely!",
+ "If you exit, I'll... EAT YOUR MOUSE.",
+ "You can never really exit, you know.",
+ "E-x-i-t?"
+ };
+
+ if(exiting) /* Eh, oops. I'll need to try to fix this later. */
+ return;
+
+ StopSound();
+ if(goptions & GOO_CONFIRMEXIT)
+ if(IDYES != MessageBox(hAppWnd,emsg[rand()&3],"Exit FCE Ultra?",MB_ICONQUESTION|MB_YESNO))
+ return;
+
+ FCEUI_StopMovie();
+ FCEUD_AviStop();
+
+ exiting=1;
+ if(GI)
+ {
+ FCEUI_CloseGame();
+ GI=0;
+ }
+}
+
+void DoPriority(void)
+{
+ if(eoptions&EO_HIGHPRIO)
+ {
+ if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_HIGHEST))
+ {
+ AddLogText("Error setting thread priority to THREAD_PRIORITY_HIGHEST.",1);
+ }
+ }
+ else
+ if(!SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_NORMAL))
+ {
+ AddLogText("Error setting thread priority to THREAD_PRIORITY_NORMAL.",1);
+ }
+}
+
+static int changerecursive=0;
+
+#include "throttle.c"
+
+#include "sound.c"
+#include "video.c"
+#include "window.c"
+#include "config.c"
+#include "args.c"
+
+int DriverInitialize(void)
+{
+ if(soundo)
+ soundo=InitSound();
+
+ SetVideoMode(fullscreen);
+ InitInputStuff(); /* Initialize DInput interfaces. */
+ return 1;
+}
+
+static void DriverKill(void)
+{
+ sprintf(TempArray,"%s/fceu98.cfg",BaseDirectory);
+ SaveConfig(TempArray);
+ DestroyInput();
+ ResetVideo();
+ if(soundo) TrashSound();
+ CloseWave();
+ ByebyeWindow();
+}
+
+void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count);
+
+void ApplyDefaultCommandMapping(void);
+
+int main(int argc,char *argv[])
+{
+ char *t;
+
+ if(timeBeginPeriod(1)!=TIMERR_NOERROR)
+ {
+ AddLogText("Error setting timer granularity to 1ms.",1);
+ }
+
+ InitCommonControls();
+
+ if(!FCEUI_Initialize())
+ goto doexito;
+ ApplyDefaultCommandMapping();
+
+ srand(GetTickCount()); // rand() is used for some GUI sillyness.
+
+ fceu_hInstance=GetModuleHandle(0);
+
+ GetBaseDirectory();
+
+ sprintf(TempArray,"%s\\fceu98.cfg",BaseDirectory);
+ LoadConfig(TempArray);
+
+ t=ParseArgies(argc,argv);
+ /* Bleh, need to find a better place for this. */
+ {
+ palyo&=1;
+ FCEUI_SetVidSystem(palyo);
+ genie&=1;
+ FCEUI_SetGameGenie(genie);
+ fullscreen&=1;
+ soundo&=1;
+ FCEUI_SetSoundVolume(soundvolume);
+ FCEUI_SetSoundQuality(soundquality);
+ }
+ ParseGIInput(NULL); /* Since a game doesn't have to be
+ loaded before the GUI can be used, make
+ sure the temporary input type variables
+ are set.
+ */
+ CreateDirs();
+ SetDirs();
+
+ DoVideoConfigFix();
+ DoTimingConfigFix();
+
+ if(eoptions&EO_CPALETTE)
+ FCEUI_SetPaletteArray(cpalette);
+
+ if(!t) fullscreen=0;
+
+ CreateMainWindow();
+
+ if(!InitDInput())
+ goto doexito;
+
+ if(!DriverInitialize())
+ goto doexito;
+
+ InitSpeedThrottle();
+ UpdateMenu();
+
+ if(t)
+ ALoad(t);
+ else if(eoptions&EO_FOAFTERSTART)
+ LoadNewGamey(hAppWnd, 0);
+
+doloopy:
+ UpdateFCEUWindow();
+ if(GI)
+ {
+ while(GI)
+ {
+ uint8 *gfx=0;
+ int32 *sound=0;
+ int32 ssize=0;
+ FCEUI_Emulate(&gfx, &sound, &ssize, 0);
+ xbsave = gfx;
+ FCEUD_Update(gfx, sound, ssize);
+ static int stopCount=0;
+ if(FCEUI_EmulationPaused() & 1)
+ {
+ if(stopCount==0)
+ UpdateMemWatch();
+
+ stopCount++;
+ if(stopCount > 8)
+ {
+ StopSound();
+ stopCount = 0;
+ }
+ //if in bot mode, don't idle. eat the CPU up :)
+ if(!FCEU_BotMode())
+ {
+ int notAlternateThrottle = !(soundoptions&SO_OLDUP) && soundo && ((NoWaiting&1)?(256*16):fps_scale) >= 64;
+ if(notAlternateThrottle)
+ Sleep(5); // HACK to fix 100% CPU usage that happens sporadically when paused in background - also, this affects the repeat rate of frame advance and its sound quality
+ else
+ Sleep(1); // lesser, so frame advance repeat doesn't take too long with the alternate throttling
+ }
+ else if(stopCount == 1)
+ {
+ Sleep(0);
+ }
+ }
+ else
+ {
+ //UpdateMemWatch();
+ stopCount=0;
+ }
+ }
+ xbsave = NULL;
+ RedrawWindow(hAppWnd,0,0,RDW_ERASE|RDW_INVALIDATE);
+ StopSound();
+ }
+ Sleep(50);
+ if(!exiting)
+ goto doloopy;
+
+ doexito:
+ DriverKill();
+ timeEndPeriod(1);
+ FCEUI_Kill();
+ return(0);
+}
+
+void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count)
+{
+ static int skipcount = 0;
+ int temp_fps_scale=(NoWaiting&1)?(256*16):fps_scale;
+ int maxskip = (temp_fps_scale<=256) ? 0 : temp_fps_scale>>8;
+
+ int ocount = Count;
+ // apply frame scaling to Count
+ Count = (Count<<8)/temp_fps_scale;
+
+ //Disable sound and throttling for BotMode--we want max speed!
+ if(FCEU_BotMode())
+ {
+ if(XBuf && (skipcount >= 64))
+ {
+ skipcount = 0;
+ FCEUD_BlitScreen(XBuf);
+ }
+ else
+ {
+ skipcount++;
+ }
+ UpdateFCEUWindow();
+ FCEUD_UpdateInput();
+ return;
+ }
+
+ if(!(soundoptions&SO_OLDUP) && soundo && temp_fps_scale >= 64)
+ {
+ // sounds better with FPS scaling, and is much less code than the other version...
+
+ int32 writeSize = GetWriteSound();
+ int32 writeCount = Count;
+/*
+ // prevents delay when exiting fast-forward
+ if((NoWaiting&1) && writeCount>writeSize)
+ writeCount=writeSize;
+*/
+
+ if(Buffer && (writeCount))
+ FCEUD_WriteSoundData(Buffer,temp_fps_scale,MAX(writeSize,writeCount));
+
+ if(XBuf && (skipcount >= maxskip))
+ {
+ skipcount = 0;
+ FCEUD_BlitScreen(XBuf);
+ UpdateMemWatch();
+ }
+ else
+ skipcount++;
+
+ UpdateFCEUWindow();
+ FCEUD_UpdateInput();
+ }
+ else
+ {
+ // I don't understand this code, so I kept it around as an option ("old sound update")
+ // in case it's doing something clever and necessary that I can't fathom
+ // (oops, also it seems to be important for speeds <25% so it's always used then)
+
+ const int soundScale = !(soundoptions&SO_OLDUP) ? temp_fps_scale : 256;
+
+ if(Count)
+ {
+ int32 can=GetWriteSound();
+ static int uflow=0;
+ int32 tmpcan;
+ extern int FCEUDnetplay;
+
+ // don't underflow when scaling fps
+ if(can >= GetMaxSound() && fps_scale<=256) uflow=1; // Go into massive underflow mode.
+
+ if(can > Count) can=Count;
+ else uflow=0;
+
+ FCEUD_WriteSoundData(Buffer,soundScale,can);
+
+ tmpcan = GetWriteSound();
+ // don't underflow when scaling fps
+ if(fps_scale>256 || ((tmpcan < Count*0.90) && !uflow) || (skipcount >= maxskip))
+ {
+ if(XBuf && (skipcount >= maxskip))
+ {
+ skipcount = 0;
+ FCEUD_BlitScreen(XBuf);
+ UpdateMemWatch();
+ }
+ else
+ {
+ skipcount++;
+ //FCEU_printf("Skipped0");
+ // FCEU_PrintError("Skipped0");
+ }
+ Buffer+=can;
+ Count-=can;
+ if(Count)
+ {
+ if(NoWaiting)
+ {
+ can=GetWriteSound();
+ if(Count>can) Count=can;
+ FCEUD_WriteSoundData(Buffer,soundScale,Count);
+ }
+ else
+ {
+ int cnum=0;
+ extern int silencer;
+ while(Count>0)
+ {
+ FCEUD_WriteSoundData(Buffer,soundScale,(Count<ocount) ? Count : ocount);
+ if(!(soundoptions&SO_OLDUP))
+ {
+ cnum++;
+ if(cnum>2)
+ silencer=1;
+ }
+ Count -= ocount;
+ // prevent long updates from interfering with gui responsiveness:
+ UpdateFCEUWindow();
+ FCEUD_UpdateInput();
+ }
+ silencer=0;
+ }
+ }
+ }
+ else
+ {
+ skipcount++;
+ //FCEU_printf("Skipped");
+#ifdef NETWORK
+ if(!NoWaiting && FCEUDnetplay && (uflow || tmpcan >= (Count * 0.90)))
+ {
+ if(Count > tmpcan) Count=tmpcan;
+ while(tmpcan > 0)
+ {
+ //printf("Overwrite: %d\n", (Count <= tmpcan)?Count : tmpcan);
+ FCEUD_WriteSoundData(Buffer,soundScale,(Count <= tmpcan)?Count : tmpcan);
+ tmpcan -= Count;
+ }
+ }
+#endif
+ }
+ }
+ else
+ {
+ /* This complex statement deserves some explanation.
+ Make sure this special speed throttling hasn't been disabled by the user
+ first. Second, we don't want to throttle the speed if the fast-forward
+ button is pressed down(or during certain network play conditions).
+
+ Now, if we're at this point, we'll throttle speed if sound is disabled.
+ Otherwise, it gets a bit more complicated. We'll throttle speed if focus
+ to FCE Ultra has been lost and we're writing to the primary sound buffer
+ because our sound code won't block. Blocking does seem to work when
+ writing to a secondary buffer, so we won't throttle when a secondary
+ buffer is used.
+ */
+ int skipthis = 0;
+
+ doagain: //mbg merge 6/30/06
+
+ if(!(eoptions&EO_NOTHROTTLE) || fps_scale != 256)
+ if(!NoWaiting)
+ if(!soundo || (soundo && nofocus && !(soundoptions&SO_SECONDARY)) || FCEUI_EmulationPaused() )
+ skipthis = SpeedThrottle();
+
+ if(XBuf)
+ {
+ if((!skipthis && !NoWaiting) || (skipcount >= maxskip))
+ {
+ FCEUD_BlitScreen(XBuf);
+ UpdateMemWatch();
+ skipcount = 0;
+ }
+ else
+ {
+ skipcount++;
+ }
+ }
+
+
+ //mbg merge 6/30/06
+ if(userpause)
+ {
+ StopSound();
+ Sleep(50);
+ BlockingCheck();
+ goto doagain;
+ }
+ }
+
+ UpdateFCEUWindow();
+ FCEUD_UpdateInput();
+ PPUViewDoBlit();
+ //mbg merge 6/29/06
+ UpdateMemoryView(0);
+ UpdateCDLogger();
+ UpdateLogWindow();
+ NTViewDoBlit(0);
+
+ } // end of !(old sound code) block
+}
+
+/*
+void FCEUD_Update(uint8 *XBuf, int32 *Buffer, int Count)
+{
+ FCEUD_BlitScreen(XBuf);
+ if(Count && soundo)
+ FCEUD_WriteSoundData(Buffer,Count);
+ FCEUD_UpdateInput();
+}
+*/
+
+static void FCEUD_MakePathDirs(const char *fname)
+{
+ char path[MAX_PATH];
+ const char* div=fname;
+ do {
+ const char* fptr=strchr(div,'\\');
+ if(!fptr) fptr=strchr(div,'/');
+ if(!fptr) break;
+ int off=fptr-fname;
+ strncpy(path,fname,off);
+ path[off]='\0';
+ mkdir(path);
+ div=fptr+1;
+ while(div[0]=='\\'||div[0]=='/') div++;
+ } while(1);
+}
+
+FILE *FCEUD_UTF8fopen(const char *n, const char *m)
+{
+ if(strchr(m,'w')||strchr(m,'+'))
+ FCEUD_MakePathDirs(n);
+
+ return(fopen(n,m));
+}
+
+int FCEUD_ShowStatusIcon(void)
+{
+ return status_icon;
+}
+
+void FCEUD_ToggleStatusIcon(void)
+{
+ status_icon=!status_icon;
+ UpdateMenu();
+}
diff --git a/drivers/win/memwatch.c b/drivers/win/memwatch.c
new file mode 100644
index 00000000..f8c51ca4
--- /dev/null
+++ b/drivers/win/memwatch.c
@@ -0,0 +1,450 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2006 Luke Gustafson
+ *
+ * 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 "common.h"
+
+#include "memwatch.h"
+
+static HWND hwndMemWatch=0;
+static char addresses[24][16];
+static char labels[24][24];
+static int NeedsInit = 1;
+char *MemWatchDir = 0;
+
+static char *U8ToStr(uint8 a)
+{
+ static char TempArray[8];
+ TempArray[0] = '0' + a/100;
+ TempArray[1] = '0' + (a%100)/10;
+ TempArray[2] = '0' + (a%10);
+ TempArray[3] = 0;
+ return TempArray;
+}
+
+
+//I don't trust scanf for speed
+static uint16 FastStrToU16(char* s)
+{
+ int i;
+ uint16 v=0;
+ for(i=0; i < 4; i++)
+ {
+ if(s[i] == 0) return v;
+ v<<=4;
+ if(s[i] >= '0' && s[i] <= '9')
+ {
+ v+=s[i]-'0';
+ }
+ else if(s[i] >= 'a' && s[i] <= 'f')
+ {
+ v+=s[i]-'a'+10;
+ }
+ else if(s[i] >= 'A' && s[i] <= 'F')
+ {
+ v+=s[i]-'A'+10;
+ }
+ else
+ {
+ return 0xFFFF;
+ }
+ }
+ return v;
+}
+
+static char *U16ToDecStr(uint16 a)
+{
+ static char TempArray[8];
+ TempArray[0] = '0' + a/10000;
+ TempArray[1] = '0' + (a%10000)/1000;
+ TempArray[2] = '0' + (a%1000)/100;
+ TempArray[3] = '0' + (a%100)/10;
+ TempArray[4] = '0' + (a%10);
+ TempArray[5] = 0;
+ return TempArray;
+}
+
+//sorry this is hard to read... but I don't trust printf for speed!
+static char *U16ToHexStr(uint16 a)
+{
+ static char TempArray[8];
+ TempArray[0] = a/4096 > 9?'A'+a/4096-10:'0' + a/4096;
+ TempArray[1] = (a%4096)/256 > 9?'A'+(a%4096)/256 - 10:'0' + (a%4096)/256;
+ TempArray[2] = (a%256)/16 > 9?'A'+(a%256)/16 - 10:'0' + (a%256)/16;
+ TempArray[3] = a%16 > 9?'A'+(a%16) - 10:'0' + (a%16);
+ TempArray[4] = 0;
+ return TempArray;
+}
+
+static char *U8ToHexStr(uint8 a)
+{
+ static char TempArray[8];
+ TempArray[0] = a/16 > 9?'A'+a/16 - 10:'0' + a/16;
+ TempArray[1] = a%16 > 9?'A'+(a%16) - 10:'0' + (a%16);
+ TempArray[2] = 0;
+ return TempArray;
+}
+
+//Update the values in the Memory Watch window
+void UpdateMemWatch()
+{
+ if(hwndMemWatch)
+ {
+ char TempArray[16];
+ int i, twobytes, hex;
+ uint16 a;
+ for(i = 0; i < 24; i++)
+ {
+ GetDlgItemText(hwndMemWatch,1001+i*3,TempArray,16);
+ twobytes=0;
+ hex = 0;
+ TempArray[15]=0;
+ switch(TempArray[0])
+ {
+ case 0:
+ SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)"---");
+ continue;
+ case '!':
+ twobytes=1;
+ a=FastStrToU16(TempArray+1);
+ break;
+ case 'x':
+ hex = 1;
+ a=FastStrToU16(TempArray+1);
+ break;
+ case 'X':
+ hex = twobytes = 1;
+ a = FastStrToU16(TempArray+1);
+ break;
+ default:
+ a=FastStrToU16(TempArray);
+ break;
+ }
+ if(a != 0xFFFF)
+ {
+ if(hex == 0)
+ {
+ if(twobytes == 0)
+ {
+ SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U8ToStr(ARead[a](a)));
+ }
+ else
+ {
+ SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U16ToDecStr(ARead[a](a)+256*ARead[a+1](a+1)));
+ }
+ }
+ else
+ {
+ if(twobytes == 0)
+ {
+ SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U8ToHexStr(ARead[a](a)));
+ }
+ else
+ {
+ SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)U16ToHexStr(ARead[a](a)+256*ARead[a+1](a+1)));
+ }
+ }
+ }
+ else
+ {
+ SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR)"---");
+ }
+ }
+ }
+}
+
+//Save labels/addresses so next time dialog is opened,
+//you don't lose what you've entered.
+static void SaveStrings()
+{
+ int i;
+ for(i=0;i<24;i++)
+ {
+ GetDlgItemText(hwndMemWatch,1001+i*3,addresses[i],16);
+ GetDlgItemText(hwndMemWatch,1000+i*3,labels[i],24);
+ }
+}
+
+//replaces spaces with a dummy character
+static void TakeOutSpaces(int i)
+{
+ int j;
+ for(j=0;j<16;j++)
+ {
+ if(addresses[i][j] == ' ') addresses[i][j] = '|';
+ if(labels[i][j] == ' ') labels[i][j] = '|';
+ }
+ for(;j<24;j++)
+ {
+ if(labels[i][j] == ' ') labels[i][j] = '|';
+ }
+}
+
+//replaces dummy characters with spaces
+static void PutInSpaces(int i)
+{
+ int j;
+ for(j=0;j<16;j++)
+ {
+ if(addresses[i][j] == '|') addresses[i][j] = ' ';
+ if(labels[i][j] == '|') labels[i][j] = ' ';
+ }
+ for(;j<24;j++)
+ {
+ if(labels[i][j] == '|') labels[i][j] = ' ';
+ }
+}
+
+//Saves all the addresses and labels to disk
+static void SaveMemWatch()
+{
+ const char filter[]="Memory address list(*.txt)\0*.txt\0";
+ char nameo[2048];
+ OPENFILENAME ofn;
+ memset(&ofn,0,sizeof(ofn));
+ ofn.lStructSize=sizeof(ofn);
+ ofn.hInstance=fceu_hInstance;
+ ofn.lpstrTitle="Save Memory Watch As...";
+ ofn.lpstrFilter=filter;
+ nameo[0]=0;
+ ofn.lpstrFile=nameo;
+ ofn.nMaxFile=256;
+ ofn.Flags=OFN_EXPLORER|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT;
+ ofn.lpstrInitialDir=MemWatchDir;
+ if(GetSaveFileName(&ofn))
+ {
+ int i,j;
+
+ //Save the directory
+ if(ofn.nFileOffset < 1024)
+ {
+ free(MemWatchDir);
+ MemWatchDir=malloc(strlen(ofn.lpstrFile)+1);
+ strcpy(MemWatchDir,ofn.lpstrFile);
+ MemWatchDir[ofn.nFileOffset]=0;
+ }
+
+ //quick get length of nameo
+ for(i=0;i<2048;i++)
+ {
+ if(nameo[i] == 0)
+ {
+ break;
+ }
+ }
+
+ //add .txt if nameo doesn't have it
+ if((i < 4 || nameo[i-4] != '.') && i < 2040)
+ {
+ nameo[i] = '.';
+ nameo[i+1] = 't';
+ nameo[i+2] = 'x';
+ nameo[i+3] = 't';
+ nameo[i+4] = 0;
+ }
+
+ SaveStrings();
+ FILE *fp=FCEUD_UTF8fopen(nameo,"w");
+ for(i=0;i<24;i++)
+ {
+ //Use dummy strings to fill empty slots
+ if(labels[i][0] == 0)
+ {
+ labels[i][0] = '|';
+ labels[i][1] = 0;
+ }
+ if(addresses[i][0] == 0)
+ {
+ addresses[i][0] = '|';
+ addresses[i][1] = 0;
+ }
+ //spaces can be a problem for scanf so get rid of them
+ TakeOutSpaces(i);
+ fprintf(fp, "%s %s\n", addresses[i], labels[i]);
+ PutInSpaces(i);
+ }
+ fclose(fp);
+ }
+}
+
+//Loads a previously saved file
+static void LoadMemWatch()
+{
+ const char filter[]="Memory address list(*.txt)\0*.txt\0";
+ char nameo[2048];
+ OPENFILENAME ofn;
+ memset(&ofn,0,sizeof(ofn));
+ ofn.lStructSize=sizeof(ofn);
+ ofn.hInstance=fceu_hInstance;
+ ofn.lpstrTitle="Load Memory Watch...";
+ ofn.lpstrFilter=filter;
+ nameo[0]=0;
+ ofn.lpstrFile=nameo;
+ ofn.nMaxFile=256;
+ ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
+ ofn.lpstrInitialDir=MemWatchDir;
+
+ if(GetOpenFileName(&ofn))
+ {
+ int i,j;
+
+ //Save the directory
+ if(ofn.nFileOffset < 1024)
+ {
+ free(MemWatchDir);
+ MemWatchDir=malloc(strlen(ofn.lpstrFile)+1);
+ strcpy(MemWatchDir,ofn.lpstrFile);
+ MemWatchDir[ofn.nFileOffset]=0;
+ }
+
+ FILE *fp=FCEUD_UTF8fopen(nameo,"r");
+ for(i=0;i<24;i++)
+ {
+ fscanf(fp, "%s ", nameo); //re-using nameo--bady style :P
+ for(j = 0; j < 16; j++)
+ addresses[i][j] = nameo[j];
+ fscanf(fp, "%s\n", nameo);
+ for(j = 0; j < 24; j++)
+ labels[i][j] = nameo[j];
+
+ //Replace dummy strings with empty strings
+ if(addresses[i][0] == '|')
+ {
+ addresses[i][0] = 0;
+ }
+ if(labels[i][0] == '|')
+ {
+ labels[i][0] = 0;
+ }
+ PutInSpaces(i);
+
+ addresses[i][15] = 0;
+ labels[i][23] = 0; //just in case
+
+ SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR) "---");
+ SetDlgItemText(hwndMemWatch,1001+i*3,(LPTSTR) addresses[i]);
+ SetDlgItemText(hwndMemWatch,1000+i*3,(LPTSTR) labels[i]);
+ }
+ fclose(fp);
+ }
+}
+
+static BOOL CALLBACK MemWatchCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ DSMFix(uMsg);
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ break;
+ case WM_CLOSE:
+ case WM_QUIT:
+ SaveStrings();
+ DestroyWindow(hwndMemWatch);
+ hwndMemWatch=0;
+ break;
+ case WM_COMMAND:
+ switch(HIWORD(wParam))
+ {
+ case BN_CLICKED:
+ switch(LOWORD(wParam))
+ {
+ case 101: //Save button clicked
+ StopSound();
+ SaveMemWatch();
+ break;
+ case 102: //Load button clicked
+ StopSound();
+ LoadMemWatch();
+ break;
+ case 103: //Clear button clicked
+ StopSound();
+ if(MessageBox(hwndMemWatch, "Clear all text?", "Confirm clear", MB_YESNO)==IDYES)
+ {
+ int i;
+ for(i=0;i<24;i++)
+ {
+ addresses[i][0] = 0;
+ labels[i][0] = 0;
+ SetDlgItemText(hwndMemWatch,1001+i*3,(LPTSTR) addresses[i]);
+ SetDlgItemText(hwndMemWatch,1000+i*3,(LPTSTR) labels[i]);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if(!(wParam>>16)) //Close button clicked
+ {
+ switch(wParam&0xFFFF)
+ {
+ case 1:
+ SaveStrings();
+ DestroyWindow(hwndMemWatch);
+ hwndMemWatch=0;
+ break;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+//Open the Memory Watch dialog
+void CreateMemWatch(HWND parent)
+{
+ if(NeedsInit) //Clear the strings
+ {
+ NeedsInit = 0;
+ int i,j;
+ for(i=0;i<24;i++)
+ {
+ for(j=0;j<24;j++)
+ {
+ addresses[i][j] = 0;
+ labels[i][j] = 0;
+ }
+ }
+ }
+
+ if(hwndMemWatch) //If already open, give focus
+ {
+ SetFocus(hwndMemWatch);
+ return;
+ }
+
+ //Create
+ //hwndMemWatch=CreateDialog(fceu_hInstance,"MEMWATCH",parent,MemWatchCallB);
+ hwndMemWatch=CreateDialog(fceu_hInstance,"MEMWATCH",NULL,MemWatchCallB);
+
+ //Initialize values to previous entered addresses/labels
+ {
+ int i;
+ for(i = 0; i < 24; i++)
+ {
+ SetDlgItemText(hwndMemWatch,1002+i*3,(LPTSTR) "---");
+ SetDlgItemText(hwndMemWatch,1001+i*3,(LPTSTR) addresses[i]);
+ SetDlgItemText(hwndMemWatch,1000+i*3,(LPTSTR) labels[i]);
+ }
+ }
+}
+
diff --git a/drivers/win/memwatch.h b/drivers/win/memwatch.h
new file mode 100644
index 00000000..949625aa
--- /dev/null
+++ b/drivers/win/memwatch.h
@@ -0,0 +1,3 @@
+void UpdateMemWatch();
+void CreateMemWatch();
+extern char * MemWatchDir;
diff --git a/drivers/win/netplay.c b/drivers/win/netplay.c
new file mode 100644
index 00000000..5720d42a
--- /dev/null
+++ b/drivers/win/netplay.c
@@ -0,0 +1,490 @@
+/* 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 "common.h"
+#include "../../md5.h"
+
+static int recv_tcpwrap(uint8 *buf, int len);
+static void NetStatAdd(char *text);
+
+static HWND netwin=0;
+
+static char *netstatt[64];
+static int netstattcount=0;
+static int netlocalplayers = 1;
+
+static char *netplayhost = 0;
+static char *netplaynick = 0;
+static char *netgamekey = 0;
+static char *netpassword = 0;
+static int remotetport=0xFCE;
+
+static SOCKET Socket=INVALID_SOCKET;
+
+static int wsainit=0;
+
+int FCEUDnetplay = 0;
+static void WSE(char *ahh)
+{
+ char tmp[256];
+ sprintf(tmp,"*** Winsock: %s",ahh);
+ NetStatAdd(tmp);
+}
+
+static void en32(uint8 *buf, uint32 morp)
+{
+ buf[0]=morp;
+ buf[1]=morp>>8;
+ buf[2]=morp>>16;
+ buf[3]=morp>>24;
+}
+
+static uint32 de32(uint8 *morp)
+{
+ return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24));
+}
+static void FixCDis(HWND hParent, int how);
+void FCEUD_NetworkClose(void)
+{
+ NetStatAdd("*** Connection lost.");
+ if(netwin)
+ {
+ SetDlgItemText(netwin,250,"Connect");
+ FixCDis(netwin,1);
+ }
+ if(Socket!=INVALID_SOCKET)
+ {
+ closesocket(Socket);
+ Socket=INVALID_SOCKET;
+ }
+
+ if(wsainit)
+ {
+ WSACleanup();
+ wsainit=0;
+ }
+ /* Make sure blocking is returned to normal once network play is stopped. */
+ NoWaiting&=~2;
+ FCEUDnetplay = 0;
+ FCEUI_NetplayStop();
+}
+static void FixCDis(HWND hParent, int how)
+{
+ int x;
+
+ for(x=200;x<=206;x++)
+ EnableWindow( GetDlgItem(hParent,x),how);
+}
+static void GetSettings(HWND hwndDlg)
+{
+ char buf[256];
+ char **strs[4]={&netplayhost,&netplaynick,&netgamekey,&netpassword};
+ int ids[4]={200,203,205,206};
+ int x;
+
+ for(x=0;x<4;x++)
+ {
+ GetDlgItemText(hwndDlg,ids[x],buf,256);
+ if(*strs[x])
+ {
+ free(*strs[x]);
+ *strs[x] = 0;
+ }
+ if(buf[0])
+ {
+ *strs[x] = malloc(strlen(buf) + 1);
+ strcpy(*strs[x], buf);
+ }
+ }
+ remotetport = GetDlgItemInt(hwndDlg,201,0,0);
+ netlocalplayers=1 + SendDlgItemMessage(hwndDlg,204,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
+}
+static BOOL CALLBACK NetCon(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_CLOSE:
+ GetSettings(hwndDlg);
+ DestroyWindow(hwndDlg);
+ netwin=0;
+ FCEUD_NetworkClose();
+ break;
+ case WM_COMMAND:
+ if(HIWORD(wParam)==BN_CLICKED)
+ {
+ switch(LOWORD(wParam))
+ {
+ case 250:
+ if(FCEUDnetplay)
+ {
+ FCEUD_NetworkClose();
+ SetDlgItemText(hwndDlg,250,"Connect");
+ FixCDis(hwndDlg,1);
+ }
+ else if(GI)
+ {
+ GetSettings(hwndDlg);
+ if(FCEUD_NetworkConnect())
+ {
+ SetDlgItemText(hwndDlg,250,"Disconnect");
+ FixCDis(hwndDlg,0);
+ }
+ }
+ break;
+ }
+ }
+ else if(HIWORD(wParam)==EN_CHANGE && Socket!=INVALID_SOCKET)
+ {
+ char buf[1024];
+ int t;
+
+
+ t=GetDlgItemText(hwndDlg,102,buf,1024);
+ buf[1023]=0;
+
+ if(strchr(buf,'\r'))
+ {
+ char *src,*dest;
+
+ src=dest=buf;
+
+ while(*src)
+ {
+ if(*src != '\n' && *src != '\r')
+ {
+ *dest = *src;
+ dest++;
+ }
+ src++;
+ }
+ *dest = 0;
+ FCEUI_NetplayText(buf);
+ SetDlgItemText(hwndDlg,102,"");
+ }
+ }
+ break;
+ case WM_INITDIALOG:
+ if(netplayhost)
+ SetDlgItemText(hwndDlg,200,netplayhost);
+ SetDlgItemInt(hwndDlg,201,remotetport,0);
+ if(netplaynick)
+ SetDlgItemText(hwndDlg,203,netplaynick);
+ if(netgamekey)
+ SetDlgItemText(hwndDlg,205,netgamekey);
+ if(netpassword)
+ SetDlgItemText(hwndDlg,206,netpassword);
+
+ {
+ int x;
+ char buf[8];
+ for(x=0;x<4;x++)
+ {
+ sprintf(buf,"%d",x+1);
+ SendDlgItemMessage(hwndDlg,204,CB_ADDSTRING,0,(LPARAM)(LPSTR)buf);
+ }
+ SendDlgItemMessage(hwndDlg,204,CB_SETCURSEL,netlocalplayers-1,(LPARAM)(LPSTR)0);
+ }
+
+
+ break;
+ }
+
+ return 0;
+}
+
+static void NetStatAdd(char *text)
+{
+ int x;
+ uint32 totallen = 0;
+ char *textbuf;
+
+ if(!netwin) return;
+ if(netstattcount>=64) free(netstatt[netstattcount&63]);
+
+ if(!(netstatt[netstattcount&63]=malloc(strlen(text)+1)))
+ return;
+ strcpy(netstatt[netstattcount&63],text);
+ netstattcount++;
+
+ if(netstattcount>=64)
+ {
+ for(x=netstattcount&63;;)
+ {
+ totallen += strlen(netstatt[x]);
+ x=(x+1)&63;
+ if(x==(netstattcount&63)) break;
+ totallen += 2;
+ }
+
+ totallen++; // NULL
+ textbuf = malloc(totallen);
+ textbuf[0] = 0;
+
+ for(x=netstattcount&63;;)
+ {
+ strcat(textbuf,netstatt[x]);
+ x=(x+1)&63;
+ if(x==(netstattcount&63)) break;
+ strcat(textbuf,"\r\n");
+ }
+ }
+ else
+ {
+ for(x=0;x<netstattcount;x++)
+ {
+ totallen += strlen(netstatt[x]);
+ if(x<(netstattcount-1))
+ totallen += 2;
+ }
+ totallen++;
+ textbuf = malloc(totallen);
+ textbuf[0] = 0;
+ for(x=0;x<netstattcount;x++)
+ {
+ strcat(textbuf,netstatt[x]);
+ if(x<(netstattcount-1))
+ strcat(textbuf,"\r\n");
+ }
+ }
+ SetDlgItemText(netwin,101,textbuf);
+ free(textbuf);
+ SendDlgItemMessage(netwin,101,EM_LINESCROLL,0,32767);
+}
+
+void FCEUD_NetplayText(uint8 *text)
+{
+ NetStatAdd(text);
+}
+
+int FCEUD_NetworkConnect(void)
+{
+ WSADATA WSAData;
+ SOCKADDR_IN sockin; /* I want to play with fighting robots. */
+ SOCKET TSocket;
+ int netdivisor;
+
+ if(WSAStartup(MAKEWORD(1,1),&WSAData))
+ {
+ NetStatAdd("*** Error initializing WIndows Sockets.");
+ return(0);
+ }
+ wsainit=1;
+
+ if( (TSocket=socket(AF_INET,SOCK_STREAM,0))==INVALID_SOCKET)
+ {
+ WSE("Error creating stream socket.");
+ FCEUD_NetworkClose();
+ return(0);
+ }
+
+ memset(&sockin,0,sizeof(sockin));
+ sockin.sin_family=AF_INET;
+
+ {
+ struct hostent *phostentb;
+ unsigned long hadr;
+ int sockin_len;
+
+ sockin.sin_port=0;
+ sockin.sin_addr.s_addr=INADDR_ANY;
+ sockin_len=sizeof(sockin);
+
+ hadr=inet_addr(netplayhost);
+
+ if(hadr!=INADDR_NONE)
+ sockin.sin_addr.s_addr=hadr;
+ else
+ {
+ NetStatAdd("*** Looking up host name...");
+ if(!(phostentb=gethostbyname((const char *)netplayhost)))
+ {
+ WSE("Error getting host network information.");
+ closesocket(TSocket);
+ FCEUD_NetworkClose();
+ return(0);
+ }
+ memcpy((char *)&sockin.sin_addr,((PHOSTENT)phostentb)->h_addr,((PHOSTENT)phostentb)->h_length);
+ }
+
+ sockin.sin_port=htons(remotetport);
+ NetStatAdd("*** Connecting to remote host...");
+ if(connect(TSocket,(PSOCKADDR)&sockin,sizeof(sockin))==SOCKET_ERROR)
+ {
+ WSE("Error connecting to remote host.");
+ closesocket(TSocket);
+ FCEUD_NetworkClose();
+ return(0);
+ }
+ Socket=TSocket;
+ NetStatAdd("*** Sending initialization data to server...");
+
+ {
+ uint8 *sendbuf;
+ uint8 buf[1];
+ uint32 sblen;
+
+ sblen = 4 + 16 + 16 + 64 + 1 + (netplaynick?strlen(netplaynick):0);
+ sendbuf = malloc(sblen);
+ memset(sendbuf, 0, sblen);
+
+ en32(sendbuf, sblen - 4);
+
+ if(netgamekey)
+ {
+ struct md5_context md5;
+ uint8 md5out[16];
+
+ md5_starts(&md5);
+ md5_update(&md5, GI->MD5, 16);
+ md5_update(&md5, netgamekey, strlen(netgamekey));
+ md5_finish(&md5, md5out);
+ memcpy(sendbuf + 4, md5out, 16);
+ }
+ else
+ memcpy(sendbuf + 4, GI->MD5, 16);
+
+ if(netpassword)
+ {
+ struct md5_context md5;
+ uint8 md5out[16];
+
+ md5_starts(&md5);
+ md5_update(&md5, netpassword, strlen(netpassword));
+ md5_finish(&md5, md5out);
+ memcpy(sendbuf + 4 + 16, md5out, 16);
+ }
+
+ memset(sendbuf + 4 + 16 + 16, 0, 64);
+ sendbuf[4 + 16 + 16 + 64] = netlocalplayers;
+
+ if(netplaynick)
+ memcpy(sendbuf + 4 + 16 + 16 + 64 + 1,netplaynick,strlen(netplaynick));
+
+ send(Socket, sendbuf, sblen, 0);
+ free(sendbuf);
+
+ recv_tcpwrap(buf, 1);
+ netdivisor = buf[0];
+ }
+ }
+
+
+ FCEUI_NetplayStart(netlocalplayers,netdivisor);
+ NetStatAdd("*** Connection established.");
+
+ FCEUDnetplay = 1;
+ int tcpopt = 1;
+ if(setsockopt(TSocket, IPPROTO_TCP, TCP_NODELAY, &tcpopt, sizeof(int)))
+ puts("Nodelay fail");
+
+ return(1);
+}
+
+
+int FCEUD_SendData(void *data, uint32 len)
+{
+ send(Socket, data, len ,0);
+ return(1);
+}
+
+static int recv_tcpwrap(uint8 *buf, int len)
+{
+ fd_set fdoo;
+ int t;
+ struct timeval popeye;
+
+ popeye.tv_sec=0;
+ popeye.tv_usec=100000;
+
+ while(len)
+ {
+ FD_ZERO(&fdoo);
+ FD_SET(Socket,&fdoo);
+
+ switch(select(0,&fdoo,0,0,&popeye))
+ {
+ case 0: //BlockingCheck();
+ continue;
+ case SOCKET_ERROR:return(0);
+ }
+
+ t=recv(Socket,buf,len,0);
+ if(t<=0) return(0);
+ len -= t;
+ buf += t;
+ }
+ return(1);
+}
+
+int FCEUD_RecvData(void *data, uint32 len)
+{
+ NoWaiting&=~2;
+
+ for(;;)
+ {
+ fd_set funfun;
+ struct timeval popeye;
+
+ popeye.tv_sec=0;
+ popeye.tv_usec=100000;
+
+ FD_ZERO(&funfun);
+ FD_SET(Socket,&funfun);
+
+ switch(select(0,&funfun,0,0,&popeye))
+ {
+ case 0:continue;
+ case SOCKET_ERROR:return(0);
+ }
+
+ if(FD_ISSET(Socket,&funfun))
+ {
+ if(recv_tcpwrap(data,len)>0)
+ {
+ unsigned long beefie;
+ if(!ioctlsocket(Socket,FIONREAD,&beefie))
+ if(beefie)
+ NoWaiting|=2;
+ return(1);
+ }
+ else
+ return(0);
+ }
+ else
+ return(0);
+ }
+ return 0;
+}
+
+void ShowNetplayConsole(void)
+{
+ if(!netwin)
+ netwin=CreateDialog(fceu_hInstance,"NETMOO",0,NetCon);
+}
+
+CFGSTRUCT NetplayConfig[]={
+ AC(remotetport),
+ AC(netlocalplayers),
+ ACS(netgamekey),
+ ACS(netplayhost),
+ ACS(netplaynick),
+ ACS(netpassword),
+ ENDCFGSTRUCT
+};
diff --git a/drivers/win/netplay.h b/drivers/win/netplay.h
new file mode 100644
index 00000000..c2f2f923
--- /dev/null
+++ b/drivers/win/netplay.h
@@ -0,0 +1 @@
+extern CFGSTRUCT NetplayConfig[];
diff --git a/drivers/win/ppuview.c b/drivers/win/ppuview.c
new file mode 100644
index 00000000..b2111386
--- /dev/null
+++ b/drivers/win/ppuview.c
@@ -0,0 +1,352 @@
+/* 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 "common.h"
+#include "..\..\palette.h"
+
+
+
+HWND hPPUView;
+
+extern uint8 *VPage[8];
+extern uint8 PALRAM[0x20];
+
+int PPUViewPosX,PPUViewPosY;
+uint8 palcache[32] = { 0xFF }; //palette cache
+uint8 chrcache0[0x1000],chrcache1[0x1000]; //cache CHR, fixes a refresh problem when right-clicking
+uint8 *pattern0,*pattern1; //pattern table bitmap arrays
+uint8 *ppuv_palette;
+static int pindex0=0,pindex1=0;
+int PPUViewScanline=0,PPUViewer=0;
+int PPUViewSkip,PPUViewRefresh;
+int mouse_x,mouse_y;
+
+#define PATTERNWIDTH 128
+#define PATTERNHEIGHT 128
+#define PATTERNBITWIDTH PATTERNWIDTH*3
+#define PATTERNDESTX 10
+#define PATTERNDESTY 15
+#define ZOOM 2
+
+#define PALETTEWIDTH 32*4*4
+#define PALETTEHEIGHT 32*2
+#define PALETTEBITWIDTH PALETTEWIDTH*3
+#define PALETTEDESTX 10
+#define PALETTEDESTY 327
+
+#define TBM_SETPOS (WM_USER+5)
+#define TBM_SETRANGE (WM_USER+6)
+#define TBM_GETPOS (WM_USER)
+
+BITMAPINFO bmInfo;
+HDC pDC,TmpDC0,TmpDC1;
+HBITMAP TmpBmp0,TmpBmp1;
+HGDIOBJ TmpObj0,TmpObj1;
+
+BITMAPINFO bmInfo2;
+HDC TmpDC2,TmpDC3;
+HBITMAP TmpBmp2,TmpBmp3;
+HGDIOBJ TmpObj2,TmpObj3;
+
+
+void PPUViewDoBlit() {
+ if(!hPPUView) return;
+ if(PPUViewSkip < PPUViewRefresh) {
+ PPUViewSkip++;
+ return;
+ }
+ PPUViewSkip=0;
+
+ StretchBlt(pDC,PATTERNDESTX,PATTERNDESTY,PATTERNWIDTH*ZOOM,PATTERNHEIGHT*ZOOM,TmpDC0,0,PATTERNHEIGHT-1,PATTERNWIDTH,-PATTERNHEIGHT,SRCCOPY);
+ StretchBlt(pDC,PATTERNDESTX+(PATTERNWIDTH*ZOOM)+1,PATTERNDESTY,PATTERNWIDTH*ZOOM,PATTERNHEIGHT*ZOOM,TmpDC1,0,PATTERNHEIGHT-1,PATTERNWIDTH,-PATTERNHEIGHT,SRCCOPY);
+ StretchBlt(pDC,PALETTEDESTX,PALETTEDESTY,PALETTEWIDTH,PALETTEHEIGHT,TmpDC2,0,PALETTEHEIGHT-1,PALETTEWIDTH,-PALETTEHEIGHT,SRCCOPY);
+}
+
+void DrawPatternTable(uint8 *bitmap, uint8 *table, uint8 pal) {
+ int i,j,x,y,index=0;
+ int p=0,tmp;
+ uint8 chr0,chr1;
+ uint8 *pbitmap = bitmap;
+
+ pal <<= 2;
+ for (i = 0; i < 16; i++) {
+ for (j = 0; j < 16; j++) {
+ for (y = 0; y < 8; y++) {
+ chr0 = table[index];
+ chr1 = table[index+8];
+ tmp=7;
+ for (x = 0; x < 8; x++) {
+ p = (chr0>>tmp)&1;
+ p |= ((chr1>>tmp)&1)<<1;
+ p = palcache[p|pal];
+ tmp--;
+
+ *(uint8*)(pbitmap++) = palo[p].b;
+ *(uint8*)(pbitmap++) = palo[p].g;
+ *(uint8*)(pbitmap++) = palo[p].r;
+ }
+ index++;
+ pbitmap += ((PALETTEBITWIDTH>>2)-24);
+ }
+ index+=8;
+ pbitmap -= (((PALETTEBITWIDTH>>2)<<3)-24);
+ }
+ pbitmap += ((PALETTEBITWIDTH>>2)*7);
+ }
+
+}
+
+void UpdatePPUView(int refreshchr) {
+ int x,y,i;
+ uint8 *pbitmap = ppuv_palette;
+
+ if(!hPPUView) return;
+ if(PPUViewSkip < PPUViewRefresh) return;
+
+ if(refreshchr) {
+ for (i = 0, x=0x1000; i < 0x1000; i++, x++) {
+ chrcache0[i] = VPage[i>>10][i];
+ chrcache1[i] = VPage[x>>10][x];
+ }
+ }
+
+ //update palette only if required
+ if(memcmp(palcache,PALRAM,32) != 0) { //bbit note: let para know that this if is useless and
+ //cache palette content will not work because of the lines below that change
+ memcpy(palcache,PALRAM,32); //palcache which will make it not equal next time
+ palcache[0x10] = palcache[0x00];
+ palcache[0x14] = palcache[0x00];
+ palcache[0x18] = palcache[0x00];
+ palcache[0x1C] = palcache[0x00];
+
+ //draw palettes
+ for (y = 0; y < PALETTEHEIGHT; y++) {
+ for (x = 0; x < PALETTEWIDTH; x++) {
+ i = (((y>>5)<<4)+(x>>5));
+ *(uint8*)(pbitmap++) = palo[palcache[i]].b;
+ *(uint8*)(pbitmap++) = palo[palcache[i]].g;
+ *(uint8*)(pbitmap++) = palo[palcache[i]].r;
+ }
+ }
+
+ //draw line seperators on palette
+ pbitmap = (ppuv_palette+PALETTEBITWIDTH*31);
+ for (x = 0; x < PALETTEWIDTH*2; x++) {
+ *(uint8*)(pbitmap++) = 0;
+ *(uint8*)(pbitmap++) = 0;
+ *(uint8*)(pbitmap++) = 0;
+ }
+ pbitmap = (ppuv_palette-3);
+ for (y = 0; y < 64*3; y++) {
+ if(!(y%3)) pbitmap += (32*4*3);
+ for (x = 0; x < 6; x++) {
+ *(uint8*)(pbitmap++) = 0;
+ }
+ pbitmap += ((32*4*3)-6);
+ }
+ memcpy(palcache,PALRAM,32); //palcache which will make it not equal next time
+ }
+
+ DrawPatternTable(pattern0,chrcache0,pindex0);
+ DrawPatternTable(pattern1,chrcache1,pindex1);
+
+ //PPUViewDoBlit();
+}
+
+void KillPPUView() {
+ //GDI cleanup
+ DeleteObject(TmpBmp0);
+ SelectObject(TmpDC0,TmpObj0);
+ DeleteDC(TmpDC0);
+ DeleteObject(TmpBmp1);
+ SelectObject(TmpDC1,TmpObj1);
+ DeleteDC(TmpDC1);
+ DeleteObject(TmpBmp2);
+ SelectObject(TmpDC2,TmpObj2);
+ DeleteDC(TmpDC2);
+ ReleaseDC(hPPUView,pDC);
+
+ DestroyWindow(hPPUView);
+ hPPUView=NULL;
+ PPUViewer=0;
+ PPUViewSkip=0;
+}
+
+extern void StopSound(void);
+
+BOOL CALLBACK PPUViewCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+ RECT wrect;
+ char str[20];
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ SetWindowPos(hwndDlg,0,PPUViewPosX,PPUViewPosY,0,0,SWP_NOSIZE|SWP_NOZORDER|SWP_NOOWNERZORDER);
+
+ //prepare the bitmap attributes
+ //pattern tables
+ memset(&bmInfo.bmiHeader,0,sizeof(BITMAPINFOHEADER));
+ bmInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmInfo.bmiHeader.biWidth = PATTERNWIDTH;
+ bmInfo.bmiHeader.biHeight = PATTERNHEIGHT;
+ bmInfo.bmiHeader.biPlanes = 1;
+ bmInfo.bmiHeader.biBitCount = 24;
+
+ //palettes
+ memset(&bmInfo2.bmiHeader,0,sizeof(BITMAPINFOHEADER));
+ bmInfo2.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmInfo2.bmiHeader.biWidth = PALETTEWIDTH;
+ bmInfo2.bmiHeader.biHeight = PALETTEHEIGHT;
+ bmInfo2.bmiHeader.biPlanes = 1;
+ bmInfo2.bmiHeader.biBitCount = 24;
+
+ //create memory dcs
+ pDC = GetDC(hwndDlg); // GetDC(GetDlgItem(hwndDlg,101));
+ TmpDC0 = CreateCompatibleDC(pDC); //pattern table 0
+ TmpDC1 = CreateCompatibleDC(pDC); //pattern table 1
+ TmpDC2 = CreateCompatibleDC(pDC); //palettes
+
+ //create bitmaps and select them into the memory dc's
+ TmpBmp0 = CreateDIBSection(pDC,&bmInfo,DIB_RGB_COLORS,(void**)&pattern0,0,0);
+ TmpObj0 = SelectObject(TmpDC0,TmpBmp0);
+ TmpBmp1 = CreateDIBSection(pDC,&bmInfo,DIB_RGB_COLORS,(void**)&pattern1,0,0);
+ TmpObj1 = SelectObject(TmpDC1,TmpBmp1);
+ TmpBmp2 = CreateDIBSection(pDC,&bmInfo2,DIB_RGB_COLORS,(void**)&ppuv_palette,0,0);
+ TmpObj2 = SelectObject(TmpDC2,TmpBmp2);
+
+ //Refresh Trackbar
+ SendDlgItemMessage(hwndDlg,201,TBM_SETRANGE,0,(LPARAM)MAKELONG(0,25));
+ SendDlgItemMessage(hwndDlg,201,TBM_SETPOS,1,PPUViewRefresh);
+
+ //Set Text Limit
+ SendDlgItemMessage(hwndDlg,102,EM_SETLIMITTEXT,3,0);
+
+ //force redraw the first time the PPU Viewer is opened
+ PPUViewSkip=100;
+
+ //clear cache
+ memset(palcache,0,32);
+ memset(chrcache0,0,0x1000);
+ memset(chrcache1,0,0x1000);
+
+ PPUViewer=1;
+ break;
+ case WM_PAINT:
+ PPUViewDoBlit();
+ break;
+ case WM_CLOSE:
+ case WM_QUIT:
+ KillPPUView();
+ break;
+ case WM_MOVING:
+ StopSound();
+ break;
+ case WM_MOVE:
+ GetWindowRect(hwndDlg,&wrect);
+ PPUViewPosX = wrect.left;
+ PPUViewPosY = wrect.top;
+ break;
+ case WM_RBUTTONDBLCLK:
+ case WM_RBUTTONDOWN:
+ mouse_x = GET_X_LPARAM(lParam);
+ mouse_y = GET_Y_LPARAM(lParam);
+ if(((mouse_x >= PATTERNDESTX) && (mouse_x < (PATTERNDESTX+(PATTERNWIDTH*ZOOM)))) && (mouse_y >= PATTERNDESTY) && (mouse_y < (PATTERNDESTY+(PATTERNHEIGHT*ZOOM)))) {
+ if(pindex0 == 7) pindex0 = 0;
+ else pindex0++;
+ }
+ else if(((mouse_x >= PATTERNDESTX+(PATTERNWIDTH*ZOOM)+1) && (mouse_x < (PATTERNDESTX+(PATTERNWIDTH*ZOOM)*2+1))) && (mouse_y >= PATTERNDESTY) && (mouse_y < (PATTERNDESTY+(PATTERNHEIGHT*ZOOM)))) {
+ if(pindex1 == 7) pindex1 = 0;
+ else pindex1++;
+ }
+ UpdatePPUView(0);
+ PPUViewDoBlit();
+ break;
+ case WM_MOUSEMOVE:
+ mouse_x = GET_X_LPARAM(lParam);
+ mouse_y = GET_Y_LPARAM(lParam);
+ if(((mouse_x >= PATTERNDESTX) && (mouse_x < (PATTERNDESTX+(PATTERNWIDTH*ZOOM)))) && (mouse_y >= PATTERNDESTY) && (mouse_y < (PATTERNDESTY+(PATTERNHEIGHT*ZOOM)))) {
+ mouse_x = (mouse_x-PATTERNDESTX)/(8*ZOOM);
+ mouse_y = (mouse_y-PATTERNDESTY)/(8*ZOOM);
+ sprintf(str,"Tile: $%X%X",mouse_y,mouse_x);
+ SetDlgItemText(hwndDlg,103,str);
+ SetDlgItemText(hwndDlg,104,"Tile:");
+ SetDlgItemText(hwndDlg,105,"Palettes");
+ }
+ else if(((mouse_x >= PATTERNDESTX+(PATTERNWIDTH*ZOOM)+1) && (mouse_x < (PATTERNDESTX+(PATTERNWIDTH*ZOOM)*2+1))) && (mouse_y >= PATTERNDESTY) && (mouse_y < (PATTERNDESTY+(PATTERNHEIGHT*ZOOM)))) {
+ mouse_x = (mouse_x-(PATTERNDESTX+(PATTERNWIDTH*ZOOM)+1))/(8*ZOOM);
+ mouse_y = (mouse_y-PATTERNDESTY)/(8*ZOOM);
+ sprintf(str,"Tile: $%X%X",mouse_y,mouse_x);
+ SetDlgItemText(hwndDlg,104,str);
+ SetDlgItemText(hwndDlg,103,"Tile:");
+ SetDlgItemText(hwndDlg,105,"Palettes");
+ }
+ else if(((mouse_x >= PALETTEDESTX) && (mouse_x < (PALETTEDESTX+PALETTEWIDTH))) && (mouse_y >= PALETTEDESTY) && (mouse_y < (PALETTEDESTY+PALETTEHEIGHT))) {
+ mouse_x = (mouse_x-PALETTEDESTX)/32;
+ mouse_y = (mouse_y-PALETTEDESTY)/32;
+ sprintf(str,"Palette: $%02X",palcache[(mouse_y<<4)|mouse_x]);
+ SetDlgItemText(hwndDlg,103,"Tile:");
+ SetDlgItemText(hwndDlg,104,"Tile:");
+ SetDlgItemText(hwndDlg,105,str);
+ }
+ else {
+ SetDlgItemText(hwndDlg,103,"Tile:");
+ SetDlgItemText(hwndDlg,104,"Tile:");
+ SetDlgItemText(hwndDlg,105,"Palettes");
+ }
+
+ break;
+ case WM_NCACTIVATE:
+ sprintf(str,"%d",PPUViewScanline);
+ SetDlgItemText(hwndDlg,102,str);
+ break;
+ case WM_COMMAND:
+ switch(HIWORD(wParam)) {
+ case EN_UPDATE:
+ GetDlgItemText(hwndDlg,102,str,4);
+ sscanf(str,"%d",&PPUViewScanline);
+ if(PPUViewScanline > 239) PPUViewScanline = 239;
+ break;
+ }
+ break;
+ case WM_HSCROLL:
+ if(lParam) { //refresh trackbar
+ PPUViewRefresh = SendDlgItemMessage(hwndDlg,201,TBM_GETPOS,0,0);
+ }
+ break;
+ }
+ return FALSE;
+}
+
+void DoPPUView() {
+ if(!GI) {
+ FCEUD_PrintError("You must have a game loaded before you can use the PPU Viewer.");
+ return;
+ }
+ if(GI->type==GIT_NSF) {
+ FCEUD_PrintError("Sorry, you can't use the PPU Viewer with NSFs.");
+ return;
+ }
+
+ if(!hPPUView) hPPUView = CreateDialog(fceu_hInstance,"PPUVIEW",NULL,PPUViewCallB);
+ if(hPPUView) {
+ SetWindowPos(hPPUView,HWND_TOP,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE|SWP_NOOWNERZORDER);
+ UpdatePPUView(1);
+ PPUViewDoBlit();
+ }
+}
diff --git a/drivers/win/ppuview.h b/drivers/win/ppuview.h
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/drivers/win/ppuview.h
diff --git a/drivers/win/res.res b/drivers/win/res.res
new file mode 100644
index 00000000..00f59af4
--- /dev/null
+++ b/drivers/win/res.res
Binary files differ
diff --git a/drivers/win/sound.c b/drivers/win/sound.c
new file mode 100644
index 00000000..cd3949c9
--- /dev/null
+++ b/drivers/win/sound.c
@@ -0,0 +1,665 @@
+/* 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
+ */
+
+
+LPDIRECTSOUND ppDS=0; /* DirectSound object. */
+LPDIRECTSOUNDBUFFER ppbuf=0; /* Primary buffer object. */
+LPDIRECTSOUNDBUFFER ppbufsec=0; /* Secondary buffer object. */
+LPDIRECTSOUNDBUFFER ppbufw; /* Buffer to actually write to. */
+
+long DSBufferSize; /* The size of the buffer that we can write to, in bytes. */
+
+long BufHowMuch; /* How many bytes we should try to buffer. */
+DWORD ToWritePos; /* Position which the next write to the buffer
+ should write to.
+ */
+
+
+
+DSBUFFERDESC DSBufferDesc;
+WAVEFORMATEX wfa;
+WAVEFORMATEX wf;
+
+int bittage;
+static int mute=0; /* TODO: add to config? add to GUI. */
+
+void TrashSound(void)
+{
+ FCEUI_Sound(0);
+ if(ppbufsec)
+ {
+ IDirectSoundBuffer_Stop(ppbufsec);
+ IDirectSoundBuffer_Release(ppbufsec);
+ ppbufsec=0;
+ }
+ if(ppbuf)
+ {
+ IDirectSoundBuffer_Stop(ppbuf);
+ IDirectSoundBuffer_Release(ppbuf);
+ ppbuf=0;
+ }
+ if(ppDS)
+ {
+ IDirectSound_Release(ppDS);
+ ppDS=0;
+ }
+}
+
+void CheckDStatus(void)
+{
+ DWORD status;
+ status=0;
+ IDirectSoundBuffer_GetStatus(ppbufw, &status);
+
+ if(status&DSBSTATUS_BUFFERLOST)
+ {
+ IDirectSoundBuffer_Restore(ppbufw);
+ }
+
+ if(!(status&DSBSTATUS_PLAYING))
+ {
+ ToWritePos=0;
+ IDirectSoundBuffer_SetFormat(ppbufw,&wf);
+ IDirectSoundBuffer_Play(ppbufw,0,0,DSBPLAY_LOOPING);
+ }
+}
+
+static uint32_t RawCanWrite(void)
+{
+ DWORD CurWritePos,CurPlayPos=0;
+
+ CheckDStatus();
+
+ CurWritePos=0;
+
+ if(IDirectSoundBuffer_GetCurrentPosition(ppbufw,&CurPlayPos,&CurWritePos)==DS_OK)
+ {
+// FCEU_DispMessage("%8d",(CurWritePos-CurPlayPos));
+ }
+ CurWritePos=(CurPlayPos+BufHowMuch)%DSBufferSize;
+
+ /* If the current write pos is >= half the buffer size less than the to write pos,
+ assume DirectSound has wrapped around.
+ */
+
+ if(((int32_t)ToWritePos-(int32_t)CurWritePos) >= (DSBufferSize/2))
+ {
+ CurWritePos+=DSBufferSize;
+ //FCEU_printf("Fixit: %d,%d,%d\n",ToWritePos,CurWritePos,CurWritePos-DSBufferSize);
+ }
+ if(ToWritePos<CurWritePos)
+ {
+ int32_t howmuch=(int32_t)CurWritePos-(int32_t)ToWritePos;
+ if(howmuch > BufHowMuch) /* Oopsie. Severe buffer overflow... */
+ {
+ //FCEU_printf("Ack");
+ ToWritePos=CurWritePos%DSBufferSize;
+ }
+ return(CurWritePos-ToWritePos);
+ }
+ else
+ return(0);
+}
+
+int32 GetWriteSound(void)
+{
+ if(!soundo)
+ return 0;
+ return(RawCanWrite() >> bittage);
+}
+
+int32 GetMaxSound(void)
+{
+ return( BufHowMuch >> bittage);
+}
+
+static int RawWrite(void *data, uint32_t len)
+{
+ uint32_t cw;
+
+ //printf("Pre: %d\n",SexyALI_DSound_RawCanWrite(device));
+ //fflush(stdout);
+
+ if(!soundo)
+ return 0;
+
+ CheckDStatus();
+ /* In this block, we write as much data as we can, then we write
+ the rest of it in >=1ms chunks.
+ */
+ while(len)
+ {
+ VOID *LockPtr[2]={0,0};
+ DWORD LockLen[2]={0,0};
+ int32_t curlen;
+
+ // THIS LIMITS THE EMULATION SPEED
+ if((!NoWaiting) || (soundoptions&SO_OLDUP))
+ while(!(curlen=RawCanWrite()))
+ {
+ Sleep(1);
+ }
+
+ if(curlen>len) curlen=len;
+
+ if(DS_OK == IDirectSoundBuffer_Lock(ppbufw,ToWritePos,curlen,&LockPtr[0],&LockLen[0],&LockPtr[1],&LockLen[1],0))
+ {
+ }
+
+ if(LockPtr[1] != 0 && LockPtr[1] != LockPtr[0])
+ {
+ if(mute)
+ {
+ if(bittage)
+ {
+ memset(LockPtr[0], 0, LockLen[0]);
+ memset(LockPtr[1], 0, len-LockLen[0]);
+ }
+ else
+ {
+ memset(LockPtr[0], 0x80, LockLen[0]);
+ memset(LockPtr[1], 0x80, len-LockLen[0]);
+ }
+ }
+ else
+ {
+ /* not mute */
+ memcpy(LockPtr[0],data,LockLen[0]);
+ memcpy(LockPtr[1],data+LockLen[0],len-LockLen[0]);
+ }
+ }
+ else if(LockPtr[0])
+ {
+ if(mute)
+ {
+ if(bittage)
+ memset(LockPtr[0], 0, curlen);
+ else
+ memset(LockPtr[0], 0x80, curlen);
+ }
+ else
+ {
+ /* not mute */
+ memcpy(LockPtr[0],data,curlen);
+ }
+ }
+ IDirectSoundBuffer_Unlock(ppbufw,LockPtr[0],LockLen[0],LockPtr[1],LockLen[1]);
+ ToWritePos=(ToWritePos+curlen)%DSBufferSize;
+
+ len-=curlen;
+ (uint8_t *) data+=curlen;
+
+ if(len && !NoWaiting && (fps_scale <= 256 || (soundoptions&SO_OLDUP)))
+ Sleep(1); // do some extra sleeping if we think there's time and we're not scaling up the FPS or in turbo mode
+
+ } // end while(len) loop
+
+
+ return(1);
+}
+
+int silencer=0;
+
+int FCEUD_WriteSoundData(int32 *Buffer, int scale, int Count)
+{
+#define WSD_BUFSIZE (2 * 96000 / 50)
+
+ int P;
+ int iCount=0;
+ static int16 MBuffer[WSD_BUFSIZE*2];
+
+ if(!(soundoptions&SO_OLDUP))
+ {
+ if(FCEUI_EmulationPaused())
+ memset(MBuffer, 0, WSD_BUFSIZE); // slow and/or unnecessary
+
+ if(FCEUI_EmulationPaused()) scale >>= 1;
+
+ // limit frequency change to between 50% and 200%
+ if(scale > 512) scale = 512;
+ if(scale < 128) scale = 128;
+ }
+
+// for(;Count>0;Count-=WSD_BUFSIZE)
+ {
+ int amt = (soundoptions&SO_OLDUP) ? Count : (Count > WSD_BUFSIZE ? WSD_BUFSIZE : Count);
+
+ if(!bittage)
+ {
+ if(silencer)
+ for(P=0;P<amt;P++)
+ *(((uint8*)MBuffer)+P)=((int8)(Buffer[0]>>8))^128;
+ else if(scale == 256) // exactly 100% speed
+ for(P=0;P<amt;P++)
+ *(((uint8*)MBuffer)+P)=((int8)(Buffer[P]>>8))^128;
+ else // change sound frequency
+ for(P=0;P<amt;P++)
+ *(((uint8*)MBuffer)+P)=((int8)(Buffer[P*scale/256]>>8))^128;
+
+ RawWrite(MBuffer,amt);
+ }
+ else // force 8-bit sound is off:
+ {
+ if(silencer)
+ for(P=0;P<amt;P++)
+ MBuffer[P]=Buffer[0];
+ else if(scale == 256) // exactly 100% speed
+ for(P=0;P<amt;P++)
+ MBuffer[P]=Buffer[P];
+ else // change sound frequency
+ for(P=0;P<amt;P++)
+ MBuffer[P]=Buffer[P*scale/256];
+
+ RawWrite(MBuffer,amt * 2);
+ }
+
+ iCount+=amt;
+ }
+
+ // FCEUI_AviSoundUpdate((void*)MBuffer, Count);
+ return iCount;
+}
+
+int InitSound()
+{
+ DSCAPS dscaps;
+ DSBCAPS dsbcaps;
+
+ memset(&wf,0x00,sizeof(wf));
+ wf.wFormatTag = WAVE_FORMAT_PCM;
+ wf.nChannels = 1;
+ wf.nSamplesPerSec = soundrate;
+
+ ddrval=DirectSoundCreate(0,&ppDS,0);
+ if (ddrval != DS_OK)
+ {
+ FCEUD_PrintError("DirectSound: Error creating DirectSound object.");
+ return 0;
+ }
+
+ if(soundoptions&SO_SECONDARY)
+ {
+ trysecondary:
+ ddrval=IDirectSound_SetCooperativeLevel(ppDS,hAppWnd,DSSCL_PRIORITY);
+ if (ddrval != DS_OK)
+ {
+ FCEUD_PrintError("DirectSound: Error setting cooperative level to DDSCL_PRIORITY.");
+ TrashSound();
+ return 0;
+ }
+ }
+ else
+ {
+ ddrval=IDirectSound_SetCooperativeLevel(ppDS,hAppWnd,DSSCL_WRITEPRIMARY);
+ if (ddrval != DS_OK)
+ {
+ FCEUD_PrintError("DirectSound: Error setting cooperative level to DDSCL_WRITEPRIMARY. Forcing use of secondary sound buffer and trying again...");
+ soundoptions|=SO_SECONDARY;
+ goto trysecondary;
+ }
+ }
+ memset(&dscaps,0x00,sizeof(dscaps));
+ dscaps.dwSize=sizeof(dscaps);
+ ddrval=IDirectSound_GetCaps(ppDS,&dscaps);
+ if(ddrval!=DS_OK)
+ {
+ FCEUD_PrintError("DirectSound: Error getting capabilities.");
+ return 0;
+ }
+
+ if(dscaps.dwFlags&DSCAPS_EMULDRIVER)
+ FCEUD_PrintError("DirectSound: Sound device is being emulated through waveform-audio functions. Sound quality will most likely be awful. Try to update your sound device's sound drivers.");
+
+ IDirectSound_Compact(ppDS);
+
+ memset(&DSBufferDesc,0x00,sizeof(DSBUFFERDESC));
+ DSBufferDesc.dwSize=sizeof(DSBufferDesc);
+ if(soundoptions&SO_SECONDARY)
+ DSBufferDesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
+ else
+ DSBufferDesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_GETCURRENTPOSITION2;
+
+ ddrval=IDirectSound_CreateSoundBuffer(ppDS,&DSBufferDesc,&ppbuf,0);
+ if (ddrval != DS_OK)
+ {
+ FCEUD_PrintError("DirectSound: Error creating primary buffer.");
+ TrashSound();
+ return 0;
+ }
+
+ memset(&wfa,0x00,sizeof(wfa));
+
+ if(soundoptions&SO_FORCE8BIT)
+ bittage=0;
+ else
+ {
+ bittage=1;
+ if( (!(dscaps.dwFlags&DSCAPS_PRIMARY16BIT) && !(soundoptions&SO_SECONDARY)) ||
+ (!(dscaps.dwFlags&DSCAPS_SECONDARY16BIT) && (soundoptions&SO_SECONDARY)))
+ {
+ FCEUD_PrintError("DirectSound: 16-bit sound is not supported. Forcing 8-bit sound.");
+ bittage=0;
+ soundoptions|=SO_FORCE8BIT;
+ }
+ }
+
+ wf.wBitsPerSample=8<<bittage;
+ wf.nBlockAlign = bittage+1;
+ wf.nAvgBytesPerSec = wf.nSamplesPerSec * wf.nBlockAlign;
+
+ ddrval=IDirectSoundBuffer_SetFormat(ppbuf,&wf);
+ if (ddrval != DS_OK)
+ {
+ FCEUD_PrintError("DirectSound: Error setting primary buffer format.");
+ TrashSound();
+ return 0;
+ }
+
+ IDirectSoundBuffer_GetFormat(ppbuf,&wfa,sizeof(wfa),0);
+
+ if(soundoptions&SO_SECONDARY)
+ {
+ memset(&DSBufferDesc,0x00,sizeof(DSBUFFERDESC));
+ DSBufferDesc.dwSize=sizeof(DSBufferDesc);
+ DSBufferDesc.dwFlags=DSBCAPS_GETCURRENTPOSITION2;
+ if(soundoptions&SO_GFOCUS)
+ DSBufferDesc.dwFlags|=DSBCAPS_GLOBALFOCUS;
+ DSBufferDesc.dwBufferBytes=65536;
+ DSBufferDesc.lpwfxFormat=&wfa;
+ ddrval=IDirectSound_CreateSoundBuffer(ppDS, &DSBufferDesc, &ppbufsec, 0);
+ if (ddrval != DS_OK)
+ {
+ FCEUD_PrintError("DirectSound: Error creating secondary buffer.");
+ TrashSound();
+ return 0;
+ }
+ }
+
+ //sprintf(TempArray,"%d\n",wfa.nSamplesPerSec);
+ //FCEUD_PrintError(TempArray);
+
+ if(soundoptions&SO_SECONDARY)
+ {
+ DSBufferSize=65536;
+ IDirectSoundBuffer_SetCurrentPosition(ppbufsec,0);
+ ppbufw=ppbufsec;
+ }
+ else
+ {
+ memset(&dsbcaps,0,sizeof(dsbcaps));
+ dsbcaps.dwSize=sizeof(dsbcaps);
+ ddrval=IDirectSoundBuffer_GetCaps(ppbuf,&dsbcaps);
+ if (ddrval != DS_OK)
+ {
+ FCEUD_PrintError("DirectSound: Error getting buffer capabilities.");
+ TrashSound();
+ return 0;
+ }
+
+ DSBufferSize=dsbcaps.dwBufferBytes;
+
+ if(DSBufferSize<8192)
+ {
+ FCEUD_PrintError("DirectSound: Primary buffer size is too small!");
+ TrashSound();
+ return 0;
+ }
+ ppbufw=ppbuf;
+ }
+
+ BufHowMuch=(soundbuftime*soundrate/1000)<<bittage;
+ FCEUI_Sound(soundrate);
+ return 1;
+}
+
+static HWND uug=0;
+
+static void UpdateSD(HWND hwndDlg)
+{
+ int t;
+
+ CheckDlgButton(hwndDlg,126,soundo?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,122,(soundoptions&SO_FORCE8BIT)?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,123,(soundoptions&SO_SECONDARY)?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,124,(soundoptions&SO_GFOCUS)?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,130,(soundoptions&SO_MUTEFA)?BST_CHECKED:BST_UNCHECKED);
+ CheckDlgButton(hwndDlg,131,(soundoptions&SO_OLDUP)?BST_CHECKED:BST_UNCHECKED);
+ SendDlgItemMessage(hwndDlg,129,CB_SETCURSEL,soundquality,(LPARAM)(LPSTR)0);
+ t=0;
+ if(soundrate==22050) t=1;
+ else if(soundrate==44100) t=2;
+ else if(soundrate==48000) t=3;
+ else if(soundrate==96000) t=4;
+ SendDlgItemMessage(hwndDlg,200,CB_SETCURSEL,t,(LPARAM)(LPSTR)0);
+}
+
+BOOL CALLBACK SoundConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+
+ switch(uMsg) {
+ case WM_NCRBUTTONDOWN:
+ case WM_NCMBUTTONDOWN:
+ case WM_NCLBUTTONDOWN:StopSound();break;
+
+ case WM_INITDIALOG:
+ /* Volume Trackbar */
+ SendDlgItemMessage(hwndDlg,500,TBM_SETRANGE,1,MAKELONG(0,150));
+ SendDlgItemMessage(hwndDlg,500,TBM_SETTICFREQ,25,0);
+ SendDlgItemMessage(hwndDlg,500,TBM_SETPOS,1,150-soundvolume);
+
+ /* buffer size time trackbar */
+ SendDlgItemMessage(hwndDlg,128,TBM_SETRANGE,1,MAKELONG(15,200));
+ SendDlgItemMessage(hwndDlg,128,TBM_SETTICFREQ,1,0);
+ SendDlgItemMessage(hwndDlg,128,TBM_SETPOS,1,soundbuftime);
+
+ {
+ char tbuf[8];
+ sprintf(tbuf,"%d",soundbuftime);
+ SetDlgItemText(hwndDlg,666,(LPTSTR)tbuf);
+ }
+
+ SendDlgItemMessage(hwndDlg,129,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Low");
+ SendDlgItemMessage(hwndDlg,129,CB_ADDSTRING,0,(LPARAM)(LPSTR)"High");
+ SendDlgItemMessage(hwndDlg,129,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Highest");
+
+ SendDlgItemMessage(hwndDlg,200,CB_ADDSTRING,0,(LPARAM)(LPSTR)"11025");
+ SendDlgItemMessage(hwndDlg,200,CB_ADDSTRING,0,(LPARAM)(LPSTR)"22050");
+ SendDlgItemMessage(hwndDlg,200,CB_ADDSTRING,0,(LPARAM)(LPSTR)"44100");
+ SendDlgItemMessage(hwndDlg,200,CB_ADDSTRING,0,(LPARAM)(LPSTR)"48000");
+ SendDlgItemMessage(hwndDlg,200,CB_ADDSTRING,0,(LPARAM)(LPSTR)"96000");
+
+ UpdateSD(hwndDlg);
+ break;
+ case WM_VSCROLL:
+ soundvolume=150-SendDlgItemMessage(hwndDlg,500,TBM_GETPOS,0,0);
+ FCEUI_SetSoundVolume(soundvolume);
+ break;
+ case WM_HSCROLL:
+ {
+ char tbuf[8];
+ soundbuftime=SendDlgItemMessage(hwndDlg,128,TBM_GETPOS,0,0);
+ sprintf(tbuf,"%d",soundbuftime);
+ SetDlgItemText(hwndDlg,666,(LPTSTR)tbuf);
+ BufHowMuch=(soundbuftime*soundrate/1000)<<bittage;
+ //soundbufsize=(soundbuftime*soundrate/1000);
+ }
+ break;
+ case WM_CLOSE:
+ case WM_QUIT: goto gornk;
+ case WM_COMMAND:
+ switch(HIWORD(wParam))
+ {
+ case CBN_SELENDOK:
+ switch(LOWORD(wParam))
+ {
+ case 200:
+ {
+ int tmp;
+ tmp=SendDlgItemMessage(hwndDlg,200,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
+ if(tmp==0) tmp=11025;
+ else if(tmp==1) tmp=22050;
+ else if(tmp==2) tmp=44100;
+ else if(tmp==3) tmp=48000;
+ else tmp=96000;
+ if(tmp!=soundrate)
+ {
+ soundrate=tmp;
+ if(soundrate<44100)
+ {
+ soundquality=0;
+ FCEUI_SetSoundQuality(0);
+ UpdateSD(hwndDlg);
+ }
+ if(soundo)
+ {
+ TrashSound();
+ soundo=InitSound();
+ UpdateSD(hwndDlg);
+ }
+ }
+ }
+ break;
+
+ case 129:
+ soundquality=SendDlgItemMessage(hwndDlg,129,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
+ if(soundrate<44100) soundquality=0;
+ FCEUI_SetSoundQuality(soundquality);
+ UpdateSD(hwndDlg);
+ break;
+ }
+ break;
+
+ case BN_CLICKED:
+ switch(LOWORD(wParam))
+ {
+ case 122:soundoptions^=SO_FORCE8BIT;
+ if(soundo)
+ {
+ TrashSound();
+ soundo=InitSound();
+ UpdateSD(hwndDlg);
+ }
+ break;
+ case 123:soundoptions^=SO_SECONDARY;
+ if(soundo)
+ {
+ TrashSound();
+ soundo=InitSound();
+ UpdateSD(hwndDlg);
+ }
+ break;
+ case 124:soundoptions^=SO_GFOCUS;
+ if(soundo)
+ {
+ TrashSound();
+ soundo=InitSound();
+ UpdateSD(hwndDlg);
+ }
+ break;
+ case 130:soundoptions^=SO_MUTEFA;
+ break;
+ case 131:soundoptions^=SO_OLDUP;
+ if(soundo)
+ {
+ TrashSound();
+ soundo=InitSound();
+ UpdateSD(hwndDlg);
+ }
+ break;
+ case 126:soundo=!soundo;
+ if(!soundo) TrashSound();
+ else soundo=InitSound();
+ UpdateSD(hwndDlg);
+ break;
+ }
+ }
+
+ if(!(wParam>>16))
+ switch(wParam&0xFFFF)
+ {
+ case 1:
+ gornk:
+ DestroyWindow(hwndDlg);
+ uug=0;
+ break;
+ }
+ }
+ return 0;
+}
+
+
+void ConfigSound(void)
+{
+ if(!uug)
+ uug=CreateDialog(fceu_hInstance,"SOUNDCONFIG",0,SoundConCallB);
+ else
+ SetFocus(uug);
+}
+
+
+void StopSound(void)
+{
+ if(soundo)
+ {
+ VOID *LockPtr=0;
+ DWORD LockLen=0;
+ if(DS_OK == IDirectSoundBuffer_Lock(ppbufw,0,DSBufferSize,&LockPtr,&LockLen,0,0,0))
+ {
+ //FCEUD_PrintError("K");
+ if(bittage)
+ memset(LockPtr, 0, LockLen);
+ else
+ memset(LockPtr, 0x80, LockLen);
+ IDirectSoundBuffer_Unlock(ppbufw,LockPtr,LockLen,0,0);
+ }
+
+ //IDirectSoundBuffer_Stop(ppbufw);
+ }
+}
+
+void FCEUD_SoundToggle(void)
+{
+ if(mute)
+ {
+ mute=0;
+ FCEU_DispMessage("Sound mute off.");
+ }
+ else
+ {
+ mute=1;
+ StopSound();
+ FCEU_DispMessage("Sound mute on.");
+ }
+}
+
+void FCEUD_SoundVolumeAdjust(int n)
+{
+ switch(n)
+ {
+ case -1: soundvolume-=10; if(soundvolume<0) soundvolume=0; break;
+ case 0: soundvolume=100; break;
+ case 1: soundvolume+=10; if(soundvolume>150) soundvolume=150; break;
+ }
+ mute=0;
+ FCEUI_SetSoundVolume(soundvolume);
+ FCEU_DispMessage("Sound volume %d.", soundvolume);
+}
+
+#include "wave.c"
diff --git a/drivers/win/state.c b/drivers/win/state.c
new file mode 100644
index 00000000..7e6ec504
--- /dev/null
+++ b/drivers/win/state.c
@@ -0,0 +1,40 @@
+void FCEUD_SaveStateAs(void)
+{
+ const char filter[]="FCE Ultra Save State(*.fc?)\0*.fc?\0";
+ char nameo[2048];
+ OPENFILENAME ofn;
+
+ StopSound();
+ memset(&ofn,0,sizeof(ofn));
+ ofn.lStructSize=sizeof(ofn);
+ ofn.hInstance=fceu_hInstance;
+ ofn.lpstrTitle="Save State As...";
+ ofn.lpstrFilter=filter;
+ nameo[0]=0;
+ ofn.lpstrFile=nameo;
+ ofn.nMaxFile=256;
+ ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
+ if(GetSaveFileName(&ofn))
+ FCEUI_SaveState(nameo);
+}
+
+void FCEUD_LoadStateFrom(void)
+{
+ const char filter[]="FCE Ultra Save State(*.fc?)\0*.fc?\0";
+ char nameo[2048];
+ OPENFILENAME ofn;
+
+ StopSound();
+ memset(&ofn,0,sizeof(ofn));
+ ofn.lStructSize=sizeof(ofn);
+ ofn.hInstance=fceu_hInstance;
+ ofn.lpstrTitle="Load State From...";
+ ofn.lpstrFilter=filter;
+ nameo[0]=0;
+ ofn.lpstrFile=nameo;
+ ofn.nMaxFile=256;
+ ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
+ if(GetOpenFileName(&ofn))
+ FCEUI_LoadState(nameo);
+}
+
diff --git a/drivers/win/throttle.c b/drivers/win/throttle.c
new file mode 100644
index 00000000..443194b4
--- /dev/null
+++ b/drivers/win/throttle.c
@@ -0,0 +1,146 @@
+/* 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
+ */
+
+static uint64 tmethod,tfreq;
+static uint64 desiredfps;
+
+static int32 fps_scale_table[]=
+{ 3, 3, 4, 8, 16, 32, 64, 128, 192, 256, 384, 512, 768, 1024, 2048, 4096, 8192, 16384, 16384};
+int32 fps_scale = 256;
+
+static void RefreshThrottleFPS(void)
+{
+ desiredfps=FCEUI_GetDesiredFPS()>>8;
+ desiredfps=(desiredfps*fps_scale)>>8;
+}
+
+static uint64 GetCurTime(void)
+{
+ if(tmethod)
+ {
+ uint64 tmp;
+
+ /* Practically, LARGE_INTEGER and uint64 differ only by signness and name. */
+ QueryPerformanceCounter((LARGE_INTEGER*)&tmp);
+
+ return(tmp);
+ }
+ else
+ return((uint64)GetTickCount());
+
+}
+
+static void InitSpeedThrottle(void)
+{
+ tmethod=0;
+ if(QueryPerformanceFrequency((LARGE_INTEGER*)&tfreq))
+ {
+ tmethod=1;
+ }
+ else
+ tfreq=1000;
+ tfreq<<=16; /* Adjustment for fps returned from FCEUI_GetDesiredFPS(). */
+}
+
+
+static int SpeedThrottle(void)
+{
+ static uint64 ttime,ltime;
+
+ waiter:
+
+ ttime=GetCurTime();
+
+ if( (ttime-ltime) < (tfreq/desiredfps) )
+ {
+ uint64 sleepy;
+ sleepy=(tfreq/desiredfps)-(ttime-ltime);
+ sleepy*=1000;
+ if(tfreq>=65536)
+ sleepy/=tfreq>>16;
+ else
+ sleepy=0;
+ if(sleepy>100)
+ {
+ // block for a max of 100ms to
+ // keep the gui responsive
+ Sleep(100);
+ return 1;
+ }
+ Sleep(sleepy);
+ goto waiter;
+ }
+ if( (ttime-ltime) >= (tfreq*4/desiredfps))
+ ltime=ttime;
+ else
+ {
+ ltime+=tfreq/desiredfps;
+
+ if( (ttime-ltime) >= (tfreq/desiredfps) ) // Oops, we're behind!
+ return(1);
+ }
+ return(0);
+}
+
+// Quick code for internal FPS display.
+uint64 FCEUD_GetTime(void)
+{
+ return(GetCurTime());
+}
+uint64 FCEUD_GetTimeFreq(void)
+{
+ return(tfreq>>16);
+}
+
+static void IncreaseEmulationSpeed(void)
+{
+ int i;
+ for(i=1; fps_scale_table[i]<fps_scale; i++)
+ ;
+ fps_scale = fps_scale_table[i+1];
+}
+
+static void DecreaseEmulationSpeed(void)
+{
+ int i;
+ for(i=1; fps_scale_table[i]<fps_scale; i++)
+ ;
+ fps_scale = fps_scale_table[i-1];
+}
+
+#define fps_table_size (sizeof(fps_scale_table)/sizeof(fps_scale_table[0]))
+
+void FCEUD_SetEmulationSpeed(int cmd)
+{
+ switch(cmd)
+ {
+ case EMUSPEED_SLOWEST: fps_scale=fps_scale_table[0]; break;
+ case EMUSPEED_SLOWER: DecreaseEmulationSpeed(); break;
+ case EMUSPEED_NORMAL: fps_scale=256; break;
+ case EMUSPEED_FASTER: IncreaseEmulationSpeed(); break;
+ case EMUSPEED_FASTEST: fps_scale=fps_scale_table[fps_table_size-1]; break;
+ default:
+ return;
+ }
+
+ RefreshThrottleFPS();
+
+ FCEU_DispMessage("emulation speed %d%%",(fps_scale*100)>>8);
+}
diff --git a/drivers/win/video.c b/drivers/win/video.c
new file mode 100644
index 00000000..ec3b1890
--- /dev/null
+++ b/drivers/win/video.c
@@ -0,0 +1,1125 @@
+/* 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
+ */
+
+static int RecalcCustom(void);
+
+#define VF_DDSTRETCHED 1
+
+#define VEF_LOSTSURFACE 1
+#define VEF____INTERNAL 2
+
+#define VMDF_DXBLT 1
+#define VMDF_STRFS 2
+
+typedef struct {
+ int x;
+ int y;
+ int bpp;
+ int flags;
+ int xscale;
+ int yscale;
+ RECT srect;
+ RECT drect;
+ int special;
+} vmdef;
+
+// left, top, right, bottom
+static vmdef vmodes[11]={
+ {320,240,8,0,1,1,0}, //0
+ {320,240,8,0,1,1,0}, //1
+ {512,384,8,0,1,1,0}, //2
+ {640,480,8,0,1,1,0}, //3
+ {640,480,8,0,1,1,0}, //4
+ {640,480,8,0,1,1,0}, //5
+ {640,480,8,VMDF_DXBLT,2,2,0}, //6
+ {1024,768,8,VMDF_DXBLT,4,3,0}, //7
+ {1280,1024,8,VMDF_DXBLT,5,4,0}, //8
+ {1600,1200,8,VMDF_DXBLT,6,5,0}, //9
+ {800,600,8,VMDF_DXBLT|VMDF_STRFS,0,0} //10
+ };
+static DDCAPS caps;
+static int mustrestore=0;
+static DWORD CBM[3];
+
+static int bpp;
+static int vflags;
+static int veflags;
+static int winspecial = 0;
+
+int disvaccel = 0; /* Disable video hardware acceleration. */
+
+int fssync=0;
+int winsync=0;
+
+#ifdef _USE_SHARED_MEMORY_
+PALETTEENTRY *color_palette; // shared memory changes
+HANDLE mapColorPalette;
+#else
+PALETTEENTRY color_palette[256];
+#endif //_USE_SHARED_MEMORY_
+
+static int PaletteChanged=0;
+
+LPDIRECTDRAWCLIPPER lpClipper=0;
+LPDIRECTDRAW lpDD=0;
+LPDIRECTDRAW7 lpDD7=0;
+LPDIRECTDRAWPALETTE lpddpal = 0;
+
+DDSURFACEDESC2 ddsd;
+
+DDSURFACEDESC2 ddsdback;
+LPDIRECTDRAWSURFACE7 lpDDSPrimary=0;
+LPDIRECTDRAWSURFACE7 lpDDSDBack=0;
+LPDIRECTDRAWSURFACE7 lpDDSBack=0;
+
+static void ShowDDErr(char *s)
+{
+ char tempo[512];
+ sprintf(tempo,"DirectDraw: %s",s);
+ FCEUD_PrintError(tempo);
+}
+
+int RestoreDD(int w)
+{
+ if(w)
+ {
+ if(!lpDDSBack) return 0;
+ if(IDirectDrawSurface7_Restore(lpDDSBack)!=DD_OK) return 0;
+ }
+ else
+ {
+ if(!lpDDSPrimary) return 0;
+ if(IDirectDrawSurface7_Restore(lpDDSPrimary)!=DD_OK) return 0;
+ }
+ veflags|=1;
+ return 1;
+}
+
+void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g, unsigned char b)
+{
+ color_palette[index].peRed=r;
+ color_palette[index].peGreen=g;
+ color_palette[index].peBlue=b;
+ PaletteChanged=1;
+}
+
+void FCEUD_GetPalette(unsigned char i, unsigned char *r, unsigned char *g, unsigned char *b)
+{
+ *r=color_palette[i].peRed;
+ *g=color_palette[i].peGreen;
+ *b=color_palette[i].peBlue;
+}
+
+static int InitializeDDraw(int fs)
+{
+#ifdef _USE_SHARED_MEMORY_
+ mapColorPalette = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE, 0, 256 * sizeof(PALETTEENTRY),"fceu.ColorPalette");
+ if(mapColorPalette == NULL || GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ CloseHandle(mapColorPalette);
+ mapColorPalette = NULL;
+ color_palette = malloc(256 * sizeof(PALETTEENTRY));
+ }
+ else
+ color_palette = (PALETTEENTRY *)MapViewOfFile(mapColorPalette, FILE_MAP_WRITE, 0, 0, 0);
+#endif
+
+ //(disvaccel&(1<<(fs?1:0)))?(GUID FAR *)DDCREATE_EMULATIONONLY:
+ ddrval = DirectDrawCreate((disvaccel&(1<<(fs?1:0)))?(GUID FAR *)DDCREATE_EMULATIONONLY:NULL, &lpDD, NULL);
+ if (ddrval != DD_OK)
+ {
+ ShowDDErr("Error creating DirectDraw object.");
+ return 0;
+ }
+
+ ddrval = IDirectDraw_QueryInterface(lpDD,&IID_IDirectDraw7,(LPVOID *)&lpDD7);
+ IDirectDraw_Release(lpDD);
+
+ if (ddrval != DD_OK)
+ {
+ ShowDDErr("Error querying interface.");
+ return 0;
+ }
+
+ caps.dwSize=sizeof(caps);
+ if(IDirectDraw7_GetCaps(lpDD7,&caps,0)!=DD_OK)
+ {
+ ShowDDErr("Error getting capabilities.");
+ return 0;
+ }
+ return 1;
+}
+
+static int GetBPP(void)
+{
+ DDPIXELFORMAT ddpix;
+
+ memset(&ddpix,0,sizeof(ddpix));
+ ddpix.dwSize=sizeof(ddpix);
+
+ ddrval=IDirectDrawSurface7_GetPixelFormat(lpDDSPrimary,&ddpix);
+ if (ddrval != DD_OK)
+ {
+ ShowDDErr("Error getting primary surface pixel format.");
+ return 0;
+ }
+
+ if(ddpix.dwFlags&DDPF_RGB)
+ {
+ bpp=ddpix.DUMMYUNIONNAMEN(1).dwRGBBitCount;
+ CBM[0]=ddpix.DUMMYUNIONNAMEN(2).dwRBitMask;
+ CBM[1]=ddpix.DUMMYUNIONNAMEN(3).dwGBitMask;
+ CBM[2]=ddpix.DUMMYUNIONNAMEN(4).dwBBitMask;
+ }
+ else
+ {
+ ShowDDErr("RGB data not valid.");
+ return 0;
+ }
+ if(bpp==15) bpp=16;
+
+ return 1;
+}
+
+static int InitBPPStuff(int fs)
+{
+ if(bpp >= 16)
+ {
+ InitBlitToHigh(bpp >> 3, CBM[0], CBM[1], CBM[2], 0, fs?vmodes[vmod].special:winspecial);
+ }
+ else if(bpp==8)
+ {
+ ddrval=IDirectDraw7_CreatePalette( lpDD7, DDPCAPS_8BIT|DDPCAPS_ALLOW256|DDPCAPS_INITIALIZE,color_palette,&lpddpal,NULL);
+ if (ddrval != DD_OK)
+ {
+ ShowDDErr("Error creating palette object.");
+ return 0;
+ }
+ ddrval=IDirectDrawSurface7_SetPalette(lpDDSPrimary, lpddpal);
+ if (ddrval != DD_OK)
+ {
+ ShowDDErr("Error setting palette object.");
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int SetVideoMode(int fs)
+{
+ int specmul; // Special scaler size multiplier
+
+
+ if(fs)
+ if(!vmod)
+ if(!RecalcCustom())
+ return(0);
+
+ vflags=0;
+ veflags=1;
+ PaletteChanged=1;
+
+ ResetVideo();
+ StopSound();
+
+ if(!InitializeDDraw(fs)) return(1); // DirectDraw not initialized
+
+
+ if(!fs)
+ {
+ if(winspecial == 2 || winspecial == 1)
+ specmul = 2;
+ else if(winspecial == 3 || winspecial == 4)
+ specmul = 3;
+ else
+ specmul = 1;
+
+ ShowCursorAbs(1);
+ windowedfailed=1;
+ HideFWindow(0);
+
+ ddrval = IDirectDraw7_SetCooperativeLevel ( lpDD7, hAppWnd, DDSCL_NORMAL);
+ if (ddrval != DD_OK)
+ {
+ ShowDDErr("Error setting cooperative level.");
+ return 1;
+ }
+
+ /* Beginning */
+ memset(&ddsd,0,sizeof(ddsd));
+ ddsd.dwSize = sizeof(ddsd);
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ ddrval = IDirectDraw7_CreateSurface ( lpDD7, &ddsd, &lpDDSPrimary,(IUnknown FAR*)NULL);
+ if (ddrval != DD_OK)
+ {
+ FCEU_PrintError("%08x, %d\n",ddrval,lpDD7);
+ ShowDDErr("Error creating primary surface.");
+ return 1;
+ }
+
+ memset(&ddsdback,0,sizeof(ddsdback));
+ ddsdback.dwSize=sizeof(ddsdback);
+ ddsdback.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
+ ddsdback.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN;
+
+ ddsdback.dwWidth=256 * specmul;
+ ddsdback.dwHeight=240 * specmul;
+
+ /*
+ If the blit hardware can't stretch, assume it's cheap(and slow)
+ and create the buffer in system memory.
+ */
+ if(!(caps.dwCaps&DDCAPS_BLTSTRETCH))
+ ddsdback.ddsCaps.dwCaps|=DDSCAPS_SYSTEMMEMORY;
+
+ ddrval = IDirectDraw7_CreateSurface ( lpDD7, &ddsdback, &lpDDSBack, (IUnknown FAR*)NULL);
+ if (ddrval != DD_OK)
+ {
+ ShowDDErr("Error creating secondary surface.");
+ return 0;
+ }
+
+ if(!GetBPP())
+ return 0;
+
+ if(bpp!=16 && bpp!=24 && bpp!=32)
+ {
+ ShowDDErr("Current bit depth not supported!");
+ return 0;
+ }
+
+ if(!InitBPPStuff(fs))
+ return 0;
+
+ ddrval=IDirectDraw7_CreateClipper(lpDD7,0,&lpClipper,0);
+ if (ddrval != DD_OK)
+ {
+ ShowDDErr("Error creating clipper.");
+ return 0;
+ }
+
+ ddrval=IDirectDrawClipper_SetHWnd(lpClipper,0,hAppWnd);
+ if (ddrval != DD_OK)
+ {
+ ShowDDErr("Error setting clipper window.");
+ return 0;
+ }
+ ddrval=IDirectDrawSurface7_SetClipper(lpDDSPrimary,lpClipper);
+ if (ddrval != DD_OK)
+ {
+ ShowDDErr("Error attaching clipper to primary surface.");
+ return 0;
+ }
+
+ windowedfailed=0;
+ SetMainWindowStuff();
+ }
+ else /* Following is full-screen */
+ {
+ if(vmod == 0)
+ {
+ if(vmodes[0].special == 2 || vmodes[0].special == 1)
+ specmul = 2;
+ else if(vmodes[0].special == 3 || vmodes[0].special == 4)
+ specmul = 3;
+ else
+ specmul = 1;
+ }
+ HideFWindow(1);
+
+ ddrval = IDirectDraw7_SetCooperativeLevel ( lpDD7, hAppWnd,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT);
+ if (ddrval != DD_OK)
+ {
+ ShowDDErr("Error setting cooperative level.");
+ return 0;
+ }
+
+ ddrval = IDirectDraw7_SetDisplayMode(lpDD7, vmodes[vmod].x, vmodes[vmod].y,vmodes[vmod].bpp,0,0);
+ if (ddrval != DD_OK)
+ {
+ ShowDDErr("Error setting display mode.");
+ return 0;
+ }
+ if(vmodes[vmod].flags&VMDF_DXBLT)
+ {
+ memset(&ddsdback,0,sizeof(ddsdback));
+ ddsdback.dwSize=sizeof(ddsdback);
+ ddsdback.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
+ ddsdback.ddsCaps.dwCaps= DDSCAPS_OFFSCREENPLAIN;
+
+ ddsdback.dwWidth=256 * specmul; //vmodes[vmod].srect.right;
+ ddsdback.dwHeight=240 * specmul; //vmodes[vmod].srect.bottom;
+
+ if(!(caps.dwCaps&DDCAPS_BLTSTRETCH))
+ ddsdback.ddsCaps.dwCaps|=DDSCAPS_SYSTEMMEMORY;
+
+ ddrval = IDirectDraw7_CreateSurface ( lpDD7, &ddsdback, &lpDDSBack, (IUnknown FAR*)NULL);
+ if(ddrval!=DD_OK)
+ {
+ ShowDDErr("Error creating secondary surface.");
+ return 0;
+ }
+ }
+
+ // create foreground surface
+
+ memset(&ddsd,0,sizeof(ddsd));
+ ddsd.dwSize = sizeof(ddsd);
+
+ ddsd.dwFlags = DDSD_CAPS;
+ ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+
+ if(fssync==3) // Double buffering.
+ {
+ ddsd.dwFlags |= DDSD_BACKBUFFERCOUNT;
+ ddsd.dwBackBufferCount = 1;
+ ddsd.ddsCaps.dwCaps |= DDSCAPS_COMPLEX | DDSCAPS_FLIP;
+ }
+
+ ddrval = IDirectDraw7_CreateSurface ( lpDD7, &ddsd, &lpDDSPrimary,(IUnknown FAR*)NULL);
+ if (ddrval != DD_OK)
+ {
+ ShowDDErr("Error creating primary surface.");
+ return 0;
+ }
+
+ if(fssync==3)
+ {
+ DDSCAPS2 tmp;
+
+ memset(&tmp,0,sizeof(tmp));
+ tmp.dwCaps=DDSCAPS_BACKBUFFER;
+
+ if(IDirectDrawSurface7_GetAttachedSurface(lpDDSPrimary,&tmp,&lpDDSDBack)!=DD_OK)
+ {
+ ShowDDErr("Error getting attached surface.");
+ return 0;
+ }
+ }
+
+ if(!GetBPP())
+ return 0;
+ if(!InitBPPStuff(fs))
+ return 0;
+
+ mustrestore=1;
+ ShowCursorAbs(0);
+ }
+
+ InputScreenChanged(fs);
+ fullscreen=fs;
+ return 1;
+}
+
+static void BlitScreenWindow(uint8 *XBuf);
+static void BlitScreenFull(uint8 *XBuf);
+//static uint8 *XBSave;
+void FCEUD_BlitScreen(uint8 *XBuf)
+{
+ xbsave = XBuf;
+ if(!NoWaiting)
+ {
+ int ws;
+
+ if(fullscreen) ws=fssync;
+ else ws = winsync;
+
+ if(ws==1)
+ IDirectDraw7_WaitForVerticalBlank(lpDD7,DDWAITVB_BLOCKBEGIN,0);
+ else if(ws == 2)
+ {
+ BOOL invb = 0;
+
+ while((DD_OK == IDirectDraw7_GetVerticalBlankStatus(lpDD7,&invb)) && !invb)
+ Sleep(0);
+ }
+ }
+
+ if(fullscreen)
+ {
+ BlitScreenFull(XBuf);
+ }
+ else
+ {
+ if(!windowedfailed)
+ BlitScreenWindow(XBuf);
+ }
+}
+
+static void FixPaletteHi(void)
+{
+ int x;
+ SetPaletteBlitToHigh(color_palette);
+}
+
+static void BlitScreenWindow(unsigned char *XBuf)
+{
+ int pitch;
+ unsigned char *ScreenLoc;
+ static RECT srect;
+ RECT drect;
+ int specialmul;
+
+ if(winspecial == 2 || winspecial == 1)
+ specialmul = 2;
+ else if(winspecial == 4 || winspecial == 3)
+ specialmul = 3;
+ else specialmul = 1;
+
+
+ srect.top=srect.left=0;
+ srect.right=VNSWID * specialmul;
+ srect.bottom=totallines * specialmul;
+
+ if(PaletteChanged==1)
+ {
+ FixPaletteHi();
+ PaletteChanged=0;
+ }
+
+ if(!GetClientAbsRect(&drect)) return;
+
+ ddrval=IDirectDrawSurface7_Lock(lpDDSBack,NULL,&ddsdback, 0, NULL);
+ if(ddrval!=DD_OK)
+ {
+ if(ddrval==DDERR_SURFACELOST) RestoreDD(1);
+ return;
+ }
+
+ pitch=ddsdback.DUMMYUNIONNAMEN(1).lPitch;
+ ScreenLoc=ddsdback.lpSurface;
+ if(veflags&1)
+ {
+ memset(ScreenLoc,0,pitch*240);
+ veflags&=~1;
+ }
+ Blit8ToHigh(XBuf+srendline*256+VNSCLIP,ScreenLoc, VNSWID, totallines, pitch,specialmul,specialmul);
+
+ IDirectDrawSurface7_Unlock(lpDDSBack, NULL);
+
+ if(IDirectDrawSurface7_Blt(lpDDSPrimary, &drect,lpDDSBack,&srect,DDBLT_ASYNC,0)!=DD_OK)
+ {
+ ddrval=IDirectDrawSurface7_Blt(lpDDSPrimary, &drect,lpDDSBack,&srect,DDBLT_WAIT,0);
+ if(ddrval!=DD_OK)
+ {
+ if(ddrval==DDERR_SURFACELOST) {RestoreDD(1);RestoreDD(0);}
+ return;
+ }
+ }
+}
+
+static void BlitScreenFull(uint8 *XBuf)
+{
+ static int pitch;
+ char *ScreenLoc;
+ unsigned long x;
+ uint8 y;
+ RECT srect,drect;
+ LPDIRECTDRAWSURFACE7 lpDDSVPrimary;
+ int specmul; // Special scaler size multiplier
+ if(vmodes[0].special == 2 || vmodes[0].special == 1)
+ specmul = 2;
+ else if(vmodes[0].special == 3 || vmodes[0].special == 4)
+ specmul = 3;
+ else
+ specmul = 1;
+
+
+ if(fssync==3)
+ lpDDSVPrimary=lpDDSDBack;
+ else
+ lpDDSVPrimary=lpDDSPrimary;
+
+ if(PaletteChanged==1)
+ {
+ if(bpp>=16)
+ FixPaletteHi();
+ else
+ {
+ ddrval=IDirectDrawPalette_SetEntries(lpddpal,0,0,256,color_palette);
+ if(ddrval!=DD_OK)
+ {
+ if(ddrval==DDERR_SURFACELOST) RestoreDD(0);
+ return;
+ }
+ }
+ PaletteChanged=0;
+ }
+
+ if(vmodes[vmod].flags&VMDF_DXBLT)
+ {
+ ddrval=IDirectDrawSurface7_Lock(lpDDSBack,NULL,&ddsdback, 0, NULL);
+ if(ddrval!=DD_OK)
+ {
+ if(ddrval==DDERR_SURFACELOST) RestoreDD(1);
+ return;
+ }
+ ScreenLoc=ddsdback.lpSurface;
+ pitch=ddsdback.DUMMYUNIONNAMEN(1).lPitch;
+
+ srect.top=0;
+ srect.left=0;
+ srect.right=VNSWID * specmul;
+ srect.bottom=totallines * specmul;
+
+ if(vmodes[vmod].flags&VMDF_STRFS)
+ {
+ drect.top=0;
+ drect.left=0;
+ drect.right=vmodes[vmod].x;
+ drect.bottom=vmodes[vmod].y;
+ }
+ else
+ {
+ drect.top=(vmodes[vmod].y-(totallines*vmodes[vmod].yscale))>>1;
+ drect.bottom=drect.top+(totallines*vmodes[vmod].yscale);
+ drect.left=(vmodes[vmod].x-VNSWID*vmodes[vmod].xscale)>>1;
+ drect.right=drect.left+VNSWID*vmodes[vmod].xscale;
+ }
+ }
+ else
+ {
+ ddrval=IDirectDrawSurface7_Lock(lpDDSVPrimary,NULL,&ddsd, 0, NULL);
+ if(ddrval!=DD_OK)
+ {
+ if(ddrval==DDERR_SURFACELOST) RestoreDD(0);
+ return;
+ }
+
+ ScreenLoc=ddsd.lpSurface;
+ pitch=ddsd.DUMMYUNIONNAMEN(1).lPitch;
+ }
+
+ if(veflags&1)
+ {
+ if(vmodes[vmod].flags&VMDF_DXBLT)
+ {
+ veflags|=2;
+ memset((char *)ScreenLoc,0,pitch*srect.bottom);
+ }
+ else
+ {
+ memset((char *)ScreenLoc,0,pitch*vmodes[vmod].y);
+ }
+ PaletteChanged=1;
+ veflags&=~1;
+ }
+
+ if(vmod==5)
+ {
+ if(eoptions&EO_CLIPSIDES)
+ {
+ asm volatile(
+ "xorl %%edx, %%edx\n\t"
+ "akoop1:\n\t"
+ "movb $120,%%al \n\t"
+ "akoop2:\n\t"
+ "movb 1(%%esi),%%dl\n\t"
+ "shl $16,%%edx\n\t"
+ "movb (%%esi),%%dl\n\t"
+ "movl %%edx,(%%edi)\n\t"
+ "addl $2,%%esi\n\t"
+ "addl $4,%%edi\n\t"
+ "decb %%al\n\t"
+ "jne akoop2\n\t"
+ "addl $16,%%esi\n\t"
+ "addl %%ecx,%%edi\n\t"
+ "decb %%bl\n\t"
+ "jne akoop1\n\t"
+ :
+ : "S" (XBuf+srendline*256+VNSCLIP), "D" (ScreenLoc+((240-totallines)/2)*pitch+(640-(VNSWID<<1))/2),"b" (totallines), "c" ((pitch-VNSWID)<<1)
+ : "%al", "%edx", "%cc" );
+ }
+ else
+ {
+ asm volatile(
+ "xorl %%edx, %%edx\n\t"
+ "koop1:\n\t"
+ "movb $128,%%al \n\t"
+ "koop2:\n\t"
+ "movb 1(%%esi),%%dl\n\t"
+ "shl $16,%%edx\n\t"
+ "movb (%%esi),%%dl\n\t"
+ "movl %%edx,(%%edi)\n\t"
+ "addl $2,%%esi\n\t"
+ "addl $4,%%edi\n\t"
+ "decb %%al\n\t"
+ "jne koop2\n\t"
+ "addl %%ecx,%%edi\n\t"
+ "decb %%bl\n\t"
+ "jne koop1\n\t"
+ :
+ : "S" (XBuf+srendline*256), "D" (ScreenLoc+((240-totallines)/2)*pitch+(640-512)/2),"b" (totallines), "c" (pitch-512+pitch)
+ : "%al", "%edx", "%cc" );
+ }
+ }
+ else if(vmod==4)
+ {
+ if(eoptions&EO_CLIPSIDES)
+ {
+ asm volatile(
+ "ayoop1:\n\t"
+ "movb $120,%%al \n\t"
+ "ayoop2:\n\t"
+ "movb 1(%%esi),%%dh\n\t"
+ "movb %%dh,%%dl\n\t"
+ "shl $16,%%edx\n\t"
+ "movb (%%esi),%%dl\n\t"
+ "movb %%dl,%%dh\n\t" // Ugh
+ "movl %%edx,(%%edi)\n\t"
+ "addl $2,%%esi\n\t"
+ "addl $4,%%edi\n\t"
+ "decb %%al\n\t"
+ "jne ayoop2\n\t"
+ "addl $16,%%esi\n\t"
+ "addl %%ecx,%%edi\n\t"
+ "decb %%bl\n\t"
+ "jne ayoop1\n\t"
+ :
+ : "S" (XBuf+srendline*256+VNSCLIP), "D" (ScreenLoc+((240-totallines)/2)*pitch+(640-(VNSWID<<1))/2),"b" (totallines), "c" ((pitch-VNSWID)<<1)
+ : "%al", "%edx", "%cc" );
+ }
+ else
+ {
+ asm volatile(
+ "yoop1:\n\t"
+ "movb $128,%%al \n\t"
+ "yoop2:\n\t"
+ "movb 1(%%esi),%%dh\n\t"
+ "movb %%dh,%%dl\n\t"
+ "shl $16,%%edx\n\t"
+ "movb (%%esi),%%dl\n\t"
+ "movb %%dl,%%dh\n\t" // Ugh
+ "movl %%edx,(%%edi)\n\t"
+ "addl $2,%%esi\n\t"
+ "addl $4,%%edi\n\t"
+ "decb %%al\n\t"
+ "jne yoop2\n\t"
+ "addl %%ecx,%%edi\n\t"
+ "decb %%bl\n\t"
+ "jne yoop1\n\t"
+ :
+ : "S" (XBuf+srendline*256), "D" (ScreenLoc+((240-totallines)/2)*pitch+(640-512)/2),"b" (totallines), "c" (pitch-512+pitch)
+ : "%al", "%edx", "%cc" );
+ }
+ }
+ else
+ {
+ if(!(vmodes[vmod].flags&VMDF_DXBLT))
+ {
+ if(vmodes[vmod].special)
+ ScreenLoc += (vmodes[vmod].drect.left*(bpp>>3)) + ((vmodes[vmod].drect.top)*pitch);
+ else
+ ScreenLoc+=((vmodes[vmod].x-VNSWID)>>1)*(bpp>>3)+(((vmodes[vmod].y-totallines)>>1))*pitch;
+ }
+
+ if(bpp>=16)
+ {
+ Blit8ToHigh(XBuf+srendline*256+VNSCLIP,ScreenLoc, VNSWID, totallines, pitch,specmul,specmul);
+ }
+ else
+ {
+ XBuf+=srendline*256+VNSCLIP;
+ if(vmodes[vmod].special)
+ Blit8To8(XBuf,ScreenLoc, VNSWID, totallines, pitch,vmodes[vmod].xscale,vmodes[vmod].yscale,0,vmodes[vmod].special);
+ else
+ Blit8To8(XBuf,ScreenLoc, VNSWID, totallines, pitch,1,1,0,0);
+ }
+ }
+
+ if(vmodes[vmod].flags&VMDF_DXBLT)
+ {
+ IDirectDrawSurface7_Unlock(lpDDSBack, NULL);
+
+ if(veflags&2)
+ {
+ if(IDirectDrawSurface7_Lock(lpDDSVPrimary,NULL,&ddsd, 0, NULL)==DD_OK)
+ {
+ memset(ddsd.lpSurface,0,ddsd.DUMMYUNIONNAMEN(1).lPitch*vmodes[vmod].y);
+ IDirectDrawSurface7_Unlock(lpDDSVPrimary, NULL);
+ veflags&=~2;
+ }
+ }
+
+
+ if(IDirectDrawSurface7_Blt(lpDDSVPrimary, &drect,lpDDSBack,&srect,DDBLT_ASYNC,0)!=DD_OK)
+ {
+ ddrval=IDirectDrawSurface7_Blt(lpDDSVPrimary, &drect,lpDDSBack,&srect,DDBLT_WAIT,0);
+ if(ddrval!=DD_OK)
+ {
+ if(ddrval==DDERR_SURFACELOST)
+ {
+ RestoreDD(0);
+ RestoreDD(1);
+ }
+ return;
+ }
+
+ }
+ }
+ else
+ IDirectDrawSurface7_Unlock(lpDDSVPrimary, NULL);
+ if(fssync==3)
+ {
+ IDirectDrawSurface7_Flip(lpDDSPrimary,0,0);
+
+ }
+}
+
+void ResetVideo(void)
+{
+ ShowCursorAbs(1);
+ KillBlitToHigh();
+ if(lpDD7)
+ if(mustrestore)
+ {IDirectDraw7_RestoreDisplayMode(lpDD7);mustrestore=0;}
+ if(lpddpal) {IDirectDrawPalette_Release(lpddpal); lpddpal = 0;}
+ if(lpDDSBack) {IDirectDrawSurface7_Release(lpDDSBack);lpDDSBack=0;}
+ if(lpDDSPrimary) {IDirectDrawSurface7_Release(lpDDSPrimary);lpDDSPrimary=0;}
+ if(lpClipper) {IDirectDrawClipper_Release(lpClipper);lpClipper=0;}
+ if(lpDD7)
+ { IDirectDraw_Release(lpDD7); lpDD7 = NULL; }
+
+}
+
+int specialmlut[5] = {1,2,2,3,3};
+
+static int RecalcCustom(void)
+{
+ vmdef *cmode = &vmodes[0];
+
+ cmode->flags&=~VMDF_DXBLT;
+
+ if(cmode->flags&VMDF_STRFS)
+ {
+ cmode->flags|=VMDF_DXBLT;
+ }
+ else if(cmode->xscale!=1 || cmode->yscale!=1 || cmode->special)
+ {
+ if(cmode->special)
+ {
+ int mult = specialmlut[cmode->special];
+
+ if(cmode->xscale < mult)
+ cmode->xscale = mult;
+ if(cmode->yscale < mult)
+ cmode->yscale = mult;
+
+ if(cmode->xscale != mult || cmode->yscale != mult)
+ cmode->flags|=VMDF_DXBLT;
+ }
+ else
+ cmode->flags|=VMDF_DXBLT;
+
+
+ if(VNSWID*cmode->xscale>cmode->x)
+ {
+ if(cmode->special)
+ {
+ FCEUD_PrintError("Scaled width is out of range.");
+ return(0);
+ }
+ else
+ {
+ FCEUD_PrintError("Scaled width is out of range. Reverting to no horizontal scaling.");
+ cmode->xscale=1;
+ }
+ }
+ if(totallines*cmode->yscale>cmode->y)
+ {
+ if(cmode->special)
+ {
+ FCEUD_PrintError("Scaled height is out of range.");
+ return(0);
+ }
+ else
+ {
+ FCEUD_PrintError("Scaled height is out of range. Reverting to no vertical scaling.");
+ cmode->yscale=1;
+ }
+ }
+
+ cmode->srect.left=VNSCLIP;
+ cmode->srect.top=srendline;
+ cmode->srect.right=256-VNSCLIP;
+ cmode->srect.bottom=erendline+1;
+
+ cmode->drect.top=(cmode->y-(totallines*cmode->yscale))>>1;
+ cmode->drect.bottom=cmode->drect.top+totallines*cmode->yscale;
+
+ cmode->drect.left=(cmode->x-(VNSWID*cmode->xscale))>>1;
+ cmode->drect.right=cmode->drect.left+VNSWID*cmode->xscale;
+ }
+
+ if((cmode->special == 1 || cmode->special == 3) && cmode->bpp == 8)
+ {
+ cmode->bpp = 32;
+ //FCEUD_PrintError("HQ2x/HQ3x requires 16bpp or 32bpp(best).");
+ //return(0);
+ }
+
+ if(cmode->x<VNSWID)
+ {
+ FCEUD_PrintError("Horizontal resolution is too low.");
+ return(0);
+ }
+ if(cmode->y<totallines && !(cmode->flags&VMDF_STRFS))
+ {
+ FCEUD_PrintError("Vertical resolution must not be less than the total number of drawn scanlines.");
+ return(0);
+ }
+
+ return(1);
+}
+
+BOOL SetDlgItemDouble(HWND hDlg, int item, double value)
+{
+ char buf[8];
+ sprintf(buf,"%.6f",value);
+ SetDlgItemText(hDlg, item, buf);
+}
+
+double GetDlgItemDouble(HWND hDlg, int item)
+{
+ char buf[8];
+ double ret = 0;
+
+ GetDlgItemText(hDlg, item, buf, 8);
+ sscanf(buf,"%lf",&ret);
+ return(ret);
+}
+
+BOOL CALLBACK VideoConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ static char *vmstr[11]={
+ "Custom",
+ "320x240 Full Screen",
+ "512x384 Centered",
+ "640x480 Centered",
+ "640x480 Scanlines",
+ "640x480 \"4 per 1\"",
+ "640x480 2x,2y",
+ "1024x768 4x,3y",
+ "1280x1024 5x,4y",
+ "1600x1200 6x,5y",
+ "800x600 Stretched"
+ };
+ int x;
+
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ for(x=0;x<11;x++)
+ SendDlgItemMessage(hwndDlg,100,CB_ADDSTRING,0,(LPARAM)(LPSTR)vmstr[x]);
+ SendDlgItemMessage(hwndDlg,100,CB_SETCURSEL,vmod,(LPARAM)(LPSTR)0);
+
+ SendDlgItemMessage(hwndDlg,202,CB_ADDSTRING,0,(LPARAM)(LPSTR)"8");
+ SendDlgItemMessage(hwndDlg,202,CB_ADDSTRING,0,(LPARAM)(LPSTR)"16");
+ SendDlgItemMessage(hwndDlg,202,CB_ADDSTRING,0,(LPARAM)(LPSTR)"24");
+ SendDlgItemMessage(hwndDlg,202,CB_ADDSTRING,0,(LPARAM)(LPSTR)"32");
+ SendDlgItemMessage(hwndDlg,202,CB_SETCURSEL,(vmodes[0].bpp>>3)-1,(LPARAM)(LPSTR)0);
+
+ SetDlgItemInt(hwndDlg,200,vmodes[0].x,0);
+ SetDlgItemInt(hwndDlg,201,vmodes[0].y,0);
+
+ SetDlgItemInt(hwndDlg,302,vmodes[0].xscale,0);
+ SetDlgItemInt(hwndDlg,303,vmodes[0].yscale,0);
+ CheckRadioButton(hwndDlg,300,301,(vmodes[0].flags&VMDF_STRFS)?301:300);
+
+ {
+ char *str[]={"<none>","hq2x","Scale2x","hq3x","Scale3x"};
+ int x;
+ for(x=0;x<5;x++)
+ {
+ SendDlgItemMessage(hwndDlg,304,CB_ADDSTRING,0,(LPARAM)(LPSTR)str[x]);
+ SendDlgItemMessage(hwndDlg,406,CB_ADDSTRING,0,(LPARAM)(LPSTR)str[x]);
+ }
+ }
+ SendDlgItemMessage(hwndDlg,304,CB_SETCURSEL,vmodes[0].special,(LPARAM)(LPSTR)0);
+ SendDlgItemMessage(hwndDlg,406,CB_SETCURSEL,winspecial,(LPARAM)(LPSTR)0);
+
+ if(eoptions&EO_FSAFTERLOAD)
+ CheckDlgButton(hwndDlg,102,BST_CHECKED);
+
+ if(eoptions&EO_CLIPSIDES)
+ CheckDlgButton(hwndDlg,106,BST_CHECKED);
+
+ if(disvaccel&1)
+ CheckDlgButton(hwndDlg,130,BST_CHECKED);
+
+ if(disvaccel&2)
+ CheckDlgButton(hwndDlg,131,BST_CHECKED);
+
+ if(eoptions&EO_FORCEISCALE)
+ CheckDlgButton(hwndDlg,402,BST_CHECKED);
+
+ if(eoptions&EO_FORCEASPECT)
+ CheckDlgButton(hwndDlg,403,BST_CHECKED);
+
+ SetDlgItemInt(hwndDlg,500,srendlinen,0);
+ SetDlgItemInt(hwndDlg,501,erendlinen,0);
+
+ SetDlgItemInt(hwndDlg,502,srendlinep,0);
+ SetDlgItemInt(hwndDlg,503,erendlinep,0);
+
+
+ SetDlgItemDouble(hwndDlg, 400, winsizemulx);
+ SetDlgItemDouble(hwndDlg, 401, winsizemuly);
+ SetDlgItemDouble(hwndDlg, 404, saspectw);
+ SetDlgItemDouble(hwndDlg, 405, saspecth);
+
+ //SetDlgI temInt(hwndDlg,103,winsizemul,0);
+
+ SendDlgItemMessage(hwndDlg,104,CB_ADDSTRING,0,(LPARAM)(LPSTR)"<none>");
+ SendDlgItemMessage(hwndDlg,105,CB_ADDSTRING,0,(LPARAM)(LPSTR)"<none>");
+
+ SendDlgItemMessage(hwndDlg,104,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Wait for VBlank");
+ SendDlgItemMessage(hwndDlg,104,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Lazy wait for VBlank");
+
+ SendDlgItemMessage(hwndDlg,105,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Wait for VBlank");
+ SendDlgItemMessage(hwndDlg,105,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Lazy wait for VBlank");
+ SendDlgItemMessage(hwndDlg,105,CB_ADDSTRING,0,(LPARAM)(LPSTR)"Double Buffering");
+
+ SendDlgItemMessage(hwndDlg,104,CB_SETCURSEL,winsync,(LPARAM)(LPSTR)0);
+ SendDlgItemMessage(hwndDlg,105,CB_SETCURSEL,fssync,(LPARAM)(LPSTR)0);
+
+ if(eoptions&EO_NOSPRLIM)
+ CheckDlgButton(hwndDlg,600,BST_CHECKED);
+
+ break;
+ case WM_CLOSE:
+ case WM_QUIT: goto gornk;
+ case WM_COMMAND:
+ if(!(wParam>>16))
+ switch(wParam&0xFFFF)
+ {
+ case 1:
+ gornk:
+
+ if(IsDlgButtonChecked(hwndDlg,106)==BST_CHECKED)
+ eoptions|=EO_CLIPSIDES;
+ else
+ eoptions&=~EO_CLIPSIDES;
+
+ if(IsDlgButtonChecked(hwndDlg,600)==BST_CHECKED)
+ eoptions|=EO_NOSPRLIM;
+ else
+ eoptions&=~EO_NOSPRLIM;
+
+ srendlinen=GetDlgItemInt(hwndDlg,500,0,0);
+ erendlinen=GetDlgItemInt(hwndDlg,501,0,0);
+ srendlinep=GetDlgItemInt(hwndDlg,502,0,0);
+ erendlinep=GetDlgItemInt(hwndDlg,503,0,0);
+
+
+ if(erendlinen>239) erendlinen=239;
+ if(srendlinen>erendlinen) srendlinen=erendlinen;
+
+ if(erendlinep>239) erendlinep=239;
+ if(srendlinep>erendlinen) srendlinep=erendlinep;
+
+ UpdateRendBounds();
+
+ if(IsDlgButtonChecked(hwndDlg,301)==BST_CHECKED)
+ vmodes[0].flags|=VMDF_STRFS;
+ else
+ vmodes[0].flags&=~VMDF_STRFS;
+
+ vmod=SendDlgItemMessage(hwndDlg,100,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
+ vmodes[0].x=GetDlgItemInt(hwndDlg,200,0,0);
+ vmodes[0].y=GetDlgItemInt(hwndDlg,201,0,0);
+ vmodes[0].bpp=(SendDlgItemMessage(hwndDlg,202,CB_GETCURSEL,0,(LPARAM)(LPSTR)0)+1)<<3;
+
+ vmodes[0].xscale=GetDlgItemInt(hwndDlg,302,0,0);
+ vmodes[0].yscale=GetDlgItemInt(hwndDlg,303,0,0);
+ vmodes[0].special=SendDlgItemMessage(hwndDlg,304,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
+
+ winspecial = SendDlgItemMessage(hwndDlg,406,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
+ disvaccel = 0;
+
+ if(IsDlgButtonChecked(hwndDlg,130)==BST_CHECKED)
+ disvaccel |= 1;
+ if(IsDlgButtonChecked(hwndDlg,131)==BST_CHECKED)
+ disvaccel |= 2;
+
+
+ if(IsDlgButtonChecked(hwndDlg,101)==BST_CHECKED)
+ fullscreen=1;
+ else
+ fullscreen=0;
+ if(IsDlgButtonChecked(hwndDlg,102)==BST_CHECKED)
+ eoptions|=EO_FSAFTERLOAD;
+ else
+ eoptions&=~EO_FSAFTERLOAD;
+
+ eoptions &= ~(EO_FORCEISCALE | EO_FORCEASPECT);
+ if(IsDlgButtonChecked(hwndDlg,402)==BST_CHECKED)
+ eoptions|=EO_FORCEISCALE;
+ if(IsDlgButtonChecked(hwndDlg,403)==BST_CHECKED)
+ eoptions|=EO_FORCEASPECT;
+
+
+ winsizemulx=GetDlgItemDouble(hwndDlg, 400);
+ winsizemuly=GetDlgItemDouble(hwndDlg, 401);
+ saspectw=GetDlgItemDouble(hwndDlg, 404);
+ saspecth=GetDlgItemDouble(hwndDlg, 405);
+ FixWXY(0);
+
+ winsync=SendDlgItemMessage(hwndDlg,104,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
+ fssync=SendDlgItemMessage(hwndDlg,105,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
+ EndDialog(hwndDlg,0);
+ break;
+ }
+ }
+ return 0;
+}
+
+static void SetFSVideoMode(void)
+{
+ changerecursive=1;
+ if(!SetVideoMode(1))
+ SetVideoMode(0);
+ changerecursive=0;
+}
+
+
+void DoVideoConfigFix(void)
+{
+ FCEUI_DisableSpriteLimitation(eoptions&EO_NOSPRLIM);
+ UpdateRendBounds();
+}
+
+void ConfigVideo(void)
+{
+ DialogBox(fceu_hInstance,"VIDEOCONFIG",hAppWnd,VideoConCallB);
+ DoVideoConfigFix();
+ if(fullscreen)
+ SetFSVideoMode();
+ else
+ {
+ changerecursive=1;
+ SetVideoMode(0);
+ changerecursive=0;
+ }
+ //SetMainWindowStuff();
+}
+
diff --git a/drivers/win/wave.c b/drivers/win/wave.c
new file mode 100644
index 00000000..ea2ee022
--- /dev/null
+++ b/drivers/win/wave.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
+ */
+
+int CloseWave(void)
+{
+
+ return(FCEUI_EndWaveRecord());
+}
+
+int CreateSoundSave(void)
+{
+ const char filter[]="MS WAVE(*.wav)\0*.wav\0";
+ char nameo[2048];
+ OPENFILENAME ofn;
+
+ FCEUI_EndWaveRecord();
+
+ memset(&ofn,0,sizeof(ofn));
+ ofn.lStructSize=sizeof(ofn);
+ ofn.hInstance=fceu_hInstance;
+ ofn.lpstrTitle="Log Sound As...";
+ ofn.lpstrFilter=filter;
+ nameo[0]=0;
+ ofn.lpstrFile=nameo;
+ ofn.nMaxFile=256;
+ ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
+ if(GetSaveFileName(&ofn))
+ return FCEUI_BeginWaveRecord(nameo);
+ return 0;
+}
diff --git a/drivers/win/window.c b/drivers/win/window.c
new file mode 100644
index 00000000..efe158c3
--- /dev/null
+++ b/drivers/win/window.c
@@ -0,0 +1,2222 @@
+/* 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 "state.c" /* Save/Load state AS */
+
+extern char *md5_asciistr(uint8 digest[16]);
+extern FCEUGI *FCEUGameInfo;
+extern int EnableRewind;
+
+void DSMFix(UINT msg)
+{
+ switch(msg)
+ {
+ case WM_VSCROLL:
+ case WM_NCRBUTTONDOWN:
+ case WM_NCMBUTTONDOWN:
+ case WM_NCLBUTTONDOWN:
+ case WM_ENTERMENULOOP:StopSound();break;
+ }
+}
+static void ConfigGUI(void);
+static void ConfigTiming(void);
+static void ConfigPalette(void);
+static void ConfigDirectories(void);
+
+static HMENU fceumenu=0;
+
+static int tog=0;
+static int CheckedAutoFirePattern=40004;
+static int CheckedAutoFireOffset=40016;
+static int EnableBackgroundInput=0;
+
+void ShowCursorAbs(int w)
+{
+ static int stat=0;
+ if(w)
+ {
+ if(stat==-1) {stat++; ShowCursor(1);}
+ }
+ else
+ {
+ if(stat==0) {stat--; ShowCursor(0);}
+ }
+}
+
+
+void CalcWindowSize(RECT *al)
+{
+ al->left=0;
+ al->right=VNSWID*winsizemulx;
+ al->top=0;
+ al->bottom=totallines*winsizemuly;
+
+ AdjustWindowRectEx(al,GetWindowLong(hAppWnd,GWL_STYLE),GetMenu(hAppWnd)!=NULL,GetWindowLong(hAppWnd,GWL_EXSTYLE));
+
+ al->right-=al->left;
+ al->left=0;
+ al->bottom-=al->top;
+ al->top=0;
+}
+
+
+void RedoMenuGI(FCEUGI *gi)
+{
+ int simpled[]={101,111,110,200,201,204,203,141,142,143,151,152,300,40003,40028, 0};
+ int x;
+
+ x = 0;
+ while(simpled[x])
+ {
+ #ifndef FCEUDEF_DEBUGGER
+ if(simpled[x] == 203)
+ EnableMenuItem(fceumenu,simpled[x],MF_BYCOMMAND | MF_GRAYED);
+ else
+ #endif
+ #ifndef _USE_SHARED_MEMORY_
+ if(simpled[x] == 40002 || simpled[x] == 40003)
+ EnableMenuItem(fceumenu,simpled[x],MF_BYCOMMAND| MF_GRAYED);
+ else
+ #endif
+ EnableMenuItem(fceumenu,simpled[x],MF_BYCOMMAND | (gi?MF_ENABLED:MF_GRAYED));
+ x++;
+ }
+}
+
+void UpdateMenu(void)
+{
+ static int *polo[3]={&genie,&palyo,&status_icon};
+ static int polo2[3]={310,311,303};
+ int x;
+
+ for(x=0;x<3;x++)
+ CheckMenuItem(fceumenu,polo2[x],*polo[x]?MF_CHECKED:MF_UNCHECKED);
+
+ if(eoptions&EO_BGRUN)
+ CheckMenuItem(fceumenu,301,MF_CHECKED);
+ else
+ CheckMenuItem(fceumenu,301,MF_UNCHECKED);
+
+ if(FCEU_BotMode())
+ CheckMenuItem(fceumenu,40003, MF_CHECKED);
+ else
+ CheckMenuItem(fceumenu,40003, MF_UNCHECKED);
+
+ if(GetAutoFireDesynch())
+ CheckMenuItem(fceumenu,40025, MF_CHECKED);
+ else
+ CheckMenuItem(fceumenu,40025, MF_UNCHECKED);
+
+ CheckMenuItem(fceumenu,302, EnableBackgroundInput?MF_CHECKED:MF_UNCHECKED);
+ CheckMenuItem(fceumenu,40029, EnableRewind?MF_CHECKED:MF_UNCHECKED);
+
+ int AutoFirePatternIDs[]={40004,40005,40006,40007,40008,40009,40010,40011,40012,40013,40014,40015,40022,40023,40024,0};
+ int AutoFireOffsetIDs[]={40016,40017,40018,40019,40020,40021,0};
+
+ x = 0;
+ while(AutoFirePatternIDs[x])
+ {
+ CheckMenuItem(fceumenu,AutoFirePatternIDs[x],
+ AutoFirePatternIDs[x]==CheckedAutoFirePattern?MF_CHECKED:MF_UNCHECKED);
+ x++;
+ }
+
+ x = 0;
+ while(AutoFireOffsetIDs[x])
+ {
+ CheckMenuItem(fceumenu,AutoFireOffsetIDs[x],
+ AutoFireOffsetIDs[x]==CheckedAutoFireOffset?MF_CHECKED:MF_UNCHECKED);
+ x++;
+ }
+}
+
+static HMENU recentmenu, recentdmenu;
+char *rfiles[10]={0,0,0,0,0,0,0,0,0,0};
+char *rdirs[10]={0,0,0,0,0,0,0,0,0,0};
+
+void UpdateRMenu(HMENU menu, char **strs, int mitem, int baseid)
+{
+ MENUITEMINFO moo;
+ int x;
+
+ moo.cbSize=sizeof(moo);
+ moo.fMask=MIIM_SUBMENU|MIIM_STATE;
+
+ GetMenuItemInfo(GetSubMenu(fceumenu,0),mitem,FALSE,&moo);
+ moo.hSubMenu=menu;
+ moo.fState=strs[0]?MFS_ENABLED:MFS_GRAYED;
+
+ SetMenuItemInfo(GetSubMenu(fceumenu,0),mitem,FALSE,&moo);
+
+ for(x=0;x<10;x++)
+ RemoveMenu(menu,baseid+x,MF_BYCOMMAND);
+ for(x=9;x>=0;x--)
+ {
+ char tmp[128+5];
+ if(!strs[x]) continue;
+
+ moo.cbSize=sizeof(moo);
+ moo.fMask=MIIM_DATA|MIIM_ID|MIIM_TYPE;
+
+ if(strlen(strs[x])<128)
+ {
+ sprintf(tmp,"&%d. %s",(x+1)%10,strs[x]);
+ }
+ else
+ sprintf(tmp,"&%d. %s",(x+1)%10,strs[x]+strlen(strs[x])-127);
+
+ moo.cch=strlen(tmp);
+ moo.fType=0;
+ moo.wID=baseid+x;
+ moo.dwTypeData=tmp;
+ InsertMenuItem(menu,0,1,&moo);
+ }
+ DrawMenuBar(hAppWnd);
+}
+
+void AddRecent(char *fn)
+{
+ int x;
+
+ for(x=0;x<10;x++)
+ if(rfiles[x])
+ if(!strcmp(rfiles[x],fn)) // Item is already in list.
+ {
+ int y;
+ char *tmp;
+
+ tmp=rfiles[x]; // Save pointer.
+ for(y=x;y;y--)
+ rfiles[y]=rfiles[y-1]; // Move items down.
+
+ rfiles[0]=tmp; // Put item on top.
+ UpdateRMenu(recentmenu, rfiles, 102, 600);
+ return;
+ }
+
+ if(rfiles[9]) free(rfiles[9]);
+ for(x=9;x;x--) rfiles[x]=rfiles[x-1];
+ rfiles[0]=malloc(strlen(fn)+1);
+ strcpy(rfiles[0],fn);
+ UpdateRMenu(recentmenu, rfiles, 102, 600);
+}
+
+void AddRecentDir(char *fn)
+{
+ int x;
+
+ for(x=0;x<10;x++)
+ if(rdirs[x])
+ if(!strcmp(rdirs[x],fn)) // Item is already in list.
+ {
+ int y;
+ char *tmp;
+
+ tmp=rdirs[x]; // Save pointer.
+ for(y=x;y;y--)
+ rdirs[y]=rdirs[y-1]; // Move items down.
+
+ rdirs[0]=tmp; // Put item on top.
+ UpdateRMenu(recentdmenu, rdirs, 103, 700);
+ return;
+ }
+
+ if(rdirs[9]) free(rdirs[9]);
+ for(x=9;x;x--) rdirs[x]=rdirs[x-1];
+ rdirs[0]=malloc(strlen(fn)+1);
+ strcpy(rdirs[0],fn);
+ UpdateRMenu(recentdmenu, rdirs, 103, 700);
+}
+
+
+
+void HideMenu(int h)
+{
+ if(h)
+ {
+ SetMenu(hAppWnd,0);
+ }
+ else
+ {
+ SetMenu(hAppWnd,fceumenu);
+ }
+}
+
+static LONG WindowXC=1<<30,WindowYC;
+void HideFWindow(int h)
+{
+ LONG desa;
+
+ if(h) /* Full-screen. */
+ {
+ RECT bo;
+ GetWindowRect(hAppWnd,&bo);
+ WindowXC=bo.left;
+ WindowYC=bo.top;
+
+ SetMenu(hAppWnd,0);
+ desa=WS_POPUP|WS_CLIPSIBLINGS;
+ }
+ else
+ {
+ desa=WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS;
+ HideMenu(tog);
+ /* Stupid DirectDraw bug(I think?) requires this. Need to investigate it. */
+ SetWindowPos(hAppWnd,HWND_NOTOPMOST,0,0,0,0,SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE);
+ }
+
+ SetWindowLong(hAppWnd,GWL_STYLE,desa|(GetWindowLong(hAppWnd,GWL_STYLE)&WS_VISIBLE));
+ SetWindowPos(hAppWnd,0,0,0,0,0,SWP_FRAMECHANGED|SWP_NOACTIVATE|SWP_NOCOPYBITS|SWP_NOMOVE|SWP_NOREPOSITION|SWP_NOSIZE|SWP_NOZORDER);
+}
+
+void ToggleHideMenu(void)
+{
+ extern FCEUGI *FCEUGameInfo;
+ if(!fullscreen && (FCEUGameInfo || tog))
+ {
+ tog^=1;
+ HideMenu(tog);
+ SetMainWindowStuff();
+ }
+}
+
+void FCEUD_HideMenuToggle(void)
+{
+ ToggleHideMenu();
+}
+
+static void ALoad(char *nameo)
+{
+ if((GI=FCEUI_LoadGame(nameo,1)))
+ {
+ palyo=FCEUI_GetCurrentVidSystem(0,0);
+ UpdateMenu();
+ FixFL();
+ SetMainWindowStuff();
+ AddRecent(nameo);
+ RefreshThrottleFPS();
+ if(eoptions&EO_HIDEMENU && !tog)
+ ToggleHideMenu();
+ if(eoptions&EO_FSAFTERLOAD)
+ SetFSVideoMode();
+ }
+ else
+ StopSound();
+ ParseGIInput(GI);
+ RedoMenuGI(GI);
+}
+
+void LoadNewGamey(HWND hParent, char *initialdir)
+{
+ const char filter[]="All usable files(*.nes,*.nsf,*.fds,*.unf,*.zip,*.gz)\0*.nes;*.nsf;*.fds;*.unf;*.zip;*.gz\0All non-compressed usable files(*.nes,*.nsf,*.fds,*.unf)\0*.nes;*.nsf;*.fds;*.unf\0All files (*.*)\0*.*\0";
+ char nameo[2048];
+ OPENFILENAME ofn;
+ memset(&ofn,0,sizeof(ofn));
+ ofn.lStructSize=sizeof(ofn);
+ ofn.hInstance=fceu_hInstance;
+ ofn.lpstrTitle="FCE Ultra Open File...";
+ ofn.lpstrFilter=filter;
+ nameo[0]=0;
+ ofn.hwndOwner=hParent;
+ ofn.lpstrFile=nameo;
+ ofn.nMaxFile=256;
+ ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY; //OFN_EXPLORER|OFN_ENABLETEMPLATE|OFN_ENABLEHOOK;
+ ofn.lpstrInitialDir=initialdir?initialdir:gfsdir;
+ if(GetOpenFileName(&ofn))
+ {
+ char *tmpdir;
+
+ if((tmpdir=malloc(ofn.nFileOffset+1)))
+ {
+ strncpy(tmpdir,ofn.lpstrFile,ofn.nFileOffset);
+ tmpdir[ofn.nFileOffset]=0;
+ AddRecentDir(tmpdir);
+
+ if(!initialdir) // Prevent setting the File->Open default
+ // directory when a "Recent Directory" is selected.
+ {
+ if(gfsdir)
+ free(gfsdir);
+ gfsdir = tmpdir;
+ }
+ else
+ free(tmpdir);
+ }
+ ALoad(nameo);
+ }
+}
+
+static uint32 mousex,mousey,mouseb;
+void GetMouseData(uint32 *md)
+{
+ if(FCEUI_IsMovieActive()<0)
+ return;
+
+ md[0]=mousex;
+ md[1]=mousey;
+ if(!fullscreen)
+ {
+ if(ismaximized)
+ {
+ RECT t;
+ GetClientRect(hAppWnd, &t);
+ md[0] = md[0] * VNSWID / (t.right?t.right:1);
+ md[1] = md[1] * totallines / (t.bottom?t.bottom:1);
+ }
+ else
+ {
+ md[0]/=winsizemulx;
+ md[1]/=winsizemuly;
+ }
+ md[0]+=VNSCLIP;
+ }
+
+ md[1]+=srendline;
+ md[2]=((mouseb==MK_LBUTTON)?1:0)|((mouseb==MK_RBUTTON)?2:0);
+}
+
+//static int sizchange=0;
+static int vchanged=0;
+
+extern void RestartMovieOrReset(int pow);
+
+
+void MapInput(void);
+
+LRESULT FAR PASCAL AppWndProc(HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
+{
+ DSMFix(msg);
+ switch(msg) {
+ case WM_LBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_RBUTTONDOWN:
+ case WM_RBUTTONUP:
+ mouseb=wParam;
+ goto proco;
+ case WM_MOUSEMOVE:
+ {
+ mousex=LOWORD(lParam);
+ mousey=HIWORD(lParam);
+ }
+ goto proco;
+ case WM_ERASEBKGND:
+ if(xbsave)
+ return(0);
+ else goto proco;
+ case WM_PAINT:if(xbsave)
+ {
+ PAINTSTRUCT ps;
+ BeginPaint(hWnd,&ps);
+ FCEUD_BlitScreen(xbsave);
+ EndPaint(hWnd,&ps);
+ return(0);
+ }
+ goto proco;
+ case WM_SIZE:
+ if(!fullscreen && !changerecursive)
+ switch(wParam)
+ {
+ case SIZE_MAXIMIZED: ismaximized = 1;SetMainWindowStuff();break;
+ case SIZE_RESTORED: ismaximized = 0;SetMainWindowStuff();break;
+ }
+ break;
+ case WM_SIZING:
+ {
+ RECT *wrect=(RECT *)lParam;
+ RECT srect;
+
+ int h=wrect->bottom-wrect->top;
+ int w=wrect->right-wrect->left;
+ int how;
+
+ if(wParam == WMSZ_BOTTOM || wParam == WMSZ_TOP)
+ how = 2;
+ else if(wParam == WMSZ_LEFT || wParam == WMSZ_RIGHT)
+ how = 1;
+ else if(wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_BOTTOMRIGHT
+ || wParam == WMSZ_TOPRIGHT || wParam == WMSZ_TOPLEFT)
+ how = 3;
+ if(how & 1)
+ winsizemulx*= (double)w/winwidth;
+ if(how & 2)
+ winsizemuly*= (double)h/winheight;
+ if(how & 1) FixWXY(0);
+ else FixWXY(1);
+
+ CalcWindowSize(&srect);
+ winwidth=srect.right;
+ winheight=srect.bottom;
+ wrect->right = wrect->left + srect.right;
+ wrect->bottom = wrect->top + srect.bottom;
+ }
+ //sizchange=1;
+ //break;
+ goto proco;
+ case WM_DISPLAYCHANGE:
+ if(!fullscreen && !changerecursive)
+ vchanged=1;
+ goto proco;
+ case WM_DROPFILES:
+ {
+ UINT len;
+ char *ftmp;
+
+ len=DragQueryFile((HANDLE)wParam,0,0,0)+1;
+ if((ftmp=malloc(len)))
+ {
+ DragQueryFile((HANDLE)wParam,0,ftmp,len);
+ ALoad(ftmp);
+ free(ftmp);
+ }
+ }
+ break;
+ case WM_COMMAND:
+ if(!(wParam>>16))
+ {
+ wParam&=0xFFFF;
+ if(wParam>=600 && wParam<=609) // Recent files
+ {
+ if(rfiles[wParam-600]) ALoad(rfiles[wParam-600]);
+ }
+ else if(wParam >= 700 && wParam <= 709) // Recent dirs
+ {
+ if(rdirs[wParam-700])
+ LoadNewGamey(hWnd, rdirs[wParam - 700]);
+ }
+ switch(wParam)
+ {
+ case 40004:
+ SetAutoFirePattern(1,1);
+ CheckedAutoFirePattern = wParam;
+ UpdateMenu();
+ break;
+ case 40005:
+ SetAutoFirePattern(1,2);
+ CheckedAutoFirePattern = wParam;
+ UpdateMenu();
+ break;
+ case 40006:
+ SetAutoFirePattern(1,3);
+ CheckedAutoFirePattern = wParam;
+ UpdateMenu();
+ break;
+ case 40007:
+ SetAutoFirePattern(1,4);
+ CheckedAutoFirePattern = wParam;
+ UpdateMenu();
+ break;
+ case 40008:
+ SetAutoFirePattern(1,5);
+ CheckedAutoFirePattern = wParam;
+ UpdateMenu();
+ break;
+ case 40009:
+ SetAutoFirePattern(2,1);
+ CheckedAutoFirePattern = wParam;
+ UpdateMenu();
+ break;
+ case 40010:
+ SetAutoFirePattern(2,2);
+ CheckedAutoFirePattern = wParam;
+ UpdateMenu();
+ break;
+ case 40011:
+ SetAutoFirePattern(2,3);
+ CheckedAutoFirePattern = wParam;
+ UpdateMenu();
+ break;
+ case 40012:
+ SetAutoFirePattern(2,4);
+ CheckedAutoFirePattern = wParam;
+ UpdateMenu();
+ break;
+ case 40013:
+ SetAutoFirePattern(3,1);
+ CheckedAutoFirePattern = wParam;
+ UpdateMenu();
+ break;
+ case 40014:
+ SetAutoFirePattern(3,2);
+ CheckedAutoFirePattern = wParam;
+ UpdateMenu();
+ break;
+ case 40015:
+ SetAutoFirePattern(3,3);
+ CheckedAutoFirePattern = wParam;
+ UpdateMenu();
+ break;
+ case 40022:
+ SetAutoFirePattern(4,1);
+ CheckedAutoFirePattern = wParam;
+ UpdateMenu();
+ break;
+ case 40023:
+ SetAutoFirePattern(4,2);
+ CheckedAutoFirePattern = wParam;
+ UpdateMenu();
+ break;
+ case 40024:
+ SetAutoFirePattern(5,1);
+ CheckedAutoFirePattern = wParam;
+ UpdateMenu();
+ break;
+ case 40016:
+ case 40017:
+ case 40018:
+ case 40019:
+ case 40020:
+ case 40021:
+ SetAutoFireOffset(wParam - 40016);
+ CheckedAutoFireOffset = wParam;
+ UpdateMenu();
+ break;
+ case 40025:
+ SetAutoFireDesynch(GetAutoFireDesynch()^1);
+ UpdateMenu();
+ break;
+ case 300:ToggleHideMenu();break;
+ case 301:
+ eoptions^=EO_BGRUN;
+ if((eoptions & EO_BGRUN) == 0)
+ {
+ EnableBackgroundInput = 0;
+ KeyboardSetBackgroundAccess(EnableBackgroundInput);
+ SetJoystickBackgroundAccess(EnableBackgroundInput);
+ }
+ UpdateMenu();
+ break;
+ case 302:EnableBackgroundInput ^= 1;
+ eoptions |= EO_BGRUN*EnableBackgroundInput;
+ KeyboardSetBackgroundAccess(EnableBackgroundInput);
+ SetJoystickBackgroundAccess(EnableBackgroundInput);
+ UpdateMenu();
+ break;
+ case 40029:
+ EnableRewind^= 1;
+ UpdateMenu();
+ break;
+ case 303:status_icon=!status_icon;UpdateMenu();break;
+ case 310:genie^=1;FCEUI_SetGameGenie(genie);UpdateMenu();break;
+ case 311:palyo^=1;
+ FCEUI_SetVidSystem(palyo);
+ RefreshThrottleFPS();
+ UpdateMenu();
+ FixFL();
+// DoVideoConfigFix();
+ SetMainWindowStuff();
+ break;
+ case 40003: FCEU_SetBotMode(1^FCEU_BotMode());
+ UpdateMenu(); break;
+ case 40002: CreateBasicBot();break;
+ case 40028: DoMemmo(0); break;
+ case 320:StopSound();ConfigDirectories();break;
+ case 327:StopSound();ConfigGUI();break;
+ case 321:StopSound();ConfigInput(hWnd);break;
+ case 322:ConfigTiming();break;
+ case 323:StopSound();ShowNetplayConsole();break;
+ case 324:StopSound();ConfigPalette();break;
+ case 325:StopSound();ConfigSound();break;
+ case 326:ConfigVideo();break;
+ case 328:MapInput();break;
+
+ case 200:RestartMovieOrReset(0);break;
+ case 201:RestartMovieOrReset(1);break;
+ case 40026: FCEUI_FDSSelect();break;
+ case 40001: FCEUI_FDSInsert();break;
+ case 40027: FCEUI_VSUniCoin();break;
+
+
+ #ifdef FCEUDEF_DEBUGGER
+ case 203:BeginDSeq(hWnd);break;
+ #endif
+
+ case 204:ConfigAddCheat(hWnd);break;
+ case 205:CreateMemWatch(hWnd);break;
+ case 100:StopSound();
+ LoadNewGamey(hWnd, 0);
+ break;
+ case 101:if(GI)
+ {
+ #ifdef FCEUDEF_DEBUGGER
+ KillDebugger();
+ #endif
+ FCEUI_CloseGame();
+ GI=0;
+ RedoMenuGI(GI);
+ }
+ break;
+ case 110:FCEUD_SaveStateAs();break;
+ case 111:FCEUD_LoadStateFrom();break;
+
+ case 120:
+ {
+ MENUITEMINFO mi;
+ char *str;
+
+ StopSound();
+ if(CreateSoundSave())
+ str="Stop Sound Logging";
+ else
+ str="Log Sound As...";
+ memset(&mi,0,sizeof(mi));
+ mi.fMask=MIIM_DATA|MIIM_TYPE;
+ mi.cbSize=sizeof(mi);
+ GetMenuItemInfo(fceumenu,120,0,&mi);
+ mi.fMask=MIIM_DATA|MIIM_TYPE;
+ mi.cbSize=sizeof(mi);
+ mi.dwTypeData=str;
+ mi.cch=strlen(str);
+ SetMenuItemInfo(fceumenu,120,0,&mi);
+ }
+ break;
+ case 130:DoFCEUExit();break;
+
+ case 141:FCEUD_MovieRecordTo();break;
+ case 142:FCEUD_MovieReplayFrom();break;
+ case 143:FCEUI_StopMovie();break;
+
+ case 151:FCEUD_AviRecordTo();break;
+ case 152:FCEUD_AviStop();break;
+
+ case 400:StopSound();ShowAboutBox();break;
+ case 401:MakeLogWindow();break;
+ }
+ }
+ break;
+
+
+ case WM_SYSCOMMAND:
+ if(GI && wParam == SC_SCREENSAVE && (goptions & GOO_DISABLESS))
+ return(0);
+
+ if(wParam==SC_KEYMENU)
+ {
+ if(GI && InputType[2]==SIFC_FKB && cidisabled)
+ break;
+ if(lParam == VK_RETURN || fullscreen || tog) break;
+ }
+ goto proco;
+ case WM_SYSKEYDOWN:
+ if(GI && InputType[2]==SIFC_FKB && cidisabled)
+ break; /* Hopefully this won't break DInput... */
+
+ if(fullscreen || tog)
+ {
+ if(wParam==VK_MENU)
+ break;
+ }
+ if(wParam==VK_F10)
+ {
+ return 0;
+ /*
+ if(!moocow) FCEUD_PrintError("Iyee");
+ if(!(lParam&0x40000000))
+ FCEUI_ResetNES();
+ break;
+ */
+ }
+
+ if(wParam == VK_RETURN)
+ {
+ if(!(lParam&(1<<30)))
+ {
+ UpdateMenu();
+ changerecursive=1;
+ if(!SetVideoMode(fullscreen^1))
+ SetVideoMode(fullscreen);
+ changerecursive=0;
+ }
+ break;
+ }
+ goto proco;
+
+ case WM_KEYDOWN:
+ if(GI)
+ {
+ /* Only disable command keys if a game is loaded(and the other
+ conditions are right, of course). */
+ if(InputType[2]==SIFC_FKB)
+ {
+ if(wParam==VK_SCROLL)
+ {
+ cidisabled^=1;
+ FCEUI_DispMessage("Family Keyboard %sabled.",cidisabled?"en":"dis");
+ }
+ if(cidisabled)
+ break; /* Hopefully this won't break DInput... */
+ }
+ }
+ /*
+ if(!(lParam&0x40000000))
+ switch( wParam )
+ {
+ case VK_F11:FCEUI_PowerNES();break;
+ case VK_F12:DoFCEUExit();break;
+ //case VK_F2:userpause^=1;break;
+ case VK_F3:ToggleHideMenu();break;
+ }
+ */
+ goto proco;
+ case WM_CLOSE:
+ case WM_DESTROY:
+ case WM_QUIT:DoFCEUExit();break;
+ case WM_ACTIVATEAPP:
+ if((BOOL)wParam)
+ {
+ nofocus=0;
+ }
+ else
+ {
+ nofocus=1;
+ }
+ goto proco;
+ case WM_ENTERMENULOOP:
+ EnableMenuItem(fceumenu,143,MF_BYCOMMAND | (FCEUI_IsMovieActive()?MF_ENABLED:MF_GRAYED));
+ EnableMenuItem(fceumenu,152,MF_BYCOMMAND | (FCEUI_AviIsRecording()?MF_ENABLED:MF_GRAYED));
+ default:
+ proco:
+ return DefWindowProc(hWnd,msg,wParam,lParam);
+ }
+ return 0;
+}
+
+void FixWXY(int pref)
+{
+ if(eoptions&EO_FORCEASPECT)
+ {
+ /* First, make sure the ratio is valid, and if it's not, change
+ it so that it doesn't break everything.
+ */
+ if(saspectw < 0.01) saspectw = 0.01;
+ if(saspecth < 0.01) saspecth = 0.01;
+ if((saspectw / saspecth) > 100) saspecth = saspectw;
+ if((saspecth / saspectw) > 100) saspectw = saspecth;
+
+ if((saspectw / saspecth) < 0.1) saspecth = saspectw;
+ if((saspecth / saspectw) > 0.1) saspectw = saspecth;
+
+ if(!pref)
+ {
+ winsizemuly = winsizemulx * 256 / 240 * 3 / 4 * saspectw / saspecth;
+ }
+ else
+ {
+ winsizemulx = winsizemuly * 240 / 256 * 4 / 3 * saspecth / saspectw;
+ }
+ }
+ if(winspecial)
+ {
+ int mult;
+ if(winspecial == 1 || winspecial == 2) mult = 2;
+ else mult = 3;
+ if(winsizemulx < mult)
+ {
+ if(eoptions&EO_FORCEASPECT)
+ winsizemuly *= mult / winsizemulx;
+ winsizemulx = mult;
+ }
+ if(winsizemuly < mult)
+ {
+ if(eoptions&EO_FORCEASPECT)
+ winsizemulx *= mult / winsizemuly;
+ winsizemuly = mult;
+ }
+ }
+
+ if(winsizemulx<0.1)
+ winsizemulx=0.1;
+ if(winsizemuly<0.1)
+ winsizemuly=0.1;
+
+ if(eoptions & EO_FORCEISCALE)
+ {
+ int x,y;
+
+ x = winsizemulx * 2;
+ y = winsizemuly * 2;
+
+ x = (x>>1) + (x&1);
+ y = (y>>1) + (y&1);
+
+ if(!x) x=1;
+ if(!y) y=1;
+
+ winsizemulx = x;
+ winsizemuly = y;
+ }
+
+ if(winsizemulx > 100) winsizemulx = 100;
+ if(winsizemuly > 100) winsizemuly = 100;
+}
+
+void UpdateFCEUWindow(void)
+{
+ int w,h;
+ RECT wrect;
+
+ if(vchanged && !fullscreen && !changerecursive && !nofocus)
+ {
+ SetVideoMode(0);
+ vchanged=0;
+ }
+
+ BlockingCheck();
+ #ifdef FCEUDEF_DEBUGGER
+ UpdateDebugger();
+ #endif
+
+ if(!(eoptions&EO_BGRUN))
+ while(nofocus)
+ {
+ StopSound();
+ Sleep(75);
+ BlockingCheck();
+ }
+ if(userpause)
+ {
+ StopSound();
+ while(userpause)
+ {
+ Sleep(50);
+ BlockingCheck();
+ }
+ }
+}
+
+void ByebyeWindow(void)
+{
+ SetMenu(hAppWnd,0);
+ DestroyMenu(fceumenu);
+ DestroyWindow(hAppWnd);
+}
+
+int CreateMainWindow(void)
+{
+ WNDCLASSEX winclass;
+ RECT tmp;
+
+ memset(&winclass,0,sizeof(winclass));
+ winclass.cbSize=sizeof(WNDCLASSEX);
+ winclass.style=CS_OWNDC|CS_HREDRAW|CS_VREDRAW|CS_SAVEBITS;
+ winclass.lpfnWndProc=AppWndProc;
+ winclass.cbClsExtra=0;
+ winclass.cbWndExtra=0;
+ winclass.hInstance=fceu_hInstance;
+ winclass.hIcon=LoadIcon(fceu_hInstance, "ICON_1");
+ winclass.hIconSm=LoadIcon(fceu_hInstance, "ICON_1");
+ winclass.hCursor=LoadCursor(NULL, IDC_ARROW);
+ winclass.hbrBackground=GetStockObject(BLACK_BRUSH);
+ //winclass.lpszMenuName="FCEUMENU";
+ winclass.lpszClassName="FCEULTRA";
+
+ if(!RegisterClassEx(&winclass))
+ return FALSE;
+
+ AdjustWindowRectEx(&tmp,WS_OVERLAPPEDWINDOW,1,0);
+
+ fceumenu=LoadMenu(fceu_hInstance,"FCEUMENU");
+
+ recentmenu=CreateMenu();
+ recentdmenu = CreateMenu();
+
+ UpdateRMenu(recentmenu, rfiles, 102, 600);
+ UpdateRMenu(recentdmenu, rdirs, 103, 700);
+
+ RedoMenuGI(NULL);
+
+ hAppWnd = CreateWindowEx(0,"FCEULTRA","FCE Ultra",
+ WS_OVERLAPPEDWINDOW|WS_CLIPSIBLINGS, /* Style */
+ CW_USEDEFAULT,CW_USEDEFAULT,256,240, /* X,Y ; Width, Height */
+ NULL,fceumenu,fceu_hInstance,NULL );
+ DragAcceptFiles(hAppWnd, 1);
+ SetMainWindowStuff();
+ return 1;
+}
+
+
+int SetMainWindowStuff(void)
+{
+ RECT tmp;
+
+ GetWindowRect(hAppWnd,&tmp);
+
+ if(ismaximized)
+ {
+ winwidth=tmp.right - tmp.left;
+ winheight=tmp.bottom - tmp.top;
+
+ ShowWindow(hAppWnd, SW_SHOWMAXIMIZED);
+ }
+ else
+ {
+ RECT srect;
+ if(WindowXC!=(1<<30))
+ {
+ /* Subtracting and adding for if(eoptions&EO_USERFORCE) below. */
+ tmp.bottom-=tmp.top;
+ tmp.bottom+=WindowYC;
+
+ tmp.right-=tmp.left;
+ tmp.right+=WindowXC;
+
+
+ tmp.left=WindowXC;
+ tmp.top=WindowYC;
+ WindowXC=1<<30;
+ }
+
+ CalcWindowSize(&srect);
+ SetWindowPos(hAppWnd,HWND_TOP,tmp.left,tmp.top,srect.right,srect.bottom,SWP_SHOWWINDOW);
+ winwidth=srect.right;
+ winheight=srect.bottom;
+
+ ShowWindow(hAppWnd, SW_SHOWNORMAL);
+ }
+ return 1;
+}
+
+int GetClientAbsRect(LPRECT lpRect)
+{
+ POINT point;
+ point.x=point.y=0;
+ if(!ClientToScreen(hAppWnd,&point)) return 0;
+
+ lpRect->top=point.y;
+ lpRect->left=point.x;
+
+ if(ismaximized)
+ {
+ RECT al;
+ GetClientRect(hAppWnd, &al);
+ lpRect->right = point.x + al.right;
+ lpRect->bottom = point.y + al.bottom;
+ }
+ else
+ {
+ lpRect->right=point.x+VNSWID*winsizemulx;
+ lpRect->bottom=point.y+totallines*winsizemuly;
+ }
+ return 1;
+}
+
+
+int LoadPaletteFile(void)
+{
+ FILE *fp;
+ const char filter[]="All usable files(*.pal)\0*.pal\0All files (*.*)\0*.*\0";
+ char nameo[2048];
+ OPENFILENAME ofn;
+ memset(&ofn,0,sizeof(ofn));
+ ofn.lStructSize=sizeof(ofn);
+ ofn.hInstance=fceu_hInstance;
+ ofn.lpstrTitle="FCE Ultra Open Palette File...";
+ ofn.lpstrFilter=filter;
+ nameo[0]=0;
+ ofn.lpstrFile=nameo;
+ ofn.nMaxFile=256;
+ ofn.Flags=OFN_EXPLORER|OFN_FILEMUSTEXIST|OFN_HIDEREADONLY;
+ ofn.lpstrInitialDir=0;
+ if(GetOpenFileName(&ofn))
+ {
+ if((fp=FCEUD_UTF8fopen(nameo,"rb")))
+ {
+ fread(cpalette,1,192,fp);
+ fclose(fp);
+ FCEUI_SetPaletteArray(cpalette);
+ eoptions|=EO_CPALETTE;
+ return(1);
+ }
+ else
+ FCEUD_PrintError("Error opening palette file!");
+ }
+ return(0);
+}
+static HWND pwindow;
+static BOOL CALLBACK PaletteConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ DSMFix(uMsg);
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ if(ntsccol)
+ CheckDlgButton(hwndDlg,100,BST_CHECKED);
+ SendDlgItemMessage(hwndDlg,500,TBM_SETRANGE,1,MAKELONG(0,128));
+ SendDlgItemMessage(hwndDlg,501,TBM_SETRANGE,1,MAKELONG(0,128));
+ FCEUI_GetNTSCTH(&ntsctint,&ntschue);
+ SendDlgItemMessage(hwndDlg,500,TBM_SETPOS,1,ntsctint);
+ SendDlgItemMessage(hwndDlg,501,TBM_SETPOS,1,ntschue);
+ EnableWindow(GetDlgItem(hwndDlg,201),(eoptions&EO_CPALETTE)?1:0);
+ break;
+ case WM_HSCROLL:
+ ntsctint=SendDlgItemMessage(hwndDlg,500,TBM_GETPOS,0,(LPARAM)(LPSTR)0);
+ ntschue=SendDlgItemMessage(hwndDlg,501,TBM_GETPOS,0,(LPARAM)(LPSTR)0);
+ FCEUI_SetNTSCTH(ntsccol,ntsctint,ntschue);
+ break;
+ case WM_CLOSE:
+ case WM_QUIT: goto gornk;
+ case WM_COMMAND:
+ if(!(wParam>>16))
+ switch(wParam&0xFFFF)
+ {
+ case 100:ntsccol^=1;FCEUI_SetNTSCTH(ntsccol,ntsctint,ntschue);break;
+ case 200:
+ StopSound();
+ if(LoadPaletteFile())
+ EnableWindow(GetDlgItem(hwndDlg,201),1);
+ break;
+ case 201:FCEUI_SetPaletteArray(0);
+ eoptions&=~EO_CPALETTE;
+ EnableWindow(GetDlgItem(hwndDlg,201),0);
+ break;
+ case 1:
+ gornk:
+ DestroyWindow(hwndDlg);
+ pwindow=0; // Yay for user race conditions.
+ break;
+ }
+ }
+ return 0;
+}
+
+static void ConfigPalette(void)
+{
+ if(!pwindow)
+ pwindow=CreateDialog(fceu_hInstance,"PALCONFIG",0,PaletteConCallB);
+ else
+ SetFocus(pwindow);
+}
+
+
+static BOOL CALLBACK TimingConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ int x;
+
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ if(eoptions&EO_HIGHPRIO)
+ CheckDlgButton(hwndDlg,105,BST_CHECKED);
+ if(eoptions&EO_NOTHROTTLE)
+ CheckDlgButton(hwndDlg,101,BST_CHECKED);
+ for(x=0;x<10;x++)
+ {
+ char buf[8];
+ sprintf(buf,"%d",x);
+ SendDlgItemMessage(hwndDlg,110,CB_ADDSTRING,0,(LPARAM)(LPSTR)buf);
+ SendDlgItemMessage(hwndDlg,111,CB_ADDSTRING,0,(LPARAM)(LPSTR)buf);
+ }
+ SendDlgItemMessage(hwndDlg,110,CB_SETCURSEL,maxconbskip,(LPARAM)(LPSTR)0);
+ SendDlgItemMessage(hwndDlg,111,CB_SETCURSEL,ffbskip,(LPARAM)(LPSTR)0);
+ break;
+ case WM_CLOSE:
+ case WM_QUIT: goto gornk;
+ case WM_COMMAND:
+ if(!(wParam>>16))
+ switch(wParam&0xFFFF)
+ {
+ case 1:
+ gornk:
+ if(IsDlgButtonChecked(hwndDlg,105)==BST_CHECKED)
+ eoptions|=EO_HIGHPRIO;
+ else
+ eoptions&=~EO_HIGHPRIO;
+
+ if(IsDlgButtonChecked(hwndDlg,101)==BST_CHECKED)
+ eoptions|=EO_NOTHROTTLE;
+ else
+ eoptions&=~EO_NOTHROTTLE;
+
+ maxconbskip=SendDlgItemMessage(hwndDlg,110,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
+ ffbskip=SendDlgItemMessage(hwndDlg,111,CB_GETCURSEL,0,(LPARAM)(LPSTR)0);
+ EndDialog(hwndDlg,0);
+ break;
+ }
+ }
+ return 0;
+}
+
+void DoTimingConfigFix(void)
+{
+ DoPriority();
+}
+
+static void ConfigTiming(void)
+{
+ DialogBox(fceu_hInstance,"TIMINGCONFIG",hAppWnd,TimingConCallB);
+ DoTimingConfigFix();
+}
+
+static BOOL CALLBACK GUIConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg) {
+ case WM_INITDIALOG:
+ if(eoptions&EO_FOAFTERSTART)
+ CheckDlgButton(hwndDlg,102,BST_CHECKED);
+ if(eoptions&EO_HIDEMENU)
+ CheckDlgButton(hwndDlg,104,BST_CHECKED);
+ if(goptions & GOO_CONFIRMEXIT)
+ CheckDlgButton(hwndDlg,110,BST_CHECKED);
+ if(goptions & GOO_DISABLESS)
+ CheckDlgButton(hwndDlg,111,BST_CHECKED);
+ break;
+ case WM_CLOSE:
+ case WM_QUIT: goto gornk;
+ case WM_COMMAND:
+ if(!(wParam>>16))
+ switch(wParam&0xFFFF)
+ {
+ case 1:
+ gornk:
+ if(IsDlgButtonChecked(hwndDlg,102)==BST_CHECKED)
+ eoptions|=EO_FOAFTERSTART;
+ else
+ eoptions&=~EO_FOAFTERSTART;
+ if(IsDlgButtonChecked(hwndDlg,104)==BST_CHECKED)
+ eoptions|=EO_HIDEMENU;
+ else
+ eoptions&=~EO_HIDEMENU;
+
+ goptions &= ~(GOO_CONFIRMEXIT | GOO_DISABLESS);
+
+ if(IsDlgButtonChecked(hwndDlg,110)==BST_CHECKED)
+ goptions |= GOO_CONFIRMEXIT;
+ if(IsDlgButtonChecked(hwndDlg,111)==BST_CHECKED)
+ goptions |= GOO_DISABLESS;
+ EndDialog(hwndDlg,0);
+ break;
+ }
+ }
+ return 0;
+}
+
+static void ConfigGUI(void)
+{
+ DialogBox(fceu_hInstance,"GUICONFIG",hAppWnd,GUIConCallB);
+}
+
+
+static int BrowseForFolder(HWND hParent, char *htext, char *buf)
+{
+ BROWSEINFO bi;
+ LPCITEMIDLIST pidl;
+ int ret=1;
+
+ buf[0]=0;
+
+ memset(&bi,0,sizeof(bi));
+
+ bi.hwndOwner=hParent;
+ bi.lpszTitle=htext;
+ bi.ulFlags=BIF_RETURNONLYFSDIRS;
+
+ if(FAILED(CoInitialize(0)))
+ return(0);
+
+ if(!(pidl=SHBrowseForFolder(&bi)))
+ {
+ ret=0;
+ goto end1;
+ }
+
+ if(!SHGetPathFromIDList(pidl,buf))
+ {
+ ret=0;
+ goto end2;
+ }
+
+ end2:
+ /* This probably isn't the best way to free the memory... */
+ CoTaskMemFree((PVOID)pidl);
+
+ end1:
+ CoUninitialize();
+ return(ret);
+}
+
+static BOOL CALLBACK DirConCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ int x;
+
+ switch(uMsg){
+ case WM_INITDIALOG:
+ for(x=0;x<6;x++)
+ SetDlgItemText(hwndDlg,100+x,DOvers[x]);
+ if(eoptions&EO_SNAPNAME)
+ CheckDlgButton(hwndDlg,300,BST_CHECKED);
+ break;
+ case WM_CLOSE:
+ case WM_QUIT: goto gornk;
+ case WM_COMMAND:
+ if(!(wParam>>16))
+ {
+ if((wParam&0xFFFF)>=200 && (wParam&0xFFFF)<=205)
+ {
+ static char *helpert[6]={"Cheats","Miscellaneous","Nonvolatile Game Data","Save States","Screen Snapshots","Base Directory"};
+ char name[MAX_PATH];
+
+ if(BrowseForFolder(hwndDlg,helpert[((wParam&0xFFFF)-200)],name))
+ SetDlgItemText(hwndDlg,100+((wParam&0xFFFF)-200),name);
+ }
+ else switch(wParam&0xFFFF)
+ {
+ case 1:
+ gornk:
+
+ if(IsDlgButtonChecked(hwndDlg,300)==BST_CHECKED)
+ eoptions|=EO_SNAPNAME;
+ else
+ eoptions&=~EO_SNAPNAME;
+
+ RemoveDirs(); // Remove empty directories.
+
+ for(x=0;x<6;x++)
+ {
+ LONG len;
+ len=SendDlgItemMessage(hwndDlg,100+x,WM_GETTEXTLENGTH,0,0);
+ if(len<=0)
+ {
+ if(DOvers[x]) free(DOvers[x]);
+ DOvers[x]=0;
+ continue;
+ }
+ len++; // Add 1 for null character.
+ if(!(DOvers[x]=malloc(len)))
+ continue;
+ if(!GetDlgItemText(hwndDlg,100+x,DOvers[x],len))
+ {
+ free(DOvers[x]);
+ DOvers[x]=0;
+ continue;
+ }
+
+ }
+
+ CreateDirs(); // Create needed directories.
+ SetDirs(); // Set the directories in the core.
+ EndDialog(hwndDlg,0);
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+
+static void ConfigDirectories(void)
+{
+ DialogBox(fceu_hInstance,"DIRCONFIG",hAppWnd,DirConCallB);
+}
+
+static int ReplayDialogReadOnlyStatus = 0;
+static int ReplayDialogStopFrame = 0;
+
+static char* GetReplayPath(HWND hwndDlg)
+{
+ char* fn=0;
+ char szChoice[MAX_PATH];
+ LONG lIndex = SendDlgItemMessage(hwndDlg, 200, CB_GETCURSEL, 0, 0);
+ LONG lCount = SendDlgItemMessage(hwndDlg, 200, CB_GETCOUNT, 0, 0);
+
+ // NOTE: lCount-1 is the "Browse..." list item
+ if(lIndex != CB_ERR && lIndex != lCount-1)
+ {
+ LONG lStringLength = SendDlgItemMessage(hwndDlg, 200, CB_GETLBTEXTLEN, (WPARAM)lIndex, 0);
+ if(lStringLength < MAX_PATH)
+ {
+ char szDrive[MAX_PATH]={0};
+ char szDirectory[MAX_PATH]={0};
+ char szFilename[MAX_PATH]={0};
+ char szExt[MAX_PATH]={0};
+ char szTemp[MAX_PATH]={0};
+
+ SendDlgItemMessage(hwndDlg, 200, CB_GETLBTEXT, (WPARAM)lIndex, (LPARAM)szTemp);
+ if(szTemp[0] && szTemp[1]!=':')
+ sprintf(szChoice, ".\\%s", szTemp);
+ else
+ strcpy(szChoice, szTemp);
+
+ SetCurrentDirectory(BaseDirectory);
+
+ _splitpath(szChoice, szDrive, szDirectory, szFilename, szExt);
+ if(szDrive[0]=='\0' && szDirectory[0]=='\0')
+ fn=FCEU_MakePath(FCEUMKF_MOVIE, szChoice); // need to make a full path
+ else
+ fn=strdup(szChoice); // given a full path
+ }
+ }
+
+ return fn;
+}
+
+static char* GetRecordPath(HWND hwndDlg)
+{
+ char* fn=0;
+ char szChoice[MAX_PATH];
+ char szDrive[MAX_PATH]={0};
+ char szDirectory[MAX_PATH]={0};
+ char szFilename[MAX_PATH]={0};
+ char szExt[MAX_PATH]={0};
+
+ GetDlgItemText(hwndDlg, 200, szChoice, sizeof(szChoice));
+
+ _splitpath(szChoice, szDrive, szDirectory, szFilename, szExt);
+ if(szDrive[0]=='\0' && szDirectory[0]=='\0')
+ fn=FCEU_MakePath(FCEUMKF_MOVIE, szChoice); // need to make a full path
+ else
+ fn=strdup(szChoice); // given a full path
+
+ return fn;
+}
+
+static char* GetSavePath(HWND hwndDlg)
+{
+ char* fn=0;
+ char szDrive[MAX_PATH]={0};
+ char szDirectory[MAX_PATH]={0};
+ char szFilename[MAX_PATH]={0};
+ char szExt[MAX_PATH]={0};
+ LONG lIndex = SendDlgItemMessage(hwndDlg, 301, CB_GETCURSEL, 0, 0);
+ LONG lStringLength = SendDlgItemMessage(hwndDlg, 301, CB_GETLBTEXTLEN, (WPARAM)lIndex, 0);
+
+ fn = (char*)malloc(lStringLength);
+ SendDlgItemMessage(hwndDlg, 301, CB_GETLBTEXT, (WPARAM)lIndex, (LPARAM)fn);
+
+ _splitpath(fn, szDrive, szDirectory, szFilename, szExt);
+ if(szDrive[0]=='\0' && szDirectory[0]=='\0')
+ {
+ char* newfn=FCEU_MakePath(FCEUMKF_MOVIE, fn); // need to make a full path
+ free(fn);
+ fn=newfn;
+ }
+
+ return fn;
+}
+
+
+// C:\fceu\movies\bla.fcm + C:\fceu\fceu\ -> C:\fceu\movies\bla.fcm
+// movies\bla.fcm + fceu\ -> movies\bla.fcm
+
+// C:\fceu\movies\bla.fcm + C:\fceu\ -> movies\bla.fcm
+void AbsoluteToRelative(char *const dst, const char *const dir, const char *const root)
+{
+ int i, igood=0;
+
+ for(i = 0 ; ; i++)
+ {
+ int a = tolower(dir[i]);
+ int b = tolower(root[i]);
+ if(a == '/' || a == '\0' || a == '.') a = '\\';
+ if(b == '/' || b == '\0' || b == '.') b = '\\';
+
+ if(a != b)
+ {
+ igood = 0;
+ break;
+ }
+
+ if(a == '\\')
+ igood = i+1;
+
+ if(!dir[i] || !root[i])
+ break;
+ }
+
+// if(igood)
+// sprintf(dst, ".\\%s", dir + igood);
+// else
+ strcpy(dst, dir + igood);
+}
+
+extern int movieConvertOffset1, movieConvertOffset2,movieConvertOK;
+static int movieHackType=3;
+
+static void UpdateReplayDialog(HWND hwndDlg)
+{
+ movieConvertOffset1=0, movieConvertOffset2=0,movieConvertOK=0;
+
+ int doClear=1;
+ char *fn=GetReplayPath(hwndDlg);
+
+ // remember the previous setting for the read-only checkbox
+ if(IsWindowEnabled(GetDlgItem(hwndDlg, 201)))
+ ReplayDialogReadOnlyStatus = (SendDlgItemMessage(hwndDlg, 201, BM_GETCHECK, 0, 0) == BST_CHECKED) ? 1 : 0;
+
+ if(fn)
+ {
+ MOVIE_INFO info;
+ char metadata[MOVIE_MAX_METADATA];
+ char rom_name[MAX_PATH];
+
+ memset(&info, 0, sizeof(info));
+ info.metadata = metadata;
+ info.metadata_size = sizeof(metadata);
+ info.name_of_rom_used = rom_name;
+ info.name_of_rom_used_size = sizeof(rom_name);
+
+ if(FCEUI_MovieGetInfo(fn, &info))
+ {
+#define MOVIE_FLAG_NOSYNCHACK (1<<4) // set in newer version, used for old movie compatibility
+ extern int resetDMCacc;
+ extern int justAutoConverted;
+ int noNoSyncHack=!(info.flags&MOVIE_FLAG_NOSYNCHACK) && resetDMCacc;
+ EnableWindow(GetDlgItem(hwndDlg,1000),justAutoConverted || noNoSyncHack);
+ EnableWindow(GetDlgItem(hwndDlg,1001),justAutoConverted || noNoSyncHack);
+ if(justAutoConverted)
+ {
+ // use values as nesmock offsets
+ if(movieHackType != 0)
+ {
+ movieHackType=0;
+ SendDlgItemMessage(hwndDlg, 1000, WM_SETTEXT, 0,(LPARAM)"2");
+ SendDlgItemMessage(hwndDlg, 1001, WM_SETTEXT, 0,(LPARAM)"0");
+ SendDlgItemMessage(hwndDlg, 2000, WM_SETTEXT, 0,(LPARAM)"Offset:");
+ SendDlgItemMessage(hwndDlg, 2001, WM_SETTEXT, 0,(LPARAM)"from");
+ }
+ }
+ else if(noNoSyncHack)
+ {
+ // use values as sound reset hack values
+ if(movieHackType != 1)
+ {
+ movieHackType=1;
+// extern int32 DMCacc;
+// extern int8 DMCBitCount;
+// char str[256];
+// sprintf(str, "%d", DMCacc);
+// SendDlgItemMessage(hwndDlg, 1000, WM_SETTEXT, 0,(LPARAM)str);
+// sprintf(str, "%d", DMCBitCount);
+// SendDlgItemMessage(hwndDlg, 1001, WM_SETTEXT, 0,(LPARAM)str);
+ SendDlgItemMessage(hwndDlg, 1000, WM_SETTEXT, 0,(LPARAM)"8");
+ SendDlgItemMessage(hwndDlg, 1001, WM_SETTEXT, 0,(LPARAM)"0");
+ SendDlgItemMessage(hwndDlg, 2000, WM_SETTEXT, 0,(LPARAM)"Missing data: acc=");
+ SendDlgItemMessage(hwndDlg, 2001, WM_SETTEXT, 0,(LPARAM)"bc=");
+ }
+ }
+ else if(movieHackType != 2)
+ {
+ movieHackType=2;
+ SendDlgItemMessage(hwndDlg, 1000, WM_SETTEXT, 0,(LPARAM)"");
+ SendDlgItemMessage(hwndDlg, 1001, WM_SETTEXT, 0,(LPARAM)"");
+ SendDlgItemMessage(hwndDlg, 2000, WM_SETTEXT, 0,(LPARAM)"");
+ SendDlgItemMessage(hwndDlg, 2001, WM_SETTEXT, 0,(LPARAM)"");
+ }
+
+/* { // select away to autoconverted movie... but actually we don't want to do that now that there's an offset setting in the dialog
+ extern char lastMovieInfoFilename [512];
+ char relative[MAX_PATH];
+ AbsoluteToRelative(relative, lastMovieInfoFilename, BaseDirectory);
+
+ LONG lOtherIndex = SendDlgItemMessage(hwndDlg, 200, CB_FINDSTRING, (WPARAM)-1, (LPARAM)relative);
+ if(lOtherIndex != CB_ERR)
+ {
+ // select already existing string
+ SendDlgItemMessage(hwndDlg, 200, CB_SETCURSEL, lOtherIndex, 0);
+ } else {
+ LONG lIndex = SendDlgItemMessage(hwndDlg, 200, CB_GETCURSEL, 0, 0);
+ SendDlgItemMessage(hwndDlg, 200, CB_INSERTSTRING, lIndex, (LPARAM)relative);
+ SendDlgItemMessage(hwndDlg, 200, CB_SETCURSEL, lIndex, 0);
+ }
+
+ // restore focus to the dialog
+// SetFocus(GetDlgItem(hwndDlg, 200));
+ }*/
+
+
+ char tmp[256];
+ uint32 div;
+
+ sprintf(tmp, "%lu", info.num_frames);
+ SetWindowTextA(GetDlgItem(hwndDlg,301), tmp); // frames
+ SetDlgItemText(hwndDlg,1003,tmp);
+
+ div = (FCEUI_GetCurrentVidSystem(0,0)) ? 50 : 60; // PAL timing
+ info.num_frames += (div>>1); // round up
+ sprintf(tmp, "%02d:%02d:%02d", (info.num_frames/(div*60*60)), (info.num_frames/(div*60))%60, (info.num_frames/div) % 60);
+ SetWindowTextA(GetDlgItem(hwndDlg,300), tmp); // length
+
+ sprintf(tmp, "%lu", info.rerecord_count);
+ SetWindowTextA(GetDlgItem(hwndDlg,302), tmp); // rerecord
+
+ {
+ // convert utf8 metadata to windows widechar
+ WCHAR wszMeta[MOVIE_MAX_METADATA];
+ if(MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, metadata, -1, wszMeta, MOVIE_MAX_METADATA))
+ {
+ if(wszMeta[0])
+ SetWindowTextW(GetDlgItem(hwndDlg,303), wszMeta); // metadata
+ else
+ SetWindowTextW(GetDlgItem(hwndDlg,303), L"(this movie has no author info)"); // metadata
+ }
+ }
+
+ EnableWindow(GetDlgItem(hwndDlg,201),(info.read_only)? FALSE : TRUE); // disable read-only checkbox if the file access is read-only
+ SendDlgItemMessage(hwndDlg,201,BM_SETCHECK,info.read_only ? BST_CHECKED : (ReplayDialogReadOnlyStatus ? BST_CHECKED : BST_UNCHECKED), 0);
+
+ SetWindowText(GetDlgItem(hwndDlg,306),(info.flags & MOVIE_FLAG_FROM_RESET) ? "Reset or Power-On" : "Savestate");
+ if(info.movie_version > 1)
+ {
+ char emuStr[128];
+ SetWindowText(GetDlgItem(hwndDlg,304),info.name_of_rom_used);
+ SetWindowText(GetDlgItem(hwndDlg,305),md5_asciistr(info.md5_of_rom_used));
+ if(info.emu_version_used > 64)
+ sprintf(emuStr, "FCEU %d.%02d.%02d%s", info.emu_version_used/10000, (info.emu_version_used/100)%100, (info.emu_version_used)%100, info.emu_version_used < 9813 ? " (blip)" : "");
+ else
+ {
+ if(info.emu_version_used == 1)
+ strcpy(emuStr, "Famtasia");
+ else if(info.emu_version_used == 2)
+ strcpy(emuStr, "Nintendulator");
+ else if(info.emu_version_used == 3)
+ strcpy(emuStr, "VirtuaNES");
+ else
+ {
+ strcpy(emuStr, "(unknown)");
+ char* dot = strrchr(fn,'.');
+ if(dot)
+ {
+ if(!stricmp(dot,".fmv"))
+ strcpy(emuStr, "Famtasia? (unknown version)");
+ else if(!stricmp(dot,".nmv"))
+ strcpy(emuStr, "Nintendulator? (unknown version)");
+ else if(!stricmp(dot,".vmv"))
+ strcpy(emuStr, "VirtuaNES? (unknown version)");
+ else if(!stricmp(dot,".fcm"))
+ strcpy(emuStr, "FCEU? (unknown version)");
+ }
+ }
+ }
+ SetWindowText(GetDlgItem(hwndDlg,307),emuStr);
+ }
+ else
+ {
+ SetWindowText(GetDlgItem(hwndDlg,304),"unknown");
+ SetWindowText(GetDlgItem(hwndDlg,305),"unknown");
+ SetWindowText(GetDlgItem(hwndDlg,307),"FCEU 0.98.10 (blip)");
+ }
+
+ SetWindowText(GetDlgItem(hwndDlg,308),md5_asciistr(FCEUGameInfo->MD5));
+ EnableWindow(GetDlgItem(hwndDlg,1),TRUE); // enable OK
+
+ doClear = 0;
+ }
+
+ free(fn);
+ }
+ else
+ {
+ EnableWindow(GetDlgItem(hwndDlg,1000),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,1001),FALSE);
+ }
+
+ if(doClear)
+ {
+ SetWindowText(GetDlgItem(hwndDlg,300),"");
+ SetWindowText(GetDlgItem(hwndDlg,301),"");
+ SetWindowText(GetDlgItem(hwndDlg,302),"");
+ SetWindowText(GetDlgItem(hwndDlg,303),"");
+ SetWindowText(GetDlgItem(hwndDlg,304),"");
+ SetWindowText(GetDlgItem(hwndDlg,305),"");
+ SetWindowText(GetDlgItem(hwndDlg,306),"Nothing (invalid movie)");
+ SetWindowText(GetDlgItem(hwndDlg,307),"");
+ SetWindowText(GetDlgItem(hwndDlg,308),md5_asciistr(FCEUGameInfo->MD5));
+ SetDlgItemText(hwndDlg,1003,"");
+ EnableWindow(GetDlgItem(hwndDlg,201),FALSE);
+ SendDlgItemMessage(hwndDlg,201,BM_SETCHECK,BST_UNCHECKED,0);
+ EnableWindow(GetDlgItem(hwndDlg,1),FALSE);
+ }
+}
+
+
+
+#define MAX(x,y) ((x)<(y)?(y):(x))
+#define MIN(x,y) ((x)>(y)?(y):(x))
+
+static BOOL CALLBACK ReplayDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ {
+ movieHackType=3;
+ SendDlgItemMessage(hwndDlg, 201, BM_SETCHECK, moviereadonly?BST_CHECKED:BST_UNCHECKED, 0);
+ SendDlgItemMessage(hwndDlg, 1002,BM_SETCHECK, BST_UNCHECKED, 0);
+
+ char* findGlob[2] = {FCEU_MakeFName(FCEUMKF_MOVIEGLOB, 0, 0),
+ FCEU_MakeFName(FCEUMKF_MOVIEGLOB2, 0, 0)};
+
+ extern int suppress_scan_chunks;
+ suppress_scan_chunks=1;
+
+ int i=0, j=0;
+
+ for(j=0;j<2;j++)
+ {
+ char* temp=0;
+ do {
+ temp=strchr(findGlob[j],'/');
+ if(temp)
+ *temp = '\\';
+ } while(temp);
+
+ // disabled because... apparently something is case sensitive??
+// for(i=1;i<strlen(findGlob[j]);i++)
+// findGlob[j][i] = tolower(findGlob[j][i]);
+ }
+
+// FCEU_PrintError(findGlob[0]);
+// FCEU_PrintError(findGlob[1]);
+
+ for(j=0;j<2;j++)
+ {
+ // if the two directories are the same, only look through one of them to avoid adding everything twice
+ if(j==1 && !strnicmp(findGlob[0],findGlob[1],MAX(strlen(findGlob[0]),strlen(findGlob[1]))-6))
+ continue;
+
+ char globBase[512];
+ strcpy(globBase,findGlob[j]);
+ globBase[strlen(globBase)-5]='\0';
+
+ extern char FileBase[];
+ char szFindPath[512];
+ WIN32_FIND_DATA wfd;
+ HANDLE hFind;
+
+ memset(&wfd, 0, sizeof(wfd));
+ hFind = FindFirstFile(findGlob[j], &wfd);
+ if(hFind != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ continue;
+
+ // filter out everything that's not *.fcm, *.fmv, *.vmv, or *.nmv
+ // (because FindFirstFile is too dumb to do that)
+ {
+ char* dot=strrchr(wfd.cFileName,'.');
+ if(!dot)
+ continue;
+ char ext [512];
+ strcpy(ext, dot+1);
+ int k, extlen=strlen(ext);
+ for(k=0;k<extlen;k++)
+ ext[k]=tolower(ext[k]);
+ if(strcmp(ext,"fcm") && strcmp(ext,"fmv") && strcmp(ext,"vmv") && strcmp(ext,"nmv"))
+ continue;
+ }
+
+ MOVIE_INFO info;
+ char metadata[MOVIE_MAX_METADATA];
+ char rom_name[MAX_PATH];
+
+ memset(&info, 0, sizeof(info));
+ info.metadata = metadata;
+ info.metadata_size = sizeof(metadata);
+ info.name_of_rom_used = rom_name;
+ info.name_of_rom_used_size = sizeof(rom_name);
+
+ char filename [512];
+ sprintf(filename, "%s%s", globBase, wfd.cFileName);
+
+ char* dot = strrchr(filename, '.');
+ int fcm = (dot && tolower(dot[1]) == 'f' && tolower(dot[2]) == 'c' && tolower(dot[3]) == 'm');
+
+ if(fcm && !FCEUI_MovieGetInfo(filename, &info))
+ continue;
+
+ char md51 [256];
+ char md52 [256];
+ if(fcm) strcpy(md51, md5_asciistr(FCEUGameInfo->MD5));
+ if(fcm) strcpy(md52, md5_asciistr(info.md5_of_rom_used));
+ if(!fcm || strcmp(md51, md52))
+ {
+ if(fcm)
+ {
+ int k, count1=0, count2=0;
+ for(k=0;k<strlen(md51);k++) count1 += md51[k]-'0';
+ for(k=0;k<strlen(md52);k++) count2 += md52[k]-'0';
+ if(count1 && count2)
+ continue;
+ }
+
+ char* tlen1=strstr(wfd.cFileName, " (");
+ char* tlen2=strstr(FileBase, " (");
+ int tlen3=tlen1?(int)(tlen1-wfd.cFileName):strlen(wfd.cFileName);
+ int tlen4=tlen2?(int)(tlen2-FileBase):strlen(FileBase);
+ int len=MAX(0,MIN(tlen3,tlen4));
+ if(strnicmp(wfd.cFileName, FileBase, len))
+ {
+ char temp[512];
+ strcpy(temp,FileBase);
+ temp[len]='\0';
+ if(!strstr(wfd.cFileName, temp))
+ continue;
+ }
+ }
+
+ char relative[MAX_PATH];
+ AbsoluteToRelative(relative, filename, BaseDirectory);
+ SendDlgItemMessage(hwndDlg, 200, CB_INSERTSTRING, i++, (LPARAM)relative);
+ } while(FindNextFile(hFind, &wfd));
+ FindClose(hFind);
+ }
+ }
+
+ suppress_scan_chunks=0;
+
+ free(findGlob[0]);
+ free(findGlob[1]);
+
+ if(i>0)
+ SendDlgItemMessage(hwndDlg, 200, CB_SETCURSEL, i-1, 0);
+ SendDlgItemMessage(hwndDlg, 200, CB_INSERTSTRING, i++, (LPARAM)"Browse...");
+
+ UpdateReplayDialog(hwndDlg);
+ }
+
+ SetFocus(GetDlgItem(hwndDlg, 200));
+ return FALSE;
+
+ case WM_COMMAND:
+ if(HIWORD(wParam) == CBN_SELCHANGE)
+ {
+ UpdateReplayDialog(hwndDlg);
+ }
+ else if(HIWORD(wParam) == CBN_CLOSEUP)
+ {
+ LONG lCount = SendDlgItemMessage(hwndDlg, 200, CB_GETCOUNT, 0, 0);
+ LONG lIndex = SendDlgItemMessage(hwndDlg, 200, CB_GETCURSEL, 0, 0);
+ if (lIndex != CB_ERR && lIndex == lCount-1)
+ SendMessage(hwndDlg, WM_COMMAND, (WPARAM)IDOK, 0); // send an OK notification to open the file browser
+ }
+ else
+ {
+ int wID = LOWORD(wParam);
+ switch(wID)
+ {
+ case IDOK:
+ {
+ LONG lCount = SendDlgItemMessage(hwndDlg, 200, CB_GETCOUNT, 0, 0);
+ LONG lIndex = SendDlgItemMessage(hwndDlg, 200, CB_GETCURSEL, 0, 0);
+ if(lIndex != CB_ERR)
+ {
+ if(lIndex == lCount-1)
+ {
+ // pop open a file browser...
+ char *pn=FCEU_GetPath(FCEUMKF_MOVIE);
+ char szFile[MAX_PATH]={0};
+ OPENFILENAME ofn;
+ int nRet;
+
+ memset(&ofn, 0, sizeof(ofn));
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = hwndDlg;
+ ofn.lpstrFilter = "Supported Movie Files (*.fcm|*.fmv|*.nmv|*.vmv)\0*.fcm;*.fmv;*.nmv;*.vmv\0FCEU Movie Files (*.fcm)\0*.fcm\0Famtasia Movie Files (*.fmv)\0*.fmv\0Nintendulator Movie Files (*.nmv)\0*.nmv\0VirtuaNES Movie Files (*.vmv)\0*.vmv\0All files(*.*)\0*.*\0\0";
+ ofn.lpstrFile = szFile;
+ ofn.nMaxFile = sizeof(szFile);
+ ofn.lpstrInitialDir = pn;
+ ofn.Flags = OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
+ ofn.lpstrDefExt = "fcm";
+ ofn.lpstrTitle = "Replay Movie from File";
+
+ if(GetOpenFileName(&ofn))
+ {
+ char relative[MAX_PATH];
+ AbsoluteToRelative(relative, szFile, BaseDirectory);
+
+ LONG lOtherIndex = SendDlgItemMessage(hwndDlg, 200, CB_FINDSTRING, (WPARAM)-1, (LPARAM)relative);
+ if(lOtherIndex != CB_ERR)
+ {
+ // select already existing string
+ SendDlgItemMessage(hwndDlg, 200, CB_SETCURSEL, lOtherIndex, 0);
+ } else {
+ SendDlgItemMessage(hwndDlg, 200, CB_INSERTSTRING, lIndex, (LPARAM)relative);
+ SendDlgItemMessage(hwndDlg, 200, CB_SETCURSEL, lIndex, 0);
+ }
+
+ // restore focus to the dialog
+ SetFocus(GetDlgItem(hwndDlg, 200));
+ UpdateReplayDialog(hwndDlg);
+// if (ofn.Flags & OFN_READONLY)
+// SendDlgItemMessage(hwndDlg, 201, BM_SETCHECK, BST_CHECKED, 0);
+// else
+// SendDlgItemMessage(hwndDlg, 201, BM_SETCHECK, BST_UNCHECKED, 0);
+ }
+
+ free(pn);
+ }
+ else
+ {
+ // user had made their choice
+ // TODO: warn the user when they open a movie made with a different ROM
+ char* fn=GetReplayPath(hwndDlg);
+ char TempArray[16];
+ ReplayDialogReadOnlyStatus = (SendDlgItemMessage(hwndDlg, 201, BM_GETCHECK, 0, 0) == BST_CHECKED) ? 1 : 0;
+
+ char offset1Str[32]={0};
+ char offset2Str[32]={0};
+
+ SendDlgItemMessage(hwndDlg, 1003, WM_GETTEXT, (WPARAM)32, (LPARAM)offset1Str);
+ ReplayDialogStopFrame = (SendDlgItemMessage(hwndDlg, 1002, BM_GETCHECK,0,0) == BST_CHECKED)? strtol(offset1Str,0,10):0;
+
+ SendDlgItemMessage(hwndDlg, 1000, WM_GETTEXT, (WPARAM)32, (LPARAM)offset1Str);
+ SendDlgItemMessage(hwndDlg, 1001, WM_GETTEXT, (WPARAM)32, (LPARAM)offset2Str);
+
+ movieConvertOffset1=strtol(offset1Str,0,10);
+ movieConvertOffset2=strtol(offset2Str,0,10);
+ movieConvertOK=1;
+
+ EndDialog(hwndDlg, (INT_PTR)fn);
+ }
+ }
+ }
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+ }
+ }
+
+ case WM_CTLCOLORSTATIC:
+ if((HWND)lParam == GetDlgItem(hwndDlg, 308))
+ {
+ // draw the md5 sum in red if it's different from the md5 of the rom used in the replay
+ HDC hdcStatic = (HDC)wParam;
+ char szMd5Text[35];
+
+ GetDlgItemText(hwndDlg, 305, szMd5Text, 35);
+ if(!strlen(szMd5Text) || !strcmp(szMd5Text, "unknown") || !strcmp(szMd5Text, "00000000000000000000000000000000") || !strcmp(szMd5Text, md5_asciistr(FCEUGameInfo->MD5)))
+ SetTextColor(hdcStatic, RGB(0,0,0)); // use black color for a match (or no comparison)
+ else
+ SetTextColor(hdcStatic, RGB(255,0,0)); // use red for a mismatch
+ SetBkMode(hdcStatic, TRANSPARENT);
+ return (LONG)GetStockObject(NULL_BRUSH);
+ }
+ else
+ return FALSE;
+ }
+
+ return FALSE;
+};
+
+void FCEUD_MovieReplayFrom(void)
+{
+ char* fn;
+
+ StopSound();
+
+ fn=(char*)DialogBox(fceu_hInstance, "IDD_REPLAYINP", hAppWnd, ReplayDialogProc);
+ if(fn)
+ {
+ FCEUI_LoadMovie(fn, ReplayDialogReadOnlyStatus, ReplayDialogStopFrame);
+ free(fn);
+ palyo=FCEUI_GetCurrentVidSystem(0,0);
+ UpdateMenu();
+ FixFL();
+ SetMainWindowStuff();
+ RefreshThrottleFPS();
+
+ extern int movie_readonly;
+ moviereadonly = movie_readonly; // for prefs
+ }
+}
+
+static void UpdateRecordDialogPath(HWND hwndDlg, const char* fname)
+{
+ char* baseMovieDir = FCEU_GetPath(FCEUMKF_MOVIE);
+ char* fn=0;
+
+ // display a shortened filename if the file exists in the base movie directory
+ if(!strncmp(fname, baseMovieDir, strlen(baseMovieDir)))
+ {
+ char szDrive[MAX_PATH]={0};
+ char szDirectory[MAX_PATH]={0};
+ char szFilename[MAX_PATH]={0};
+ char szExt[MAX_PATH]={0};
+
+ _splitpath(fname, szDrive, szDirectory, szFilename, szExt);
+ fn=(char*)malloc(strlen(szFilename)+strlen(szExt)+1);
+ _makepath(fn, "", "", szFilename, szExt);
+ }
+ else
+ fn=strdup(fname);
+
+ if(fn)
+ {
+ SetWindowText(GetDlgItem(hwndDlg,200),fn); // FIXME: make utf-8?
+ free(fn);
+ }
+}
+
+static void UpdateRecordDialog(HWND hwndDlg)
+{
+ int enable=0;
+ char* fn=0;
+
+ fn=GetRecordPath(hwndDlg);
+
+ if(fn)
+ {
+ if(access(fn, F_OK) ||
+ !access(fn, W_OK))
+ {
+ LONG lCount = SendDlgItemMessage(hwndDlg, 301, CB_GETCOUNT, 0, 0);
+ LONG lIndex = SendDlgItemMessage(hwndDlg, 301, CB_GETCURSEL, 0, 0);
+ if(lIndex != lCount-1)
+ {
+ enable=1;
+ }
+ }
+
+ free(fn);
+ }
+
+ EnableWindow(GetDlgItem(hwndDlg,1),enable ? TRUE : FALSE);
+}
+
+struct CreateMovieParameters
+{
+ char* szFilename; // on Dialog creation, this is the default filename to display. On return, this is the filename that the user chose.
+ int recordFrom; // 0 = "Power-On", 1 = "Reset", 2 = "Now", 3+ = savestate file in szSavestateFilename
+ char* szSavestateFilename;
+ WCHAR metadata[MOVIE_MAX_METADATA];
+};
+
+static BOOL CALLBACK RecordDialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ static struct CreateMovieParameters* p = NULL;
+
+ switch(uMsg)
+ {
+ case WM_INITDIALOG:
+ p = (struct CreateMovieParameters*)lParam;
+ UpdateRecordDialogPath(hwndDlg, p->szFilename);
+ free(p->szFilename);
+
+ /* Populate the "record from..." dialog */
+ {
+ char* findGlob=FCEU_MakeFName(FCEUMKF_STATEGLOB, 0, 0);
+ WIN32_FIND_DATA wfd;
+ HANDLE hFind;
+ int i=0;
+
+ SendDlgItemMessage(hwndDlg, 301, CB_INSERTSTRING, i++, (LPARAM)"Start");
+ SendDlgItemMessage(hwndDlg, 301, CB_INSERTSTRING, i++, (LPARAM)"Reset");
+ SendDlgItemMessage(hwndDlg, 301, CB_INSERTSTRING, i++, (LPARAM)"Now");
+
+ memset(&wfd, 0, sizeof(wfd));
+ hFind = FindFirstFile(findGlob, &wfd);
+ if(hFind != INVALID_HANDLE_VALUE)
+ {
+ do
+ {
+ if ((wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ||
+ (wfd.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
+ continue;
+
+ if (strlen(wfd.cFileName) < 4 ||
+ !strcmp(wfd.cFileName + (strlen(wfd.cFileName) - 4), ".fcm"))
+ continue;
+
+ SendDlgItemMessage(hwndDlg, 301, CB_INSERTSTRING, i++, (LPARAM)wfd.cFileName);
+ } while(FindNextFile(hFind, &wfd));
+ FindClose(hFind);
+ }
+ free(findGlob);
+
+ SendDlgItemMessage(hwndDlg, 301, CB_INSERTSTRING, i++, (LPARAM)"Browse...");
+ SendDlgItemMessage(hwndDlg, 301, CB_SETCURSEL, 0, 0); // choose "from reset" as a default
+ }
+ UpdateRecordDialog(hwndDlg);
+
+ return TRUE;
+
+ case WM_COMMAND:
+ if(HIWORD(wParam) == CBN_SELCHANGE)
+ {
+ LONG lIndex = SendDlgItemMessage(hwndDlg, 301, CB_GETCURSEL, 0, 0);
+ if(lIndex == CB_ERR)
+ {
+ // fix listbox selection
+ SendDlgItemMessage(hwndDlg, 301, CB_SETCURSEL, (WPARAM)0, 0);
+ }
+ UpdateRecordDialog(hwndDlg);
+ return TRUE;
+ }
+ else if(HIWORD(wParam) == CBN_CLOSEUP)
+ {
+ LONG lCount = SendDlgItemMessage(hwndDlg, 301, CB_GETCOUNT, 0, 0);
+ LONG lIndex = SendDlgItemMessage(hwndDlg, 301, CB_GETCURSEL, 0, 0);
+ if (lIndex != CB_ERR && lIndex == lCount-1)
+ {
+ OPENFILENAME ofn;
+ char szChoice[MAX_PATH]={0};
+
+ // pop open a file browser to choose the savestate
+ memset(&ofn, 0, sizeof(ofn));
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = hwndDlg;
+ ofn.lpstrFilter = "FCE Ultra Save State(*.fc?)\0*.fc?\0\0";
+ ofn.lpstrFile = szChoice;
+ ofn.lpstrDefExt = "fcs";
+ ofn.nMaxFile = MAX_PATH;
+ if(GetOpenFileName(&ofn))
+ {
+ SendDlgItemMessage(hwndDlg, 301, CB_INSERTSTRING, lIndex, (LPARAM)szChoice);
+ SendDlgItemMessage(hwndDlg, 301, CB_SETCURSEL, (WPARAM)lIndex, 0);
+ }
+ else
+ UpdateRecordDialog(hwndDlg);
+ }
+ return TRUE;
+ }
+ else if(HIWORD(wParam) == EN_CHANGE && LOWORD(wParam) == 200)
+ {
+ UpdateRecordDialog(hwndDlg);
+ }
+ else
+ {
+ switch(LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ LONG lIndex = SendDlgItemMessage(hwndDlg, 301, CB_GETCURSEL, 0, 0);
+ p->szFilename = GetRecordPath(hwndDlg);
+ GetDlgItemTextW(hwndDlg,300,p->metadata,MOVIE_MAX_METADATA);
+ p->recordFrom = (int)lIndex;
+ if(lIndex>=3)
+ p->szSavestateFilename = GetSavePath(hwndDlg);
+ EndDialog(hwndDlg, 1);
+ }
+ return TRUE;
+
+ case IDCANCEL:
+ EndDialog(hwndDlg, 0);
+ return TRUE;
+
+ case 201:
+ {
+ OPENFILENAME ofn;
+ char szChoice[MAX_PATH]={0};
+
+ // browse button
+ memset(&ofn, 0, sizeof(ofn));
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = hwndDlg;
+ ofn.lpstrFilter = "FCE Ultra Movie File(*.fcm)\0*.fcm\0All files(*.*)\0*.*\0\0";
+ ofn.lpstrFile = szChoice;
+ ofn.lpstrDefExt = "fcm";
+ ofn.nMaxFile = MAX_PATH;
+ ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
+ if(GetSaveFileName(&ofn))
+ UpdateRecordDialogPath(hwndDlg,szChoice);
+ }
+ return TRUE;
+ }
+ }
+ }
+
+ return FALSE;
+}
+
+void FCEUD_MovieRecordTo(void)
+{
+ struct CreateMovieParameters p;
+ p.szFilename=FCEUI_MovieGetCurrentName(0);
+
+ StopSound();
+
+ if(DialogBoxParam(fceu_hInstance,"IDD_RECORDINP",hAppWnd,RecordDialogProc,(LPARAM)&p))
+ {
+ // turn WCHAR into UTF8
+ char meta[MOVIE_MAX_METADATA<<2];
+ WideCharToMultiByte(CP_UTF8, 0, p.metadata, -1, meta, sizeof(meta), NULL, NULL);
+
+ if(p.recordFrom >= 3)
+ {
+ // attempt to load the savestate
+ // FIXME: pop open a messagebox if this fails
+ FCEUI_LoadState(p.szSavestateFilename);
+ {
+ extern int loadStateFailed;
+ if(loadStateFailed)
+ {
+ char str [1024];
+ sprintf(str, "Failed to load save state \"%s\".\nRecording from current state instead...", p.szSavestateFilename);
+ FCEUD_PrintError(str);
+ }
+ }
+ free(p.szSavestateFilename);
+ }
+
+ FCEUI_SaveMovie(p.szFilename, (p.recordFrom==0) ? MOVIE_FLAG_FROM_POWERON : ((p.recordFrom==1) ? MOVIE_FLAG_FROM_RESET : 0), meta);
+ }
+
+ free(p.szFilename);
+}
+
+void FCEUD_AviRecordTo(void)
+{
+ OPENFILENAME ofn;
+ char szChoice[MAX_PATH];
+
+ if(FCEUMOV_IsPlaying())
+ {
+ extern char curMovieFilename[];
+ strcpy(szChoice, curMovieFilename);
+ char* dot=strrchr(szChoice,'.');
+ if(dot) *dot='\0';
+ strcat(szChoice,".avi");
+ }
+ else
+ {
+ extern char FileBase[];
+ sprintf(szChoice, "%s.avi", FileBase);
+ }
+
+ StopSound();
+
+ // avi record file browser
+ memset(&ofn, 0, sizeof(ofn));
+ ofn.lStructSize = sizeof(ofn);
+ ofn.hwndOwner = hAppWnd;
+ ofn.lpstrFilter = "AVI Files (*.avi)\0*.avi\0\0";
+ ofn.lpstrFile = szChoice;
+ ofn.lpstrDefExt = "avi";
+ ofn.lpstrTitle = "Save AVI as";
+
+ ofn.nMaxFile = MAX_PATH;
+ ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT;
+ if(GetSaveFileName(&ofn))
+ {
+ FCEUI_AviBegin(szChoice);
+ }
+}
+
+void FCEUD_AviStop(void)
+{
+ FCEUI_AviEnd();
+}
+
+void FCEUD_CmdOpen(void)
+{
+ StopSound();
+ LoadNewGamey(hAppWnd, 0);
+}
+
diff --git a/endian.c b/endian.c
new file mode 100644
index 00000000..1295064e
--- /dev/null
+++ b/endian.c
@@ -0,0 +1,103 @@
+/* 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
+ */
+
+/* Contains file I/O functions that write/read data */
+/* LSB first. */
+
+
+#include <stdio.h>
+#include "types.h"
+#include "endian.h"
+
+void FlipByteOrder(uint8 *src, uint32 count)
+{
+ uint8 *start=src;
+ uint8 *end=src+count-1;
+
+ if((count&1) || !count) return; /* This shouldn't happen. */
+
+ while(count--)
+ {
+ uint8 tmp;
+
+ tmp=*end;
+ *end=*start;
+ *start=tmp;
+ end--;
+ start++;
+ }
+}
+
+int write16le(uint16 b, FILE *fp)
+{
+ uint8 s[2];
+ s[0]=b;
+ s[1]=b>>8;
+ return((fwrite(s,1,2,fp)<2)?0:2);
+}
+
+int write32le(uint32 b, FILE *fp)
+{
+ uint8 s[4];
+ s[0]=b;
+ s[1]=b>>8;
+ s[2]=b>>16;
+ s[3]=b>>24;
+ return((fwrite(s,1,4,fp)<4)?0:4);
+}
+
+int read32le(uint32 *Bufo, FILE *fp)
+{
+ uint32 buf;
+ if(fread(&buf,1,4,fp)<4)
+ return 0;
+ #ifdef LSB_FIRST
+ *(uint32*)Bufo=buf;
+ #else
+ *(uint32*)Bufo=((buf&0xFF)<<24)|((buf&0xFF00)<<8)|((buf&0xFF0000)>>8)|((buf&0xFF000000)>>24);
+ #endif
+ return 1;
+}
+
+int read16le(char *d, FILE *fp)
+{
+ #ifdef LSB_FIRST
+ return((fread(d,1,2,fp)<2)?0:2);
+ #else
+ int ret;
+ ret=fread(d+1,1,1,fp);
+ ret+=fread(d,1,1,fp);
+ return ret<2?0:2;
+ #endif
+}
+
+void FCEU_en32lsb(uint8 *buf, uint32 morp)
+{
+ buf[0]=morp;
+ buf[1]=morp>>8;
+ buf[2]=morp>>16;
+ buf[3]=morp>>24;
+}
+
+uint32 FCEU_de32lsb(uint8 *morp)
+{
+ return(morp[0]|(morp[1]<<8)|(morp[2]<<16)|(morp[3]<<24));
+}
+
diff --git a/endian.h b/endian.h
new file mode 100644
index 00000000..85b7d381
--- /dev/null
+++ b/endian.h
@@ -0,0 +1,7 @@
+int write16le(uint16 b, FILE *fp);
+int write32le(uint32 b, FILE *fp);
+int read32le(uint32 *Bufo, FILE *fp);
+void FlipByteOrder(uint8 *src, uint32 count);
+
+void FCEU_en32lsb(uint8 *, uint32);
+uint32 FCEU_de32lsb(uint8 *);
diff --git a/fceu.c b/fceu.c
new file mode 100644
index 00000000..0fd37743
--- /dev/null
+++ b/fceu.c
@@ -0,0 +1,780 @@
+/* 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 <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#ifdef _USE_SHARED_MEMORY_
+#include <windows.h>
+#endif
+
+#include "types.h"
+#include "x6502.h"
+#include "fceu.h"
+#include "ppu.h"
+#include "sound.h"
+#include "netplay.h"
+#include "general.h"
+#include "endian.h"
+#include "memory.h"
+
+#include "cart.h"
+#include "nsf.h"
+#include "fds.h"
+#include "ines.h"
+#include "unif.h"
+#include "cheat.h"
+#include "palette.h"
+#include "state.h"
+#include "movie.h"
+#include "video.h"
+#include "input.h"
+#include "file.h"
+#include "crc32.h"
+#include "vsuni.h"
+#ifdef _USE_SHARED_MEMORY_
+#include "drivers/win/basicbot.h"
+#endif
+
+uint64 timestampbase;
+
+
+FCEUGI *FCEUGameInfo = NULL;
+void (*GameInterface)(int h);
+
+void (*GameStateRestore)(int version);
+
+readfunc ARead[0x10000];
+writefunc BWrite[0x10000];
+static readfunc *AReadG;
+static writefunc *BWriteG;
+static int RWWrap=0;
+static int EmulationPaused=0;
+static int RewindStatus[4] = {0, 0, 0, 0}; //is it safe to load rewind state
+static int RewindIndex = 0; //which rewind state we're on
+int EnableRewind = 0; //is rewind enabled
+
+static DECLFW(BNull)
+{
+
+}
+
+static DECLFR(ANull)
+{
+ return(X.DB);
+}
+
+int AllocGenieRW(void)
+{
+ if(!(AReadG=(readfunc *)FCEU_malloc(0x8000*sizeof(readfunc))))
+ return 0;
+ if(!(BWriteG=(writefunc *)FCEU_malloc(0x8000*sizeof(writefunc))))
+ return 0;
+ RWWrap=1;
+ return 1;
+}
+
+void FlushGenieRW(void)
+{
+ int32 x;
+
+ if(RWWrap)
+ {
+ for(x=0;x<0x8000;x++)
+ {
+ ARead[x+0x8000]=AReadG[x];
+ BWrite[x+0x8000]=BWriteG[x];
+ }
+ free(AReadG);
+ free(BWriteG);
+ AReadG=0;
+ BWriteG=0;
+ RWWrap=0;
+ }
+}
+
+readfunc FASTAPASS(1) GetReadHandler(int32 a)
+{
+ if(a>=0x8000 && RWWrap)
+ return AReadG[a-0x8000];
+ else
+ return ARead[a];
+}
+
+void FASTAPASS(3) SetReadHandler(int32 start, int32 end, readfunc func)
+{
+ int32 x;
+
+ if(!func)
+ func=ANull;
+
+ if(RWWrap)
+ for(x=end;x>=start;x--)
+ {
+ if(x>=0x8000)
+ AReadG[x-0x8000]=func;
+ else
+ ARead[x]=func;
+ }
+ else
+
+ for(x=end;x>=start;x--)
+ ARead[x]=func;
+}
+
+writefunc FASTAPASS(1) GetWriteHandler(int32 a)
+{
+ if(RWWrap && a>=0x8000)
+ return BWriteG[a-0x8000];
+ else
+ return BWrite[a];
+}
+
+void FASTAPASS(3) SetWriteHandler(int32 start, int32 end, writefunc func)
+{
+ int32 x;
+
+ if(!func)
+ func=BNull;
+
+ if(RWWrap)
+ for(x=end;x>=start;x--)
+ {
+ if(x>=0x8000)
+ BWriteG[x-0x8000]=func;
+ else
+ BWrite[x]=func;
+ }
+ else
+ for(x=end;x>=start;x--)
+ BWrite[x]=func;
+}
+
+#ifdef _USE_SHARED_MEMORY_
+HANDLE mapGameMemBlock;
+uint8 *GameMemBlock;
+HANDLE mapRAM;
+uint8 *RAM;
+HANDLE mapBotInput;
+uint32 *BotInput;
+#else
+uint8 GameMemBlock[131072];
+uint8 RAM[0x800];
+#endif //_USE_SHARED_MEMORY_
+
+uint8 PAL=0;
+
+
+static DECLFW(BRAML)
+{
+ RAM[A]=V;
+}
+
+static DECLFW(BRAMH)
+{
+ RAM[A&0x7FF]=V;
+}
+
+static DECLFR(ARAML)
+{
+ return RAM[A];
+}
+
+static DECLFR(ARAMH)
+{
+ return RAM[A&0x7FF];
+}
+
+static void CloseGame(void)
+{
+ if(FCEUGameInfo)
+ {
+ if(FCEUnetplay)
+ FCEUD_NetworkClose();
+ FCEUI_StopMovie();
+ if(FCEUGameInfo->name)
+ {
+ free(FCEUGameInfo->name);
+ FCEUGameInfo->name=0;
+ }
+ if(FCEUGameInfo->type!=GIT_NSF)
+ FCEU_FlushGameCheats(0,0);
+ GameInterface(GI_CLOSE);
+ ResetExState(0,0);
+ CloseGenie();
+ free(FCEUGameInfo);
+ FCEUGameInfo = 0;
+ }
+}
+
+void ResetGameLoaded(void)
+{
+ if(FCEUGameInfo) CloseGame();
+ GameStateRestore=0;
+ PPU_hook=0;
+ GameHBIRQHook=0;
+ if(GameExpSound.Kill)
+ GameExpSound.Kill();
+ memset(&GameExpSound,0,sizeof(GameExpSound));
+ MapIRQHook=0;
+ MMC5Hack=0;
+ PAL&=1;
+ pale=0;
+}
+
+int UNIFLoad(const char *name, FCEUFILE *fp);
+int iNESLoad(const char *name, FCEUFILE *fp, int OverwriteVidMode);
+int FDSLoad(const char *name, FCEUFILE *fp);
+int NSFLoad(FCEUFILE *fp);
+
+char lastLoadedGameName [2048] = {0,}; // hack for movie WRAM clearing on record from poweron
+
+FCEUGI *FCEUI_LoadGame(const char *name, int OverwriteVidMode)
+{
+#ifdef WIN32
+ StopSound();
+#endif
+
+ FCEUFILE *fp;
+ char *ipsfn;
+
+ ResetGameLoaded();
+
+ RewindStatus[0] = RewindStatus[1] = 0;
+ RewindStatus[2] = RewindStatus[3] = 0;
+
+ FCEUGameInfo = malloc(sizeof(FCEUGI));
+ memset(FCEUGameInfo, 0, sizeof(FCEUGI));
+
+ FCEUGameInfo->soundchan = 0;
+ FCEUGameInfo->soundrate = 0;
+ FCEUGameInfo->name=0;
+ FCEUGameInfo->type=GIT_CART;
+ FCEUGameInfo->vidsys=GIV_USER;
+ FCEUGameInfo->input[0]=FCEUGameInfo->input[1]=-1;
+ FCEUGameInfo->inputfc=-1;
+ FCEUGameInfo->cspecial=0;
+
+ FCEU_printf("Loading %s...\n\n",name);
+
+ GetFileBase(name);
+
+ ipsfn=FCEU_MakeFName(FCEUMKF_IPS,0,0);
+ fp=FCEU_fopen(name,ipsfn,"rb",0);
+ free(ipsfn);
+
+ if(!fp)
+ {
+ FCEU_PrintError("Error opening \"%s\"!",name);
+ return 0;
+ }
+
+ if(iNESLoad(name,fp,OverwriteVidMode))
+ goto endlseq;
+ if(NSFLoad(fp))
+ goto endlseq;
+ if(UNIFLoad(name,fp))
+ goto endlseq;
+ if(FDSLoad(name,fp))
+ goto endlseq;
+
+ FCEU_PrintError("An error occurred while loading the file.");
+ FCEUD_PrintError("An error occurred while loading the file.");
+ FCEU_fclose(fp);
+ return 0;
+
+ endlseq:
+
+ FCEU_fclose(fp);
+
+ FCEU_ResetVidSys();
+
+ if(FCEUGameInfo->type!=GIT_NSF)
+ if(FSettings.GameGenie)
+ OpenGenie();
+ PowerNES();
+
+ FCEUSS_CheckStates();
+ FCEUMOV_CheckMovies();
+
+ if(FCEUGameInfo->type!=GIT_NSF)
+ {
+ FCEU_LoadGamePalette();
+ FCEU_LoadGameCheats(0);
+ }
+
+ FCEU_ResetPalette();
+ FCEU_ResetMessages(); // Save state, status messages, etc.
+
+ strcpy(lastLoadedGameName, name);
+
+ return(FCEUGameInfo);
+}
+
+
+int FCEUI_Initialize(void)
+{
+#ifdef _USE_SHARED_MEMORY_
+ // set up shared memory mappings
+ mapGameMemBlock = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE, 0, 131072,"fceu.GameMemBlock");
+ if(mapGameMemBlock == NULL || GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ CloseHandle(mapGameMemBlock);
+ mapGameMemBlock = NULL;
+ GameMemBlock = (uint8 *) malloc(131072);
+ RAM = (uint8 *) malloc(2048);
+ }
+ else
+ {
+ GameMemBlock = (uint8 *)MapViewOfFile(mapGameMemBlock, FILE_MAP_WRITE, 0, 0, 0);
+
+ // set up shared memory mappings
+ mapRAM = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE, 0, 0x800,"fceu.RAM");
+ RAM = (uint8 *)MapViewOfFile(mapRAM, FILE_MAP_WRITE, 0, 0, 0);
+ }
+
+ // Give RAM pointer to state structure
+ extern SFORMAT SFCPU[];
+ SFCPU[6].v = RAM;
+
+ //Bot input
+ mapBotInput = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE,0, 4096, "fceu.BotInput");
+ BotInput = (uint32 *) MapViewOfFile(mapBotInput, FILE_MAP_WRITE, 0, 0, 0);
+ BotInput[0] = 0;
+
+#endif //_USE_SHARED_MEMORY_
+
+ if(!FCEU_InitVirtualVideo())
+ return 0;
+ memset(&FSettings,0,sizeof(FSettings));
+ FSettings.UsrFirstSLine[0]=8;
+ FSettings.UsrFirstSLine[1]=0;
+ FSettings.UsrLastSLine[0]=231;
+ FSettings.UsrLastSLine[1]=239;
+ FSettings.SoundVolume=100;
+ FCEUPPU_Init();
+ X6502_Init();
+ return 1;
+}
+
+void FCEUI_Kill(void)
+{
+ FCEU_KillVirtualVideo();
+ FCEU_KillGenie();
+
+#ifdef _USE_SHARED_MEMORY_
+ //clean up shared memory
+ if(mapRAM)
+ {
+ UnmapViewOfFile(mapRAM);
+ CloseHandle(mapRAM);
+ RAM = NULL;
+ }
+ else
+ {
+ free(RAM);
+ RAM = NULL;
+ }
+ if(mapGameMemBlock)
+ {
+ UnmapViewOfFile(mapGameMemBlock);
+ CloseHandle(mapGameMemBlock);
+ GameMemBlock = NULL;
+ }
+ else
+ {
+ free(GameMemBlock);
+ GameMemBlock = NULL;
+ }
+
+ UnmapViewOfFile(mapBotInput);
+ CloseHandle(mapBotInput);
+ BotInput = NULL;
+#endif
+}
+
+int rapidAlternator = 0;
+int AutoFirePattern[8] = {1,0,0,0,0,0,0,0};
+int AutoFirePatternLength = 2;
+int AutoFireOffset = 0;
+
+void SetAutoFirePattern(int onframes, int offframes)
+{
+ int i;
+ for(i = 0; i < onframes && i < 8; i++)
+ {
+ AutoFirePattern[i] = 1;
+ }
+ for(;i < 8; i++)
+ {
+ AutoFirePattern[i] = 0;
+ }
+ if(onframes + offframes < 2)
+ {
+ AutoFirePatternLength = 2;
+ }
+ else if(onframes + offframes > 8)
+ {
+ AutoFirePatternLength = 8;
+ }
+ else
+ {
+ AutoFirePatternLength = onframes + offframes;
+ }
+}
+
+void SetAutoFireOffset(int offset)
+{
+ if(offset < 0 || offset > 8) return;
+ AutoFireOffset = offset;
+}
+
+void AutoFire(void)
+{
+ static int counter = 0;
+ counter = (++counter) % (8*7*5*3);
+ //If recording a movie, use the frame # for the autofire so the offset
+ //doesn't get screwed up when loading.
+ if(FCEUMOV_IsPlaying() || FCEUMOV_IsRecording())
+ {
+ rapidAlternator= AutoFirePattern[(AutoFireOffset + FCEUMOV_GetFrame())%AutoFirePatternLength];
+ }
+ else
+ {
+ rapidAlternator= AutoFirePattern[(AutoFireOffset + counter)%AutoFirePatternLength];
+ }
+}
+
+void UpdateRewind(void);
+
+void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int skip)
+{
+ int r,ssize;
+
+#ifdef _USE_SHARED_MEMORY_
+ UpdateBasicBot();
+#endif
+
+ FCEU_UpdateBot();
+
+ if(EmulationPaused&2)
+ EmulationPaused &= ~1; // clear paused flag temporarily (frame advance)
+ else if(EmulationPaused&1 || FCEU_BotMode())
+ {
+ memcpy(XBuf, XBackBuf, 256*256);
+ FCEU_PutImage();
+ *pXBuf=XBuf;
+ *SoundBuf=WaveFinal;
+ *SoundBufSize=0;
+
+ return;
+ }
+
+ if(!FCEU_BotMode())
+ {
+ AutoFire();
+ UpdateRewind();
+ }
+
+ FCEU_UpdateInput();
+ if(geniestage!=1) FCEU_ApplyPeriodicCheats();
+ r=FCEUPPU_Loop(skip);
+
+ ssize=FlushEmulateSound();
+
+//#ifdef WIN32
+// FCEUI_AviVideoUpdate(XBuf);
+//#endif
+
+ timestampbase += timestamp;
+ timestamp = 0;
+
+
+ *pXBuf=skip?0:XBuf;
+ *SoundBuf=WaveFinal;
+ *SoundBufSize=ssize;
+
+ if(EmulationPaused&2)
+ {
+ EmulationPaused = 1; // restore paused flag
+#ifdef WIN32
+ #define SO_MUTEFA 16
+ extern int soundoptions;
+ if(soundoptions&SO_MUTEFA)
+#endif
+ *SoundBufSize=0; // keep sound muted
+ }
+}
+
+void FCEUI_CloseGame(void)
+{
+ CloseGame();
+}
+
+void RestartMovieOrReset(int pow)
+{
+ extern int movie_readonly;
+ if(FCEUMOV_IsPlaying() || FCEUMOV_IsRecording() && movie_readonly)
+ {
+ extern char curMovieFilename[512];
+ FCEUI_LoadMovie(curMovieFilename, movie_readonly, 0);
+ if(FCEUI_IsMovieActive())
+ return;
+ }
+
+ if(pow)
+ FCEUI_PowerNES();
+ else
+ FCEUI_ResetNES();
+}
+
+void ResetNES(void)
+{
+ FCEUMOV_AddCommand(FCEUNPCMD_RESET);
+ if(!FCEUGameInfo) return;
+ GameInterface(GI_RESETM2);
+ FCEUSND_Reset();
+ FCEUPPU_Reset();
+ X6502_Reset();
+
+ // clear back baffer
+ extern uint8 *XBackBuf;
+ memset(XBackBuf,0,256*256);
+}
+
+void FCEU_MemoryRand(uint8 *ptr, uint32 size)
+{
+ int x=0;
+ while(size)
+ {
+ *ptr=(x&4)?0xFF:0x00;
+ x++;
+ size--;
+ ptr++;
+ }
+}
+
+void hand(X6502 *X, int type, unsigned int A)
+{
+
+}
+
+int suppressAddPowerCommand=0; // hack... yeah, I know...
+void PowerNES(void)
+{
+ if(!suppressAddPowerCommand)
+ FCEUMOV_AddCommand(FCEUNPCMD_POWER);
+ if(!FCEUGameInfo) return;
+
+ FCEU_CheatResetRAM();
+ FCEU_CheatAddRAM(2,0,RAM);
+
+ GeniePower();
+
+ FCEU_MemoryRand(RAM,0x800);
+ //memset(RAM,0xFF,0x800);
+
+ SetReadHandler(0x0000,0xFFFF,ANull);
+ SetWriteHandler(0x0000,0xFFFF,BNull);
+
+ SetReadHandler(0,0x7FF,ARAML);
+ SetWriteHandler(0,0x7FF,BRAML);
+
+ SetReadHandler(0x800,0x1FFF,ARAMH); /* Part of a little */
+ SetWriteHandler(0x800,0x1FFF,BRAMH); /* hack for a small speed boost. */
+
+ InitializeInput();
+ FCEUSND_Power();
+ FCEUPPU_Power();
+
+ /* Have the external game hardware "powered" after the internal NES stuff.
+ Needed for the NSF code and VS System code.
+ */
+ GameInterface(GI_POWER);
+ if(FCEUGameInfo->type==GIT_VSUNI)
+ FCEU_VSUniPower();
+
+ timestampbase=0;
+ X6502_Power();
+ FCEU_PowerCheats();
+ // clear back baffer
+ extern uint8 *XBackBuf;
+ memset(XBackBuf,0,256*256);
+}
+
+void FCEU_ResetVidSys(void)
+{
+ int w;
+
+ if(FCEUGameInfo->vidsys==GIV_NTSC)
+ w=0;
+ else if(FCEUGameInfo->vidsys==GIV_PAL)
+ w=1;
+ else
+ w=FSettings.PAL;
+
+ PAL=w?1:0;
+ FCEUPPU_SetVideoSystem(w);
+ SetSoundVariables();
+}
+
+FCEUS FSettings;
+
+void FCEU_printf(char *format, ...)
+{
+ char temp[2048];
+
+ va_list ap;
+
+ va_start(ap,format);
+ vsprintf(temp,format,ap);
+ FCEUD_Message(temp);
+
+ va_end(ap);
+}
+
+void FCEU_PrintError(char *format, ...)
+{
+ char temp[2048];
+
+ va_list ap;
+
+ va_start(ap,format);
+ vsprintf(temp,format,ap);
+ FCEUD_PrintError(temp);
+
+ va_end(ap);
+}
+
+void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall)
+{
+ FSettings.UsrFirstSLine[0]=ntscf;
+ FSettings.UsrLastSLine[0]=ntscl;
+ FSettings.UsrFirstSLine[1]=palf;
+ FSettings.UsrLastSLine[1]=pall;
+ if(PAL)
+ {
+ FSettings.FirstSLine=FSettings.UsrFirstSLine[1];
+ FSettings.LastSLine=FSettings.UsrLastSLine[1];
+ }
+ else
+ {
+ FSettings.FirstSLine=FSettings.UsrFirstSLine[0];
+ FSettings.LastSLine=FSettings.UsrLastSLine[0];
+ }
+
+}
+
+void FCEUI_SetVidSystem(int a)
+{
+ FSettings.PAL=a?1:0;
+ if(FCEUGameInfo)
+ {
+ FCEU_ResetVidSys();
+ FCEU_ResetPalette();
+ }
+}
+
+int FCEUI_GetCurrentVidSystem(int *slstart, int *slend)
+{
+ if(slstart)
+ *slstart=FSettings.FirstSLine;
+ if(slend)
+ *slend=FSettings.LastSLine;
+ return(PAL);
+}
+
+void FCEUI_SetGameGenie(int a)
+{
+ FSettings.GameGenie=a?1:0;
+}
+
+void FCEUI_SetSnapName(int a)
+{
+ FSettings.SnapName=a;
+}
+
+int32 FCEUI_GetDesiredFPS(void)
+{
+ if(PAL)
+ return(838977920); // ~50.007
+ else
+ return(1008307711); // ~60.1
+}
+
+int FCEUI_EmulationPaused(void)
+{
+ return (EmulationPaused&1);
+}
+
+void FCEUI_ToggleEmulationPause(void)
+{
+ EmulationPaused = (EmulationPaused&1)^1;
+}
+
+void FCEUI_FrameAdvance(void)
+{
+ EmulationPaused |= 1|2;
+}
+
+static int RewindCounter = 0;
+
+void UpdateRewind(void)
+{
+ if(!EnableRewind)
+ return;
+
+ char * f;
+ RewindCounter = (RewindCounter + 1) % 256;
+ if(RewindCounter == 0)
+ {
+ RewindIndex = (RewindIndex + 1) % 4;
+ f = FCEU_MakeFName(FCEUMKF_REWINDSTATE,RewindIndex,0);
+ FCEUSS_Save(f);
+ free(f);
+ RewindStatus[RewindIndex] = 1;
+ }
+}
+
+void FCEUI_Rewind(void)
+{
+ if(!EnableRewind)
+ return;
+
+ if(RewindStatus[RewindIndex] == 1)
+ {
+ char * f;
+ f = FCEU_MakeFName(FCEUMKF_REWINDSTATE,RewindIndex,0);
+ FCEUSS_Load(f);
+ free(f);
+
+ //Set pointer to previous available slot
+ if(RewindStatus[(RewindIndex + 3)%4] == 1)
+ {
+ RewindIndex = (RewindIndex + 3)%4;
+ }
+
+ //Reset time to next rewind save
+ RewindCounter = 0;
+ }
+}
+
diff --git a/fceu.h b/fceu.h
new file mode 100644
index 00000000..624a803a
--- /dev/null
+++ b/fceu.h
@@ -0,0 +1,115 @@
+#ifndef _FCEUH
+#define _FCEUH
+
+extern int fceuindbg;
+void ResetGameLoaded(void);
+
+#define DECLFR(x) uint8 FP_FASTAPASS(1) x (uint32 A)
+#define DECLFW(x) void FP_FASTAPASS(2) x (uint32 A, uint8 V)
+
+void FCEU_MemoryRand(uint8 *ptr, uint32 size);
+void FASTAPASS(3) SetReadHandler(int32 start, int32 end, readfunc func);
+void FASTAPASS(3) SetWriteHandler(int32 start, int32 end, writefunc func);
+writefunc FASTAPASS(1) GetWriteHandler(int32 a);
+readfunc FASTAPASS(1) GetReadHandler(int32 a);
+
+int AllocGenieRW(void);
+void FlushGenieRW(void);
+
+void FCEU_ResetVidSys(void);
+
+void ResetMapping(void);
+void ResetNES(void);
+void PowerNES(void);
+
+void SetAutoFireOffset(int offset);
+void SetAutoFirePattern(int onframes, int offframes);
+void AutoFire(void);
+void FCEUI_Rewind(void);
+
+extern uint64 timestampbase;
+extern uint32 MMC5HackVROMMask;
+extern uint8 *MMC5HackExNTARAMPtr;
+extern int MMC5Hack;
+extern uint8 *MMC5HackVROMPTR;
+extern uint8 MMC5HackCHRMode;
+extern uint8 MMC5HackSPMode;
+extern uint8 MMC5HackSPScroll;
+extern uint8 MMC5HackSPPage;
+
+#ifdef _USE_SHARED_MEMORY_
+extern uint8 *RAM; //shared memory modifications
+extern uint8 *GameMemBlock; //shared memory modifications
+extern uint32 *BotInput;
+#else
+extern uint8 RAM[0x800];
+extern uint8 GameMemBlock[131072];
+#endif
+
+extern readfunc ARead[0x10000];
+extern writefunc BWrite[0x10000];
+
+extern void (*GameInterface)(int h);
+extern void (*GameStateRestore)(int version);
+
+#define GI_RESETM2 1
+#define GI_POWER 2
+#define GI_CLOSE 3
+
+#include "git.h"
+extern FCEUGI *FCEUGameInfo;
+extern int GameAttributes;
+
+extern uint8 PAL;
+
+#include "driver.h"
+
+typedef struct {
+ int PAL;
+ int NetworkPlay;
+ int SoundVolume;
+ int GameGenie;
+
+ /* Current first and last rendered scanlines. */
+ int FirstSLine;
+ int LastSLine;
+
+ /* Driver code(user)-specified first and last rendered scanlines.
+ Usr*SLine[0] is for NTSC, Usr*SLine[1] is for PAL.
+ */
+ int UsrFirstSLine[2];
+ int UsrLastSLine[2];
+ int SnapName;
+ uint32 SndRate;
+ int soundq;
+ int lowpass;
+} FCEUS;
+
+extern FCEUS FSettings;
+
+void FCEU_PrintError(char *format, ...);
+void FCEU_printf(char *format, ...);
+void FCEU_DispMessage(char *format, ...);
+
+void SetNESDeemph(uint8 d, int force);
+void DrawTextTrans(uint8 *dest, uint32 width, uint8 *textmsg, uint8 fgcolor);
+void FCEU_PutImage(void);
+#ifdef FRAMESKIP
+void FCEU_PutImageDummy(void);
+#endif
+
+extern uint8 Exit;
+extern uint8 pale;
+extern uint8 vsdip;
+
+#define FCEUDEF_DEBUGGER
+
+#define JOY_A 1
+#define JOY_B 2
+#define JOY_SELECT 4
+#define JOY_START 8
+#define JOY_UP 0x10
+#define JOY_DOWN 0x20
+#define JOY_LEFT 0x40
+#define JOY_RIGHT 0x80
+#endif
diff --git a/fceustr.c b/fceustr.c
new file mode 100644
index 00000000..3904bb4c
--- /dev/null
+++ b/fceustr.c
@@ -0,0 +1,27 @@
+#include <string.h>
+#include <stdlib.h>
+
+#include "types.h"
+#include "fceustr.h"
+
+
+/* Creates a fceustr from a C-style string. */
+fceustr *fceustr_create(const char *str)
+{
+ fceustr *ret;
+
+ ret=malloc(sizeof(fceustr));
+
+ ret->data=malloc(strlen(str)+1);
+ strcpy(ret->data,str);
+
+ ret->len=strlen(str);
+
+ return(ret);
+}
+
+void fceustr_destroy(fceustr *str)
+{
+ if(str->data) free(str->data);
+ free(str);
+}
diff --git a/fceustr.h b/fceustr.h
new file mode 100644
index 00000000..7033c3b0
--- /dev/null
+++ b/fceustr.h
@@ -0,0 +1,4 @@
+typedef struct {
+ uint8 *data;
+ uint32 len; /* Not including extra NULL character. */
+} fceustr;
diff --git a/fcoeffs.h b/fcoeffs.h
new file mode 100644
index 00000000..38c4370c
--- /dev/null
+++ b/fcoeffs.h
@@ -0,0 +1,1589 @@
+#define SQ2NCOEFFS 1024
+
+static int32 sq2coeffs[SQ2NCOEFFS];
+
+static int32 SQ2C44100NTSC[SQ2NCOEFFS/2]=
+{
+ #include "fir/c44100ntsc.h"
+};
+
+static int32 SQ2C48000NTSC[SQ2NCOEFFS/2]=
+{
+ #include "fir/c48000ntsc.h"
+};
+
+static int32 SQ2C96000NTSC[SQ2NCOEFFS/2]=
+{
+ #include "fir/c96000ntsc.h"
+};
+
+static int32 SQ2C44100PAL[SQ2NCOEFFS/2]=
+{
+ #include "fir/c44100pal.h"
+};
+
+static int32 SQ2C48000PAL[SQ2NCOEFFS/2]=
+{
+ #include "fir/c48000pal.h"
+};
+
+static int32 SQ2C96000PAL[SQ2NCOEFFS/2]=
+{
+ #include "fir/c96000pal.h"
+};
+
+#define NCOEFFS 484
+
+static int32 coeffs[NCOEFFS];
+
+/* 96000hz filter could probably be improved. */
+
+/*
+Parks-McClellan FIR Filter Design
+
+Filter type: Low pass
+Passband: 0 - 0.016761904
+Order: 483
+Passband ripple: 0.01 dB
+Transition band: 0.01005714
+Stopband attenuation: 103.0 dB
+
+Coefficients:
+*/
+static int32 C96000NTSC[NCOEFFS/2]=
+{
+/*0*/ 65536*16* -5.9950991853042605E-6
+/*1*/, 65536*16* -3.0394382502604395E-6
+/*2*/, 65536*16* -3.728403434239284E-6
+/*3*/, 65536*16* -4.460351826790638E-6
+/*4*/, 65536*16* -5.2164320385801135E-6
+/*5*/, 65536*16* -5.9787071016806234E-6
+/*6*/, 65536*16* -6.716463411023574E-6
+/*7*/, 65536*16* -7.408551386580002E-6
+/*8*/, 65536*16* -8.023491429829738E-6
+/*9*/, 65536*16* -8.531232892238868E-6
+/*10*/, 65536*16* -8.878741512154837E-6
+/*11*/, 65536*16* -9.046773382992595E-6
+/*12*/, 65536*16* -8.993971214348702E-6
+/*13*/, 65536*16* -8.66944931521744E-6
+/*14*/, 65536*16* -8.049348524459474E-6
+/*15*/, 65536*16* -7.083238646482467E-6
+/*16*/, 65536*16* -5.746762349938464E-6
+/*17*/, 65536*16* -4.005753681691657E-6
+/*18*/, 65536*16* -1.838018035195733E-6
+/*19*/, 65536*16* 7.763983938828864E-7
+/*20*/, 65536*16* 3.842232025916005E-6
+/*21*/, 65536*16* 7.361161707034959E-6
+/*22*/, 65536*16* 1.1325948767988128E-5
+/*23*/, 65536*16* 1.5711486406341978E-5
+/*24*/, 65536*16* 2.0488201424957098E-5
+/*25*/, 65536*16* 2.5608402660083142E-5
+/*26*/, 65536*16* 3.101231858515874E-5
+/*27*/, 65536*16* 3.6630654060842745E-5
+/*28*/, 65536*16* 4.2375439803123404E-5
+/*29*/, 65536*16* 4.815060832963289E-5
+/*30*/, 65536*16* 5.384626411548906E-5
+/*31*/, 65536*16* 5.934549587237094E-5
+/*32*/, 65536*16* 6.451785679907682E-5
+/*33*/, 65536*16* 6.923065879553487E-5
+/*34*/, 65536*16* 7.334304650233838E-5
+/*35*/, 65536*16* 7.671308820252635E-5
+/*36*/, 65536*16* 7.920112989696133E-5
+/*37*/, 65536*16* 8.066793124218096E-5
+/*38*/, 65536*16* 8.098382483962539E-5
+/*39*/, 65536*16* 8.002921154479775E-5
+/*40*/, 65536*16* 7.769789869215064E-5
+/*41*/, 65536*16* 7.390152475899438E-5
+/*42*/, 65536*16* 6.857231550142758E-5
+/*43*/, 65536*16* 6.16673817460573E-5
+/*44*/, 65536*16* 5.3169767940001464E-5
+/*45*/, 65536*16* 4.309495398773014E-5
+/*46*/, 65536*16* 3.148737405995964E-5
+/*47*/, 65536*16* 1.8428415219696232E-5
+/*48*/, 65536*16* 4.0337781533928895E-6
+/*49*/, 65536*16* -1.154525373085283E-5
+/*50*/, 65536*16* -2.8120750949316567E-5
+/*51*/, 65536*16* -4.5470242422149815E-5
+/*52*/, 65536*16* -6.333736379615692E-5
+/*53*/, 65536*16* -8.143489509942166E-5
+/*54*/, 65536*16* -9.94475640226242E-5
+/*55*/, 65536*16* -1.1703729468742291E-4
+/*56*/, 65536*16* -1.3384679191408508E-4
+/*57*/, 65536*16* -1.4950548598267213E-4
+/*58*/, 65536*16* -1.6363792959068823E-4
+/*59*/, 65536*16* -1.7586732627086947E-4
+/*60*/, 65536*16* -1.858264971517669E-4
+/*61*/, 65536*16* -1.9316312487547242E-4
+/*62*/, 65536*16* -1.975494021862538E-4
+/*63*/, 65536*16* -1.9868977868165154E-4
+/*64*/, 65536*16* -1.963293865814053E-4
+/*65*/, 65536*16* -1.9026146175876417E-4
+/*66*/, 65536*16* -1.803352078962109E-4
+/*67*/, 65536*16* -1.66463443436789E-4
+/*68*/, 65536*16* -1.4862710934868261E-4
+/*69*/, 65536*16* -1.2688200452566298E-4
+/*70*/, 65536*16* -1.0136212853169677E-4
+/*71*/, 65536*16* -7.228199463954364E-5
+/*72*/, 65536*16* -3.9939461621236575E-5
+/*73*/, 65536*16* -4.7134932934724E-6
+/*74*/, 65536*16* 3.2936215273699675E-5
+/*75*/, 65536*16* 7.247384833064696E-5
+/*76*/, 65536*16* 1.1329187082792405E-4
+/*77*/, 65536*16* 1.5471948843725746E-4
+/*78*/, 65536*16* 1.9603027714808286E-4
+/*79*/, 65536*16* 2.364532958813608E-4
+/*80*/, 65536*16* 2.751853212246927E-4
+/*81*/, 65536*16* 3.114033208188799E-4
+/*82*/, 65536*16* 3.442804841775461E-4
+/*83*/, 65536*16* 3.7300098840546946E-4
+/*84*/, 65536*16* 3.967764136715296E-4
+/*85*/, 65536*16* 4.148631617351676E-4
+/*86*/, 65536*16* 4.265789297533608E-4
+/*87*/, 65536*16* 4.3132002526188114E-4
+/*88*/, 65536*16* 4.2857701618443636E-4
+/*89*/, 65536*16* 4.179510914969621E-4
+/*90*/, 65536*16* 3.991670037587729E-4
+/*91*/, 65536*16* 3.720870989970653E-4
+/*92*/, 65536*16* 3.367209236003282E-4
+/*93*/, 65536*16* 2.932338231303312E-4
+/*94*/, 65536*16* 2.419533571940393E-4
+/*95*/, 65536*16* 1.8337169647749448E-4
+/*96*/, 65536*16* 1.1814612711310299E-4
+/*97*/, 65536*16* 4.709567952563025E-5
+/*98*/, 65536*16* -2.880519351052945E-5
+/*99*/, 65536*16* -1.08436462295612E-4
+/*100*/, 65536*16* -1.905455293630124E-4
+/*101*/, 65536*16* -2.7376362665015007E-4
+/*102*/, 65536*16* -3.566259161939277E-4
+/*103*/, 65536*16* -4.375928024937683E-4
+/*104*/, 65536*16* -5.150762555847844E-4
+/*105*/, 65536*16* -5.874662774920191E-4
+/*106*/, 65536*16* -6.531605887419429E-4
+/*107*/, 65536*16* -7.105951946653638E-4
+/*108*/, 65536*16* -7.582757639600853E-4
+/*109*/, 65536*16* -7.948096207059845E-4
+/*110*/, 65536*16* -8.189373133065186E-4
+/*111*/, 65536*16* -8.295634640890689E-4
+/*112*/, 65536*16* -8.257854455404298E-4
+/*113*/, 65536*16* -8.069208861135825E-4
+/*114*/, 65536*16* -7.725316214556066E-4
+/*115*/, 65536*16* -7.224442067331338E-4
+/*116*/, 65536*16* -6.567673177902021E-4
+/*117*/, 65536*16* -5.759031970767677E-4
+/*118*/, 65536*16* -4.8055576975832975E-4
+/*119*/, 65536*16* -3.7173219275304865E-4
+/*120*/, 65536*16* -2.507394811359122E-4
+/*121*/, 65536*16* -1.191747608775131E-4
+/*122*/, 65536*16* 2.1089774143064154E-5
+/*123*/, 65536*16* 1.6792832047168277E-4
+/*124*/, 65536*16* 3.189887341095747E-4
+/*125*/, 65536*16* 4.7172479984555337E-4
+/*126*/, 65536*16* 6.234346495766704E-4
+/*127*/, 65536*16* 7.713029674040095E-4
+/*128*/, 65536*16* 9.124478381058291E-4
+/*129*/, 65536*16* 0.0010439713492973299
+/*130*/, 65536*16* 0.0011630121060354824
+/*131*/, 65536*16* 0.0012668003330792172
+/*132*/, 65536*16* 0.0013527131638668246
+/*133*/, 65536*16* 0.0014183305230994348
+/*134*/, 65536*16* 0.0014614889365474647
+/*135*/, 65536*16* 0.0014803340336415063
+/*136*/, 65536*16* 0.0014733688575452508
+/*137*/, 65536*16* 0.001439498243826639
+/*138*/, 65536*16* 0.0013780680098511918
+/*139*/, 65536*16* 0.0012888970057146566
+/*140*/, 65536*16* 0.0011723026532406624
+/*141*/, 65536*16* 0.0010291180003947405
+/*142*/, 65536*16* 8.607001658653358E-4
+/*143*/, 65536*16* 6.689295599970792E-4
+/*144*/, 65536*16* 4.5619928199453885E-4
+/*145*/, 65536*16* 2.253948582736753E-4
+/*146*/, 65536*16* -2.0136349562764177E-5
+/*147*/, 65536*16* -2.766248035657636E-4
+/*148*/, 65536*16* -5.399290507797791E-4
+/*149*/, 65536*16* -8.055939397996815E-4
+/*150*/, 65536*16* -0.0010689177291287714
+/*151*/, 65536*16* -0.0013250265370767429
+/*152*/, 65536*16* -0.0015689549600474482
+/*153*/, 65536*16* -0.0017957322527663085
+/*154*/, 65536*16* -0.002000472024117418
+/*155*/, 65536*16* -0.0021784645223266222
+/*156*/, 65536*16* -0.0023252695222818146
+/*157*/, 65536*16* -0.0024368087083972345
+/*158*/, 65536*16* -0.002509455241851095
+/*159*/, 65536*16* -0.0025401189567937766
+/*160*/, 65536*16* -0.0025263261450844377
+/*161*/, 65536*16* -0.0024662908754217406
+/*162*/, 65536*16* -0.002358977944127433
+/*163*/, 65536*16* -0.002204154401342649
+/*164*/, 65536*16* -0.002002429343138771
+/*165*/, 65536*16* -0.0017552803385372808
+/*166*/, 65536*16* -0.0014650656045065488
+/*167*/, 65536*16* -0.001135021049166992
+/*168*/, 65536*16* -7.692415547098649E-4
+/*169*/, 65536*16* -3.7264671522013244E-4
+/*170*/, 65536*16* 4.906989195928291E-5
+/*171*/, 65536*16* 4.895067103339711E-4
+/*172*/, 65536*16* 9.416355837269647E-4
+/*173*/, 65536*16* 0.001397897684142057
+/*174*/, 65536*16* 0.0018503121614766558
+/*175*/, 65536*16* 0.002290597319733804
+/*176*/, 65536*16* 0.0027103015920374113
+/*177*/, 65536*16* 0.0031009433327120863
+/*178*/, 65536*16* 0.0034541565687980116
+/*179*/, 65536*16* 0.0037618412630103333
+/*180*/, 65536*16* 0.004016315066649496
+/*181*/, 65536*16* 0.004210464374744574
+/*182*/, 65536*16* 0.004337892288164658
+/*183*/, 65536*16* 0.004393060165490985
+/*184*/, 65536*16* 0.004371421226297046
+/*185*/, 65536*16* 0.004269542847715132
+/*186*/, 65536*16* 0.00408521543517564
+/*187*/, 65536*16* 0.0038175457430583526
+/*188*/, 65536*16* 0.00346703221076496
+/*189*/, 65536*16* 0.0030356209846777236
+/*190*/, 65536*16* 0.002526740400739804
+/*191*/, 65536*16* 0.0019453134428630866
+/*192*/, 65536*16* 0.0012977462825954304
+/*193*/, 65536*16* 5.918933555500828E-4
+/*194*/, 65536*16* -1.6300197379338156E-4
+/*195*/, 65536*16* -9.563908629597664E-4
+/*196*/, 65536*16* -0.0017765255338228524
+/*197*/, 65536*16* -0.0026105886000394158
+/*198*/, 65536*16* -0.003444843158936217
+/*199*/, 65536*16* -0.004264802433556331
+/*200*/, 65536*16* -0.00505541655658742
+/*201*/, 65536*16* -0.005801274223045036
+/*202*/, 65536*16* -0.0064868164183708756
+/*203*/, 65536*16* -0.007096559102022994
+/*204*/, 65536*16* -0.007615322236172286
+/*205*/, 65536*16* -0.008028460796606074
+/*206*/, 65536*16* -0.008322095341268461
+/*207*/, 65536*16* -0.008483337773170242
+/*208*/, 65536*16* -0.008500509194641638
+/*209*/, 65536*16* -0.008363346317351387
+/*210*/, 65536*16* -0.008063192746297233
+/*211*/, 65536*16* -0.007593172286363423
+/*212*/, 65536*16* -0.0069483408893122045
+/*213*/, 65536*16* -0.006125814985695579
+/*214*/, 65536*16* -0.005124873148956596
+/*215*/, 65536*16* -0.003947029569132915
+/*216*/, 65536*16* -0.002596077508306772
+/*217*/, 65536*16* -0.0010781012650798818
+/*218*/, 65536*16* 5.985434770618447E-4
+/*219*/, 65536*16* 0.0024232820773754
+/*220*/, 65536*16* 0.004383405101533075
+/*221*/, 65536*16* 0.006464184070028333
+/*222*/, 65536*16* 0.008649017282842432
+/*223*/, 65536*16* 0.010919604285452066
+/*224*/, 65536*16* 0.013256146772932903
+/*225*/, 65536*16* 0.015637573164024095
+/*226*/, 65536*16* 0.018041784432073237
+/*227*/, 65536*16* 0.020445917198990023
+/*228*/, 65536*16* 0.022826621253151515
+/*229*/, 65536*16* 0.025160347111354456
+/*230*/, 65536*16* 0.02742363969736895
+/*231*/, 65536*16* 0.02959343430076011
+/*232*/, 65536*16* 0.03164735012116834
+/*233*/, 65536*16* 0.03356397767681876
+/*234*/, 65536*16* 0.035323155364389396
+/*235*/, 65536*16* 0.03690623176571385
+/*236*/, 65536*16* 0.03829630932788767
+/*237*/, 65536*16* 0.03947846623700253
+/*238*/, 65536*16* 0.040439953107911
+/*239*/, 65536*16* 0.0411703612762271
+/*240*/, 65536*16* 0.04166176091370756
+/*241*/, 65536*16* 0.041908806136461134
+};
+
+/*
+Parks-McClellan FIR Filter Design
+
+Filter type: Low pass
+Passband: 0 - 0.01804395
+Order: 483
+Passband ripple: 0.01 dB
+Transition band: 0.0108263
+Stopband attenuation: 114.0 dB
+
+Coefficients:
+*/
+
+static int32 C96000PAL[NCOEFFS/2]=
+{
+/*0*/ 65536*16* 3.850781559466991E-7
+/*1*/, 65536*16* -1.280019401722687E-6
+/*2*/, 65536*16* -1.3004583488088965E-6
+/*3*/, 65536*16* -1.7523167437749452E-6
+/*4*/, 65536*16* -2.410249470764872E-6
+/*5*/, 65536*16* -3.2346426554155092E-6
+/*6*/, 65536*16* -4.227271662321092E-6
+/*7*/, 65536*16* -5.3971678027414914E-6
+/*8*/, 65536*16* -6.753444785567694E-6
+/*9*/, 65536*16* -8.302128790766257E-6
+/*10*/, 65536*16* -1.0045896006160685E-5
+/*11*/, 65536*16* -1.1982368218542129E-5
+/*12*/, 65536*16* -1.4104296519058353E-5
+/*13*/, 65536*16* -1.6397945806910793E-5
+/*14*/, 65536*16* -1.8843550708827064E-5
+/*15*/, 65536*16* -2.1413952016264175E-5
+/*16*/, 65536*16* -2.407540699773165E-5
+/*17*/, 65536*16* -2.6786418491045868E-5
+/*18*/, 65536*16* -2.949883620881563E-5
+/*19*/, 65536*16* -3.215685693993941E-5
+/*20*/, 65536*16* -3.4698621200866915E-5
+/*21*/, 65536*16* -3.7055635055088747E-5
+/*22*/, 65536*16* -3.915516367387583E-5
+/*23*/, 65536*16* -4.092005046973106E-5
+/*24*/, 65536*16* -4.227173792151256E-5
+/*25*/, 65536*16* -4.313002076491602E-5
+/*26*/, 65536*16* -4.3416606424857764E-5
+/*27*/, 65536*16* -4.3054793786740716E-5
+/*28*/, 65536*16* -4.1974462257106624E-5
+/*29*/, 65536*16* -4.011236719136458E-5
+/*30*/, 65536*16* -3.7415159397597796E-5
+/*31*/, 65536*16* -3.3846213818414235E-5
+/*32*/, 65536*16* -2.9372757531099172E-5
+/*33*/, 65536*16* -2.3989695934591954E-5
+/*34*/, 65536*16* -1.7705989252101064E-5
+/*35*/, 65536*16* -1.0551320217411096E-5
+/*36*/, 65536*16* -2.5775325043216536E-6
+/*37*/, 65536*16* 6.139645766572715E-6
+/*38*/, 65536*16* 1.5501423038008354E-5
+/*39*/, 65536*16* 2.5384753820737575E-5
+/*40*/, 65536*16* 3.5643398684518664E-5
+/*41*/, 65536*16* 4.6108393091574726E-5
+/*42*/, 65536*16* 5.659011526249589E-5
+/*43*/, 65536*16* 6.68803323899828E-5
+/*44*/, 65536*16* 7.675537622878941E-5
+/*45*/, 65536*16* 8.597960059720824E-5
+/*46*/, 65536*16* 9.430960279897814E-5
+/*47*/, 65536*16* 1.0149893801465577E-4
+/*48*/, 65536*16* 1.0730328189856642E-4
+/*49*/, 65536*16* 1.1148622997923174E-4
+/*50*/, 65536*16* 1.1382511217545132E-4
+/*51*/, 65536*16* 1.141174295909343E-4
+/*52*/, 65536*16* 1.1218671460549208E-4
+/*53*/, 65536*16* 1.078890398041802E-4
+/*54*/, 65536*16* 1.0111839925160891E-4
+/*55*/, 65536*16* 9.181292532691402E-5
+/*56*/, 65536*16* 7.995923739813694E-5
+/*57*/, 65536*16* 6.559772591687974E-5
+/*58*/, 65536*16* 4.882471526869663E-5
+/*59*/, 65536*16* 2.9795861807919456E-5
+/*60*/, 65536*16* 8.727003235393024E-6
+/*61*/, 65536*16* -1.4106777294769694E-5
+/*62*/, 65536*16* -3.836880959229582E-5
+/*63*/, 65536*16* -6.366921149307032E-5
+/*64*/, 65536*16* -8.956481187350594E-5
+/*65*/, 65536*16* -1.1556632861786434E-4
+/*66*/, 65536*16* -1.411455941949306E-4
+/*67*/, 65536*16* -1.657445386231986E-4
+/*68*/, 65536*16* -1.8878427001863077E-4
+/*69*/, 65536*16* -2.0967688285495866E-4
+/*70*/, 65536*16* -2.2783715638612827E-4
+/*71*/, 65536*16* -2.4269587549180196E-4
+/*72*/, 65536*16* -2.5371305459897316E-4
+/*73*/, 65536*16* -2.603919787720978E-4
+/*74*/, 65536*16* -2.6229284265917287E-4
+/*75*/, 65536*16* -2.59046413963889E-4
+/*76*/, 65536*16* -2.503668396740634E-4
+/*77*/, 65536*16* -2.3606367328604213E-4
+/*78*/, 65536*16* -2.160524966650091E-4
+/*79*/, 65536*16* -1.903639226156617E-4
+/*80*/, 65536*16* -1.59150691014015E-4
+/*81*/, 65536*16* -1.2269241610349266E-4
+/*82*/, 65536*16* -8.139812226735764E-5
+/*83*/, 65536*16* -3.5805772732231955E-5
+/*84*/, 65536*16* 1.3420603339835859E-5
+/*85*/, 65536*16* 6.549742374431074E-5
+/*86*/, 65536*16* 1.1953033076822495E-4
+/*87*/, 65536*16* 1.745269622757623E-4
+/*88*/, 65536*16* 2.2941123586808386E-4
+/*89*/, 65536*16* 2.830419125977025E-4
+/*90*/, 65536*16* 3.3423267917052983E-4
+/*91*/, 65536*16* 3.81774499172079E-4
+/*92*/, 65536*16* 4.244616654237554E-4
+/*93*/, 65536*16* 4.611154134679936E-4
+/*94*/, 65536*16* 4.906128810250551E-4
+/*95*/, 65536*16* 5.119138315653597E-4
+/*96*/, 65536*16* 5.240878477917174E-4
+/*97*/, 65536*16* 5.263406012974186E-4
+/*98*/, 65536*16* 5.180395272684202E-4
+/*99*/, 65536*16* 4.987363674123535E-4
+/*100*/, 65536*16* 4.681879119879578E-4
+/*101*/, 65536*16* 4.263728836819278E-4
+/*102*/, 65536*16* 3.735054898141368E-4
+/*103*/, 65536*16* 3.1004425441119956E-4
+/*104*/, 65536*16* 2.3669640454159868E-4
+/*105*/, 65536*16* 1.5441686754990788E-4
+/*106*/, 65536*16* 6.440207419421148E-5
+/*107*/, 65536*16* -3.192198333335273E-5
+/*108*/, 65536*16* -1.3291717686663037E-4
+/*109*/, 65536*16* -2.3675627296534203E-4
+/*110*/, 65536*16* -3.414512496033162E-4
+/*111*/, 65536*16* -4.4488659997924806E-4
+/*112*/, 65536*16* -5.44857304239037E-4
+/*113*/, 65536*16* -6.391106241040588E-4
+/*114*/, 65536*16* -7.253914361418537E-4
+/*115*/, 65536*16* -8.0148962040363E-4
+/*116*/, 65536*16* -8.652895191393541E-4
+/*117*/, 65536*16* -9.148193159968953E-4
+/*118*/, 65536*16* -9.483009583169883E-4
+/*119*/, 65536*16* -9.64197392644944E-4
+/*120*/, 65536*16* -9.612579850877552E-4
+/*121*/, 65536*16* -9.385600118624972E-4
+/*122*/, 65536*16* -8.955444281498081E-4
+/*123*/, 65536*16* -8.320477398703453E-4
+/*124*/, 65536*16* -7.483247067952744E-4
+/*125*/, 65536*16* -6.450648142040654E-4
+/*126*/, 65536*16* -5.234000259248345E-4
+/*127*/, 65536*16* -3.8490357943433983E-4
+/*128*/, 65536*16* -2.3157879639504726E-4
+/*129*/, 65536*16* -6.583909529283622E-5
+/*130*/, 65536*16* 1.0952239530879758E-4
+/*131*/, 65536*16* 2.9137227027685464E-4
+/*132*/, 65536*16* 4.76285797012954E-4
+/*133*/, 65536*16* 6.606041066674581E-4
+/*134*/, 65536*16* 8.404993785845289E-4
+/*135*/, 65536*16* 0.0010120465600366754
+/*136*/, 65536*16* 0.00117130077980147
+/*137*/, 65536*16* 0.0013143787565297594
+/*138*/, 65536*16* 0.0014375429397231808
+/*139*/, 65536*16* 0.0015372865339524395
+/*140*/, 65536*16* 0.0016104178085955662
+/*141*/, 65536*16* 0.0016541417860661317
+/*142*/, 65536*16* 0.0016661374441763997
+/*143*/, 65536*16* 0.0016446287155235182
+/*144*/, 65536*16* 0.0015884472759871292
+/*145*/, 65536*16* 0.0014970858621845143
+/*146*/, 65536*16* 0.0013707399310406382
+/*147*/, 65536*16* 0.0012103371052757787
+/*148*/, 65536*16* 0.0010175519857289184
+/*149*/, 65536*16* 7.94807053668863E-4
+/*150*/, 65536*16* 5.452573395422002E-4
+/*151*/, 65536*16* 2.727594075846488E-4
+/*152*/, 65536*16* -1.8175144027827955E-5
+/*153*/, 65536*16* -3.2244298920455907E-4
+/*154*/, 65536*16* -6.344261333752713E-4
+/*155*/, 65536*16* -9.480839637356165E-4
+/*156*/, 65536*16* -0.001257058056943197
+/*157*/, 65536*16* -0.001554788246611654
+/*158*/, 65536*16* -0.001834637661184569
+/*159*/, 65536*16* -0.0020900256934556468
+/*160*/, 65536*16* -0.0023145651572872143
+/*161*/, 65536*16* -0.0025022020560114683
+/*162*/, 65536*16* -0.002647354498854991
+/*163*/, 65536*16* -0.002745048447695108
+/*164*/, 65536*16* -0.0027910469441460657
+/*165*/, 65536*16* -0.002781970255972488
+/*166*/, 65536*16* -0.0027154038464012363
+/*167*/, 65536*16* -0.002589991713387623
+/*168*/, 65536*16* -0.0024055123883779776
+/*169*/, 65536*16* -0.0021629354924022053
+/*170*/, 65536*16* -0.0018644567566629092
+/*171*/, 65536*16* -0.0015135100031795994
+/*172*/, 65536*16* -0.0011147548631940517
+/*173*/, 65536*16* -6.740394224166433E-4
+/*174*/, 65536*16* -1.9833762845333352E-4
+/*175*/, 65536*16* 3.043386309556266E-4
+/*176*/, 65536*16* 8.250516255359581E-4
+/*177*/, 65536*16* 0.0013540734762851313
+/*178*/, 65536*16* 0.0018810427835111666
+/*179*/, 65536*16* 0.002395141352428365
+/*180*/, 65536*16* 0.002885286937512414
+/*181*/, 65536*16* 0.0033403397957704442
+/*182*/, 65536*16* 0.003749319662913449
+/*183*/, 65536*16* 0.00410162844368435
+/*184*/, 65536*16* 0.00438727601255591
+/*185*/, 65536*16* 0.004597103692808949
+/*186*/, 65536*16* 0.004723001540295747
+/*187*/, 65536*16* 0.004758115147888017
+/*188*/, 65536*16* 0.0046970379302800494
+/*189*/, 65536*16* 0.0045359837766146575
+/*190*/, 65536*16* 0.004272937350956345
+/*191*/, 65536*16* 0.003907777448988567
+/*192*/, 65536*16* 0.0034423707924944227
+/*193*/, 65536*16* 0.0028806330094231125
+/*194*/, 65536*16* 0.0022285548928660825
+/*195*/, 65536*16* 0.0014941919971143964
+/*196*/, 65536*16* 6.876167025638233E-4
+/*197*/, 65536*16* -1.7916781098860902E-4
+/*198*/, 65536*16* -0.001092351250031068
+/*199*/, 65536*16* -0.002036476651580642
+/*200*/, 65536*16* -0.002994635788760751
+/*201*/, 65536*16* -0.003948697212655613
+/*202*/, 65536*16* -0.004879563858611486
+/*203*/, 65536*16* -0.005767456511229176
+/*204*/, 65536*16* -0.006592218979894068
+/*205*/, 65536*16* -0.007333640031607341
+/*206*/, 65536*16* -0.007971787269457032
+/*207*/, 65536*16* -0.008487346947516187
+/*208*/, 65536*16* -0.008861964740105959
+/*209*/, 65536*16* -0.009078580419089913
+/*210*/, 65536*16* -0.009121751784315056
+/*211*/, 65536*16* -0.008977961157199062
+/*212*/, 65536*16* -0.008635898786325313
+/*213*/, 65536*16* -0.008086718339557295
+/*214*/, 65536*16* -0.007324258683042848
+/*215*/, 65536*16* -0.0063452279676933475
+/*216*/, 65536*16* -0.005149346015761238
+/*217*/, 65536*16* -0.0037394415039958702
+/*218*/, 65536*16* -0.0021215012056140783
+/*219*/, 65536*16* -3.046703636518387E-4
+/*220*/, 65536*16* 0.0016987979320526618
+/*221*/, 65536*16* 0.0038736435001752246
+/*222*/, 65536*16* 0.006201749792159754
+/*223*/, 65536*16* 0.00866234250983842
+/*224*/, 65536*16* 0.011232233932071251
+/*225*/, 65536*16* 0.013886109426908738
+/*226*/, 65536*16* 0.016596852190097027
+/*227*/, 65536*16* 0.01933590131308301
+/*228*/, 65536*16* 0.022073637826085922
+/*229*/, 65536*16* 0.024779792715016697
+/*230*/, 65536*16* 0.027423870545765342
+/*231*/, 65536*16* 0.029975581949125456
+/*232*/, 65536*16* 0.03240527801144671
+/*233*/, 65536*16* 0.034684379593278115
+/*234*/, 65536*16* 0.03678579448103684
+/*235*/, 65536*16* 0.03868431571442653
+/*236*/, 65536*16* 0.04035699420925718
+/*237*/, 65536*16* 0.041783479941480954
+/*238*/, 65536*16* 0.04294632536294341
+/*239*/, 65536*16* 0.043831247006285705
+/*240*/, 65536*16* 0.044427339714649856
+/*241*/, 65536*16* 0.04472724072106236
+};
+
+/*
+Parks-McClellan FIR Filter Design
+
+Filter type: Low pass
+Passband: 0 - 0.0077845
+Order: 483
+Passband ripple: 0.1 dB
+Transition band: 0.005625
+Stopband attenuation: 60.0 dB
+*/
+static int32 C48000NTSC[NCOEFFS/2]=
+{
+/*0*/ 65536*16* -1.2211019733097893E-4
+/*1*/ , 65536*16* 5.374660789759626E-4
+/*2*/ , 65536*16* 1.9882723274804067E-4
+/*3*/ , 65536*16* 1.3631041618360223E-4
+/*4*/ , 65536*16* 1.3153691128499229E-4
+/*5*/ , 65536*16* 1.3886281724158703E-4
+/*6*/ , 65536*16* 1.4887278966773673E-4
+/*7*/ , 65536*16* 1.5943890243162037E-4
+/*8*/ , 65536*16* 1.7020639605259616E-4
+/*9*/ , 65536*16* 1.809192079749018E-4
+/*10*/ , 65536*16* 1.9162093203709557E-4
+/*11*/ , 65536*16* 2.02127312351196E-4
+/*12*/ , 65536*16* 2.1249848894399555E-4
+/*13*/ , 65536*16* 2.2254095363111247E-4
+/*14*/ , 65536*16* 2.323202963851337E-4
+/*15*/ , 65536*16* 2.4163344759163413E-4
+/*16*/ , 65536*16* 2.505472122265602E-4
+/*17*/ , 65536*16* 2.5885306226458603E-4
+/*18*/ , 65536*16* 2.6660828860384193E-4
+/*19*/ , 65536*16* 2.736061193417779E-4
+/*20*/ , 65536*16* 2.79907587492226E-4
+/*21*/ , 65536*16* 2.852884076207648E-4
+/*22*/ , 65536*16* 2.898305905338908E-4
+/*23*/ , 65536*16* 2.93305922863925E-4
+/*24*/ , 65536*16* 2.958004341042564E-4
+/*25*/ , 65536*16* 2.9706939623100196E-4
+/*26*/ , 65536*16* 2.972508466837626E-4
+/*27*/ , 65536*16* 2.960684730022295E-4
+/*28*/ , 65536*16* 2.937123123731801E-4
+/*29*/ , 65536*16* 2.898634667442807E-4
+/*30*/ , 65536*16* 2.8478700978604426E-4
+/*31*/ , 65536*16* 2.7808505097364714E-4
+/*32*/ , 65536*16* 2.7016032300539216E-4
+/*33*/ , 65536*16* 2.6042025835357706E-4
+/*34*/ , 65536*16* 2.496053090718662E-4
+/*35*/ , 65536*16* 2.3660011363209167E-4
+/*36*/ , 65536*16* 2.228827056917728E-4
+/*37*/ , 65536*16* 2.0662381151599093E-4
+/*38*/ , 65536*16* 1.8946729340692708E-4
+/*39*/ , 65536*16* 1.707894290302382E-4
+/*40*/ , 65536*16* 1.4964075656329285E-4
+/*41*/ , 65536*16* 1.2806315562352013E-4
+/*42*/ , 65536*16* 1.0470129333132878E-4
+/*43*/ , 65536*16* 7.952742687952367E-5
+/*44*/ , 65536*16* 5.3080519892589936E-5
+/*45*/ , 65536*16* 2.5960680465529317E-5
+/*46*/ , 65536*16* -2.5651586484338896E-6
+/*47*/ , 65536*16* -3.248840068536756E-5
+/*48*/ , 65536*16* -6.374045088088799E-5
+/*49*/ , 65536*16* -9.575401529845337E-5
+/*50*/ , 65536*16* -1.2853435644071695E-4
+/*51*/ , 65536*16* -1.6188456243132127E-4
+/*52*/ , 65536*16* -1.9591394048834482E-4
+/*53*/ , 65536*16* -2.3037663947407175E-4
+/*54*/ , 65536*16* -2.6523734278928246E-4
+/*55*/ , 65536*16* -3.0020331327926296E-4
+/*56*/ , 65536*16* -3.352268879856044E-4
+/*57*/ , 65536*16* -3.700260022275662E-4
+/*58*/ , 65536*16* -4.045571559416333E-4
+/*59*/ , 65536*16* -4.38534577720557E-4
+/*60*/ , 65536*16* -4.718927645081437E-4
+/*61*/ , 65536*16* -5.043317033789757E-4
+/*62*/ , 65536*16* -5.357994753678582E-4
+/*63*/ , 65536*16* -5.659671580788766E-4
+/*64*/ , 65536*16* -5.947897013020397E-4
+/*65*/ , 65536*16* -6.219384666963997E-4
+/*66*/ , 65536*16* -6.473787936195385E-4
+/*67*/ , 65536*16* -6.707514595741775E-4
+/*68*/ , 65536*16* -6.920680579893526E-4
+/*69*/ , 65536*16* -7.109402066802999E-4
+/*70*/ , 65536*16* -7.274298271538291E-4
+/*71*/ , 65536*16* -7.411375648954899E-4
+/*72*/ , 65536*16* -7.520788343347275E-4
+/*73*/ , 65536*16* -7.600510659768832E-4
+/*74*/ , 65536*16* -7.647430899316486E-4
+/*75*/ , 65536*16* -7.664294191482773E-4
+/*76*/ , 65536*16* -7.644147173692687E-4
+/*77*/ , 65536*16* -7.590920613362674E-4
+/*78*/ , 65536*16* -7.501459543641885E-4
+/*79*/ , 65536*16* -7.373621082253133E-4
+/*80*/ , 65536*16* -7.208964561671388E-4
+/*81*/ , 65536*16* -7.006901755632023E-4
+/*82*/ , 65536*16* -6.764591748580997E-4
+/*83*/ , 65536*16* -6.483697284795448E-4
+/*84*/ , 65536*16* -6.164929718400197E-4
+/*85*/ , 65536*16* -5.806918766677904E-4
+/*86*/ , 65536*16* -5.409344735839229E-4
+/*87*/ , 65536*16* -4.97405373620265E-4
+/*88*/ , 65536*16* -4.502086002815554E-4
+/*89*/ , 65536*16* -3.9932330033988294E-4
+/*90*/ , 65536*16* -3.448028565721092E-4
+/*91*/ , 65536*16* -2.8685420307046736E-4
+/*92*/ , 65536*16* -2.256958038579715E-4
+/*93*/ , 65536*16* -1.615040528190604E-4
+/*94*/ , 65536*16* -9.438524808984473E-5
+/*95*/ , 65536*16* -2.4519303584370608E-5
+/*96*/ , 65536*16* 4.786961616483501E-5
+/*97*/ , 65536*16* 1.2248011782462745E-4
+/*98*/ , 65536*16* 1.990534978611127E-4
+/*99*/ , 65536*16* 2.7728245405517893E-4
+/*100*/ , 65536*16* 3.5690342407690407E-4
+/*101*/ , 65536*16* 4.376002679601721E-4
+/*102*/ , 65536*16* 5.19047629492113E-4
+/*103*/ , 65536*16* 6.008846564336277E-4
+/*104*/ , 65536*16* 6.827617063818499E-4
+/*105*/ , 65536*16* 7.643160551093983E-4
+/*106*/ , 65536*16* 8.451272011819538E-4
+/*107*/ , 65536*16* 9.248890776355356E-4
+/*108*/ , 65536*16* 0.001003072355955673
+/*109*/ , 65536*16* 0.0010794672777372975
+/*110*/ , 65536*16* 0.0011534276232606116
+/*111*/ , 65536*16* 0.0012247823207262698
+/*112*/ , 65536*16* 0.0012929541324917778
+/*113*/ , 65536*16* 0.001357585199795128
+/*114*/ , 65536*16* 0.001418338397346014
+/*115*/ , 65536*16* 0.0014746734285279383
+/*116*/ , 65536*16* 0.0015262884930771822
+/*117*/ , 65536*16* 0.0015728226550844923
+/*118*/ , 65536*16* 0.00161379655898045
+/*119*/ , 65536*16* 0.001648915948444658
+/*120*/ , 65536*16* 0.0016778840108713717
+/*121*/ , 65536*16* 0.0017002560629258679
+/*122*/ , 65536*16* 0.0017157641984855009
+/*123*/ , 65536*16* 0.0017241805985007432
+/*124*/ , 65536*16* 0.001725182645995729
+/*125*/ , 65536*16* 0.0017184841648036691
+/*126*/ , 65536*16* 0.0017039216808435336
+/*127*/ , 65536*16* 0.001681334520841587
+/*128*/ , 65536*16* 0.0016504918660173195
+/*129*/ , 65536*16* 0.0016112687597971862
+/*130*/ , 65536*16* 0.0015636063248128528
+/*131*/ , 65536*16* 0.0015074624593932396
+/*132*/ , 65536*16* 0.0014427699009003175
+/*133*/ , 65536*16* 0.001369527394628539
+/*134*/ , 65536*16* 0.0012878043567412672
+/*135*/ , 65536*16* 0.0011977101442406943
+/*136*/ , 65536*16* 0.0010993686954177168
+/*137*/ , 65536*16* 9.928872878864818E-4
+/*138*/ , 65536*16* 8.784941174786496E-4
+/*139*/ , 65536*16* 7.564288883294911E-4
+/*140*/ , 65536*16* 6.270372159510238E-4
+/*141*/ , 65536*16* 4.905983779660314E-4
+/*142*/ , 65536*16* 3.4754116793679786E-4
+/*143*/ , 65536*16* 1.9816162887093084E-4
+/*144*/ , 65536*16* 4.300342678121075E-5
+/*145*/ , 65536*16* -1.1751370467978956E-4
+/*146*/ , 65536*16* -2.8280605795854083E-4
+/*147*/ , 65536*16* -4.523173545514795E-4
+/*148*/ , 65536*16* -6.255041797790695E-4
+/*149*/ , 65536*16* -8.016355996557292E-4
+/*150*/ , 65536*16* -9.801573426762404E-4
+/*151*/ , 65536*16* -0.0011602954820678437
+/*152*/ , 65536*16* -0.001341343986206184
+/*153*/ , 65536*16* -0.001522571621631356
+/*154*/ , 65536*16* -0.001703172768158951
+/*155*/ , 65536*16* -0.0018823360844618293
+/*156*/ , 65536*16* -0.00205930337901632
+/*157*/ , 65536*16* -0.0022331579230920632
+/*158*/ , 65536*16* -0.002403069015327
+/*159*/ , 65536*16* -0.0025682175666884455
+/*160*/ , 65536*16* -0.002727682820990084
+/*161*/ , 65536*16* -0.002880584481539458
+/*162*/ , 65536*16* -0.003026077683940661
+/*163*/ , 65536*16* -0.00316326704154516
+/*164*/ , 65536*16* -0.003291235176827385
+/*165*/ , 65536*16* -0.0034091436232751705
+/*166*/ , 65536*16* -0.0035161624262765347
+/*167*/ , 65536*16* -0.00361139707788214
+/*168*/ , 65536*16* -0.0036940241232429707
+/*169*/ , 65536*16* -0.003763249197925811
+/*170*/ , 65536*16* -0.0038183138554794805
+/*171*/ , 65536*16* -0.003858413648517434
+/*172*/ , 65536*16* -0.0038828565696081884
+/*173*/ , 65536*16* -0.0038909308779192654
+/*174*/ , 65536*16* -0.0038820231307916493
+/*175*/ , 65536*16* -0.0038554750792844325
+/*176*/ , 65536*16* -0.003810737282493679
+/*177*/ , 65536*16* -0.003747262375484652
+/*178*/ , 65536*16* -0.0036646285078894706
+/*179*/ , 65536*16* -0.0035623728689170597
+/*180*/ , 65536*16* -0.0034401218523635543
+/*181*/ , 65536*16* -0.003297594128579178
+/*182*/ , 65536*16* -0.0031344918897463427
+/*183*/ , 65536*16* -0.0029506999116335536
+/*184*/ , 65536*16* -0.002746012743503227
+/*185*/ , 65536*16* -0.0025204082871514897
+/*186*/ , 65536*16* -0.0022738407863853822
+/*187*/ , 65536*16* -0.0020063873037173175
+/*188*/ , 65536*16* -0.0017182175415557032
+/*189*/ , 65536*16* -0.0014095092681882975
+/*190*/ , 65536*16* -0.0010805220633352567
+/*191*/ , 65536*16* -7.316077716348434E-4
+/*192*/ , 65536*16* -3.631468249678417E-4
+/*193*/ , 65536*16* 2.438177178474359E-5
+/*194*/ , 65536*16* 4.3040711526763105E-4
+/*195*/ , 65536*16* 8.543758511240976E-4
+/*196*/ , 65536*16* 0.0012955688715509065
+/*197*/ , 65536*16* 0.0017532574138845757
+/*198*/ , 65536*16* 0.0022266720975588176
+/*199*/ , 65536*16* 0.0027149312534676365
+/*200*/ , 65536*16* 0.003217102703811305
+/*201*/ , 65536*16* 0.0037322302087511496
+/*202*/ , 65536*16* 0.004259307964559864
+/*203*/ , 65536*16* 0.004797205731205993
+/*204*/ , 65536*16* 0.00534482556712745
+/*205*/ , 65536*16* 0.00590099232932727
+/*206*/ , 65536*16* 0.0064644836497811
+/*207*/ , 65536*16* 0.007034017389280477
+/*208*/ , 65536*16* 0.007608353016621833
+/*209*/ , 65536*16* 0.008186157965561618
+/*210*/ , 65536*16* 0.008766068964147668
+/*211*/ , 65536*16* 0.009346716260147759
+/*212*/ , 65536*16* 0.009926718862388615
+/*213*/ , 65536*16* 0.010504681043184161
+/*214*/ , 65536*16* 0.01107917387309342
+/*215*/ , 65536*16* 0.011648797102049465
+/*216*/ , 65536*16* 0.012212089485935572
+/*217*/ , 65536*16* 0.012767702033610684
+/*218*/ , 65536*16* 0.01331416222058608
+/*219*/ , 65536*16* 0.013850107485964188
+/*220*/ , 65536*16* 0.01437415626494087
+/*221*/ , 65536*16* 0.01488494484218882
+/*222*/ , 65536*16* 0.015381157046388828
+/*223*/ , 65536*16* 0.015861470914555698
+/*224*/ , 65536*16* 0.016324639468324405
+/*225*/ , 65536*16* 0.01676942738258265
+/*226*/ , 65536*16* 0.017194657140859698
+/*227*/ , 65536*16* 0.01759919326505855
+/*228*/ , 65536*16* 0.01798195744932672
+/*229*/ , 65536*16* 0.018341882104229386
+/*230*/ , 65536*16* 0.018678046774501487
+/*231*/ , 65536*16* 0.018989525183852277
+/*232*/ , 65536*16* 0.019275463483745325
+/*233*/ , 65536*16* 0.019535099985330217
+/*234*/ , 65536*16* 0.019767681230128092
+/*235*/ , 65536*16* 0.019972616359274192
+/*236*/ , 65536*16* 0.02014933369102741
+/*237*/ , 65536*16* 0.020297350637687013
+/*238*/ , 65536*16* 0.020416241350314838
+/*239*/ , 65536*16* 0.020505719050281913
+/*240*/ , 65536*16* 0.020565502954380747
+/*241*/ , 65536*16* 0.02059542406883178
+};
+
+
+/* 44100 NTSC
+
+Parks-McClellan FIR Filter Design
+
+Filter type: Low pass
+Passband: 0 - 0.006695
+Order: 483
+Passband ripple: 0.2 dB
+Transition band: 0.005625
+Stopband attenuation: 66.4 dB
+
+Coefficients:
+*/
+
+static int32 C44100NTSC[NCOEFFS/2]=
+{
+/*0*/ 65536 *16 * 2.7250584077004043E-4
+/*1*/, 65536 *16 * -5.6651407794062126E-5
+/*2*/, 65536 *16 * -5.387595203270082E-5
+/*3*/, 65536 *16 * -5.3104114528112036E-5
+/*4*/, 65536 *16 * -5.3927905431407917E-5
+/*5*/, 65536 *16 * -5.624810531844495E-5
+/*6*/, 65536 *16 * -5.9753966587005594E-5
+/*7*/, 65536 *16 * -6.443298022976466E-5
+/*8*/, 65536 *16 * -7.002861393823279E-5
+/*9*/, 65536 *16 * -7.658937335809571E-5
+/*10*/, 65536 *16 * -8.388337472693157E-5
+/*11*/, 65536 *16 * -9.20081628039712E-5
+/*12*/, 65536 *16 * -1.007311169050114E-4
+/*13*/, 65536 *16 * -1.1019992230503533E-4
+/*14*/, 65536 *16 * -1.2014773803429516E-4
+/*15*/, 65536 *16 * -1.3080398984366903E-4
+/*16*/, 65536 *16 * -1.4175865072457003E-4
+/*17*/, 65536 *16 * -1.536527853404198E-4
+/*18*/, 65536 *16 * -1.6517054562524376E-4
+/*19*/, 65536 *16 * -1.7797585116596963E-4
+/*20*/, 65536 *16 * -1.909845496405445E-4
+/*21*/, 65536 *16 * -2.0389566936141008E-4
+/*22*/, 65536 *16 * -2.1726846302640957E-4
+/*23*/, 65536 *16 * -2.310008165840215E-4
+/*24*/, 65536 *16 * -2.4506881863360544E-4
+/*25*/, 65536 *16 * -2.5926465655995895E-4
+/*26*/, 65536 *16 * -2.735381275272462E-4
+/*27*/, 65536 *16 * -2.878190904612406E-4
+/*28*/, 65536 *16 * -3.0209388781875723E-4
+/*29*/, 65536 *16 * -3.163448868528516E-4
+/*30*/, 65536 *16 * -3.30514980542584E-4
+/*31*/, 65536 *16 * -3.4458721564408845E-4
+/*32*/, 65536 *16 * -3.5843761692424506E-4
+/*33*/, 65536 *16 * -3.720823326733447E-4
+/*34*/, 65536 *16 * -3.8529611278848583E-4
+/*35*/, 65536 *16 * -3.982435971141635E-4
+/*36*/, 65536 *16 * -4.1054225307421383E-4
+/*37*/, 65536 *16 * -4.223385042208698E-4
+/*38*/, 65536 *16 * -4.3363210365443626E-4
+/*39*/, 65536 *16 * -4.440451096331875E-4
+/*40*/, 65536 *16 * -4.537334227294333E-4
+/*41*/, 65536 *16 * -4.6260960194346025E-4
+/*42*/, 65536 *16 * -4.706224417116799E-4
+/*43*/, 65536 *16 * -4.776010427698281E-4
+/*44*/, 65536 *16 * -4.8350610346281614E-4
+/*45*/, 65536 *16 * -4.8826489934975626E-4
+/*46*/, 65536 *16 * -4.918511387810396E-4
+/*47*/, 65536 *16 * -4.941839548845786E-4
+/*48*/, 65536 *16 * -4.95186572618022E-4
+/*49*/, 65536 *16 * -4.947817087436606E-4
+/*50*/, 65536 *16 * -4.928828353341973E-4
+/*51*/, 65536 *16 * -4.894676199661217E-4
+/*52*/, 65536 *16 * -4.8443244774343773E-4
+/*53*/, 65536 *16 * -4.778002134883142E-4
+/*54*/, 65536 *16 * -4.694896704084311E-4
+/*55*/, 65536 *16 * -4.593928438902496E-4
+/*56*/, 65536 *16 * -4.4763586771533415E-4
+/*57*/, 65536 *16 * -4.3399559196764174E-4
+/*58*/, 65536 *16 * -4.185187519793231E-4
+/*59*/, 65536 *16 * -4.0118338859945383E-4
+/*60*/, 65536 *16 * -3.820043675631783E-4
+/*61*/, 65536 *16 * -3.6090543967085524E-4
+/*62*/, 65536 *16 * -3.379128204177913E-4
+/*63*/, 65536 *16 * -3.130247503897743E-4
+/*64*/, 65536 *16 * -2.8628759491904673E-4
+/*65*/, 65536 *16 * -2.5769205396918157E-4
+/*66*/, 65536 *16 * -2.2726228845123853E-4
+/*67*/, 65536 *16 * -1.9501222414998665E-4
+/*68*/, 65536 *16 * -1.609903786128509E-4
+/*69*/, 65536 *16 * -1.2525258280646142E-4
+/*70*/, 65536 *16 * -8.786088130641809E-5
+/*71*/, 65536 *16 * -4.885883411475722E-5
+/*72*/, 65536 *16 * -8.373566315346232E-6
+/*73*/, 65536 *16 * 3.362843819360238E-5
+/*74*/, 65536 *16 * 7.69302822233031E-5
+/*75*/, 65536 *16 * 1.2151249228835434E-4
+/*76*/, 65536 *16 * 1.6724878315058612E-4
+/*77*/, 65536 *16 * 2.1402171363813576E-4
+/*78*/, 65536 *16 * 2.6167305946436103E-4
+/*79*/, 65536 *16 * 3.10122854445744E-4
+/*80*/, 65536 *16 * 3.5921866691687363E-4
+/*81*/, 65536 *16 * 4.0882826181233784E-4
+/*82*/, 65536 *16 * 4.5876834733749337E-4
+/*83*/, 65536 *16 * 5.089048509923103E-4
+/*84*/, 65536 *16 * 5.590621717784201E-4
+/*85*/, 65536 *16 * 6.090870406928206E-4
+/*86*/, 65536 *16 * 6.587768488216395E-4
+/*87*/, 65536 *16 * 7.079653533691067E-4
+/*88*/, 65536 *16 * 7.56434905175643E-4
+/*89*/, 65536 *16 * 8.040537989021466E-4
+/*90*/, 65536 *16 * 8.505576158388297E-4
+/*91*/, 65536 *16 * 8.958345533585908E-4
+/*92*/, 65536 *16 * 9.396170235698547E-4
+/*93*/, 65536 *16 * 9.817197600520506E-4
+/*94*/, 65536 *16 * 0.0010219440113723856
+/*95*/, 65536 *16 * 0.0010600976395277468
+/*96*/, 65536 *16 * 0.0010959465933076378
+/*97*/, 65536 *16 * 0.0011293213059753442
+/*98*/, 65536 *16 * 0.001160012212002378
+/*99*/, 65536 *16 * 0.0011878334518393636
+/*100*/, 65536 *16 * 0.0012125633172564833
+/*101*/, 65536 *16 * 0.0012340340153475305
+/*102*/, 65536 *16 * 0.0012520523486154733
+/*103*/, 65536 *16 * 0.001266464375255462
+/*104*/, 65536 *16 * 0.001277070934117742
+/*105*/, 65536 *16 * 0.0012837351142488396
+/*106*/, 65536 *16 * 0.0012862625405968798
+/*107*/, 65536 *16 * 0.0012845614834936406
+/*108*/, 65536 *16 * 0.0012784420593778636
+/*109*/, 65536 *16 * 0.0012678178114382621
+/*110*/, 65536 *16 * 0.0012525556826375537
+/*111*/, 65536 *16 * 0.0012325473943852084
+/*112*/, 65536 *16 * 0.0012077126268838676
+/*113*/, 65536 *16 * 0.0011779966448355029
+/*114*/, 65536 *16 * 0.0011433146771737655
+/*115*/, 65536 *16 * 0.0011036347058885887
+/*116*/, 65536 *16 * 0.0010589202139950945
+/*117*/, 65536 *16 * 0.0010091683044254098
+/*118*/, 65536 *16 * 9.543624468571229E-4
+/*119*/, 65536 *16 * 8.945398819399117E-4
+/*120*/, 65536 *16 * 8.297313883125644E-4
+/*121*/, 65536 *16 * 7.600155199968718E-4
+/*122*/, 65536 *16 * 6.854405952299358E-4
+/*123*/, 65536 *16 * 6.061236114458317E-4
+/*124*/, 65536 *16 * 5.221478191516476E-4
+/*125*/, 65536 *16 * 4.336813620599164E-4
+/*126*/, 65536 *16 * 3.408549526515998E-4
+/*127*/, 65536 *16 * 2.438450825114285E-4
+/*128*/, 65536 *16 * 1.428494911857926E-4
+/*129*/, 65536 *16 * 3.8067640594361634E-5
+/*130*/, 65536 *16 * -7.027035111775681E-5
+/*131*/, 65536 *16 * -1.818984143827126E-4
+/*132*/, 65536 *16 * -2.9656343184630157E-4
+/*133*/, 65536 *16 * -4.1397802421901906E-4
+/*134*/, 65536 *16 * -5.33838500742085E-4
+/*135*/, 65536 *16 * -6.558110253978588E-4
+/*136*/, 65536 *16 * -7.795655816897978E-4
+/*137*/, 65536 *16 * -9.047371821667003E-4
+/*138*/, 65536 *16 * -0.001030961345825847
+/*139*/, 65536 *16 * -0.0011578367988084777
+/*140*/, 65536 *16 * -0.0012849810572319298
+/*141*/, 65536 *16 * -0.0014119662266064482
+/*142*/, 65536 *16 * -0.0015383759515758101
+/*143*/, 65536 *16 * -0.001663756794188296
+/*144*/, 65536 *16 * -0.0017876541594460456
+/*145*/, 65536 *16 * -0.001909621722046808
+/*146*/, 65536 *16 * -0.0020291786719378088
+/*147*/, 65536 *16 * -0.002145855089743562
+/*148*/, 65536 *16 * -0.002259171910476534
+/*149*/, 65536 *16 * -0.0023686314802222655
+/*150*/, 65536 *16 * -0.002473745572697707
+/*151*/, 65536 *16 * -0.0025740277587192853
+/*152*/, 65536 *16 * -0.0026689831666099955
+/*153*/, 65536 *16 * -0.0027581124255643377
+/*154*/, 65536 *16 * -0.0028409282136656177
+/*155*/, 65536 *16 * -0.0029169432593640367
+/*156*/, 65536 *16 * -0.002985680612410139
+/*157*/, 65536 *16 * -0.003046658228485494
+/*158*/, 65536 *16 * -0.003099414222252269
+/*159*/, 65536 *16 * -0.0031434902530511595
+/*160*/, 65536 *16 * -0.003178436798255356
+/*161*/, 65536 *16 * -0.0032038260756887147
+/*162*/, 65536 *16 * -0.003219225355080285
+/*163*/, 65536 *16 * -0.0032242502222488744
+/*164*/, 65536 *16 * -0.003218506103318342
+/*165*/, 65536 *16 * -0.003201625222636992
+/*166*/, 65536 *16 * -0.003173259488065382
+/*167*/, 65536 *16 * -0.0031330803817718332
+/*168*/, 65536 *16 * -0.0030807779128908526
+/*169*/, 65536 *16 * -0.0030160821637947783
+/*170*/, 65536 *16 * -0.0029387362752889335
+/*171*/, 65536 *16 * -0.002848510131379585
+/*172*/, 65536 *16 * -0.0027451998188029363
+/*173*/, 65536 *16 * -0.00262863682904045
+/*174*/, 65536 *16 * -0.0024986780420415064
+/*175*/, 65536 *16 * -0.0023552114528323513
+/*176*/, 65536 *16 * -0.0021981491527779964
+/*177*/, 65536 *16 * -0.0020274504745732714
+/*178*/, 65536 *16 * -0.0018430877753141852
+/*179*/, 65536 *16 * -0.0016450910502005863
+/*180*/, 65536 *16 * -0.0014334955802048866
+/*181*/, 65536 *16 * -0.0012083983821827642
+/*182*/, 65536 *16 * -9.699135443572468E-4
+/*183*/, 65536 *16 * -7.181935207475589E-4
+/*184*/, 65536 *16 * -4.534224887286362E-4
+/*185*/, 65536 *16 * -1.758311300125605E-4
+/*186*/, 65536 *16 * 1.1433027008948132E-4
+/*187*/, 65536 *16 * 4.1675921199616097E-4
+/*188*/, 65536 *16 * 7.311320710094336E-4
+/*189*/, 65536 *16 * 0.0010570872458505827
+/*190*/, 65536 *16 * 0.0013942372682560795
+/*191*/, 65536 *16 * 0.001742148094642797
+/*192*/, 65536 *16 * 0.002100362793433286
+/*193*/, 65536 *16 * 0.0024683818857210646
+/*194*/, 65536 *16 * 0.002845695057494279
+/*195*/, 65536 *16 * 0.0032317385772924275
+/*196*/, 65536 *16 * 0.0036259433326630884
+/*197*/, 65536 *16 * 0.0040276894120370626
+/*198*/, 65536 *16 * 0.004436353627556968
+/*199*/, 65536 *16 * 0.004851271439526238
+/*200*/, 65536 *16 * 0.005271762758295799
+/*201*/, 65536 *16 * 0.005697120565601845
+/*202*/, 65536 *16 * 0.006126626859240469
+/*203*/, 65536 *16 * 0.006559527746778011
+/*204*/, 65536 *16 * 0.0069950693344747504
+/*205*/, 65536 *16 * 0.007432470090915211
+/*206*/, 65536 *16 * 0.007870944336430185
+/*207*/, 65536 *16 * 0.008309688701943495
+/*208*/, 65536 *16 * 0.008747898549370043
+/*209*/, 65536 *16 * 0.009184747205291654
+/*210*/, 65536 *16 * 0.009619414724898365
+/*211*/, 65536 *16 * 0.010051063453485451
+/*212*/, 65536 *16 * 0.010478876316671397
+/*213*/, 65536 *16 * 0.010902016899039163
+/*214*/, 65536 *16 * 0.011319665474466693
+/*215*/, 65536 *16 * 0.011730992134403782
+/*216*/, 65536 *16 * 0.012135186113163639
+/*217*/, 65536 *16 * 0.01253143889871197
+/*218*/, 65536 *16 * 0.012918956981226547
+/*219*/, 65536 *16 * 0.013296952886747157
+/*220*/, 65536 *16 * 0.013664665893392403
+/*221*/, 65536 *16 * 0.014021339353548561
+/*222*/, 65536 *16 * 0.014366244972764902
+/*223*/, 65536 *16 * 0.014698670942210527
+/*224*/, 65536 *16 * 0.015017930945351435
+/*225*/, 65536 *16 * 0.015323359168800435
+/*226*/, 65536 *16 * 0.015614322198635518
+/*227*/, 65536 *16 * 0.015890204972590742
+/*228*/, 65536 *16 * 0.016150433344740527
+/*229*/, 65536 *16 * 0.01639445378257351
+/*230*/, 65536 *16 * 0.016621758349582072
+/*231*/, 65536 *16 * 0.01683186471138077
+/*232*/, 65536 *16 * 0.01702432745775747
+/*233*/, 65536 *16 * 0.017198732908190056
+/*234*/, 65536 *16 * 0.017354710361561963
+/*235*/, 65536 *16 * 0.017491928210652433
+/*236*/, 65536 *16 * 0.017610096156964024
+/*237*/, 65536 *16 * 0.017708958417438553
+/*238*/, 65536 *16 * 0.017788304726419644
+/*239*/, 65536 *16 * 0.01784796484627723
+/*240*/, 65536 *16 * 0.017887808513528385
+/*241*/, 65536 *16 * 0.01790775243433271
+};
+
+/* 48000 PAL
+Parks-McClellan FIR Filter Design
+
+Filter type: Low pass
+Passband: 0 - 0.008810
+Order: 483
+Passband ripple: 0.133 dB
+Transition band: 0.005625
+Stopband attenuation: 63.0 dB
+
+Coefficients:
+*/
+static int32 C48000PAL[NCOEFFS/2]=
+{
+/*0*/ 65536 *16 * -4.8720337170268194E-4
+/*1*/, 65536 *16 * 7.629902642634879E-7
+/*2*/, 65536 *16 * 2.1378369687164975E-6
+/*3*/, 65536 *16 * 4.2506426520122444E-6
+/*4*/, 65536 *16 * 7.369889860416342E-6
+/*5*/, 65536 *16 * 1.1216062943011637E-5
+/*6*/, 65536 *16 * 1.6073843505677063E-5
+/*7*/, 65536 *16 * 2.1633099120040373E-5
+/*8*/, 65536 *16 * 2.8206508485377597E-5
+/*9*/, 65536 *16 * 3.543629776593455E-5
+/*10*/, 65536 *16 * 4.368764327716006E-5
+/*11*/, 65536 *16 * 5.2518982409171E-5
+/*12*/, 65536 *16 * 6.239757141317561E-5
+/*13*/, 65536 *16 * 7.27096511997309E-5
+/*14*/, 65536 *16 * 8.417180660805913E-5
+/*15*/, 65536 *16 * 9.556951705928003E-5
+/*16*/, 65536 *16 * 1.0902571193097876E-4
+/*17*/, 65536 *16 * 1.227237340685471E-4
+/*18*/, 65536 *16 * 1.3608963828565135E-4
+/*19*/, 65536 *16 * 1.5074291732163737E-4
+/*20*/, 65536 *16 * 1.654957671774518E-4
+/*21*/, 65536 *16 * 1.8094544537755017E-4
+/*22*/, 65536 *16 * 1.9650254639058925E-4
+/*23*/, 65536 *16 * 2.124977005396817E-4
+/*24*/, 65536 *16 * 2.2850169154416925E-4
+/*25*/, 65536 *16 * 2.447269340662641E-4
+/*26*/, 65536 *16 * 2.60813097374866E-4
+/*27*/, 65536 *16 * 2.769089011403406E-4
+/*28*/, 65536 *16 * 2.926838284872595E-4
+/*29*/, 65536 *16 * 3.082587328683191E-4
+/*30*/, 65536 *16 * 3.233018169377691E-4
+/*31*/, 65536 *16 * 3.379664790017549E-4
+/*32*/, 65536 *16 * 3.520147829064225E-4
+/*33*/, 65536 *16 * 3.6489502104188965E-4
+/*34*/, 65536 *16 * 3.771837837785839E-4
+/*35*/, 65536 *16 * 3.8841744550992556E-4
+/*36*/, 65536 *16 * 3.985152578693797E-4
+/*37*/, 65536 *16 * 4.0737410559796126E-4
+/*38*/, 65536 *16 * 4.1485052511765913E-4
+/*39*/, 65536 *16 * 4.2087321591616255E-4
+/*40*/, 65536 *16 * 4.252880030529943E-4
+/*41*/, 65536 *16 * 4.2804175098790727E-4
+/*42*/, 65536 *16 * 4.289792011350111E-4
+/*43*/, 65536 *16 * 4.280677040429387E-4
+/*44*/, 65536 *16 * 4.251526022872329E-4
+/*45*/, 65536 *16 * 4.202312572840644E-4
+/*46*/, 65536 *16 * 4.1313629237647344E-4
+/*47*/, 65536 *16 * 4.0393669855985745E-4
+/*48*/, 65536 *16 * 3.9229544134295797E-4
+/*49*/, 65536 *16 * 3.785081882385653E-4
+/*50*/, 65536 *16 * 3.624387298611128E-4
+/*51*/, 65536 *16 * 3.439609793120755E-4
+/*52*/, 65536 *16 * 3.2317107312926493E-4
+/*53*/, 65536 *16 * 3.0001522643985015E-4
+/*54*/, 65536 *16 * 2.7456037312211196E-4
+/*55*/, 65536 *16 * 2.468022375847908E-4
+/*56*/, 65536 *16 * 2.1682011116032351E-4
+/*57*/, 65536 *16 * 1.846463359087917E-4
+/*58*/, 65536 *16 * 1.5038519581308458E-4
+/*59*/, 65536 *16 * 1.1409999503195986E-4
+/*60*/, 65536 *16 * 7.592602477010921E-5
+/*61*/, 65536 *16 * 3.594949037485983E-5
+/*62*/, 65536 *16 * -5.654205953473915E-6
+/*63*/, 65536 *16 * -4.8796158887641113E-5
+/*64*/, 65536 *16 * -9.324450907374415E-5
+/*65*/, 65536 *16 * -1.3875102646747199E-4
+/*66*/, 65536 *16 * -1.853099936736042E-4
+/*67*/, 65536 *16 * -2.3256519878196182E-4
+/*68*/, 65536 *16 * -2.803629983423417E-4
+/*69*/, 65536 *16 * -3.284299717573991E-4
+/*70*/, 65536 *16 * -3.7655572805983734E-4
+/*71*/, 65536 *16 * -4.244648731259925E-4
+/*72*/, 65536 *16 * -4.7191652130487173E-4
+/*73*/, 65536 *16 * -5.18626812434502E-4
+/*74*/, 65536 *16 * -5.64334322901072E-4
+/*75*/, 65536 *16 * -6.087503654593899E-4
+/*76*/, 65536 *16 * -6.515995849807032E-4
+/*77*/, 65536 *16 * -6.925935510204477E-4
+/*78*/, 65536 *16 * -7.314432865833455E-4
+/*79*/, 65536 *16 * -7.678735923848921E-4
+/*80*/, 65536 *16 * -8.015359919770463E-4
+/*81*/, 65536 *16 * -8.322768680565776E-4
+/*82*/, 65536 *16 * -8.597539203190856E-4
+/*83*/, 65536 *16 * -8.836879776280238E-4
+/*84*/, 65536 *16 * -9.038629010388075E-4
+/*85*/, 65536 *16 * -9.200080217158554E-4
+/*86*/, 65536 *16 * -9.319235257639778E-4
+/*87*/, 65536 *16 * -9.393690949611698E-4
+/*88*/, 65536 *16 * -9.421725179420662E-4
+/*89*/, 65536 *16 * -9.401299048871544E-4
+/*90*/, 65536 *16 * -9.33106896645869E-4
+/*91*/, 65536 *16 * -9.209400636174311E-4
+/*92*/, 65536 *16 * -9.035401279622776E-4
+/*93*/, 65536 *16 * -8.807854817776823E-4
+/*94*/, 65536 *16 * -8.526430615286829E-4
+/*95*/, 65536 *16 * -8.190296190822509E-4
+/*96*/, 65536 *16 * -7.799980167439345E-4
+/*97*/, 65536 *16 * -7.355478199155667E-4
+/*98*/, 65536 *16 * -6.8567697874281E-4
+/*99*/, 65536 *16 * -6.305240657493408E-4
+/*100*/, 65536 *16 * -5.701694385732142E-4
+/*101*/, 65536 *16 * -5.047740591296687E-4
+/*102*/, 65536 *16 * -4.344980221283718E-4
+/*103*/, 65536 *16 * -3.595556715693896E-4
+/*104*/, 65536 *16 * -2.8017864491759883E-4
+/*105*/, 65536 *16 * -1.9664106446578853E-4
+/*106*/, 65536 *16 * -1.0924056590418239E-4
+/*107*/, 65536 *16 * -1.831009861307028E-5
+/*108*/, 65536 *16 * 7.579029921420169E-5
+/*109*/, 65536 *16 * 1.726696848384902E-4
+/*110*/, 65536 *16 * 2.719067221880469E-4
+/*111*/, 65536 *16 * 3.7305728261123155E-4
+/*112*/, 65536 *16 * 4.7562651195605295E-4
+/*113*/, 65536 *16 * 5.791888527128953E-4
+/*114*/, 65536 *16 * 6.831673135667645E-4
+/*115*/, 65536 *16 * 7.870493762901182E-4
+/*116*/, 65536 *16 * 8.902822670362451E-4
+/*117*/, 65536 *16 * 9.923024258505538E-4
+/*118*/, 65536 *16 * 0.0010925350458368308
+/*119*/, 65536 *16 * 0.0011903898503065698
+/*120*/, 65536 *16 * 0.0012852771482304163
+/*121*/, 65536 *16 * 0.0013765956662458894
+/*122*/, 65536 *16 * 0.001463753120426749
+/*123*/, 65536 *16 * 0.001546148019165285
+/*124*/, 65536 *16 * 0.0016231971391851225
+/*125*/, 65536 *16 * 0.0016943089588603764
+/*126*/, 65536 *16 * 0.0017589264521182184
+/*127*/, 65536 *16 * 0.001816477825843157
+/*128*/, 65536 *16 * 0.001866465750234791
+/*129*/, 65536 *16 * 0.001908351881851273
+/*130*/, 65536 *16 * 0.0019416355874888774
+/*131*/, 65536 *16 * 0.0019658912100497094
+/*132*/, 65536 *16 * 0.0019806705540431754
+/*133*/, 65536 *16 * 0.001985602463070219
+/*134*/, 65536 *16 * 0.0019803173347810094
+/*135*/, 65536 *16 * 0.001964518487218229
+/*136*/, 65536 *16 * 0.00193792749109128
+/*137*/, 65536 *16 * 0.0019003361153152295
+/*138*/, 65536 *16 * 0.0018515636696845045
+/*139*/, 65536 *16 * 0.0017915008584460717
+/*140*/, 65536 *16 * 0.0017200735452676211
+/*141*/, 65536 *16 * 0.0016372830430278298
+/*142*/, 65536 *16 * 0.0015431709906056357
+/*143*/, 65536 *16 * 0.0014378573929982352
+/*144*/, 65536 *16 * 0.0013215084987890104
+/*145*/, 65536 *16 * 0.001194328283068528
+/*146*/, 65536 *16 * 0.0010566468386934231
+/*147*/, 65536 *16 * 9.088002025373218E-4
+/*148*/, 65536 *16 * 7.512135584215806E-4
+/*149*/, 65536 *16 * 5.843621536328689E-4
+/*150*/, 65536 *16 * 4.087894375795271E-4
+/*151*/, 65536 *16 * 2.2510227575334467E-4
+/*152*/, 65536 *16 * 3.396239791846655E-5
+/*153*/, 65536 *16 * -1.6390294871759475E-4
+/*154*/, 65536 *16 * -3.6771789280231503E-4
+/*155*/, 65536 *16 * -5.766405458635558E-4
+/*156*/, 65536 *16 * -7.897872933737203E-4
+/*157*/, 65536 *16 * -0.001006209757480115
+/*158*/, 65536 *16 * -0.0012249304977170316
+/*159*/, 65536 *16 * -0.0014449054341312839
+/*160*/, 65536 *16 * -0.0016650898600315796
+/*161*/, 65536 *16 * -0.001884343774622382
+/*162*/, 65536 *16 * -0.0021015342465919864
+/*163*/, 65536 *16 * -0.0023154975831354337
+/*164*/, 65536 *16 * -0.0025250324219407566
+/*165*/, 65536 *16 * -0.0027289312457094736
+/*166*/, 65536 *16 * -0.0029259546931934967
+/*167*/, 65536 *16 * -0.003114871201398419
+/*168*/, 65536 *16 * -0.003294430723892981
+/*169*/, 65536 *16 * -0.003463396424710959
+/*170*/, 65536 *16 * -0.003620525188769811
+/*171*/, 65536 *16 * -0.0037645967189351955
+/*172*/, 65536 *16 * -0.003894396916361478
+/*173*/, 65536 *16 * -0.00400874728567525
+/*174*/, 65536 *16 * -0.004106485394068385
+/*175*/, 65536 *16 * -0.004186497692846864
+/*176*/, 65536 *16 * -0.004247692032125654
+/*177*/, 65536 *16 * -0.004289020763525844
+/*178*/, 65536 *16 * -0.0043095197889136795
+/*179*/, 65536 *16 * -0.004308238489219152
+/*180*/, 65536 *16 * -0.004284317631022625
+/*181*/, 65536 *16 * -0.0042369380515990835
+/*182*/, 65536 *16 * -0.004165372803509635
+/*183*/, 65536 *16 * -0.004068956516951112
+/*184*/, 65536 *16 * -0.003947110543306579
+/*185*/, 65536 *16 * -0.003799332887739826
+/*186*/, 65536 *16 * -0.0036252122359255057
+/*187*/, 65536 *16 * -0.0034244255727248728
+/*188*/, 65536 *16 * -0.0031967441992062605
+/*189*/, 65536 *16 * -0.0029420359603045624
+/*190*/, 65536 *16 * -0.002660262473612329
+/*191*/, 65536 *16 * -0.0023514913391939015
+/*192*/, 65536 *16 * -0.002015874218170038
+/*193*/, 65536 *16 * -0.0016537021922741356
+/*194*/, 65536 *16 * -0.0012653326032471951
+/*195*/, 65536 *16 * -8.512425489658283E-4
+/*196*/, 65536 *16 * -4.12008134196091E-4
+/*197*/, 65536 *16 * 5.169160678832697E-5
+/*198*/, 65536 *16 * 5.3906734093252E-4
+/*199*/, 65536 *16 * 0.0010492444783799305
+/*200*/, 65536 *16 * 0.0015812369440962736
+/*201*/, 65536 *16 * 0.002133975437656693
+/*202*/, 65536 *16 * 0.002706284295633396
+/*203*/, 65536 *16 * 0.003296910987472264
+/*204*/, 65536 *16 * 0.0039045040922850343
+/*205*/, 65536 *16 * 0.004527645156076457
+/*206*/, 65536 *16 * 0.005164822580527953
+/*207*/, 65536 *16 * 0.00581446977998051
+/*208*/, 65536 *16 * 0.00647492818678252
+/*209*/, 65536 *16 * 0.007144495527005753
+/*210*/, 65536 *16 * 0.007821417135435386
+/*211*/, 65536 *16 * 0.008503870707064397
+/*212*/, 65536 *16 * 0.00919000676302643
+/*213*/, 65536 *16 * 0.009877917856582038
+/*214*/, 65536 *16 * 0.010565689475867907
+/*215*/, 65536 *16 * 0.011251366750588049
+/*216*/, 65536 *16 * 0.01193298816023733
+/*217*/, 65536 *16 * 0.012608574497468706
+/*218*/, 65536 *16 * 0.013276151008399953
+/*219*/, 65536 *16 * 0.013933744269275995
+/*220*/, 65536 *16 * 0.014579397589755912
+/*221*/, 65536 *16 * 0.015211171751139368
+/*222*/, 65536 *16 * 0.015827155422328678
+/*223*/, 65536 *16 * 0.01642547256780349
+/*224*/, 65536 *16 * 0.01700428326907068
+/*225*/, 65536 *16 * 0.017561819587529177
+/*226*/, 65536 *16 * 0.018096338432718698
+/*227*/, 65536 *16 * 0.018606183762999433
+/*228*/, 65536 *16 * 0.019089749497960648
+/*229*/, 65536 *16 * 0.019545523698532997
+/*230*/, 65536 *16 * 0.019972069058400564
+/*231*/, 65536 *16 * 0.02036803110561515
+/*232*/, 65536 *16 * 0.020732154475618856
+/*233*/, 65536 *16 * 0.021063275458886234
+/*234*/, 65536 *16 * 0.021360340738775345
+/*235*/, 65536 *16 * 0.02162239534537267
+/*236*/, 65536 *16 * 0.021848603142668337
+/*237*/, 65536 *16 * 0.02203823092181804
+/*238*/, 65536 *16 * 0.022190674411724294
+/*239*/, 65536 *16 * 0.022305434241445123
+/*240*/, 65536 *16 * 0.022382153728111424
+/*241*/, 65536 *16 * 0.022420574751016616
+};
+
+/* 44100 PAL
+Parks-McClellan FIR Filter Design
+
+Filter type: Low pass
+Passband: 0 - 0.0076373
+Order: 483
+Passband ripple: 0.1 dB
+Transition band: 0.005625
+Stopband attenuation: 60.5 dB
+
+Coefficients:
+*/
+static int32 C44100PAL[NCOEFFS/2]=
+{
+/*0*/ 65536 *16 * 5.793783958720019E-4
+/*1*/, 65536 *16 * 1.0571291666629312E-4
+/*2*/, 65536 *16 * 1.1459085882755871E-4
+/*3*/, 65536 *16 * 1.2371675029136968E-4
+/*4*/, 65536 *16 * 1.3275170325031607E-4
+/*5*/, 65536 *16 * 1.4207721167879995E-4
+/*6*/, 65536 *16 * 1.5130497600100568E-4
+/*7*/, 65536 *16 * 1.6077227873948047E-4
+/*8*/, 65536 *16 * 1.6990814771316866E-4
+/*9*/, 65536 *16 * 1.79005024990367E-4
+/*10*/, 65536 *16 * 1.8739246068939436E-4
+/*11*/, 65536 *16 * 1.9572039600801667E-4
+/*12*/, 65536 *16 * 2.0352846914404956E-4
+/*13*/, 65536 *16 * 2.1201116607443127E-4
+/*14*/, 65536 *16 * 2.188838839136502E-4
+/*15*/, 65536 *16 * 2.2495686284733203E-4
+/*16*/, 65536 *16 * 2.3149812422937834E-4
+/*17*/, 65536 *16 * 2.363635497444841E-4
+/*18*/, 65536 *16 * 2.410054979130104E-4
+/*19*/, 65536 *16 * 2.445286108284421E-4
+/*20*/, 65536 *16 * 2.474675828550653E-4
+/*21*/, 65536 *16 * 2.4934815214903343E-4
+/*22*/, 65536 *16 * 2.50372333906785E-4
+/*23*/, 65536 *16 * 2.501665763315339E-4
+/*24*/, 65536 *16 * 2.488750795254978E-4
+/*25*/, 65536 *16 * 2.4640153199411455E-4
+/*26*/, 65536 *16 * 2.428720291968876E-4
+/*27*/, 65536 *16 * 2.3801309032826844E-4
+/*28*/, 65536 *16 * 2.3160240772113682E-4
+/*29*/, 65536 *16 * 2.2423402291517938E-4
+/*30*/, 65536 *16 * 2.152856501527123E-4
+/*31*/, 65536 *16 * 2.0488674543318888E-4
+/*32*/, 65536 *16 * 1.9317919544163198E-4
+/*33*/, 65536 *16 * 1.7994016398005858E-4
+/*34*/, 65536 *16 * 1.6541109383681028E-4
+/*35*/, 65536 *16 * 1.4938382649739635E-4
+/*36*/, 65536 *16 * 1.3200975730094075E-4
+/*37*/, 65536 *16 * 1.1313240842725184E-4
+/*38*/, 65536 *16 * 9.296992728984174E-5
+/*39*/, 65536 *16 * 7.143010735440594E-5
+/*40*/, 65536 *16 * 4.8632764324109725E-5
+/*41*/, 65536 *16 * 2.443073549738759E-5
+/*42*/, 65536 *16 * -8.284349612349981E-7
+/*43*/, 65536 *16 * -2.7227387247375577E-5
+/*44*/, 65536 *16 * -5.4818038895146106E-5
+/*45*/, 65536 *16 * -8.330005435111118E-5
+/*46*/, 65536 *16 * -1.1275737974091186E-4
+/*47*/, 65536 *16 * -1.4298620796919756E-4
+/*48*/, 65536 *16 * -1.7390785487074508E-4
+/*49*/, 65536 *16 * -2.054308580401118E-4
+/*50*/, 65536 *16 * -2.37415521983132E-4
+/*51*/, 65536 *16 * -2.697456782629617E-4
+/*52*/, 65536 *16 * -3.022375619849705E-4
+/*53*/, 65536 *16 * -3.348339660959209E-4
+/*54*/, 65536 *16 * -3.673583086741243E-4
+/*55*/, 65536 *16 * -3.996554197363865E-4
+/*56*/, 65536 *16 * -4.3147108191834185E-4
+/*57*/, 65536 *16 * -4.6285023012872966E-4
+/*58*/, 65536 *16 * -4.934440989261961E-4
+/*59*/, 65536 *16 * -5.231720978150925E-4
+/*60*/, 65536 *16 * -5.518656107257292E-4
+/*61*/, 65536 *16 * -5.793049560550073E-4
+/*62*/, 65536 *16 * -6.053792205725333E-4
+/*63*/, 65536 *16 * -6.298765704841736E-4
+/*64*/, 65536 *16 * -6.526402738994988E-4
+/*65*/, 65536 *16 * -6.734722964365358E-4
+/*66*/, 65536 *16 * -6.922485843472661E-4
+/*67*/, 65536 *16 * -7.088111930758961E-4
+/*68*/, 65536 *16 * -7.229789042068006E-4
+/*69*/, 65536 *16 * -7.34572975483669E-4
+/*70*/, 65536 *16 * -7.435049180176613E-4
+/*71*/, 65536 *16 * -7.496258178311876E-4
+/*72*/, 65536 *16 * -7.527294926570751E-4
+/*73*/, 65536 *16 * -7.528075552986548E-4
+/*74*/, 65536 *16 * -7.496410435428715E-4
+/*75*/, 65536 *16 * -7.432054606042111E-4
+/*76*/, 65536 *16 * -7.33375741493331E-4
+/*77*/, 65536 *16 * -7.200753858529672E-4
+/*78*/, 65536 *16 * -7.03226653737734E-4
+/*79*/, 65536 *16 * -6.827921676621563E-4
+/*80*/, 65536 *16 * -6.58752773848678E-4
+/*81*/, 65536 *16 * -6.31061807229375E-4
+/*82*/, 65536 *16 * -5.997124150992168E-4
+/*83*/, 65536 *16 * -5.647352645065657E-4
+/*84*/, 65536 *16 * -5.261799041455252E-4
+/*85*/, 65536 *16 * -4.8402880277824417E-4
+/*86*/, 65536 *16 * -4.3840329475572E-4
+/*87*/, 65536 *16 * -3.893672279202991E-4
+/*88*/, 65536 *16 * -3.37002579326518E-4
+/*89*/, 65536 *16 * -2.8148278838384204E-4
+/*90*/, 65536 *16 * -2.2288467365854118E-4
+/*91*/, 65536 *16 * -1.6140368454103024E-4
+/*92*/, 65536 *16 * -9.718648150744015E-5
+/*93*/, 65536 *16 * -3.046343268277719E-5
+/*94*/, 65536 *16 * 3.859234051837562E-5
+/*95*/, 65536 *16 * 1.0974328274324426E-4
+/*96*/, 65536 *16 * 1.8273974279995372E-4
+/*97*/, 65536 *16 * 2.5730055402762935E-4
+/*98*/, 65536 *16 * 3.3318458939353874E-4
+/*99*/, 65536 *16 * 4.100891270013777E-4
+/*100*/, 65536 *16 * 4.876860015464126E-4
+/*101*/, 65536 *16 * 5.657011755504638E-4
+/*102*/, 65536 *16 * 6.437547403393535E-4
+/*103*/, 65536 *16 * 7.215350856659516E-4
+/*104*/, 65536 *16 * 7.986901321007353E-4
+/*105*/, 65536 *16 * 8.748424228508639E-4
+/*106*/, 65536 *16 * 9.496338070297501E-4
+/*107*/, 65536 *16 * 0.0010226804298925178
+/*108*/, 65536 *16 * 0.001093633836878271
+/*109*/, 65536 *16 * 0.0011620773771650913
+/*110*/, 65536 *16 * 0.001227641045409496
+/*111*/, 65536 *16 * 0.0012899374110895208
+/*112*/, 65536 *16 * 0.001348607725415767
+/*113*/, 65536 *16 * 0.001403236086962171
+/*114*/, 65536 *16 * 0.0014534904370406968
+/*115*/, 65536 *16 * 0.0014989864777827345
+/*116*/, 65536 *16 * 0.0015393672007052272
+/*117*/, 65536 *16 * 0.0015743174329729173
+/*118*/, 65536 *16 * 0.0016034756800234508
+/*119*/, 65536 *16 * 0.0016265420570988364
+/*120*/, 65536 *16 * 0.0016432110467175217
+/*121*/, 65536 *16 * 0.0016532197970121178
+/*122*/, 65536 *16 * 0.0016562968359550962
+/*123*/, 65536 *16 * 0.0016521969919585549
+/*124*/, 65536 *16 * 0.001640721606064916
+/*125*/, 65536 *16 * 0.001621678045313759
+/*126*/, 65536 *16 * 0.0015948992297934834
+/*127*/, 65536 *16 * 0.0015602457924787695
+/*128*/, 65536 *16 * 0.0015176354451292787
+/*129*/, 65536 *16 * 0.0014669598890367775
+/*130*/, 65536 *16 * 0.001408218899058892
+/*131*/, 65536 *16 * 0.001341376545671481
+/*132*/, 65536 *16 * 0.0012664621369705463
+/*133*/, 65536 *16 * 0.0011835425953369801
+/*134*/, 65536 *16 * 0.0010927146027981068
+/*135*/, 65536 *16 * 9.941150953832762E-4
+/*136*/, 65536 *16 * 8.878982163088053E-4
+/*137*/, 65536 *16 * 7.742911468907501E-4
+/*138*/, 65536 *16 * 6.535350381595103E-4
+/*139*/, 65536 *16 * 5.259114487251054E-4
+/*140*/, 65536 *16 * 3.9173611703422796E-4
+/*141*/, 65536 *16 * 2.513813444320677E-4
+/*142*/, 65536 *16 * 1.0522988594595334E-4
+/*143*/, 65536 *16 * -4.627799877161863E-5
+/*144*/, 65536 *16 * -2.0266153878465397E-4
+/*145*/, 65536 *16 * -3.6344539072942917E-4
+/*146*/, 65536 *16 * -5.28061484912101E-4
+/*147*/, 65536 *16 * -6.959549845043866E-4
+/*148*/, 65536 *16 * -8.665108935058429E-4
+/*149*/, 65536 *16 * -0.0010391137133997624
+/*150*/, 65536 *16 * -0.001213088248571412
+/*151*/, 65536 *16 * -0.0013877438142645866
+/*152*/, 65536 *16 * -0.0015623746142961936
+/*153*/, 65536 *16 * -0.001736242850147973
+/*154*/, 65536 *16 * -0.0019085899496564314
+/*155*/, 65536 *16 * -0.002078639823528187
+/*156*/, 65536 *16 * -0.0022456104279907118
+/*157*/, 65536 *16 * -0.002408678368623706
+/*158*/, 65536 *16 * -0.002567052121352872
+/*159*/, 65536 *16 * -0.0027198956481072887
+/*160*/, 65536 *16 * -0.0028663750213148488
+/*161*/, 65536 *16 * -0.0030056713494924794
+/*162*/, 65536 *16 * -0.0031369487365098063
+/*163*/, 65536 *16 * -0.0032593909953083865
+/*164*/, 65536 *16 * -0.0033721594370116153
+/*165*/, 65536 *16 * -0.0034744643621211356
+/*166*/, 65536 *16 * -0.0035654990231207963
+/*167*/, 65536 *16 * -0.003644488024347632
+/*168*/, 65536 *16 * -0.0037106644342197828
+/*169*/, 65536 *16 * -0.0037632989436418352
+/*170*/, 65536 *16 * -0.00380166827783197
+/*171*/, 65536 *16 * -0.0038250950477227447
+/*172*/, 65536 *16 * -0.0038329329853570827
+/*173*/, 65536 *16 * -0.0038245430145814447
+/*174*/, 65536 *16 * -0.0037993625516763766
+/*175*/, 65536 *16 * -0.003756842883124589
+/*176*/, 65536 *16 * -0.0036964913119694686
+/*177*/, 65536 *16 * -0.0036178458358447655
+/*178*/, 65536 *16 * -0.00352050628243193
+/*179*/, 65536 *16 * -0.003404123578517079
+/*180*/, 65536 *16 * -0.003268383375473133
+/*181*/, 65536 *16 * -0.0031130454148921446
+/*182*/, 65536 *16 * -0.002937909773123352
+/*183*/, 65536 *16 * -0.0027428475146560275
+/*184*/, 65536 *16 * -0.0025277729297779944
+/*185*/, 65536 *16 * -0.0022926869206439508
+/*186*/, 65536 *16 * -0.0020376141174133374
+/*187*/, 65536 *16 * -0.0017626719756025908
+/*188*/, 65536 *16 * -0.0014680351622130402
+/*189*/, 65536 *16 * -0.0011539297872750212
+/*190*/, 65536 *16 * -8.206567501069872E-4
+/*191*/, 65536 *16 * -4.685710694984321E-4
+/*192*/, 65536 *16 * -9.811116382477182E-5
+/*193*/, 65536 *16 * 2.902488429495873E-4
+/*194*/, 65536 *16 * 6.959516881166062E-4
+/*195*/, 65536 *16 * 0.0011183883405789612
+/*196*/, 65536 *16 * 0.0015568865209671754
+/*197*/, 65536 *16 * 0.0020107155705137744
+/*198*/, 65536 *16 * 0.002479084293281152
+/*199*/, 65536 *16 * 0.002961149037985776
+/*200*/, 65536 *16 * 0.0034560223628435746
+/*201*/, 65536 *16 * 0.0039627343373741354
+/*202*/, 65536 *16 * 0.0044803036416812955
+/*203*/, 65536 *16 * 0.005007678185806692
+/*204*/, 65536 *16 * 0.00554377521563058
+/*205*/, 65536 *16 * 0.006087456836491167
+/*206*/, 65536 *16 * 0.006637561024809676
+/*207*/, 65536 *16 * 0.007192890398414245
+/*208*/, 65536 *16 * 0.0077522050201042055
+/*209*/, 65536 *16 * 0.008314254820045306
+/*210*/, 65536 *16 * 0.008877749982246051
+/*211*/, 65536 *16 * 0.009441393781470539
+/*212*/, 65536 *16 * 0.010003862886118781
+/*213*/, 65536 *16 * 0.01056383933598836
+/*214*/, 65536 *16 * 0.011119972235266088
+/*215*/, 65536 *16 * 0.011670924253482212
+/*216*/, 65536 *16 * 0.012215363764388693
+/*217*/, 65536 *16 * 0.012751945584822125
+/*218*/, 65536 *16 * 0.013279348664168343
+/*219*/, 65536 *16 * 0.013796251849197938
+/*220*/, 65536 *16 * 0.0143013718962506
+/*221*/, 65536 *16 * 0.014793420656675483
+/*222*/, 65536 *16 * 0.015271157641252524
+/*223*/, 65536 *16 * 0.015733358657288442
+/*224*/, 65536 *16 * 0.016178837288118402
+/*225*/, 65536 *16 * 0.016606446422463023
+/*226*/, 65536 *16 * 0.01701507865820779
+/*227*/, 65536 *16 * 0.017403671672970734
+/*228*/, 65536 *16 * 0.01777119975394863
+/*229*/, 65536 *16 * 0.018116717572056962
+/*230*/, 65536 *16 * 0.01843930362202181
+/*231*/, 65536 *16 * 0.01873811058717855
+/*232*/, 65536 *16 * 0.01901234584784063
+/*233*/, 65536 *16 * 0.019261287195027194
+/*234*/, 65536 *16 * 0.019484271195397335
+/*235*/, 65536 *16 * 0.0196806998422779
+/*236*/, 65536 *16 * 0.019850058102456474
+/*237*/, 65536 *16 * 0.019991882444368586
+/*238*/, 65536 *16 * 0.0201058042761605
+/*239*/, 65536 *16 * 0.02019151207246131
+/*240*/, 65536 *16 * 0.02024878178965319
+/*241*/, 65536 *16 * 0.020277449712345474
+};
diff --git a/fds.c b/fds.c
new file mode 100644
index 00000000..901a618e
--- /dev/null
+++ b/fds.c
@@ -0,0 +1,887 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "types.h"
+#include "x6502.h"
+#include "fceu.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"
+
+/* 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<TotalSides;x++)
+ {
+ int b;
+ for(b=0; b<65500; b++)
+ diskdata[x][b] ^= diskdatao[x][b];
+ }
+
+}
+
+void FDSSound();
+void FDSSoundReset(void);
+void FDSSoundStateAdd(void);
+static void RenderSound(void);
+static void RenderSoundHQ(void);
+
+static void FDSInit(void)
+{
+ memset(FDSRegs,0,sizeof(FDSRegs));
+ writeskip=DiskPtr=DiskSeekIRQ=0;
+ setmirror(1);
+
+ 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,0x4025,FDSWrite);
+
+ SetWriteHandler(0x6000,0xdfff,FDSRAMWrite);
+ SetReadHandler(0x6000,0xdfff,FDSRAMRead);
+ SetReadHandler(0xE000,0xFFFF,FDSBIOSRead);
+ IRQCount=IRQLatch=IRQa=0;
+
+ FDSSoundReset();
+ InDisk=0;
+ SelectDisk=0;
+}
+
+void FCEU_FDSInsert(void)
+{
+ if(TotalSides==0)
+ {
+ FCEU_DispMessage("Not FDS; can't eject disk.");
+ return;
+ }
+ if(InDisk==255)
+ {
+ FCEU_DispMessage("Disk %d Side %s Inserted",SelectDisk>>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(FSettings.soundq>=1)
+ RenderSoundHQ();
+ else
+ 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<end;x++)
+ {
+ uint32 t=FDSDoSound();
+ t+=t>>1;
+ t>>=4;
+ Wave[x>>4]+=t; //(t>>2)-(t>>3); //>>3;
+ }
+}
+
+static void RenderSoundHQ(void)
+{
+ int32 x;
+
+ if(!(SPSG[0x9]&0x80))
+ for(x=FBC;x<SOUNDTS;x++)
+ {
+ uint32 t=FDSDoSound();
+ t+=t>>1;
+ WaveHi[x]+=t; //(t<<2)-(t<<1);
+ }
+ FBC=SOUNDTS;
+}
+
+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(FSettings.soundq>=1)
+ {
+ fdso.cycles=(int64)1<<39;
+ }
+ else
+ {
+ 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=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;x<TotalSides;x++)
+ if(diskdata[x])
+ {
+ free(diskdata[x]);
+ diskdata[x]=0;
+ }
+}
+
+static int SubLoad(FCEUFILE *fp)
+{
+ struct md5_context md5;
+ uint8 header[16];
+ int x;
+
+ FCEU_fread(header,16,1,fp);
+
+ if(memcmp(header,"FDS\x1a",4))
+ {
+ if(!(memcmp(header+1,"*NINTENDO-HVC*",14)))
+ {
+ long t;
+ t=FCEU_fgetsize(fp);
+ if(t<65500)
+ t=65500;
+ TotalSides=t/65500;
+ FCEU_fseek(fp,0,SEEK_SET);
+ }
+ else
+ return(0);
+ }
+ else
+ TotalSides=header[4];
+
+ md5_starts(&md5);
+
+ if(TotalSides>8) TotalSides=8;
+ if(TotalSides<1) TotalSides=1;
+
+ for(x=0;x<TotalSides;x++)
+ {
+ diskdata[x]=(uint8 *)FCEU_malloc(65500);
+ if(!diskdata[x])
+ {
+ int zol;
+ for(zol=0;zol<x;zol++)
+ free(diskdata[zol]);
+ return 0;
+ }
+ FCEU_fread(diskdata[x],1,65500,fp);
+ md5_update(&md5,diskdata[x],65500);
+ }
+ md5_finish(&md5,FCEUGameInfo->MD5);
+ return(1);
+}
+
+static void PreSave(void)
+{
+ int x;
+
+ //if(DiskWritten)
+ for(x=0;x<TotalSides;x++)
+ {
+ int b;
+ for(b=0; b<65500; b++)
+ diskdata[x][b] ^= diskdatao[x][b];
+ }
+}
+
+static void PostSave(void)
+{
+ int x;
+
+ //if(DiskWritten)
+ for(x=0;x<TotalSides;x++)
+ {
+ int b;
+
+ for(b=0; b<65500; b++)
+ diskdata[x][b] ^= diskdatao[x][b];
+ }
+
+}
+
+int FDSLoad(const char *name, FCEUFILE *fp)
+{
+ FILE *zp;
+ int x;
+ char *fn;
+
+ FCEU_fseek(fp,0,SEEK_SET);
+
+ if(!SubLoad(fp))
+ return(0);
+
+
+ fn = FCEU_MakeFName(FCEUMKF_FDSROM,0,0);
+
+ if(!(zp=FCEUD_UTF8fopen(fn,"rb")))
+ {
+ FCEU_PrintError("FDS BIOS ROM image missing!");
+ FreeFDSMemory();
+ free(fn);
+ return 0;
+ }
+
+ free(fn);
+
+ if(fread(FDSBIOS,1,8192,zp)!=8192)
+ {
+ fclose(zp);
+ FreeFDSMemory();
+ FCEU_PrintError("Error reading FDS BIOS ROM image.");
+ return 0;
+ }
+
+ fclose(zp);
+
+
+ {
+ FCEUFILE *tp;
+ char *fn=FCEU_MakeFName(FCEUMKF_FDS,0,0);
+
+ int x;
+ for(x=0;x<TotalSides;x++)
+ {
+ diskdatao[x]=(uint8 *)FCEU_malloc(65500);
+ memcpy(diskdatao[x],diskdata[x],65500);
+ }
+
+ if((tp=FCEU_fopen(fn,0,"rb",0)))
+ {
+ FreeFDSMemory();
+ if(!SubLoad(tp))
+ {
+ FCEU_PrintError("Error reading auxillary FDS file.");
+ free(fn);
+ return(0);
+ }
+ FCEU_fclose(tp);
+ DiskWritten=1; /* For save state handling. */
+ }
+ free(fn);
+ }
+
+ FCEUGameInfo->type=GIT_FDS;
+ GameInterface=FDSGI;
+
+ SelectDisk=0;
+ InDisk=255;
+
+ ResetExState(PreSave,PostSave);
+ FDSSoundStateAdd();
+
+ for(x=0;x<TotalSides;x++)
+ {
+ char temp[5];
+ sprintf(temp,"DDT%d",x);
+ AddExState(diskdata[x],65500,0,temp);
+ }
+
+ AddExState(FDSRAM,32768,0,"FDSR");
+ AddExState(FDSRegs,sizeof(FDSRegs),0,"FREG");
+ AddExState(CHRRAM,8192,0,"CHRR");
+ AddExState(&IRQCount, 4, 1, "IRQC");
+ AddExState(&IRQLatch, 4, 1, "IQL1");
+ AddExState(&IRQa, 1, 0, "IRQA");
+ AddExState(&writeskip,1,0,"WSKI");
+ AddExState(&DiskPtr,4,1,"DPTR");
+ AddExState(&DiskSeekIRQ,4,1,"DSIR");
+ AddExState(&SelectDisk,1,0,"SELD");
+ AddExState(&InDisk,1,0,"INDI");
+ AddExState(&DiskWritten,1,0,"DSKW");
+
+ ResetCartMapping();
+ SetupCartCHRMapping(0,CHRRAM,8192,1);
+ SetupCartMirroring(0,0,0);
+ memset(CHRRAM,0,8192);
+ memset(FDSRAM,0,32768);
+
+ FCEU_printf(" Sides: %d\n\n",TotalSides);
+
+ FCEUI_SetVidSystem(0);
+
+ return 1;
+}
+
+void FDSClose(void)
+{
+ FILE *fp;
+ int x;
+ char *fn=FCEU_MakeFName(FCEUMKF_FDS,0,0);
+
+ if(!DiskWritten) return;
+
+ if(!(fp=FCEUD_UTF8fopen(fn,"wb")))
+ {
+ free(fn);
+ return;
+ }
+ free(fn);
+
+ for(x=0;x<TotalSides;x++)
+ {
+ if(fwrite(diskdata[x],1,65500,fp)!=65500)
+ {
+ FCEU_PrintError("Error saving FDS image!");
+ fclose(fp);
+ return;
+ }
+ }
+ FreeFDSMemory();
+ fclose(fp);
+}
diff --git a/fds.h b/fds.h
new file mode 100644
index 00000000..4269d70f
--- /dev/null
+++ b/fds.h
@@ -0,0 +1,5 @@
+void FDSSoundReset(void);
+
+void FCEU_FDSInsert(void);
+//void FCEU_FDSEject(void);
+void FCEU_FDSSelect(void);
diff --git a/file.c b/file.c
new file mode 100644
index 00000000..475d4b97
--- /dev/null
+++ b/file.c
@@ -0,0 +1,574 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <zlib.h>
+#include "unzip.h"
+
+#include "types.h"
+#include "file.h"
+#include "endian.h"
+#include "memory.h"
+#include "driver.h"
+#include "general.h"
+
+typedef struct {
+ uint8 *data;
+ uint32 size;
+ uint32 location;
+} MEMWRAP;
+
+void ApplyIPS(FILE *ips, MEMWRAP *dest)
+{
+ uint8 header[5];
+ uint32 count=0;
+
+ FCEU_printf(" Applying IPS...\n");
+ if(fread(header,1,5,ips)!=5)
+ {
+ fclose(ips);
+ return;
+ }
+ if(memcmp(header,"PATCH",5))
+ {
+ fclose(ips);
+ return;
+ }
+
+ while(fread(header,1,3,ips)==3)
+ {
+ uint32 offset=(header[0]<<16)|(header[1]<<8)|header[2];
+ uint16 size;
+
+ if(!memcmp(header,"EOF",3))
+ {
+ FCEU_printf(" IPS EOF: Did %d patches\n\n",count);
+ fclose(ips);
+ return;
+ }
+
+ size=fgetc(ips)<<8;
+ size|=fgetc(ips);
+ if(!size) /* RLE */
+ {
+ uint8 *start;
+ uint8 b;
+ size=fgetc(ips)<<8;
+ size|=fgetc(ips);
+
+ //FCEU_printf(" Offset: %8d Size: %5d RLE\n",offset,size);
+
+ if((offset+size)>dest->size)
+ {
+ uint8 *tmp;
+
+ // Probably a little slow.
+ tmp=(uint8 *)realloc(dest->data,offset+size);
+ if(!tmp)
+ {
+ FCEU_printf(" Oops. IPS patch %d(type RLE) goes beyond end of file. Could not allocate memory.\n",count);
+ fclose(ips);
+ return;
+ }
+ dest->size=offset+size;
+ dest->data=tmp;
+ memset(dest->data+dest->size,0,offset+size-dest->size);
+ }
+ b=fgetc(ips);
+ start=dest->data+offset;
+ do
+ {
+ *start=b;
+ start++;
+ } while(--size);
+ }
+ else /* Normal patch */
+ {
+ //FCEU_printf(" Offset: %8d Size: %5d\n",offset,size);
+ if((offset+size)>dest->size)
+ {
+ uint8 *tmp;
+
+ // Probably a little slow.
+ tmp=(uint8 *)realloc(dest->data,offset+size);
+ if(!tmp)
+ {
+ FCEU_printf(" Oops. IPS patch %d(type normal) goes beyond end of file. Could not allocate memory.\n",count);
+ fclose(ips);
+ return;
+ }
+ dest->data=tmp;
+ memset(dest->data+dest->size,0,offset+size-dest->size);
+ }
+ fread(dest->data+offset,1,size,ips);
+ }
+ count++;
+ }
+ fclose(ips);
+ FCEU_printf(" Hard IPS end!\n");
+}
+
+static MEMWRAP *MakeMemWrap(void *tz, int type)
+{
+ MEMWRAP *tmp;
+
+ if(!(tmp=(MEMWRAP *)FCEU_malloc(sizeof(MEMWRAP))))
+ goto doret;
+ tmp->location=0;
+
+ if(type==0)
+ {
+ fseek((FILE *)tz,0,SEEK_END);
+ tmp->size=ftell((FILE *)tz);
+ fseek((FILE *)tz,0,SEEK_SET);
+ if(!(tmp->data=(uint8*)FCEU_malloc(tmp->size)))
+ {
+ free(tmp);
+ tmp=0;
+ goto doret;
+ }
+ fread(tmp->data,1,tmp->size,(FILE *)tz);
+ }
+ else if(type==1)
+ {
+ /* Bleck. The gzip file format has the size of the uncompressed data,
+ but I can't get to the info with the zlib interface(?). */
+ for(tmp->size=0; gzgetc(tz) != EOF; tmp->size++);
+ gzseek(tz,0,SEEK_SET);
+ if(!(tmp->data=(uint8 *)FCEU_malloc(tmp->size)))
+ {
+ free(tmp);
+ tmp=0;
+ goto doret;
+ }
+ gzread(tz,tmp->data,tmp->size);
+ }
+ else if(type==2)
+ {
+ unz_file_info ufo;
+ unzGetCurrentFileInfo(tz,&ufo,0,0,0,0,0,0);
+
+ tmp->size=ufo.uncompressed_size;
+ if(!(tmp->data=(uint8 *)FCEU_malloc(ufo.uncompressed_size)))
+ {
+ free(tmp);
+ tmp=0;
+ goto doret;
+ }
+ unzReadCurrentFile(tz,tmp->data,ufo.uncompressed_size);
+ }
+
+ doret:
+ if(type==0)
+ {
+ fclose((FILE *)tz);
+ }
+ else if(type==1)
+ {
+ gzclose(tz);
+ }
+ else if(type==2)
+ {
+ unzCloseCurrentFile(tz);
+ unzClose(tz);
+ }
+ return tmp;
+}
+
+#ifndef __GNUC__
+ #define strcasecmp strcmp
+#endif
+
+
+FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext)
+{
+ FILE *ipsfile=0;
+ FCEUFILE *fceufp;
+ void *t;
+
+ if(strchr(mode,'r'))
+ ipsfile=FCEUD_UTF8fopen(ipsfn,"rb");
+
+ fceufp=(FCEUFILE *)malloc(sizeof(FCEUFILE));
+
+ {
+ unzFile tz;
+ if((tz=unzOpen(path))) // If it's not a zip file, use regular file handlers.
+ // Assuming file type by extension usually works,
+ // but I don't like it. :)
+ {
+ if(unzGoToFirstFile(tz)==UNZ_OK)
+ {
+ for(;;)
+ {
+ char tempu[512]; // Longer filenames might be possible, but I don't
+ // think people would name files that long in zip files...
+ unzGetCurrentFileInfo(tz,0,tempu,512,0,0,0,0);
+ tempu[511]=0;
+ if(strlen(tempu)>=4)
+ {
+ char *za=tempu+strlen(tempu)-4;
+
+ if(!ext)
+ {
+ if(!strcasecmp(za,".nes") || !strcasecmp(za,".fds") ||
+ !strcasecmp(za,".nsf") || !strcasecmp(za,".unf") ||
+ !strcasecmp(za,".nez"))
+ break;
+ }
+ else if(!strcasecmp(za,ext))
+ break;
+ }
+ if(strlen(tempu)>=5)
+ {
+ if(!strcasecmp(tempu+strlen(tempu)-5,".unif"))
+ break;
+ }
+ if(unzGoToNextFile(tz)!=UNZ_OK)
+ {
+ if(unzGoToFirstFile(tz)!=UNZ_OK) goto zpfail;
+ break;
+ }
+ }
+ if(unzOpenCurrentFile(tz)!=UNZ_OK)
+ goto zpfail;
+ }
+ else
+ {
+ zpfail:
+ free(fceufp);
+ unzClose(tz);
+ return 0;
+ }
+ if(!(fceufp->fp=MakeMemWrap(tz,2)))
+ {
+ free(fceufp);
+ return(0);
+ }
+ fceufp->type=2;
+ if(ipsfile)
+ ApplyIPS(ipsfile,(MEMWRAP *)fceufp->fp);
+ return(fceufp);
+ }
+ }
+
+ if((t=FCEUD_UTF8fopen(path,"rb")))
+ {
+ uint32 magic;
+
+ magic=fgetc((FILE *)t);
+ magic|=fgetc((FILE *)t)<<8;
+ magic|=fgetc((FILE *)t)<<16;
+
+ if(magic!=0x088b1f) /* Not gzip... */
+ fclose((FILE *)t);
+ else /* Probably gzip */
+ {
+ int fd;
+
+ fd = dup(fileno( (FILE *)t));
+
+ fclose(t);
+
+ lseek(fd, 0, SEEK_SET);
+
+ if((t=gzdopen(fd,mode)))
+ {
+ fceufp->type=1;
+ fceufp->fp=t;
+ if(ipsfile)
+ {
+ fceufp->fp=MakeMemWrap(t,1);
+ gzclose(t);
+
+ if(fceufp->fp)
+ {
+ free(fceufp);
+ return(0);
+ }
+
+ fceufp->type=3;
+ ApplyIPS(ipsfile,(MEMWRAP *)fceufp->fp);
+ }
+ return(fceufp);
+ }
+ close(fd);
+ }
+
+ }
+
+ if((t=FCEUD_UTF8fopen(path,mode)))
+ {
+ fseek((FILE *)t,0,SEEK_SET);
+ fceufp->type=0;
+ fceufp->fp=t;
+ if(ipsfile)
+ {
+ if(!(fceufp->fp=MakeMemWrap(t,0)))
+ {
+ free(fceufp);
+ return(0);
+ }
+ fceufp->type=3;
+ ApplyIPS(ipsfile,(MEMWRAP *)fceufp->fp);
+ }
+ return(fceufp);
+ }
+
+ free(fceufp);
+ return 0;
+}
+
+int FCEU_fclose(FCEUFILE *fp)
+{
+ if(fp->type==1)
+ {
+ gzclose(fp->fp);
+ }
+ else if(fp->type>=2)
+ {
+ free(((MEMWRAP*)(fp->fp))->data);
+ free(fp->fp);
+ }
+ else
+ {
+ fclose((FILE *)fp->fp);
+ }
+ free(fp);
+ return 1;
+}
+
+uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp)
+{
+ if(fp->type==1)
+ {
+ return gzread(fp->fp,ptr,size*nmemb);
+ }
+ else if(fp->type>=2)
+ {
+ MEMWRAP *wz;
+ uint32 total=size*nmemb;
+
+ wz=(MEMWRAP*)fp->fp;
+ if(wz->location>=wz->size) return 0;
+
+ if((wz->location+total)>wz->size)
+ {
+ int ak=wz->size-wz->location;
+ memcpy((uint8*)ptr,wz->data+wz->location,ak);
+ wz->location=wz->size;
+ return(ak/size);
+ }
+ else
+ {
+ memcpy((uint8*)ptr,wz->data+wz->location,total);
+ wz->location+=total;
+ return nmemb;
+ }
+ }
+ else
+ {
+ return fread(ptr,size,nmemb,(FILE *)fp->fp);
+ }
+}
+
+uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp)
+{
+ if(fp->type==1)
+ {
+ return gzwrite(fp->fp,ptr,size*nmemb);
+ }
+ else if(fp->type>=2)
+ {
+ return 0;
+ }
+ else
+ return fwrite(ptr,size,nmemb,(FILE *)fp->fp);
+}
+
+int FCEU_fseek(FCEUFILE *fp, long offset, int whence)
+{
+ if(fp->type==1)
+ {
+ return( (gzseek(fp->fp,offset,whence)>0)?0:-1);
+ }
+ else if(fp->type>=2)
+ {
+ MEMWRAP *wz;
+ wz=(MEMWRAP*)fp->fp;
+
+ switch(whence)
+ {
+ case SEEK_SET:if(offset>=wz->size)
+ return(-1);
+ wz->location=offset;break;
+ case SEEK_CUR:if(offset+wz->location>wz->size)
+ return (-1);
+ wz->location+=offset;
+ break;
+ }
+ return 0;
+ }
+ else
+ return fseek((FILE *)fp->fp,offset,whence);
+}
+
+uint64 FCEU_ftell(FCEUFILE *fp)
+{
+ if(fp->type==1)
+ {
+ return gztell(fp->fp);
+ }
+ else if(fp->type>=2)
+ {
+ return (((MEMWRAP *)(fp->fp))->location);
+ }
+ else
+ return ftell((FILE *)fp->fp);
+}
+
+void FCEU_rewind(FCEUFILE *fp)
+{
+ if(fp->type==1)
+ {
+ gzrewind(fp->fp);
+ }
+ else if(fp->type>=2)
+ {
+ ((MEMWRAP *)(fp->fp))->location=0;
+ }
+ else
+ /* Rewind */
+ fseek(fp->fp,0,SEEK_SET);
+}
+
+int FCEU_read16le(uint16 *val, FCEUFILE *fp)
+{
+ uint8 t[2];
+
+ if(fp->type>=1)
+ {
+ if(fp->type>=2)
+ {
+ MEMWRAP *wz;
+ wz=(MEMWRAP *)fp->fp;
+ if(wz->location+2>wz->size)
+ {return 0;}
+ *(uint32 *)t=*(uint32 *)(wz->data+wz->location);
+ wz->location+=2;
+ }
+ else if(fp->type==1)
+ if(gzread(fp->fp,&t,2)!=2) return(0);
+ return(1);
+ }
+ else
+ {
+ if(fread(t,1,2,(FILE *)fp->fp)!=2) return(0);
+ }
+ *val=t[0]|(t[1]<<8);
+ return(1);
+}
+
+int FCEU_read32le(uint32 *Bufo, FCEUFILE *fp)
+{
+ if(fp->type>=1)
+ {
+ uint8 t[4];
+ #ifndef LSB_FIRST
+ uint8 x[4];
+ #endif
+ if(fp->type>=2)
+ {
+ MEMWRAP *wz;
+ wz=(MEMWRAP *)fp->fp;
+ if(wz->location+4>wz->size)
+ {return 0;}
+ *(uint32 *)t=*(uint32 *)(wz->data+wz->location);
+ wz->location+=4;
+ }
+ else if(fp->type==1)
+ gzread(fp->fp,&t,4);
+ #ifndef LSB_FIRST
+ x[0]=t[3];
+ x[1]=t[2];
+ x[2]=t[1];
+ x[3]=t[0];
+ *(uint32*)Bufo=*(uint32*)x;
+ #else
+ *(uint32*)Bufo=*(uint32*)t;
+ #endif
+ return 1;
+ }
+ else
+ {
+ return read32le(Bufo,(FILE *)fp->fp);
+ }
+}
+
+int FCEU_fgetc(FCEUFILE *fp)
+{
+ if(fp->type==1)
+ return gzgetc(fp->fp);
+ else if(fp->type>=2)
+ {
+ MEMWRAP *wz;
+ wz=(MEMWRAP *)fp->fp;
+ if(wz->location<wz->size)
+ return wz->data[wz->location++];
+ return EOF;
+ }
+ else
+ return fgetc((FILE *)fp->fp);
+}
+
+uint64 FCEU_fgetsize(FCEUFILE *fp)
+{
+ if(fp->type==1)
+ {
+ int x,t;
+ t=gztell(fp->fp);
+ gzrewind(fp->fp);
+ for(x=0; gzgetc(fp->fp) != EOF; x++);
+ gzseek(fp->fp,t,SEEK_SET);
+ return(x);
+ }
+ else if(fp->type>=2)
+ return ((MEMWRAP*)(fp->fp))->size;
+ else
+ {
+ long t,r;
+ t=ftell((FILE *)fp->fp);
+ fseek((FILE *)fp->fp,0,SEEK_END);
+ r=ftell((FILE *)fp->fp);
+ fseek((FILE *)fp->fp,t,SEEK_SET);
+ return r;
+ }
+}
+
+int FCEU_fisarchive(FCEUFILE *fp)
+{
+ if(fp->type==2)
+ return 1;
+ return 0;
+}
diff --git a/file.h b/file.h
new file mode 100644
index 00000000..8d473f9f
--- /dev/null
+++ b/file.h
@@ -0,0 +1,18 @@
+typedef struct {
+ void *fp; // FILE* or ptr to ZIPWRAP
+ uint32 type; // 0=normal file, 1=gzip, 2=zip
+} FCEUFILE;
+
+FCEUFILE *FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext);
+int FCEU_fclose(FCEUFILE*);
+uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE*);
+uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE*);
+int FCEU_fseek(FCEUFILE*, long offset, int whence);
+uint64 FCEU_ftell(FCEUFILE*);
+void FCEU_rewind(FCEUFILE*);
+int FCEU_read32le(uint32 *Bufo, FCEUFILE*);
+int FCEU_read16le(uint16 *Bufo, FCEUFILE*);
+int FCEU_fgetc(FCEUFILE*);
+uint64 FCEU_fgetsize(FCEUFILE*);
+int FCEU_fisarchive(FCEUFILE*);
+
diff --git a/filter.c b/filter.c
new file mode 100644
index 00000000..1d31b3f5
--- /dev/null
+++ b/filter.c
@@ -0,0 +1,201 @@
+#include <math.h>
+#include <stdio.h>
+#include "types.h"
+
+#include "sound.h"
+#include "x6502.h"
+#include "fceu.h"
+#include "filter.h"
+
+#include "fcoeffs.h"
+
+static uint32 mrindex;
+static uint32 mrratio;
+
+void SexyFilter2(int32 *in, int32 count)
+{
+ #ifdef moo
+ static int64 acc=0;
+ double x,p;
+ int64 c;
+
+ x=2*M_PI*6000/FSettings.SndRate;
+ p=((double)2-cos(x)) - sqrt(pow((double)2-cos(x),2) -1 );
+
+ c=p*0x100000;
+ //printf("%f\n",(double)c/0x100000);
+ #endif
+ static int64 acc=0;
+
+ while(count--)
+ {
+ int64 dropcurrent;
+ dropcurrent=((*in<<16)-acc)>>3;
+
+ acc+=dropcurrent;
+ *in=acc>>16;
+ in++;
+ //acc=((int64)0x100000-c)* *in + ((c*acc)>>20);
+ //*in=acc>>20;
+ //in++;
+ }
+}
+
+void SexyFilter(int32 *in, int32 *out, int32 count)
+{
+ static int64 acc1=0,acc2=0;
+ int32 mul1,mul2,vmul;
+
+ mul1=(94<<16)/FSettings.SndRate;
+ mul2=(24<<16)/FSettings.SndRate;
+ vmul=(FSettings.SoundVolume<<16)*3/4/100;
+
+ if(FSettings.soundq) vmul/=4;
+ else vmul*=2; /* TODO: Increase volume in low quality sound rendering code itself */
+
+ while(count)
+ {
+ int64 ino=(int64)*in*vmul;
+ acc1+=((ino-acc1)*mul1)>>16;
+ acc2+=((ino-acc1-acc2)*mul2)>>16;
+ //printf("%d ",*in);
+ *in=0;
+ {
+ int32 t=(acc1-ino+acc2)>>16;
+ //if(t>32767 || t<-32768) printf("Flow: %d\n",t);
+ if(t>32767) t=32767;
+ if(t<-32768) t=-32768;
+ *out=t;
+ }
+ in++;
+ out++;
+ count--;
+ }
+}
+
+/* Returns number of samples written to out. */
+/* leftover is set to the number of samples that need to be copied
+ from the end of in to the beginning of in.
+*/
+
+//static uint32 mva=1000;
+
+/* This filtering code assumes that almost all input values stay below 32767.
+ Do not adjust the volume in the wlookup tables and the expansion sound
+ code to be higher, or you *might* overflow the FIR code.
+*/
+
+int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover)
+{
+ uint32 x;
+ uint32 max;
+ int32 *outsave=out;
+ int32 count=0;
+
+// for(x=0;x<inlen;x++)
+// {
+// if(in[x]>mva){ mva=in[x]; printf("%ld\n",in[x]);}
+// }
+ max=(inlen-1)<<16;
+
+ if(FSettings.soundq==2)
+ for(x=mrindex;x<max;x+=mrratio)
+ {
+ int32 acc=0,acc2=0;
+ unsigned int c;
+ int32 *S,*D;
+
+ for(c=SQ2NCOEFFS,S=&in[(x>>16)-SQ2NCOEFFS],D=sq2coeffs;c;c--,D++)
+ {
+ acc+=(S[c]**D)>>6;
+ acc2+=(S[1+c]**D)>>6;
+ }
+
+ acc=((int64)acc*(65536-(x&65535))+(int64)acc2*(x&65535))>>(16+11);
+ *out=acc;
+ out++;
+ count++;
+ }
+ else
+ for(x=mrindex;x<max;x+=mrratio)
+ {
+ int32 acc=0,acc2=0;
+ unsigned int c;
+ int32 *S,*D;
+
+ for(c=NCOEFFS,S=&in[(x>>16)-NCOEFFS],D=coeffs;c;c--,D++)
+ {
+ acc+=(S[c]**D)>>6;
+ acc2+=(S[1+c]**D)>>6;
+ }
+
+ acc=((int64)acc*(65536-(x&65535))+(int64)acc2*(x&65535))>>(16+11);
+ *out=acc;
+ out++;
+ count++;
+ }
+
+ mrindex=x-max;
+
+ if(FSettings.soundq==2)
+ {
+ mrindex+=SQ2NCOEFFS*65536;
+ *leftover=SQ2NCOEFFS+1;
+ }
+ else
+ {
+ mrindex+=NCOEFFS*65536;
+ *leftover=NCOEFFS+1;
+ }
+
+ if(GameExpSound.NeoFill)
+ GameExpSound.NeoFill(outsave,count);
+
+ SexyFilter(outsave,outsave,count);
+ if(FSettings.lowpass)
+ SexyFilter2(outsave,count);
+ return(count);
+}
+
+void MakeFilters(int32 rate)
+{
+ int32 *tabs[6]={C44100NTSC,C44100PAL,C48000NTSC,C48000PAL,C96000NTSC,
+ C96000PAL};
+ int32 *sq2tabs[6]={SQ2C44100NTSC,SQ2C44100PAL,SQ2C48000NTSC,SQ2C48000PAL,
+ SQ2C96000NTSC,SQ2C96000PAL};
+
+ int32 *tmp;
+ int32 x;
+ uint32 nco;
+
+ if(FSettings.soundq==2)
+ nco=SQ2NCOEFFS;
+ else
+ nco=NCOEFFS;
+
+ mrindex=(nco+1)<<16;
+ mrratio=(PAL?(int64)(PAL_CPU*65536):(int64)(NTSC_CPU*65536))/rate;
+
+ if(FSettings.soundq==2)
+ tmp=sq2tabs[(PAL?1:0)|(rate==48000?2:0)|(rate==96000?4:0)];
+ else
+ tmp=tabs[(PAL?1:0)|(rate==48000?2:0)|(rate==96000?4:0)];
+
+ if(FSettings.soundq==2)
+ for(x=0;x<SQ2NCOEFFS>>1;x++)
+ sq2coeffs[x]=sq2coeffs[SQ2NCOEFFS-1-x]=tmp[x];
+ else
+ for(x=0;x<NCOEFFS>>1;x++)
+ coeffs[x]=coeffs[NCOEFFS-1-x]=tmp[x];
+
+ #ifdef MOO
+ /* Some tests involving precision and error. */
+ {
+ static int64 acc=0;
+ int x;
+ for(x=0;x<SQ2NCOEFFS;x++)
+ acc+=(int64)32767*sq2coeffs[x];
+ printf("Foo: %lld\n",acc);
+ }
+ #endif
+}
diff --git a/filter.h b/filter.h
new file mode 100644
index 00000000..9a025187
--- /dev/null
+++ b/filter.h
@@ -0,0 +1,3 @@
+int32 NeoFilterSound(int32 *in, int32 *out, uint32 inlen, int32 *leftover);
+void MakeFilters(int32 rate);
+void SexyFilter(int32 *in, int32 *out, int32 count);
diff --git a/fir/c44100ntsc.coef b/fir/c44100ntsc.coef
new file mode 100644
index 00000000..f04fdf4d
--- /dev/null
+++ b/fir/c44100ntsc.coef
@@ -0,0 +1,1039 @@
+;; ***** 44100 NTSC *****
+;; Filter length: 1024
+;; Symmetry: cosine
+;; Sampling frequency: 1789772.72727273
+;; Grid density: 10257
+;; Deviation parameter: y=-4.26609210258497e-4
+;;
+;; Specifications:
+;; (limit > 22050 894886.363636 0 0.5)
+;; (limit < 22050 894886.363636 0 0.5)
+;; (limit > 0 15000 1 1)
+;; (limit < 0 15000 1 1)
+;;
+;; Coefficients:
+
+1.11262153794412e-4
+9.1203952189514e-6
+9.4094541490789e-6
+9.63661279581735e-6
+9.84815294136282e-6
+9.96211856753532e-6
+1.00189663896491e-5
+1.00061013360251e-5
+9.93435399969655e-6
+9.78762126385669e-6
+9.55321925729624e-6
+9.24825080375786e-6
+8.85255837386989e-6
+8.3877114761375e-6
+7.82178714333584e-6
+7.1788229094432e-6
+6.44522053069757e-6
+5.62630847050353e-6
+4.71582963040218e-6
+3.72380169562418e-6
+2.64841660044426e-6
+1.49502905722044e-6
+2.5217761121751e-7
+-1.05186474836932e-6
+-2.43551352329469e-6
+-3.89295417250434e-6
+-5.42664110084146e-6
+-7.00566917418741e-6
+-8.6368208569906e-6
+-1.03114527925382e-5
+-1.20443408108932e-5
+-1.38216102337816e-5
+-1.56130215867248e-5
+-1.74276497066345e-5
+-1.9254250127445e-5
+-2.1098626694142e-5
+-2.29097403788758e-5
+-2.47248863743773e-5
+-2.64998143086568e-5
+-2.82478400091917e-5
+-2.99318307877882e-5
+-3.15778370419873e-5
+-3.31419021725666e-5
+-3.46367208626458e-5
+-3.60349486303977e-5
+-3.73560747385557e-5
+-3.85602232740176e-5
+-3.96502202312979e-5
+-4.06110449657408e-5
+-4.14368419481133e-5
+-4.21090019281467e-5
+-4.25993967830844e-5
+-4.29068991904435e-5
+-4.3025032131568e-5
+-4.30140517026991e-5
+-4.28433545718674e-5
+-4.25296899490834e-5
+-4.17374194914376e-5
+-4.10040920794666e-5
+-3.99666912810865e-5
+-3.87371755083029e-5
+-3.72607458775728e-5
+-3.55874669626075e-5
+-3.36986152823895e-5
+-3.16000530912765e-5
+-2.92767128040033e-5
+-2.67371187168457e-5
+-2.40039338911553e-5
+-2.10604880457374e-5
+-1.79335828101573e-5
+-1.46133694055927e-5
+-1.11253968130194e-5
+-7.46614405238464e-6
+-3.64613498607798e-6
+3.02368354254293e-7
+4.39158630158039e-6
+8.58777072285901e-6
+1.28879143039278e-5
+1.72582028358521e-5
+2.16969577994228e-5
+2.61829629831333e-5
+3.06979810398452e-5
+3.52209058193995e-5
+3.97300635833027e-5
+4.42050962120303e-5
+4.86055004649174e-5
+5.29441057028915e-5
+5.71712798076152e-5
+6.1268495205598e-5
+6.52195501855984e-5
+6.90007266683825e-5
+7.25913577445526e-5
+7.59499489511726e-5
+7.90918784345419e-5
+8.19505156283039e-5
+8.45470657873134e-5
+8.68293263041973e-5
+8.88086064198062e-5
+9.041692946077e-5
+9.16797599287126e-5
+9.25599457920887e-5
+9.30552765000977e-5
+9.31313982341795e-5
+9.27936061980597e-5
+9.20420846305276e-5
+9.08521132221629e-5
+8.92085476183645e-5
+8.71017975335516e-5
+8.45414314948811e-5
+8.15311641149105e-5
+7.80711279919507e-5
+7.41574998124299e-5
+6.97895128455476e-5
+6.4947479038247e-5
+5.97479711603871e-5
+5.40630354898453e-5
+4.79856481353068e-5
+4.15182368501593e-5
+3.46802768321681e-5
+2.74958585451822e-5
+1.9976788603383e-5
+1.21472923550567e-5
+4.04120472382678e-6
+-4.30770705476995e-6
+-1.28821872779466e-5
+-2.16320221744917e-5
+-3.05324054839951e-5
+-3.95504446928096e-5
+-4.86452773517834e-5
+-5.7776933929632e-5
+-6.6888917187142e-5
+-7.59839395688362e-5
+-8.49770646155345e-5
+-9.38485765943731e-5
+-1.02535728955288e-4
+-1.11020769697226e-4
+-1.19224175025087e-4
+-1.2712371399013e-4
+-1.34677854331765e-4
+-1.41855973321246e-4
+-1.48585528294192e-4
+-1.54823475008983e-4
+-1.60563784962364e-4
+-1.65737939175439e-4
+-1.70324767136095e-4
+-1.74273576399229e-4
+-1.77562540511869e-4
+-1.80153948404509e-4
+-1.82017783412252e-4
+-1.83125404333719e-4
+-1.83446338947795e-4
+-1.82987530180017e-4
+-1.81703356594349e-4
+-1.79590850554495e-4
+-1.76619461091599e-4
+-1.72815899566497e-4
+-1.68147649678904e-4
+-1.62620596029299e-4
+-1.56237231040979e-4
+-1.49008305143425e-4
+-1.40957023196796e-4
+-1.32072008950485e-4
+-1.22389162483219e-4
+-1.11934088499394e-4
+-1.00737065257502e-4
+-8.88160519212646e-5
+-7.61930807071772e-5
+-6.29496222727675e-5
+-4.91050367300618e-5
+-3.4718130025881e-5
+-1.98160195514693e-5
+-4.45731586994588e-6
+1.12803144028591e-5
+2.73309987906755e-5
+4.36737905686176e-5
+6.01909058617092e-5
+7.68545149813897e-5
+9.35675866162103e-5
+1.10269459400764e-4
+1.26883165335663e-4
+1.43335855360237e-4
+1.5954241113618e-4
+1.7543332757703e-4
+1.90940022499485e-4
+2.05960757764001e-4
+2.20430019515099e-4
+2.34260760602835e-4
+2.47409140535342e-4
+2.59761075613858e-4
+2.71275815558309e-4
+2.81867857874407e-4
+2.91473514559014e-4
+3.00005851286105e-4
+3.07432616093836e-4
+3.136935557549e-4
+3.18736128450691e-4
+3.22478991985463e-4
+3.24900573947518e-4
+3.25973108476246e-4
+3.25641186246162e-4
+3.23884645760423e-4
+3.20666060011718e-4
+3.15989435094453e-4
+3.09830843773395e-4
+3.02185552345498e-4
+2.93038759521248e-4
+2.82430889955413e-4
+2.70353445973182e-4
+2.56830966886862e-4
+2.41887536833496e-4
+2.25571633496883e-4
+2.07916002422089e-4
+1.88968510710595e-4
+1.68789504787793e-4
+1.47443939450696e-4
+1.24981317138686e-4
+1.01499245340524e-4
+7.70572862247137e-5
+5.17676358522932e-5
+2.57118134228229e-5
+-1.01754062817161e-6
+-2.83262175890525e-5
+-5.60999252995387e-5
+-8.41915010649744e-5
+-1.1252906652508e-4
+-1.40975352908305e-4
+-1.69434579431538e-4
+-1.97729073916177e-4
+-2.25769653344743e-4
+-2.53411042361576e-4
+-2.80565122507133e-4
+-3.07036438304828e-4
+-3.32753626249541e-4
+-3.57541896186656e-4
+-3.81307666526521e-4
+-4.0391150118367e-4
+-4.25231243203619e-4
+-4.45145780258752e-4
+-4.63545025829737e-4
+-4.80322675164487e-4
+-4.95350782085733e-4
+-5.08549438324035e-4
+-5.1980265947403e-4
+-5.29043766376402e-4
+-5.36172525139055e-4
+-5.41133538554177e-4
+-5.43848643414634e-4
+-5.44256723291212e-4
+-5.42320002202435e-4
+-5.37993404337165e-4
+-5.3125334500245e-4
+-5.22075219690071e-4
+-5.10445445493085e-4
+-4.96377734888716e-4
+-4.79880717778625e-4
+-4.60971283056312e-4
+-4.39684651488982e-4
+-4.16063905823169e-4
+-3.90177619816529e-4
+-3.62085220183381e-4
+-3.31863091675268e-4
+-2.99597107541406e-4
+-2.65413754083361e-4
+-2.29377222808396e-4
+-1.91654451928034e-4
+-1.52344557932817e-4
+-1.11608104095083e-4
+-6.95603957788035e-5
+-2.64016442748731e-5
+1.7724163386627e-5
+6.26416184275484e-5
+1.08189979248416e-4
+1.54147272535691e-4
+2.00349856093844e-4
+2.46587459314576e-4
+2.92670674130578e-4
+3.38391411475662e-4
+3.83540211401206e-4
+4.27913576964888e-4
+4.71300626361147e-4
+5.13512876149826e-4
+5.54323952929787e-4
+5.93537470537219e-4
+6.3093434662098e-4
+6.66344965329304e-4
+6.99565407441501e-4
+7.30423799872388e-4
+7.58708693685015e-4
+7.8427979033147e-4
+8.06945553271288e-4
+8.26584756687851e-4
+8.43031977801634e-4
+8.56156258972257e-4
+8.65836592594565e-4
+8.71968746552343e-4
+8.74461813660048e-4
+8.73231202274345e-4
+8.68218292668308e-4
+8.59348624025311e-4
+8.46612447774565e-4
+8.29979222422541e-4
+8.09446427744043e-4
+7.85031357561925e-4
+7.56766215319943e-4
+7.2470699047867e-4
+6.88883919685657e-4
+6.49416331024001e-4
+6.06391057283913e-4
+5.59935330476022e-4
+5.10167371200662e-4
+4.57252072332643e-4
+4.01354265598951e-4
+3.42656496994208e-4
+2.81355941136781e-4
+2.17670656870967e-4
+1.51832975264559e-4
+8.40749859869234e-5
+1.46584064604961e-5
+-5.61496056174954e-5
+-1.28086904625854e-4
+-2.00818433548331e-4
+-2.7409972137809e-4
+-3.47601002332966e-4
+-4.21031974632111e-4
+-4.94030730396776e-4
+-5.66317666429227e-4
+-6.37548654873925e-4
+-7.07408810891205e-4
+-7.75547530396904e-4
+-8.41675004612485e-4
+-9.05453133996662e-4
+-9.66558548716224e-4
+-0.00102466993047469
+-0.00107948243327616
+-0.00113072204795905
+-0.0011780892664915
+-0.0012212925453813
+-0.00126007236261203
+-0.00129417936102408
+-0.00132338623135961
+-0.0013474534440369
+-0.0013662023453885
+-0.00137942837511788
+-0.00138698055366682
+-0.00138870045367779
+-0.00138448957970039
+-0.00137424428374859
+-0.00135788629777192
+-0.00133536298920924
+-0.00130665165054127
+-0.0012717543272168
+-0.00123070624585239
+-0.00118356717926831
+-0.00113040319129687
+-0.00107131700797982
+-0.00100646498239645
+-9.35995104217189e-4
+-8.60096571782921e-4
+-7.78998336060133e-4
+-6.92940701872996e-4
+-6.02182768095548e-4
+-5.07003036815179e-4
+-4.07757323218773e-4
+-3.04760010372766e-4
+-1.98383609989422e-4
+-8.89918915329279e-5
+2.29793702787778e-5
+1.37122990345803e-4
+2.5299360795038e-4
+3.70143341115017e-4
+4.88088953030987e-4
+6.06342750948422e-4
+7.24424959757904e-4
+8.41821410938308e-4
+9.58029848643689e-4
+0.00107251650886565
+0.00118475391682864
+0.00129425308462396
+0.00140047084052004
+0.0015028980384223
+0.00160100966703419
+0.00169431442637767
+0.00178229788006395
+0.00186449094208792
+0.00194041558775561
+0.00200963542959276
+0.00207169741768017
+0.00212618334414435
+0.00217270035390745
+0.00221088750080458
+0.00224042087255895
+0.00226095514052231
+0.00227220321739892
+0.00227394132978118
+0.00226594070088644
+0.00224802424476919
+0.00222001601735845
+0.00218185426405224
+0.00213342446297001
+0.00207473710872034
+0.00200576081219353
+0.00192660143920357
+0.00183730661827725
+0.00173804987265467
+0.00162899296733253
+0.00151036806619154
+0.00138244091224245
+0.00124553715590493
+0.00110001314361977
+9.46246978211101e-4
+7.84695240224382e-4
+6.15844939874971e-4
+4.4020774824205e-4
+2.58345305088762e-4
+7.08612579074651e-5
+-1.21606350631308e-4
+-3.18395388345862e-4
+-5.1879155790156e-4
+-7.22062937747848e-4
+-9.27451114779463e-4
+-0.00113416157741747
+-0.00134138689888361
+-0.00154827070291184
+-0.00175397288566918
+-0.0019576116273234
+-0.00215831253617746
+-0.00235515587055034
+-0.00254724254904768
+-0.00273366690374425
+-0.00291350898429464
+-0.00308585950693817
+-0.00324979222163811
+-0.00340441875730436
+-0.00354884211798964
+-0.00368218571253443
+-0.00380358990740782
+-0.00391221887526166
+-0.00400723057140825
+-0.00408785624750138
+-0.004153333003793
+-0.00420292395555919
+-0.00423593387073267
+-0.00425171118587346
+-0.00424964450870412
+-0.00422915907860119
+-0.0041897356858097
+-0.0041309026307971
+-0.00405221509383098
+-0.00395331866912401
+-0.00383391116350846
+-0.00369371631770201
+-0.00353253640058538
+-0.00335022403053123
+-0.00314672640265953
+-0.00292200117900966
+-0.00267612720029126
+-0.0024091787521236
+-0.00212137053496313
+-0.00181290180786275
+-0.00148412961640828
+-0.0011353892343628
+-7.67128314412436e-4
+-3.79839813513112e-4
+2.59043686551276e-5
+4.494860301294e-4
+8.90225310173371e-4
+0.00134736056332534
+0.00182009665332689
+0.00230757943767435
+0.00280890399487952
+0.00332310364103925
+0.00384915066180797
+0.00438599870804931
+0.00493254091385408
+0.00548765927782258
+0.00605013603781409
+0.00661878037036735
+0.00719234109024943
+0.00776954418385769
+0.008349090387754
+0.0089296683452915
+0.00950994984323646
+0.0100885721308606
+0.0106641926633217
+0.0112354494946774
+0.0118009885819235
+0.0123594520486416
+0.0129094923924999
+0.0134497740224004
+0.0139789646616159
+0.0144957819012448
+0.0149989403071262
+0.0154871953429542
+0.0159593047296737
+0.0164141332589184
+0.0168504983748113
+0.0172673032190162
+0.0176634911539869
+0.0180380745830505
+0.018390088086466
+0.0187186209562544
+0.0190228378422047
+0.0193019578242075
+0.0195552647135139
+0.0197821099505764
+0.0199819035649561
+0.0201541247940216
+0.0202983267902526
+0.0204141411144792
+0.0205012617098339
+0.0205594794331608
+0.0205886274212954
+0.0205886274212954
+0.0205594794331608
+0.0205012617098339
+0.0204141411144792
+0.0202983267902526
+0.0201541247940216
+0.0199819035649561
+0.0197821099505764
+0.0195552647135139
+0.0193019578242075
+0.0190228378422047
+0.0187186209562544
+0.018390088086466
+0.0180380745830505
+0.0176634911539869
+0.0172673032190162
+0.0168504983748113
+0.0164141332589184
+0.0159593047296737
+0.0154871953429542
+0.0149989403071262
+0.0144957819012448
+0.0139789646616159
+0.0134497740224004
+0.0129094923924999
+0.0123594520486416
+0.0118009885819235
+0.0112354494946774
+0.0106641926633217
+0.0100885721308606
+0.00950994984323646
+0.0089296683452915
+0.008349090387754
+0.00776954418385769
+0.00719234109024943
+0.00661878037036735
+0.00605013603781409
+0.00548765927782258
+0.00493254091385408
+0.00438599870804931
+0.00384915066180797
+0.00332310364103925
+0.00280890399487952
+0.00230757943767435
+0.00182009665332689
+0.00134736056332534
+8.90225310173371e-4
+4.494860301294e-4
+2.59043686551276e-5
+-3.79839813513112e-4
+-7.67128314412436e-4
+-0.0011353892343628
+-0.00148412961640828
+-0.00181290180786275
+-0.00212137053496313
+-0.0024091787521236
+-0.00267612720029126
+-0.00292200117900966
+-0.00314672640265953
+-0.00335022403053123
+-0.00353253640058538
+-0.00369371631770201
+-0.00383391116350846
+-0.00395331866912401
+-0.00405221509383098
+-0.0041309026307971
+-0.0041897356858097
+-0.00422915907860119
+-0.00424964450870412
+-0.00425171118587346
+-0.00423593387073267
+-0.00420292395555919
+-0.004153333003793
+-0.00408785624750138
+-0.00400723057140825
+-0.00391221887526166
+-0.00380358990740782
+-0.00368218571253443
+-0.00354884211798964
+-0.00340441875730436
+-0.00324979222163811
+-0.00308585950693817
+-0.00291350898429464
+-0.00273366690374425
+-0.00254724254904768
+-0.00235515587055034
+-0.00215831253617746
+-0.0019576116273234
+-0.00175397288566918
+-0.00154827070291184
+-0.00134138689888361
+-0.00113416157741747
+-9.27451114779463e-4
+-7.22062937747848e-4
+-5.1879155790156e-4
+-3.18395388345862e-4
+-1.21606350631308e-4
+7.08612579074651e-5
+2.58345305088762e-4
+4.4020774824205e-4
+6.15844939874971e-4
+7.84695240224382e-4
+9.46246978211101e-4
+0.00110001314361977
+0.00124553715590493
+0.00138244091224245
+0.00151036806619154
+0.00162899296733253
+0.00173804987265467
+0.00183730661827725
+0.00192660143920357
+0.00200576081219353
+0.00207473710872034
+0.00213342446297001
+0.00218185426405224
+0.00222001601735845
+0.00224802424476919
+0.00226594070088644
+0.00227394132978118
+0.00227220321739892
+0.00226095514052231
+0.00224042087255895
+0.00221088750080458
+0.00217270035390745
+0.00212618334414435
+0.00207169741768017
+0.00200963542959276
+0.00194041558775561
+0.00186449094208792
+0.00178229788006395
+0.00169431442637767
+0.00160100966703419
+0.0015028980384223
+0.00140047084052004
+0.00129425308462396
+0.00118475391682864
+0.00107251650886565
+9.58029848643689e-4
+8.41821410938308e-4
+7.24424959757904e-4
+6.06342750948422e-4
+4.88088953030987e-4
+3.70143341115017e-4
+2.5299360795038e-4
+1.37122990345803e-4
+2.29793702787778e-5
+-8.89918915329279e-5
+-1.98383609989422e-4
+-3.04760010372766e-4
+-4.07757323218773e-4
+-5.07003036815179e-4
+-6.02182768095548e-4
+-6.92940701872996e-4
+-7.78998336060133e-4
+-8.60096571782921e-4
+-9.35995104217189e-4
+-0.00100646498239645
+-0.00107131700797982
+-0.00113040319129687
+-0.00118356717926831
+-0.00123070624585239
+-0.0012717543272168
+-0.00130665165054127
+-0.00133536298920924
+-0.00135788629777192
+-0.00137424428374859
+-0.00138448957970039
+-0.00138870045367779
+-0.00138698055366682
+-0.00137942837511788
+-0.0013662023453885
+-0.0013474534440369
+-0.00132338623135961
+-0.00129417936102408
+-0.00126007236261203
+-0.0012212925453813
+-0.0011780892664915
+-0.00113072204795905
+-0.00107948243327616
+-0.00102466993047469
+-9.66558548716224e-4
+-9.05453133996662e-4
+-8.41675004612485e-4
+-7.75547530396904e-4
+-7.07408810891205e-4
+-6.37548654873925e-4
+-5.66317666429227e-4
+-4.94030730396776e-4
+-4.21031974632111e-4
+-3.47601002332966e-4
+-2.7409972137809e-4
+-2.00818433548331e-4
+-1.28086904625854e-4
+-5.61496056174954e-5
+1.46584064604961e-5
+8.40749859869234e-5
+1.51832975264559e-4
+2.17670656870967e-4
+2.81355941136781e-4
+3.42656496994208e-4
+4.01354265598951e-4
+4.57252072332643e-4
+5.10167371200662e-4
+5.59935330476022e-4
+6.06391057283913e-4
+6.49416331024001e-4
+6.88883919685657e-4
+7.2470699047867e-4
+7.56766215319943e-4
+7.85031357561925e-4
+8.09446427744043e-4
+8.29979222422541e-4
+8.46612447774565e-4
+8.59348624025311e-4
+8.68218292668308e-4
+8.73231202274345e-4
+8.74461813660048e-4
+8.71968746552343e-4
+8.65836592594565e-4
+8.56156258972257e-4
+8.43031977801634e-4
+8.26584756687851e-4
+8.06945553271288e-4
+7.8427979033147e-4
+7.58708693685015e-4
+7.30423799872388e-4
+6.99565407441501e-4
+6.66344965329304e-4
+6.3093434662098e-4
+5.93537470537219e-4
+5.54323952929787e-4
+5.13512876149826e-4
+4.71300626361147e-4
+4.27913576964888e-4
+3.83540211401206e-4
+3.38391411475662e-4
+2.92670674130578e-4
+2.46587459314576e-4
+2.00349856093844e-4
+1.54147272535691e-4
+1.08189979248416e-4
+6.26416184275484e-5
+1.7724163386627e-5
+-2.64016442748731e-5
+-6.95603957788035e-5
+-1.11608104095083e-4
+-1.52344557932817e-4
+-1.91654451928034e-4
+-2.29377222808396e-4
+-2.65413754083361e-4
+-2.99597107541406e-4
+-3.31863091675268e-4
+-3.62085220183381e-4
+-3.90177619816529e-4
+-4.16063905823169e-4
+-4.39684651488982e-4
+-4.60971283056312e-4
+-4.79880717778625e-4
+-4.96377734888716e-4
+-5.10445445493085e-4
+-5.22075219690071e-4
+-5.3125334500245e-4
+-5.37993404337165e-4
+-5.42320002202435e-4
+-5.44256723291212e-4
+-5.43848643414634e-4
+-5.41133538554177e-4
+-5.36172525139055e-4
+-5.29043766376402e-4
+-5.1980265947403e-4
+-5.08549438324035e-4
+-4.95350782085733e-4
+-4.80322675164487e-4
+-4.63545025829737e-4
+-4.45145780258752e-4
+-4.25231243203619e-4
+-4.0391150118367e-4
+-3.81307666526521e-4
+-3.57541896186656e-4
+-3.32753626249541e-4
+-3.07036438304828e-4
+-2.80565122507133e-4
+-2.53411042361576e-4
+-2.25769653344743e-4
+-1.97729073916177e-4
+-1.69434579431538e-4
+-1.40975352908305e-4
+-1.1252906652508e-4
+-8.41915010649744e-5
+-5.60999252995387e-5
+-2.83262175890525e-5
+-1.01754062817161e-6
+2.57118134228229e-5
+5.17676358522932e-5
+7.70572862247137e-5
+1.01499245340524e-4
+1.24981317138686e-4
+1.47443939450696e-4
+1.68789504787793e-4
+1.88968510710595e-4
+2.07916002422089e-4
+2.25571633496883e-4
+2.41887536833496e-4
+2.56830966886862e-4
+2.70353445973182e-4
+2.82430889955413e-4
+2.93038759521248e-4
+3.02185552345498e-4
+3.09830843773395e-4
+3.15989435094453e-4
+3.20666060011718e-4
+3.23884645760423e-4
+3.25641186246162e-4
+3.25973108476246e-4
+3.24900573947518e-4
+3.22478991985463e-4
+3.18736128450691e-4
+3.136935557549e-4
+3.07432616093836e-4
+3.00005851286105e-4
+2.91473514559014e-4
+2.81867857874407e-4
+2.71275815558309e-4
+2.59761075613858e-4
+2.47409140535342e-4
+2.34260760602835e-4
+2.20430019515099e-4
+2.05960757764001e-4
+1.90940022499485e-4
+1.7543332757703e-4
+1.5954241113618e-4
+1.43335855360237e-4
+1.26883165335663e-4
+1.10269459400764e-4
+9.35675866162103e-5
+7.68545149813897e-5
+6.01909058617092e-5
+4.36737905686176e-5
+2.73309987906755e-5
+1.12803144028591e-5
+-4.45731586994588e-6
+-1.98160195514693e-5
+-3.4718130025881e-5
+-4.91050367300618e-5
+-6.29496222727675e-5
+-7.61930807071772e-5
+-8.88160519212646e-5
+-1.00737065257502e-4
+-1.11934088499394e-4
+-1.22389162483219e-4
+-1.32072008950485e-4
+-1.40957023196796e-4
+-1.49008305143425e-4
+-1.56237231040979e-4
+-1.62620596029299e-4
+-1.68147649678904e-4
+-1.72815899566497e-4
+-1.76619461091599e-4
+-1.79590850554495e-4
+-1.81703356594349e-4
+-1.82987530180017e-4
+-1.83446338947795e-4
+-1.83125404333719e-4
+-1.82017783412252e-4
+-1.80153948404509e-4
+-1.77562540511869e-4
+-1.74273576399229e-4
+-1.70324767136095e-4
+-1.65737939175439e-4
+-1.60563784962364e-4
+-1.54823475008983e-4
+-1.48585528294192e-4
+-1.41855973321246e-4
+-1.34677854331765e-4
+-1.2712371399013e-4
+-1.19224175025087e-4
+-1.11020769697226e-4
+-1.02535728955288e-4
+-9.38485765943731e-5
+-8.49770646155345e-5
+-7.59839395688362e-5
+-6.6888917187142e-5
+-5.7776933929632e-5
+-4.86452773517834e-5
+-3.95504446928096e-5
+-3.05324054839951e-5
+-2.16320221744917e-5
+-1.28821872779466e-5
+-4.30770705476995e-6
+4.04120472382678e-6
+1.21472923550567e-5
+1.9976788603383e-5
+2.74958585451822e-5
+3.46802768321681e-5
+4.15182368501593e-5
+4.79856481353068e-5
+5.40630354898453e-5
+5.97479711603871e-5
+6.4947479038247e-5
+6.97895128455476e-5
+7.41574998124299e-5
+7.80711279919507e-5
+8.15311641149105e-5
+8.45414314948811e-5
+8.71017975335516e-5
+8.92085476183645e-5
+9.08521132221629e-5
+9.20420846305276e-5
+9.27936061980597e-5
+9.31313982341795e-5
+9.30552765000977e-5
+9.25599457920887e-5
+9.16797599287126e-5
+9.041692946077e-5
+8.88086064198062e-5
+8.68293263041973e-5
+8.45470657873134e-5
+8.19505156283039e-5
+7.90918784345419e-5
+7.59499489511726e-5
+7.25913577445526e-5
+6.90007266683825e-5
+6.52195501855984e-5
+6.1268495205598e-5
+5.71712798076152e-5
+5.29441057028915e-5
+4.86055004649174e-5
+4.42050962120303e-5
+3.97300635833027e-5
+3.52209058193995e-5
+3.06979810398452e-5
+2.61829629831333e-5
+2.16969577994228e-5
+1.72582028358521e-5
+1.28879143039278e-5
+8.58777072285901e-6
+4.39158630158039e-6
+3.02368354254293e-7
+-3.64613498607798e-6
+-7.46614405238464e-6
+-1.11253968130194e-5
+-1.46133694055927e-5
+-1.79335828101573e-5
+-2.10604880457374e-5
+-2.40039338911553e-5
+-2.67371187168457e-5
+-2.92767128040033e-5
+-3.16000530912765e-5
+-3.36986152823895e-5
+-3.55874669626075e-5
+-3.72607458775728e-5
+-3.87371755083029e-5
+-3.99666912810865e-5
+-4.10040920794666e-5
+-4.17374194914376e-5
+-4.25296899490834e-5
+-4.28433545718674e-5
+-4.30140517026991e-5
+-4.3025032131568e-5
+-4.29068991904435e-5
+-4.25993967830844e-5
+-4.21090019281467e-5
+-4.14368419481133e-5
+-4.06110449657408e-5
+-3.96502202312979e-5
+-3.85602232740176e-5
+-3.73560747385557e-5
+-3.60349486303977e-5
+-3.46367208626458e-5
+-3.31419021725666e-5
+-3.15778370419873e-5
+-2.99318307877882e-5
+-2.82478400091917e-5
+-2.64998143086568e-5
+-2.47248863743773e-5
+-2.29097403788758e-5
+-2.1098626694142e-5
+-1.9254250127445e-5
+-1.74276497066345e-5
+-1.56130215867248e-5
+-1.38216102337816e-5
+-1.20443408108932e-5
+-1.03114527925382e-5
+-8.6368208569906e-6
+-7.00566917418741e-6
+-5.42664110084146e-6
+-3.89295417250434e-6
+-2.43551352329469e-6
+-1.05186474836932e-6
+2.5217761121751e-7
+1.49502905722044e-6
+2.64841660044426e-6
+3.72380169562418e-6
+4.71582963040218e-6
+5.62630847050353e-6
+6.44522053069757e-6
+7.1788229094432e-6
+7.82178714333584e-6
+8.3877114761375e-6
+8.85255837386989e-6
+9.24825080375786e-6
+9.55321925729624e-6
+9.78762126385669e-6
+9.93435399969655e-6
+1.00061013360251e-5
+1.00189663896491e-5
+9.96211856753532e-6
+9.84815294136282e-6
+9.63661279581735e-6
+9.4094541490789e-6
+9.1203952189514e-6
+1.11262153794412e-4
diff --git a/fir/c44100ntsc.h b/fir/c44100ntsc.h
new file mode 100644
index 00000000..a7e7920d
--- /dev/null
+++ b/fir/c44100ntsc.h
@@ -0,0 +1,512 @@
+116,
+9,
+9,
+10,
+10,
+10,
+10,
+10,
+10,
+10,
+10,
+9,
+9,
+8,
+8,
+7,
+6,
+5,
+4,
+3,
+2,
+1,
+0,
+-1,
+-2,
+-4,
+-5,
+-7,
+-9,
+-10,
+-12,
+-14,
+-16,
+-18,
+-20,
+-22,
+-24,
+-25,
+-27,
+-29,
+-31,
+-33,
+-34,
+-36,
+-37,
+-39,
+-40,
+-41,
+-42,
+-43,
+-44,
+-44,
+-44,
+-45,
+-45,
+-44,
+-44,
+-43,
+-42,
+-41,
+-40,
+-39,
+-37,
+-35,
+-33,
+-30,
+-28,
+-25,
+-22,
+-18,
+-15,
+-11,
+-7,
+-3,
+0,
+4,
+9,
+13,
+18,
+22,
+27,
+32,
+36,
+41,
+46,
+50,
+55,
+59,
+64,
+68,
+72,
+76,
+79,
+82,
+85,
+88,
+91,
+93,
+94,
+96,
+97,
+97,
+97,
+97,
+96,
+95,
+93,
+91,
+88,
+85,
+81,
+77,
+73,
+68,
+62,
+56,
+50,
+43,
+36,
+28,
+20,
+12,
+4,
+-4,
+-13,
+-22,
+-32,
+-41,
+-51,
+-60,
+-70,
+-79,
+-89,
+-98,
+-107,
+-116,
+-125,
+-133,
+-141,
+-148,
+-155,
+-162,
+-168,
+-173,
+-178,
+-182,
+-186,
+-188,
+-190,
+-192,
+-192,
+-191,
+-190,
+-188,
+-185,
+-181,
+-176,
+-170,
+-163,
+-156,
+-147,
+-138,
+-128,
+-117,
+-105,
+-93,
+-79,
+-66,
+-51,
+-36,
+-20,
+-4,
+11,
+28,
+45,
+63,
+80,
+98,
+115,
+133,
+150,
+167,
+183,
+200,
+215,
+231,
+245,
+259,
+272,
+284,
+295,
+305,
+314,
+322,
+328,
+334,
+338,
+340,
+341,
+341,
+339,
+336,
+331,
+324,
+316,
+307,
+296,
+283,
+269,
+253,
+236,
+218,
+198,
+176,
+154,
+131,
+106,
+80,
+54,
+26,
+-1,
+-29,
+-58,
+-88,
+-117,
+-147,
+-177,
+-207,
+-236,
+-265,
+-294,
+-321,
+-348,
+-374,
+-399,
+-423,
+-445,
+-466,
+-486,
+-503,
+-519,
+-533,
+-545,
+-554,
+-562,
+-567,
+-570,
+-570,
+-568,
+-564,
+-557,
+-547,
+-535,
+-520,
+-503,
+-483,
+-461,
+-436,
+-409,
+-379,
+-347,
+-314,
+-278,
+-240,
+-200,
+-159,
+-117,
+-72,
+-27,
+18,
+65,
+113,
+161,
+210,
+258,
+306,
+354,
+402,
+448,
+494,
+538,
+581,
+622,
+661,
+698,
+733,
+765,
+795,
+822,
+846,
+866,
+883,
+897,
+907,
+914,
+916,
+915,
+910,
+901,
+887,
+870,
+848,
+823,
+793,
+759,
+722,
+680,
+635,
+587,
+534,
+479,
+420,
+359,
+295,
+228,
+159,
+88,
+15,
+-58,
+-134,
+-210,
+-287,
+-364,
+-441,
+-518,
+-593,
+-668,
+-741,
+-813,
+-882,
+-949,
+-1013,
+-1074,
+-1131,
+-1185,
+-1235,
+-1280,
+-1321,
+-1357,
+-1387,
+-1412,
+-1432,
+-1446,
+-1454,
+-1456,
+-1451,
+-1440,
+-1423,
+-1400,
+-1370,
+-1333,
+-1290,
+-1241,
+-1185,
+-1123,
+-1055,
+-981,
+-901,
+-816,
+-726,
+-631,
+-531,
+-427,
+-319,
+-208,
+-93,
+24,
+143,
+265,
+388,
+511,
+635,
+759,
+882,
+1004,
+1124,
+1242,
+1357,
+1468,
+1575,
+1678,
+1776,
+1868,
+1955,
+2034,
+2107,
+2172,
+2229,
+2278,
+2318,
+2349,
+2370,
+2382,
+2384,
+2376,
+2357,
+2327,
+2287,
+2237,
+2175,
+2103,
+2020,
+1926,
+1822,
+1708,
+1583,
+1449,
+1306,
+1153,
+992,
+822,
+645,
+461,
+270,
+74,
+-127,
+-333,
+-543,
+-757,
+-972,
+-1189,
+-1406,
+-1623,
+-1839,
+-2052,
+-2263,
+-2469,
+-2670,
+-2866,
+-3055,
+-3235,
+-3407,
+-3569,
+-3721,
+-3861,
+-3988,
+-4102,
+-4201,
+-4286,
+-4355,
+-4407,
+-4441,
+-4458,
+-4456,
+-4434,
+-4393,
+-4331,
+-4249,
+-4145,
+-4020,
+-3873,
+-3704,
+-3512,
+-3299,
+-3063,
+-2806,
+-2526,
+-2224,
+-1900,
+-1556,
+-1190,
+-804,
+-398,
+27,
+471,
+933,
+1412,
+1908,
+2419,
+2945,
+3484,
+4036,
+4599,
+5172,
+5754,
+6344,
+6940,
+7541,
+8146,
+8754,
+9363,
+9971,
+10578,
+11182,
+11781,
+12374,
+12959,
+13536,
+14103,
+14658,
+15199,
+15727,
+16239,
+16734,
+17211,
+17669,
+18106,
+18521,
+18914,
+19283,
+19627,
+19946,
+20239,
+20505,
+20743,
+20952,
+21133,
+21284,
+21405,
+21497,
+21558,
+21588,
diff --git a/fir/c44100ntsc.scm b/fir/c44100ntsc.scm
new file mode 100644
index 00000000..bc66d6b8
--- /dev/null
+++ b/fir/c44100ntsc.scm
@@ -0,0 +1,12 @@
+(title "44100 NTSC")
+
+(verbose #t)
+
+(cosine-symmetry)
+(filter-length 1024)
+(sampling-frequency 1789772.727272727272)
+(limit-= (band 0 15000) 1)
+(limit-= (band 22050 894886.363636) 0 .5)
+(output-file "c44100ntsc.coef")
+(plot-file "c44100ntsc.plot")
+(go)
diff --git a/fir/c44100pal.coef b/fir/c44100pal.coef
new file mode 100644
index 00000000..e46c9a70
--- /dev/null
+++ b/fir/c44100pal.coef
@@ -0,0 +1,1039 @@
+;; ***** 44100 PAL *****
+;; Filter length: 1024
+;; Symmetry: cosine
+;; Sampling frequency: 1662607.125
+;; Grid density: 10257
+;; Deviation parameter: y=-4.28595835756995e-4
+;;
+;; Specifications:
+;; (limit > 22050 831303.5625 0 0.5)
+;; (limit < 22050 831303.5625 0 0.5)
+;; (limit > 0 15500 1 1)
+;; (limit < 0 15500 1 1)
+;;
+;; Coefficients:
+
+-1.11200257011025e-4
+-7.94996380288693e-6
+-8.13285647140816e-6
+-8.24614335450001e-6
+-8.28726470313328e-6
+-8.24897818906316e-6
+-8.13579312269827e-6
+-7.93678154525632e-6
+-7.66363813247865e-6
+-7.28830988147217e-6
+-6.83300292562487e-6
+-6.27926662890536e-6
+-5.63180592699196e-6
+-4.90087590625251e-6
+-4.08336036205811e-6
+-3.16293668294449e-6
+-2.15293957076619e-6
+-1.06608354010604e-6
+1.17779154321068e-7
+1.36339097208028e-6
+2.70697389916737e-6
+4.13545107510629e-6
+5.6127107530343e-6
+7.15216767756425e-6
+8.76565171236067e-6
+1.04110267491666e-5
+1.209928683708e-5
+1.3807553643137e-5
+1.55498084717804e-5
+1.73113519018396e-5
+1.90726123593194e-5
+2.08203230001769e-5
+2.25533698766556e-5
+2.42417431818782e-5
+2.59088069682988e-5
+2.75097685821301e-5
+2.90529184467942e-5
+3.05258134239308e-5
+3.1906749021575e-5
+3.31955898421991e-5
+3.43727119744575e-5
+3.54234983372247e-5
+3.63431784582818e-5
+3.71120880500224e-5
+3.77205312917436e-5
+3.81506665317904e-5
+3.84008667836707e-5
+3.84617902622245e-5
+3.83356611921185e-5
+3.80172027315447e-5
+3.74882685294917e-5
+3.67702946218063e-5
+3.58419705572146e-5
+3.46879785388071e-5
+3.32641657027279e-5
+3.14968254692446e-5
+2.98205583919132e-5
+2.77079444336199e-5
+2.54270156775404e-5
+2.29383213938169e-5
+2.02427147104623e-5
+1.73385589814633e-5
+1.42538741163702e-5
+1.0974704577089e-5
+7.5345671480003e-6
+3.92576081368077e-6
+1.83369853607622e-7
+-3.6781367339795e-6
+-7.66697534902539e-6
+-1.17479928711011e-5
+-1.58899910541553e-5
+-2.00875350281883e-5
+-2.43269194651492e-5
+-2.85687842714339e-5
+-3.28189740432224e-5
+-3.70047365577994e-5
+-4.11243186584193e-5
+-4.51827880544111e-5
+-4.91366464792378e-5
+-5.29228769501386e-5
+-5.6577177841953e-5
+-6.00407527379607e-5
+-6.33015334642338e-5
+-6.6321066975926e-5
+-6.90803733771612e-5
+-7.1551714886712e-5
+-7.37245485134222e-5
+-7.55586426528957e-5
+-7.70803234827881e-5
+-7.81982347188838e-5
+-7.89408927811607e-5
+-7.92941109743888e-5
+-7.92348985225341e-5
+-7.87415759361739e-5
+-7.78153743941276e-5
+-7.64300985875165e-5
+-7.46031420059581e-5
+-7.23191346398865e-5
+-6.95708993868544e-5
+-6.63607831282715e-5
+-6.27086197063989e-5
+-5.86124087120698e-5
+-5.40735813007961e-5
+-4.91146153453121e-5
+-4.37274299935917e-5
+-3.796629483321e-5
+-3.17982121227615e-5
+-2.52841084140995e-5
+-1.84333267027672e-5
+-1.13023888811976e-5
+-3.91269277424297e-6
+3.78856288808815e-6
+1.16356826931571e-5
+1.96757362744974e-5
+2.78537134537647e-5
+3.61195928120633e-5
+4.44322494738248e-5
+5.27623610515163e-5
+6.1053941504231e-5
+6.92572576428739e-5
+7.7331248720778e-5
+8.52344475900456e-5
+9.2926888863339e-5
+1.00334146579291e-4
+1.07431425645115e-4
+1.1416670963617e-4
+1.20489431734329e-4
+1.26354387911283e-4
+1.31720166830177e-4
+1.36538713088326e-4
+1.40793996948262e-4
+1.44431432682464e-4
+1.47393924564116e-4
+1.49667322189054e-4
+1.51240640106038e-4
+1.52049596360267e-4
+1.52081469279039e-4
+1.51330637705528e-4
+1.49757451217301e-4
+1.47362931428648e-4
+1.44140529279305e-4
+1.40080755562269e-4
+1.35181216701032e-4
+1.29425084953382e-4
+1.22873714879804e-4
+1.15510843581741e-4
+1.07326364837661e-4
+9.83786335794599e-5
+8.86945777859818e-5
+7.82876287061222e-5
+6.7224812176488e-5
+5.55089298390305e-5
+4.32026588267973e-5
+3.0365713255082e-5
+1.70475989751417e-5
+3.29372966720524e-6
+-1.08241832988715e-5
+-2.52343906526312e-5
+-3.98841814115523e-5
+-5.46823094969964e-5
+-6.95847998647964e-5
+-8.44762835454931e-5
+-9.93135063167747e-5
+-1.13988295988881e-4
+-1.28441297371119e-4
+-1.4257904039858e-4
+-1.5632814652685e-4
+-1.69596926160502e-4
+-1.82304197147325e-4
+-1.94375475955832e-4
+-2.05729261288574e-4
+-2.16294796061533e-4
+-2.25986416409321e-4
+-2.34733017787645e-4
+-2.42489478192021e-4
+-2.49164314249808e-4
+-2.54710160797573e-4
+-2.59055230879128e-4
+-2.62163331622264e-4
+-2.63980952682017e-4
+-2.64483868515565e-4
+-2.63625449149133e-4
+-2.61381251495432e-4
+-2.57733197100289e-4
+-2.52658112953211e-4
+-2.4615901828968e-4
+-2.38226811903974e-4
+-2.28884870924857e-4
+-2.18140483365099e-4
+-2.06019172507064e-4
+-1.9254469774914e-4
+-1.77785719247505e-4
+-1.61739992805436e-4
+-1.4451846040208e-4
+-1.26149587549934e-4
+-1.06709031104119e-4
+-8.62669952337453e-5
+-6.49336478463108e-5
+-4.27728447441012e-5
+-1.98970247861957e-5
+3.61164973426469e-6
+2.75939454346297e-5
+5.19905050322827e-5
+7.66611814451522e-5
+1.01478414196256e-4
+1.26339943357148e-4
+1.51085348502373e-4
+1.75595678238513e-4
+1.99742079669349e-4
+2.23388522276371e-4
+2.46394584033161e-4
+2.68636208374242e-4
+2.89982341455338e-4
+3.10294458286738e-4
+3.29443424793821e-4
+3.47313309870382e-4
+3.6377364605836e-4
+3.78710912554491e-4
+3.9202650014604e-4
+4.03608977052316e-4
+4.13354985071458e-4
+4.2116122650496e-4
+4.26988609123688e-4
+4.30738794863119e-4
+4.32336229285393e-4
+4.31759427084928e-4
+4.2893275128775e-4
+4.23845616813245e-4
+4.16470263567494e-4
+4.06783273414362e-4
+3.94804321373921e-4
+3.80535441649663e-4
+3.6401636005173e-4
+3.4529014942601e-4
+3.24391189898946e-4
+3.01376781077692e-4
+2.76343301836257e-4
+2.4936486879876e-4
+2.20548944074394e-4
+1.90007301298934e-4
+1.57842659191524e-4
+1.24220152772481e-4
+8.92685161781954e-5
+5.31339845287204e-5
+1.59816963628024e-5
+-2.19908840946184e-5
+-6.06534567846234e-5
+-9.97630661046562e-5
+-1.39179726975758e-4
+-1.78679270880486e-4
+-2.1805919019443e-4
+-2.57108546253423e-4
+-2.95641094902746e-4
+-3.33403666779113e-4
+-3.70254587494631e-4
+-4.05911568827225e-4
+-4.4022838615012e-4
+-4.72955839415529e-4
+-5.0391796703662e-4
+-5.32914238319358e-4
+-5.59744514364898e-4
+-5.84238077102726e-4
+-6.06224526249333e-4
+-6.25539846131288e-4
+-6.42027789895408e-4
+-6.5555230038567e-4
+-6.65977498710118e-4
+-6.7318950015647e-4
+-6.77091605863607e-4
+-6.77614237688126e-4
+-6.74643387824144e-4
+-6.681810692764e-4
+-6.58148553515012e-4
+-6.44548593096861e-4
+-6.27372049258136e-4
+-6.06651646698617e-4
+-5.82419271110313e-4
+-5.54718009495967e-4
+-5.23626832014741e-4
+-4.8926746405434e-4
+-4.51699986733748e-4
+-4.11106675639873e-4
+-3.67606528939805e-4
+-3.21382862239143e-4
+-2.72607382898212e-4
+-2.21497157339506e-4
+-1.68258628656205e-4
+-1.13130227471391e-4
+-5.63383710913267e-5
+1.82703643648985e-6
+6.11059297587035e-5
+1.21227953996855e-4
+1.81881505870662e-4
+2.42786733495668e-4
+3.03615254629841e-4
+3.64050987977855e-4
+4.23804182290753e-4
+4.82537070178806e-4
+5.39916161965727e-4
+5.95641281700095e-4
+6.49402169641121e-4
+7.00854505724994e-4
+7.4971795695236e-4
+7.95682703239628e-4
+8.38445709493196e-4
+8.77748678164893e-4
+9.13311645337574e-4
+9.44886650093644e-4
+9.72247670017337e-4
+9.95115178537146e-4
+0.00101336913401633
+0.00102677501507253
+0.00103518648644738
+0.00103846440012199
+0.00103648919038668
+0.00102917891064352
+0.0010164716114175
+9.98315800820138e-4
+9.74705065755381e-4
+9.45660726451063e-4
+9.11220671795009e-4
+8.71464226265813e-4
+8.26493006790482e-4
+7.76428186484775e-4
+7.2141888229852e-4
+6.61697436756462e-4
+5.9741912245776e-4
+5.28873675826444e-4
+4.56291683005437e-4
+3.79985318339895e-4
+3.00269695262299e-4
+2.17487142122525e-4
+1.31991772965616e-4
+4.41879631490349e-5
+-4.55545140015219e-5
+-1.36775307453412e-4
+-2.29072500656193e-4
+-3.21982815448816e-4
+-4.15050766626564e-4
+-5.0777980705733e-4
+-5.99729527875493e-4
+-6.90384622866925e-4
+-7.79287829793652e-4
+-8.65926265038561e-4
+-9.49836926138828e-4
+-0.00103052577700171
+-0.0011075193071442
+-0.00118036874439703
+-0.00124859930815059
+-0.00131180178646339
+-0.00136953952393335
+-0.00142140513653781
+-0.00146703736814346
+-0.00150608163518545
+-0.00153818964747658
+-0.00156307825078861
+-0.0015804778819231
+-0.0015901634714776
+-0.00159189434514815
+-0.00158555114709596
+-0.00157096689703477
+-0.00154807524691094
+-0.00151680067268875
+-0.00147716260085239
+-0.001429198787489
+-0.00137294453725215
+-0.00130854205285008
+-0.00123616307121754
+-0.00115598693403096
+-0.00106828307283493
+-9.73328815012761e-4
+-8.71455057796053e-4
+-7.63043529919569e-4
+-6.48499103297409e-4
+-5.28275515871108e-4
+-4.02868466889883e-4
+-2.72797605270643e-4
+-1.38620034875188e-4
+-9.39779893315131e-7
+1.39630165237839e-4
+2.8245890419115e-4
+4.26851878411663e-4
+5.72128676056236e-4
+7.17555283175031e-4
+8.62419664123234e-4
+0.00100599136178572
+0.00114749964897685
+0.00128619716461828
+0.00142133896436276
+0.00155215453934691
+0.00167789165485006
+0.00179782254312389
+0.00191119051397053
+0.00201730596666936
+0.00211548603714526
+0.00220503610710518
+0.00228534178059485
+0.00235576204962984
+0.0024157435894097
+0.00246475064259446
+0.0025022831737163
+0.00252789297770596
+0.00254116769788057
+0.00254176992461642
+0.00252938841718385
+0.00250379536745675
+0.00246480413845626
+0.00241227787677937
+0.00234617618821264
+0.00226649941700418
+0.00217330314170672
+0.00206673238197944
+0.00194696407580016
+0.0018143173361094
+0.00166908671482331
+0.00151170100656022
+0.00134262363203965
+0.00116240941365375
+9.71632852686666e-4
+7.70995591058202e-4
+5.61217875060209e-4
+3.43102377440826e-4
+1.17486802048521e-4
+-1.14695107246174e-4
+-3.52499536963163e-4
+-5.9490463003285e-4
+-8.40850949031332e-4
+-0.00108922785396699
+-0.00133888418878215
+-0.00158864742890517
+-0.0018373063114507
+-0.00208361779036314
+-0.0023263150988098
+-0.00256412644472558
+-0.00279574533789046
+-0.00301988207803446
+-0.00323521397538706
+-0.00344046688386521
+-0.00363433985468964
+-0.00381554830386696
+-0.00398282823032301
+-0.0041349694223421
+-0.00427073396319018
+-0.00438896904598832
+-0.00448852839147268
+-0.00456836880890372
+-0.004627400257634
+-0.00466470470414415
+-0.00467932298600597
+-0.00467041907819992
+-0.00463720779225358
+-0.00457898303537998
+-0.00449512222942258
+-0.00438507069238121
+-0.00424834585547379
+-0.00408459615492852
+-0.0038935194962581
+-0.0036749355234766
+-0.00342874251403819
+-0.00315493309153929
+-0.00285361231552705
+-0.00252496859694177
+-0.00216931316953576
+-0.0017870143203001
+-0.00137859287897444
+-9.44633240898953e-4
+-4.85835090373757e-4
+-2.9962514126255e-6
+5.03012372252255e-4
+0.0010312109513981
+0.00158050717151511
+0.00214976554763945
+0.00273772736746413
+0.00334306999099584
+0.0039644076312235
+0.00460023689832775
+0.00524903833016921
+0.00590919805593498
+0.00657904898248033
+0.00725688057525865
+0.00794091363222304
+0.00862934675318832
+0.00932034748070898
+0.0100120457135665
+0.0107025377765967
+0.011389916307798
+0.0120722612532503
+0.0127476582242783
+0.0134141882202367
+0.0140699467449269
+0.0147130285913083
+0.0153416010646532
+0.0159537971993272
+0.0165478416438899
+0.0171219834943615
+0.0176745067361407
+0.018203769229927
+0.0187082111673434
+0.0191862910393147
+0.0196366013582463
+0.0200577339311999
+0.0204484730566774
+0.0208075842002215
+0.021134001566882
+0.0214267119717681
+0.0216848382317027
+0.0219075680887292
+0.022094238422553
+0.0222442604033734
+0.0223571935299417
+0.0224326657161866
+0.0224704675290829
+0.0224704675290829
+0.0224326657161866
+0.0223571935299417
+0.0222442604033734
+0.022094238422553
+0.0219075680887292
+0.0216848382317027
+0.0214267119717681
+0.021134001566882
+0.0208075842002215
+0.0204484730566774
+0.0200577339311999
+0.0196366013582463
+0.0191862910393147
+0.0187082111673434
+0.018203769229927
+0.0176745067361407
+0.0171219834943615
+0.0165478416438899
+0.0159537971993272
+0.0153416010646532
+0.0147130285913083
+0.0140699467449269
+0.0134141882202367
+0.0127476582242783
+0.0120722612532503
+0.011389916307798
+0.0107025377765967
+0.0100120457135665
+0.00932034748070898
+0.00862934675318832
+0.00794091363222304
+0.00725688057525865
+0.00657904898248033
+0.00590919805593498
+0.00524903833016921
+0.00460023689832775
+0.0039644076312235
+0.00334306999099584
+0.00273772736746413
+0.00214976554763945
+0.00158050717151511
+0.0010312109513981
+5.03012372252255e-4
+-2.9962514126255e-6
+-4.85835090373757e-4
+-9.44633240898953e-4
+-0.00137859287897444
+-0.0017870143203001
+-0.00216931316953576
+-0.00252496859694177
+-0.00285361231552705
+-0.00315493309153929
+-0.00342874251403819
+-0.0036749355234766
+-0.0038935194962581
+-0.00408459615492852
+-0.00424834585547379
+-0.00438507069238121
+-0.00449512222942258
+-0.00457898303537998
+-0.00463720779225358
+-0.00467041907819992
+-0.00467932298600597
+-0.00466470470414415
+-0.004627400257634
+-0.00456836880890372
+-0.00448852839147268
+-0.00438896904598832
+-0.00427073396319018
+-0.0041349694223421
+-0.00398282823032301
+-0.00381554830386696
+-0.00363433985468964
+-0.00344046688386521
+-0.00323521397538706
+-0.00301988207803446
+-0.00279574533789046
+-0.00256412644472558
+-0.0023263150988098
+-0.00208361779036314
+-0.0018373063114507
+-0.00158864742890517
+-0.00133888418878215
+-0.00108922785396699
+-8.40850949031332e-4
+-5.9490463003285e-4
+-3.52499536963163e-4
+-1.14695107246174e-4
+1.17486802048521e-4
+3.43102377440826e-4
+5.61217875060209e-4
+7.70995591058202e-4
+9.71632852686666e-4
+0.00116240941365375
+0.00134262363203965
+0.00151170100656022
+0.00166908671482331
+0.0018143173361094
+0.00194696407580016
+0.00206673238197944
+0.00217330314170672
+0.00226649941700418
+0.00234617618821264
+0.00241227787677937
+0.00246480413845626
+0.00250379536745675
+0.00252938841718385
+0.00254176992461642
+0.00254116769788057
+0.00252789297770596
+0.0025022831737163
+0.00246475064259446
+0.0024157435894097
+0.00235576204962984
+0.00228534178059485
+0.00220503610710518
+0.00211548603714526
+0.00201730596666936
+0.00191119051397053
+0.00179782254312389
+0.00167789165485006
+0.00155215453934691
+0.00142133896436276
+0.00128619716461828
+0.00114749964897685
+0.00100599136178572
+8.62419664123234e-4
+7.17555283175031e-4
+5.72128676056236e-4
+4.26851878411663e-4
+2.8245890419115e-4
+1.39630165237839e-4
+-9.39779893315131e-7
+-1.38620034875188e-4
+-2.72797605270643e-4
+-4.02868466889883e-4
+-5.28275515871108e-4
+-6.48499103297409e-4
+-7.63043529919569e-4
+-8.71455057796053e-4
+-9.73328815012761e-4
+-0.00106828307283493
+-0.00115598693403096
+-0.00123616307121754
+-0.00130854205285008
+-0.00137294453725215
+-0.001429198787489
+-0.00147716260085239
+-0.00151680067268875
+-0.00154807524691094
+-0.00157096689703477
+-0.00158555114709596
+-0.00159189434514815
+-0.0015901634714776
+-0.0015804778819231
+-0.00156307825078861
+-0.00153818964747658
+-0.00150608163518545
+-0.00146703736814346
+-0.00142140513653781
+-0.00136953952393335
+-0.00131180178646339
+-0.00124859930815059
+-0.00118036874439703
+-0.0011075193071442
+-0.00103052577700171
+-9.49836926138828e-4
+-8.65926265038561e-4
+-7.79287829793652e-4
+-6.90384622866925e-4
+-5.99729527875493e-4
+-5.0777980705733e-4
+-4.15050766626564e-4
+-3.21982815448816e-4
+-2.29072500656193e-4
+-1.36775307453412e-4
+-4.55545140015219e-5
+4.41879631490349e-5
+1.31991772965616e-4
+2.17487142122525e-4
+3.00269695262299e-4
+3.79985318339895e-4
+4.56291683005437e-4
+5.28873675826444e-4
+5.9741912245776e-4
+6.61697436756462e-4
+7.2141888229852e-4
+7.76428186484775e-4
+8.26493006790482e-4
+8.71464226265813e-4
+9.11220671795009e-4
+9.45660726451063e-4
+9.74705065755381e-4
+9.98315800820138e-4
+0.0010164716114175
+0.00102917891064352
+0.00103648919038668
+0.00103846440012199
+0.00103518648644738
+0.00102677501507253
+0.00101336913401633
+9.95115178537146e-4
+9.72247670017337e-4
+9.44886650093644e-4
+9.13311645337574e-4
+8.77748678164893e-4
+8.38445709493196e-4
+7.95682703239628e-4
+7.4971795695236e-4
+7.00854505724994e-4
+6.49402169641121e-4
+5.95641281700095e-4
+5.39916161965727e-4
+4.82537070178806e-4
+4.23804182290753e-4
+3.64050987977855e-4
+3.03615254629841e-4
+2.42786733495668e-4
+1.81881505870662e-4
+1.21227953996855e-4
+6.11059297587035e-5
+1.82703643648985e-6
+-5.63383710913267e-5
+-1.13130227471391e-4
+-1.68258628656205e-4
+-2.21497157339506e-4
+-2.72607382898212e-4
+-3.21382862239143e-4
+-3.67606528939805e-4
+-4.11106675639873e-4
+-4.51699986733748e-4
+-4.8926746405434e-4
+-5.23626832014741e-4
+-5.54718009495967e-4
+-5.82419271110313e-4
+-6.06651646698617e-4
+-6.27372049258136e-4
+-6.44548593096861e-4
+-6.58148553515012e-4
+-6.681810692764e-4
+-6.74643387824144e-4
+-6.77614237688126e-4
+-6.77091605863607e-4
+-6.7318950015647e-4
+-6.65977498710118e-4
+-6.5555230038567e-4
+-6.42027789895408e-4
+-6.25539846131288e-4
+-6.06224526249333e-4
+-5.84238077102726e-4
+-5.59744514364898e-4
+-5.32914238319358e-4
+-5.0391796703662e-4
+-4.72955839415529e-4
+-4.4022838615012e-4
+-4.05911568827225e-4
+-3.70254587494631e-4
+-3.33403666779113e-4
+-2.95641094902746e-4
+-2.57108546253423e-4
+-2.1805919019443e-4
+-1.78679270880486e-4
+-1.39179726975758e-4
+-9.97630661046562e-5
+-6.06534567846234e-5
+-2.19908840946184e-5
+1.59816963628024e-5
+5.31339845287204e-5
+8.92685161781954e-5
+1.24220152772481e-4
+1.57842659191524e-4
+1.90007301298934e-4
+2.20548944074394e-4
+2.4936486879876e-4
+2.76343301836257e-4
+3.01376781077692e-4
+3.24391189898946e-4
+3.4529014942601e-4
+3.6401636005173e-4
+3.80535441649663e-4
+3.94804321373921e-4
+4.06783273414362e-4
+4.16470263567494e-4
+4.23845616813245e-4
+4.2893275128775e-4
+4.31759427084928e-4
+4.32336229285393e-4
+4.30738794863119e-4
+4.26988609123688e-4
+4.2116122650496e-4
+4.13354985071458e-4
+4.03608977052316e-4
+3.9202650014604e-4
+3.78710912554491e-4
+3.6377364605836e-4
+3.47313309870382e-4
+3.29443424793821e-4
+3.10294458286738e-4
+2.89982341455338e-4
+2.68636208374242e-4
+2.46394584033161e-4
+2.23388522276371e-4
+1.99742079669349e-4
+1.75595678238513e-4
+1.51085348502373e-4
+1.26339943357148e-4
+1.01478414196256e-4
+7.66611814451522e-5
+5.19905050322827e-5
+2.75939454346297e-5
+3.61164973426469e-6
+-1.98970247861957e-5
+-4.27728447441012e-5
+-6.49336478463108e-5
+-8.62669952337453e-5
+-1.06709031104119e-4
+-1.26149587549934e-4
+-1.4451846040208e-4
+-1.61739992805436e-4
+-1.77785719247505e-4
+-1.9254469774914e-4
+-2.06019172507064e-4
+-2.18140483365099e-4
+-2.28884870924857e-4
+-2.38226811903974e-4
+-2.4615901828968e-4
+-2.52658112953211e-4
+-2.57733197100289e-4
+-2.61381251495432e-4
+-2.63625449149133e-4
+-2.64483868515565e-4
+-2.63980952682017e-4
+-2.62163331622264e-4
+-2.59055230879128e-4
+-2.54710160797573e-4
+-2.49164314249808e-4
+-2.42489478192021e-4
+-2.34733017787645e-4
+-2.25986416409321e-4
+-2.16294796061533e-4
+-2.05729261288574e-4
+-1.94375475955832e-4
+-1.82304197147325e-4
+-1.69596926160502e-4
+-1.5632814652685e-4
+-1.4257904039858e-4
+-1.28441297371119e-4
+-1.13988295988881e-4
+-9.93135063167747e-5
+-8.44762835454931e-5
+-6.95847998647964e-5
+-5.46823094969964e-5
+-3.98841814115523e-5
+-2.52343906526312e-5
+-1.08241832988715e-5
+3.29372966720524e-6
+1.70475989751417e-5
+3.0365713255082e-5
+4.32026588267973e-5
+5.55089298390305e-5
+6.7224812176488e-5
+7.82876287061222e-5
+8.86945777859818e-5
+9.83786335794599e-5
+1.07326364837661e-4
+1.15510843581741e-4
+1.22873714879804e-4
+1.29425084953382e-4
+1.35181216701032e-4
+1.40080755562269e-4
+1.44140529279305e-4
+1.47362931428648e-4
+1.49757451217301e-4
+1.51330637705528e-4
+1.52081469279039e-4
+1.52049596360267e-4
+1.51240640106038e-4
+1.49667322189054e-4
+1.47393924564116e-4
+1.44431432682464e-4
+1.40793996948262e-4
+1.36538713088326e-4
+1.31720166830177e-4
+1.26354387911283e-4
+1.20489431734329e-4
+1.1416670963617e-4
+1.07431425645115e-4
+1.00334146579291e-4
+9.2926888863339e-5
+8.52344475900456e-5
+7.7331248720778e-5
+6.92572576428739e-5
+6.1053941504231e-5
+5.27623610515163e-5
+4.44322494738248e-5
+3.61195928120633e-5
+2.78537134537647e-5
+1.96757362744974e-5
+1.16356826931571e-5
+3.78856288808815e-6
+-3.91269277424297e-6
+-1.13023888811976e-5
+-1.84333267027672e-5
+-2.52841084140995e-5
+-3.17982121227615e-5
+-3.796629483321e-5
+-4.37274299935917e-5
+-4.91146153453121e-5
+-5.40735813007961e-5
+-5.86124087120698e-5
+-6.27086197063989e-5
+-6.63607831282715e-5
+-6.95708993868544e-5
+-7.23191346398865e-5
+-7.46031420059581e-5
+-7.64300985875165e-5
+-7.78153743941276e-5
+-7.87415759361739e-5
+-7.92348985225341e-5
+-7.92941109743888e-5
+-7.89408927811607e-5
+-7.81982347188838e-5
+-7.70803234827881e-5
+-7.55586426528957e-5
+-7.37245485134222e-5
+-7.1551714886712e-5
+-6.90803733771612e-5
+-6.6321066975926e-5
+-6.33015334642338e-5
+-6.00407527379607e-5
+-5.6577177841953e-5
+-5.29228769501386e-5
+-4.91366464792378e-5
+-4.51827880544111e-5
+-4.11243186584193e-5
+-3.70047365577994e-5
+-3.28189740432224e-5
+-2.85687842714339e-5
+-2.43269194651492e-5
+-2.00875350281883e-5
+-1.58899910541553e-5
+-1.17479928711011e-5
+-7.66697534902539e-6
+-3.6781367339795e-6
+1.83369853607622e-7
+3.92576081368077e-6
+7.5345671480003e-6
+1.0974704577089e-5
+1.42538741163702e-5
+1.73385589814633e-5
+2.02427147104623e-5
+2.29383213938169e-5
+2.54270156775404e-5
+2.77079444336199e-5
+2.98205583919132e-5
+3.14968254692446e-5
+3.32641657027279e-5
+3.46879785388071e-5
+3.58419705572146e-5
+3.67702946218063e-5
+3.74882685294917e-5
+3.80172027315447e-5
+3.83356611921185e-5
+3.84617902622245e-5
+3.84008667836707e-5
+3.81506665317904e-5
+3.77205312917436e-5
+3.71120880500224e-5
+3.63431784582818e-5
+3.54234983372247e-5
+3.43727119744575e-5
+3.31955898421991e-5
+3.1906749021575e-5
+3.05258134239308e-5
+2.90529184467942e-5
+2.75097685821301e-5
+2.59088069682988e-5
+2.42417431818782e-5
+2.25533698766556e-5
+2.08203230001769e-5
+1.90726123593194e-5
+1.73113519018396e-5
+1.55498084717804e-5
+1.3807553643137e-5
+1.209928683708e-5
+1.04110267491666e-5
+8.76565171236067e-6
+7.15216767756425e-6
+5.6127107530343e-6
+4.13545107510629e-6
+2.70697389916737e-6
+1.36339097208028e-6
+1.17779154321068e-7
+-1.06608354010604e-6
+-2.15293957076619e-6
+-3.16293668294449e-6
+-4.08336036205811e-6
+-4.90087590625251e-6
+-5.63180592699196e-6
+-6.27926662890536e-6
+-6.83300292562487e-6
+-7.28830988147217e-6
+-7.66363813247865e-6
+-7.93678154525632e-6
+-8.13579312269827e-6
+-8.24897818906316e-6
+-8.28726470313328e-6
+-8.24614335450001e-6
+-8.13285647140816e-6
+-7.94996380288693e-6
+-1.11200257011025e-4
diff --git a/fir/c44100pal.h b/fir/c44100pal.h
new file mode 100644
index 00000000..624a4a9f
--- /dev/null
+++ b/fir/c44100pal.h
@@ -0,0 +1,512 @@
+-116,
+-8,
+-8,
+-8,
+-8,
+-8,
+-8,
+-8,
+-8,
+-7,
+-7,
+-6,
+-5,
+-5,
+-4,
+-3,
+-2,
+-1,
+0,
+1,
+2,
+4,
+5,
+7,
+9,
+10,
+12,
+14,
+16,
+18,
+19,
+21,
+23,
+25,
+27,
+28,
+30,
+32,
+33,
+34,
+36,
+37,
+38,
+38,
+39,
+40,
+40,
+40,
+40,
+39,
+39,
+38,
+37,
+36,
+34,
+33,
+31,
+29,
+26,
+24,
+21,
+18,
+14,
+11,
+7,
+4,
+0,
+-3,
+-8,
+-12,
+-16,
+-21,
+-25,
+-29,
+-34,
+-38,
+-43,
+-47,
+-51,
+-55,
+-59,
+-62,
+-66,
+-69,
+-72,
+-75,
+-77,
+-79,
+-80,
+-81,
+-82,
+-83,
+-83,
+-82,
+-81,
+-80,
+-78,
+-75,
+-72,
+-69,
+-65,
+-61,
+-56,
+-51,
+-45,
+-39,
+-33,
+-26,
+-19,
+-11,
+-4,
+3,
+12,
+20,
+29,
+37,
+46,
+55,
+64,
+72,
+81,
+89,
+97,
+105,
+112,
+119,
+126,
+132,
+138,
+143,
+147,
+151,
+154,
+156,
+158,
+159,
+159,
+158,
+157,
+154,
+151,
+146,
+141,
+135,
+128,
+121,
+112,
+103,
+93,
+82,
+70,
+58,
+45,
+31,
+17,
+3,
+-11,
+-26,
+-41,
+-57,
+-72,
+-88,
+-104,
+-119,
+-134,
+-149,
+-163,
+-177,
+-191,
+-203,
+-215,
+-226,
+-236,
+-246,
+-254,
+-261,
+-267,
+-271,
+-274,
+-276,
+-277,
+-276,
+-274,
+-270,
+-264,
+-258,
+-249,
+-240,
+-228,
+-216,
+-201,
+-186,
+-169,
+-151,
+-132,
+-111,
+-90,
+-68,
+-44,
+-20,
+3,
+28,
+54,
+80,
+106,
+132,
+158,
+184,
+209,
+234,
+258,
+281,
+304,
+325,
+345,
+364,
+381,
+397,
+411,
+423,
+433,
+441,
+447,
+451,
+453,
+452,
+449,
+444,
+436,
+426,
+413,
+399,
+381,
+362,
+340,
+316,
+289,
+261,
+231,
+199,
+165,
+130,
+93,
+55,
+16,
+-23,
+-63,
+-104,
+-145,
+-187,
+-228,
+-269,
+-310,
+-349,
+-388,
+-425,
+-461,
+-495,
+-528,
+-558,
+-586,
+-612,
+-635,
+-655,
+-673,
+-687,
+-698,
+-705,
+-709,
+-710,
+-707,
+-700,
+-690,
+-675,
+-657,
+-636,
+-610,
+-581,
+-549,
+-513,
+-473,
+-431,
+-385,
+-336,
+-285,
+-232,
+-176,
+-118,
+-59,
+1,
+64,
+127,
+190,
+254,
+318,
+381,
+444,
+505,
+566,
+624,
+680,
+734,
+786,
+834,
+879,
+920,
+957,
+990,
+1019,
+1043,
+1062,
+1076,
+1085,
+1088,
+1086,
+1079,
+1065,
+1046,
+1022,
+991,
+955,
+913,
+866,
+814,
+756,
+693,
+626,
+554,
+478,
+398,
+314,
+228,
+138,
+46,
+-47,
+-143,
+-240,
+-337,
+-435,
+-532,
+-628,
+-723,
+-817,
+-907,
+-995,
+-1080,
+-1161,
+-1237,
+-1309,
+-1375,
+-1436,
+-1490,
+-1538,
+-1579,
+-1612,
+-1639,
+-1657,
+-1667,
+-1669,
+-1662,
+-1647,
+-1623,
+-1590,
+-1548,
+-1498,
+-1439,
+-1372,
+-1296,
+-1212,
+-1120,
+-1020,
+-913,
+-800,
+-680,
+-553,
+-422,
+-286,
+-145,
+0,
+146,
+296,
+447,
+599,
+752,
+904,
+1054,
+1203,
+1348,
+1490,
+1627,
+1759,
+1885,
+2004,
+2115,
+2218,
+2312,
+2396,
+2470,
+2533,
+2584,
+2623,
+2650,
+2664,
+2665,
+2652,
+2625,
+2584,
+2529,
+2460,
+2376,
+2278,
+2167,
+2041,
+1902,
+1750,
+1585,
+1407,
+1218,
+1018,
+808,
+588,
+359,
+123,
+-120,
+-369,
+-623,
+-881,
+-1142,
+-1403,
+-1665,
+-1926,
+-2184,
+-2439,
+-2688,
+-2931,
+-3166,
+-3392,
+-3607,
+-3810,
+-4000,
+-4176,
+-4335,
+-4478,
+-4602,
+-4706,
+-4790,
+-4852,
+-4891,
+-4906,
+-4897,
+-4862,
+-4801,
+-4713,
+-4598,
+-4454,
+-4283,
+-4082,
+-3853,
+-3595,
+-3308,
+-2992,
+-2647,
+-2274,
+-1873,
+-1445,
+-990,
+-509,
+-3,
+527,
+1081,
+1657,
+2254,
+2870,
+3505,
+4156,
+4823,
+5504,
+6196,
+6898,
+7609,
+8326,
+9048,
+9773,
+10498,
+11222,
+11943,
+12658,
+13366,
+14065,
+14753,
+15427,
+16086,
+16728,
+17351,
+17953,
+18533,
+19088,
+19616,
+20118,
+20590,
+21032,
+21441,
+21818,
+22160,
+22467,
+22738,
+22971,
+23167,
+23324,
+23443,
+23522,
+23561,
diff --git a/fir/c44100pal.scm b/fir/c44100pal.scm
new file mode 100644
index 00000000..6188fcd2
--- /dev/null
+++ b/fir/c44100pal.scm
@@ -0,0 +1,12 @@
+(title "44100 PAL")
+
+(verbose #t)
+
+(cosine-symmetry)
+(filter-length 1024)
+(sampling-frequency 1662607.125)
+(limit-= (band 0 15500) 1)
+(limit-= (band 22050 831303.5625) 0 .5)
+(output-file "c44100pal.coef")
+(plot-file "c44100pal.plot")
+(go)
diff --git a/fir/c48000ntsc.coef b/fir/c48000ntsc.coef
new file mode 100644
index 00000000..36a49ceb
--- /dev/null
+++ b/fir/c48000ntsc.coef
@@ -0,0 +1,1039 @@
+;; ***** Simple test filter *****
+;; Filter length: 1024
+;; Symmetry: cosine
+;; Sampling frequency: 1789772.72727273
+;; Grid density: 10257
+;; Deviation parameter: y=-4.15334587672572e-4
+;;
+;; Specifications:
+;; (limit > 24000 894886.363636 0 0.5)
+;; (limit < 24000 894886.363636 0 0.5)
+;; (limit > 0 17000 1 1)
+;; (limit < 0 17000 1 1)
+;;
+;; Coefficients:
+
+-1.09949811042225e-4
+-1.22806738594947e-5
+-1.2856649387849e-5
+-1.33942943882967e-5
+-1.38759188766186e-5
+-1.42903486313313e-5
+-1.46314856397791e-5
+-1.48912662330057e-5
+-1.50872358926362e-5
+-1.51736783706926e-5
+-1.51920174272043e-5
+-1.50946540712042e-5
+-1.4906159571695e-5
+-1.46043232504438e-5
+-1.41826804115075e-5
+-1.3656619477754e-5
+-1.30159730761761e-5
+-1.22550097006306e-5
+-1.13887071556529e-5
+-1.03867032653885e-5
+-9.28900860776593e-6
+-8.04914399027275e-6
+-6.71896085473064e-6
+-5.26687936275949e-6
+-3.70827372384805e-6
+-2.05782362044426e-6
+-3.07184084317173e-7
+1.56196204778674e-6
+3.49335533222506e-6
+5.50094513191646e-6
+7.58454405677602e-6
+9.73122206351426e-6
+1.1925384533121e-5
+1.41723759116143e-5
+1.64486730093282e-5
+1.87185665617164e-5
+2.10193314554571e-5
+2.32868013030244e-5
+2.553385658201e-5
+2.77448936592136e-5
+2.98938550558335e-5
+3.19813209008917e-5
+3.39767566092725e-5
+3.58854777832478e-5
+3.77083338973254e-5
+3.93896125185267e-5
+4.09448701284991e-5
+4.2335041675049e-5
+4.355182102547e-5
+4.45811599449272e-5
+4.53754087968507e-5
+4.5963991898548e-5
+4.63912768895152e-5
+4.66332273332272e-5
+4.6623761079951e-5
+4.61449042224772e-5
+4.56999092246609e-5
+4.48566415488991e-5
+4.37716646911701e-5
+4.24332940559181e-5
+4.08053879668338e-5
+3.88924305216162e-5
+3.67371834848531e-5
+3.42871968756067e-5
+3.16108049585284e-5
+2.86477428425672e-5
+2.54397360410253e-5
+2.19995003725315e-5
+1.83235898190551e-5
+1.44365831918759e-5
+1.0347151946393e-5
+6.06550691029756e-6
+1.62938066833157e-6
+-2.97932202860966e-6
+-7.69928040586833e-6
+-1.25326516699612e-5
+-1.74386499250263e-5
+-2.24193699837587e-5
+-2.74121537882667e-5
+-3.2420323875298e-5
+-3.74096430792575e-5
+-4.23517165718808e-5
+-4.71910843635185e-5
+-5.19552722226438e-5
+-5.65526133942226e-5
+-6.09864135270981e-5
+-6.52252080560519e-5
+-6.92340008906634e-5
+-7.29676421256746e-5
+-7.64220773917906e-5
+-7.957469184604e-5
+-8.23723520198843e-5
+-8.48145294498788e-5
+-8.68637280156417e-5
+-8.847590640524e-5
+-8.96579831689903e-5
+-9.03754273981505e-5
+-9.06277650874391e-5
+-9.0390962049786e-5
+-8.96295019021089e-5
+-8.83699462608486e-5
+-8.65929014634202e-5
+-8.42777636122367e-5
+-8.1438947139124e-5
+-7.80310589482434e-5
+-7.4130290344153e-5
+-6.97213148895689e-5
+-6.47743915798445e-5
+-5.93190057095397e-5
+-5.3369300678592e-5
+-4.70020380599523e-5
+-4.01241085336933e-5
+-3.28791381626816e-5
+-2.52335267849121e-5
+-1.72013052766137e-5
+-8.85204247806303e-6
+-2.36203952998983e-7
+8.65426060083348e-6
+1.77326837630105e-5
+2.70119909588562e-5
+3.63935730200405e-5
+4.58302978650995e-5
+5.53120362349631e-5
+6.47532841902274e-5
+7.41091974779693e-5
+8.33336809092267e-5
+9.23584465403365e-5
+1.0115262933884e-4
+1.09631128039229e-4
+1.17757486894641e-4
+1.25489570576103e-4
+1.32754230059236e-4
+1.39503431050419e-4
+1.45701107814038e-4
+1.51259946463513e-4
+1.56172084911138e-4
+1.6038874820501e-4
+1.63870537117991e-4
+1.66539506236844e-4
+1.68421511031107e-4
+1.69442548025091e-4
+1.69579877038768e-4
+1.6881612357465e-4
+1.67142961466588e-4
+1.64531403910968e-4
+1.60985251495646e-4
+1.56489605383482e-4
+1.5103863824127e-4
+1.44638439288558e-4
+1.3732499213528e-4
+1.29095155164885e-4
+1.19970934485128e-4
+1.09972583377882e-4
+9.91339782697809e-5
+8.75139349992027e-5
+7.51413396638277e-5
+6.20524024461875e-5
+4.83301074719599e-5
+3.39882067477733e-5
+1.91401658681103e-5
+3.81291646780894e-6
+-1.18969312223288e-5
+-2.79091174901399e-5
+-4.41757419681384e-5
+-6.06051695381194e-5
+-7.70882672632681e-5
+-9.35502837597759e-5
+-1.09925493394208e-4
+-1.26105817993473e-4
+-1.41986602739464e-4
+-1.57477825556515e-4
+-1.72511116490329e-4
+-1.86975264016647e-4
+-2.0078755537738e-4
+-2.13836321481426e-4
+-2.26049064513734e-4
+-2.37368218087728e-4
+-2.47667060725941e-4
+-2.56892753723085e-4
+-2.64968427146944e-4
+-2.71811293915514e-4
+-2.77368381437469e-4
+-2.81573581193851e-4
+-2.84371752243438e-4
+-2.85739766097855e-4
+-2.85600433310225e-4
+-2.83955117995654e-4
+-2.80740799593234e-4
+-2.75948247317517e-4
+-2.69611626635144e-4
+-2.61691007650807e-4
+-2.52188089302722e-4
+-2.41138311003691e-4
+-2.28565411014119e-4
+-2.14482121588247e-4
+-1.9895360017079e-4
+-1.8201715772697e-4
+-1.63736603204964e-4
+-1.44183596994227e-4
+-1.23436201666099e-4
+-1.01558928824961e-4
+-7.86622769828866e-5
+-5.48472741191755e-5
+-3.02274887834648e-5
+-4.9052508479435e-6
+2.10064626953057e-5
+4.73692357955313e-5
+7.40576789101123e-5
+1.00930166818208e-4
+1.27850827966983e-4
+1.54673624437643e-4
+1.81245925229617e-4
+2.07459909036642e-4
+2.33129240741297e-4
+2.58109799089455e-4
+2.82247208675082e-4
+3.05421790075743e-4
+3.27480832505477e-4
+3.48269568065021e-4
+3.6763827845558e-4
+3.85499646838909e-4
+4.01682103671787e-4
+4.16086785395773e-4
+4.28597839023261e-4
+4.39097519078108e-4
+4.47510063482399e-4
+4.53732616193564e-4
+4.57673475015079e-4
+4.59289837761018e-4
+4.5850639594641e-4
+4.55297854632095e-4
+4.49607814238691e-4
+4.41429940481748e-4
+4.30750173165062e-4
+4.17571750776714e-4
+4.01921059289583e-4
+3.83832134824733e-4
+3.63333748980151e-4
+3.40524023663407e-4
+3.15436084161991e-4
+2.88188541554642e-4
+2.58843348650986e-4
+2.2755513753174e-4
+1.94439484002676e-4
+1.59617684118401e-4
+1.23249634741989e-4
+8.5510700519544e-5
+4.65441005957331e-5
+6.57031586978297e-6
+-3.42428951570416e-5
+-7.5699448554351e-5
+-1.17574026058653e-4
+-1.59659853873827e-4
+-2.01745572207549e-4
+-2.4360492525437e-4
+-2.8501090249108e-4
+-3.25733846890315e-4
+-3.65540766223455e-4
+-4.04206100994041e-4
+-4.41510228555032e-4
+-4.77213532040263e-4
+-5.11116556934743e-4
+-5.42986611641292e-4
+-5.72614695207158e-4
+-5.99800201510281e-4
+-6.24363710833356e-4
+-6.46126331992769e-4
+-6.64897970015276e-4
+-6.8052501770588e-4
+-6.92886060830722e-4
+-7.01833451901113e-4
+-7.07250228969443e-4
+-7.09057753989528e-4
+-7.07154827552179e-4
+-7.01496865293485e-4
+-6.92021891429721e-4
+-6.78737292920809e-4
+-6.61615877709466e-4
+-6.40668301834071e-4
+-6.15954503334807e-4
+-5.87516953638343e-4
+-5.5543054818097e-4
+-5.19817664992314e-4
+-4.80761718393648e-4
+-4.38443435457234e-4
+-3.92999331139588e-4
+-3.44607011339858e-4
+-2.9348321650997e-4
+-2.3983421051813e-4
+-1.83896811789197e-4
+-1.2592231659735e-4
+-6.61594042730277e-5
+-4.9252546289175e-6
+5.75175579438193e-5
+1.20840816301453e-4
+1.84748121533308e-4
+2.48893569837659e-4
+3.12957694717443e-4
+3.76586747195116e-4
+4.39458057575329e-4
+5.01208720002647e-4
+5.61505630848618e-4
+6.19978340175428e-4
+6.76328791582876e-4
+7.30187225165355e-4
+7.81228789019675e-4
+8.29133676742072e-4
+8.73586107685454e-4
+9.14292826672621e-4
+9.50980660353665e-4
+9.8335580172593e-4
+0.00101117365679917
+0.0010342034115958
+0.00105223766601628
+0.0010650850759155
+0.00107259035326429
+0.00107459393770505
+0.00107099171776075
+0.0010616907401631
+0.00104663727550016
+0.00102579422906041
+9.99174270226947e-4
+9.66796775092314e-4
+9.28727841773456e-4
+8.85038362639593e-4
+8.35888033960542e-4
+7.81415464948617e-4
+7.21781542997729e-4
+6.5723033289136e-4
+5.88002310491308e-4
+5.14363552961592e-4
+4.36612788588694e-4
+3.55077835414929e-4
+2.70131130639128e-4
+1.82143163521255e-4
+9.15090743372197e-5
+-1.33605757547524e-6
+-9.59647394963337e-5
+-1.91891614650009e-4
+-2.88666748710662e-4
+-3.85790985377778e-4
+-4.82744482577328e-4
+-5.79040781433632e-4
+-6.74149659110707e-4
+-7.67559001801454e-4
+-8.58757697345997e-4
+-9.47196836410621e-4
+-0.00103237718183087
+-0.00111379514944025
+-0.00119095339891772
+-0.00126336405490239
+-0.0013305487657181
+-0.00139205895696274
+-0.00144748189993549
+-0.00149637609832828
+-0.00153838019191627
+-0.00157313252823261
+-0.00160031824966766
+-0.00161963448121335
+-0.00163083428806327
+-0.00163368043294617
+-0.00162801106822713
+-0.00161369463758679
+-0.001590627176841
+-0.00155873704279726
+-0.00151802687039672
+-0.00146852840940013
+-0.00141032303015301
+-0.00134354264387151
+-0.00126835601060216
+-0.00118498680408603
+-0.00109369844655022
+-9.94796296696515e-4
+-8.8865052983109e-4
+-7.75668795643321e-4
+-6.56296891780576e-4
+-5.31000918141328e-4
+-4.00317796479334e-4
+-2.64818077987588e-4
+-1.25114221854341e-4
+1.81841346036177e-5
+1.64393641166078e-4
+3.12811847712545e-4
+4.62729945674983e-4
+6.13406073593611e-4
+7.64065647645698e-4
+9.13943516660458e-4
+0.00106223039501543
+0.00120813812086204
+0.00135086874684724
+0.00148959926942261
+0.00162354046408344
+0.00175189262820587
+0.00187387246188932
+0.00198871017104844
+0.00209565287683832
+0.0021939767567535
+0.00228297968827271
+0.00236200869351783
+0.00243042754510312
+0.00248762788988958
+0.0025330698432872
+0.00256626682234492
+0.00258674212159455
+0.00259411104319052
+0.00258801693114338
+0.0025681874145284
+0.00253439944797282
+0.0024864849067166
+0.00242436415305489
+0.00234800707561149
+0.00225745930340907
+0.00215285442473657
+0.00203435432097337
+0.00190222275978058
+0.00175681593792146
+0.00159852537978592
+0.0014278366643269
+0.00124529939623188
+0.00105153398032655
+8.47243678747333e-4
+6.33180470845124e-4
+4.10182654032466e-4
+1.79134409511786e-4
+-5.90060425716582e-5
+-3.03246569572555e-4
+-5.52504441714844e-4
+-8.05662799984435e-4
+-0.00106155482217139
+-0.00131898406132897
+-0.00157669465967831
+-0.00183340910297136
+-0.00208780837793107
+-0.00233856516182173
+-0.00258431370577947
+-0.00282368901281709
+-0.00305532603599211
+-0.00327782955235904
+-0.00348982317700461
+-0.00368994504305836
+-0.00387684142913267
+-0.00404917288620234
+-0.00420563779140244
+-0.00434495904267169
+-0.00446589522922125
+-0.00456726636733209
+-0.0046479215365105
+-0.00470677650973429
+-0.00474281564445811
+-0.00475506485728163
+-0.00474262236885261
+-0.00470469762343002
+-0.00464054556498023
+-0.00454951664806806
+-0.00443104181074602
+-0.0042846470727934
+-0.00410997073193062
+-0.00390671622712066
+-0.00367472523350812
+-0.00341390471257351
+-0.00312428955884935
+-0.0028060183794834
+-0.00245932446744169
+-0.00208454478573285
+-0.00168215159474978
+-0.00125270028130292
+-7.96876227266184e-4
+-3.15420122431397e-4
+1.90771392553303e-4
+7.20722841875099e-4
+0.00127336018779148
+0.00184749620984379
+0.00244188239334642
+0.00305516500721029
+0.00368588762187621
+0.00433255328849199
+0.00499354206149272
+0.00566720184348075
+0.0063517971761537
+0.00704553740219523
+0.00774656770503074
+0.00845301860954979
+0.00916293528892598
+0.00987436353423422
+0.0105853002711883
+0.0112937615141001
+0.0119976912030812
+0.0126950714702282
+0.0133838628629058
+0.0140620731478666
+0.0147276747542291
+0.015378682266711
+0.0160131634096303
+0.0166292108981782
+0.0172249492566478
+0.0177985839161102
+0.0183483448715057
+0.0188725570567793
+0.019369603943763
+0.0198379424297359
+0.020276126356732
+0.0206827991478066
+0.0210566858163425
+0.0213966117522584
+0.0217015035994142
+0.0219704341407132
+0.0222025359487478
+0.0223970968853833
+0.0225534819131259
+0.0226711961954482
+0.0227498857420413
+0.0227892926322558
+0.0227892926322558
+0.0227498857420413
+0.0226711961954482
+0.0225534819131259
+0.0223970968853833
+0.0222025359487478
+0.0219704341407132
+0.0217015035994142
+0.0213966117522584
+0.0210566858163425
+0.0206827991478066
+0.020276126356732
+0.0198379424297359
+0.019369603943763
+0.0188725570567793
+0.0183483448715057
+0.0177985839161102
+0.0172249492566478
+0.0166292108981782
+0.0160131634096303
+0.015378682266711
+0.0147276747542291
+0.0140620731478666
+0.0133838628629058
+0.0126950714702282
+0.0119976912030812
+0.0112937615141001
+0.0105853002711883
+0.00987436353423422
+0.00916293528892598
+0.00845301860954979
+0.00774656770503074
+0.00704553740219523
+0.0063517971761537
+0.00566720184348075
+0.00499354206149272
+0.00433255328849199
+0.00368588762187621
+0.00305516500721029
+0.00244188239334642
+0.00184749620984379
+0.00127336018779148
+7.20722841875099e-4
+1.90771392553303e-4
+-3.15420122431397e-4
+-7.96876227266184e-4
+-0.00125270028130292
+-0.00168215159474978
+-0.00208454478573285
+-0.00245932446744169
+-0.0028060183794834
+-0.00312428955884935
+-0.00341390471257351
+-0.00367472523350812
+-0.00390671622712066
+-0.00410997073193062
+-0.0042846470727934
+-0.00443104181074602
+-0.00454951664806806
+-0.00464054556498023
+-0.00470469762343002
+-0.00474262236885261
+-0.00475506485728163
+-0.00474281564445811
+-0.00470677650973429
+-0.0046479215365105
+-0.00456726636733209
+-0.00446589522922125
+-0.00434495904267169
+-0.00420563779140244
+-0.00404917288620234
+-0.00387684142913267
+-0.00368994504305836
+-0.00348982317700461
+-0.00327782955235904
+-0.00305532603599211
+-0.00282368901281709
+-0.00258431370577947
+-0.00233856516182173
+-0.00208780837793107
+-0.00183340910297136
+-0.00157669465967831
+-0.00131898406132897
+-0.00106155482217139
+-8.05662799984435e-4
+-5.52504441714844e-4
+-3.03246569572555e-4
+-5.90060425716582e-5
+1.79134409511786e-4
+4.10182654032466e-4
+6.33180470845124e-4
+8.47243678747333e-4
+0.00105153398032655
+0.00124529939623188
+0.0014278366643269
+0.00159852537978592
+0.00175681593792146
+0.00190222275978058
+0.00203435432097337
+0.00215285442473657
+0.00225745930340907
+0.00234800707561149
+0.00242436415305489
+0.0024864849067166
+0.00253439944797282
+0.0025681874145284
+0.00258801693114338
+0.00259411104319052
+0.00258674212159455
+0.00256626682234492
+0.0025330698432872
+0.00248762788988958
+0.00243042754510312
+0.00236200869351783
+0.00228297968827271
+0.0021939767567535
+0.00209565287683832
+0.00198871017104844
+0.00187387246188932
+0.00175189262820587
+0.00162354046408344
+0.00148959926942261
+0.00135086874684724
+0.00120813812086204
+0.00106223039501543
+9.13943516660458e-4
+7.64065647645698e-4
+6.13406073593611e-4
+4.62729945674983e-4
+3.12811847712545e-4
+1.64393641166078e-4
+1.81841346036177e-5
+-1.25114221854341e-4
+-2.64818077987588e-4
+-4.00317796479334e-4
+-5.31000918141328e-4
+-6.56296891780576e-4
+-7.75668795643321e-4
+-8.8865052983109e-4
+-9.94796296696515e-4
+-0.00109369844655022
+-0.00118498680408603
+-0.00126835601060216
+-0.00134354264387151
+-0.00141032303015301
+-0.00146852840940013
+-0.00151802687039672
+-0.00155873704279726
+-0.001590627176841
+-0.00161369463758679
+-0.00162801106822713
+-0.00163368043294617
+-0.00163083428806327
+-0.00161963448121335
+-0.00160031824966766
+-0.00157313252823261
+-0.00153838019191627
+-0.00149637609832828
+-0.00144748189993549
+-0.00139205895696274
+-0.0013305487657181
+-0.00126336405490239
+-0.00119095339891772
+-0.00111379514944025
+-0.00103237718183087
+-9.47196836410621e-4
+-8.58757697345997e-4
+-7.67559001801454e-4
+-6.74149659110707e-4
+-5.79040781433632e-4
+-4.82744482577328e-4
+-3.85790985377778e-4
+-2.88666748710662e-4
+-1.91891614650009e-4
+-9.59647394963337e-5
+-1.33605757547524e-6
+9.15090743372197e-5
+1.82143163521255e-4
+2.70131130639128e-4
+3.55077835414929e-4
+4.36612788588694e-4
+5.14363552961592e-4
+5.88002310491308e-4
+6.5723033289136e-4
+7.21781542997729e-4
+7.81415464948617e-4
+8.35888033960542e-4
+8.85038362639593e-4
+9.28727841773456e-4
+9.66796775092314e-4
+9.99174270226947e-4
+0.00102579422906041
+0.00104663727550016
+0.0010616907401631
+0.00107099171776075
+0.00107459393770505
+0.00107259035326429
+0.0010650850759155
+0.00105223766601628
+0.0010342034115958
+0.00101117365679917
+9.8335580172593e-4
+9.50980660353665e-4
+9.14292826672621e-4
+8.73586107685454e-4
+8.29133676742072e-4
+7.81228789019675e-4
+7.30187225165355e-4
+6.76328791582876e-4
+6.19978340175428e-4
+5.61505630848618e-4
+5.01208720002647e-4
+4.39458057575329e-4
+3.76586747195116e-4
+3.12957694717443e-4
+2.48893569837659e-4
+1.84748121533308e-4
+1.20840816301453e-4
+5.75175579438193e-5
+-4.9252546289175e-6
+-6.61594042730277e-5
+-1.2592231659735e-4
+-1.83896811789197e-4
+-2.3983421051813e-4
+-2.9348321650997e-4
+-3.44607011339858e-4
+-3.92999331139588e-4
+-4.38443435457234e-4
+-4.80761718393648e-4
+-5.19817664992314e-4
+-5.5543054818097e-4
+-5.87516953638343e-4
+-6.15954503334807e-4
+-6.40668301834071e-4
+-6.61615877709466e-4
+-6.78737292920809e-4
+-6.92021891429721e-4
+-7.01496865293485e-4
+-7.07154827552179e-4
+-7.09057753989528e-4
+-7.07250228969443e-4
+-7.01833451901113e-4
+-6.92886060830722e-4
+-6.8052501770588e-4
+-6.64897970015276e-4
+-6.46126331992769e-4
+-6.24363710833356e-4
+-5.99800201510281e-4
+-5.72614695207158e-4
+-5.42986611641292e-4
+-5.11116556934743e-4
+-4.77213532040263e-4
+-4.41510228555032e-4
+-4.04206100994041e-4
+-3.65540766223455e-4
+-3.25733846890315e-4
+-2.8501090249108e-4
+-2.4360492525437e-4
+-2.01745572207549e-4
+-1.59659853873827e-4
+-1.17574026058653e-4
+-7.5699448554351e-5
+-3.42428951570416e-5
+6.57031586978297e-6
+4.65441005957331e-5
+8.5510700519544e-5
+1.23249634741989e-4
+1.59617684118401e-4
+1.94439484002676e-4
+2.2755513753174e-4
+2.58843348650986e-4
+2.88188541554642e-4
+3.15436084161991e-4
+3.40524023663407e-4
+3.63333748980151e-4
+3.83832134824733e-4
+4.01921059289583e-4
+4.17571750776714e-4
+4.30750173165062e-4
+4.41429940481748e-4
+4.49607814238691e-4
+4.55297854632095e-4
+4.5850639594641e-4
+4.59289837761018e-4
+4.57673475015079e-4
+4.53732616193564e-4
+4.47510063482399e-4
+4.39097519078108e-4
+4.28597839023261e-4
+4.16086785395773e-4
+4.01682103671787e-4
+3.85499646838909e-4
+3.6763827845558e-4
+3.48269568065021e-4
+3.27480832505477e-4
+3.05421790075743e-4
+2.82247208675082e-4
+2.58109799089455e-4
+2.33129240741297e-4
+2.07459909036642e-4
+1.81245925229617e-4
+1.54673624437643e-4
+1.27850827966983e-4
+1.00930166818208e-4
+7.40576789101123e-5
+4.73692357955313e-5
+2.10064626953057e-5
+-4.9052508479435e-6
+-3.02274887834648e-5
+-5.48472741191755e-5
+-7.86622769828866e-5
+-1.01558928824961e-4
+-1.23436201666099e-4
+-1.44183596994227e-4
+-1.63736603204964e-4
+-1.8201715772697e-4
+-1.9895360017079e-4
+-2.14482121588247e-4
+-2.28565411014119e-4
+-2.41138311003691e-4
+-2.52188089302722e-4
+-2.61691007650807e-4
+-2.69611626635144e-4
+-2.75948247317517e-4
+-2.80740799593234e-4
+-2.83955117995654e-4
+-2.85600433310225e-4
+-2.85739766097855e-4
+-2.84371752243438e-4
+-2.81573581193851e-4
+-2.77368381437469e-4
+-2.71811293915514e-4
+-2.64968427146944e-4
+-2.56892753723085e-4
+-2.47667060725941e-4
+-2.37368218087728e-4
+-2.26049064513734e-4
+-2.13836321481426e-4
+-2.0078755537738e-4
+-1.86975264016647e-4
+-1.72511116490329e-4
+-1.57477825556515e-4
+-1.41986602739464e-4
+-1.26105817993473e-4
+-1.09925493394208e-4
+-9.35502837597759e-5
+-7.70882672632681e-5
+-6.06051695381194e-5
+-4.41757419681384e-5
+-2.79091174901399e-5
+-1.18969312223288e-5
+3.81291646780894e-6
+1.91401658681103e-5
+3.39882067477733e-5
+4.83301074719599e-5
+6.20524024461875e-5
+7.51413396638277e-5
+8.75139349992027e-5
+9.91339782697809e-5
+1.09972583377882e-4
+1.19970934485128e-4
+1.29095155164885e-4
+1.3732499213528e-4
+1.44638439288558e-4
+1.5103863824127e-4
+1.56489605383482e-4
+1.60985251495646e-4
+1.64531403910968e-4
+1.67142961466588e-4
+1.6881612357465e-4
+1.69579877038768e-4
+1.69442548025091e-4
+1.68421511031107e-4
+1.66539506236844e-4
+1.63870537117991e-4
+1.6038874820501e-4
+1.56172084911138e-4
+1.51259946463513e-4
+1.45701107814038e-4
+1.39503431050419e-4
+1.32754230059236e-4
+1.25489570576103e-4
+1.17757486894641e-4
+1.09631128039229e-4
+1.0115262933884e-4
+9.23584465403365e-5
+8.33336809092267e-5
+7.41091974779693e-5
+6.47532841902274e-5
+5.53120362349631e-5
+4.58302978650995e-5
+3.63935730200405e-5
+2.70119909588562e-5
+1.77326837630105e-5
+8.65426060083348e-6
+-2.36203952998983e-7
+-8.85204247806303e-6
+-1.72013052766137e-5
+-2.52335267849121e-5
+-3.28791381626816e-5
+-4.01241085336933e-5
+-4.70020380599523e-5
+-5.3369300678592e-5
+-5.93190057095397e-5
+-6.47743915798445e-5
+-6.97213148895689e-5
+-7.4130290344153e-5
+-7.80310589482434e-5
+-8.1438947139124e-5
+-8.42777636122367e-5
+-8.65929014634202e-5
+-8.83699462608486e-5
+-8.96295019021089e-5
+-9.0390962049786e-5
+-9.06277650874391e-5
+-9.03754273981505e-5
+-8.96579831689903e-5
+-8.847590640524e-5
+-8.68637280156417e-5
+-8.48145294498788e-5
+-8.23723520198843e-5
+-7.957469184604e-5
+-7.64220773917906e-5
+-7.29676421256746e-5
+-6.92340008906634e-5
+-6.52252080560519e-5
+-6.09864135270981e-5
+-5.65526133942226e-5
+-5.19552722226438e-5
+-4.71910843635185e-5
+-4.23517165718808e-5
+-3.74096430792575e-5
+-3.2420323875298e-5
+-2.74121537882667e-5
+-2.24193699837587e-5
+-1.74386499250263e-5
+-1.25326516699612e-5
+-7.69928040586833e-6
+-2.97932202860966e-6
+1.62938066833157e-6
+6.06550691029756e-6
+1.0347151946393e-5
+1.44365831918759e-5
+1.83235898190551e-5
+2.19995003725315e-5
+2.54397360410253e-5
+2.86477428425672e-5
+3.16108049585284e-5
+3.42871968756067e-5
+3.67371834848531e-5
+3.88924305216162e-5
+4.08053879668338e-5
+4.24332940559181e-5
+4.37716646911701e-5
+4.48566415488991e-5
+4.56999092246609e-5
+4.61449042224772e-5
+4.6623761079951e-5
+4.66332273332272e-5
+4.63912768895152e-5
+4.5963991898548e-5
+4.53754087968507e-5
+4.45811599449272e-5
+4.355182102547e-5
+4.2335041675049e-5
+4.09448701284991e-5
+3.93896125185267e-5
+3.77083338973254e-5
+3.58854777832478e-5
+3.39767566092725e-5
+3.19813209008917e-5
+2.98938550558335e-5
+2.77448936592136e-5
+2.553385658201e-5
+2.32868013030244e-5
+2.10193314554571e-5
+1.87185665617164e-5
+1.64486730093282e-5
+1.41723759116143e-5
+1.1925384533121e-5
+9.73122206351426e-6
+7.58454405677602e-6
+5.50094513191646e-6
+3.49335533222506e-6
+1.56196204778674e-6
+-3.07184084317173e-7
+-2.05782362044426e-6
+-3.70827372384805e-6
+-5.26687936275949e-6
+-6.71896085473064e-6
+-8.04914399027275e-6
+-9.28900860776593e-6
+-1.03867032653885e-5
+-1.13887071556529e-5
+-1.22550097006306e-5
+-1.30159730761761e-5
+-1.3656619477754e-5
+-1.41826804115075e-5
+-1.46043232504438e-5
+-1.4906159571695e-5
+-1.50946540712042e-5
+-1.51920174272043e-5
+-1.51736783706926e-5
+-1.50872358926362e-5
+-1.48912662330057e-5
+-1.46314856397791e-5
+-1.42903486313313e-5
+-1.38759188766186e-5
+-1.33942943882967e-5
+-1.2856649387849e-5
+-1.22806738594947e-5
+-1.09949811042225e-4
diff --git a/fir/c48000ntsc.h b/fir/c48000ntsc.h
new file mode 100644
index 00000000..82c7cb29
--- /dev/null
+++ b/fir/c48000ntsc.h
@@ -0,0 +1,512 @@
+-115,
+-12,
+-13,
+-14,
+-14,
+-14,
+-15,
+-15,
+-15,
+-15,
+-15,
+-15,
+-15,
+-15,
+-14,
+-14,
+-13,
+-12,
+-11,
+-10,
+-9,
+-8,
+-7,
+-5,
+-3,
+-2,
+0,
+1,
+3,
+5,
+7,
+10,
+12,
+14,
+17,
+19,
+22,
+24,
+26,
+29,
+31,
+33,
+35,
+37,
+39,
+41,
+42,
+44,
+45,
+46,
+47,
+48,
+48,
+48,
+48,
+48,
+47,
+47,
+45,
+44,
+42,
+40,
+38,
+35,
+33,
+30,
+26,
+23,
+19,
+15,
+10,
+6,
+1,
+-3,
+-8,
+-13,
+-18,
+-23,
+-28,
+-33,
+-39,
+-44,
+-49,
+-54,
+-59,
+-63,
+-68,
+-72,
+-76,
+-80,
+-83,
+-86,
+-88,
+-91,
+-92,
+-94,
+-94,
+-95,
+-94,
+-93,
+-92,
+-90,
+-88,
+-85,
+-81,
+-77,
+-73,
+-67,
+-62,
+-55,
+-49,
+-42,
+-34,
+-26,
+-18,
+-9,
+0,
+9,
+18,
+28,
+38,
+48,
+57,
+67,
+77,
+87,
+96,
+106,
+114,
+123,
+131,
+139,
+146,
+152,
+158,
+163,
+168,
+171,
+174,
+176,
+177,
+177,
+177,
+175,
+172,
+168,
+164,
+158,
+151,
+143,
+135,
+125,
+115,
+103,
+91,
+78,
+65,
+50,
+35,
+20,
+3,
+-12,
+-29,
+-46,
+-63,
+-80,
+-98,
+-115,
+-132,
+-148,
+-165,
+-180,
+-196,
+-210,
+-224,
+-237,
+-248,
+-259,
+-269,
+-277,
+-285,
+-290,
+-295,
+-298,
+-299,
+-299,
+-297,
+-294,
+-289,
+-282,
+-274,
+-264,
+-252,
+-239,
+-224,
+-208,
+-190,
+-171,
+-151,
+-129,
+-106,
+-82,
+-57,
+-31,
+-5,
+22,
+49,
+77,
+105,
+134,
+162,
+190,
+217,
+244,
+270,
+295,
+320,
+343,
+365,
+385,
+404,
+421,
+436,
+449,
+460,
+469,
+475,
+479,
+481,
+480,
+477,
+471,
+462,
+451,
+437,
+421,
+402,
+380,
+357,
+330,
+302,
+271,
+238,
+203,
+167,
+129,
+89,
+48,
+6,
+-35,
+-79,
+-123,
+-167,
+-211,
+-255,
+-298,
+-341,
+-383,
+-423,
+-462,
+-500,
+-535,
+-569,
+-600,
+-628,
+-654,
+-677,
+-697,
+-713,
+-726,
+-735,
+-741,
+-743,
+-741,
+-735,
+-725,
+-711,
+-693,
+-671,
+-645,
+-616,
+-582,
+-545,
+-504,
+-459,
+-412,
+-361,
+-307,
+-251,
+-192,
+-132,
+-69,
+-5,
+60,
+126,
+193,
+260,
+328,
+394,
+460,
+525,
+588,
+650,
+709,
+765,
+819,
+869,
+916,
+958,
+997,
+1031,
+1060,
+1084,
+1103,
+1116,
+1124,
+1126,
+1123,
+1113,
+1097,
+1075,
+1047,
+1013,
+973,
+928,
+876,
+819,
+756,
+689,
+616,
+539,
+457,
+372,
+283,
+190,
+95,
+-1,
+-100,
+-201,
+-302,
+-404,
+-506,
+-607,
+-706,
+-804,
+-900,
+-993,
+-1082,
+-1167,
+-1248,
+-1324,
+-1395,
+-1459,
+-1517,
+-1569,
+-1613,
+-1649,
+-1678,
+-1698,
+-1710,
+-1713,
+-1707,
+-1692,
+-1667,
+-1634,
+-1591,
+-1539,
+-1478,
+-1408,
+-1329,
+-1242,
+-1146,
+-1043,
+-931,
+-813,
+-688,
+-556,
+-419,
+-277,
+-131,
+19,
+172,
+328,
+485,
+643,
+801,
+958,
+1113,
+1266,
+1416,
+1561,
+1702,
+1836,
+1964,
+2085,
+2197,
+2300,
+2393,
+2476,
+2548,
+2608,
+2656,
+2690,
+2712,
+2720,
+2713,
+2692,
+2657,
+2607,
+2542,
+2462,
+2367,
+2257,
+2133,
+1994,
+1842,
+1676,
+1497,
+1305,
+1102,
+888,
+663,
+430,
+187,
+-61,
+-317,
+-579,
+-844,
+-1113,
+-1383,
+-1653,
+-1922,
+-2189,
+-2452,
+-2709,
+-2960,
+-3203,
+-3437,
+-3659,
+-3869,
+-4065,
+-4245,
+-4409,
+-4556,
+-4682,
+-4789,
+-4873,
+-4935,
+-4973,
+-4986,
+-4972,
+-4933,
+-4865,
+-4770,
+-4646,
+-4492,
+-4309,
+-4096,
+-3853,
+-3579,
+-3276,
+-2942,
+-2578,
+-2185,
+-1763,
+-1313,
+-835,
+-330,
+200,
+755,
+1335,
+1937,
+2560,
+3203,
+3864,
+4543,
+5236,
+5942,
+6660,
+7387,
+8122,
+8863,
+9608,
+10354,
+11099,
+11842,
+12580,
+13311,
+14033,
+14745,
+15443,
+16125,
+16791,
+17436,
+18061,
+18663,
+19239,
+19789,
+20310,
+20801,
+21261,
+21687,
+22079,
+22435,
+22755,
+23037,
+23281,
+23485,
+23649,
+23772,
+23854,
+23896,
diff --git a/fir/c48000ntsc.scm b/fir/c48000ntsc.scm
new file mode 100644
index 00000000..53e3e3f2
--- /dev/null
+++ b/fir/c48000ntsc.scm
@@ -0,0 +1,12 @@
+(title "48000 NTSC")
+
+(verbose #t)
+
+(cosine-symmetry)
+(filter-length 1024)
+(sampling-frequency 1789772.727272727272)
+(limit-= (band 0 17000) 1)
+(limit-= (band 24000 894886.363636) 0 .5)
+(output-file "c48000ntsc.coef")
+(plot-file "c48000ntsc.plot")
+(go)
diff --git a/fir/c48000pal.coef b/fir/c48000pal.coef
new file mode 100644
index 00000000..818ab692
--- /dev/null
+++ b/fir/c48000pal.coef
@@ -0,0 +1,1039 @@
+;; ***** 48000 PAL *****
+;; Filter length: 1024
+;; Symmetry: cosine
+;; Sampling frequency: 1662607.125
+;; Grid density: 10257
+;; Deviation parameter: y=-4.04456123260461e-4
+;;
+;; Specifications:
+;; (limit > 24000 831303.5625 0 0.5)
+;; (limit < 24000 831303.5625 0 0.5)
+;; (limit > 0 17500 1 1)
+;; (limit < 0 17500 1 1)
+;;
+;; Coefficients:
+
+1.0783172932896e-4
+1.3561475850253e-5
+1.43150420416283e-5
+1.49886363377349e-5
+1.56015105099026e-5
+1.61381192401086e-5
+1.66025516801309e-5
+1.69644855111871e-5
+1.72420268548982e-5
+1.74096049850514e-5
+1.7466907549538e-5
+1.74305599416104e-5
+1.72624970620822e-5
+1.69512561328662e-5
+1.65342695578314e-5
+1.59775197454088e-5
+1.52766280693198e-5
+1.44428101292738e-5
+1.34684866379703e-5
+1.23509418255071e-5
+1.1081808312081e-5
+9.68440865212042e-6
+8.15580831379911e-6
+6.49256056198478e-6
+4.70330948990956e-6
+2.7936406340967e-6
+7.85613395286448e-7
+-1.32808013796309e-6
+-3.52876960484536e-6
+-5.8080561629844e-6
+-8.15813413487457e-6
+-1.05512845558752e-5
+-1.30105356059099e-5
+-1.54617489968656e-5
+-1.79517990398971e-5
+-2.04397035642729e-5
+-2.28952912040035e-5
+-2.53180967028265e-5
+-2.76813804395839e-5
+-2.99602884421574e-5
+-3.21440371766843e-5
+-3.42144286692688e-5
+-3.61550983136946e-5
+-3.7936448702778e-5
+-3.95673425206259e-5
+-4.10009072283261e-5
+-4.22696474647012e-5
+-4.330258187421e-5
+-4.41187219554721e-5
+-4.46550647769792e-5
+-4.49347491986505e-5
+-4.49183030848856e-5
+-4.46584800684937e-5
+-4.41642416915663e-5
+-4.33946068310562e-5
+-4.20871716501139e-5
+-4.07538528085648e-5
+-3.89585839480776e-5
+-3.69098747867203e-5
+-3.45543123183317e-5
+-3.18949347092464e-5
+-2.89523632049071e-5
+-2.57213276898428e-5
+-2.22202644601619e-5
+-1.84617206755275e-5
+-1.44991867492458e-5
+-1.02613766503818e-5
+-5.85405894330665e-6
+-1.27028212217224e-6
+3.4875707995152e-6
+8.36526659552602e-6
+1.33338533249663e-5
+1.8385703423788e-5
+2.34769030974947e-5
+2.85812390861387e-5
+3.36580878548364e-5
+3.86654975743835e-5
+4.3578901034037e-5
+4.83892064467925e-5
+5.29979535540185e-5
+5.74271144638819e-5
+6.16215703975737e-5
+6.55395388635905e-5
+6.91595354640541e-5
+7.24387952032281e-5
+7.53549961562705e-5
+7.78768810641327e-5
+7.99367008803979e-5
+8.15775690813463e-5
+8.27210398644824e-5
+8.336395615943e-5
+8.34873471492661e-5
+8.3069518826596e-5
+8.20987920151301e-5
+8.05698418267922e-5
+7.84588588088235e-5
+7.57790438357932e-5
+7.25271257954213e-5
+6.869107843266e-5
+6.42839469147515e-5
+5.93705790211257e-5
+5.38840838876231e-5
+4.7915115002444e-5
+4.14264390433695e-5
+3.44799673466393e-5
+2.70923034925926e-5
+1.93377097998663e-5
+1.12230483582735e-5
+2.77563609884032e-6
+-5.95253220278385e-6
+-1.48596469580734e-5
+-2.39905698155697e-5
+-3.31928444133421e-5
+-4.24774078883453e-5
+-5.17561952024819e-5
+-6.09681170673795e-5
+-7.00816711966441e-5
+-7.89965327587163e-5
+-8.76739937512259e-5
+-9.60257665780481e-5
+-1.040422410093e-4
+-1.1158288385138e-4
+-1.18671435004228e-4
+-1.25189526359341e-4
+-1.31095577074443e-4
+-1.3633898735937e-4
+-1.40872811972437e-4
+-1.44637497417931e-4
+-1.47604758781598e-4
+-1.49721217177156e-4
+-1.50937788247908e-4
+-1.51260723345739e-4
+-1.50640490277245e-4
+-1.49027129666833e-4
+-1.46478116043421e-4
+-1.4290837237091e-4
+-1.38355651240051e-4
+-1.32821684691922e-4
+-1.26301014847642e-4
+-1.18832774313583e-4
+-1.10412614981825e-4
+-1.01079807360939e-4
+-9.08863150937633e-5
+-7.9855536779786e-5
+-6.80420533998678e-5
+-5.55036002160919e-5
+-4.23070943880991e-5
+-2.85100491723636e-5
+-1.41910602190798e-5
+5.74159896625749e-7
+1.5685350087147e-5
+3.10821961290075e-5
+4.66746733164285e-5
+6.23410430656923e-5
+7.79838341733242e-5
+9.35400846529469e-5
+1.08858050814022e-4
+1.23885745586263e-4
+1.38490587292571e-4
+1.52569798991098e-4
+1.6602735554204e-4
+1.78757451082868e-4
+1.90662487656944e-4
+2.0165164397247e-4
+2.11641859228633e-4
+2.20511364369255e-4
+2.2822201475425e-4
+2.34662780276811e-4
+2.39770894383923e-4
+2.43490345927973e-4
+2.45765411178182e-4
+2.46534390337095e-4
+2.45775167592942e-4
+2.43426392718766e-4
+2.39499784238424e-4
+2.33967252721536e-4
+2.2684189259918e-4
+2.18093865253775e-4
+2.0779413468937e-4
+1.95927141401289e-4
+1.82552706187548e-4
+1.67719946286442e-4
+1.5149295655487e-4
+1.33932663941035e-4
+1.15116784735802e-4
+9.51630411589421e-5
+7.41353615298954e-5
+5.21718190054817e-5
+2.93810695999424e-5
+5.86942660727624e-6
+-1.81928117661243e-5
+-4.26953547177328e-5
+-6.74884760425993e-5
+-9.24000620732457e-5
+-1.17306452222934e-4
+-1.42028053706926e-4
+-1.6641748536327e-4
+-1.90295327481145e-4
+-2.13526648772877e-4
+-2.35920378174742e-4
+-2.57335540622496e-4
+-2.77618149216888e-4
+-2.96599532917617e-4
+-3.14140693377271e-4
+-3.30094800932447e-4
+-3.44339603052102e-4
+-3.56739336123611e-4
+-3.67174212136651e-4
+-3.75531849424532e-4
+-3.81724589486029e-4
+-3.85657939336761e-4
+-3.87265732840677e-4
+-3.86491839797252e-4
+-3.83275416154692e-4
+-3.7760973646446e-4
+-3.69439578879e-4
+-3.58799773629522e-4
+-3.45691587198199e-4
+-3.30143612933627e-4
+-3.12196804269503e-4
+-2.91948940195075e-4
+-2.6941592693139e-4
+-2.4475129607813e-4
+-2.18033329216043e-4
+-1.89400291263887e-4
+-1.59001839727708e-4
+-1.26964645968482e-4
+-9.3468599675526e-5
+-5.87099485768434e-5
+-2.28718895559617e-5
+1.38661453336005e-5
+5.12504716648456e-5
+8.90765541567582e-5
+1.27141536384486e-4
+1.6517131814265e-4
+2.02945866294048e-4
+2.40219213745026e-4
+2.76746123957115e-4
+3.12293133420806e-4
+3.46593092375836e-4
+3.79424363443158e-4
+4.1054132937402e-4
+4.39736117650459e-4
+4.66739582083122e-4
+4.91387907517869e-4
+5.1345669379648e-4
+5.32755361807803e-4
+5.4909940710768e-4
+5.62348662402172e-4
+5.72345993122783e-4
+5.7896654574189e-4
+5.82090419479584e-4
+5.81654406347142e-4
+5.77562548184356e-4
+5.69788762315823e-4
+5.58298302006844e-4
+5.43090048796913e-4
+5.24193502963293e-4
+5.0164051079223e-4
+4.75510033518712e-4
+4.45905690887374e-4
+4.12931250800377e-4
+3.76718492573694e-4
+3.37454368210552e-4
+2.95309158288872e-4
+2.50487407773454e-4
+2.03239263665977e-4
+1.53785113286668e-4
+1.02426054275038e-4
+4.94039771196527e-5
+-4.9436684286017e-6
+-6.03298616514903e-5
+-1.16406402480797e-4
+-1.72843182266513e-4
+-2.29302160827241e-4
+-2.85424280783829e-4
+-3.40849878416515e-4
+-3.95231606514409e-4
+-4.4818593119753e-4
+-4.99366108188115e-4
+-5.48439341418767e-4
+-5.95017923651795e-4
+-6.38796736934187e-4
+-6.79430579536826e-4
+-7.16620285053831e-4
+-7.50034221495514e-4
+-7.79437560472454e-4
+-8.0454137082786e-4
+-8.25108701083097e-4
+-8.40934131367373e-4
+-8.51820948123654e-4
+-8.57609584970445e-4
+-8.58175472793311e-4
+-8.53390483100241e-4
+-8.43209551079894e-4
+-8.27590879655203e-4
+-8.06510409502537e-4
+-7.79995072230027e-4
+-7.48155417238511e-4
+-7.11020274128235e-4
+-6.68770312317841e-4
+-6.21544132125251e-4
+-5.69560032134081e-4
+-5.13047603992703e-4
+-4.52260267743927e-4
+-3.87511758268314e-4
+-3.19128561449503e-4
+-2.47461748174838e-4
+-1.72891786174927e-4
+-9.58451800481746e-5
+-1.67437726740921e-5
+6.39622864075221e-5
+1.45802914515735e-4
+2.28276969072054e-4
+3.10881168326302e-4
+3.931285095721e-4
+4.74478553853189e-4
+5.54406623481691e-4
+6.32405031540309e-4
+7.07946519860834e-4
+7.80505190513501e-4
+8.49580370607698e-4
+9.14664923660729e-4
+9.75306400682111e-4
+0.00103102014646356
+0.00108137261722973
+0.00112594391364669
+0.00116436209978936
+0.00119625989249914
+0.00122130266875817
+0.00123924969043022
+0.00124980344180312
+0.00125278240951216
+0.00124802165372955
+0.00123540269762469
+0.00121484756393481
+0.0011863534276383
+0.00114991049765994
+0.00110562855369365
+0.0010536068934269
+9.94030202153522e-4
+9.27120376158647e-4
+8.53156860257162e-4
+7.72454365212224e-4
+6.85390250514192e-4
+5.92375082207849e-4
+4.9387876727933e-4
+3.90393002098172e-4
+2.82480107088887e-4
+1.7070831244188e-4
+5.56879005104824e-5
+-6.1906284350905e-5
+-1.81415283544607e-4
+-3.02142730803428e-4
+-4.2333875391934e-4
+-5.44296445422888e-4
+-6.64236400947683e-4
+-7.82407565044765e-4
+-8.98051026608098e-4
+-0.00101038113005766
+-0.00111866302268561
+-0.0012221295410412
+-0.0013200609608465
+-0.00141171609738229
+-0.00149643580490023
+-0.00157354248105082
+-0.00164240522652266
+-0.00170243934737355
+-0.00175309370471778
+-0.00179387496858474
+-0.00182430930810295
+-0.00184402395447169
+-0.00185266724915187
+-0.00184997271570004
+-0.00183570586409282
+-0.00180972121663046
+-0.00177195203127539
+-0.00172237368010418
+-0.00166105454652476
+-0.00158811703816067
+-0.00150378726049984
+-0.00140832762076639
+-0.0013020899508538
+-0.00118551225223178
+-0.00105910322772149
+-9.23393236851473e-4
+-7.79055327805226e-4
+-6.26768212465557e-4
+-4.67302931140705e-4
+-3.01491270723501e-4
+-1.30195855297908e-4
+4.56401652766111e-5
+2.25027067508283e-4
+4.06972972690671e-4
+5.90405019516109e-4
+7.74216306706467e-4
+9.57318662226946e-4
+0.00113855626997318
+0.00131678634527204
+0.0014908552858621
+0.00165959118483483
+0.00182185835208505
+0.00197650815267658
+0.00212242280398454
+0.00225851246246872
+0.00238371539035943
+0.00249702508323125
+0.00259744117052929
+0.0026840846677887
+0.00275607645257497
+0.00281263432325704
+0.0028530403230186
+0.0028766569205693
+0.00288293135970344
+0.00287140344532155
+0.00284168448509905
+0.00279352301691183
+0.00272673120228367
+0.00264124885341234
+0.00253711261587615
+0.00241447127968604
+0.00227360193577821
+0.00211485651002808
+0.00193873386299929
+0.00174582789013106
+0.00153686167145326
+0.00131264246333188
+0.00107412717117761
+8.22324668075117e-4
+5.58399255126717e-4
+2.83585936906761e-4
+-7.91653518883316e-7
+-2.93275867453424e-4
+-5.92385560905748e-4
+-8.96504293668282e-4
+-0.0012039962137455
+-0.00151310994118933
+-0.00182206762040076
+-0.00212903602637386
+-0.00243213041621861
+-0.00272944724644087
+-0.00301904353935261
+-0.0032989847822554
+-0.00356729741889108
+-0.00382205238995045
+-0.0040612825745775
+-0.00428310710833949
+-0.0044856335950343
+-0.00466702696411301
+-0.00482550437652975
+-0.0049593584042375
+-0.00506692577218407
+-0.00514666052596478
+-0.0051970785659304
+-0.00521680784237087
+-0.0052045920045337
+-0.00515926816288351
+-0.00507981542203718
+-0.00496534580148461
+-0.00481509247434497
+-0.00462843395985089
+-0.00440489964062938
+-0.00414419512168892
+-0.0038461191704701
+-0.00351070824147442
+-0.00313809095768648
+-0.00272861114037865
+-0.00228275272798312
+-0.0018011488246512
+-0.00128463575154861
+-7.34189492529516e-4
+-1.50939392418879e-4
+4.63827670998463e-4
+0.001108634043237
+0.00178191442074677
+0.00248189327531725
+0.00320672778303872
+0.0039543772472654
+0.00472272054027297
+0.0055095123033422
+0.00631238695466698
+0.00712888111691215
+0.00795646562805878
+0.0087925100600243
+0.00963433252114155
+0.0104791770461524
+0.0113242494156599
+0.0121667411979553
+0.0130037845552242
+0.0138325371327049
+0.0146501343342719
+0.015453752838051
+0.0162405643560213
+0.0170077895549428
+0.017752734005397
+0.0184727026611722
+0.0191651536375909
+0.0198275436619083
+0.0204575091596416
+0.0210527297897325
+0.021611049283905
+0.0221303981307109
+0.0226088947033753
+0.0230447502475501
+0.023436353984896
+0.0237822666417811
+0.0240811879818443
+0.0243320190632054
+0.0245338129670568
+0.0246858223616
+0.0247874779906384
+0.0248384026328523
+0.0248384026328523
+0.0247874779906384
+0.0246858223616
+0.0245338129670568
+0.0243320190632054
+0.0240811879818443
+0.0237822666417811
+0.023436353984896
+0.0230447502475501
+0.0226088947033753
+0.0221303981307109
+0.021611049283905
+0.0210527297897325
+0.0204575091596416
+0.0198275436619083
+0.0191651536375909
+0.0184727026611722
+0.017752734005397
+0.0170077895549428
+0.0162405643560213
+0.015453752838051
+0.0146501343342719
+0.0138325371327049
+0.0130037845552242
+0.0121667411979553
+0.0113242494156599
+0.0104791770461524
+0.00963433252114155
+0.0087925100600243
+0.00795646562805878
+0.00712888111691215
+0.00631238695466698
+0.0055095123033422
+0.00472272054027297
+0.0039543772472654
+0.00320672778303872
+0.00248189327531725
+0.00178191442074677
+0.001108634043237
+4.63827670998463e-4
+-1.50939392418879e-4
+-7.34189492529516e-4
+-0.00128463575154861
+-0.0018011488246512
+-0.00228275272798312
+-0.00272861114037865
+-0.00313809095768648
+-0.00351070824147442
+-0.0038461191704701
+-0.00414419512168892
+-0.00440489964062938
+-0.00462843395985089
+-0.00481509247434497
+-0.00496534580148461
+-0.00507981542203718
+-0.00515926816288351
+-0.0052045920045337
+-0.00521680784237087
+-0.0051970785659304
+-0.00514666052596478
+-0.00506692577218407
+-0.0049593584042375
+-0.00482550437652975
+-0.00466702696411301
+-0.0044856335950343
+-0.00428310710833949
+-0.0040612825745775
+-0.00382205238995045
+-0.00356729741889108
+-0.0032989847822554
+-0.00301904353935261
+-0.00272944724644087
+-0.00243213041621861
+-0.00212903602637386
+-0.00182206762040076
+-0.00151310994118933
+-0.0012039962137455
+-8.96504293668282e-4
+-5.92385560905748e-4
+-2.93275867453424e-4
+-7.91653518883316e-7
+2.83585936906761e-4
+5.58399255126717e-4
+8.22324668075117e-4
+0.00107412717117761
+0.00131264246333188
+0.00153686167145326
+0.00174582789013106
+0.00193873386299929
+0.00211485651002808
+0.00227360193577821
+0.00241447127968604
+0.00253711261587615
+0.00264124885341234
+0.00272673120228367
+0.00279352301691183
+0.00284168448509905
+0.00287140344532155
+0.00288293135970344
+0.0028766569205693
+0.0028530403230186
+0.00281263432325704
+0.00275607645257497
+0.0026840846677887
+0.00259744117052929
+0.00249702508323125
+0.00238371539035943
+0.00225851246246872
+0.00212242280398454
+0.00197650815267658
+0.00182185835208505
+0.00165959118483483
+0.0014908552858621
+0.00131678634527204
+0.00113855626997318
+9.57318662226946e-4
+7.74216306706467e-4
+5.90405019516109e-4
+4.06972972690671e-4
+2.25027067508283e-4
+4.56401652766111e-5
+-1.30195855297908e-4
+-3.01491270723501e-4
+-4.67302931140705e-4
+-6.26768212465557e-4
+-7.79055327805226e-4
+-9.23393236851473e-4
+-0.00105910322772149
+-0.00118551225223178
+-0.0013020899508538
+-0.00140832762076639
+-0.00150378726049984
+-0.00158811703816067
+-0.00166105454652476
+-0.00172237368010418
+-0.00177195203127539
+-0.00180972121663046
+-0.00183570586409282
+-0.00184997271570004
+-0.00185266724915187
+-0.00184402395447169
+-0.00182430930810295
+-0.00179387496858474
+-0.00175309370471778
+-0.00170243934737355
+-0.00164240522652266
+-0.00157354248105082
+-0.00149643580490023
+-0.00141171609738229
+-0.0013200609608465
+-0.0012221295410412
+-0.00111866302268561
+-0.00101038113005766
+-8.98051026608098e-4
+-7.82407565044765e-4
+-6.64236400947683e-4
+-5.44296445422888e-4
+-4.2333875391934e-4
+-3.02142730803428e-4
+-1.81415283544607e-4
+-6.1906284350905e-5
+5.56879005104824e-5
+1.7070831244188e-4
+2.82480107088887e-4
+3.90393002098172e-4
+4.9387876727933e-4
+5.92375082207849e-4
+6.85390250514192e-4
+7.72454365212224e-4
+8.53156860257162e-4
+9.27120376158647e-4
+9.94030202153522e-4
+0.0010536068934269
+0.00110562855369365
+0.00114991049765994
+0.0011863534276383
+0.00121484756393481
+0.00123540269762469
+0.00124802165372955
+0.00125278240951216
+0.00124980344180312
+0.00123924969043022
+0.00122130266875817
+0.00119625989249914
+0.00116436209978936
+0.00112594391364669
+0.00108137261722973
+0.00103102014646356
+9.75306400682111e-4
+9.14664923660729e-4
+8.49580370607698e-4
+7.80505190513501e-4
+7.07946519860834e-4
+6.32405031540309e-4
+5.54406623481691e-4
+4.74478553853189e-4
+3.931285095721e-4
+3.10881168326302e-4
+2.28276969072054e-4
+1.45802914515735e-4
+6.39622864075221e-5
+-1.67437726740921e-5
+-9.58451800481746e-5
+-1.72891786174927e-4
+-2.47461748174838e-4
+-3.19128561449503e-4
+-3.87511758268314e-4
+-4.52260267743927e-4
+-5.13047603992703e-4
+-5.69560032134081e-4
+-6.21544132125251e-4
+-6.68770312317841e-4
+-7.11020274128235e-4
+-7.48155417238511e-4
+-7.79995072230027e-4
+-8.06510409502537e-4
+-8.27590879655203e-4
+-8.43209551079894e-4
+-8.53390483100241e-4
+-8.58175472793311e-4
+-8.57609584970445e-4
+-8.51820948123654e-4
+-8.40934131367373e-4
+-8.25108701083097e-4
+-8.0454137082786e-4
+-7.79437560472454e-4
+-7.50034221495514e-4
+-7.16620285053831e-4
+-6.79430579536826e-4
+-6.38796736934187e-4
+-5.95017923651795e-4
+-5.48439341418767e-4
+-4.99366108188115e-4
+-4.4818593119753e-4
+-3.95231606514409e-4
+-3.40849878416515e-4
+-2.85424280783829e-4
+-2.29302160827241e-4
+-1.72843182266513e-4
+-1.16406402480797e-4
+-6.03298616514903e-5
+-4.9436684286017e-6
+4.94039771196527e-5
+1.02426054275038e-4
+1.53785113286668e-4
+2.03239263665977e-4
+2.50487407773454e-4
+2.95309158288872e-4
+3.37454368210552e-4
+3.76718492573694e-4
+4.12931250800377e-4
+4.45905690887374e-4
+4.75510033518712e-4
+5.0164051079223e-4
+5.24193502963293e-4
+5.43090048796913e-4
+5.58298302006844e-4
+5.69788762315823e-4
+5.77562548184356e-4
+5.81654406347142e-4
+5.82090419479584e-4
+5.7896654574189e-4
+5.72345993122783e-4
+5.62348662402172e-4
+5.4909940710768e-4
+5.32755361807803e-4
+5.1345669379648e-4
+4.91387907517869e-4
+4.66739582083122e-4
+4.39736117650459e-4
+4.1054132937402e-4
+3.79424363443158e-4
+3.46593092375836e-4
+3.12293133420806e-4
+2.76746123957115e-4
+2.40219213745026e-4
+2.02945866294048e-4
+1.6517131814265e-4
+1.27141536384486e-4
+8.90765541567582e-5
+5.12504716648456e-5
+1.38661453336005e-5
+-2.28718895559617e-5
+-5.87099485768434e-5
+-9.3468599675526e-5
+-1.26964645968482e-4
+-1.59001839727708e-4
+-1.89400291263887e-4
+-2.18033329216043e-4
+-2.4475129607813e-4
+-2.6941592693139e-4
+-2.91948940195075e-4
+-3.12196804269503e-4
+-3.30143612933627e-4
+-3.45691587198199e-4
+-3.58799773629522e-4
+-3.69439578879e-4
+-3.7760973646446e-4
+-3.83275416154692e-4
+-3.86491839797252e-4
+-3.87265732840677e-4
+-3.85657939336761e-4
+-3.81724589486029e-4
+-3.75531849424532e-4
+-3.67174212136651e-4
+-3.56739336123611e-4
+-3.44339603052102e-4
+-3.30094800932447e-4
+-3.14140693377271e-4
+-2.96599532917617e-4
+-2.77618149216888e-4
+-2.57335540622496e-4
+-2.35920378174742e-4
+-2.13526648772877e-4
+-1.90295327481145e-4
+-1.6641748536327e-4
+-1.42028053706926e-4
+-1.17306452222934e-4
+-9.24000620732457e-5
+-6.74884760425993e-5
+-4.26953547177328e-5
+-1.81928117661243e-5
+5.86942660727624e-6
+2.93810695999424e-5
+5.21718190054817e-5
+7.41353615298954e-5
+9.51630411589421e-5
+1.15116784735802e-4
+1.33932663941035e-4
+1.5149295655487e-4
+1.67719946286442e-4
+1.82552706187548e-4
+1.95927141401289e-4
+2.0779413468937e-4
+2.18093865253775e-4
+2.2684189259918e-4
+2.33967252721536e-4
+2.39499784238424e-4
+2.43426392718766e-4
+2.45775167592942e-4
+2.46534390337095e-4
+2.45765411178182e-4
+2.43490345927973e-4
+2.39770894383923e-4
+2.34662780276811e-4
+2.2822201475425e-4
+2.20511364369255e-4
+2.11641859228633e-4
+2.0165164397247e-4
+1.90662487656944e-4
+1.78757451082868e-4
+1.6602735554204e-4
+1.52569798991098e-4
+1.38490587292571e-4
+1.23885745586263e-4
+1.08858050814022e-4
+9.35400846529469e-5
+7.79838341733242e-5
+6.23410430656923e-5
+4.66746733164285e-5
+3.10821961290075e-5
+1.5685350087147e-5
+5.74159896625749e-7
+-1.41910602190798e-5
+-2.85100491723636e-5
+-4.23070943880991e-5
+-5.55036002160919e-5
+-6.80420533998678e-5
+-7.9855536779786e-5
+-9.08863150937633e-5
+-1.01079807360939e-4
+-1.10412614981825e-4
+-1.18832774313583e-4
+-1.26301014847642e-4
+-1.32821684691922e-4
+-1.38355651240051e-4
+-1.4290837237091e-4
+-1.46478116043421e-4
+-1.49027129666833e-4
+-1.50640490277245e-4
+-1.51260723345739e-4
+-1.50937788247908e-4
+-1.49721217177156e-4
+-1.47604758781598e-4
+-1.44637497417931e-4
+-1.40872811972437e-4
+-1.3633898735937e-4
+-1.31095577074443e-4
+-1.25189526359341e-4
+-1.18671435004228e-4
+-1.1158288385138e-4
+-1.040422410093e-4
+-9.60257665780481e-5
+-8.76739937512259e-5
+-7.89965327587163e-5
+-7.00816711966441e-5
+-6.09681170673795e-5
+-5.17561952024819e-5
+-4.24774078883453e-5
+-3.31928444133421e-5
+-2.39905698155697e-5
+-1.48596469580734e-5
+-5.95253220278385e-6
+2.77563609884032e-6
+1.12230483582735e-5
+1.93377097998663e-5
+2.70923034925926e-5
+3.44799673466393e-5
+4.14264390433695e-5
+4.7915115002444e-5
+5.38840838876231e-5
+5.93705790211257e-5
+6.42839469147515e-5
+6.869107843266e-5
+7.25271257954213e-5
+7.57790438357932e-5
+7.84588588088235e-5
+8.05698418267922e-5
+8.20987920151301e-5
+8.3069518826596e-5
+8.34873471492661e-5
+8.336395615943e-5
+8.27210398644824e-5
+8.15775690813463e-5
+7.99367008803979e-5
+7.78768810641327e-5
+7.53549961562705e-5
+7.24387952032281e-5
+6.91595354640541e-5
+6.55395388635905e-5
+6.16215703975737e-5
+5.74271144638819e-5
+5.29979535540185e-5
+4.83892064467925e-5
+4.3578901034037e-5
+3.86654975743835e-5
+3.36580878548364e-5
+2.85812390861387e-5
+2.34769030974947e-5
+1.8385703423788e-5
+1.33338533249663e-5
+8.36526659552602e-6
+3.4875707995152e-6
+-1.27028212217224e-6
+-5.85405894330665e-6
+-1.02613766503818e-5
+-1.44991867492458e-5
+-1.84617206755275e-5
+-2.22202644601619e-5
+-2.57213276898428e-5
+-2.89523632049071e-5
+-3.18949347092464e-5
+-3.45543123183317e-5
+-3.69098747867203e-5
+-3.89585839480776e-5
+-4.07538528085648e-5
+-4.20871716501139e-5
+-4.33946068310562e-5
+-4.41642416915663e-5
+-4.46584800684937e-5
+-4.49183030848856e-5
+-4.49347491986505e-5
+-4.46550647769792e-5
+-4.41187219554721e-5
+-4.330258187421e-5
+-4.22696474647012e-5
+-4.10009072283261e-5
+-3.95673425206259e-5
+-3.7936448702778e-5
+-3.61550983136946e-5
+-3.42144286692688e-5
+-3.21440371766843e-5
+-2.99602884421574e-5
+-2.76813804395839e-5
+-2.53180967028265e-5
+-2.28952912040035e-5
+-2.04397035642729e-5
+-1.79517990398971e-5
+-1.54617489968656e-5
+-1.30105356059099e-5
+-1.05512845558752e-5
+-8.15813413487457e-6
+-5.8080561629844e-6
+-3.52876960484536e-6
+-1.32808013796309e-6
+7.85613395286448e-7
+2.7936406340967e-6
+4.70330948990956e-6
+6.49256056198478e-6
+8.15580831379911e-6
+9.68440865212042e-6
+1.1081808312081e-5
+1.23509418255071e-5
+1.34684866379703e-5
+1.44428101292738e-5
+1.52766280693198e-5
+1.59775197454088e-5
+1.65342695578314e-5
+1.69512561328662e-5
+1.72624970620822e-5
+1.74305599416104e-5
+1.7466907549538e-5
+1.74096049850514e-5
+1.72420268548982e-5
+1.69644855111871e-5
+1.66025516801309e-5
+1.61381192401086e-5
+1.56015105099026e-5
+1.49886363377349e-5
+1.43150420416283e-5
+1.3561475850253e-5
+1.0783172932896e-4
diff --git a/fir/c48000pal.h b/fir/c48000pal.h
new file mode 100644
index 00000000..ce2e9e80
--- /dev/null
+++ b/fir/c48000pal.h
@@ -0,0 +1,512 @@
+113,
+14,
+15,
+15,
+16,
+16,
+17,
+17,
+18,
+18,
+18,
+18,
+18,
+17,
+17,
+16,
+16,
+15,
+14,
+12,
+11,
+10,
+8,
+6,
+4,
+2,
+0,
+-1,
+-3,
+-6,
+-8,
+-11,
+-13,
+-16,
+-18,
+-21,
+-24,
+-26,
+-29,
+-31,
+-33,
+-35,
+-37,
+-39,
+-41,
+-42,
+-44,
+-45,
+-46,
+-46,
+-47,
+-47,
+-46,
+-46,
+-45,
+-44,
+-42,
+-40,
+-38,
+-36,
+-33,
+-30,
+-26,
+-23,
+-19,
+-15,
+-10,
+-6,
+-1,
+3,
+8,
+13,
+19,
+24,
+29,
+35,
+40,
+45,
+50,
+55,
+60,
+64,
+68,
+72,
+75,
+79,
+81,
+83,
+85,
+86,
+87,
+87,
+87,
+86,
+84,
+82,
+79,
+76,
+72,
+67,
+62,
+56,
+50,
+43,
+36,
+28,
+20,
+11,
+2,
+-6,
+-15,
+-25,
+-34,
+-44,
+-54,
+-63,
+-73,
+-82,
+-91,
+-100,
+-109,
+-117,
+-124,
+-131,
+-137,
+-142,
+-147,
+-151,
+-154,
+-156,
+-158,
+-158,
+-157,
+-156,
+-153,
+-149,
+-145,
+-139,
+-132,
+-124,
+-115,
+-105,
+-95,
+-83,
+-71,
+-58,
+-44,
+-29,
+-14,
+0,
+16,
+32,
+48,
+65,
+81,
+98,
+114,
+129,
+145,
+159,
+174,
+187,
+199,
+211,
+221,
+231,
+239,
+246,
+251,
+255,
+257,
+258,
+257,
+255,
+251,
+245,
+237,
+228,
+217,
+205,
+191,
+175,
+158,
+140,
+120,
+99,
+77,
+54,
+30,
+6,
+-19,
+-44,
+-70,
+-96,
+-123,
+-148,
+-174,
+-199,
+-223,
+-247,
+-269,
+-291,
+-311,
+-329,
+-346,
+-361,
+-374,
+-385,
+-393,
+-400,
+-404,
+-406,
+-405,
+-401,
+-395,
+-387,
+-376,
+-362,
+-346,
+-327,
+-306,
+-282,
+-256,
+-228,
+-198,
+-166,
+-133,
+-98,
+-61,
+-23,
+14,
+53,
+93,
+133,
+173,
+212,
+251,
+290,
+327,
+363,
+397,
+430,
+461,
+489,
+515,
+538,
+558,
+575,
+589,
+600,
+607,
+610,
+609,
+605,
+597,
+585,
+569,
+549,
+526,
+498,
+467,
+432,
+395,
+353,
+309,
+262,
+213,
+161,
+107,
+51,
+-5,
+-63,
+-122,
+-181,
+-240,
+-299,
+-357,
+-414,
+-469,
+-523,
+-575,
+-623,
+-669,
+-712,
+-751,
+-786,
+-817,
+-843,
+-865,
+-881,
+-893,
+-899,
+-899,
+-894,
+-884,
+-867,
+-845,
+-817,
+-784,
+-745,
+-701,
+-651,
+-597,
+-537,
+-474,
+-406,
+-334,
+-259,
+-181,
+-100,
+-17,
+67,
+152,
+239,
+325,
+412,
+497,
+581,
+663,
+742,
+818,
+890,
+959,
+1022,
+1081,
+1133,
+1180,
+1220,
+1254,
+1280,
+1299,
+1310,
+1313,
+1308,
+1295,
+1273,
+1243,
+1205,
+1159,
+1104,
+1042,
+972,
+894,
+809,
+718,
+621,
+517,
+409,
+296,
+179,
+58,
+-64,
+-190,
+-316,
+-443,
+-570,
+-696,
+-820,
+-941,
+-1059,
+-1173,
+-1281,
+-1384,
+-1480,
+-1569,
+-1649,
+-1722,
+-1785,
+-1838,
+-1881,
+-1912,
+-1933,
+-1942,
+-1939,
+-1924,
+-1897,
+-1858,
+-1806,
+-1741,
+-1665,
+-1576,
+-1476,
+-1365,
+-1243,
+-1110,
+-968,
+-816,
+-657,
+-490,
+-316,
+-136,
+47,
+235,
+426,
+619,
+811,
+1003,
+1193,
+1380,
+1563,
+1740,
+1910,
+2072,
+2225,
+2368,
+2499,
+2618,
+2723,
+2814,
+2889,
+2949,
+2991,
+3016,
+3022,
+3010,
+2979,
+2929,
+2859,
+2769,
+2660,
+2531,
+2384,
+2217,
+2032,
+1830,
+1611,
+1376,
+1126,
+862,
+585,
+297,
+0,
+-307,
+-621,
+-940,
+-1262,
+-1586,
+-1910,
+-2232,
+-2550,
+-2862,
+-3165,
+-3459,
+-3740,
+-4007,
+-4258,
+-4491,
+-4703,
+-4893,
+-5059,
+-5200,
+-5313,
+-5396,
+-5449,
+-5470,
+-5457,
+-5409,
+-5326,
+-5206,
+-5048,
+-4853,
+-4618,
+-4345,
+-4032,
+-3681,
+-3290,
+-2861,
+-2393,
+-1888,
+-1347,
+-769,
+-158,
+486,
+1162,
+1868,
+2602,
+3362,
+4146,
+4952,
+5777,
+6619,
+7475,
+8342,
+9219,
+10102,
+10988,
+11874,
+12757,
+13635,
+14504,
+15361,
+16204,
+17029,
+17833,
+18615,
+19370,
+20096,
+20790,
+21451,
+22075,
+22660,
+23205,
+23707,
+24164,
+24574,
+24937,
+25250,
+25513,
+25725,
+25884,
+25991,
+26044,
diff --git a/fir/c48000pal.scm b/fir/c48000pal.scm
new file mode 100644
index 00000000..6feaea9b
--- /dev/null
+++ b/fir/c48000pal.scm
@@ -0,0 +1,12 @@
+(title "48000 PAL")
+
+(verbose #t)
+
+(cosine-symmetry)
+(filter-length 1024)
+(sampling-frequency 1662607.125)
+(limit-= (band 0 17500) 1)
+(limit-= (band 24000 831303.5625) 0 .5)
+(output-file "c48000pal.coef")
+(plot-file "c48000pal.plot")
+(go)
diff --git a/fir/c96000ntsc.coef b/fir/c96000ntsc.coef
new file mode 100644
index 00000000..e2b1469d
--- /dev/null
+++ b/fir/c96000ntsc.coef
@@ -0,0 +1,1039 @@
+;; ***** 96000 NTSC *****
+;; Filter length: 1024
+;; Symmetry: cosine
+;; Sampling frequency: 1789772.72727273
+;; Grid density: 10257
+;; Deviation parameter: y=-3.41994150089587e-6
+;;
+;; Specifications:
+;; (limit > 48000 894886.363636 0 0.5)
+;; (limit < 48000 894886.363636 0 0.5)
+;; (limit > 0 36000 1 1)
+;; (limit < 0 36000 1 1)
+;;
+;; Coefficients:
+
+6.25765784406859e-7
+-5.74349474884059e-7
+-4.38563052056152e-7
+-4.2275208095965e-7
+-4.22986843582035e-7
+-4.62591739880567e-7
+-4.87548260748437e-7
+-5.09702102203457e-7
+-5.53575138212173e-7
+-5.58776629837758e-7
+-5.61504899335206e-7
+-5.87512127558038e-7
+-5.61361967225389e-7
+-5.3712751262779e-7
+-5.01344341031087e-7
+-4.53511011468631e-7
+-3.38624331418706e-7
+-2.44517851394823e-7
+-1.54707945258839e-7
+-5.05264098238236e-9
+1.44876241366308e-7
+2.81681324083492e-7
+4.3227430974949e-7
+6.00075575484758e-7
+7.75112423789865e-7
+9.21520058445204e-7
+1.09935217260167e-6
+1.25500772923897e-6
+1.34551951148203e-6
+1.46860535142565e-6
+1.55182559228546e-6
+1.60770440406623e-6
+1.6294811644839e-6
+1.61363975974438e-6
+1.53782569699597e-6
+1.43132387640668e-6
+1.28959869628182e-6
+1.10621331781889e-6
+8.5785768415765e-7
+6.04567255230193e-7
+2.96426729531177e-7
+-5.24862218589967e-8
+-4.3476366150865e-7
+-8.17500360283736e-7
+-1.21281774093872e-6
+-1.6246903514035e-6
+-2.03191995568737e-6
+-2.42034886505034e-6
+-2.77710918199585e-6
+-3.08872255757467e-6
+-3.34868062209883e-6
+-3.54951933335568e-6
+-3.67684205210421e-6
+-3.75096178007138e-6
+-3.73781668478926e-6
+-3.62820827681515e-6
+-3.40106555337159e-6
+-3.10558378787101e-6
+-2.73085981209485e-6
+-2.23880629643428e-6
+-1.66299764538256e-6
+-1.01450351451109e-6
+-2.9897580679925e-7
+4.778230486617e-7
+1.30134942732076e-6
+2.15698996474846e-6
+3.01139455704895e-6
+3.83150595451006e-6
+4.6486553085021e-6
+5.39866854742161e-6
+6.0633779344053e-6
+6.64505288826461e-6
+7.10620984925846e-6
+7.42554420262448e-6
+7.5921592957585e-6
+7.59604323829658e-6
+7.4322223638238e-6
+7.07019338593616e-6
+6.5530535251783e-6
+5.81138982456196e-6
+4.93125339021914e-6
+3.84118987018593e-6
+2.62399132900517e-6
+1.28261796938256e-6
+-1.84404808868073e-7
+-1.73983144001699e-6
+-3.33935604298266e-6
+-4.96530162809768e-6
+-6.55816909846896e-6
+-8.09156481962559e-6
+-9.54514698333832e-6
+-1.08541688245874e-5
+-1.19812039266178e-5
+-1.29258356094021e-5
+-1.35864741790705e-5
+-1.40143363153509e-5
+-1.41096581487199e-5
+-1.39167543346076e-5
+-1.33693589565357e-5
+-1.25232516456216e-5
+-1.12945331543608e-5
+-9.75795645920384e-6
+-7.94061043444157e-6
+-5.82669848029968e-6
+-3.46810975732889e-6
+-8.98080427581192e-7
+1.83157780808837e-6
+4.65462384661346e-6
+7.49499200727654e-6
+1.03647465427585e-5
+1.31179949559878e-5
+1.57239303578456e-5
+1.80905523657776e-5
+2.0183001663178e-5
+2.19109883335264e-5
+2.3237064442004e-5
+2.41135213673391e-5
+2.44756148778194e-5
+2.42814484952927e-5
+2.35477964026005e-5
+2.22346916834176e-5
+2.03698259249784e-5
+1.79397096215955e-5
+1.49707237863667e-5
+1.15270292808691e-5
+7.67266645113299e-6
+3.44948129599163e-6
+-1.07237403409055e-6
+-5.75008290742105e-6
+-1.05566723150875e-5
+-1.53239936200644e-5
+-1.99867517520571e-5
+-2.44092890499766e-5
+-2.8476946106292e-5
+-3.21077759116387e-5
+-3.51664827487924e-5
+-3.75869046571029e-5
+-3.92567099728606e-5
+-4.01135752080094e-5
+-4.01278786536825e-5
+-3.92125256039437e-5
+-3.73919246991607e-5
+-3.46200271022937e-5
+-3.09755908244563e-5
+-2.64479100675461e-5
+-2.11542725315722e-5
+-1.50963566347366e-5
+-8.47653619728616e-6
+-1.37057784993502e-6
+6.08602710173464e-6
+1.37140404419924e-5
+2.13787482610813e-5
+2.88933776644191e-5
+3.60545970430637e-5
+4.27456382286692e-5
+4.87313166822799e-5
+5.38887103915501e-5
+5.8058617211836e-5
+6.10944817720679e-5
+6.28816258498489e-5
+6.3320088392269e-5
+6.2383362148182e-5
+5.99917552478514e-5
+5.61760181265976e-5
+5.08935610500647e-5
+4.42950092732983e-5
+3.6439179398353e-5
+2.74298095627849e-5
+1.74547874668573e-5
+6.66515424198749e-6
+-4.68762174381739e-6
+-1.63848253814674e-5
+-2.8182112834728e-5
+-3.98156943957032e-5
+-5.10302848833116e-5
+-6.15260332171321e-5
+-7.10668055624751e-5
+-7.9381160780839e-5
+-8.6241178990473e-5
+-9.14514657680923e-5
+-9.48068546980327e-5
+-9.61699375283378e-5
+-9.54489884121157e-5
+-9.25431334779362e-5
+-8.74787550676798e-5
+-8.02605459808726e-5
+-7.09737795002089e-5
+-5.97576234894939e-5
+-4.67784017657438e-5
+-3.22960637446588e-5
+-1.65036203311736e-5
+1.8211835731409e-7
+1.75262241794632e-5
+3.50927801023099e-5
+5.25300164078023e-5
+6.94390025027894e-5
+8.53884090898411e-5
+1.00039703633977e-4
+1.12981102411937e-4
+1.23877401105374e-4
+1.32393120309911e-4
+1.38242615396576e-4
+1.41266585644598e-4
+1.4121817567785e-4
+1.38042535292926e-4
+1.31649152408872e-4
+1.22120271607441e-4
+1.09537433110581e-4
+9.40746256399753e-5
+7.59553413177967e-5
+5.55488335464633e-5
+3.31799427308997e-5
+9.3129309380048e-6
+-1.55984918923049e-5
+-4.10035600300493e-5
+-6.63607029679837e-5
+-9.11217498548619e-5
+-1.14693160653602e-4
+-1.3649515371509e-4
+-1.56012871346288e-4
+-1.72712890799109e-4
+-1.86143587824593e-4
+-1.95867813754568e-4
+-2.01564656263033e-4
+-2.02972759290336e-4
+-1.99940581124459e-4
+-1.92322259909184e-4
+-1.80218777351567e-4
+-1.63698996808348e-4
+-1.43003280779161e-4
+-1.18465320314384e-4
+-9.04917696812033e-5
+-5.95982432996934e-5
+-2.64033774281263e-5
+8.46197218886673e-6
+4.42652590354071e-5
+8.02019609117841e-5
+1.15541252681312e-4
+1.49425273628651e-4
+1.81062455609401e-4
+2.09683164935054e-4
+2.34566545855999e-4
+2.55025900468172e-4
+2.70467901918912e-4
+2.80406359763515e-4
+2.84407406120996e-4
+2.82264151028901e-4
+2.73776828577359e-4
+2.5895765641908e-4
+2.37953443006062e-4
+2.1102114984442e-4
+1.78588106227681e-4
+1.41212212859299e-4
+9.95536562423676e-5
+5.44472498542575e-5
+6.75449572476166e-6
+-4.25222554328811e-5
+-9.23549576825794e-5
+-1.41631593345759e-4
+-1.89235824337239e-4
+-2.34097670788864e-4
+-2.75097479638622e-4
+-3.11248660924794e-4
+-3.41546210305275e-4
+-3.6520512783402e-4
+-3.81480006450086e-4
+-3.89787045113193e-4
+-3.89714320620699e-4
+-3.80996818757606e-4
+-3.63624442874326e-4
+-3.37695073721237e-4
+-3.03528513188856e-4
+-2.61672595277376e-4
+-2.12805216855414e-4
+-1.5784688743622e-4
+-9.77861652078604e-5
+-3.38688510549031e-5
+3.2648755958072e-5
+1.0033481570486e-4
+1.67733200025968e-4
+2.33335865754758e-4
+2.95634963180971e-4
+3.53183000686343e-4
+4.0453284744819e-4
+4.48399130268426e-4
+4.83572426498987e-4
+5.09056494666997e-4
+5.24013376631556e-4
+5.27803269367299e-4
+5.20044733952871e-4
+5.00570452769771e-4
+4.69520604910353e-4
+4.27212976261102e-4
+3.74332302277009e-4
+3.11719405101292e-4
+2.4049642873856e-4
+1.62018623241135e-4
+7.77972401313209e-5
+-1.0421191823049e-5
+-1.00812954839322e-4
+-1.91461604856559e-4
+-2.80316135283874e-4
+-3.65416962259402e-4
+-4.44738742737373e-4
+-5.16388437211181e-4
+-5.7857587894405e-4
+-6.29661563116967e-4
+-6.68237124788548e-4
+-6.93099922163973e-4
+-7.03317710030114e-4
+-6.98306631998326e-4
+-6.77769213150651e-4
+-6.41708348696407e-4
+-5.90559386915195e-4
+-5.25007863899402e-4
+-4.46146123054525e-4
+-3.55373132320712e-4
+-2.54360156353956e-4
+-1.45071717361813e-4
+-2.97162036859542e-5
+8.93270297991375e-5
+2.09526647266989e-4
+3.28243937050044e-4
+4.42825108572239e-4
+5.50664563111469e-4
+6.49142096052024e-4
+7.35899347492255e-4
+8.08678813372905e-4
+8.65523171991587e-4
+9.04777569323206e-4
+9.25107116181618e-4
+9.25552318316001e-4
+9.05640042608797e-4
+8.65234115911146e-4
+8.0473337889979e-4
+7.24942146452377e-4
+6.27117586694952e-4
+5.12950399686843e-4
+3.84563786119676e-4
+2.44411218574473e-4
+9.52682661182032e-5
+-5.97889332973182e-5
+-2.17502222608939e-4
+-3.7445891759764e-4
+-5.27167441451825e-4
+-6.72193393846827e-4
+-8.06079651608051e-4
+-9.25663256011369e-4
+-0.00102787495695661
+-0.00111008900761353
+-0.00116992392499094
+-0.00120551745886091
+-0.00121548371811249
+-0.0011989248218485
+-0.0011555522393021
+-0.00108561639886755
+-9.9000582500186e-4
+-8.70172856666792e-4
+-7.28120340175158e-4
+-5.66433876277261e-4
+-3.88151392209041e-4
+-1.96801980103244e-4
+3.75093312325743e-6
+2.09322095650866e-4
+4.1549713716762e-4
+6.17799794351121e-4
+8.11620934737964e-4
+9.92538248565781e-4
+0.00115617378867886
+0.00129855548399389
+0.00141597287741981
+0.0015052170871903
+0.00156360378300213
+0.00158905340455267
+0.00158018090872272
+0.00153629897219207
+0.00145746643569152
+0.00134453135703501
+0.00119910939952723
+0.00102353850722866
+8.20937608545406e-4
+5.95027095905744e-4
+3.50205434101682e-4
+9.13465860120201e-5
+-1.7622097696941e-4
+-4.46838493896153e-4
+-7.14664538170732e-4
+-9.73687424753197e-4
+-0.00121805258911382
+-0.00144196600754232
+-0.0016399967811266
+-0.00180713029567505
+-0.001938830336207
+-0.00203135511114057
+-0.00208158044812268
+-0.00208731796144981
+-0.00204724366396365
+-0.00196104442646158
+-0.00182936323384608
+-0.00165389169291624
+-0.0014372985389836
+-0.00118323635265763
+-8.96271981083588e-4
+-5.81806731072718e-4
+-2.45983969131179e-4
+1.04393268705522e-4
+4.62058789535929e-4
+8.19362766165076e-4
+0.00116846046706454
+0.00150147763859084
+0.00181068622281172
+0.00208861201086775
+0.00232834378817504
+0.00252349896511836
+0.00266859591166639
+0.00275902790411783
+0.00279124340926817
+0.00276288498825251
+0.00267283848815515
+0.00252129596374058
+0.00230975956455204
+0.00204114448975825
+0.00171962024485907
+0.00135067945010547
+9.40962894913222e-4
+4.98221383153697e-4
+3.11253989827009e-5
+-4.50834653780459e-4
+-9.37594792361491e-4
+-0.00141868069476593
+-0.00188337795207629
+-0.00232105491343088
+-0.00272131689968742
+-0.00307423050019428
+-0.00337059265933034
+-0.00360213033363967
+-0.0037616846970991
+-0.00384345278070074
+-0.00384308253291384
+-0.00375783644187481
+-0.00358674852203873
+-0.0033306360078639
+-0.00299217530772653
+-0.00257588667746325
+-0.00208809554811269
+-0.00153691651385721
+-9.32052699698408e-4
+-2.84731720800277e-4
+3.92575824923933e-4
+0.00108624395731248
+0.00178184935779994
+0.002464387302064
+0.0031185876084081
+0.003729182192749
+0.00428124852326713
+0.00476054551468834
+0.00515380348662816
+0.00544899423639641
+0.00563571869175492
+0.00570538540965876
+0.00565150400549031
+0.00546990291198768
+0.00515881834238826
+0.00471916302694636
+0.00415449166195703
+0.00347110481638838
+0.00267799125626014
+0.00178683880102889
+8.11802943926725e-4
+-2.30562873065775e-4
+-0.00132153102743281
+-0.00244054733990411
+-0.00356539492058686
+-0.00467268587078703
+-0.00573814176089155
+-0.00673696915030418
+-0.00764439443252765
+-0.00843600526449621
+-0.00908818810332266
+-0.00957862488505226
+-0.00988665936971963
+-0.0099937068885515
+-0.00988371464077663
+-0.00954336583418968
+-0.00896253186591292
+-0.00813442269973128
+-0.00705586455196647
+-0.00572741237854925
+-0.00415349209382152
+-0.00234233959454067
+-3.06098977672814e-4
+0.00193941933088424
+0.00437477465814811
+0.00697721762570139
+0.00972087552164101
+0.0125771999157822
+0.0155152397694249
+0.0185021810309104
+0.021503710104957
+0.0244845910618796
+0.0274091350854231
+0.0302417753259086
+0.0329475282481102
+0.0354926172612528
+0.0378449140820321
+0.039974473230549
+0.0418539747756063
+0.0434591523630184
+0.0447691888654274
+0.0457670156843866
+0.046439581452649
+0.0467780781663164
+0.0467780781663164
+0.046439581452649
+0.0457670156843866
+0.0447691888654274
+0.0434591523630184
+0.0418539747756063
+0.039974473230549
+0.0378449140820321
+0.0354926172612528
+0.0329475282481102
+0.0302417753259086
+0.0274091350854231
+0.0244845910618796
+0.021503710104957
+0.0185021810309104
+0.0155152397694249
+0.0125771999157822
+0.00972087552164101
+0.00697721762570139
+0.00437477465814811
+0.00193941933088424
+-3.06098977672814e-4
+-0.00234233959454067
+-0.00415349209382152
+-0.00572741237854925
+-0.00705586455196647
+-0.00813442269973128
+-0.00896253186591292
+-0.00954336583418968
+-0.00988371464077663
+-0.0099937068885515
+-0.00988665936971963
+-0.00957862488505226
+-0.00908818810332266
+-0.00843600526449621
+-0.00764439443252765
+-0.00673696915030418
+-0.00573814176089155
+-0.00467268587078703
+-0.00356539492058686
+-0.00244054733990411
+-0.00132153102743281
+-2.30562873065775e-4
+8.11802943926725e-4
+0.00178683880102889
+0.00267799125626014
+0.00347110481638838
+0.00415449166195703
+0.00471916302694636
+0.00515881834238826
+0.00546990291198768
+0.00565150400549031
+0.00570538540965876
+0.00563571869175492
+0.00544899423639641
+0.00515380348662816
+0.00476054551468834
+0.00428124852326713
+0.003729182192749
+0.0031185876084081
+0.002464387302064
+0.00178184935779994
+0.00108624395731248
+3.92575824923933e-4
+-2.84731720800277e-4
+-9.32052699698408e-4
+-0.00153691651385721
+-0.00208809554811269
+-0.00257588667746325
+-0.00299217530772653
+-0.0033306360078639
+-0.00358674852203873
+-0.00375783644187481
+-0.00384308253291384
+-0.00384345278070074
+-0.0037616846970991
+-0.00360213033363967
+-0.00337059265933034
+-0.00307423050019428
+-0.00272131689968742
+-0.00232105491343088
+-0.00188337795207629
+-0.00141868069476593
+-9.37594792361491e-4
+-4.50834653780459e-4
+3.11253989827009e-5
+4.98221383153697e-4
+9.40962894913222e-4
+0.00135067945010547
+0.00171962024485907
+0.00204114448975825
+0.00230975956455204
+0.00252129596374058
+0.00267283848815515
+0.00276288498825251
+0.00279124340926817
+0.00275902790411783
+0.00266859591166639
+0.00252349896511836
+0.00232834378817504
+0.00208861201086775
+0.00181068622281172
+0.00150147763859084
+0.00116846046706454
+8.19362766165076e-4
+4.62058789535929e-4
+1.04393268705522e-4
+-2.45983969131179e-4
+-5.81806731072718e-4
+-8.96271981083588e-4
+-0.00118323635265763
+-0.0014372985389836
+-0.00165389169291624
+-0.00182936323384608
+-0.00196104442646158
+-0.00204724366396365
+-0.00208731796144981
+-0.00208158044812268
+-0.00203135511114057
+-0.001938830336207
+-0.00180713029567505
+-0.0016399967811266
+-0.00144196600754232
+-0.00121805258911382
+-9.73687424753197e-4
+-7.14664538170732e-4
+-4.46838493896153e-4
+-1.7622097696941e-4
+9.13465860120201e-5
+3.50205434101682e-4
+5.95027095905744e-4
+8.20937608545406e-4
+0.00102353850722866
+0.00119910939952723
+0.00134453135703501
+0.00145746643569152
+0.00153629897219207
+0.00158018090872272
+0.00158905340455267
+0.00156360378300213
+0.0015052170871903
+0.00141597287741981
+0.00129855548399389
+0.00115617378867886
+9.92538248565781e-4
+8.11620934737964e-4
+6.17799794351121e-4
+4.1549713716762e-4
+2.09322095650866e-4
+3.75093312325743e-6
+-1.96801980103244e-4
+-3.88151392209041e-4
+-5.66433876277261e-4
+-7.28120340175158e-4
+-8.70172856666792e-4
+-9.9000582500186e-4
+-0.00108561639886755
+-0.0011555522393021
+-0.0011989248218485
+-0.00121548371811249
+-0.00120551745886091
+-0.00116992392499094
+-0.00111008900761353
+-0.00102787495695661
+-9.25663256011369e-4
+-8.06079651608051e-4
+-6.72193393846827e-4
+-5.27167441451825e-4
+-3.7445891759764e-4
+-2.17502222608939e-4
+-5.97889332973182e-5
+9.52682661182032e-5
+2.44411218574473e-4
+3.84563786119676e-4
+5.12950399686843e-4
+6.27117586694952e-4
+7.24942146452377e-4
+8.0473337889979e-4
+8.65234115911146e-4
+9.05640042608797e-4
+9.25552318316001e-4
+9.25107116181618e-4
+9.04777569323206e-4
+8.65523171991587e-4
+8.08678813372905e-4
+7.35899347492255e-4
+6.49142096052024e-4
+5.50664563111469e-4
+4.42825108572239e-4
+3.28243937050044e-4
+2.09526647266989e-4
+8.93270297991375e-5
+-2.97162036859542e-5
+-1.45071717361813e-4
+-2.54360156353956e-4
+-3.55373132320712e-4
+-4.46146123054525e-4
+-5.25007863899402e-4
+-5.90559386915195e-4
+-6.41708348696407e-4
+-6.77769213150651e-4
+-6.98306631998326e-4
+-7.03317710030114e-4
+-6.93099922163973e-4
+-6.68237124788548e-4
+-6.29661563116967e-4
+-5.7857587894405e-4
+-5.16388437211181e-4
+-4.44738742737373e-4
+-3.65416962259402e-4
+-2.80316135283874e-4
+-1.91461604856559e-4
+-1.00812954839322e-4
+-1.0421191823049e-5
+7.77972401313209e-5
+1.62018623241135e-4
+2.4049642873856e-4
+3.11719405101292e-4
+3.74332302277009e-4
+4.27212976261102e-4
+4.69520604910353e-4
+5.00570452769771e-4
+5.20044733952871e-4
+5.27803269367299e-4
+5.24013376631556e-4
+5.09056494666997e-4
+4.83572426498987e-4
+4.48399130268426e-4
+4.0453284744819e-4
+3.53183000686343e-4
+2.95634963180971e-4
+2.33335865754758e-4
+1.67733200025968e-4
+1.0033481570486e-4
+3.2648755958072e-5
+-3.38688510549031e-5
+-9.77861652078604e-5
+-1.5784688743622e-4
+-2.12805216855414e-4
+-2.61672595277376e-4
+-3.03528513188856e-4
+-3.37695073721237e-4
+-3.63624442874326e-4
+-3.80996818757606e-4
+-3.89714320620699e-4
+-3.89787045113193e-4
+-3.81480006450086e-4
+-3.6520512783402e-4
+-3.41546210305275e-4
+-3.11248660924794e-4
+-2.75097479638622e-4
+-2.34097670788864e-4
+-1.89235824337239e-4
+-1.41631593345759e-4
+-9.23549576825794e-5
+-4.25222554328811e-5
+6.75449572476166e-6
+5.44472498542575e-5
+9.95536562423676e-5
+1.41212212859299e-4
+1.78588106227681e-4
+2.1102114984442e-4
+2.37953443006062e-4
+2.5895765641908e-4
+2.73776828577359e-4
+2.82264151028901e-4
+2.84407406120996e-4
+2.80406359763515e-4
+2.70467901918912e-4
+2.55025900468172e-4
+2.34566545855999e-4
+2.09683164935054e-4
+1.81062455609401e-4
+1.49425273628651e-4
+1.15541252681312e-4
+8.02019609117841e-5
+4.42652590354071e-5
+8.46197218886673e-6
+-2.64033774281263e-5
+-5.95982432996934e-5
+-9.04917696812033e-5
+-1.18465320314384e-4
+-1.43003280779161e-4
+-1.63698996808348e-4
+-1.80218777351567e-4
+-1.92322259909184e-4
+-1.99940581124459e-4
+-2.02972759290336e-4
+-2.01564656263033e-4
+-1.95867813754568e-4
+-1.86143587824593e-4
+-1.72712890799109e-4
+-1.56012871346288e-4
+-1.3649515371509e-4
+-1.14693160653602e-4
+-9.11217498548619e-5
+-6.63607029679837e-5
+-4.10035600300493e-5
+-1.55984918923049e-5
+9.3129309380048e-6
+3.31799427308997e-5
+5.55488335464633e-5
+7.59553413177967e-5
+9.40746256399753e-5
+1.09537433110581e-4
+1.22120271607441e-4
+1.31649152408872e-4
+1.38042535292926e-4
+1.4121817567785e-4
+1.41266585644598e-4
+1.38242615396576e-4
+1.32393120309911e-4
+1.23877401105374e-4
+1.12981102411937e-4
+1.00039703633977e-4
+8.53884090898411e-5
+6.94390025027894e-5
+5.25300164078023e-5
+3.50927801023099e-5
+1.75262241794632e-5
+1.8211835731409e-7
+-1.65036203311736e-5
+-3.22960637446588e-5
+-4.67784017657438e-5
+-5.97576234894939e-5
+-7.09737795002089e-5
+-8.02605459808726e-5
+-8.74787550676798e-5
+-9.25431334779362e-5
+-9.54489884121157e-5
+-9.61699375283378e-5
+-9.48068546980327e-5
+-9.14514657680923e-5
+-8.6241178990473e-5
+-7.9381160780839e-5
+-7.10668055624751e-5
+-6.15260332171321e-5
+-5.10302848833116e-5
+-3.98156943957032e-5
+-2.8182112834728e-5
+-1.63848253814674e-5
+-4.68762174381739e-6
+6.66515424198749e-6
+1.74547874668573e-5
+2.74298095627849e-5
+3.6439179398353e-5
+4.42950092732983e-5
+5.08935610500647e-5
+5.61760181265976e-5
+5.99917552478514e-5
+6.2383362148182e-5
+6.3320088392269e-5
+6.28816258498489e-5
+6.10944817720679e-5
+5.8058617211836e-5
+5.38887103915501e-5
+4.87313166822799e-5
+4.27456382286692e-5
+3.60545970430637e-5
+2.88933776644191e-5
+2.13787482610813e-5
+1.37140404419924e-5
+6.08602710173464e-6
+-1.37057784993502e-6
+-8.47653619728616e-6
+-1.50963566347366e-5
+-2.11542725315722e-5
+-2.64479100675461e-5
+-3.09755908244563e-5
+-3.46200271022937e-5
+-3.73919246991607e-5
+-3.92125256039437e-5
+-4.01278786536825e-5
+-4.01135752080094e-5
+-3.92567099728606e-5
+-3.75869046571029e-5
+-3.51664827487924e-5
+-3.21077759116387e-5
+-2.8476946106292e-5
+-2.44092890499766e-5
+-1.99867517520571e-5
+-1.53239936200644e-5
+-1.05566723150875e-5
+-5.75008290742105e-6
+-1.07237403409055e-6
+3.44948129599163e-6
+7.67266645113299e-6
+1.15270292808691e-5
+1.49707237863667e-5
+1.79397096215955e-5
+2.03698259249784e-5
+2.22346916834176e-5
+2.35477964026005e-5
+2.42814484952927e-5
+2.44756148778194e-5
+2.41135213673391e-5
+2.3237064442004e-5
+2.19109883335264e-5
+2.0183001663178e-5
+1.80905523657776e-5
+1.57239303578456e-5
+1.31179949559878e-5
+1.03647465427585e-5
+7.49499200727654e-6
+4.65462384661346e-6
+1.83157780808837e-6
+-8.98080427581192e-7
+-3.46810975732889e-6
+-5.82669848029968e-6
+-7.94061043444157e-6
+-9.75795645920384e-6
+-1.12945331543608e-5
+-1.25232516456216e-5
+-1.33693589565357e-5
+-1.39167543346076e-5
+-1.41096581487199e-5
+-1.40143363153509e-5
+-1.35864741790705e-5
+-1.29258356094021e-5
+-1.19812039266178e-5
+-1.08541688245874e-5
+-9.54514698333832e-6
+-8.09156481962559e-6
+-6.55816909846896e-6
+-4.96530162809768e-6
+-3.33935604298266e-6
+-1.73983144001699e-6
+-1.84404808868073e-7
+1.28261796938256e-6
+2.62399132900517e-6
+3.84118987018593e-6
+4.93125339021914e-6
+5.81138982456196e-6
+6.5530535251783e-6
+7.07019338593616e-6
+7.4322223638238e-6
+7.59604323829658e-6
+7.5921592957585e-6
+7.42554420262448e-6
+7.10620984925846e-6
+6.64505288826461e-6
+6.0633779344053e-6
+5.39866854742161e-6
+4.6486553085021e-6
+3.83150595451006e-6
+3.01139455704895e-6
+2.15698996474846e-6
+1.30134942732076e-6
+4.778230486617e-7
+-2.9897580679925e-7
+-1.01450351451109e-6
+-1.66299764538256e-6
+-2.23880629643428e-6
+-2.73085981209485e-6
+-3.10558378787101e-6
+-3.40106555337159e-6
+-3.62820827681515e-6
+-3.73781668478926e-6
+-3.75096178007138e-6
+-3.67684205210421e-6
+-3.54951933335568e-6
+-3.34868062209883e-6
+-3.08872255757467e-6
+-2.77710918199585e-6
+-2.42034886505034e-6
+-2.03191995568737e-6
+-1.6246903514035e-6
+-1.21281774093872e-6
+-8.17500360283736e-7
+-4.3476366150865e-7
+-5.24862218589967e-8
+2.96426729531177e-7
+6.04567255230193e-7
+8.5785768415765e-7
+1.10621331781889e-6
+1.28959869628182e-6
+1.43132387640668e-6
+1.53782569699597e-6
+1.61363975974438e-6
+1.6294811644839e-6
+1.60770440406623e-6
+1.55182559228546e-6
+1.46860535142565e-6
+1.34551951148203e-6
+1.25500772923897e-6
+1.09935217260167e-6
+9.21520058445204e-7
+7.75112423789865e-7
+6.00075575484758e-7
+4.3227430974949e-7
+2.81681324083492e-7
+1.44876241366308e-7
+-5.05264098238236e-9
+-1.54707945258839e-7
+-2.44517851394823e-7
+-3.38624331418706e-7
+-4.53511011468631e-7
+-5.01344341031087e-7
+-5.3712751262779e-7
+-5.61361967225389e-7
+-5.87512127558038e-7
+-5.61504899335206e-7
+-5.58776629837758e-7
+-5.53575138212173e-7
+-5.09702102203457e-7
+-4.87548260748437e-7
+-4.62591739880567e-7
+-4.22986843582035e-7
+-4.2275208095965e-7
+-4.38563052056152e-7
+-5.74349474884059e-7
+6.25765784406859e-7
diff --git a/fir/c96000ntsc.h b/fir/c96000ntsc.h
new file mode 100644
index 00000000..4a85a5b5
--- /dev/null
+++ b/fir/c96000ntsc.h
@@ -0,0 +1,512 @@
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+1,
+1,
+1,
+1,
+1,
+1,
+1,
+1,
+1,
+1,
+1,
+1,
+0,
+0,
+0,
+0,
+0,
+0,
+-1,
+-1,
+-2,
+-2,
+-2,
+-3,
+-3,
+-3,
+-3,
+-3,
+-3,
+-3,
+-3,
+-3,
+-2,
+-2,
+-1,
+-1,
+0,
+0,
+1,
+2,
+3,
+4,
+4,
+5,
+6,
+6,
+7,
+7,
+7,
+7,
+7,
+7,
+6,
+6,
+5,
+4,
+2,
+1,
+0,
+-1,
+-3,
+-5,
+-6,
+-8,
+-10,
+-11,
+-12,
+-13,
+-14,
+-14,
+-14,
+-14,
+-14,
+-13,
+-11,
+-10,
+-8,
+-6,
+-3,
+0,
+1,
+4,
+7,
+10,
+13,
+16,
+18,
+21,
+22,
+24,
+25,
+25,
+25,
+24,
+23,
+21,
+18,
+15,
+12,
+8,
+3,
+-1,
+-6,
+-11,
+-16,
+-20,
+-25,
+-29,
+-33,
+-36,
+-39,
+-41,
+-42,
+-42,
+-41,
+-39,
+-36,
+-32,
+-27,
+-22,
+-15,
+-8,
+-1,
+6,
+14,
+22,
+30,
+37,
+44,
+51,
+56,
+60,
+64,
+65,
+66,
+65,
+62,
+58,
+53,
+46,
+38,
+28,
+18,
+6,
+-4,
+-17,
+-29,
+-41,
+-53,
+-64,
+-74,
+-83,
+-90,
+-95,
+-99,
+-100,
+-100,
+-97,
+-91,
+-84,
+-74,
+-62,
+-49,
+-33,
+-17,
+0,
+18,
+36,
+55,
+72,
+89,
+104,
+118,
+129,
+138,
+144,
+148,
+148,
+144,
+138,
+128,
+114,
+98,
+79,
+58,
+34,
+9,
+-16,
+-42,
+-69,
+-95,
+-120,
+-143,
+-163,
+-181,
+-195,
+-205,
+-211,
+-212,
+-209,
+-201,
+-188,
+-171,
+-149,
+-124,
+-94,
+-62,
+-27,
+8,
+46,
+84,
+121,
+156,
+189,
+219,
+245,
+267,
+283,
+294,
+298,
+295,
+287,
+271,
+249,
+221,
+187,
+148,
+104,
+57,
+7,
+-44,
+-96,
+-148,
+-198,
+-245,
+-288,
+-326,
+-358,
+-382,
+-400,
+-408,
+-408,
+-399,
+-381,
+-354,
+-318,
+-274,
+-223,
+-165,
+-102,
+-35,
+34,
+105,
+175,
+244,
+309,
+370,
+424,
+470,
+507,
+533,
+549,
+553,
+545,
+524,
+492,
+447,
+392,
+326,
+252,
+169,
+81,
+-10,
+-105,
+-200,
+-293,
+-383,
+-466,
+-541,
+-606,
+-660,
+-700,
+-726,
+-737,
+-732,
+-710,
+-672,
+-619,
+-550,
+-467,
+-372,
+-266,
+-152,
+-31,
+93,
+219,
+344,
+464,
+577,
+680,
+771,
+847,
+907,
+948,
+970,
+970,
+949,
+907,
+843,
+760,
+657,
+537,
+403,
+256,
+99,
+-62,
+-228,
+-392,
+-552,
+-704,
+-845,
+-970,
+-1077,
+-1164,
+-1226,
+-1264,
+-1274,
+-1257,
+-1211,
+-1138,
+-1038,
+-912,
+-763,
+-593,
+-407,
+-206,
+3,
+219,
+435,
+647,
+851,
+1040,
+1212,
+1361,
+1484,
+1578,
+1639,
+1666,
+1656,
+1610,
+1528,
+1409,
+1257,
+1073,
+860,
+623,
+367,
+95,
+-184,
+-468,
+-749,
+-1020,
+-1277,
+-1512,
+-1719,
+-1894,
+-2033,
+-2130,
+-2182,
+-2188,
+-2146,
+-2056,
+-1918,
+-1734,
+-1507,
+-1240,
+-939,
+-610,
+-257,
+109,
+484,
+859,
+1225,
+1574,
+1898,
+2190,
+2441,
+2646,
+2798,
+2893,
+2926,
+2897,
+2802,
+2643,
+2421,
+2140,
+1803,
+1416,
+986,
+522,
+32,
+-472,
+-983,
+-1487,
+-1974,
+-2433,
+-2853,
+-3223,
+-3534,
+-3777,
+-3944,
+-4030,
+-4029,
+-3940,
+-3760,
+-3492,
+-3137,
+-2701,
+-2189,
+-1611,
+-977,
+-298,
+411,
+1139,
+1868,
+2584,
+3270,
+3910,
+4489,
+4991,
+5404,
+5713,
+5909,
+5982,
+5926,
+5735,
+5409,
+4948,
+4356,
+3639,
+2808,
+1873,
+851,
+-241,
+-1385,
+-2559,
+-3738,
+-4899,
+-6016,
+-7064,
+-8015,
+-8845,
+-9529,
+-10043,
+-10366,
+-10479,
+-10363,
+-10006,
+-9397,
+-8529,
+-7398,
+-6005,
+-4355,
+-2456,
+-320,
+2033,
+4587,
+7316,
+10193,
+13188,
+16268,
+19400,
+22548,
+25673,
+28740,
+31710,
+34547,
+37216,
+39683,
+41916,
+43887,
+45570,
+46943,
+47990,
+48695,
+49050,
diff --git a/fir/c96000ntsc.scm b/fir/c96000ntsc.scm
new file mode 100644
index 00000000..84e26d7a
--- /dev/null
+++ b/fir/c96000ntsc.scm
@@ -0,0 +1,12 @@
+(title "96000 NTSC")
+
+(verbose #t)
+
+(cosine-symmetry)
+(filter-length 1024)
+(sampling-frequency 1789772.727272727272)
+(limit-= (band 0 36850) 1)
+(limit-= (band 48000 894886.363636) 0 .5)
+(output-file "c96000ntsc.coef")
+(plot-file "c96000ntsc.plot")
+(go)
diff --git a/fir/c96000pal.coef b/fir/c96000pal.coef
new file mode 100644
index 00000000..cc8f87c8
--- /dev/null
+++ b/fir/c96000pal.coef
@@ -0,0 +1,1039 @@
+;; ***** 96000 PAL *****
+;; Filter length: 1024
+;; Symmetry: cosine
+;; Sampling frequency: 1662607.125
+;; Grid density: 10257
+;; Deviation parameter: y=-1.67321403971065e-8
+;;
+;; Specifications:
+;; (limit > 48000 831303.5625 0 0.5)
+;; (limit < 48000 831303.5625 0 0.5)
+;; (limit > 0 33400 1 1)
+;; (limit < 0 33400 1 1)
+;;
+;; Coefficients:
+
+1.03151991819582e-8
+8.38300275294078e-9
+1.10906859282933e-8
+1.03271192432242e-8
+1.14333552786323e-8
+1.30077482700426e-8
+1.41716278773579e-8
+1.74208569471553e-8
+2.00800027395966e-8
+2.09724315061768e-8
+2.22929661801192e-8
+1.95132650596489e-8
+1.76960158618376e-8
+1.3068715878392e-8
+1.07557125018314e-8
+6.05954400825878e-9
+1.83985020585335e-9
+-4.35513294668295e-9
+-1.25339352914121e-8
+-2.18251091115114e-8
+-3.19847926493859e-8
+-4.14587362468332e-8
+-5.15215025811016e-8
+-6.3122768061061e-8
+-7.34212411189246e-8
+-8.35519847400028e-8
+-9.19816359673906e-8
+-1.00062504114338e-7
+-1.0581696028102e-7
+-1.09342060902351e-7
+-1.09899151121439e-7
+-1.07199067922224e-7
+-1.01333875812554e-7
+-9.17625273815014e-8
+-7.89956849981134e-8
+-6.14126768147793e-8
+-3.99528124923842e-8
+-1.43267231105268e-8
+1.51839061412207e-8
+4.71079084065085e-8
+8.33872247697555e-8
+1.20450960766471e-7
+1.6066011924682e-7
+1.99015401296622e-7
+2.3707190547137e-7
+2.72939884477538e-7
+3.05703733943038e-7
+3.34271689565622e-7
+3.57246917030831e-7
+3.71753520789388e-7
+3.80032136027046e-7
+3.77007825091848e-7
+3.65236448771379e-7
+3.39343358482371e-7
+3.02990066262988e-7
+2.53431354500078e-7
+1.93531346067046e-7
+1.20312660464537e-7
+3.83506638823491e-8
+-5.50094412531977e-8
+-1.55165787913079e-7
+-2.62247401958816e-7
+-3.72869415873669e-7
+-4.85000602763094e-7
+-5.9487324901853e-7
+-7.00817920677767e-7
+-7.96695832853341e-7
+-8.83009467313344e-7
+-9.516801687493e-7
+-1.00406302340324e-6
+-1.03355489807237e-6
+-1.03946679063045e-6
+-1.01783166180378e-6
+-9.67049604607247e-7
+-8.87746045951503e-7
+-7.77649486859982e-7
+-6.37499558026062e-7
+-4.67089278916325e-7
+-2.69324680211038e-7
+-4.79481886690687e-8
+1.95178720022609e-7
+4.53619817534114e-7
+7.23956612504e-7
+9.97486152500784e-7
+1.26826910787562e-6
+1.53005288621509e-6
+1.77357589639965e-6
+1.99304439308787e-6
+2.17833876701336e-6
+2.32279469282784e-6
+2.41942298528229e-6
+2.46085469574341e-6
+2.44371789997691e-6
+2.36167902121603e-6
+2.21343228064008e-6
+1.99610535588337e-6
+1.71076949967104e-6
+1.35846743996931e-6
+9.44346239710729e-7
+4.73800121500147e-7
+-4.49606767418064e-8
+-6.0197624767097e-7
+-1.18587637892365e-6
+-1.78302023739655e-6
+-2.38006119965271e-6
+-2.96212165638707e-6
+-3.51170040070893e-6
+-4.01344340051503e-6
+-4.44917701834718e-6
+-4.80493586876171e-6
+-5.063623966477e-6
+-5.21373005767686e-6
+-5.24183699733879e-6
+-5.1394946501258e-6
+-4.90048958017337e-6
+-4.52057551249377e-6
+-4.00121137621988e-6
+-3.34381409235837e-6
+-2.55698769776267e-6
+-1.65168508479184e-6
+-6.41630367682649e-7
+4.5272033468355e-7
+1.61065667346661e-6
+2.80519025479194e-6
+4.00982303462755e-6
+5.19442047840389e-6
+6.32696760641722e-6
+7.37667453186873e-6
+8.31026493121452e-6
+9.09759867217571e-6
+9.70730330637792e-6
+1.01139238186566e-5
+1.02939875082689e-5
+1.0228657500937e-5
+9.90357194955147e-6
+9.31094999767115e-6
+8.44836300475225e-6
+7.32184325292062e-6
+5.9411139708878e-6
+4.32718679501898e-6
+2.5045517191364e-6
+5.08537844109541e-7
+-1.62303718375881e-6
+-3.84347493132933e-6
+-6.10417289473804e-6
+-8.34891011005015e-6
+-1.05213195267016e-5
+-1.25625562618188e-5
+-1.44140306102446e-5
+-1.60176157455328e-5
+-1.73187930064226e-5
+-1.82665081367835e-5
+-1.88180884125302e-5
+-1.89349221542663e-5
+-1.85905030202489e-5
+-1.77652468409902e-5
+-1.64542644771625e-5
+-1.46606892008227e-5
+-1.24032950277693e-5
+-9.71123313104019e-6
+-6.62826926323268e-6
+-3.20916832281648e-6
+4.80912959878512e-7
+4.36391659133863e-6
+8.35431095023709e-6
+1.23587745013029e-5
+1.62776057022447e-5
+2.00104633597274e-5
+2.34525897473363e-5
+2.6504113480356e-5
+2.90669843834708e-5
+3.10523292715376e-5
+3.23801498345e-5
+3.29827423119358e-5
+3.28062497909458e-5
+3.18141310912695e-5
+2.99885330657398e-5
+2.73307787009361e-5
+2.3863596601089e-5
+1.9630985529227e-5
+1.46979062042561e-5
+9.15102381017684e-6
+3.09475951446394e-6
+-3.34513850836547e-6
+-1.00309472232173e-5
+-1.68084780282784e-5
+-2.35164419241063e-5
+-2.99843308432599e-5
+-3.60413748500087e-5
+-4.15175966696302e-5
+-4.62496011329744e-5
+-5.00834846280012e-5
+-5.2881756318201e-5
+-5.45231256798723e-5
+-5.49127392818389e-5
+-5.39779986324577e-5
+-5.1680740099127e-5
+-4.80092456996724e-5
+-4.29902880316882e-5
+-3.66811426138427e-5
+-2.91770944785758e-5
+-2.06050398177054e-5
+-1.1125982738189e-5
+-9.29469045115252e-7
+9.76750875584034e-6
+2.07264139138749e-5
+3.16889547008264e-5
+4.23881612033781e-5
+5.25469490585536e-5
+6.18941440803559e-5
+7.01613699670651e-5
+7.70982488738663e-5
+8.24733429562758e-5
+8.60846255633886e-5
+8.77652355990178e-5
+8.73861281253179e-5
+8.48651355449836e-5
+8.01683770409635e-5
+7.33144164498558e-5
+6.43756190395851e-5
+5.347813081375e-5
+4.08032785217656e-5
+2.65822878709086e-5
+1.10959100456974e-5
+-5.33248429467424e-6
+-2.23418652788707e-5
+-3.95425112453473e-5
+-5.65228132450726e-5
+-7.28580214960265e-5
+-8.81236947188922e-5
+-1.01900589865764e-4
+-1.13790446423011e-4
+-1.23423041654638e-4
+-1.30468892775236e-4
+-1.34648743318249e-4
+-1.35739884161422e-4
+-1.33588879261025e-4
+-1.2811333539122e-4
+-1.19309561896777e-4
+-1.0725481963731e-4
+-9.21093274384085e-5
+-7.41158206776385e-5
+-5.35961801579358e-5
+-3.09472952504257e-5
+-6.63430458187306e-6
+1.88188660219006e-5
+4.48385613205947e-5
+7.0815621084536e-5
+9.61160455879359e-5
+1.20099004917142e-4
+1.42129235004429e-4
+1.61594559165767e-4
+1.77921607229302e-4
+1.90590736122456e-4
+1.99151775086795e-4
+2.03236949574574e-4
+2.02573580216899e-4
+1.96994293467081e-4
+1.86445019398819e-4
+1.70990903256481e-4
+1.50819069616185e-4
+1.26238358089726e-4
+9.76776349699245e-5
+6.56776045971978e-5
+3.08848326050668e-5
+-5.96356740813766e-6
+-4.40513605910619e-5
+-8.25032454022742e-5
+-1.20401080500299e-4
+-1.56806879798798e-4
+-1.90783149605849e-4
+-2.21419291675664e-4
+-2.47848788110117e-4
+-2.69279472445284e-4
+-2.85009149126569e-4
+-2.94450224275897e-4
+-2.97145272500789e-4
+-2.9278440100842e-4
+-2.81218526412152e-4
+-2.62467514354949e-4
+-2.36726227379411e-4
+-2.04367498164773e-4
+-1.65935928106054e-4
+-1.22144676611347e-4
+-7.38611116469124e-5
+-2.2092886327107e-5
+3.20332747710491e-5
+8.72935203677178e-5
+1.4239311797007e-4
+1.95996823059339e-4
+2.46758430731207e-4
+2.93354710149485e-4
+3.34516779687324e-4
+3.69063740137675e-4
+3.95935025218761e-4
+4.14218377731336e-4
+4.23179220684935e-4
+4.22282619148847e-4
+4.11214766210894e-4
+3.89896739795703e-4
+3.58494957675319e-4
+3.17425558178502e-4
+2.67352241592445e-4
+2.09178855148142e-4
+1.44035366727157e-4
+7.3257656515258e-5
+-1.63779237740676e-6
+-7.89848893170478e-5
+-1.57002327126315e-4
+-2.33835056002673e-4
+-3.07594047026731e-4
+-3.76404164136881e-4
+-4.38446131068721e-4
+-4.9200703290972e-4
+-5.35520428249821e-4
+-5.67613638239988e-4
+-5.87143099888524e-4
+-5.93232478671107e-4
+-5.85300692351394e-4
+-5.63086337917986e-4
+-5.26663373800026e-4
+-4.76451870743233e-4
+-4.13216007201208e-4
+-3.38060678040117e-4
+-2.52409733078722e-4
+-1.57988085254148e-4
+-5.6784716422895e-5
+4.89841731832692e-5
+1.56922907604873e-4
+2.64508461181843e-4
+3.69146665341244e-4
+4.68233075668834e-4
+5.59215876696991e-4
+6.39657748300381e-4
+7.07299816040927e-4
+7.6012020281837e-4
+7.96391761417496e-4
+8.14730777273661e-4
+8.14142664644267e-4
+7.94056446208742e-4
+7.5435263217961e-4
+6.9537963487656e-4
+6.17959079267155e-4
+5.23381496018073e-4
+4.13387627487922e-4
+2.90142907465985e-4
+1.5619696018914e-4
+1.44330402738205e-5
+-1.31990568245096e-4
+-2.79707337982926e-4
+-4.25218148098678e-4
+-5.6497087428213e-4
+-6.95445072726885e-4
+-8.13236256145513e-4
+-9.15141775653344e-4
+-9.98243562663091e-4
+-0.0010599866628307
+-0.00109825180635536
+-0.00111141913270169
+-0.00109842176590062
+-0.00105878723152578
+-9.92667960092833e-4
+-9.00853865253174e-4
+-7.84775133395688e-4
+-6.46484210138539e-4
+-4.8862706565045e-4
+-3.14396237291812e-4
+-1.27470456729415e-4
+6.80586481779722e-5
+2.67772482152798e-4
+4.67021632594192e-4
+6.61030288225903e-4
+8.45007409820417e-4
+0.00101425950405569
+0.00116430673085702
+0.00129099572518951
+0.0013906093284534
+0.0014599674225506
+0.00149651846177726
+0.00149841919645406
+0.00146459939319946
+0.00139480951060361
+0.00128965157704395
+0.00115058933642334
+9.79937911476128e-4
+7.80834826954757e-4
+5.57187482764196e-4
+3.13605594907024e-4
+5.53078264280656e-5
+-2.1198068576069e-4
+-4.82152145309325e-4
+-7.48849254545155e-4
+-0.0010056096258098
+-0.00124601613279792
+-0.00146385027634117
+-0.00165324714625177
+-0.00180884426159716
+-0.00192592281171168
+-0.00200054079682649
+-0.00202964706581313
+-0.00201118336129597
+-0.00194415758323169
+-0.00182870407402118
+-0.00166611043274461
+-0.0014588228462092
+-0.00121042184021843
+-9.25571871008901e-4
+-6.09943356897427e-4
+-2.70108419498178e-4
+8.65878287229843e-5
+4.52176307534593e-4
+8.18234381982771e-4
+0.00117607035980743
+0.00151692075161767
+0.00183215385494268
+0.00211347938372566
+0.00235315096692847
+0.00254416760290437
+0.00268046014161941
+0.00275706287455375
+0.00277026461769735
+0.00271773284742105
+0.00259861436853517
+0.00241359905001614
+0.00216495311562251
+0.00185651528950842
+0.00149365620556701
+0.0010832027611814
+6.33323430643252e-4
+1.5338150399634e-4
+-3.46245873742672e-4
+-8.54375818614214e-4
+-0.00135925347644246
+-0.00184880903364977
+-0.00231092502530074
+-0.0027337187227384
+-0.00310582337372604
+-0.00341666930468077
+-0.00365675622328083
+-0.00381790643652724
+-0.00389350186222283
+-0.00387868559008699
+-0.00377053814671627
+-0.00356820912785959
+-0.00327301016165189
+-0.0028884598696194
+-0.00242028158028417
+-0.0018763509819845
+-0.00126659496546869
+-6.02837209621259e-4
+1.01397889009688e-4
+8.31132315629842e-4
+0.00157021607771463
+0.00230165125086365
+0.00300793964707363
+0.00367145812920719
+0.00427484711920302
+0.00480141038410035
+0.00523550974836302
+0.00556295588482682
+0.00577137823517525
+0.00585057149230045
+0.0057928072764395
+0.00559310428736023
+0.00524945134321352
+0.00476297411539252
+0.00413804459791576
+0.00338232730758133
+0.00250675668335827
+0.00152545134396061
+4.55555350931454e-4
+-6.82980522572643e-4
+-0.00186768708315042
+-0.00307391993768759
+-0.00427525920508468
+-0.00544395757085389
+-0.00655142415066617
+-0.00756874635507542
+-0.00846722496704464
+-0.00921892960311577
+-0.00979724946072329
+-0.0101774361576858
+-0.0103371277935579
+-0.0102568377148858
+-0.0099204091949967
+-0.00931541332239757
+-0.0084334894941071
+-0.00727062096870851
+-0.0058273332996356
+-0.0041088188533721
+-0.00212497423336652
+1.09643059299226e-4
+0.00257594505916577
+0.0052505266785003
+0.00810596046568048
+0.0111111690166798
+0.0142318659846858
+0.0174310658866196
+0.0206696428324693
+0.0239069404409966
+0.0271014128800568
+0.0302112916385789
+0.0331952625461897
+0.0360131429726491
+0.0386265459586327
+0.0409995195603867
+0.0430991464884573
+0.0448960998991556
+0.0463651374584695
+0.0474855309975742
+0.0482414158697416
+0.0486220638091454
+0.0486220638091454
+0.0482414158697416
+0.0474855309975742
+0.0463651374584695
+0.0448960998991556
+0.0430991464884573
+0.0409995195603867
+0.0386265459586327
+0.0360131429726491
+0.0331952625461897
+0.0302112916385789
+0.0271014128800568
+0.0239069404409966
+0.0206696428324693
+0.0174310658866196
+0.0142318659846858
+0.0111111690166798
+0.00810596046568048
+0.0052505266785003
+0.00257594505916577
+1.09643059299226e-4
+-0.00212497423336652
+-0.0041088188533721
+-0.0058273332996356
+-0.00727062096870851
+-0.0084334894941071
+-0.00931541332239757
+-0.0099204091949967
+-0.0102568377148858
+-0.0103371277935579
+-0.0101774361576858
+-0.00979724946072329
+-0.00921892960311577
+-0.00846722496704464
+-0.00756874635507542
+-0.00655142415066617
+-0.00544395757085389
+-0.00427525920508468
+-0.00307391993768759
+-0.00186768708315042
+-6.82980522572643e-4
+4.55555350931454e-4
+0.00152545134396061
+0.00250675668335827
+0.00338232730758133
+0.00413804459791576
+0.00476297411539252
+0.00524945134321352
+0.00559310428736023
+0.0057928072764395
+0.00585057149230045
+0.00577137823517525
+0.00556295588482682
+0.00523550974836302
+0.00480141038410035
+0.00427484711920302
+0.00367145812920719
+0.00300793964707363
+0.00230165125086365
+0.00157021607771463
+8.31132315629842e-4
+1.01397889009688e-4
+-6.02837209621259e-4
+-0.00126659496546869
+-0.0018763509819845
+-0.00242028158028417
+-0.0028884598696194
+-0.00327301016165189
+-0.00356820912785959
+-0.00377053814671627
+-0.00387868559008699
+-0.00389350186222283
+-0.00381790643652724
+-0.00365675622328083
+-0.00341666930468077
+-0.00310582337372604
+-0.0027337187227384
+-0.00231092502530074
+-0.00184880903364977
+-0.00135925347644246
+-8.54375818614214e-4
+-3.46245873742672e-4
+1.5338150399634e-4
+6.33323430643252e-4
+0.0010832027611814
+0.00149365620556701
+0.00185651528950842
+0.00216495311562251
+0.00241359905001614
+0.00259861436853517
+0.00271773284742105
+0.00277026461769735
+0.00275706287455375
+0.00268046014161941
+0.00254416760290437
+0.00235315096692847
+0.00211347938372566
+0.00183215385494268
+0.00151692075161767
+0.00117607035980743
+8.18234381982771e-4
+4.52176307534593e-4
+8.65878287229843e-5
+-2.70108419498178e-4
+-6.09943356897427e-4
+-9.25571871008901e-4
+-0.00121042184021843
+-0.0014588228462092
+-0.00166611043274461
+-0.00182870407402118
+-0.00194415758323169
+-0.00201118336129597
+-0.00202964706581313
+-0.00200054079682649
+-0.00192592281171168
+-0.00180884426159716
+-0.00165324714625177
+-0.00146385027634117
+-0.00124601613279792
+-0.0010056096258098
+-7.48849254545155e-4
+-4.82152145309325e-4
+-2.1198068576069e-4
+5.53078264280656e-5
+3.13605594907024e-4
+5.57187482764196e-4
+7.80834826954757e-4
+9.79937911476128e-4
+0.00115058933642334
+0.00128965157704395
+0.00139480951060361
+0.00146459939319946
+0.00149841919645406
+0.00149651846177726
+0.0014599674225506
+0.0013906093284534
+0.00129099572518951
+0.00116430673085702
+0.00101425950405569
+8.45007409820417e-4
+6.61030288225903e-4
+4.67021632594192e-4
+2.67772482152798e-4
+6.80586481779722e-5
+-1.27470456729415e-4
+-3.14396237291812e-4
+-4.8862706565045e-4
+-6.46484210138539e-4
+-7.84775133395688e-4
+-9.00853865253174e-4
+-9.92667960092833e-4
+-0.00105878723152578
+-0.00109842176590062
+-0.00111141913270169
+-0.00109825180635536
+-0.0010599866628307
+-9.98243562663091e-4
+-9.15141775653344e-4
+-8.13236256145513e-4
+-6.95445072726885e-4
+-5.6497087428213e-4
+-4.25218148098678e-4
+-2.79707337982926e-4
+-1.31990568245096e-4
+1.44330402738205e-5
+1.5619696018914e-4
+2.90142907465985e-4
+4.13387627487922e-4
+5.23381496018073e-4
+6.17959079267155e-4
+6.9537963487656e-4
+7.5435263217961e-4
+7.94056446208742e-4
+8.14142664644267e-4
+8.14730777273661e-4
+7.96391761417496e-4
+7.6012020281837e-4
+7.07299816040927e-4
+6.39657748300381e-4
+5.59215876696991e-4
+4.68233075668834e-4
+3.69146665341244e-4
+2.64508461181843e-4
+1.56922907604873e-4
+4.89841731832692e-5
+-5.6784716422895e-5
+-1.57988085254148e-4
+-2.52409733078722e-4
+-3.38060678040117e-4
+-4.13216007201208e-4
+-4.76451870743233e-4
+-5.26663373800026e-4
+-5.63086337917986e-4
+-5.85300692351394e-4
+-5.93232478671107e-4
+-5.87143099888524e-4
+-5.67613638239988e-4
+-5.35520428249821e-4
+-4.9200703290972e-4
+-4.38446131068721e-4
+-3.76404164136881e-4
+-3.07594047026731e-4
+-2.33835056002673e-4
+-1.57002327126315e-4
+-7.89848893170478e-5
+-1.63779237740676e-6
+7.3257656515258e-5
+1.44035366727157e-4
+2.09178855148142e-4
+2.67352241592445e-4
+3.17425558178502e-4
+3.58494957675319e-4
+3.89896739795703e-4
+4.11214766210894e-4
+4.22282619148847e-4
+4.23179220684935e-4
+4.14218377731336e-4
+3.95935025218761e-4
+3.69063740137675e-4
+3.34516779687324e-4
+2.93354710149485e-4
+2.46758430731207e-4
+1.95996823059339e-4
+1.4239311797007e-4
+8.72935203677178e-5
+3.20332747710491e-5
+-2.2092886327107e-5
+-7.38611116469124e-5
+-1.22144676611347e-4
+-1.65935928106054e-4
+-2.04367498164773e-4
+-2.36726227379411e-4
+-2.62467514354949e-4
+-2.81218526412152e-4
+-2.9278440100842e-4
+-2.97145272500789e-4
+-2.94450224275897e-4
+-2.85009149126569e-4
+-2.69279472445284e-4
+-2.47848788110117e-4
+-2.21419291675664e-4
+-1.90783149605849e-4
+-1.56806879798798e-4
+-1.20401080500299e-4
+-8.25032454022742e-5
+-4.40513605910619e-5
+-5.96356740813766e-6
+3.08848326050668e-5
+6.56776045971978e-5
+9.76776349699245e-5
+1.26238358089726e-4
+1.50819069616185e-4
+1.70990903256481e-4
+1.86445019398819e-4
+1.96994293467081e-4
+2.02573580216899e-4
+2.03236949574574e-4
+1.99151775086795e-4
+1.90590736122456e-4
+1.77921607229302e-4
+1.61594559165767e-4
+1.42129235004429e-4
+1.20099004917142e-4
+9.61160455879359e-5
+7.0815621084536e-5
+4.48385613205947e-5
+1.88188660219006e-5
+-6.63430458187306e-6
+-3.09472952504257e-5
+-5.35961801579358e-5
+-7.41158206776385e-5
+-9.21093274384085e-5
+-1.0725481963731e-4
+-1.19309561896777e-4
+-1.2811333539122e-4
+-1.33588879261025e-4
+-1.35739884161422e-4
+-1.34648743318249e-4
+-1.30468892775236e-4
+-1.23423041654638e-4
+-1.13790446423011e-4
+-1.01900589865764e-4
+-8.81236947188922e-5
+-7.28580214960265e-5
+-5.65228132450726e-5
+-3.95425112453473e-5
+-2.23418652788707e-5
+-5.33248429467424e-6
+1.10959100456974e-5
+2.65822878709086e-5
+4.08032785217656e-5
+5.347813081375e-5
+6.43756190395851e-5
+7.33144164498558e-5
+8.01683770409635e-5
+8.48651355449836e-5
+8.73861281253179e-5
+8.77652355990178e-5
+8.60846255633886e-5
+8.24733429562758e-5
+7.70982488738663e-5
+7.01613699670651e-5
+6.18941440803559e-5
+5.25469490585536e-5
+4.23881612033781e-5
+3.16889547008264e-5
+2.07264139138749e-5
+9.76750875584034e-6
+-9.29469045115252e-7
+-1.1125982738189e-5
+-2.06050398177054e-5
+-2.91770944785758e-5
+-3.66811426138427e-5
+-4.29902880316882e-5
+-4.80092456996724e-5
+-5.1680740099127e-5
+-5.39779986324577e-5
+-5.49127392818389e-5
+-5.45231256798723e-5
+-5.2881756318201e-5
+-5.00834846280012e-5
+-4.62496011329744e-5
+-4.15175966696302e-5
+-3.60413748500087e-5
+-2.99843308432599e-5
+-2.35164419241063e-5
+-1.68084780282784e-5
+-1.00309472232173e-5
+-3.34513850836547e-6
+3.09475951446394e-6
+9.15102381017684e-6
+1.46979062042561e-5
+1.9630985529227e-5
+2.3863596601089e-5
+2.73307787009361e-5
+2.99885330657398e-5
+3.18141310912695e-5
+3.28062497909458e-5
+3.29827423119358e-5
+3.23801498345e-5
+3.10523292715376e-5
+2.90669843834708e-5
+2.6504113480356e-5
+2.34525897473363e-5
+2.00104633597274e-5
+1.62776057022447e-5
+1.23587745013029e-5
+8.35431095023709e-6
+4.36391659133863e-6
+4.80912959878512e-7
+-3.20916832281648e-6
+-6.62826926323268e-6
+-9.71123313104019e-6
+-1.24032950277693e-5
+-1.46606892008227e-5
+-1.64542644771625e-5
+-1.77652468409902e-5
+-1.85905030202489e-5
+-1.89349221542663e-5
+-1.88180884125302e-5
+-1.82665081367835e-5
+-1.73187930064226e-5
+-1.60176157455328e-5
+-1.44140306102446e-5
+-1.25625562618188e-5
+-1.05213195267016e-5
+-8.34891011005015e-6
+-6.10417289473804e-6
+-3.84347493132933e-6
+-1.62303718375881e-6
+5.08537844109541e-7
+2.5045517191364e-6
+4.32718679501898e-6
+5.9411139708878e-6
+7.32184325292062e-6
+8.44836300475225e-6
+9.31094999767115e-6
+9.90357194955147e-6
+1.0228657500937e-5
+1.02939875082689e-5
+1.01139238186566e-5
+9.70730330637792e-6
+9.09759867217571e-6
+8.31026493121452e-6
+7.37667453186873e-6
+6.32696760641722e-6
+5.19442047840389e-6
+4.00982303462755e-6
+2.80519025479194e-6
+1.61065667346661e-6
+4.5272033468355e-7
+-6.41630367682649e-7
+-1.65168508479184e-6
+-2.55698769776267e-6
+-3.34381409235837e-6
+-4.00121137621988e-6
+-4.52057551249377e-6
+-4.90048958017337e-6
+-5.1394946501258e-6
+-5.24183699733879e-6
+-5.21373005767686e-6
+-5.063623966477e-6
+-4.80493586876171e-6
+-4.44917701834718e-6
+-4.01344340051503e-6
+-3.51170040070893e-6
+-2.96212165638707e-6
+-2.38006119965271e-6
+-1.78302023739655e-6
+-1.18587637892365e-6
+-6.0197624767097e-7
+-4.49606767418064e-8
+4.73800121500147e-7
+9.44346239710729e-7
+1.35846743996931e-6
+1.71076949967104e-6
+1.99610535588337e-6
+2.21343228064008e-6
+2.36167902121603e-6
+2.44371789997691e-6
+2.46085469574341e-6
+2.41942298528229e-6
+2.32279469282784e-6
+2.17833876701336e-6
+1.99304439308787e-6
+1.77357589639965e-6
+1.53005288621509e-6
+1.26826910787562e-6
+9.97486152500784e-7
+7.23956612504e-7
+4.53619817534114e-7
+1.95178720022609e-7
+-4.79481886690687e-8
+-2.69324680211038e-7
+-4.67089278916325e-7
+-6.37499558026062e-7
+-7.77649486859982e-7
+-8.87746045951503e-7
+-9.67049604607247e-7
+-1.01783166180378e-6
+-1.03946679063045e-6
+-1.03355489807237e-6
+-1.00406302340324e-6
+-9.516801687493e-7
+-8.83009467313344e-7
+-7.96695832853341e-7
+-7.00817920677767e-7
+-5.9487324901853e-7
+-4.85000602763094e-7
+-3.72869415873669e-7
+-2.62247401958816e-7
+-1.55165787913079e-7
+-5.50094412531977e-8
+3.83506638823491e-8
+1.20312660464537e-7
+1.93531346067046e-7
+2.53431354500078e-7
+3.02990066262988e-7
+3.39343358482371e-7
+3.65236448771379e-7
+3.77007825091848e-7
+3.80032136027046e-7
+3.71753520789388e-7
+3.57246917030831e-7
+3.34271689565622e-7
+3.05703733943038e-7
+2.72939884477538e-7
+2.3707190547137e-7
+1.99015401296622e-7
+1.6066011924682e-7
+1.20450960766471e-7
+8.33872247697555e-8
+4.71079084065085e-8
+1.51839061412207e-8
+-1.43267231105268e-8
+-3.99528124923842e-8
+-6.14126768147793e-8
+-7.89956849981134e-8
+-9.17625273815014e-8
+-1.01333875812554e-7
+-1.07199067922224e-7
+-1.09899151121439e-7
+-1.09342060902351e-7
+-1.0581696028102e-7
+-1.00062504114338e-7
+-9.19816359673906e-8
+-8.35519847400028e-8
+-7.34212411189246e-8
+-6.3122768061061e-8
+-5.15215025811016e-8
+-4.14587362468332e-8
+-3.19847926493859e-8
+-2.18251091115114e-8
+-1.25339352914121e-8
+-4.35513294668295e-9
+1.83985020585335e-9
+6.05954400825878e-9
+1.07557125018314e-8
+1.3068715878392e-8
+1.76960158618376e-8
+1.95132650596489e-8
+2.22929661801192e-8
+2.09724315061768e-8
+2.00800027395966e-8
+1.74208569471553e-8
+1.41716278773579e-8
+1.30077482700426e-8
+1.14333552786323e-8
+1.03271192432242e-8
+1.10906859282933e-8
+8.38300275294078e-9
+1.03151991819582e-8
diff --git a/fir/c96000pal.h b/fir/c96000pal.h
new file mode 100644
index 00000000..454888a7
--- /dev/null
+++ b/fir/c96000pal.h
@@ -0,0 +1,512 @@
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+-1,
+-1,
+-1,
+-1,
+-1,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+0,
+1,
+1,
+1,
+1,
+2,
+2,
+2,
+2,
+2,
+2,
+2,
+2,
+2,
+1,
+1,
+0,
+0,
+0,
+0,
+-1,
+-1,
+-2,
+-3,
+-3,
+-4,
+-4,
+-5,
+-5,
+-5,
+-5,
+-5,
+-5,
+-4,
+-4,
+-3,
+-2,
+-1,
+0,
+0,
+1,
+2,
+4,
+5,
+6,
+7,
+8,
+9,
+10,
+10,
+10,
+10,
+10,
+9,
+8,
+7,
+6,
+4,
+2,
+0,
+-1,
+-4,
+-6,
+-8,
+-11,
+-13,
+-15,
+-16,
+-18,
+-19,
+-19,
+-19,
+-19,
+-18,
+-17,
+-15,
+-13,
+-10,
+-6,
+-3,
+0,
+4,
+8,
+12,
+17,
+20,
+24,
+27,
+30,
+32,
+33,
+34,
+34,
+33,
+31,
+28,
+25,
+20,
+15,
+9,
+3,
+-3,
+-10,
+-17,
+-24,
+-31,
+-37,
+-43,
+-48,
+-52,
+-55,
+-57,
+-57,
+-56,
+-54,
+-50,
+-45,
+-38,
+-30,
+-21,
+-11,
+0,
+10,
+21,
+33,
+44,
+55,
+64,
+73,
+80,
+86,
+90,
+92,
+91,
+88,
+84,
+76,
+67,
+56,
+42,
+27,
+11,
+-5,
+-23,
+-41,
+-59,
+-76,
+-92,
+-106,
+-119,
+-129,
+-136,
+-141,
+-142,
+-140,
+-134,
+-125,
+-112,
+-96,
+-77,
+-56,
+-32,
+-6,
+19,
+47,
+74,
+100,
+125,
+149,
+169,
+186,
+199,
+208,
+213,
+212,
+206,
+195,
+179,
+158,
+132,
+102,
+68,
+32,
+-6,
+-46,
+-86,
+-126,
+-164,
+-200,
+-232,
+-259,
+-282,
+-298,
+-308,
+-311,
+-307,
+-294,
+-275,
+-248,
+-214,
+-173,
+-128,
+-77,
+-23,
+33,
+91,
+149,
+205,
+258,
+307,
+350,
+386,
+415,
+434,
+443,
+442,
+431,
+408,
+375,
+332,
+280,
+219,
+151,
+76,
+-1,
+-82,
+-164,
+-245,
+-322,
+-394,
+-459,
+-515,
+-561,
+-595,
+-615,
+-622,
+-613,
+-590,
+-552,
+-499,
+-433,
+-354,
+-264,
+-165,
+-59,
+51,
+164,
+277,
+387,
+490,
+586,
+670,
+741,
+797,
+835,
+854,
+853,
+832,
+790,
+729,
+647,
+548,
+433,
+304,
+163,
+15,
+-138,
+-293,
+-445,
+-592,
+-729,
+-852,
+-959,
+-1046,
+-1111,
+-1151,
+-1165,
+-1151,
+-1110,
+-1040,
+-944,
+-822,
+-677,
+-512,
+-329,
+-133,
+71,
+280,
+489,
+693,
+886,
+1063,
+1220,
+1353,
+1458,
+1530,
+1569,
+1571,
+1535,
+1462,
+1352,
+1206,
+1027,
+818,
+584,
+328,
+57,
+-222,
+-505,
+-785,
+-1054,
+-1306,
+-1534,
+-1733,
+-1896,
+-2019,
+-2097,
+-2128,
+-2108,
+-2038,
+-1917,
+-1747,
+-1529,
+-1269,
+-970,
+-639,
+-283,
+90,
+474,
+857,
+1233,
+1590,
+1921,
+2216,
+2467,
+2667,
+2810,
+2890,
+2904,
+2849,
+2724,
+2530,
+2270,
+1946,
+1566,
+1135,
+664,
+160,
+-363,
+-895,
+-1425,
+-1938,
+-2423,
+-2866,
+-3256,
+-3582,
+-3834,
+-4003,
+-4082,
+-4067,
+-3953,
+-3741,
+-3431,
+-3028,
+-2537,
+-1967,
+-1328,
+-632,
+106,
+871,
+1646,
+2413,
+3154,
+3849,
+4482,
+5034,
+5489,
+5833,
+6051,
+6134,
+6074,
+5864,
+5504,
+4994,
+4339,
+3546,
+2628,
+1599,
+477,
+-716,
+-1958,
+-3223,
+-4482,
+-5708,
+-6869,
+-7936,
+-8878,
+-9666,
+-10273,
+-10671,
+-10839,
+-10755,
+-10402,
+-9767,
+-8843,
+-7623,
+-6110,
+-4308,
+-2228,
+114,
+2701,
+5505,
+8499,
+11650,
+14923,
+18277,
+21673,
+25068,
+28417,
+31678,
+34807,
+37762,
+40502,
+42991,
+45192,
+47076,
+48617,
+49792,
+50584,
+50983,
diff --git a/fir/c96000pal.scm b/fir/c96000pal.scm
new file mode 100644
index 00000000..fee6e0cc
--- /dev/null
+++ b/fir/c96000pal.scm
@@ -0,0 +1,12 @@
+(title "96000 PAL")
+
+(verbose #t)
+
+(cosine-symmetry)
+(filter-length 1024)
+(sampling-frequency 1662607.125)
+(limit-= (band 0 33400) 1)
+(limit-= (band 48000 831303.5625) 0 .5)
+(output-file "c96000pal.coef")
+(plot-file "c96000pal.plot")
+(go)
diff --git a/fir/toh.c b/fir/toh.c
new file mode 100644
index 00000000..9dffba69
--- /dev/null
+++ b/fir/toh.c
@@ -0,0 +1,24 @@
+#include <stdio.h>
+
+#define MAX 512
+
+main()
+{
+ char buf[256];
+ int count=0;
+
+ while(fgets(buf,256,stdin)>0)
+ {
+ double p;
+
+ if(sscanf(buf,"%lf",&p)==1)
+ {
+ p*=65536*16;
+ printf("%ld,\n",(long)p);
+ count++;
+ if(count==MAX) break;
+ }
+
+ }
+
+}
diff --git a/general.c b/general.c
new file mode 100644
index 00000000..540b2050
--- /dev/null
+++ b/general.c
@@ -0,0 +1,314 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "types.h"
+#include "fceu.h"
+
+#include "general.h"
+#include "state.h"
+#include "movie.h"
+
+#include "driver.h"
+
+#include "md5.h"
+
+static char BaseDirectory[2048];
+char FileBase[2048];
+static char FileExt[2048]; /* Includes the . character, as in ".nes" */
+
+static char FileBaseDirectory[2048];
+
+void FCEUI_SetBaseDirectory(char *dir)
+{
+ strncpy(BaseDirectory,dir,2047);
+ BaseDirectory[2047]=0;
+}
+
+static char *odirs[FCEUIOD__COUNT]={0,0,0,0,0}; // odirs, odors. ^_^
+
+void FCEUI_SetDirOverride(int which, char *n)
+{
+// FCEU_PrintError("odirs[%d]=%s->%s", which, odirs[which], n);
+if(which < FCEUIOD__COUNT)
+ odirs[which]=n;
+
+ if(FCEUGameInfo) /* Rebuild cache of present states/movies. */
+ {
+ if(which==FCEUIOD_STATE)
+ FCEUSS_CheckStates();
+ else if(which == FCEUIOD_MISC)
+ FCEUMOV_CheckMovies();
+ }
+}
+
+#ifndef HAVE_ASPRINTF
+static int asprintf(char **strp, const char *fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap,fmt);
+ if(!(*strp=malloc(2048)))
+ return(0);
+ ret=vsnprintf(*strp,2048,fmt,ap);
+ va_end(ap);
+ return(ret);
+}
+#endif
+
+char* FCEU_GetPath(int type)
+{
+ char *ret=0;
+ switch(type)
+ {
+ case FCEUMKF_STATE:if(odirs[FCEUIOD_STATE])
+ ret=strdup(odirs[FCEUIOD_STATE]);
+ else
+ asprintf(&ret,"%s"PSS"movie",BaseDirectory);
+ break;
+ case FCEUMKF_MOVIE:if(odirs[FCEUIOD_MISC])
+ ret=strdup(odirs[FCEUIOD_MISC]);
+ else
+ asprintf(&ret,"%s"PSS"movie",BaseDirectory);
+ break;
+ }
+ return(ret);
+}
+
+char *FCEU_MakePath(int type, const char* filebase)
+{
+ char *ret=0;
+
+ switch(type)
+ {
+ case FCEUMKF_MOVIE:if(odirs[FCEUIOD_MISC])
+ asprintf(&ret,"%s"PSS"%s",odirs[FCEUIOD_MISC],filebase);
+ else
+ asprintf(&ret,"%s"PSS"movie"PSS"%s",BaseDirectory,filebase);
+ break;
+ }
+ return(ret);
+}
+
+char *FCEU_MakeFName(int type, int id1, char *cd1)
+{
+ char *ret=0;
+ struct stat tmpstat;
+
+ switch(type)
+ {
+ case FCEUMKF_NPTEMP: asprintf(&ret,"%s"PSS"m590plqd94fo.tmp",BaseDirectory);break;
+ case FCEUMKF_MOVIE:if(id1>=0)
+ {
+ if(odirs[FCEUIOD_MISC])
+ asprintf(&ret,"%s"PSS"%s.%d.fcm",odirs[FCEUIOD_MISC],FileBase,id1);
+ else
+ asprintf(&ret,"%s"PSS"movie"PSS"%s.%d.fcm",BaseDirectory,FileBase,id1);
+ if(stat(ret,&tmpstat)==-1)
+ {
+ if(odirs[FCEUIOD_MISC])
+ asprintf(&ret,"%s"PSS"%s.%d.fcm",odirs[FCEUIOD_MISC],FileBase,id1);
+ else
+ asprintf(&ret,"%s"PSS"movie"PSS"%s.%d.fcm",BaseDirectory,FileBase,id1);
+ }
+ }
+ else
+ {
+ if(odirs[FCEUIOD_MISC])
+ asprintf(&ret,"%s"PSS"%s.fcm",odirs[FCEUIOD_MISC],FileBase);
+ else
+ asprintf(&ret,"%s"PSS"movie"PSS"%s.fcm",BaseDirectory,FileBase);
+ }
+ break;
+ case FCEUMKF_STATE:
+ if(odirs[FCEUIOD_STATE])
+ {
+ asprintf(&ret,"%s"PSS"%s.fc%d",odirs[FCEUIOD_STATE],FileBase,id1);
+ }
+ else
+ {
+ asprintf(&ret,"%s"PSS"fcs"PSS"%s.fc%d",BaseDirectory,FileBase,id1);
+ }
+ if(stat(ret,&tmpstat)==-1)
+ {
+ if(odirs[FCEUIOD_STATE])
+ {
+ asprintf(&ret,"%s"PSS"%s.fc%d",odirs[FCEUIOD_STATE],FileBase,id1);
+ }
+ else
+ {
+ asprintf(&ret,"%s"PSS"fcs"PSS"%s.fc%d",BaseDirectory,FileBase,id1);
+ }
+ }
+ break;
+ case FCEUMKF_SNAP:
+ if(FSettings.SnapName)
+ {
+ if(odirs[FCEUIOD_SNAPS])
+ asprintf(&ret,"%s"PSS"%s-%d.%s",odirs[FCEUIOD_SNAPS],FileBase,id1,cd1);
+ else
+ asprintf(&ret,"%s"PSS"snaps"PSS"%s-%d.%s",BaseDirectory,FileBase,id1,cd1);
+ }
+ else
+ {
+ if(odirs[FCEUIOD_SNAPS])
+ asprintf(&ret,"%s"PSS"%d.%s",odirs[FCEUIOD_SNAPS],id1,cd1);
+ else
+ asprintf(&ret,"%s"PSS"snaps"PSS"%d.%s",BaseDirectory,id1,cd1);
+ }
+ break;
+ case FCEUMKF_FDS:if(odirs[FCEUIOD_NV])
+ asprintf(&ret,"%s"PSS"%s.fds",odirs[FCEUIOD_NV],FileBase);
+ else
+ asprintf(&ret,"%s"PSS"sav"PSS"%s.fds",BaseDirectory,FileBase);
+ break;
+ case FCEUMKF_SAV:if(odirs[FCEUIOD_NV])
+ asprintf(&ret,"%s"PSS"%s.%s",odirs[FCEUIOD_NV],FileBase,cd1);
+ else
+ asprintf(&ret,"%s"PSS"sav"PSS"%s.%s",BaseDirectory,FileBase,cd1);
+ if(stat(ret,&tmpstat)==-1)
+ {
+ if(odirs[FCEUIOD_NV])
+ asprintf(&ret,"%s"PSS"%s.%s",odirs[FCEUIOD_NV],FileBase,cd1);
+ else
+ asprintf(&ret,"%s"PSS"sav"PSS"%s.%s",BaseDirectory,FileBase,cd1);
+ }
+ break;
+ case FCEUMKF_REWINDSTATE:
+ if(odirs[FCEUIOD_STATE])
+ {
+ asprintf(&ret,"%s"PSS"rewind%d.fcs",odirs[FCEUIOD_STATE],id1);
+ }
+ else
+ {
+ asprintf(&ret,"%s"PSS"fcs"PSS"rewind%d.fcs",BaseDirectory,id1);
+ }
+ if(stat(ret,&tmpstat)==-1)
+ {
+ if(odirs[FCEUIOD_STATE])
+ {
+ asprintf(&ret,"%s"PSS"rewind%d.fcs",odirs[FCEUIOD_STATE],id1);
+ }
+ else
+ {
+ asprintf(&ret,"%s"PSS"fcs"PSS"rewind%d.fcs",BaseDirectory,id1);
+ }
+ }
+ break;
+ case FCEUMKF_CHEAT:
+ if(odirs[FCEUIOD_CHEATS])
+ asprintf(&ret,"%s"PSS"%s.cht",odirs[FCEUIOD_CHEATS],FileBase);
+ else
+ asprintf(&ret,"%s"PSS"cheats"PSS"%s.cht",BaseDirectory,FileBase);
+ break;
+ case FCEUMKF_IPS: asprintf(&ret,"%s"PSS"%s%s.ips",FileBaseDirectory,FileBase,FileExt);
+ break;
+ case FCEUMKF_GGROM:asprintf(&ret,"%s"PSS"gg.rom",BaseDirectory);break;
+ case FCEUMKF_FDSROM:asprintf(&ret,"%s"PSS"disksys.rom",BaseDirectory);break;
+ case FCEUMKF_PALETTE:
+ if(odirs[FCEUIOD_MISC])
+ asprintf(&ret,"%s"PSS"%s.pal",odirs[FCEUIOD_MISC],FileBase);
+ else
+ asprintf(&ret,"%s"PSS"%s.pal",BaseDirectory,FileBase);
+ break;
+ case FCEUMKF_MOVIEGLOB:
+ if(odirs[FCEUIOD_MISC])
+// asprintf(&ret,"%s"PSS"%s*.fcm",odirs[FCEUIOD_MISC],FileBase);
+ asprintf(&ret,"%s"PSS"*.???",odirs[FCEUIOD_MISC]);
+ else
+// asprintf(&ret,"%s"PSS"fcs"PSS"%s*.fcm",BaseDirectory,FileBase);
+ asprintf(&ret,"%s"PSS"movie"PSS"*.???",BaseDirectory);
+ break;
+ case FCEUMKF_MOVIEGLOB2:
+ asprintf(&ret,"%s"PSS"*.???",BaseDirectory);
+ break;
+ case FCEUMKF_STATEGLOB:
+ if(odirs[FCEUIOD_STATE])
+ asprintf(&ret,"%s"PSS"%s*.fc?",odirs[FCEUIOD_STATE],FileBase);
+ else
+ asprintf(&ret,"%s"PSS"fcs"PSS"%s*.fc?",BaseDirectory,FileBase);
+ break;
+ }
+ return(ret);
+}
+
+void GetFileBase(const char *f)
+{
+ const char *tp1,*tp3;
+
+ #if PSS_STYLE==4
+ tp1=((char *)strrchr(f,':'));
+ #elif PSS_STYLE==1
+ tp1=((char *)strrchr(f,'/'));
+ #else
+ tp1=((char *)strrchr(f,'\\'));
+ #if PSS_STYLE!=3
+ tp3=((char *)strrchr(f,'/'));
+ if(tp1<tp3) tp1=tp3;
+ #endif
+ #endif
+ if(!tp1)
+ {
+ tp1=f;
+ strcpy(FileBaseDirectory,".");
+ }
+ else
+ {
+ memcpy(FileBaseDirectory,f,tp1-f);
+ FileBaseDirectory[tp1-f]=0;
+ tp1++;
+ }
+
+ if(((tp3=strrchr(f,'.'))!=NULL) && (tp3>tp1))
+ {
+ memcpy(FileBase,tp1,tp3-tp1);
+ FileBase[tp3-tp1]=0;
+ strcpy(FileExt,tp3);
+ }
+ else
+ {
+ strcpy(FileBase,tp1);
+ FileExt[0]=0;
+ }
+}
+
+uint32 uppow2(uint32 n)
+{
+ int x;
+
+ for(x=31;x>=0;x--)
+ if(n&(1<<x))
+ {
+ if((1<<x)!=n)
+ return(1<<(x+1));
+ break;
+ }
+ return n;
+}
+
diff --git a/general.h b/general.h
new file mode 100644
index 00000000..68e7b443
--- /dev/null
+++ b/general.h
@@ -0,0 +1,22 @@
+void GetFileBase(const char *f);
+extern uint32 uppow2(uint32 n);
+
+char* FCEU_GetPath(int type);
+char *FCEU_MakePath(int type, const char* filebase);
+char *FCEU_MakeFName(int type, int id1, char *cd1);
+
+#define FCEUMKF_STATE 1
+#define FCEUMKF_SNAP 2
+#define FCEUMKF_SAV 3
+#define FCEUMKF_CHEAT 4
+#define FCEUMKF_FDSROM 5
+#define FCEUMKF_PALETTE 6
+#define FCEUMKF_GGROM 7
+#define FCEUMKF_IPS 8
+#define FCEUMKF_FDS 9
+#define FCEUMKF_MOVIE 10
+#define FCEUMKF_NPTEMP 11
+#define FCEUMKF_MOVIEGLOB 12
+#define FCEUMKF_STATEGLOB 13
+#define FCEUMKF_MOVIEGLOB2 14
+#define FCEUMKF_REWINDSTATE 15
diff --git a/git.h b/git.h
new file mode 100644
index 00000000..bbe64051
--- /dev/null
+++ b/git.h
@@ -0,0 +1,29 @@
+#ifndef __FCEU_GIT
+#define __FCEU_GIT
+/* Mmm...git. Almost as funny as "gimp". */
+#define GIT_CART 0 /* Cart. */
+#define GIT_VSUNI 1 /* VS Unisystem. */
+#define GIT_FDS 2 /* Famicom Disk System. */
+#define GIT_NSF 3 /* NES Sound Format. */
+
+#define GIV_NTSC 0 /* NTSC emulation. */
+#define GIV_PAL 1 /* PAL emulation. */
+#define GIV_USER 2 /* What was set by FCEUI_SetVidSys(). */
+
+typedef struct {
+ uint8 *name; /* Game name, UTF8 encoding */
+
+ int type; /* GIT_* */
+ int vidsys; /* Current emulated video system; GIV_* */
+ int input[2]; /* Desired input for emulated input ports 1 and 2; -1
+ for unknown desired input. */
+ int inputfc; /* Desired Famicom expansion port device. -1 for unknown
+ desired input. */
+ int cspecial; /* Special cart expansion: DIP switches, barcode
+ reader, etc.
+ */
+ uint8 MD5[16];
+ int soundrate; /* For Ogg Vorbis expansion sound wacky support. 0 for default. */
+ int soundchan; /* Number of sound channels. */
+} FCEUGI;
+#endif
diff --git a/ines-bad.h b/ines-bad.h
new file mode 100644
index 00000000..20f0cf79
--- /dev/null
+++ b/ines-bad.h
@@ -0,0 +1,38 @@
+{ 0xecf78d8a13a030a6LL, "Ai Sensei no Oshiete", INESB_HACKED },
+{ 0x10f90ba5bd55c22eLL, "Alien Syndrome", INESB_HACKED },
+{ 0x4712856d3e12f21fLL, "Akumajou Densetsu", INESB_HACKED },
+{ 0x0d69ab3ad28ad1c2LL, "Banana", INESB_INCOMPLETE },
+{ 0x85d2c348a161cdbfLL, "Bio Senshi Dan", INESB_HACKED },
+{ 0x18fdb7c16aa8cb5cLL, "Bucky O'Hare", INESB_CORRUPT },
+{ 0xe27c48302108d11bLL, "Chibi Maruko Chan", INESB_HACKED },
+{ 0x9d1f505c6ba507bfLL, "Contra", INESB_HACKED },
+{ 0x60936436d3ea0ab6LL, "Crisis Force", INESB_HACKED },
+{ 0xcf31097ddbb03c5dLL, "Crystalis (Prototype)", INESB_CORRUPT },
+{ 0x92080a8ce94200eaLL, "Digital Devil Story II", INESB_HACKED },
+{ 0x97f133d8bc1c28dbLL, "Dragon Ball", INESB_HACKED },
+{ 0x6c2a2f95c2fe4b6eLL, "Dragon Ball", INESB_HACKED },
+{ 0x767aaff62963c58fLL, "Dragon Ball", INESB_HACKED },
+{ 0x500b267abb323005LL, "Dragon Warrior 4", INESB_CORRUPT },
+{ 0x02bdcf375704784bLL, "Erika to Satoru no Yume Bouken", INESB_HACKED },
+{ 0xd4fea9d2633b9186LL, "Famista 91", INESB_HACKED },
+{ 0xfdf8c812839b61f0LL, "Famista 92", INESB_HACKED },
+{ 0xb5bb1d0fb47d0850LL, "Famista 93", INESB_HACKED },
+{ 0x30471e773f7cdc89LL, "Famista 94", INESB_HACKED },
+{ 0x76c5c44ffb4a0bd7LL, "Fantasy Zone", INESB_HACKED },
+{ 0x27da2b0c500dc346LL, "Fire Emblem", INESB_HACKED },
+{ 0xb470bfb90e2b1049LL, "Fire Emblem Gaiden", INESB_HACKED },
+{ 0x23214fe456fba2ceLL, "Ganbare Goemon 2", INESB_HACKED },
+{ 0xbf8b22524e8329d9LL, "Ganbare Goemon Gaiden", INESB_HACKED },
+{ 0xa97041c3da0134e3LL, "Gegege no Kitarou 2", INESB_INCOMPLETE },
+{ 0x805db49a86db5449LL, "Goonies", INESB_HACKED },
+{ 0xc5abdaa65ac49b6bLL, "Gradius 2", INESB_HACKED },
+{ 0x04afae4ad480c11cLL, "Gradius 2", INESB_HACKED },
+{ 0x9b4bad37b5498992LL, "Gradius 2", INESB_HACKED },
+{ 0xb068d4ac10ef848eLL, "Highway Star", INESB_HACKED },
+{ 0xbf5175271e5019c3LL, "Kaiketsu Yanchamaru 3", INESB_HACKED },
+{ 0xfb4b508a236bbba3LL, "Salamander", INESB_HACKED },
+{ 0x3716c4bebf885344LL, "Super Mario Bros.", INESB_HACKED },
+{ 0x1895afc6eef26c7dLL, "Super Mario Bros.", INESB_HACKED },
+{ 0x103fc85d978b861bLL, "Sweet Home", INESB_CORRUPT },
+{ 0xfffda4407d80885aLL, "Sweet Home", INESB_CORRUPT },
+{ 0, 0, 0 }
diff --git a/ines-correct.h b/ines-correct.h
new file mode 100644
index 00000000..054b0eca
--- /dev/null
+++ b/ines-correct.h
@@ -0,0 +1,213 @@
+ {0x9cbadc25,5,8}, /* JustBreed */
+
+ {0x6e68e31a,16,8}, /* Dragon Ball 3*/
+ {0x3f15d20d,153,8}, /* Famicom Jump 2 */
+ {0x983d8175,157,8}, /* Datach Battle Rush */
+ {0x894efdbc,157,8}, /* Datach Crayon Shin Chan */
+ {0x19e81461,157,8}, /* Datach DBZ */
+ {0xbe06853f,157,8}, /* Datach J-League */
+ {0x0be0a328,157,8}, /* Datach SD Gundam Wars */
+ {0x5b457641,157,8}, /* Datach Ultraman Club */
+ {0xf51a7f46,157,8}, /* Datach Yuu Yuu Hakusho */
+
+ {0xe62e3382,71,-1}, /* Mig-29 Soviet Fighter */
+ {0x21a653c7,4,-1}, /* Super Sky Kid */
+
+ {0xdd4d9a62,209,-1}, /* Shin Samurai Spirits 2 */
+ {0x063b1151,209,-1}, /* Power Rangers 4 */
+ {0xdd8ced31,209,-1}, /* Power Rangers 3 */
+
+ {0x0c47946d,210,-1}, /* Chibi Maruko Chan */
+ {0xbd523011,210,-1}, /* Dream Master */
+ {0xc247cc80,210,-1}, /* Family Circuit '91 */
+ {0x6ec51de5,210,-1}, /* Famista '92 */
+ {0xadffd64f,210,-1}, /* Famista '93 */
+ {0x429103c9,210,-1}, /* Famista '94 */
+ {0x81b7f1a8,210,-1}, /* Heisei Tensai Bakabon */
+ {0x2447e03b,210,-1}, /* Top Striker */
+ {0x1dc0f740,210,-1}, /* Wagyan Land 2 */
+ {0xd323b806,210,-1}, /* Wagyan Land 3 */
+ {0x07eb2c12,208,-1}, /* Street Fighter IV */
+ {0x96ce586e,189,8}, /* Street Fighter 2 YOKO */
+ {0x7678f1d5,207,8}, /* Fudou Myouou Den */
+ {0x276237b3,206,0}, /* Karnov */
+ {0x4e1c1e3c,206,0}, /* Karnov */
+
+ /* Some entries to sort out the minor 33/48 mess. */
+ {0xaebd6549,48,8}, /* Bakushou!! Jinsei Gekijou 3 */
+ {0x6cdc0cd9,48,8}, /* Bubble Bobble 2 */
+ //{0x10e24006,48,8}, /* Flintstones 2 - bad dump? */
+ {0x40c0ad47,48,8}, /* Flintstones 2 */
+ {0xa7b0536c,48,8}, /* Don Doko Don 2 */
+ {0x99c395f9,48,8}, /* Captain Saver */
+ {0x1500e835,48,8}, /* Jetsons (J) */
+
+ {0x637134e8,193,1}, /* Fighting Hero */
+ {0xcbf4366f,158,8}, /* Alien Syndrome (U.S. unlicensed) */
+ {0xb19a55dd,64,8}, /* Road Runner */
+ //{0x3eafd012,116,-1}, /* AV Girl Fighting */
+ {0x1d0f4d6b,2,1}, /* Black Bass thinging */
+ {0xf92be3ec,64,-1}, /* Rolling Thunder */
+ {0x345ee51a,245,-1}, /* DQ4c */
+ {0xf518dd58,7,8}, /* Captain Skyhawk */
+ {0x7ccb12a3,43,-1}, /* SMB2j */
+ {0x6f12afc5,235,-1}, /* Golden Game 150-in-1 */
+ {0xccc03440,156,-1},
+ {0xc9ee15a7,3,-1}, /* 3 is probably best. 41 WILL NOT WORK. */
+
+ {0x3e1271d5,79,1}, /* Tiles of Fate */
+ {0x8eab381c,113,1}, /* Death Bots */
+
+ {0xd4a76b07,79,0}, /* F-15 City Wars*/
+ {0xa4fbb438,79,0},
+
+ {0x1eb4a920,79,1}, /* Double Strike */
+ {0x345d3a1a,11,1}, /* Castle of Deceit */
+ {0x62ef6c79,232,8}, /* Quattro Sports -Aladdin */
+ {0x5caa3e61,144,1}, /* Death Race */
+ {0xd2699893,88,0}, /* Dragon Spirit */
+
+ {0x2f27cdef,155,8}, /* Tatakae!! Rahmen Man */
+ {0xcfd4a281,155,8}, /* Money Game. Yay for money! */
+ {0xd1691028,154,8}, /* Devil Man */
+
+ {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 */
+
+{0x15141401,4,8}, /* Asmik Kun Land */
+{0x59280bec,4,8}, /* Jackie Chan */
+{0x4cccd878,4,8}, /* Cat Ninden Teyandee */
+{0x9eefb4b4,4,8}, /* Pachi Slot Adventure 2 */
+{0x5337f73c,4,8}, /* Niji no Silk Road */
+{0x7474ac92,4,8}, /* Kabuki: Quantum Fighter */
+
+{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) */
+
+{0xe28f2596,0,1}, /* Pac Land (J) */
+{0xfcdaca80,0,0}, /* Elevator Action */
+{0xe492d45a,0,0}, /* Zippy Race */
+{0x32fa246f,0,0}, /* Tag Team Pro Wrestling */
+{0xc05a365b,0,0}, /* Exed Exes (J) */
+{0xb3c30bea,0,0}, /* Xevious (J) */
+
+{0x804f898a,2,1}, /* Dragon Unit */
+{0xe1b260da,2,1}, /* Argos no Senshi */
+{0x6d65cac6,2,0}, /* Terra Cresta */
+{0x9ea1dc76,2,0}, /* Rainbow Islands */
+{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 */
+{0x266ce198,2,1}, /* City Adventure Touch */
+
+//{0x48349b0b,1,8}, /* Dragon Quest 2 */
+{0xd09b74dc,1,8}, /* Great Tank (J) */
+{0xe8baa782,1,8}, /* Gun Hed (J) */
+{0x970bd9c2,1,8}, /* Hanjuku Hero */
+{0xcd7a2fd7,1,8}, /* Hanjuku Hero */
+{0x63469396,1,8}, /* Hokuto no Ken 4 */
+{0x291bcd7d,1,8}, /* Pachio Kun 2 */
+{0xf74dfc91,1,-1}, /* Win, Lose, or Draw */
+
+ {0x3f56a392,1,8}, /* Captain Ed (J) */
+ {0x078ced30,1,8}, /* Choujin - Ultra Baseball */
+ {0x391aa1b8,1,8}, /* Bloody Warriors (J) */
+ {0x61a852ea,1,8}, /* Battle Stadium - Senbatsu Pro Yakyuu */
+ {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 */
+ {0x70f67ab7,1,8}, /* Musashi no Bouken */
+ {0xa9a4ea4c,1,8}, /* Satomi Hakkenden */
+ {0xcc3544b0,1,8}, /* Triathron */
+
+ {0x1d41cc8c,3,1}, /* Gyruss */
+ {0xd8eff0df,3,1}, /* Gradius (J) */
+ {0xdbf90772,3,0}, /* Alpha Mission */
+ {0xd858033d,3,0}, /* Armored Scrum Object */
+ {0xcf322bb3,3,1}, /* John Elway's Quarterback */
+ {0x9bde3267,3,1}, /* Adventures of Dino Riki */
+ {0x02cc3973,3,1}, /* 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,140,1}, /* Youkai Club*/
+{0xc2df0a00,140,1}, /* Bio Senshi Dan(hacked) */
+{0xbde3ae9b,66,1}, /* Doraemon */
+{0xd26efd78,66,1}, /* SMB Duck Hunt */
+{0x811f06d9,66,1}, /* Dragon Power */
+{0x3293afea,140,1}, /* Mississippi Satsujin Jiken */
+{0xe84274c5,66,1}, /* "" "" */
+{0x9552e8df,66,1}, /* Dragon Ball */
+
+ {0xba51ac6f,78,2},
+ {0x3d1c3137,78,8}, /* Uchuusen - Cosmo Carrier */
+
+ {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 */
+
+ {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 */
+ {0xa912b064,51|0x800,8}, /* 11-in-1 Ball Games(has CHR ROM when it shouldn't) */
+ {0xc5e5c5b2,115,-1}, /* Bao Qing Tian (As).nes */
+
+ {0xcfb224e6,-1,1}, /* Dragon Ninja (J) [p1][!].nes */
+ {0xf46ef39a,37,-1}, /* Super Mario Bros. + Tetris + Nintendo World Cup (E) [!] */
+ {0x0f05ff0a,181,-1}, /* Seicross (redump) */
+
+ {0x054bd3e9,74,-1}, /* Di 4 Ci - Ji Qi Ren Dai Zhan (As) */
+ {0x496ac8f7,74,-1}, /* Ji Jia Zhan Shi (As) */
+ {0xae854cef,74,-1}, /* Jia A Fung Yun (Chinese) */
+ {0x2cc381f6,191,-1}, /* Sugoro Quest - Dice no Senshitachi (As) */
+ {0x555a555e,191,-1},
+ {0x98c1cd4b,192,-1},/* Ying Lie Qun Xia Zhuan (Chinese) */
+ {0x442f1a29,192,-1},/* Young chivalry */
+ {0xa925226c,194,-1},/* Dai-2-Ji - Super Robot Taisen (As) */
+ {0xd5224fde,198,-1},/* [074]Crystalis (c) */
+ {0x1bc0be6c,198,-1},/* Captain Tsubasa Vol 2 - Super Striker (C) */
+ {0xdd431ba7,199,-1},/* Tenchi wo kurau 2 (c) */
+ {0x28192599,199,-1},
+ {0x700705f4,199,-1},
+ {0x9a2cf02c,199,-1},
+ {0xd8b401a7,199,-1},
+
+ {0x1f1326d4,218,-1},
+ {0xa1dc16c0,116,-1},
+ {0,-1,-1}
diff --git a/ines.c b/ines.c
new file mode 100644
index 00000000..62651970
--- /dev/null
+++ b/ines.c
@@ -0,0 +1,1362 @@
+/* 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _USE_SHARED_MEMORY_
+#include <windows.h>
+#endif
+
+#include "types.h"
+#include "x6502.h"
+#include "fceu.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"
+
+extern SFORMAT FCEUVSUNI_STATEINFO[];
+
+static uint8 *trainerpoo=0;
+static uint8 *ROM=NULL;
+static uint8 *VROM=NULL;
+
+#ifdef _USE_SHARED_MEMORY_
+HANDLE mapROM, mapVROM;
+#endif
+
+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])
+ {
+ SetReadHandler(0x7000,0x71FF,TrainerRead);
+ break;
+ }
+ }
+ }
+ break;
+ case GI_CLOSE:
+ {
+ FCEU_SaveGameSave(&iNESCart);
+
+ if(iNESCart.Close) iNESCart.Close();
+#ifdef _USE_SHARED_MEMORY_
+ if(ROM)
+ {
+ if(mapROM)
+ {
+ UnmapViewOfFile(mapROM);
+ CloseHandle(mapROM);
+ ROM=0;
+ }
+ else
+ {
+ free(ROM);
+ ROM = NULL;
+ }
+ }
+ if(VROM)
+ {
+ if(mapVROM)
+ {
+ UnmapViewOfFile(mapVROM);
+ CloseHandle(mapVROM);
+ VROM=0;
+ }
+ else
+ {
+ free(VROM);
+ VROM = NULL;
+ }
+ }
+#else
+ if(ROM) {free(ROM);ROM=0;}
+ if(VROM) {free(VROM);VROM=0;}
+#endif
+ 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 */
+
+ {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 */
+ {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 */
+ {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 */
+ {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;
+#ifdef _USE_SHARED_MEMORY_
+ if(mapVROM)
+ {
+ UnmapViewOfFile(mapVROM);
+ CloseHandle(mapVROM);
+ }
+ else
+ {
+ free(VROM);
+ }
+#else
+ free(VROM);
+#endif
+ 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, FCEUFILE *fp, int OverwriteVidMode)
+{
+ 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;
+
+#ifdef _USE_SHARED_MEMORY_
+ mapROM = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE, 0, ROM_size<<14,"fceu.ROM");
+ if(mapROM == NULL || GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ mapROM = NULL;
+ CloseHandle(mapROM);
+
+ if(!(ROM=(uint8 *)FCEU_malloc(ROM_size<<14)))
+ return 0;
+
+ if(VROM_size)
+ {
+ if(!(VROM=(uint8 *)FCEU_malloc(VROM_size<<13)))
+ {
+ free(ROM);
+ ROM = NULL;
+ return 0;
+ }
+ }
+ }
+ else
+ {
+ ROM = (uint8 *)MapViewOfFile(mapROM, FILE_MAP_WRITE, 0, 0, 0);
+ if( !ROM ) return 0;
+
+ if(VROM_size)
+ {
+ mapVROM = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE, 0, VROM_size<<13,"fceu.VROM");
+ VROM = (uint8 *)MapViewOfFile(mapVROM, FILE_MAP_WRITE, 0, 0, 0);
+ if( !VROM )
+ {
+ UnmapViewOfFile(mapROM);
+ CloseHandle(mapROM);
+ return 0;
+ }
+ }
+ }
+#else
+ 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;
+ }
+ }
+#endif
+ 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(OverwriteVidMode)
+ {
+ 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
+};
+*/
+void (*MapInitTab[256])(void)=
+{
+ 0,0, //Mapper2_init,Mapper3_init,
+ 0,0,
+ 0,0,
+ Mapper6_init,
+ 0,//Mapper7_init,
+ Mapper8_init,Mapper9_init,
+ Mapper10_init,
+ 0, //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,
+ 0,// Mapper57_init,
+ 0,// Mapper58_init,
+ Mapper59_init,Mapper60_init,
+ Mapper61_init,Mapper62_init,
+ 0,
+ Mapper64_init,Mapper65_init,
+ 0,//Mapper66_init,
+ Mapper67_init,
+ Mapper68_init,Mapper69_init,
+ 0,//Mapper70_init,
+ Mapper71_init,
+ Mapper72_init,Mapper73_init,
+ 0,
+ Mapper75_init,Mapper76_init,Mapper77_init,
+ 0, //Mapper78_init,
+ Mapper79_init,Mapper80_init,
+ 0,
+ Mapper82_init,Mapper83_init,
+ 0,
+ Mapper85_init,Mapper86_init,
+ 0, //Mapper87_init,
+ 0, //Mapper88_init,
+ Mapper89_init,
+ 0,
+ Mapper91_init,Mapper92_init,
+ 0, //Mapper93_init,
+ 0, //Mapper94_init,
+ 0,
+ Mapper96_init,Mapper97_init,
+ 0,
+ Mapper99_init,
+ 0,0,0,0,0,0,0,
+ 0, //Mapper107_init,
+ 0,0,0,0,
+ 0,Mapper113_init,
+ 0,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,
+ 0, //Mapper140_init,
+ 0,0,0,
+ 0, //Mapper144_init,
+ 0,0,0,0,0,0,
+ Mapper151_init,
+ 0, //Mapper152_init,
+ Mapper153_init,
+ 0, //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,
+ 0, //Mapper185_init,
+ 0,0,0,
+ 0, //Mapper189_init,
+ 0,
+ 0, //Mapper191_init,
+ 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,
+ 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,
+ 0, //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,131072-8192);
+ else
+ memset(GameMemBlock,0,131072);
+
+ 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 BMAPPING bmap[] = {
+ {0, NROM_Init},
+ {1, Mapper1_Init},
+ {2, UNROM_Init},
+ {3, CNROM_Init},
+ {4, Mapper4_Init},
+ {5, Mapper5_Init},
+ {7, ANROM_Init},
+ {11, Mapper11_Init},
+ {12, Mapper12_Init},
+ {13, CPROM_Init},
+ {19, Mapper19_Init},
+ {37, Mapper37_Init},
+ {44, Mapper44_Init},
+ {45, Mapper45_Init},
+ {47, Mapper47_Init},
+ {49, Mapper49_Init},
+ {52, Mapper52_Init},
+ {57, Mapper57_Init},
+ {58, Mapper58_Init},
+ {66, MHROM_Init},
+ {70, Mapper70_Init},
+ {74, Mapper74_Init},
+ {78, Mapper78_Init},
+ {87, Mapper87_Init},
+ {88, Mapper88_Init},
+ {90, Mapper90_Init},
+ {93, SUNSOFT_UNROM_Init},
+ {94, Mapper94_Init},
+ {95, Mapper95_Init},
+ {105, Mapper105_Init},
+ {107, Mapper107_Init},
+ {112, Mapper112_Init},
+ {114, Mapper114_Init},
+ {115, Mapper115_Init},
+ {116, Mapper116_Init},
+ {117, Mapper117_Init},
+ {118, Mapper118_Init},
+ {119, Mapper119_Init},
+ {133, SA72008_Init},
+ {137, S8259D_Init},
+ {138, S8259B_Init},
+ {139, S8259C_Init},
+ {140, Mapper140_Init},
+ {141, S8259A_Init},
+ {143, TCA01_Init},
+ {144, Mapper144_Init},
+ {145, SA72007_Init},
+ {146, SA0161M_Init},
+ {147, TCU01_Init},
+ {148, SA0037_Init},
+ {149, SA0036_Init},
+ {150, S74LS374N_Init},
+ {152, Mapper152_Init},
+ {154, Mapper154_Init},
+ {155, Mapper155_Init},
+ {160, Mapper90_Init},
+ {163, Mapper163_Init},
+ {164, Mapper164_Init},
+ {165, Mapper165_Init},
+ {181, Mapper181_Init},
+ {182, Mapper182_Init},
+ {183, Mapper183_Init},
+ {185, Mapper185_Init},
+ {186, Mapper186_Init},
+ {187, Mapper187_Init},
+ {188, Mapper188_Init},
+ {189, Mapper189_Init},
+ {191, Mapper191_Init},
+ {192, Mapper192_Init},
+ {194, Mapper194_Init},
+ {198, Mapper198_Init},
+ {199, Mapper199_Init},
+ {205, Mapper205_Init},
+ {206, DEIROM_Init},
+ {208, Mapper208_Init},
+ {209, Mapper209_Init},
+ {210, Mapper210_Init},
+ {211, Mapper211_Init},
+ {215, Mapper215_Init},
+ {216, Mapper216_Init},
+ {217, Mapper217_Init},
+ {218, UNLSonic_Init},
+ {219, UNLSL1632_Init},
+// {220, Mapper220_Init},
+ {222, Mapper222_Init},
+ {235, Mapper235_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;
+ }
+#ifdef _USE_SHARED_MEMORY_
+ mapVROM = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE, 0, CHRRAMSize,"fceu.VROM");
+ if(mapVROM == NULL || GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ CloseHandle(mapVROM);
+ mapVROM = NULL;
+ VROM=(uint8 *)malloc(CHRRAMSize);
+ }
+ else
+ {
+ VROM = (uint8 *)MapViewOfFile(mapVROM, FILE_MAP_WRITE, 0, 0, 0);
+ }
+#else
+ VROM=(uint8 *)malloc(CHRRAMSize);
+#endif
+ 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
new file mode 100644
index 00000000..0d707e64
--- /dev/null
+++ b/ines.h
@@ -0,0 +1,389 @@
+/* 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
+ */
+
+#ifdef INESPRIV
+
+void iNESStateRestore(int version);
+extern uint32 iNESGameCRC32;
+
+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 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 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 Mapper113_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 Mapper139_init(void);
+//void Mapper140_init(void);
+void Mapper141_init(void);
+void Mapper142_init(void);
+void Mapper143_init(void);
+//void Mapper144_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 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 Mapper11_Init(CartInfo *);
+void Mapper12_Init(CartInfo *);
+void Mapper19_Init(CartInfo *);
+void Mapper37_Init(CartInfo *);
+void Mapper44_Init(CartInfo *);
+void Mapper45_Init(CartInfo *);
+void Mapper47_Init(CartInfo *);
+void Mapper49_Init(CartInfo *);
+void Mapper52_Init(CartInfo *);
+void Mapper57_Init(CartInfo *);
+void Mapper58_Init(CartInfo *);
+void Mapper70_Init(CartInfo *);
+void Mapper74_Init(CartInfo *);
+void Mapper78_Init(CartInfo *);
+void Mapper87_Init(CartInfo *);
+void Mapper88_Init(CartInfo *);
+void Mapper90_Init(CartInfo *);
+void Mapper93_Init(CartInfo *);
+void Mapper94_Init(CartInfo *);
+void Mapper95_Init(CartInfo *);
+void Mapper105_Init(CartInfo *);
+void Mapper107_Init(CartInfo *);
+void Mapper112_Init(CartInfo *);
+void Mapper114_Init(CartInfo *);
+void Mapper115_Init(CartInfo *);
+void Mapper116_Init(CartInfo *);
+void Mapper117_Init(CartInfo *);
+void Mapper118_Init(CartInfo *);
+void Mapper119_Init(CartInfo *);
+void Mapper125_Init(CartInfo *);
+void Mapper140_Init(CartInfo *);
+void Mapper144_Init(CartInfo *);
+void Mapper152_Init(CartInfo *);
+void Mapper154_Init(CartInfo *);
+void Mapper155_Init(CartInfo *);
+void Mapper163_Init(CartInfo *);
+void Mapper164_Init(CartInfo *);
+void Mapper165_Init(CartInfo *);
+void Mapper181_Init(CartInfo *);
+void Mapper182_Init(CartInfo *);
+void Mapper183_Init(CartInfo *);
+void Mapper185_Init(CartInfo *);
+void Mapper186_Init(CartInfo *);
+void Mapper187_Init(CartInfo *);
+void Mapper188_Init(CartInfo *);
+void Mapper189_Init(CartInfo *);
+void Mapper191_Init(CartInfo *);
+void Mapper192_Init(CartInfo *);
+void Mapper194_Init(CartInfo *);
+void Mapper198_Init(CartInfo *);
+void Mapper199_Init(CartInfo *);
+void Mapper205_Init(CartInfo *);
+void Mapper208_Init(CartInfo *);
+void Mapper209_Init(CartInfo *);
+void Mapper210_Init(CartInfo *);
+void Mapper211_Init(CartInfo *);
+void Mapper215_Init(CartInfo *);
+void Mapper216_Init(CartInfo *);
+void Mapper217_Init(CartInfo *);
+void Mapper220_Init(CartInfo *);
+void Mapper222_Init(CartInfo *);
+void Mapper235_Init(CartInfo *);
+void Mapper236_Init(CartInfo *);
+void Mapper237_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
new file mode 100644
index 00000000..ae5ed142
--- /dev/null
+++ b/input.c
@@ -0,0 +1,772 @@
+/* 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 <string.h>
+
+#include "types.h"
+#include "x6502.h"
+
+#include "fceu.h"
+#include "sound.h"
+#include "netplay.h"
+#include "movie.h"
+#include "state.h"
+
+#include "input.h"
+#include "vsuni.h"
+#include "fds.h"
+
+extern INPUTC *FCEU_InitZapper(int w);
+extern INPUTC *FCEU_InitPowerpadA(int w);
+extern INPUTC *FCEU_InitPowerpadB(int w);
+extern INPUTC *FCEU_InitArkanoid(int w);
+
+extern INPUTCFC *FCEU_InitArkanoidFC(void);
+extern INPUTCFC *FCEU_InitSpaceShadow(void);
+extern INPUTCFC *FCEU_InitFKB(void);
+extern INPUTCFC *FCEU_InitSuborKB(void);
+extern INPUTCFC *FCEU_InitHS(void);
+extern INPUTCFC *FCEU_InitMahjong(void);
+extern INPUTCFC *FCEU_InitQuizKing(void);
+extern INPUTCFC *FCEU_InitFamilyTrainerA(void);
+extern INPUTCFC *FCEU_InitFamilyTrainerB(void);
+extern INPUTCFC *FCEU_InitOekaKids(void);
+extern INPUTCFC *FCEU_InitTopRider(void);
+extern INPUTCFC *FCEU_InitBarcodeWorld(void);
+
+static uint8 joy_readbit[2];
+static uint8 joy[4]={0,0,0,0};
+static uint8 LastStrobe;
+
+static int BotMode = 0;
+#ifdef _USE_SHARED_MEMORY_
+static int BotPointer = 0;
+#endif
+
+/* 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]);
+}
+extern uint8 coinon;
+
+static int FSDisable=0; /* Set to 1 if NES-style four-player adapter is disabled. */
+static int JPAttrib[2]={0,0};
+static int JPType[2]={0,0};
+static void *InputDataPtr[2];
+
+static int JPAttribFC=0;
+static int JPTypeFC=0;
+static void *InputDataPtrFC;
+
+void (*InputScanlineHook)(uint8 *bg, uint8 *spr, uint32 linets, int final);
+
+
+static INPUTC DummyJPort={0,0,0,0,0};
+static INPUTC *JPorts[2]={&DummyJPort,&DummyJPort};
+static INPUTCFC *FCExp=0;
+
+static uint8 FP_FASTAPASS(1) ReadGPVS(int w)
+{
+ uint8 ret=0;
+
+ if(joy_readbit[w]>=8)
+ ret=1;
+ else
+ {
+ ret = ((joy[w]>>(joy_readbit[w]))&1);
+ if(!fceuindbg)
+ joy_readbit[w]++;
+ }
+ return ret;
+}
+
+static uint8 FP_FASTAPASS(1) ReadGP(int w)
+{
+ uint8 ret;
+
+ if(joy_readbit[w]>=8)
+ ret = ((joy[2+w]>>(joy_readbit[w]&7))&1);
+ else
+ ret = ((joy[w]>>(joy_readbit[w]))&1);
+ if(joy_readbit[w]>=16) ret=0;
+ if(FSDisable)
+ {
+ if(joy_readbit[w]>=8) ret|=1;
+ }
+ else
+ {
+ if(joy_readbit[w]==19-w) ret|=1;
+ }
+ if(!fceuindbg)
+ joy_readbit[w]++;
+ return ret;
+}
+
+static DECLFR(JPRead)
+{
+ uint8 ret=0;
+
+ if(JPorts[A&1]->Read)
+ ret|=JPorts[A&1]->Read(A&1);
+
+ if(FCExp)
+ if(FCExp->Read)
+ ret=FCExp->Read(A&1,ret);
+
+ ret|=X.DB&0xC0;
+ return(ret);
+}
+
+static DECLFW(B4016)
+{
+ if(FCExp)
+ if(FCExp->Write)
+ FCExp->Write(V&7);
+
+ if(JPorts[0]->Write)
+ JPorts[0]->Write(V&1);
+ if(JPorts[1]->Write)
+ JPorts[1]->Write(V&1);
+
+ if((LastStrobe&1) && (!(V&1)))
+ {
+ /* This strobe code is just for convenience. If it were
+ with the code in input / *.c, it would more accurately represent
+ what's really going on. But who wants accuracy? ;)
+ Seriously, though, this shouldn't be a problem.
+ */
+ if(JPorts[0]->Strobe)
+ JPorts[0]->Strobe(0);
+ if(JPorts[1]->Strobe)
+ JPorts[1]->Strobe(1);
+ if(FCExp)
+ if(FCExp->Strobe)
+ FCExp->Strobe();
+ }
+ LastStrobe=V&0x1;
+}
+
+static void FP_FASTAPASS(1) StrobeGP(int w)
+{
+ joy_readbit[w]=0;
+}
+
+static INPUTC GPC={ReadGP,0,StrobeGP,0,0,0};
+static INPUTC GPCVS={ReadGPVS,0,StrobeGP,0,0,0};
+
+int FCEU_BotMode()
+{
+ return BotMode;
+}
+
+void FCEU_SetBotMode(int x)
+{
+ BotMode = x;
+}
+
+void FCEU_DrawInput(uint8 *buf)
+{
+ int x;
+
+ for(x=0;x<2;x++)
+ if(JPorts[x]->Draw)
+ JPorts[x]->Draw(x,buf,JPAttrib[x]);
+ if(FCExp)
+ if(FCExp->Draw)
+ FCExp->Draw(buf,JPAttribFC);
+}
+
+void FCEU_UpdateBot()
+{
+#ifdef _USE_SHARED_MEMORY_
+ //This is the external input (aka bot) code
+ if(!BotMode)
+ return;
+ if(BotInput[0])
+ {
+ BotPointer++;
+ switch(BotInput[BotPointer] >> 16)
+ {
+ case 0:
+ joy[0] = BotInput[BotPointer] & 255;
+ joy[1] = BotInput[BotPointer] >> 8;
+ joy[2] = joy[3] = 0;
+ FCEUI_FrameAdvance();
+ break;
+ case 1:
+ FCEUI_LoadState(0);
+ break;
+ default:
+ break;
+ }
+
+ //Bot input ends; let the world know we're done
+ if(BotPointer >= BotInput[0] || BotPointer >= 1023)
+ {
+ BotInput[0] = 0;
+ BotPointer = 0;
+ }
+ }
+ else
+ {
+ BotPointer = 0;
+ joy[0] = joy[1] = joy[2] = joy[3] = 0;
+ }
+#endif //_USE_SHARED_MEMORY_
+}
+
+void FCEU_UpdateInput(void)
+{
+ if(!FCEUMOV_IsPlaying() && !BotMode)
+ {
+ int x;
+
+ for(x=0;x<2;x++)
+ {
+ switch(JPType[x])
+ {
+ case SI_GAMEPAD:
+ if(!x)
+ {
+ joy[0]=*(uint32 *)InputDataPtr[0];
+ joy[2]=*(uint32 *)InputDataPtr[0] >> 16;
+ }
+ else
+ {
+ joy[1]=*(uint32 *)InputDataPtr[1] >>8;
+ joy[3]=*(uint32 *)InputDataPtr[1] >>24;
+ }
+ break;
+ default:
+ if(JPorts[x]->Update)
+ JPorts[x]->Update(x,InputDataPtr[x],JPAttrib[x]);
+ break;
+ }
+ }
+ if(FCExp)
+ if(FCExp->Update)
+ FCExp->Update(InputDataPtrFC,JPAttribFC);
+ }
+
+ if(FCEUGameInfo->type==GIT_VSUNI)
+ if(coinon) coinon--;
+
+ if(FCEUnetplay)
+ NetplayUpdate(joy);
+
+ FCEUMOV_AddJoy(joy, BotMode);
+
+ if(FCEUGameInfo->type==GIT_VSUNI)
+ FCEU_VSUniSwap(&joy[0],&joy[1]);
+}
+
+static DECLFR(VSUNIRead0)
+{
+ uint8 ret=0;
+
+ if(JPorts[0]->Read)
+ ret|=(JPorts[0]->Read(0))&1;
+
+ ret|=(vsdip&3)<<3;
+ if(coinon)
+ ret|=0x4;
+ return ret;
+}
+
+static DECLFR(VSUNIRead1)
+{
+ uint8 ret=0;
+
+ if(JPorts[1]->Read)
+ ret|=(JPorts[1]->Read(1))&1;
+ ret|=vsdip&0xFC;
+ return ret;
+}
+
+static void SLHLHook(uint8 *bg, uint8 *spr, uint32 linets, int final)
+{
+ int x;
+
+ for(x=0;x<2;x++)
+ if(JPorts[x]->SLHook)
+ JPorts[x]->SLHook(x,bg,spr,linets,final);
+ if(FCExp)
+ if(FCExp->SLHook)
+ FCExp->SLHook(bg,spr,linets,final);
+}
+
+static void CheckSLHook(void)
+{
+ InputScanlineHook=0;
+ if(JPorts[0]->SLHook || JPorts[1]->SLHook)
+ InputScanlineHook=SLHLHook;
+ if(FCExp)
+ if(FCExp->SLHook)
+ InputScanlineHook=SLHLHook;
+}
+
+static void FASTAPASS(1) SetInputStuff(int x)
+{
+ switch(JPType[x])
+ {
+ case SI_GAMEPAD:
+ if(FCEUGameInfo->type==GIT_VSUNI)
+ JPorts[x] = &GPCVS;
+ else
+ JPorts[x]=&GPC;
+ break;
+ case SI_ARKANOID:JPorts[x]=FCEU_InitArkanoid(x);break;
+ case SI_ZAPPER:JPorts[x]=FCEU_InitZapper(x);break;
+ case SI_POWERPADA:JPorts[x]=FCEU_InitPowerpadA(x);break;
+ case SI_POWERPADB:JPorts[x]=FCEU_InitPowerpadB(x);break;
+ case SI_NONE:JPorts[x]=&DummyJPort;break;
+ }
+
+ CheckSLHook();
+}
+
+static uint8 F4ReadBit[2];
+static void StrobeFami4(void)
+{
+ F4ReadBit[0]=F4ReadBit[1]=0;
+}
+
+static uint8 FP_FASTAPASS(2) ReadFami4(int w, uint8 ret)
+{
+ ret&=1;
+
+ ret |= ((joy[2+w]>>(F4ReadBit[w]))&1)<<1;
+ if(F4ReadBit[w]>=8) ret|=2;
+ else F4ReadBit[w]++;
+
+ return(ret);
+}
+
+static INPUTCFC FAMI4C={ReadFami4,0,StrobeFami4,0,0,0};
+static void SetInputStuffFC(void)
+{
+ switch(JPTypeFC)
+ {
+ case SIFC_NONE:FCExp=0;break;
+ case SIFC_ARKANOID:FCExp=FCEU_InitArkanoidFC();break;
+ case SIFC_SHADOW:FCExp=FCEU_InitSpaceShadow();break;
+ case SIFC_OEKAKIDS:FCExp=FCEU_InitOekaKids();break;
+ case SIFC_4PLAYER:FCExp=&FAMI4C;memset(&F4ReadBit,0,sizeof(F4ReadBit));break;
+ case SIFC_FKB:FCExp=FCEU_InitFKB();break;
+ case SIFC_SUBORKB:FCExp=FCEU_InitSuborKB();break;
+ case SIFC_HYPERSHOT:FCExp=FCEU_InitHS();break;
+ case SIFC_MAHJONG:FCExp=FCEU_InitMahjong();break;
+ case SIFC_QUIZKING:FCExp=FCEU_InitQuizKing();break;
+ case SIFC_FTRAINERA:FCExp=FCEU_InitFamilyTrainerA();break;
+ case SIFC_FTRAINERB:FCExp=FCEU_InitFamilyTrainerB();break;
+ case SIFC_BWORLD:FCExp=FCEU_InitBarcodeWorld();break;
+ case SIFC_TOPRIDER:FCExp=FCEU_InitTopRider();break;
+ }
+ CheckSLHook();
+}
+
+void InitializeInput(void)
+{
+ memset(joy_readbit,0,sizeof(joy_readbit));
+ memset(joy,0,sizeof(joy));
+ LastStrobe = 0;
+
+ if(FCEUGameInfo->type==GIT_VSUNI)
+ {
+ SetReadHandler(0x4016,0x4016,VSUNIRead0);
+ SetReadHandler(0x4017,0x4017,VSUNIRead1);
+ }
+ else
+ SetReadHandler(0x4016,0x4017,JPRead);
+
+ SetWriteHandler(0x4016,0x4016,B4016);
+
+ SetInputStuff(0);
+ SetInputStuff(1);
+ SetInputStuffFC();
+}
+
+void FCEUI_SetInput(int port, int type, void *ptr, int attrib)
+{
+ JPAttrib[port]=attrib;
+ JPType[port]=type;
+ InputDataPtr[port]=ptr;
+ SetInputStuff(port);
+}
+
+void FCEUI_DisableFourScore(int s)
+{
+ FSDisable=s;
+}
+
+void FCEUI_SetInputFC(int type, void *ptr, int attrib)
+{
+ JPAttribFC=attrib;
+ JPTypeFC=type;
+ InputDataPtrFC=ptr;
+ SetInputStuffFC();
+}
+
+SFORMAT FCEUCTRL_STATEINFO[]={
+ { joy_readbit, 2, "JYRB"},
+ { joy, 4, "JOYS"},
+ { &LastStrobe, 1, "LSTS"},
+ { 0 }
+ };
+
+
+void FCEU_DoSimpleCommand(int cmd)
+{
+ switch(cmd)
+ {
+ 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_POWER: PowerNES();break;
+ case FCEUNPCMD_RESET: ResetNES();break;
+ }
+}
+
+void FCEU_QSimpleCommand(int cmd)
+{
+ if(FCEUnetplay)
+ FCEUNET_SendCommand(cmd, 0);
+ else
+ {
+ 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);
+}
+
+const char* FCEUI_CommandTypeNames[]=
+{
+ "Misc.",
+ "Speed",
+ "State",
+ "Movie",
+ "Sound",
+ "AVI",
+ "FDS",
+ "VS Sys",
+};
+
+static void CommandUnImpl(void);
+static void CommandToggleDip(void);
+static void CommandStateLoad(void);
+static void CommandStateSave(void);
+static void CommandSelectSaveSlot(void);
+static void CommandEmulationSpeed(void);
+static void CommandMovieSelectSlot(void);
+static void CommandMovieRecord(void);
+static void CommandMovieReplay(void);
+static void CommandSoundAdjust(void);
+static void ViewSlots(void);
+
+struct EMUCMDTABLE FCEUI_CommandTable[]=
+{
+ { EMUCMD_POWER, EMUCMDTYPE_MISC, FCEUI_PowerNES, 0, 0, "Power", },
+ { EMUCMD_RESET, EMUCMDTYPE_MISC, FCEUI_ResetNES, 0, 0, "Reset", },
+ { EMUCMD_PAUSE, EMUCMDTYPE_MISC, FCEUI_ToggleEmulationPause, 0, 0, "Pause", },
+ { EMUCMD_FRAME_ADVANCE, EMUCMDTYPE_MISC, FCEUI_FrameAdvance, 0, 0, "Frame Advance", },
+ { EMUCMD_SCREENSHOT, EMUCMDTYPE_MISC, FCEUI_SaveSnapshot, 0, 0, "Screenshot", },
+ { EMUCMD_HIDE_MENU_TOGGLE, EMUCMDTYPE_MISC, FCEUD_HideMenuToggle, 0, 0, "Hide Menu Toggle", },
+
+ { EMUCMD_SPEED_SLOWEST, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Slowest Speed", },
+ { EMUCMD_SPEED_SLOWER, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Speed Down", },
+ { EMUCMD_SPEED_NORMAL, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Normal Speed", },
+ { EMUCMD_SPEED_FASTER, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Speed Up", },
+ { EMUCMD_SPEED_FASTEST, EMUCMDTYPE_SPEED, CommandEmulationSpeed, 0, 0, "Fastest Speed", },
+ { EMUCMD_SPEED_TURBO, EMUCMDTYPE_SPEED, FCEUD_TurboOn, FCEUD_TurboOff, 0, "Turbo", },
+
+ { EMUCMD_SAVE_SLOT_0, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 0", },
+ { EMUCMD_SAVE_SLOT_1, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 1", },
+ { EMUCMD_SAVE_SLOT_2, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 2", },
+ { EMUCMD_SAVE_SLOT_3, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 3", },
+ { EMUCMD_SAVE_SLOT_4, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 4", },
+ { EMUCMD_SAVE_SLOT_5, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 5", },
+ { EMUCMD_SAVE_SLOT_6, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 6", },
+ { EMUCMD_SAVE_SLOT_7, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 7", },
+ { EMUCMD_SAVE_SLOT_8, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 8", },
+ { EMUCMD_SAVE_SLOT_9, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Savestate Slot 9", },
+ { EMUCMD_SAVE_SLOT_NEXT, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Next Savestate Slot", },
+ { EMUCMD_SAVE_SLOT_PREV, EMUCMDTYPE_STATE, CommandSelectSaveSlot, 0, 0, "Previous Savestate Slot", },
+ { EMUCMD_SAVE_STATE, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State", },
+ { EMUCMD_SAVE_STATE_AS, EMUCMDTYPE_STATE, FCEUD_SaveStateAs, 0, 0, "Save State As...", },
+ { EMUCMD_SAVE_STATE_SLOT_0, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 0", },
+ { EMUCMD_SAVE_STATE_SLOT_1, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 1", },
+ { EMUCMD_SAVE_STATE_SLOT_2, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 2", },
+ { EMUCMD_SAVE_STATE_SLOT_3, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 3", },
+ { EMUCMD_SAVE_STATE_SLOT_4, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 4", },
+ { EMUCMD_SAVE_STATE_SLOT_5, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 5", },
+ { EMUCMD_SAVE_STATE_SLOT_6, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 6", },
+ { EMUCMD_SAVE_STATE_SLOT_7, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 7", },
+ { EMUCMD_SAVE_STATE_SLOT_8, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 8", },
+ { EMUCMD_SAVE_STATE_SLOT_9, EMUCMDTYPE_STATE, CommandStateSave, 0, 0, "Save State to Slot 9", },
+ { EMUCMD_LOAD_STATE, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State", },
+ { EMUCMD_LOAD_STATE_FROM, EMUCMDTYPE_STATE, FCEUD_LoadStateFrom, 0, 0, "Load State From...", },
+ { EMUCMD_LOAD_STATE_SLOT_0, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 0", },
+ { EMUCMD_LOAD_STATE_SLOT_1, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 1", },
+ { EMUCMD_LOAD_STATE_SLOT_2, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 2", },
+ { EMUCMD_LOAD_STATE_SLOT_3, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 3", },
+ { EMUCMD_LOAD_STATE_SLOT_4, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 4", },
+ { EMUCMD_LOAD_STATE_SLOT_5, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 5", },
+ { EMUCMD_LOAD_STATE_SLOT_6, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 6", },
+ { EMUCMD_LOAD_STATE_SLOT_7, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 7", },
+ { EMUCMD_LOAD_STATE_SLOT_8, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 8", },
+ { EMUCMD_LOAD_STATE_SLOT_9, EMUCMDTYPE_STATE, CommandStateLoad, 0, 0, "Load State from Slot 9", },
+
+/* { EMUCMD_MOVIE_SLOT_0, EMUCMDTYPE_MOVIE, CommandMovieSelectSlot, 0, 0, "Movie Slot 0", },
+ { EMUCMD_MOVIE_SLOT_1, EMUCMDTYPE_MOVIE, CommandMovieSelectSlot, 0, 0, "Movie Slot 1", },
+ { EMUCMD_MOVIE_SLOT_2, EMUCMDTYPE_MOVIE, CommandMovieSelectSlot, 0, 0, "Movie Slot 2", },
+ { EMUCMD_MOVIE_SLOT_3, EMUCMDTYPE_MOVIE, CommandMovieSelectSlot, 0, 0, "Movie Slot 3", },
+ { EMUCMD_MOVIE_SLOT_4, EMUCMDTYPE_MOVIE, CommandMovieSelectSlot, 0, 0, "Movie Slot 4", },
+ { EMUCMD_MOVIE_SLOT_5, EMUCMDTYPE_MOVIE, CommandMovieSelectSlot, 0, 0, "Movie Slot 5", },
+ { EMUCMD_MOVIE_SLOT_6, EMUCMDTYPE_MOVIE, CommandMovieSelectSlot, 0, 0, "Movie Slot 6", },
+ { EMUCMD_MOVIE_SLOT_7, EMUCMDTYPE_MOVIE, CommandMovieSelectSlot, 0, 0, "Movie Slot 7", },
+ { EMUCMD_MOVIE_SLOT_8, EMUCMDTYPE_MOVIE, CommandMovieSelectSlot, 0, 0, "Movie Slot 8", },
+ { EMUCMD_MOVIE_SLOT_9, EMUCMDTYPE_MOVIE, CommandMovieSelectSlot, 0, 0, "Movie Slot 9", },
+ { EMUCMD_MOVIE_SLOT_NEXT, EMUCMDTYPE_MOVIE, CommandMovieSelectSlot, 0, 0, "Next Movie Slot", },
+ { EMUCMD_MOVIE_SLOT_PREV, EMUCMDTYPE_MOVIE, CommandMovieSelectSlot, 0, 0, "Previous Movie Slot", },
+ { EMUCMD_MOVIE_RECORD, EMUCMDTYPE_MOVIE, CommandMovieRecord, 0, 0, "Record Movie", },*/
+ { EMUCMD_MOVIE_RECORD_TO, EMUCMDTYPE_MOVIE, FCEUD_MovieRecordTo, 0, 0, "Record Movie To...", },
+/* { EMUCMD_MOVIE_RECORD_SLOT_0, EMUCMDTYPE_MOVIE, CommandMovieRecord, 0, 0, "Record Movie to Slot 0", },
+ { EMUCMD_MOVIE_RECORD_SLOT_1, EMUCMDTYPE_MOVIE, CommandMovieRecord, 0, 0, "Record Movie to Slot 1", },
+ { EMUCMD_MOVIE_RECORD_SLOT_2, EMUCMDTYPE_MOVIE, CommandMovieRecord, 0, 0, "Record Movie to Slot 2", },
+ { EMUCMD_MOVIE_RECORD_SLOT_3, EMUCMDTYPE_MOVIE, CommandMovieRecord, 0, 0, "Record Movie to Slot 3", },
+ { EMUCMD_MOVIE_RECORD_SLOT_4, EMUCMDTYPE_MOVIE, CommandMovieRecord, 0, 0, "Record Movie to Slot 4", },
+ { EMUCMD_MOVIE_RECORD_SLOT_5, EMUCMDTYPE_MOVIE, CommandMovieRecord, 0, 0, "Record Movie to Slot 5", },
+ { EMUCMD_MOVIE_RECORD_SLOT_6, EMUCMDTYPE_MOVIE, CommandMovieRecord, 0, 0, "Record Movie to Slot 6", },
+ { EMUCMD_MOVIE_RECORD_SLOT_7, EMUCMDTYPE_MOVIE, CommandMovieRecord, 0, 0, "Record Movie to Slot 7", },
+ { EMUCMD_MOVIE_RECORD_SLOT_8, EMUCMDTYPE_MOVIE, CommandMovieRecord, 0, 0, "Record Movie to Slot 8", },
+ { EMUCMD_MOVIE_RECORD_SLOT_9, EMUCMDTYPE_MOVIE, CommandMovieRecord, 0, 0, "Record Movie to Slot 9", },
+ { EMUCMD_MOVIE_REPLAY, EMUCMDTYPE_MOVIE, CommandMovieReplay, 0, 0, "Replay Movie", },*/
+ { EMUCMD_MOVIE_REPLAY_FROM, EMUCMDTYPE_MOVIE, FCEUD_MovieReplayFrom, 0, 0, "Replay Movie From...", },
+/* { EMUCMD_MOVIE_REPLAY_SLOT_0, EMUCMDTYPE_MOVIE, CommandMovieReplay, 0, 0, "Replay Movie from Slot 0", },
+ { EMUCMD_MOVIE_REPLAY_SLOT_1, EMUCMDTYPE_MOVIE, CommandMovieReplay, 0, 0, "Replay Movie from Slot 1", },
+ { EMUCMD_MOVIE_REPLAY_SLOT_2, EMUCMDTYPE_MOVIE, CommandMovieReplay, 0, 0, "Replay Movie from Slot 2", },
+ { EMUCMD_MOVIE_REPLAY_SLOT_3, EMUCMDTYPE_MOVIE, CommandMovieReplay, 0, 0, "Replay Movie from Slot 3", },
+ { EMUCMD_MOVIE_REPLAY_SLOT_4, EMUCMDTYPE_MOVIE, CommandMovieReplay, 0, 0, "Replay Movie from Slot 4", },
+ { EMUCMD_MOVIE_REPLAY_SLOT_5, EMUCMDTYPE_MOVIE, CommandMovieReplay, 0, 0, "Replay Movie from Slot 5", },
+ { EMUCMD_MOVIE_REPLAY_SLOT_6, EMUCMDTYPE_MOVIE, CommandMovieReplay, 0, 0, "Replay Movie from Slot 6", },
+ { EMUCMD_MOVIE_REPLAY_SLOT_7, EMUCMDTYPE_MOVIE, CommandMovieReplay, 0, 0, "Replay Movie from Slot 7", },
+ { EMUCMD_MOVIE_REPLAY_SLOT_8, EMUCMDTYPE_MOVIE, CommandMovieReplay, 0, 0, "Replay Movie from Slot 8", },
+ { EMUCMD_MOVIE_REPLAY_SLOT_9, EMUCMDTYPE_MOVIE, CommandMovieReplay, 0, 0, "Replay Movie from Slot 9", },
+*/
+ { EMUCMD_MOVIE_STOP, EMUCMDTYPE_MOVIE, FCEUI_StopMovie, 0, 0, "Stop Movie", },
+ { EMUCMD_MOVIE_READONLY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleReadOnly, 0, 0, "Toggle Read-Only", },
+ { EMUCMD_MOVIE_FRAME_DISPLAY_TOGGLE, EMUCMDTYPE_MOVIE, FCEUI_MovieToggleFrameDisplay, 0, 0, "Movie Frame Display Toggle", },
+ { EMUCMD_MOVIE_INPUT_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUI_ToggleInputDisplay, 0, 0, "Toggle Input Display", },
+ { EMUCMD_MOVIE_ICON_DISPLAY_TOGGLE, EMUCMDTYPE_MISC, FCEUD_ToggleStatusIcon, 0, 0, "Toggle Status Icon", },
+
+ { EMUCMD_SOUND_TOGGLE, EMUCMDTYPE_SOUND, FCEUD_SoundToggle, 0, 0, "Sound Mute Toggle", },
+ { EMUCMD_SOUND_VOLUME_UP, EMUCMDTYPE_SOUND, CommandSoundAdjust, 0, 0, "Sound Volume Up", },
+ { EMUCMD_SOUND_VOLUME_DOWN, EMUCMDTYPE_SOUND, CommandSoundAdjust, 0, 0, "Sound Volume Down", },
+ { EMUCMD_SOUND_VOLUME_NORMAL, EMUCMDTYPE_SOUND, CommandSoundAdjust, 0, 0, "Sound Volume Normal", },
+
+ { EMUCMD_AVI_RECORD_AS, EMUCMDTYPE_AVI, FCEUD_AviRecordTo, 0, 0, "Record AVI As...", },
+ { EMUCMD_AVI_STOP, EMUCMDTYPE_AVI, FCEUD_AviStop, 0, 0, "Stop AVI", },
+
+ { EMUCMD_FDS_EJECT_INSERT, EMUCMDTYPE_FDS, FCEUI_FDSInsert, 0, 0, "Eject or Insert FDS Disk", },
+ { EMUCMD_FDS_SIDE_SELECT, EMUCMDTYPE_FDS, FCEUI_FDSSelect, 0, 0, "Switch FDS Disk Side", },
+
+ { EMUCMD_VSUNI_COIN, EMUCMDTYPE_VSUNI, FCEUI_VSUniCoin, 0, 0, "Insert Coin", },
+ { EMUCMD_VSUNI_TOGGLE_DIP_0, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 0", },
+ { EMUCMD_VSUNI_TOGGLE_DIP_1, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 1", },
+ { EMUCMD_VSUNI_TOGGLE_DIP_2, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 2", },
+ { EMUCMD_VSUNI_TOGGLE_DIP_3, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 3", },
+ { EMUCMD_VSUNI_TOGGLE_DIP_4, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 4", },
+ { EMUCMD_VSUNI_TOGGLE_DIP_5, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 5", },
+ { EMUCMD_VSUNI_TOGGLE_DIP_6, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 6", },
+ { EMUCMD_VSUNI_TOGGLE_DIP_7, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 7", },
+ { EMUCMD_VSUNI_TOGGLE_DIP_8, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 8", },
+ { EMUCMD_VSUNI_TOGGLE_DIP_9, EMUCMDTYPE_VSUNI, CommandToggleDip, 0, 0, "Toggle Dipswitch 9", },
+ { EMUCMD_MISC_REWIND, EMUCMDTYPE_MISC, FCEUI_Rewind, 0, 0, "Rewind", },
+ { EMUCMD_MISC_SHOWSTATES, EMUCMDTYPE_MISC, ViewSlots, 0,0, "View save slots", },
+};
+
+#define NUM_EMU_CMDS (sizeof(FCEUI_CommandTable)/sizeof(FCEUI_CommandTable[0]))
+
+static int execcmd;
+
+void FCEUI_HandleEmuCommands(TestCommandState* testfn)
+{
+ for(execcmd=0; execcmd<NUM_EMU_CMDS; ++execcmd)
+ {
+ int new_state = (*testfn)(execcmd);
+ int old_state = FCEUI_CommandTable[execcmd].state;
+ if (new_state == 1 && old_state == 0 && FCEUI_CommandTable[execcmd].fn_on)
+ (*(FCEUI_CommandTable[execcmd].fn_on))();
+ else if (new_state == 0 && old_state == 1 && FCEUI_CommandTable[execcmd].fn_off)
+ (*(FCEUI_CommandTable[execcmd].fn_off))();
+ FCEUI_CommandTable[execcmd].state = new_state;
+ }
+}
+
+static void CommandUnImpl(void)
+{
+ FCEU_DispMessage("command '%s' unimplemented.", FCEUI_CommandTable[execcmd].name);
+}
+
+static void CommandToggleDip(void)
+{
+ if (FCEUGameInfo->type==GIT_VSUNI)
+ FCEUI_VSUniToggleDIP(execcmd-EMUCMD_VSUNI_TOGGLE_DIP_0);
+}
+
+static void CommandEmulationSpeed(void)
+{
+ FCEUD_SetEmulationSpeed(EMUSPEED_SLOWEST+(execcmd-EMUCMD_SPEED_SLOWEST));
+}
+
+void FCEUI_SelectStateNext(int);
+
+static void ViewSlots(void)
+{
+ FCEUI_SelectState(CurrentState, 1);
+}
+
+static void CommandSelectSaveSlot(void)
+{
+ if(execcmd <= EMUCMD_SAVE_SLOT_9)
+ FCEUI_SelectState(execcmd-EMUCMD_SAVE_SLOT_0, 1);
+ else if(execcmd == EMUCMD_SAVE_SLOT_NEXT)
+ FCEUI_SelectStateNext(1);
+ else if(execcmd == EMUCMD_SAVE_SLOT_PREV)
+ FCEUI_SelectStateNext(-1);
+}
+
+static void CommandStateSave(void)
+{
+// FCEU_PrintError("execcmd=%d, EMUCMD_SAVE_STATE_SLOT_0=%d, EMUCMD_SAVE_STATE_SLOT_9=%d", execcmd,EMUCMD_SAVE_STATE_SLOT_0,EMUCMD_SAVE_STATE_SLOT_9);
+ if(execcmd >= EMUCMD_SAVE_STATE_SLOT_0 && execcmd <= EMUCMD_SAVE_STATE_SLOT_9)
+ {
+ int oldslot=FCEUI_SelectState(execcmd-EMUCMD_SAVE_STATE_SLOT_0, 0);
+ FCEUI_SaveState(0);
+ FCEUI_SelectState(oldslot, 0);
+ }
+ else
+ FCEUI_SaveState(0);
+}
+
+static void CommandStateLoad(void)
+{
+ if(execcmd >= EMUCMD_LOAD_STATE_SLOT_0 && execcmd <= EMUCMD_LOAD_STATE_SLOT_9)
+ {
+ int oldslot=FCEUI_SelectState(execcmd-EMUCMD_LOAD_STATE_SLOT_0, 0);
+ FCEUI_LoadState(0);
+ FCEUI_SelectState(oldslot, 0);
+ }
+ else
+ FCEUI_LoadState(0);
+}
+
+void FCEUI_SelectMovieNext(int);
+/*
+static void CommandMovieSelectSlot(void)
+{
+ if(execcmd <= EMUCMD_MOVIE_SLOT_9)
+ FCEUI_SelectMovie(execcmd-EMUCMD_MOVIE_SLOT_0, 1);
+ else if(execcmd == EMUCMD_MOVIE_SLOT_NEXT)
+ FCEUI_SelectMovieNext(1);
+ else if(execcmd == EMUCMD_MOVIE_SLOT_PREV)
+ FCEUI_SelectMovieNext(-1);
+}
+
+static void CommandMovieRecord(void)
+{
+ if(execcmd >= EMUCMD_MOVIE_RECORD_SLOT_0 && execcmd <= EMUCMD_MOVIE_RECORD_SLOT_9)
+ {
+ int oldslot=FCEUI_SelectMovie(execcmd-EMUCMD_MOVIE_RECORD_SLOT_0, 0);
+ FCEUI_SaveMovie(0, 0, 0);
+ FCEUI_SelectMovie(oldslot, 0);
+ }
+ else
+ FCEUI_SaveMovie(0, 0, 0);
+}
+
+static void CommandMovieReplay(void)
+{
+ if(execcmd >= EMUCMD_MOVIE_REPLAY_SLOT_0 && execcmd <= EMUCMD_MOVIE_REPLAY_SLOT_9)
+ {
+ int oldslot=FCEUI_SelectMovie(execcmd-EMUCMD_MOVIE_REPLAY_SLOT_0, 0);
+ FCEUI_LoadMovie(0, 0);
+ FCEUI_SelectMovie(oldslot, 0);
+ }
+ else
+ FCEUI_LoadMovie(0, 0);
+}
+*/
+static void CommandSoundAdjust(void)
+{
+ int n;
+ switch(execcmd)
+ {
+ case EMUCMD_SOUND_VOLUME_UP: n=1; break;
+ case EMUCMD_SOUND_VOLUME_DOWN: n=-1; break;
+ case EMUCMD_SOUND_VOLUME_NORMAL: n=0; break;
+ }
+
+ FCEUD_SoundVolumeAdjust(n);
+}
+
diff --git a/input.h b/input.h
new file mode 100644
index 00000000..cc284e9b
--- /dev/null
+++ b/input.h
@@ -0,0 +1,187 @@
+#ifndef _INPUT_H_
+#define _INPUT_H_
+
+typedef struct {
+ uint8 FP_FASTAPASS(1) (*Read)(int w);
+ void FP_FASTAPASS(1) (*Write)(uint8 v);
+ void FP_FASTAPASS(1) (*Strobe)(int w);
+ void FP_FASTAPASS(3) (*Update)(int w, void *data, int arg);
+ void FP_FASTAPASS(3) (*SLHook)(int w, uint8 *bg, uint8 *spr, uint32 linets, int final);
+ void FP_FASTAPASS(3) (*Draw)(int w, uint8 *buf, int arg);
+} INPUTC;
+
+typedef struct {
+ uint8 FP_FASTAPASS(2) (*Read)(int w, uint8 ret);
+ void FP_FASTAPASS(1) (*Write)(uint8 v);
+ void (*Strobe)(void);
+ void FP_FASTAPASS(2) (*Update)(void *data, int arg);
+ void FP_FASTAPASS(3) (*SLHook)(uint8 *bg, uint8 *spr, uint32 linets, int final);
+ void FP_FASTAPASS(2) (*Draw)(uint8 *buf, int arg);
+} INPUTCFC;
+
+void FCEU_DrawInput(uint8 *buf);
+void FCEU_UpdateInput(void);
+int FCEU_BotMode(void);
+void FCEU_SetBotMode(int x);
+void InitializeInput(void);
+void FCEU_UpdateBot(void);
+extern void (*PStrobe[2])(void);
+extern void (*InputScanlineHook)(uint8 *bg, uint8 *spr, uint32 linets, int final);
+
+void FCEU_DoSimpleCommand(int cmd);
+
+enum EMUCMD
+{
+ EMUCMD_POWER=0,
+ EMUCMD_RESET,
+ EMUCMD_PAUSE,
+ EMUCMD_FRAME_ADVANCE,
+ EMUCMD_SCREENSHOT,
+ EMUCMD_HIDE_MENU_TOGGLE,
+
+ EMUCMD_SPEED_SLOWEST,
+ EMUCMD_SPEED_SLOWER,
+ EMUCMD_SPEED_NORMAL,
+ EMUCMD_SPEED_FASTER,
+ EMUCMD_SPEED_FASTEST,
+ EMUCMD_SPEED_TURBO,
+
+ EMUCMD_SAVE_SLOT_0,
+ EMUCMD_SAVE_SLOT_1,
+ EMUCMD_SAVE_SLOT_2,
+ EMUCMD_SAVE_SLOT_3,
+ EMUCMD_SAVE_SLOT_4,
+ EMUCMD_SAVE_SLOT_5,
+ EMUCMD_SAVE_SLOT_6,
+ EMUCMD_SAVE_SLOT_7,
+ EMUCMD_SAVE_SLOT_8,
+ EMUCMD_SAVE_SLOT_9,
+ EMUCMD_SAVE_SLOT_NEXT,
+ EMUCMD_SAVE_SLOT_PREV,
+ EMUCMD_SAVE_STATE,
+ EMUCMD_SAVE_STATE_AS,
+ EMUCMD_SAVE_STATE_SLOT_0,
+ EMUCMD_SAVE_STATE_SLOT_1,
+ EMUCMD_SAVE_STATE_SLOT_2,
+ EMUCMD_SAVE_STATE_SLOT_3,
+ EMUCMD_SAVE_STATE_SLOT_4,
+ EMUCMD_SAVE_STATE_SLOT_5,
+ EMUCMD_SAVE_STATE_SLOT_6,
+ EMUCMD_SAVE_STATE_SLOT_7,
+ EMUCMD_SAVE_STATE_SLOT_8,
+ EMUCMD_SAVE_STATE_SLOT_9,
+ EMUCMD_LOAD_STATE,
+ EMUCMD_LOAD_STATE_FROM,
+ EMUCMD_LOAD_STATE_SLOT_0,
+ EMUCMD_LOAD_STATE_SLOT_1,
+ EMUCMD_LOAD_STATE_SLOT_2,
+ EMUCMD_LOAD_STATE_SLOT_3,
+ EMUCMD_LOAD_STATE_SLOT_4,
+ EMUCMD_LOAD_STATE_SLOT_5,
+ EMUCMD_LOAD_STATE_SLOT_6,
+ EMUCMD_LOAD_STATE_SLOT_7,
+ EMUCMD_LOAD_STATE_SLOT_8,
+ EMUCMD_LOAD_STATE_SLOT_9,
+
+/* EMUCMD_MOVIE_SLOT_0,
+ EMUCMD_MOVIE_SLOT_1,
+ EMUCMD_MOVIE_SLOT_2,
+ EMUCMD_MOVIE_SLOT_3,
+ EMUCMD_MOVIE_SLOT_4,
+ EMUCMD_MOVIE_SLOT_5,
+ EMUCMD_MOVIE_SLOT_6,
+ EMUCMD_MOVIE_SLOT_7,
+ EMUCMD_MOVIE_SLOT_8,
+ EMUCMD_MOVIE_SLOT_9,
+ EMUCMD_MOVIE_SLOT_NEXT,
+ EMUCMD_MOVIE_SLOT_PREV,
+ EMUCMD_MOVIE_RECORD,*/
+ EMUCMD_MOVIE_RECORD_TO,
+/* EMUCMD_MOVIE_RECORD_SLOT_0,
+ EMUCMD_MOVIE_RECORD_SLOT_1,
+ EMUCMD_MOVIE_RECORD_SLOT_2,
+ EMUCMD_MOVIE_RECORD_SLOT_3,
+ EMUCMD_MOVIE_RECORD_SLOT_4,
+ EMUCMD_MOVIE_RECORD_SLOT_5,
+ EMUCMD_MOVIE_RECORD_SLOT_6,
+ EMUCMD_MOVIE_RECORD_SLOT_7,
+ EMUCMD_MOVIE_RECORD_SLOT_8,
+ EMUCMD_MOVIE_RECORD_SLOT_9,
+ EMUCMD_MOVIE_REPLAY,*/
+ EMUCMD_MOVIE_REPLAY_FROM,
+/* EMUCMD_MOVIE_REPLAY_SLOT_0,
+ EMUCMD_MOVIE_REPLAY_SLOT_1,
+ EMUCMD_MOVIE_REPLAY_SLOT_2,
+ EMUCMD_MOVIE_REPLAY_SLOT_3,
+ EMUCMD_MOVIE_REPLAY_SLOT_4,
+ EMUCMD_MOVIE_REPLAY_SLOT_5,
+ EMUCMD_MOVIE_REPLAY_SLOT_6,
+ EMUCMD_MOVIE_REPLAY_SLOT_7,
+ EMUCMD_MOVIE_REPLAY_SLOT_8,
+ EMUCMD_MOVIE_REPLAY_SLOT_9,*/
+ EMUCMD_MOVIE_STOP,
+ EMUCMD_MOVIE_READONLY_TOGGLE,
+ EMUCMD_MOVIE_FRAME_DISPLAY_TOGGLE,
+ EMUCMD_MOVIE_INPUT_DISPLAY_TOGGLE,
+ EMUCMD_MOVIE_ICON_DISPLAY_TOGGLE,
+
+ EMUCMD_SOUND_TOGGLE,
+ EMUCMD_SOUND_VOLUME_UP,
+ EMUCMD_SOUND_VOLUME_DOWN,
+ EMUCMD_SOUND_VOLUME_NORMAL,
+
+ EMUCMD_AVI_RECORD_AS,
+ EMUCMD_AVI_STOP,
+
+ EMUCMD_FDS_EJECT_INSERT,
+ EMUCMD_FDS_SIDE_SELECT,
+
+ EMUCMD_VSUNI_COIN,
+ EMUCMD_VSUNI_TOGGLE_DIP_0,
+ EMUCMD_VSUNI_TOGGLE_DIP_1,
+ EMUCMD_VSUNI_TOGGLE_DIP_2,
+ EMUCMD_VSUNI_TOGGLE_DIP_3,
+ EMUCMD_VSUNI_TOGGLE_DIP_4,
+ EMUCMD_VSUNI_TOGGLE_DIP_5,
+ EMUCMD_VSUNI_TOGGLE_DIP_6,
+ EMUCMD_VSUNI_TOGGLE_DIP_7,
+ EMUCMD_VSUNI_TOGGLE_DIP_8,
+ EMUCMD_VSUNI_TOGGLE_DIP_9,
+ EMUCMD_MISC_REWIND,
+ EMUCMD_MISC_SHOWSTATES,
+
+ EMUCMD_MAX
+};
+
+enum EMUCMDTYPE
+{
+ EMUCMDTYPE_MISC=0,
+ EMUCMDTYPE_SPEED,
+ EMUCMDTYPE_STATE,
+ EMUCMDTYPE_MOVIE,
+ EMUCMDTYPE_SOUND,
+ EMUCMDTYPE_AVI,
+ EMUCMDTYPE_FDS,
+ EMUCMDTYPE_VSUNI,
+
+ EMUCMDTYPE_MAX
+};
+
+extern const char* FCEUI_CommandTypeNames[];
+
+typedef void EMUCMDFN(void);
+
+struct EMUCMDTABLE
+{
+ int cmd;
+ int type;
+ EMUCMDFN* fn_on;
+ EMUCMDFN* fn_off;
+ int state;
+ char* name;
+};
+
+extern struct EMUCMDTABLE FCEUI_CommandTable[];
+
+#endif //_INPUT_H_
+
diff --git a/input/arkanoid.c b/input/arkanoid.c
new file mode 100644
index 00000000..2f9d0ca9
--- /dev/null
+++ b/input/arkanoid.c
@@ -0,0 +1,119 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "share.h"
+
+typedef struct {
+ uint32 mzx,mzb;
+ uint32 readbit;
+} ARK;
+
+static ARK NESArk[2];
+static ARK FCArk;
+
+static void StrobeARKFC(void)
+{
+ FCArk.readbit=0;
+}
+
+
+static uint8 FP_FASTAPASS(2) ReadARKFC(int w,uint8 ret)
+{
+ ret&=~2;
+
+ if(w)
+ {
+ if(FCArk.readbit>=8)
+ ret|=2;
+ else
+ {
+ ret|=((FCArk.mzx>>(7-FCArk.readbit))&1)<<1;
+ if(!fceuindbg)
+ FCArk.readbit++;
+ }
+ }
+ else
+ ret|=FCArk.mzb<<1;
+ return(ret);
+}
+
+static uint32 FixX(uint32 x)
+{
+ x=98+x*144/240;
+ if(x>242) x=242;
+ x=~x;
+ return(x);
+}
+
+static void FP_FASTAPASS(2) UpdateARKFC(void *data, int arg)
+{
+ uint32 *ptr=(uint32 *)data;
+ FCArk.mzx=FixX(ptr[0]);
+ FCArk.mzb=ptr[2]?1:0;
+}
+
+static INPUTCFC ARKCFC={ReadARKFC,0,StrobeARKFC,UpdateARKFC,0,0};
+
+INPUTCFC *FCEU_InitArkanoidFC(void)
+{
+ FCArk.mzx=98;
+ FCArk.mzb=0;
+ return(&ARKCFC);
+}
+
+static uint8 FP_FASTAPASS(1) ReadARK(int w)
+{
+ uint8 ret=0;
+
+ if(NESArk[w].readbit>=8)
+ ret|=1<<4;
+ else
+ {
+ ret|=((NESArk[w].mzx>>(7-NESArk[w].readbit))&1)<<4;
+ if(!fceuindbg)
+ NESArk[w].readbit++;
+ }
+ ret|=(NESArk[w].mzb&1)<<3;
+ return(ret);
+}
+
+
+static void FP_FASTAPASS(1) StrobeARK(int w)
+{
+ NESArk[w].readbit=0;
+}
+
+static void FP_FASTAPASS(3) UpdateARK(int w, void *data, int arg)
+{
+ uint32 *ptr=(uint32*)data;
+ NESArk[w].mzx=FixX(ptr[0]);
+ NESArk[w].mzb=ptr[2]?1:0;
+}
+
+static INPUTC ARKC={ReadARK, 0, StrobeARK, UpdateARK, 0, 0};
+
+INPUTC *FCEU_InitArkanoid(int w)
+{
+ NESArk[w].mzx=98;
+ NESArk[w].mzb=0;
+ return(&ARKC);
+}
diff --git a/input/bworld.c b/input/bworld.c
new file mode 100644
index 00000000..0941b8c2
--- /dev/null
+++ b/input/bworld.c
@@ -0,0 +1,74 @@
+/* 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 <string.h>
+#include "share.h"
+
+static int seq,ptr,bit,cnt,have;
+static uint8 bdata[20];
+
+
+static uint8 FP_FASTAPASS(2) Read(int w, uint8 ret)
+{
+ if(w && have)
+ {
+ switch(seq)
+ {
+ case 0: seq++; ptr=0; ret|=0x4; break;
+ case 1: seq++; bit=bdata[ptr]; cnt=0; ret|=0x4; break;
+ case 2: ret|=((bit&0x01)^0x01)<<2; bit>>=1; if(++cnt > 7) seq++;
+ break;
+ case 3: if(++ptr > 19)
+ {
+ seq=-1;
+ have=0;
+ }
+ else
+ seq=1;
+ default: break;
+ }
+ }
+ return(ret);
+}
+
+static void FP_FASTAPASS(1) Write(uint8 V)
+{
+ //printf("%02x\n",V);
+}
+
+static void FP_FASTAPASS(2) Update(void *data, int arg)
+{
+ if(*(uint8 *)data)
+ {
+ *(uint8 *)data=0;
+ seq=ptr=0;
+ have=1;
+ strcpy(bdata,(uint8 *)data+1);
+ strcpy(&bdata[13],"SUNSOFT");
+ }
+}
+
+static INPUTCFC BarcodeWorld={Read,Write,0,Update,0,0};
+
+INPUTCFC *FCEU_InitBarcodeWorld(void)
+{
+ return(&BarcodeWorld);
+}
+
diff --git a/input/cursor.c b/input/cursor.c
new file mode 100644
index 00000000..e45ca83d
--- /dev/null
+++ b/input/cursor.c
@@ -0,0 +1,86 @@
+#include "share.h"
+
+static uint8 GunSight[]={
+ 0,0,0,0,0,0,1,0,0,0,0,0,0,
+ 0,0,0,0,0,0,2,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,0,0,0,0,0,0,
+ 0,0,0,0,0,0,2,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,3,0,0,0,0,0,0,
+ 1,2,1,2,0,3,3,3,0,2,1,2,1,
+ 0,0,0,0,0,0,3,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,2,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,0,0,0,0,0,0,
+ 0,0,0,0,0,0,2,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,0,0,0,0,0,0,
+};
+static uint8 FCEUcursor[11*19]=
+{
+ 1,0,0,0,0,0,0,0,0,0,0,
+ 1,1,0,0,0,0,0,0,0,0,0,
+ 1,2,1,0,0,0,0,0,0,0,0,
+ 1,2,2,1,0,0,0,0,0,0,0,
+ 1,2,2,2,1,0,0,0,0,0,0,
+ 1,2,2,2,2,1,0,0,0,0,0,
+ 1,2,2,2,2,2,1,0,0,0,0,
+ 1,2,2,2,2,2,2,1,0,0,0,
+ 1,2,2,2,2,2,2,2,1,0,0,
+ 1,2,2,2,2,2,2,2,2,1,0,
+ 1,2,2,2,2,2,1,1,1,1,1,
+ 1,2,2,1,2,2,1,0,0,0,0,
+ 1,2,1,0,1,2,2,1,0,0,0,
+ 1,1,0,0,1,2,2,1,0,0,0,
+ 1,0,0,0,0,1,2,2,1,0,0,
+ 0,0,0,0,0,1,2,2,1,0,0,
+ 0,0,0,0,0,0,1,2,2,1,0,
+ 0,0,0,0,0,0,1,2,2,1,0,
+ 0,0,0,0,0,0,0,1,1,0,0,
+};
+
+void FCEU_DrawGunSight(uint8 *buf, int xc, int yc)
+{
+ int x,y;
+ int c,d;
+
+ for(y=0;y<13;y++)
+ for(x=0;x<13;x++)
+ {
+ uint8 a;
+ a=GunSight[y*13+x];
+ if(a)
+ {
+ c=(yc+y-7);
+ d=(xc+x-7);
+ if(c>=0 && d>=0 && d<256 && c<240)
+ {
+ if(a==3)
+ buf[c*256+d]=0xBF-(buf[c*256+d]&0x3F);
+ else
+ buf[c*256+d]=a-1;
+ }
+ }
+ }
+}
+
+
+void FCEU_DrawCursor(uint8 *buf, int xc, int yc)
+{
+ int x,y;
+ int c,d;
+
+ if(xc<256 && yc<240)
+ for(y=0;y<19;y++)
+ for(x=0;x<11;x++)
+ {
+ uint8 a;
+ a=FCEUcursor[y*11+x];
+ if(a)
+ {
+ c=(yc+y);
+ d=(xc+x);
+ if(d<256 && c<240)
+ buf[c*256+d]=a+127;
+ }
+ }
+}
diff --git a/input/fkb.c b/input/fkb.c
new file mode 100644
index 00000000..336fc1e2
--- /dev/null
+++ b/input/fkb.c
@@ -0,0 +1,102 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string.h>
+#include "share.h"
+#include "fkb.h"
+#define AK2(x,y) ( (FKB_##x) | (FKB_##y <<8) )
+#define AK(x) FKB_##x
+
+static uint8 bufit[0x49];
+static uint8 ksmode;
+static uint8 ksindex;
+
+
+static uint16 matrix[9][2][4]=
+{
+{{AK(F8),AK(RETURN),AK(BRACKETLEFT),AK(BRACKETRIGHT)},
+ {AK(KANA),AK(RIGHTSHIFT),AK(BACKSLASH),AK(STOP)}},
+{{AK(F7),AK(AT),AK(COLON),AK(SEMICOLON)},
+ {AK(UNDERSCORE),AK(SLASH),AK(MINUS),AK(CARET)}},
+{{AK(F6),AK(O),AK(L),AK(K)},
+ {AK(PERIOD),AK(COMMA),AK(P),AK(0)}},
+{{AK(F5),AK(I),AK(U),AK(J)},
+ {AK(M),AK(N),AK(9),AK(8)}},
+{{AK(F4),AK(Y),AK(G),AK(H)},
+ {AK(B),AK(V),AK(7),AK(6)}},
+{{AK(F3),AK(T),AK(R),AK(D)},
+ {AK(F),AK(C),AK(5),AK(4)}},
+{{AK(F2),AK(W),AK(S),AK(A)},
+ {AK(X),AK(Z),AK(E),AK(3)}},
+{{AK(F1),AK(ESCAPE),AK(Q),AK(CONTROL)},
+ {AK(LEFTSHIFT),AK(GRAPH),AK(1),AK(2)}},
+{{AK(CLEAR),AK(UP),AK(RIGHT),AK(LEFT)},
+ {AK(DOWN),AK(SPACE),AK(DELETE),AK(INSERT)}},
+};
+
+static void FP_FASTAPASS(1) FKB_Write(uint8 v)
+{
+ v>>=1;
+ if(v&2)
+ {
+ if((ksmode&1) && !(v&1))
+ ksindex=(ksindex+1)%9;
+ }
+ ksmode=v;
+}
+
+static uint8 FP_FASTAPASS(2) FKB_Read(int w, uint8 ret)
+{
+ //printf("$%04x, %d, %d\n",w+0x4016,ksindex,ksmode&1);
+ if(w)
+ {
+ int x;
+
+ ret&=~0x1E;
+ for(x=0;x<4;x++)
+ if(bufit[ matrix[ksindex][ksmode&1][x]&0xFF ] || bufit[ matrix[ksindex][ksmode&1][x]>>8])
+ {
+ ret|=1<<(x+1);
+ }
+ ret^=0x1E;
+ }
+ return(ret);
+}
+
+static void FKB_Strobe(void)
+{
+ ksmode=0;
+ ksindex=0;
+ //printf("strobe\n");
+}
+
+static void FP_FASTAPASS(2) FKB_Update(void *data, int arg)
+{
+ memcpy(bufit+1,data,0x48);
+}
+
+static INPUTCFC FKB={FKB_Read,FKB_Write,FKB_Strobe,FKB_Update,0,0};
+
+INPUTCFC *FCEU_InitFKB(void)
+{
+ memset(bufit,0,sizeof(bufit));
+ ksmode=ksindex=0;
+ return(&FKB);
+}
diff --git a/input/fkb.h b/input/fkb.h
new file mode 100644
index 00000000..b5dcadd4
--- /dev/null
+++ b/input/fkb.h
@@ -0,0 +1,72 @@
+#define FKB_F1 0x01
+#define FKB_F2 0x02
+#define FKB_F3 0x03
+#define FKB_F4 0x04
+#define FKB_F5 0x05
+#define FKB_F6 0x06
+#define FKB_F7 0x07
+#define FKB_F8 0x08
+#define FKB_1 0x09
+#define FKB_2 0x0A
+#define FKB_3 0x0B
+#define FKB_4 0x0C
+#define FKB_5 0x0D
+#define FKB_6 0x0E
+#define FKB_7 0x0F
+#define FKB_8 0x10
+#define FKB_9 0x11
+#define FKB_0 0x12
+#define FKB_MINUS 0x13
+#define FKB_CARET 0x14
+#define FKB_BACKSLASH 0x15
+#define FKB_STOP 0x16
+#define FKB_ESCAPE 0x17
+#define FKB_Q 0x18
+#define FKB_W 0x19
+#define FKB_E 0x1A
+#define FKB_R 0x1B
+#define FKB_T 0x1C
+#define FKB_Y 0x1D
+#define FKB_U 0x1E
+#define FKB_I 0x1F
+#define FKB_O 0x20
+#define FKB_P 0x21
+#define FKB_AT 0x22
+#define FKB_BRACKETLEFT 0x23
+#define FKB_RETURN 0x24
+#define FKB_CONTROL 0x25
+#define FKB_A 0x26
+#define FKB_S 0x27
+#define FKB_D 0x28
+#define FKB_F 0x29
+#define FKB_G 0x2A
+#define FKB_H 0x2B
+#define FKB_J 0x2C
+#define FKB_K 0x2D
+#define FKB_L 0x2E
+#define FKB_SEMICOLON 0x2F
+#define FKB_COLON 0x30
+#define FKB_BRACKETRIGHT 0x31
+#define FKB_KANA 0x32
+#define FKB_LEFTSHIFT 0x33
+#define FKB_Z 0x34
+#define FKB_X 0x35
+#define FKB_C 0x36
+#define FKB_V 0x37
+#define FKB_B 0x38
+#define FKB_N 0x39
+#define FKB_M 0x3A
+#define FKB_COMMA 0x3B
+#define FKB_PERIOD 0x3C
+#define FKB_SLASH 0x3D
+#define FKB_UNDERSCORE 0x3E
+#define FKB_RIGHTSHIFT 0x3F
+#define FKB_GRAPH 0x40
+#define FKB_SPACE 0x41
+#define FKB_CLEAR 0x42
+#define FKB_INSERT 0x43
+#define FKB_DELETE 0x44
+#define FKB_UP 0x45
+#define FKB_LEFT 0x46
+#define FKB_RIGHT 0x47
+#define FKB_DOWN 0x48
diff --git a/input/ftrainer.c b/input/ftrainer.c
new file mode 100644
index 00000000..7adbc57b
--- /dev/null
+++ b/input/ftrainer.c
@@ -0,0 +1,74 @@
+/* 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 <string.h>
+#include "share.h"
+
+static uint32 FTVal,FTValR;
+static char side;
+
+static uint8 FP_FASTAPASS(2) FT_Read(int w, uint8 ret)
+{
+ if(w)
+ {
+ ret|=FTValR;
+ }
+ return(ret);
+}
+
+static void FP_FASTAPASS(1) FT_Write(uint8 V)
+{
+ FTValR=0;
+
+ //printf("%08x\n",FTVal);
+ if(!(V&0x1))
+ FTValR=(FTVal>>8);
+ else if(!(V&0x2))
+ FTValR=(FTVal>>4);
+ else if(!(V&0x4))
+ FTValR=FTVal;
+
+ FTValR=(~FTValR)&0xF;
+ if(side=='B')
+ FTValR=((FTValR&0x8)>>3) | ((FTValR&0x4)>>1) | ((FTValR&0x2)<<1) | ((FTValR&0x1)<<3);
+ FTValR<<=1;
+}
+
+static void FP_FASTAPASS(2) FT_Update(void *data, int arg)
+{
+ FTVal=*(uint32 *)data;
+}
+
+static INPUTCFC FamilyTrainer={FT_Read,FT_Write,0,FT_Update,0,0};
+
+INPUTCFC *FCEU_InitFamilyTrainerA(void)
+{
+ side='A';
+ FTVal=FTValR=0;
+ return(&FamilyTrainer);
+}
+
+INPUTCFC *FCEU_InitFamilyTrainerB(void)
+{
+ side='B';
+ FTVal=FTValR=0;
+ return(&FamilyTrainer);
+}
+
diff --git a/input/hypershot.c b/input/hypershot.c
new file mode 100644
index 00000000..0a1117b1
--- /dev/null
+++ b/input/hypershot.c
@@ -0,0 +1,50 @@
+/* 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 <string.h>
+#include "share.h"
+
+static uint8 HSVal,HSValR;
+
+
+static uint8 FP_FASTAPASS(2) HS_Read(int w, uint8 ret)
+{
+ if(w) ret|=HSValR;
+
+ return(ret);
+}
+
+static void HS_Strobe(void)
+{
+ HSValR=HSVal<<1;
+}
+
+static void FP_FASTAPASS(2) HS_Update(void *data, int arg)
+{
+ HSVal=*(uint8*)data;
+}
+
+static INPUTCFC HyperShot={HS_Read,0,HS_Strobe,HS_Update,0,0};
+
+INPUTCFC *FCEU_InitHS(void)
+{
+ HSVal=HSValR=0;
+ return(&HyperShot);
+}
diff --git a/input/mahjong.c b/input/mahjong.c
new file mode 100644
index 00000000..a363d9b4
--- /dev/null
+++ b/input/mahjong.c
@@ -0,0 +1,79 @@
+/* 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 <string.h>
+#include "share.h"
+
+static uint32 MReal,MRet;
+
+static uint8 FP_FASTAPASS(2) MJ_Read(int w, uint8 ret)
+{
+ if(w)
+ {
+// ret|=(MRet&1)<<1;
+ ret|=((MRet&0x80)>>6)&2;
+// MRet>>=1;
+ if(!fceuindbg)
+ MRet<<=1;
+ }
+ return(ret);
+}
+
+static void FP_FASTAPASS(1) MJ_Write(uint8 v)
+{
+ /* 1: I-D7, J-D6, K-D5, L-D4, M-D3, Big Red-D2
+ 2: A-D7, B-D6, C-D5, D-D4, E-D3, F-D2, G-D1, H-D0
+ 3: Sel-D6, Start-D7, D5, D4, D3, D2, D1
+ */
+ MRet=0;
+
+ v>>=1;
+ v&=3;
+
+ if(v==3)
+ {
+ MRet=(MReal>>14)&0x7F;
+ //MRet=((MRet&0x1F) |((MRet&0x40)>>1)|((MRet&0x20)<<1)) <<1; //(MReal>>13)&0x7F;
+ }
+ else if(v==2)
+ {
+ MRet=MReal&0xFF;
+ }
+ else if(v==1)
+ {
+ MRet=(MReal>>8)&0x3F;
+ }
+// HSValR=HSVal<<1;
+}
+
+static void FP_FASTAPASS(2) MJ_Update(void *data, int arg)
+{
+ MReal=*(uint32*)data;
+ //printf("%08x\n",MReal>>13);
+ //HSVal=*(uint8*)data;
+}
+
+static INPUTCFC Mahjong={MJ_Read,MJ_Write,0,MJ_Update,0,0};
+
+INPUTCFC *FCEU_InitMahjong(void)
+{
+ MReal=MRet=0;
+ return(&Mahjong);
+}
diff --git a/input/oekakids.c b/input/oekakids.c
new file mode 100644
index 00000000..68def01d
--- /dev/null
+++ b/input/oekakids.c
@@ -0,0 +1,95 @@
+/* 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 <string.h>
+#include "share.h"
+
+static uint8 OKValR,LastWR;
+static uint32 OKData;
+static uint32 OKX,OKY,OKB;
+
+static uint8 FP_FASTAPASS(2) OK_Read(int w, uint8 ret)
+{
+ if(w)
+ {
+ ret|=OKValR;
+ }
+ return(ret);
+}
+
+static void FP_FASTAPASS(1) OK_Write(uint8 V)
+{
+ if(!(V&0x1))
+ {
+ int32 vx,vy;
+
+ //puts("Redo");
+ OKValR=OKData=0;
+
+ if(OKB) OKData|=1;
+
+ if(OKY >= 48)
+ OKData|=2;
+ else if(OKB) OKData|=3;
+
+ vx=OKX*240/256+8;
+ vy=OKY*256/240-12;
+ if(vy<0) vy=0;
+ if(vy>255) vy=255;
+ if(vx<0) vx=0;
+ if(vx>255) vx=255;
+ OKData |= (vx<<10) | (vy<<2);
+ }
+ else
+ {
+ if((~LastWR)&V&0x02)
+ OKData<<=1;
+
+ if(!(V&0x2)) OKValR=0x4;
+ else
+ {
+ if(OKData&0x40000) OKValR=0;
+ else OKValR=0x8;
+ }
+ }
+ LastWR=V;
+}
+
+static void FP_FASTAPASS(2) OK_Update(void *data, int arg)
+{
+ //puts("Sync");
+ OKX=((uint32*)data)[0];
+ OKY=((uint32*)data)[1];
+ OKB=((uint32*)data)[2];
+}
+
+static void FP_FASTAPASS(2) DrawOeka(uint8 *buf, int arg)
+{
+ if(arg && OKY<44)
+ FCEU_DrawCursor(buf, OKX, OKY);
+}
+
+static INPUTCFC OekaKids={OK_Read,OK_Write,0,OK_Update,0,DrawOeka};
+
+INPUTCFC *FCEU_InitOekaKids(void)
+{
+ OKValR=0;
+ return(&OekaKids);
+}
diff --git a/input/powerpad.c b/input/powerpad.c
new file mode 100644
index 00000000..09bdbb31
--- /dev/null
+++ b/input/powerpad.c
@@ -0,0 +1,85 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include "share.h"
+
+
+static char side;
+static uint32 pprsb[2];
+static uint32 pprdata[2];
+
+static uint8 FP_FASTAPASS(1) ReadPP(int w)
+{
+ uint8 ret=0;
+ ret|=((pprdata[w]>>pprsb[w])&1)<<3;
+ ret|=((pprdata[w]>>(pprsb[w]+8))&1)<<4;
+ if(pprsb[w]>=4)
+ {
+ ret|=0x10;
+ if(pprsb[w]>=8)
+ ret|=0x08;
+ }
+ if(!fceuindbg)
+ pprsb[w]++;
+ return ret;
+}
+
+static void FP_FASTAPASS(1) StrobePP(int w)
+{
+ pprsb[w]=0;
+}
+
+void FP_FASTAPASS(3) UpdatePP(int w, void *data, int arg)
+{
+ static const char shifttableA[12]={8,9,0,1,11,7,4,2,10,6,5,3};
+ static const char shifttableB[12]={1,0,9,8,2,4,7,11,3,5,6,10};
+ int x;
+
+ pprdata[w]=0;
+
+ if(side=='A')
+ for(x=0;x<12;x++)
+ pprdata[w]|=(((*(uint32 *)data)>>x)&1)<<shifttableA[x];
+ else
+ for(x=0;x<12;x++)
+ pprdata[w]|=(((*(uint32 *)data)>>x)&1)<<shifttableB[x];
+}
+
+static INPUTC PwrPadCtrl={ReadPP,0,StrobePP,UpdatePP,0,0};
+
+static INPUTC *FCEU_InitPowerpad(int w)
+{
+ pprsb[w]=pprdata[w]=0;
+ return(&PwrPadCtrl);
+}
+
+INPUTC *FCEU_InitPowerpadA(int w)
+{
+ side='A';
+ return(FCEU_InitPowerpad(w));
+}
+
+INPUTC *FCEU_InitPowerpadB(int w)
+{
+ side='B';
+ return(FCEU_InitPowerpad(w));
+}
diff --git a/input/quiz.c b/input/quiz.c
new file mode 100644
index 00000000..4de29375
--- /dev/null
+++ b/input/quiz.c
@@ -0,0 +1,75 @@
+/* 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 <string.h>
+#include "share.h"
+
+static uint8 QZVal,QZValR;
+static uint8 FunkyMode;
+
+static uint8 FP_FASTAPASS(2) QZ_Read(int w, uint8 ret)
+{
+ if(w)
+ {
+ //if(X.PC==0xdc7d) return(0xFF);
+ //printf("Blah: %04x\n",X.PC);
+ //FCEUI_DumpMem("dmp2",0xc000,0xffff);
+
+ ret|=(QZValR&0x7)<<2;
+ QZValR=QZValR>>3;
+
+ if(FunkyMode)
+ {
+ //ret=0x14;
+ //puts("Funky");
+ QZValR|=0x28;
+ }
+ else
+ {
+ QZValR|=0x38;
+ }
+ }
+ return(ret);
+}
+
+static void QZ_Strobe(void)
+{
+ QZValR=QZVal;
+ //puts("Strobe");
+}
+
+static void FP_FASTAPASS(1) QZ_Write(uint8 V)
+{
+ //printf("Wr: %02x\n",V);
+ FunkyMode=V&4;
+}
+
+static void FP_FASTAPASS(2) QZ_Update(void *data, int arg)
+{
+ QZVal=*(uint8 *)data;
+}
+
+static INPUTCFC QuizKing={QZ_Read,QZ_Write,QZ_Strobe,QZ_Update,0,0};
+
+INPUTCFC *FCEU_InitQuizKing(void)
+{
+ QZVal=QZValR=0;
+ return(&QuizKing);
+}
diff --git a/input/shadow.c b/input/shadow.c
new file mode 100644
index 00000000..e2442902
--- /dev/null
+++ b/input/shadow.c
@@ -0,0 +1,151 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "share.h"
+
+typedef struct {
+ uint32 mzx,mzy,mzb;
+ int zap_readbit;
+ int bogo;
+ int zappo;
+ uint64 zaphit;
+} ZAPPER;
+
+static ZAPPER ZD;
+
+static void FP_FASTAPASS(3) ZapperFrapper(uint8 *bg, uint8 *spr, uint32 linets, int final)
+{
+ int xs,xe;
+ int zx,zy;
+
+ if(!bg) // New line, so reset stuff.
+ {
+ ZD.zappo=0;
+ return;
+ }
+ xs=ZD.zappo;
+ xe=final;
+
+ zx=ZD.mzx;
+ zy=ZD.mzy;
+
+ if(xe>256) xe=256;
+
+ if(scanline>=(zy-4) && scanline<=(zy+4))
+ {
+ while(xs<xe)
+ {
+ uint8 a1,a2;
+ uint32 sum;
+ if(xs<=(zx+4) && xs>=(zx-4))
+ {
+ a1=bg[xs];
+ if(spr)
+ {
+ a2=spr[xs];
+
+ if(!(a2&0x80))
+ if(!(a2&0x40) || (a1&64))
+ a1=a2;
+ }
+ a1&=63;
+
+ sum=palo[a1].r+palo[a1].g+palo[a1].b;
+ if(sum>=100*3)
+ {
+ ZD.zaphit=((uint64)linets+(xs+16)*(PAL?15:16))/48+timestampbase;
+ goto endo;
+ }
+ }
+ xs++;
+ }
+ }
+ endo:
+ ZD.zappo=final;
+}
+
+static INLINE int CheckColor(void)
+{
+ FCEUPPU_LineUpdate();
+
+ if((ZD.zaphit+10)>=(timestampbase+timestamp)) return(0);
+
+ return(1);
+}
+
+
+static uint8 FP_FASTAPASS(2) ReadZapper(int w, uint8 ret)
+{
+ if(w)
+ {
+ ret&=~0x18;
+ if(ZD.bogo)
+ ret|=0x10;
+ if(CheckColor())
+ ret|=0x8;
+ }
+ else
+ {
+ //printf("Kayo: %d\n",ZD.zap_readbit);
+ ret&=~2;
+ //if(ZD.zap_readbit==4) ret|=ZD.mzb&2;
+ ret|=(ret&1)<<1;
+ //ZD.zap_readbit++;
+ }
+ return ret;
+}
+
+static void FP_FASTAPASS(2) DrawZapper(uint8 *buf, int arg)
+{
+ if(arg)
+ FCEU_DrawCursor(buf, ZD.mzx, ZD.mzy);
+}
+
+static void FP_FASTAPASS(2) UpdateZapper(void *data, int arg)
+{
+ uint32 *ptr=(uint32*)data;
+
+ if(ZD.bogo)
+ ZD.bogo--;
+ if(ptr[2]&1 && (!(ZD.mzb&1)))
+ ZD.bogo=5;
+
+ ZD.mzx=ptr[0];
+ ZD.mzy=ptr[1];
+ ZD.mzb=ptr[2];
+}
+
+static void StrobeShadow(void)
+{
+ ZD.zap_readbit=0;
+}
+
+static INPUTCFC SHADOWC={ReadZapper,0,StrobeShadow,UpdateZapper,ZapperFrapper,DrawZapper};
+
+INPUTCFC *FCEU_InitSpaceShadow(void)
+{
+ memset(&ZD,0,sizeof(ZAPPER));
+ return(&SHADOWC);
+}
+
+
diff --git a/input/share.h b/input/share.h
new file mode 100644
index 00000000..e8212a3a
--- /dev/null
+++ b/input/share.h
@@ -0,0 +1,9 @@
+#include "../types.h"
+#include "../input.h"
+#include "../fceu.h"
+#include "../ppu.h"
+#include "../x6502.h"
+#include "../palette.h"
+
+void FCEU_DrawCursor(uint8 *buf, int xc, int yc);
+void FCEU_DrawGunSight(uint8 *buf, int xc, int yc);
diff --git a/input/suborkb.c b/input/suborkb.c
new file mode 100644
index 00000000..5bd70820
--- /dev/null
+++ b/input/suborkb.c
@@ -0,0 +1,94 @@
+#include <string.h>
+#include "share.h"
+#include "suborkb.h"
+#define AK2(x,y) ( (FKB_##x) | (FKB_##y <<8) )
+#define AK(x) FKB_##x
+
+static uint8 bufit[0x61];
+static uint8 ksmode;
+static uint8 ksindex;
+
+
+static uint16 matrix[13][2][4]=
+{
+{{AK(4),AK(G),AK(F),AK(C)},
+ {AK(F2),AK(E),AK(5),AK(V)}},
+{{AK(2),AK(D),AK(S),AK(END)},
+ {AK(F1),AK(W),AK(3),AK(X)}},
+{{AK(INSERT),AK(BACK),AK(NEXT),AK(RIGHT)},
+ {AK(F8),AK(PRIOR),AK(DELETE),AK(HOME)}},
+{{AK(9),AK(I),AK(L),AK(COMMA)},
+ {AK(F5),AK(O),AK(0),AK(PERIOD)}},
+{{AK(RBRACKET),AK(RETURN),AK(UP),AK(LEFT)},
+ {AK(F7),AK(LBRACKET),AK(BACKSLASH),AK(DOWN)}},
+{{AK(Q),AK(CAPITAL),AK(Z),AK(TAB)},
+ {AK(ESCAPE),AK(A),AK(1),AK(LCONTROL)}},
+{{AK(7),AK(Y),AK(K),AK(M)},
+ {AK(F4),AK(U),AK(8),AK(J)}},
+{{AK(MINUS),AK(SEMICOLON),AK(APOSTROPHE),AK(SLASH)},
+ {AK(F6),AK(P),AK(EQUALS),AK(LSHIFT)}},
+{{AK(T),AK(H),AK(N),AK(SPACE)},
+ {AK(F3),AK(R),AK(6),AK(B)}},
+{{0,0,0,0},
+ {0,0,0,0}},
+{{AK(LMENU),AK(NUMPAD4),AK(NUMPAD7),AK(F11)},
+ {AK(F12),AK(NUMPAD1),AK(NUMPAD2),AK(NUMPAD8)}},
+{{AK(SUBTRACT),AK(ADD),AK(MULTIPLY),AK(NUMPAD9)},
+ {AK(F10),AK(NUMPAD5),AK(DIVIDE),AK(NUMLOCK)}},
+{{AK(GRAVE),AK(NUMPAD6),AK(PAUSE),AK(SPACE)},
+ {AK(F9),AK(NUMPAD3),AK(DECIMAL),AK(NUMPAD0)}},
+};
+
+static void FP_FASTAPASS(1) SuborKB_Write(uint8 v)
+{
+ v>>=1;
+ if(v&2)
+ {
+ if((ksmode&1) && !(v&1))
+ ksindex=(ksindex+1)%13;
+ }
+ ksmode=v;
+}
+
+static uint8 FP_FASTAPASS(2) SuborKB_Read(int w, uint8 ret)
+{
+ if(w)
+ {
+ int x;
+
+ ret&=~0x1E;
+// if(ksindex==9)
+// {
+// if(ksmode&1)
+// ret|=2;
+// }
+// else
+// {
+ for(x=0;x<4;x++)
+ if(bufit[matrix[ksindex][ksmode&1][x]&0xFF]||bufit[matrix[ksindex][ksmode&1][x]>>8])
+ ret|=1<<(x+1);
+// }
+ ret^=0x1E;
+ }
+ return(ret);
+}
+
+static void SuborKB_Strobe(void)
+{
+ ksmode=0;
+ ksindex=0;
+}
+
+static void FP_FASTAPASS(2) SuborKB_Update(void *data, int arg)
+{
+ memcpy(bufit+1,data,0x60);
+}
+
+static INPUTCFC SuborKB={SuborKB_Read,SuborKB_Write,SuborKB_Strobe,SuborKB_Update,0,0};
+
+INPUTCFC *FCEU_InitSuborKB(void)
+{
+ memset(bufit,0,sizeof(bufit));
+ ksmode=ksindex=0;
+ return(&SuborKB);
+}
diff --git a/input/suborkb.h b/input/suborkb.h
new file mode 100644
index 00000000..735f8204
--- /dev/null
+++ b/input/suborkb.h
@@ -0,0 +1,96 @@
+#define FKB_ESCAPE 0x01
+#define FKB_F1 0x02
+#define FKB_F2 0x03
+#define FKB_F3 0x04
+#define FKB_F4 0x05
+#define FKB_F5 0x06
+#define FKB_F6 0x07
+#define FKB_F7 0x08
+#define FKB_F8 0x09
+#define FKB_F9 0x0A
+#define FKB_F10 0x0B
+#define FKB_F11 0x0C
+#define FKB_F12 0x0D
+#define FKB_PAUSE 0x0E
+#define FKB_GRAVE 0x0F
+#define FKB_1 0x10
+#define FKB_2 0x11
+#define FKB_3 0x12
+#define FKB_4 0x13
+#define FKB_5 0x14
+#define FKB_6 0x15
+#define FKB_7 0x16
+#define FKB_8 0x17
+#define FKB_9 0x18
+#define FKB_0 0x19
+#define FKB_MINUS 0x1A
+#define FKB_EQUALS 0x1B
+#define FKB_BACK 0x1C
+#define FKB_INSERT 0x1D
+#define FKB_HOME 0x1E
+#define FKB_PRIOR 0x1F
+#define FKB_NUMLOCK 0x20
+#define FKB_DIVIDE 0x21
+#define FKB_MULTIPLY 0x22
+#define FKB_SUBTRACT 0x23
+#define FKB_TAB 0x24
+#define FKB_Q 0x25
+#define FKB_W 0x26
+#define FKB_E 0x27
+#define FKB_R 0x28
+#define FKB_T 0x29
+#define FKB_Y 0x2A
+#define FKB_U 0x2B
+#define FKB_I 0x2C
+#define FKB_O 0x2D
+#define FKB_P 0x2E
+#define FKB_LBRACKET 0x2F
+#define FKB_RBRACKET 0x30
+#define FKB_RETURN 0x31
+#define FKB_DELETE 0x32
+#define FKB_END 0x33
+#define FKB_NEXT 0x34
+#define FKB_NUMPAD7 0x35
+#define FKB_NUMPAD8 0x36
+#define FKB_NUMPAD9 0x37
+#define FKB_ADD 0x38
+#define FKB_CAPITAL 0x39
+#define FKB_A 0x3A
+#define FKB_S 0x3B
+#define FKB_D 0x3C
+#define FKB_F 0x3D
+#define FKB_G 0x3E
+#define FKB_H 0x3F
+#define FKB_J 0x40
+#define FKB_K 0x41
+#define FKB_L 0x42
+#define FKB_SEMICOLON 0x43
+#define FKB_APOSTROPHE 0x44
+#define FKB_NUMPAD4 0x45
+#define FKB_NUMPAD5 0x46
+#define FKB_NUMPAD6 0x47
+#define FKB_LSHIFT 0x48
+#define FKB_Z 0x49
+#define FKB_X 0x4A
+#define FKB_C 0x4B
+#define FKB_V 0x4C
+#define FKB_B 0x4D
+#define FKB_N 0x4E
+#define FKB_M 0x4F
+#define FKB_COMMA 0x50
+#define FKB_PERIOD 0x51
+#define FKB_SLASH 0x52
+#define FKB_BACKSLASH 0x53
+#define FKB_UP 0x54
+#define FKB_NUMPAD1 0x55
+#define FKB_NUMPAD2 0x56
+#define FKB_NUMPAD3 0x57
+#define FKB_LCONTROL 0x58
+#define FKB_LMENU 0x59
+#define FKB_SPACE 0x5A
+#define FKB_LEFT 0x5B
+#define FKB_DOWN 0x5C
+#define FKB_RIGHT 0x5D
+#define FKB_NUMPAD0 0x5E
+#define FKB_DECIMAL 0x5F
+
diff --git a/input/toprider.c b/input/toprider.c
new file mode 100644
index 00000000..db72a8f2
--- /dev/null
+++ b/input/toprider.c
@@ -0,0 +1,62 @@
+/* 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 <string.h>
+#include "share.h"
+
+static uint32 bs,bss;
+static uint32 boop;
+
+static uint8 FP_FASTAPASS(2) Read(int w, uint8 ret)
+{
+ if(w)
+ {
+ ret|=(bs&1)<<3;
+ ret|=(boop&1)<<4;
+ bs>>=1;
+ boop>>=1;
+// puts("Read");
+ }
+ return(ret);
+}
+
+static void FP_FASTAPASS(1) Write(uint8 V)
+{
+ // if(V&0x2)
+ bs=bss;
+ //printf("Write: %02x\n",V);
+// boop=0xC0;
+}
+
+static void FP_FASTAPASS(2) Update(void *data, int arg)
+{
+ bss=*(uint8*)data;
+ bss|=bss<<8;
+ bss|=bss<<8;
+}
+
+static INPUTCFC TopRider={Read,Write,0,Update,0,0};
+
+INPUTCFC *FCEU_InitTopRider(void)
+{
+
+ return(&TopRider);
+}
+
diff --git a/input/zapper.c b/input/zapper.c
new file mode 100644
index 00000000..213db638
--- /dev/null
+++ b/input/zapper.c
@@ -0,0 +1,166 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "share.h"
+
+typedef struct {
+ uint32 mzx,mzy,mzb;
+ int zap_readbit;
+ int bogo;
+ int zappo;
+ uint64 zaphit;
+} ZAPPER;
+
+static ZAPPER ZD[2];
+
+static void FP_FASTAPASS(3) ZapperFrapper(int w, uint8 *bg, uint8 *spr, uint32 linets, int final)
+{
+ int xs,xe;
+ int zx,zy;
+
+ if(!bg) // New line, so reset stuff.
+ {
+ ZD[w].zappo=0;
+ return;
+ }
+ xs=ZD[w].zappo;
+ xe=final;
+
+ zx=ZD[w].mzx;
+ zy=ZD[w].mzy;
+
+ if(xe>256) xe=256;
+
+ if(scanline>=(zy-4) && scanline<=(zy+4))
+ {
+ while(xs<xe)
+ {
+ uint8 a1,a2;
+ uint32 sum;
+ if(xs<=(zx+4) && xs>=(zx-4))
+ {
+ a1=bg[xs];
+ if(spr)
+ {
+ a2=spr[xs];
+
+ if(!(a2&0x80))
+ if(!(a2&0x40) || (a1&64))
+ a1=a2;
+ }
+ a1&=63;
+
+ sum=palo[a1].r+palo[a1].g+palo[a1].b;
+ if(sum>=100*3)
+ {
+ ZD[w].zaphit=((uint64)linets+(xs+16)*(PAL?15:16))/48+timestampbase;
+ goto endo;
+ }
+ }
+ xs++;
+ }
+ }
+ endo:
+ ZD[w].zappo=final;
+}
+
+static INLINE int CheckColor(int w)
+{
+ FCEUPPU_LineUpdate();
+
+ if((ZD[w].zaphit+100)>=(timestampbase+timestamp)
+ && !(ZD[w].mzb&2)) return(0);
+
+ return(1);
+}
+
+static uint8 FP_FASTAPASS(1) ReadZapperVS(int w)
+{
+ uint8 ret=0;
+
+ if(ZD[w].zap_readbit==4) ret=1;
+
+ if(ZD[w].zap_readbit==7)
+ {
+ if(ZD[w].bogo)
+ ret|=0x1;
+ }
+ if(ZD[w].zap_readbit==6)
+ {
+ if(!CheckColor(w))
+ ret|=0x1;
+ }
+ if(!fceuindbg)
+ ZD[w].zap_readbit++;
+ return ret;
+}
+
+static void FP_FASTAPASS(1) StrobeZapperVS(int w)
+{
+ ZD[w].zap_readbit=0;
+}
+
+static uint8 FP_FASTAPASS(1) ReadZapper(int w)
+{
+ uint8 ret=0;
+ if(ZD[w].bogo)
+ ret|=0x10;
+ if(CheckColor(w))
+ ret|=0x8;
+ return ret;
+}
+
+static void FASTAPASS(3) DrawZapper(int w, uint8 *buf, int arg)
+{
+ if(arg)
+ FCEU_DrawGunSight(buf, ZD[w].mzx,ZD[w].mzy);
+}
+
+static void FP_FASTAPASS(3) UpdateZapper(int w, void *data, int arg)
+{
+ uint32 *ptr=(uint32 *)data;
+
+ //FCEU_DispMessage("%3d:%3d",ZD[w].mzx,ZD[w].mzy);
+ if(ZD[w].bogo)
+ ZD[w].bogo--;
+ if(ptr[2]&3 && (!(ZD[w].mzb&3)))
+ ZD[w].bogo=5;
+
+ ZD[w].mzx=ptr[0];
+ ZD[w].mzy=ptr[1];
+ ZD[w].mzb=ptr[2];
+}
+
+static INPUTC ZAPC={ReadZapper,0,0,UpdateZapper,ZapperFrapper,DrawZapper};
+static INPUTC ZAPVSC={ReadZapperVS,0,StrobeZapperVS,UpdateZapper,ZapperFrapper,DrawZapper};
+
+INPUTC *FCEU_InitZapper(int w)
+{
+ memset(&ZD[w],0,sizeof(ZAPPER));
+ if(FCEUGameInfo->type == GIT_VSUNI)
+ return(&ZAPVSC);
+ else
+ return(&ZAPC);
+}
+
+
diff --git a/mappers/113.c b/mappers/113.c
new file mode 100644
index 00000000..525f131c
--- /dev/null
+++ b/mappers/113.c
@@ -0,0 +1,64 @@
+/* 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"
+
+/* I'm getting the feeling this is another "jam two different bank
+ switching hardwares into one mapper".
+*/
+
+/* HES 4-in-1 */
+DECLFW(Mapper113_write)
+{
+ ROM_BANK32((V>>3)&7);
+ VROM_BANK8(((V>>3)&8)|(V&7));
+ //printf("$%04x:$%02x\n",A,V);
+}
+
+
+/* Deathbots */
+DECLFW(Mapper113_writeh)
+{
+ //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;
+ }
+}
+
+
+void Mapper113_init(void)
+{
+ ROM_BANK32(0);
+ SetWriteHandler(0x4020,0x7fff,Mapper113_write);
+ SetWriteHandler(0x8000,0xffff,Mapper113_writeh);
+}
diff --git a/mappers/15.c b/mappers/15.c
new file mode 100644
index 00000000..e649af6d
--- /dev/null
+++ b/mappers/15.c
@@ -0,0 +1,73 @@
+/* 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 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;
+ }
+}
+
+
+static DECLFW(Mapper15_write)
+{
+ mapbyte1[0]=V;
+ mapbyte1[1]=A&3;
+ Sync();
+}
+
+static void StateRestore(int version)
+{
+ Sync();
+}
+
+void Mapper15_init(void)
+{
+ mapbyte1[0]=mapbyte1[1]=0;
+ Sync();
+ GameStateRestore=StateRestore;
+ SetWriteHandler(0x8000,0xFFFF,Mapper15_write);
+}
+
diff --git a/mappers/151.c b/mappers/151.c
new file mode 100644
index 00000000..5d2cb285
--- /dev/null
+++ b/mappers/151.c
@@ -0,0 +1,41 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+
+
+DECLFW(Mapper151_write)
+{
+ switch(A&0xF000)
+ {
+ 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;
+ }
+}
+
+void Mapper151_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper151_write);
+}
+
diff --git a/mappers/16.c b/mappers/16.c
new file mode 100644
index 00000000..fae46804
--- /dev/null
+++ b/mappers/16.c
@@ -0,0 +1,303 @@
+/* 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 FP_FASTAPASS(1) BandaiIRQHook(int a)
+{
+ if(IRQa)
+ {
+ IRQCount-=a;
+ if(IRQCount<0)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ //printf("IRQ: %d, %d\n",scanline,timestamp);
+ IRQa=0;
+ IRQCount=0xFFFF;
+ }
+ }
+}
+
+static DECLFW(Mapper16_write)
+{
+ A&=0xF;
+
+ if(A<=0x7)
+ VROM_BANK1(A<<10,V);
+ else if(A==0x8)
+ ROM_BANK16(0x8000,V);
+ 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;
+ case 0xB:IRQLatch&=0xFF00; IRQLatch|=V;
+ break;
+ case 0xC:IRQLatch&=0xFF; IRQLatch|=V<<8;
+ break;
+ case 0xD: break;/* Serial EEPROM control port */
+ }
+}
+
+// Famicom jump 2:
+// 0-7: Lower bit of data selects which 256KB PRG block is in use.
+// This seems to be a hack on the developers' part, so I'll make emulation
+// of it a hack(I think the current PRG block would depend on whatever the
+// lowest bit of the CHR bank switching register that corresponds to the
+// last CHR address read).
+
+static void PRGO(void)
+{
+ uint32 base=(mapbyte1[0]&1)<<4;
+ ROM_BANK16(0x8000,(mapbyte2[0]&0xF)|base);
+ ROM_BANK16(0xC000,base|0xF);
+}
+
+static DECLFW(Mapper153_write)
+{
+ A&=0xF;
+ if(A<=0x7)
+ {
+ 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;
+ 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;
+ case 0xB:IRQLatch&=0xFF00;
+ IRQLatch|=V;
+ break;
+ case 0xC:IRQLatch&=0xFF;
+ IRQLatch|=V<<8;
+ break;
+ }
+}
+
+void Mapper16_init(void)
+{
+ MapIRQHook=BandaiIRQHook;
+ SetWriteHandler(0x6000,0xFFFF,Mapper16_write);
+}
+
+void Mapper153_init(void)
+{
+ MapIRQHook=BandaiIRQHook;
+ SetWriteHandler(0x8000,0xFFFF,Mapper153_write);
+ /* 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
new file mode 100644
index 00000000..7fae1a82
--- /dev/null
+++ b/mappers/17.c
@@ -0,0 +1,73 @@
+/* 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 void FP_FASTAPASS(1) FFEIRQHook(int a)
+{
+ if(IRQa)
+ {
+ IRQCount+=a;
+ if(IRQCount>=0x10000)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ IRQa=0;
+ IRQCount=0;
+ }
+ }
+}
+
+
+DECLFW(Mapper17_write)
+{
+ switch(A){
+ default:
+ break;
+ case 0x42FE:
+ onemir((V>>4)&1);
+ break;
+ case 0x42FF:
+ MIRROR_SET((V>>4)&1);
+ 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);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;
+ case 0x4513: VROM_BANK1(0x0C00,V);break;
+ case 0x4514: VROM_BANK1(0x1000,V);break;
+ case 0x4515: VROM_BANK1(0x1400,V);break;
+ case 0x4516: VROM_BANK1(0x1800,V);break;
+ case 0x4517: VROM_BANK1(0x1C00,V);break;
+ }
+}
+
+void Mapper17_init(void)
+{
+MapIRQHook=FFEIRQHook;
+SetWriteHandler(0x4020,0x5fff,Mapper17_write);
+}
diff --git a/mappers/18.c b/mappers/18.c
new file mode 100644
index 00000000..b682b26e
--- /dev/null
+++ b/mappers/18.c
@@ -0,0 +1,80 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+#define K4buf mapbyte2
+#define K4buf2 mapbyte3
+
+void FP_FASTAPASS(1) JalecoIRQHook(int a)
+{
+ if(IRQa && IRQCount)
+ {
+ IRQCount-=a;
+ if(IRQCount<=0)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ IRQCount=0;
+ IRQa=0;
+ }
+ }
+}
+
+DECLFW(Mapper18_write)
+{
+ 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]);
+ }
+ 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;
+ }
+}
+
+void Mapper18_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper18_write);
+ MapIRQHook=JalecoIRQHook;
+}
diff --git a/mappers/180.c b/mappers/180.c
new file mode 100644
index 00000000..bd877c81
--- /dev/null
+++ b/mappers/180.c
@@ -0,0 +1,14 @@
+#include "mapinc.h"
+
+
+
+DECLFW(Mapper180_write)
+{
+ROM_BANK16(0xC000,V);
+}
+
+void Mapper180_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper180_write);
+}
+
diff --git a/mappers/183.c b/mappers/183.c
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/mappers/183.c
diff --git a/mappers/184.c b/mappers/184.c
new file mode 100644
index 00000000..70fd6b17
--- /dev/null
+++ b/mappers/184.c
@@ -0,0 +1,15 @@
+#include "mapinc.h"
+
+
+
+DECLFW(Mapper184_write)
+{
+VROM_BANK4(0x0000,V);
+VROM_BANK4(0x1000,(V>>4));
+}
+
+void Mapper184_init(void)
+{
+ SetWriteHandler(0x6000,0xffff,Mapper184_write);
+}
+
diff --git a/mappers/193.c b/mappers/193.c
new file mode 100644
index 00000000..0afa2475
--- /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 00000000..ec133084
--- /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 00000000..03e77e69
--- /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 00000000..cac2a881
--- /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 00000000..6ab5d520
--- /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 00000000..3d799186
--- /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/21.c b/mappers/21.c
new file mode 100644
index 00000000..8d60d4c2
--- /dev/null
+++ b/mappers/21.c
@@ -0,0 +1,106 @@
+/* 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"
+
+#define K4buf mapbyte2
+#define K4IRQ mapbyte1[1]
+#define K4sel mapbyte1[0]
+
+static int acount=0;
+
+DECLFW(Mapper21_write)
+{
+ A|=((A>>5)&0xF);
+
+ 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);
+ }
+ else if(A>=0xb000 && A<=0xefff)
+ {
+ A&=0xF006;
+ {
+ int x=((A>>2)&1)|((A-0xB000)>>11);
+
+ K4buf[x]&=(0xF0)>>((A&2)<<1);
+ K4buf[x]|=(V&0xF)<<((A&2)<<1);
+ VROM_BANK1(x<<10,K4buf[x]);
+ }
+
+ }
+ 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);
+ }
+ K4sel=V;
+ break;
+ case 0xf000:IRQLatch&=0xF0;IRQLatch|=V&0xF;break;
+ case 0xf002:IRQLatch&=0x0F;IRQLatch|=V<<4;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 ((227*2)+1)
+ //#define LCYCS 341
+ if(IRQa)
+ {
+// acount+=a*3;
+ acount+=a*4;
+ if(acount>=LCYCS)
+ {
+ doagainbub:acount-=LCYCS;IRQCount++;
+ if(IRQCount&0x100) {X6502_IRQBegin(FCEU_IQEXT);IRQCount=IRQLatch;}
+ if(acount>=LCYCS) goto doagainbub;
+ }
+ }
+}
+
+void Mapper21_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper21_write);
+ MapIRQHook=KonamiIRQHook;
+}
diff --git a/mappers/212.c b/mappers/212.c
new file mode 100644
index 00000000..b069fc3f
--- /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 00000000..e0b8d82a
--- /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 00000000..03a73ce3
--- /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 00000000..772691c2
--- /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 00000000..6f7a2510
--- /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
new file mode 100644
index 00000000..4a080946
--- /dev/null
+++ b/mappers/22.c
@@ -0,0 +1,63 @@
+/* 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"
+
+#define K4buf mapbyte2
+
+
+
+DECLFW(Mapper22_write)
+{
+ if(A<=0xAFFF)
+ {
+ switch(A&0xF000)
+ {
+ 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;
+ case 0x03:onemir(1);break;
+ }
+ break;
+ }
+ }
+ else
+ {
+ 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);
+ }
+ }
+}
+
+
+void Mapper22_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper22_write);
+}
diff --git a/mappers/225.c b/mappers/225.c
new file mode 100644
index 00000000..14e38f26
--- /dev/null
+++ b/mappers/225.c
@@ -0,0 +1,87 @@
+/* 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"
+
+
+#define reg1 mapbyte1[0]
+#define reg2 mapbyte1[1]
+#define reg3 mapbyte1[2]
+#define reg4 mapbyte1[3]
+
+DECLFR(A110in1read)
+{
+switch(A&0x3)
+ {
+ case 0:return reg1;break;
+ case 1:return reg2;break;
+ case 2:return reg3;break;
+ case 3:return reg4;break;
+ }
+return 0xF;
+}
+DECLFW(A110in1regwr)
+{
+switch(A&0x3)
+ {
+ case 0:reg1=V&0xF;break;
+ case 1:reg2=V&0xF;break;
+ case 2:reg3=V&0xF;break;
+ case 3:reg4=V&0xF;break;
+ }
+}
+
+DECLFW(Mapper225_write)
+{
+ int banks=0;
+
+ MIRROR_SET((A>>13)&1);
+ if(A&0x4000)
+ banks=1;
+ else
+ banks=0;
+
+ VROM_BANK8(((A&0x003f)+(banks<<6)));
+ if(A&0x1000)
+ {
+ if(A&0x40)
+ {
+ ROM_BANK16(0x8000,((((((A>>7)&0x1F)+(banks<<5)))<<1)+1));
+ ROM_BANK16(0xC000,((((((A>>7)&0x1F)+(banks<<5)))<<1)+1));
+ }
+ else
+ {
+ ROM_BANK16(0x8000,(((((A>>7)&0x1F)+(banks<<5)))<<1));
+ ROM_BANK16(0xC000,(((((A>>7)&0x1F)+(banks<<5)))<<1));
+ }
+ }
+ else
+ {
+ ROM_BANK32(((((A>>7)&0x1F)+(banks<<5))));
+ }
+}
+
+void Mapper225_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper225_write);
+ SetReadHandler(0x5800,0x5fff,A110in1read);
+ SetWriteHandler(0x5800,0x5fff,A110in1regwr);
+}
+
diff --git a/mappers/226.c b/mappers/226.c
new file mode 100644
index 00000000..bde4f523
--- /dev/null
+++ b/mappers/226.c
@@ -0,0 +1,105 @@
+/* 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"
+
+#define rg mapbyte1
+static void DoPRG(void)
+{
+ int32 b=((rg[0]>>1)&0xF) | ((rg[0]>>3)&0x10) | ((rg[1]&1)<<5);
+ if(rg[0]&0x20) // 16 KB
+ {
+ ROM_BANK16(0x8000,(b<<1)|(rg[0]&1));
+ ROM_BANK16(0xC000,(b<<1)|(rg[0]&1));
+ }
+ else
+ ROM_BANK32(b);
+}
+
+static DECLFW(Mapper226_write)
+{
+ rg[A&1]=V;
+ DoPRG();
+ if(A&1)
+ {
+ if(rg[1]&2)
+ PPUCHRRAM=0; // Write protected.
+ else
+ PPUCHRRAM=0xFF; // Not write protected.
+ }
+ else
+ MIRROR_SET2((rg[0]>>6)&1);
+}
+
+static void M26Reset(void)
+{
+ rg[0]=rg[1]=0;
+ DoPRG();
+ PPUCHRRAM=0xFF;
+ MIRROR_SET2(0);
+}
+
+static void M26Restore(int version)
+{
+ DoPRG();
+ if(rg[1]&2)
+ PPUCHRRAM=0; // Write protected.
+ else
+ PPUCHRRAM=0xFF; // Not write protected.
+ MIRROR_SET2((rg[0]>>6)&1);
+}
+
+void Mapper226_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper226_write);
+ MapperReset=M26Reset;
+ GameStateRestore=M26Restore;
+ M26Reset();
+}
+
+#ifdef OLD // What the heck is this??
+DECLFW(Mapper226_write)
+{
+ MIRROR_SET((A>>13)&1);
+ VROM_BANK8(A&0x7F);
+ if(A&0x1000)
+ {
+ if(A&0x40)
+ {
+ ROM_BANK16(0x8000,(((A>>7))<<1)+1);
+ ROM_BANK16(0xC000,(((A>>7))<<1)+1);
+ }
+ else
+ {
+ ROM_BANK16(0x8000,(((A>>7))<<1));
+ ROM_BANK16(0xC000,(((A>>7))<<1));
+ }
+ }
+ else
+ {
+ ROM_BANK32(A>>7);
+ }
+}
+
+void Mapper226_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper226_write);
+}
+#endif
diff --git a/mappers/227.c b/mappers/227.c
new file mode 100644
index 00000000..457e79e2
--- /dev/null
+++ b/mappers/227.c
@@ -0,0 +1,79 @@
+/* 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"
+
+#define rg mapbyte1
+
+static void DoSync(uint32 A)
+{
+ int32 p=((A>>3)&0xF) | ((A>>4)&0x10);
+
+ rg[0]=A;
+ rg[1]=A>>8;
+
+ MIRROR_SET((A>>1)&1);
+ if(A&1) //32 KB
+ {
+ ROM_BANK32(p);
+ }
+ else //16 KB
+ {
+ ROM_BANK16(0x8000,(p<<1)|((A&4)>>2));
+ ROM_BANK16(0xc000,(p<<1)|((A&4)>>2));
+ }
+ if(A&0x80)
+ {
+ PPUCHRRAM=0;
+ }
+ else
+ {
+ PPUCHRRAM=0xFF;
+ if(A&0x200)
+ ROM_BANK16(0xC000,(p<<1)|7);
+ else
+ ROM_BANK16(0xC000,(p<<1)&(~7));
+ }
+}
+
+static DECLFW(Mapper227_write)
+{
+ rg[A&1]=V;
+ DoSync(A);
+}
+
+static void M227Reset(void)
+{
+ rg[0]=rg[1]=0;
+ DoSync(0);
+}
+
+static void M227Restore(int version)
+{
+ DoSync(rg[0]|(rg[1]<<8));
+}
+
+void Mapper227_init(void)
+{
+ SetWriteHandler(0x6000,0xffff,Mapper227_write);
+ MapperReset=M227Reset;
+ GameStateRestore=M227Restore;
+ M227Reset();
+}
diff --git a/mappers/228.c b/mappers/228.c
new file mode 100644
index 00000000..bfae3a63
--- /dev/null
+++ b/mappers/228.c
@@ -0,0 +1,53 @@
+/* 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(Mapper228_write)
+{
+ uint32 page,pagel,pageh;
+
+ 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) );
+}
+
+static void A52Reset(void)
+{
+ Mapper228_write(0,0);
+}
+
+void Mapper228_init(void)
+{
+ MapperReset=A52Reset;
+ A52Reset();
+ SetWriteHandler(0x8000,0xffff,Mapper228_write);
+}
+
diff --git a/mappers/229.c b/mappers/229.c
new file mode 100644
index 00000000..a78dd731
--- /dev/null
+++ b/mappers/229.c
@@ -0,0 +1,48 @@
+/* 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"
+
+
+
+DECLFW(Mapper229_write)
+{
+if(A>=0x8000)
+{
+MIRROR_SET((A>>5)&1);
+if(!(A&0x1e))
+ {
+ ROM_BANK32(0);
+ }
+else
+ {
+ ROM_BANK16(0x8000,A&0x1f);
+ ROM_BANK16(0xC000,A&0x1f);
+ }
+ VROM_BANK8(A);
+}
+
+}
+
+void Mapper229_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper229_write);
+}
+
diff --git a/mappers/23.c b/mappers/23.c
new file mode 100644
index 00000000..d61a5557
--- /dev/null
+++ b/mappers/23.c
@@ -0,0 +1,103 @@
+/* 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"
+
+#define K4buf mapbyte2
+#define K4IRQ mapbyte1[1]
+#define K4sel mapbyte1[0]
+static int acount=0;
+static DECLFW(Mapper23_write)
+{
+ if((A&0xF000)==0x8000)
+ {
+ if(K4sel&2)
+ ROM_BANK8(0xC000,V);
+ else
+ ROM_BANK8(0x8000,V);
+ }
+ else if((A&0xF000)==0xA000)
+ ROM_BANK8(0xA000,V);
+ else
+ {
+ A|=((A>>2)&0x3)|((A>>4)&0x3)|((A>>6)&0x3);
+ A&=0xF003;
+ if(A>=0xb000 && A<=0xe003)
+ {
+ int x=((A>>1)&1)|((A-0xB000)>>11);
+
+ K4buf[x]&=(0xF0)>>((A&1)<<2);
+ K4buf[x]|=(V&0xF)<<((A&1)<<2);
+ VROM_BANK1(x<<10,K4buf[x]);
+ }
+ else
+ switch(A)
+ {
+ 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);acount=0;IRQCount=IRQLatch;IRQa=V&2;K4IRQ=V&1;break;
+ case 0xf003:X6502_IRQEnd(FCEU_IQEXT);IRQa=K4IRQ;break;
+ case 0x9001:
+ case 0x9002:
+ case 0x9003:
+ if((K4sel&2)!=(V&2))
+ {
+ uint8 swa;
+ swa=PRGBankList[0];
+ ROM_BANK8(0x8000,PRGBankList[2]);
+ ROM_BANK8(0xc000,swa);
+ }
+ K4sel=V;
+ break;
+ case 0x9000:
+ 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;
+ }
+ }
+}
+
+void FP_FASTAPASS(1) KonamiIRQHook2(int a)
+{
+ #define LCYCS 341
+ if(IRQa)
+ {
+ acount+=a*3;
+ if(acount>=LCYCS)
+ {
+ doagainbub:acount-=LCYCS;IRQCount++;
+ if(IRQCount&0x100) {X6502_IRQBegin(FCEU_IQEXT);IRQCount=IRQLatch;}
+ if(acount>=LCYCS) goto doagainbub;
+ }
+ }
+}
+
+void Mapper23_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper23_write);
+ MapIRQHook=KonamiIRQHook2;
+}
+
diff --git a/mappers/230.c b/mappers/230.c
new file mode 100644
index 00000000..cbf1fbe8
--- /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 00000000..9b8d1fce
--- /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
new file mode 100644
index 00000000..548db8c2
--- /dev/null
+++ b/mappers/232.c
@@ -0,0 +1,50 @@
+/* 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 void DoIt(void)
+{
+ ROM_BANK16(0x8000,(mapbyte1[1]&3) | ((mapbyte1[0]&0x18)>>1));
+ ROM_BANK16(0xc000,3|(((mapbyte1[0])&0x18)>>1));
+}
+
+DECLFW(Mapper232_write)
+{
+ if(A<=0x9FFF)
+ mapbyte1[0]=V;
+ else
+ mapbyte1[1]=V;
+ DoIt();
+}
+
+static void QuattroReset(void)
+{
+ mapbyte1[0]=0x18;
+ DoIt();
+}
+
+void Mapper232_init(void)
+{
+ SetWriteHandler(0x6000,0xffff,Mapper232_write);
+ MapperReset=QuattroReset;
+ QuattroReset();
+}
+
diff --git a/mappers/234.c b/mappers/234.c
new file mode 100644
index 00000000..d8ca53ff
--- /dev/null
+++ b/mappers/234.c
@@ -0,0 +1,107 @@
+/* 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"
+
+#define r1 mapbyte1[0]
+#define r2 mapbyte1[1]
+
+static void DoBS(void)
+{
+ if(r1&0x40)
+ {
+ ROM_BANK32((r1&0xE)|(r2&1));
+ VROM_BANK8( ((r1&0xE)<<2) | ((r2>>4)&7) );
+ }
+ else
+ {
+ ROM_BANK32(r1&0xF);
+ VROM_BANK8( ((r1&0xF)<<2) | ((r2>>4)&3) );
+ }
+}
+
+static void R1Set(uint8 V)
+{
+ if(r1) return;
+ r1=V;
+ MIRROR_SET(V>>7);
+ DoBS();
+}
+
+static void R2Set(uint8 V)
+{
+ r2=V;
+ DoBS();
+}
+
+DECLFW(R1W)
+{
+ R1Set(V);
+}
+
+DECLFR(R1R)
+{
+ uint8 r=CartBR(A);
+ R1Set(r);
+ return r;
+}
+
+DECLFW(R2W)
+{
+ R2Set(V);
+}
+
+DECLFR(R2R)
+{
+ uint8 r=CartBR(A);
+ R2Set(r);
+ return r;
+}
+
+static void M15Restore(int version)
+{
+ DoBS();
+ MIRROR_SET(r1>>7);
+}
+
+static void M15Reset(void)
+{
+ r1=r2=0;
+ DoBS();
+ MIRROR_SET(0);
+}
+
+void Mapper234_init(void)
+{
+ SetWriteHandler(0xff80,0xff9f,R1W);
+ SetReadHandler(0xff80,0xff9f,R1R);
+
+ SetWriteHandler(0xffe8,0xfff7,R2W);
+ SetReadHandler(0xffe8,0xfff7,R2R);
+
+ SetReadHandler(0x6000,0x7FFF,0);
+ SetWriteHandler(0x6000,0x7FFF,0);
+
+ M15Reset();
+
+ GameStateRestore=M15Restore;
+ MapperReset=M15Reset;
+}
+
diff --git a/mappers/240.c b/mappers/240.c
new file mode 100644
index 00000000..dbbfe192
--- /dev/null
+++ b/mappers/240.c
@@ -0,0 +1,39 @@
+/* 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"
+
+
+
+DECLFW(Mapper240_write)
+{
+ if(A<0x8000)
+ {
+ ROM_BANK32(V>>4);
+ VROM_BANK8(V&0xF);
+ }
+}
+
+void Mapper240_init(void)
+{
+ SetWriteHandler(0x4020,0x5fff,Mapper240_write);
+ SetWriteHandler(0x8000,0xffff,Mapper240_write);
+}
+
diff --git a/mappers/241.c b/mappers/241.c
new file mode 100644
index 00000000..c0fe7fe6
--- /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
new file mode 100644
index 00000000..2fa41710
--- /dev/null
+++ b/mappers/242.c
@@ -0,0 +1,41 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+
+DECLFW(Mapper242_write)
+{
+ ROM_BANK32((A>>3)&0xF);
+ switch(V&3)
+ {
+ case 0:MIRROR_SET(0);break;
+ case 1:MIRROR_SET(1);break;
+ case 2:onemir(0);break;
+ case 3:onemir(1);break;
+ }
+}
+
+void Mapper242_init(void)
+{
+ ROM_BANK32(0);
+ SetWriteHandler(0x8000,0xffff,Mapper242_write);
+}
+
diff --git a/mappers/244.c b/mappers/244.c
new file mode 100644
index 00000000..13ea2c1d
--- /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
new file mode 100644
index 00000000..8623233c
--- /dev/null
+++ b/mappers/246.c
@@ -0,0 +1,44 @@
+/* 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"
+
+
+DECLFW(Mapper246_write)
+{
+ switch(A&0xF007)
+ {
+ 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;
+ case 0x6007:VROM_BANK2(0x1800,V);break;
+ }
+}
+
+void Mapper246_init(void)
+{
+ SetWriteHandler(0x4020,0x67ff,Mapper246_write);
+ SetWriteHandler(0x8000,0xffff,Mapper246_write);
+}
+
diff --git a/mappers/24and26.c b/mappers/24and26.c
new file mode 100644
index 00000000..0244f45e
--- /dev/null
+++ b/mappers/24and26.c
@@ -0,0 +1,369 @@
+/* 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 void (*sfun[3])(void);
+
+#define vrctemp mapbyte1[0]
+#define VPSG2 mapbyte3
+#define VPSG mapbyte2
+
+static void DoSQV1(void);
+static void DoSQV2(void);
+static void DoSawV(void);
+
+static int swaparoo;
+
+static int acount=0;
+
+static void FP_FASTAPASS(1) KonamiIRQHook(int a)
+{
+ #define LCYCS 341
+// #define LCYCS ((227*2)+1)
+ if(IRQa)
+ {
+ acount+=a*3;
+ if(acount>=LCYCS)
+ {
+ doagainbub:acount-=LCYCS;IRQCount++;
+ if(IRQCount==0x100)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ IRQCount=IRQLatch;
+ }
+ if(acount>=LCYCS) goto doagainbub;
+ }
+ }
+}
+
+static DECLFW(VRC6SW)
+{
+ 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);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);break;
+ case 0xD000:VROM_BANK1(0x0000,V);break;
+ case 0xD001:VROM_BANK1(0x0400,V);break;
+ case 0xD002:VROM_BANK1(0x0800,V);break;
+ case 0xD003:VROM_BANK1(0x0c00,V);break;
+ case 0xE000:VROM_BANK1(0x1000,V);break;
+ 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;
+ //acount=0;
+ break;
+ case 0xF001:IRQa=V&2;
+ vrctemp=V&1;
+ if(V&2)
+ {
+ IRQCount=IRQLatch;
+ acount=0;
+ }
+ X6502_IRQEnd(FCEU_IQEXT);
+ break;
+ case 0xf002:IRQa=vrctemp;
+ X6502_IRQEnd(FCEU_IQEXT);break;
+ case 0xF003:break;
+ }
+}
+
+static int32 CVBC[3];
+static int32 vcount[3];
+static int32 dcount[2];
+
+static INLINE void DoSQV(int x)
+{
+ 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<end;V++)
+ Wave[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;V<end;V++)
+ {
+ if(dcount[x]>thresh) /* Greater than, not >=. Important. */
+ Wave[V>>4]+=amp;
+ vcount[x]-=nesincsize;
+ while(vcount[x]<=0) /* Should only be <0 in a few circumstances. */
+ {
+ vcount[x]+=freq;
+ dcount[x]=(dcount[x]+1)&15;
+ }
+ }
+ }
+ }
+}
+
+static void DoSQV1(void)
+{
+ DoSQV(0);
+}
+
+static void DoSQV2(void)
+{
+ DoSQV(1);
+}
+
+static void DoSawV(void)
+{
+ int V;
+ int32 start,end;
+
+ start=CVBC[2];
+ end=(SOUNDTS<<16)/soundtsinc;
+ if(end<=start) return;
+ CVBC[2]=end;
+
+ if(VPSG2[2]&0x80)
+ {
+ static int32 saw1phaseacc=0;
+ uint32 freq3;
+ static uint8 b3=0;
+ static int32 phaseacc=0;
+ static uint32 duff=0;
+
+ freq3=(VPSG2[1]+((VPSG2[2]&15)<<8)+1);
+
+ for(V=start;V<end;V++)
+ {
+ saw1phaseacc-=nesincsize;
+ if(saw1phaseacc<=0)
+ {
+ int32 t;
+ rea:
+ t=freq3;
+ t<<=18;
+ saw1phaseacc+=t;
+ phaseacc+=VPSG2[0]&0x3f;
+ b3++;
+ if(b3==7)
+ {
+ b3=0;
+ phaseacc=0;
+ }
+ if(saw1phaseacc<=0)
+ goto rea;
+ duff=(((phaseacc>>3)&0x1f)<<4)*6/8;
+ }
+ Wave[V>>4]+=duff;
+ }
+ }
+}
+
+static INLINE void DoSQVHQ(int x)
+{
+ int32 V;
+ int32 amp=((VPSG[x<<2]&15)<<8)*6/8;
+
+ if(VPSG[(x<<2)|0x2]&0x80)
+ {
+ if(VPSG[x<<2]&0x80)
+ {
+ for(V=CVBC[x];V<SOUNDTS;V++)
+ WaveHi[V]+=amp;
+ }
+ else
+ {
+ int32 thresh=(VPSG[x<<2]>>4)&7;
+ for(V=CVBC[x];V<SOUNDTS;V++)
+ {
+ if(dcount[x]>thresh) /* 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 void DoSQV1HQ(void)
+{
+ DoSQVHQ(0);
+}
+
+static void DoSQV2HQ(void)
+{
+ DoSQVHQ(1);
+}
+
+static void DoSawVHQ(void)
+{
+ static uint8 b3=0;
+ static int32 phaseacc=0;
+ int32 V;
+
+ if(VPSG2[2]&0x80)
+ {
+ for(V=CVBC[2];V<SOUNDTS;V++)
+ {
+ WaveHi[V]+=(((phaseacc>>3)&0x1f)<<8)*6/8;
+ vcount[2]--;
+ if(vcount[2]<=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;
+}
+
+
+void VRC6Sound(int Count)
+{
+ int x;
+
+ DoSQV1();
+ DoSQV2();
+ DoSawV();
+ for(x=0;x<3;x++)
+ CVBC[x]=Count;
+}
+
+void VRC6SoundHQ(void)
+{
+ DoSQV1HQ();
+ DoSQV2HQ();
+ DoSawVHQ();
+}
+
+void VRC6SyncHQ(int32 ts)
+{
+ int x;
+ for(x=0;x<3;x++) CVBC[x]=ts;
+}
+
+static void VRC6_ESI(void)
+{
+ GameExpSound.RChange=VRC6_ESI;
+ GameExpSound.Fill=VRC6Sound;
+ GameExpSound.HiFill=VRC6SoundHQ;
+ GameExpSound.HiSync=VRC6SyncHQ;
+
+ memset(CVBC,0,sizeof(CVBC));
+ memset(vcount,0,sizeof(vcount));
+ memset(dcount,0,sizeof(dcount));
+ if(FSettings.SndRate)
+ {
+ if(FSettings.soundq>=1)
+ {
+ sfun[0]=DoSQV1HQ;
+ sfun[1]=DoSQV2HQ;
+ sfun[2]=DoSawVHQ;
+ }
+ else
+ {
+ sfun[0]=DoSQV1;
+ sfun[1]=DoSQV2;
+ sfun[2]=DoSawV;
+ }
+ }
+ else
+ memset(sfun,0,sizeof(sfun));
+}
+
+void Mapper24_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper24_write);
+ VRC6_ESI();
+ MapIRQHook=KonamiIRQHook;
+ swaparoo=0;
+}
+
+void Mapper26_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper24_write);
+ VRC6_ESI();
+ MapIRQHook=KonamiIRQHook;
+ swaparoo=1;
+}
+
+void NSFVRC6_Init(void)
+{
+ VRC6_ESI();
+ SetWriteHandler(0x8000,0xbfff,VRC6SW);
+}
diff --git a/mappers/25.c b/mappers/25.c
new file mode 100644
index 00000000..f8c1d73a
--- /dev/null
+++ b/mappers/25.c
@@ -0,0 +1,100 @@
+/* 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"
+
+#define K4buf mapbyte2
+#define K4IRQ mapbyte1[1]
+#define K4sel mapbyte1[0]
+
+static int acount=0;
+static DECLFW(Mapper25_write)
+{
+ A=(A&0xF003)|((A&0xC)>>2);
+
+ 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)
+ {
+ if(K4sel&2)
+ ROM_BANK8(0xC000,V);
+ else
+ ROM_BANK8(0x8000,V);
+ }
+ 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)
+{
+// #define LCYCS ((227*2))
+ #define LCYCS 341
+ if(IRQa)
+ {
+ acount+=a*3;
+ // acount+=a*4;
+ if(acount>=LCYCS)
+ {
+ doagainbub:acount-=LCYCS;IRQCount++;
+ if(IRQCount&0x100)
+ {//acount=0;
+ X6502_IRQBegin(FCEU_IQEXT);IRQCount=IRQLatch;
+ }
+ if(acount>=LCYCS) goto doagainbub;
+ }
+ }
+}
+
+void Mapper25_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper25_write);
+ MapIRQHook=KonamiIRQHook;
+}
+
diff --git a/mappers/255.c b/mappers/255.c
new file mode 100644
index 00000000..d65f18da
--- /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,0x5FF0,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 00000000..9dbe5cf2
--- /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
new file mode 100644
index 00000000..13e4bba9
--- /dev/null
+++ b/mappers/32.c
@@ -0,0 +1,53 @@
+/* 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"
+
+
+#define IREMCon mapbyte1[0]
+
+static DECLFW(Mapper32_write)
+{
+ switch(A>>12)
+ {
+ case 0x8:
+ mapbyte1[1]=V;
+ if(IREMCon) {ROM_BANK8(0xc000,V);ROM_BANK8(0x8000,~1);}
+ else {ROM_BANK8(0x8000,V);ROM_BANK8(0xc000,~1);}
+ break;
+ 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);
+ break;
+ case 0xa:ROM_BANK8(0xA000,V);
+ break;
+ }
+
+ if((A&0xF000)==0xb000)
+ VROM_BANK1((A&0x7)<<10,V);
+}
+
+void Mapper32_init(void)
+{
+ ROM_BANK16(0x8000,0);
+ ROM_BANK16(0xc000,~0);
+ SetWriteHandler(0x8000,0xffff,Mapper32_write);
+}
diff --git a/mappers/33.c b/mappers/33.c
new file mode 100644
index 00000000..f3362c01
--- /dev/null
+++ b/mappers/33.c
@@ -0,0 +1,80 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+static int is48;
+
+static DECLFW(Mapper33_write)
+{
+ //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(!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;
+ }
+}
+
+static void heho(void)
+{
+ if(IRQa)
+ {
+ IRQCount++;
+ if(IRQCount==0x100)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ IRQa=0;
+ }
+ }
+}
+
+void Mapper33_init(void)
+{
+ 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
new file mode 100644
index 00000000..471a7cc3
--- /dev/null
+++ b/mappers/40.c
@@ -0,0 +1,58 @@
+/* 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(Mapper40_write)
+{
+ switch(A&0xe000)
+ {
+ case 0x8000:IRQa=0;IRQCount=0;X6502_IRQEnd(FCEU_IQEXT);break;
+ case 0xa000:IRQa=1;break;
+ case 0xe000:ROM_BANK8(0xc000,V&7);break;
+ }
+}
+
+static void FP_FASTAPASS(1) Mapper40IRQ(int a)
+{
+ if(IRQa)
+ {
+ if(IRQCount<4096)
+ IRQCount+=a;
+ else
+ {
+ IRQa=0;
+ X6502_IRQBegin(FCEU_IQEXT);
+ }
+ }
+}
+
+void Mapper40_init(void)
+{
+ ROM_BANK8(0x6000,(~0)-1);
+ ROM_BANK8(0x8000,(~0)-3);
+ ROM_BANK8(0xa000,(~0)-2);
+ SetWriteHandler(0x8000,0xffff,Mapper40_write);
+ SetReadHandler(0x6000,0x7fff,CartBR);
+ MapIRQHook=Mapper40IRQ;
+}
+
+
diff --git a/mappers/41.c b/mappers/41.c
new file mode 100644
index 00000000..dfb69089
--- /dev/null
+++ b/mappers/41.c
@@ -0,0 +1,57 @@
+/* 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"
+
+
+#define calreg mapbyte1[0]
+#define calchr mapbyte1[1]
+
+DECLFW(Mapper41_write)
+{
+ if(A<0x8000)
+ {
+ 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);
+ }
+}
+
+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
new file mode 100644
index 00000000..bf31ac29
--- /dev/null
+++ b/mappers/42.c
@@ -0,0 +1,64 @@
+/* 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(Mapper42_write)
+{
+// FCEU_printf("%04x:%04x\n",A,V);
+ switch(A&0xe003)
+ {
+ 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;X6502_IRQEnd(FCEU_IQEXT);break;
+ }
+}
+
+static void FP_FASTAPASS(1) Mapper42IRQ(int a)
+{
+ if(IRQa)
+ {
+ IRQCount+=a;
+ if(IRQCount>=32768) IRQCount-=32768;
+ if(IRQCount>=24576)
+ X6502_IRQBegin(FCEU_IQEXT);
+ else
+ X6502_IRQEnd(FCEU_IQEXT);
+ }
+}
+
+static void Mapper42_StateRestore(int version)
+{
+ ROM_BANK8(0x6000,mapbyte1[0]&0xF);
+}
+
+
+void Mapper42_init(void)
+{
+ ROM_BANK8(0x6000,0);
+ ROM_BANK32(~0);
+ SetWriteHandler(0x6000,0xffff,Mapper42_write);
+ SetReadHandler(0x6000,0x7fff,CartBR);
+ MapStateRestore=Mapper42_StateRestore;
+ MapIRQHook=Mapper42IRQ;
+}
+
diff --git a/mappers/43.c b/mappers/43.c
new file mode 100644
index 00000000..ef7d40d7
--- /dev/null
+++ b/mappers/43.c
@@ -0,0 +1,76 @@
+/* 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(Mapper43_write)
+{
+ //printf("$%04x:$%02x\n",A,V);
+ if((A&0x8122)==0x8122)
+ {
+ X6502_IRQEnd(FCEU_IQEXT);
+ if(V&2) IRQa=1;
+ else
+ IRQCount=IRQa=0;
+ }
+}
+
+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);
+}
+
+static void FP_FASTAPASS(1) M43Ho(int a)
+{
+ IRQCount+=a;
+ if(IRQa)
+ if(IRQCount>=4096)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ }
+}
+
+//static DECLFR(boo)
+//{
+// printf("$%04x\n",A);
+// return( ROM[0x2000*8 +0x1000 +(A-0x5000)]);
+//}
+
+void Mapper43_init(void)
+{
+ 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
new file mode 100644
index 00000000..8c4ef6d3
--- /dev/null
+++ b/mappers/46.c
@@ -0,0 +1,48 @@
+/* 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"
+
+
+
+#define A64reg mapbyte1[0]
+#define A64wr mapbyte1[1]
+
+DECLFW(Mapper46_writel)
+{
+ A64reg=V;
+ ROM_BANK32((A64wr&1)+((A64reg&0xF)<<1));
+ VROM_BANK8(((A64wr>>4)&7)+((A64reg&0xF0)>>1));
+}
+
+DECLFW(Mapper46_write)
+{
+ A64wr=V;
+ ROM_BANK32((V&1)+((A64reg&0xF)<<1));
+ VROM_BANK8(((V>>4)&7)+((A64reg&0xF0)>>1));
+}
+
+void Mapper46_init(void)
+{
+ MIRROR_SET(0);
+ ROM_BANK32(0);
+ SetWriteHandler(0x8000,0xffff,Mapper46_write);
+ SetWriteHandler(0x6000,0x7fff,Mapper46_writel);
+}
diff --git a/mappers/50.c b/mappers/50.c
new file mode 100644
index 00000000..8d7f515f
--- /dev/null
+++ b/mappers/50.c
@@ -0,0 +1,75 @@
+/* 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 void FP_FASTAPASS(1) Mapper50IRQ(int a)
+{
+ if(IRQa)
+ {
+ if(IRQCount<4096)
+ IRQCount+=a;
+ else
+ {
+ IRQa=0;
+ X6502_IRQBegin(FCEU_IQEXT);
+ }
+ }
+}
+
+static void M50Restore(int version)
+{
+ setprg8(0xc000,mapbyte1[0]);
+}
+
+static DECLFW(M50W)
+{
+ 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 Mapper50_init(void)
+{
+ 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
new file mode 100644
index 00000000..cc1fbbdc
--- /dev/null
+++ b/mappers/51.c
@@ -0,0 +1,66 @@
+/* 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"
+
+#define mode mapbyte1[0]
+#define page mapbyte1[1]
+
+static uint32 Get8K(uint32 A)
+{
+ uint32 bank;
+
+ bank=(page<<2)|((A>>13)&1);
+
+ if(A&0x4000 && !(mode&1)) bank|=0xC;
+ if(!(A&0x8000)) bank|=0x20;
+ if(mode==2) bank|=2;
+ else bank|=(A>>13)&2;
+ return(bank);
+}
+
+static void Synco(void)
+{
+ uint32 x;
+ if(mapbyte1[0]<=2)
+ MIRROR_SET2(1);
+ else
+ MIRROR_SET2(0);
+ for(x=0x6000;x<0x10000;x+=8192)
+ ROM_BANK8(x,Get8K(x));
+}
+
+static DECLFW(Write)
+{
+ if(A&0x8000) mapbyte1[1]=V&0xF;
+ else mapbyte1[0]=(mapbyte1[0]&2)|((V>>1)&1);
+
+ if(A&0x4000) mapbyte1[0]=(mapbyte1[0]&1)|((V>>3)&2);
+ Synco();
+}
+
+void Mapper51_init(void)
+{
+ SetWriteHandler(0x6000,0xFFFF,Write);
+ SetReadHandler(0x6000,0xFFFF,CartBR);
+ mapbyte1[0]=1;
+ mapbyte1[1]=0;
+ Synco();
+}
diff --git a/mappers/59.c b/mappers/59.c
new file mode 100644
index 00000000..30ddb8b4
--- /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
new file mode 100644
index 00000000..c6c5bf5c
--- /dev/null
+++ b/mappers/6.c
@@ -0,0 +1,80 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "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<<x))
+ {
+ if(CHRBankList[x]>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 00000000..b48087ca
--- /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/61.c b/mappers/61.c
new file mode 100644
index 00000000..43039329
--- /dev/null
+++ b/mappers/61.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(Mapper61_write)
+{
+// printf("$%04x:$%02x\n",A,V);
+ switch(A&0x30)
+ {
+ 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;
+ }
+ #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 Mapper61_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper61_write);
+}
diff --git a/mappers/62.c b/mappers/62.c
new file mode 100644
index 00000000..4d03c887
--- /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) {
+ 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/65.c b/mappers/65.c
new file mode 100644
index 00000000..d8176943
--- /dev/null
+++ b/mappers/65.c
@@ -0,0 +1,74 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+
+void FP_FASTAPASS(1) IREMIRQHook(int a)
+{
+ if(IRQa)
+ {
+ IRQCount-=a;
+ if(IRQCount<-4)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ IRQa=0;
+ IRQCount=0xFFFF;
+ }
+ }
+}
+
+static DECLFW(Mapper65_write)
+{
+ //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)
+{
+ MapIRQHook=IREMIRQHook;
+ SetWriteHandler(0x8000,0xffff,Mapper65_write);
+}
diff --git a/mappers/67.c b/mappers/67.c
new file mode 100644
index 00000000..9d560f91
--- /dev/null
+++ b/mappers/67.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"
+
+
+#define suntoggle mapbyte1[0]
+
+static DECLFW(Mapper67_write)
+{
+ A&=0xF800;
+ if((A&0x800) && A<=0xb800)
+ {
+ VROM_BANK2((A-0x8800)>>1,V);
+ }
+ else switch(A)
+ {
+ case 0xc800:
+ case 0xc000:if(!suntoggle)
+ {
+ IRQCount&=0xFF;
+ IRQCount|=V<<8;
+ }
+ else
+ {
+ IRQCount&=0xFF00;
+ IRQCount|=V;
+ }
+ suntoggle^=1;
+ break;
+ case 0xd800:suntoggle=0;IRQa=V&0x10;X6502_IRQEnd(FCEU_IQEXT);break;
+
+ case 0xe800:switch(V&3)
+ {
+ case 0:MIRROR_SET2(1);break;
+ case 1:MIRROR_SET2(0);break;
+ case 2:onemir(0);break;
+ case 3:onemir(1);break;
+ }
+ break;
+ case 0xf800:ROM_BANK16(0x8000,V);break;
+ }
+}
+static void FP_FASTAPASS(1) SunIRQHook(int a)
+{
+ if(IRQa)
+ {
+ IRQCount-=a;
+ if(IRQCount<=0)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ IRQa=0;
+ IRQCount=0xFFFF;
+ }
+ }
+}
+void Mapper67_init(void)
+{
+SetWriteHandler(0x8000,0xffff,Mapper67_write);
+MapIRQHook=SunIRQHook;
+}
diff --git a/mappers/68.c b/mappers/68.c
new file mode 100644
index 00000000..69eaefc5
--- /dev/null
+++ b/mappers/68.c
@@ -0,0 +1,105 @@
+/* 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 void Fixerit(void)
+{
+ switch(mapbyte2[0]&3)
+ {
+ 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;
+ }
+}
+
+DECLFW(Mapper68_write)
+{
+// FCEU_printf("%04x,%04x\n",A,V);
+ A&=0xF000;
+
+ if(A>=0x8000 && A<=0xB000)
+ {
+ VROM_BANK2((A-0x8000)>>1,V);
+ }
+ else switch(A)
+ {
+ case 0xc000:mapbyte1[0]=V;
+ if(VROM_size && mapbyte2[0]&0x10)
+ Fixerit();
+ break;
+
+ case 0xd000:mapbyte1[1]=V;
+ if(VROM_size && mapbyte2[0]&0x10)
+ Fixerit();
+ break;
+
+ case 0xe000: mapbyte2[0]=V;
+ if(!(V&0x10))
+ {
+ switch(V&3)
+ {
+ case 0:MIRROR_SET2(1);break;
+ case 1:MIRROR_SET2(0);break;
+ case 2:onemir(0);break;
+ case 3:onemir(1);break;
+ }
+ }
+ else if(VROM_size)
+ {
+ Fixerit();
+ PPUNTARAM=0;
+ }
+ break;
+ case 0xf000: ROM_BANK16(0x8000,V);break;
+ }
+}
+
+static void Mapper68_StateRestore(int version)
+{
+ if(!(mapbyte2[0]&0x10))
+ {
+ switch(mapbyte2[0]&3)
+ {
+ case 0:MIRROR_SET(0);break;
+ case 1:MIRROR_SET(1);break;
+ case 2:onemir(0);break;
+ case 3:onemir(1);break;
+ }
+ }
+ else if(VROM_size)
+ {
+ Fixerit();
+ PPUNTARAM=0;
+ }
+}
+
+void Mapper68_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper68_write);
+ MapStateRestore=Mapper68_StateRestore;
+}
diff --git a/mappers/69.c b/mappers/69.c
new file mode 100644
index 00000000..057a5129
--- /dev/null
+++ b/mappers/69.c
@@ -0,0 +1,252 @@
+/* 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 void AYSound(int Count);
+static void AYSoundHQ(void);
+static void DoAYSQ(int x);
+static void DoAYSQHQ(int x);
+
+#define sunselect mapbyte1[0]
+#define sungah mapbyte1[1]
+static uint8 sunindex;
+
+static DECLFW(SUN5BWRAM)
+{
+ if((sungah&0xC0)==0xC0)
+ (WRAM-0x6000)[A]=V;
+}
+
+static DECLFR(SUN5AWRAM)
+{
+ if((sungah&0xC0)==0x40)
+ return X.DB;
+ return CartBR(A);
+}
+
+static DECLFW(Mapper69_SWL)
+{
+ sunindex=V%14;
+}
+
+static DECLFW(Mapper69_SWH)
+{
+ int x;
+ GameExpSound.Fill=AYSound;
+ GameExpSound.HiFill=AYSoundHQ;
+ if(FSettings.SndRate);
+ switch(sunindex)
+ {
+ case 0:
+ case 1:
+ case 8:if(FSettings.soundq>=1) DoAYSQHQ(0); else DoAYSQ(0);break;
+ case 2:
+ case 3:
+ case 9:if(FSettings.soundq>=1) DoAYSQHQ(1); else DoAYSQ(1);break;
+ case 4:
+ case 5:
+ 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;
+}
+
+static DECLFW(Mapper69_write)
+{
+ switch(A&0xE000)
+ {
+ case 0x8000:sunselect=V;break;
+ case 0xa000:
+ sunselect&=0xF;
+ if(sunselect<=7)
+ VROM_BANK1(sunselect<<10,V);
+ else
+ switch(sunselect&0x0f)
+ {
+ case 8:
+ sungah=V;
+ if(V&0x40)
+ {
+ if(V&0x80) // Select WRAM
+ setprg8r(0x10,0x6000,0);
+ }
+ else
+ setprg8(0x6000,V);
+ 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)
+ {
+ case 0:MIRROR_SET2(1);break;
+ case 1:MIRROR_SET2(0);break;
+ case 2:onemir(0);break;
+ case 3:onemir(1);break;
+ }
+ 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[3];
+static int32 dcount[3];
+static int CAYBC[3];
+
+static void DoAYSQ(int x)
+{
+ 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(amp)
+ for(V=start;V<end;V++)
+ {
+ if(dcount[x])
+ Wave[V>>4]+=amp;
+ vcount[x]-=nesincsize;
+ while(vcount[x]<=0)
+ {
+ dcount[x]^=1;
+ vcount[x]+=freq;
+ }
+ }
+}
+
+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<<x)))
+ {
+ for(V=CAYBC[x];V<SOUNDTS;V++)
+ {
+ if(dcount[x])
+ WaveHi[V]+=amp;
+ vcount[x]--;
+ if(vcount[x]<=0)
+ {
+ dcount[x]^=1;
+ vcount[x]=freq;
+ }
+ }
+ }
+ CAYBC[x]=SOUNDTS;
+}
+
+static void AYSound(int Count)
+{
+ int x;
+ DoAYSQ(0);
+ DoAYSQ(1);
+ DoAYSQ(2);
+ for(x=0;x<3;x++)
+ CAYBC[x]=Count;
+}
+
+static void AYSoundHQ(void)
+{
+ DoAYSQHQ(0);
+ DoAYSQHQ(1);
+ DoAYSQHQ(2);
+}
+
+static void AYHiSync(int32 ts)
+{
+ int x;
+
+ for(x=0;x<3;x++)
+ CAYBC[x]=ts;
+}
+
+static void FP_FASTAPASS(1) SunIRQHook(int a)
+{
+ if(IRQa)
+ {
+ IRQCount-=a;
+ if(IRQCount<=0)
+ {X6502_IRQBegin(FCEU_IQEXT);IRQa=0;IRQCount=0xFFFF;}
+ }
+}
+
+void Mapper69_StateRestore(int version)
+{
+ if(mapbyte1[1]&0x40)
+ {
+ if(mapbyte1[1]&0x80) // Select WRAM
+ setprg8r(0x10,0x6000,0);
+ }
+ else
+ setprg8(0x6000,mapbyte1[1]);
+}
+
+void Mapper69_ESI(void)
+{
+ GameExpSound.RChange=Mapper69_ESI;
+ GameExpSound.HiSync=AYHiSync;
+ memset(dcount,0,sizeof(dcount));
+ memset(vcount,0,sizeof(vcount));
+ memset(CAYBC,0,sizeof(CAYBC));
+}
+
+void NSFAY_Init(void)
+{
+ 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;
+}
+
diff --git a/mappers/71.c b/mappers/71.c
new file mode 100644
index 00000000..9b1a99da
--- /dev/null
+++ b/mappers/71.c
@@ -0,0 +1,41 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+
+
+DECLFW(Mapper71_write)
+{
+switch(A&0xF000)
+ {
+ case 0xF000:
+ case 0xE000:
+ case 0xD000:
+ case 0xC000:ROM_BANK16(0x8000,V);break;
+ case 0x9000:onemir((V>>3)&2);break;
+ }
+}
+
+void Mapper71_init(void)
+{
+SetWriteHandler(0x4020,0xffff,Mapper71_write);
+}
+
diff --git a/mappers/72.c b/mappers/72.c
new file mode 100644
index 00000000..480a035a
--- /dev/null
+++ b/mappers/72.c
@@ -0,0 +1,37 @@
+/* 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"
+
+
+DECLFW(Mapper72_write)
+{
+ mapbyte1[0]=V;
+ if(V&0x80)
+ ROM_BANK16(0x8000,V&0xF);
+ if(V&0x40)
+ VROM_BANK8(V&0xF);
+}
+
+void Mapper72_init(void)
+{
+ SetWriteHandler(0x6000,0xffff,Mapper72_write);
+}
+
diff --git a/mappers/73.c b/mappers/73.c
new file mode 100644
index 00000000..b49fa249
--- /dev/null
+++ b/mappers/73.c
@@ -0,0 +1,60 @@
+/* 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(Mapper73_write)
+{
+ //if(A>=0xd000 && A<=0xdfff)
+ X6502_IRQEnd(FCEU_IQEXT); /* How are IRQs acknowledged on this chip? */
+ switch(A&0xF000)
+ {
+ //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;
+ }
+}
+
+static void FP_FASTAPASS(1) Mapper73IRQHook(int a)
+{
+ if(IRQa)
+ {
+ IRQCount+=a;
+ if(IRQCount>=0xFFFF)
+ {
+ IRQCount&=0xFFFF;
+ IRQa=0;
+ X6502_IRQBegin(FCEU_IQEXT);
+ }
+ }
+}
+
+void Mapper73_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper73_write);
+ MapIRQHook=Mapper73IRQHook;
+}
+
diff --git a/mappers/75.c b/mappers/75.c
new file mode 100644
index 00000000..f2b00bd6
--- /dev/null
+++ b/mappers/75.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"
+
+
+#define map75sel mapbyte1[0]
+#define map75ar mapbyte2
+
+DECLFW(Mapper75_write)
+{
+switch(A&0xF000)
+ {
+ 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);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;
+ }
+}
+
+void Mapper75_init(void)
+{
+SetWriteHandler(0x8000,0xffff,Mapper75_write);
+}
+
diff --git a/mappers/76.c b/mappers/76.c
new file mode 100644
index 00000000..a59ef1e2
--- /dev/null
+++ b/mappers/76.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 uint8 MMC3_cmd;
+
+static DECLFW(Mapper76_write)
+{
+ switch(A&0xE001){
+ case 0x8000:
+ MMC3_cmd = V;
+ break;
+ case 0x8001:
+ switch(MMC3_cmd&0x07){
+ case 2: VROM_BANK2(0x000,V);break;
+ case 3: VROM_BANK2(0x800,V);break;
+ case 4: VROM_BANK2(0x1000,V);break;
+ case 5: VROM_BANK2(0x1800,V);break;
+ case 6:
+ if(MMC3_cmd&0x40) ROM_BANK8(0xC000,V);
+ else ROM_BANK8(0x8000,V);
+ break;
+ case 7: ROM_BANK8(0xA000,V);
+ break;
+ }
+ break;
+ case 0xA000:
+ MIRROR_SET(V&1);
+ break;
+ }
+}
+
+void Mapper76_init(void)
+{
+SetWriteHandler(0x8000,0xffff,Mapper76_write);
+}
+
diff --git a/mappers/77.c b/mappers/77.c
new file mode 100644
index 00000000..06f15cc0
--- /dev/null
+++ b/mappers/77.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"
+
+/* Original code provided by LULU */
+
+static DECLFW(Mapper77_write)
+{
+ mapbyte1[0]=V;
+ ROM_BANK32(V&0x7);
+ VROM_BANK2(0x0000, (V&0xf0)>>4);
+}
+
+static void Mapper77_StateRestore(int version)
+{
+ int x;
+
+ if(version>=7200)
+ {
+ ROM_BANK32(mapbyte1[0]&0x7);
+ VROM_BANK2(0x0000, (mapbyte1[0]&0xf0)>>4);
+ }
+ for(x=2;x<8;x++)
+ VRAM_BANK1(x*0x400,x);
+}
+
+void Mapper77_init(void)
+{
+ int x;
+
+ ROM_BANK32(0);
+ for(x=2;x<8;x++)
+ VRAM_BANK1(x*0x400,x);
+ SetWriteHandler(0x6000,0xffff,Mapper77_write);
+ MapStateRestore=Mapper77_StateRestore;
+}
diff --git a/mappers/79.c b/mappers/79.c
new file mode 100644
index 00000000..9148eae6
--- /dev/null
+++ b/mappers/79.c
@@ -0,0 +1,40 @@
+/* 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"
+
+
+
+DECLFW(Mapper79_write)
+{
+ if(A<0x8000 && ((A^0x4100)==0))
+ {
+ ROM_BANK32((V>>3)&1);
+ }
+ VROM_BANK8(V);
+}
+
+void Mapper79_init(void)
+{
+ ROM_BANK32(~0);
+ SetWriteHandler(0x8000,0xffff,Mapper79_write);
+ SetWriteHandler(0x4020,0x5fff,Mapper79_write);
+}
+
diff --git a/mappers/8.c b/mappers/8.c
new file mode 100644
index 00000000..53c91a28
--- /dev/null
+++ b/mappers/8.c
@@ -0,0 +1,34 @@
+/* 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(Mapper8_write)
+{
+ ROM_BANK16(0x8000,V>>3);
+ VROM_BANK8(V&7);
+}
+
+void Mapper8_init(void)
+{
+ ROM_BANK32(0);
+ SetWriteHandler(0x8000,0xFFFF,Mapper8_write);
+}
+
diff --git a/mappers/80.c b/mappers/80.c
new file mode 100644
index 00000000..1e7982e8
--- /dev/null
+++ b/mappers/80.c
@@ -0,0 +1,100 @@
+/* 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 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;
+
+ 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)
+ {
+ 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: 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);break;
+ case 0x7efd:
+ case 0x7efc: ROM_BANK8(0xA000,V);break;
+ case 0x7efe:
+ case 0x7eff: ROM_BANK8(0xC000,V);break;
+ }
+}
+
+static void booga(int version)
+{
+ mira();
+}
+
+void Mapper80_init(void)
+{
+ 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
new file mode 100644
index 00000000..b4288b1f
--- /dev/null
+++ b/mappers/82.c
@@ -0,0 +1,62 @@
+/* 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"
+
+#define ctrl mapbyte1[6]
+
+static void DoCHR(void)
+{
+ int x;
+
+ for(x=0;x<2;x++)
+ VROM_BANK2((x<<11)|((ctrl&2)<<11),mapbyte1[x]>>1);
+ for(x=0;x<4;x++)
+ VROM_BANK1((x<<10) | (((ctrl&2)^2)<<11),mapbyte1[2+x]);
+}
+
+static DECLFW(Mapper82_write)
+{
+ if(A<=0x7EF5)
+ {
+ mapbyte1[A&7]=V;
+ DoCHR();
+ }
+ else
+ switch(A)
+ {
+ case 0x7ef6:ctrl=V&3;
+ 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;
+ }
+}
+
+void Mapper82_init(void)
+{
+ ROM_BANK8(0xE000,~0);
+
+ /* external WRAM might end at $73FF */
+ SetWriteHandler(0x7ef0,0x7efc,Mapper82_write);
+}
+
diff --git a/mappers/83.c b/mappers/83.c
new file mode 100644
index 00000000..9a3bcd7b
--- /dev/null
+++ b/mappers/83.c
@@ -0,0 +1,131 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "mapinc.h"
+
+
+/*void Mapper83_init(void)
+{
+
+}
+*/
+static void FP_FASTAPASS(1) m83IRQHook(int a)
+{
+ if(IRQa)
+ {
+ IRQCount-=a;
+ if(IRQCount<0)
+ {
+ X6502_IRQBegin(FCEU_IQEXT);
+ IRQa=0;
+ IRQCount=0xFFFF;
+ }
+ }
+}
+
+static DECLFW(wrlow)
+{
+ mapbyte4[A&3]=V;
+}
+
+static DECLFR(rdlow)
+{
+ return mapbyte4[A&3];
+}
+
+static void m83prg(void)
+{
+ ROM_BANK16(0x8000,(mapbyte1[0]&0x3F));
+ ROM_BANK16(0xC000,(mapbyte1[0]&0x30)|0xF);
+}
+
+static void m83chr(void)
+{
+// if(0)
+// {
+// VROM_BANK2(0x0000,mapbyte2[0]);
+// VROM_BANK2(0x0800,mapbyte2[1]);
+// VROM_BANK2(0x1000,mapbyte2[6]);
+// VROM_BANK2(0x1800,mapbyte2[7]);
+// }
+// else
+// {
+ int x;
+ for(x=0;x<8;x++)
+ VROM_BANK1(x*0x400,mapbyte2[x]|((mapbyte1[0]&0x30)<<4));
+// }
+}
+
+static DECLFW(Mapper83_write)
+{
+ //printf("$%04x:$%02x\n",A,V);
+ switch(A)
+ {
+ case 0x8000:
+ case 0xB000:
+ case 0xB0FF:
+ case 0xB1FF:
+ {
+ mapbyte1[0]=V;
+ m83prg();
+ m83chr();
+ }
+ break;
+ case 0x8100:
+ mapbyte3[0]=V&0x80;
+ switch(V&0x3)
+ {
+ case 0x00:MIRROR_SET2(1);break;
+ case 0x01:MIRROR_SET2(0);break;
+ case 0x02:onemir(0);break;
+ case 0x03:onemir(1);break;
+ }
+ break;
+ case 0x8200:IRQCount&=0xFF00;IRQCount|=V;X6502_IRQEnd(FCEU_IQEXT);break;
+ case 0x8201:IRQa=mapbyte3[0];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 0x8310:mapbyte2[0]=V;m83chr();break;
+ case 0x8311:mapbyte2[1]=V;m83chr();break;
+ case 0x8312:mapbyte2[2]=V;m83chr();break;
+ case 0x8313:mapbyte2[3]=V;m83chr();break;
+ case 0x8314:mapbyte2[4]=V;m83chr();break;
+ 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);
+
+ MapIRQHook=m83IRQHook;
+
+ 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
new file mode 100644
index 00000000..3283182d
--- /dev/null
+++ b/mappers/85.c
@@ -0,0 +1,195 @@
+/* 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"
+
+#define vrctemp mapbyte1[0]
+static uint8 indox;
+
+#include "emu2413.h"
+
+static int acount=0;
+
+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)
+{
+ int salpo[4]={MI_V,MI_H,MI_0,MI_1};
+ setmirror(salpo[V&3]);
+}
+
+DECLFW(Mapper85_write)
+{
+ 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);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;
+ 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*3;
+
+ if(acount>=ACBOO)
+ {
+ doagainbub:acount-=ACBOO;
+ IRQCount++;
+ if(IRQCount&0x100) {X6502_IRQBegin(FCEU_IQEXT);IRQCount=IRQLatch;}
+ if(acount>=ACBOO) goto doagainbub;
+ }
+ }
+}
+
+void Mapper85_StateRestore(int version)
+{
+ int x;
+
+ if(version<7200)
+ {
+ for(x=0;x<8;x++)
+ mapbyte3[x]=CHRBankList[x];
+ for(x=0;x<3;x++)
+ mapbyte2[x]=PRGBankList[x];
+ mapbyte2[3]=(Mirroring<0x10)?Mirroring:Mirroring-0xE;
+ }
+
+ for(x=0;x<8;x++)
+ setchr1(x*0x400,mapbyte3[x]);
+ for(x=0;x<3;x++)
+ setprg8(0x8000+x*8192,mapbyte2[x]);
+ DaMirror(mapbyte2[3]);
+ //LoadOPL();
+}
+
+static void M85SC(void)
+{
+ if(VRC7Sound)
+ OPLL_set_rate(VRC7Sound, FSettings.SndRate);
+}
+
+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)
+{
+ SetWriteHandler(0x9010,0x901F,Mapper85_write);
+ SetWriteHandler(0x9030,0x903F,Mapper85_write);
+ VRC7SI();
+}
+
+void Mapper85_init(void)
+{
+ MapIRQHook=KonamiIRQHook;
+ SetWriteHandler(0x8000,0xffff,Mapper85_write);
+ GameStateRestore=Mapper85_StateRestore;
+ if(!VROM_size)
+ SetupCartCHRMapping(0, CHRRAM, 8192, 1);
+ //AddExState(VRC7Instrument, 16, 0, "VC7I");
+ //AddExState(VRC7Chan, sizeof(VRC7Chan), 0, "V7CH");
+ VRC7SI();
+}
diff --git a/mappers/86.c b/mappers/86.c
new file mode 100644
index 00000000..8404985d
--- /dev/null
+++ b/mappers/86.c
@@ -0,0 +1,38 @@
+/* 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"
+
+DECLFW(Mapper86_write)
+{
+ 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,0x6fff,Mapper86_write);
+ SetWriteHandler(0x4020,0xffff,Mapper86_write);
+}
diff --git a/mappers/89.c b/mappers/89.c
new file mode 100644
index 00000000..a3a6f09f
--- /dev/null
+++ b/mappers/89.c
@@ -0,0 +1,34 @@
+/* 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"
+
+DECLFW(Mapper89_write)
+{
+ VROM_BANK8((V&7)|((V>>4)&8));
+ ROM_BANK16(0x8000,(V>>4)&7);
+ onemir((V>>3)&1);
+}
+
+void Mapper89_init(void)
+{
+ Mirroring=0;
+ SetWriteHandler(0x8000,0xffff,Mapper89_write);
+}
diff --git a/mappers/91.c b/mappers/91.c
new file mode 100644
index 00000000..8858103a
--- /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
new file mode 100644
index 00000000..e2ad3749
--- /dev/null
+++ b/mappers/92.c
@@ -0,0 +1,45 @@
+/* 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"
+
+/* Original code provided by LULU */
+
+static DECLFW(Mapper92_write)
+{
+ uint8 reg=(A&0xF0)>>4;
+ uint8 bank=A&0xF;
+
+ if(A>=0x9000)
+ {
+ if(reg==0xD) ROM_BANK16(0xc000,bank);
+ else if(reg==0xE) VROM_BANK8(bank);
+ }
+ else
+ {
+ if(reg==0xB) ROM_BANK16(0xc000,bank);
+ else if(reg==0x7) VROM_BANK8(bank);
+ }
+}
+
+void Mapper92_init(void)
+{
+ SetWriteHandler(0x8000,0xFFFF,Mapper92_write);
+}
diff --git a/mappers/97.c b/mappers/97.c
new file mode 100644
index 00000000..2990c0e7
--- /dev/null
+++ b/mappers/97.c
@@ -0,0 +1,42 @@
+/* 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"
+
+
+
+DECLFW(Mapper97_write)
+{
+ROM_BANK16(0xC000,V&15);
+switch(V>>6)
+ {
+ case 0:break;
+ case 1:MIRROR_SET2(0);break;
+ case 2:MIRROR_SET2(1);break;
+ case 3:break;
+ }
+}
+
+void Mapper97_init(void)
+{
+ ROM_BANK16(0x8000,~0);
+ SetWriteHandler(0x8000,0xffff,Mapper97_write);
+}
+
diff --git a/mappers/99.c b/mappers/99.c
new file mode 100644
index 00000000..7a55536b
--- /dev/null
+++ b/mappers/99.c
@@ -0,0 +1,37 @@
+/* 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 writefunc oldmorko;
+
+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.am.inc b/mappers/Makefile.am.inc
new file mode 100644
index 00000000..631d532d
--- /dev/null
+++ b/mappers/Makefile.am.inc
@@ -0,0 +1 @@
+fceu_SOURCES += mappers/113.c mappers/15.c mappers/151.c mappers/16.c mappers/17.c mappers/18.c mappers/180.c mappers/183.c mappers/184.c mappers/193.c mappers/200.c mappers/201.c mappers/202.c mappers/203.c mappers/204.c mappers/21.c mappers/212.c mappers/213.c mappers/214.c mappers/215.c mappers/217.c mappers/22.c mappers/225.c mappers/226.c mappers/227.c mappers/228.c mappers/229.c mappers/23.c mappers/230.c mappers/231.c mappers/232.c mappers/234.c mappers/240.c mappers/241.c mappers/242.c mappers/244.c mappers/246.c mappers/24and26.c mappers/25.c mappers/255.c mappers/27.c mappers/32.c mappers/33.c mappers/40.c mappers/41.c mappers/42.c mappers/43.c mappers/46.c mappers/50.c mappers/51.c mappers/59.c mappers/6.c mappers/60.c mappers/61.c mappers/62.c mappers/65.c mappers/67.c mappers/68.c mappers/69.c mappers/71.c mappers/72.c mappers/73.c mappers/75.c mappers/76.c mappers/77.c mappers/79.c mappers/8.c mappers/80.c mappers/82.c mappers/83.c mappers/85.c mappers/86.c mappers/89.c mappers/91.c mappers/92.c mappers/97.c mappers/99.c mappers/emu2413.c mappers/mmc2and4.c mappers/simple.c
diff --git a/mappers/emu2413.c b/mappers/emu2413.c
new file mode 100644
index 00000000..49aa3396
--- /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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#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<<PG_BITS)
+
+/* Phase increment counter */
+#define DP_BITS 18
+#define DP_WIDTH (1<<DP_BITS)
+#define DP_BASE_BITS (DP_BITS - PG_BITS)
+
+/* Dynamic range (Accuracy of sin table) */
+#define DB_BITS 8
+#define DB_STEP (48.0/(1<<DB_BITS))
+#define DB_MUTE (1<<DB_BITS)
+
+/* Dynamic range of envelope */
+#define EG_STEP 0.375
+#define EG_BITS 7
+#define EG_MUTE (1<<EG_BITS)
+
+/* Dynamic range of total level */
+#define TL_STEP 0.75
+#define TL_BITS 6
+#define TL_MUTE (1<<TL_BITS)
+
+/* Dynamic range of sustine level */
+#define SL_STEP 3.0
+#define SL_BITS 4
+#define SL_MUTE (1<<SL_BITS)
+
+#define EG2DB(d) ((d)*(e_int32)(EG_STEP/DB_STEP))
+#define TL2EG(d) ((d)*(e_int32)(TL_STEP/EG_STEP))
+#define SL2EG(d) ((d)*(e_int32)(SL_STEP/EG_STEP))
+
+#define DB_POS(x) (e_uint32)((x)/DB_STEP)
+#define DB_NEG(x) (e_uint32)(DB_MUTE+DB_MUTE+(x)/DB_STEP)
+
+/* Bits for liner value */
+#define DB2LIN_AMP_BITS 11
+#define SLOT_AMP_BITS (DB2LIN_AMP_BITS)
+
+/* Bits for envelope phase incremental counter */
+#define EG_DP_BITS 22
+#define EG_DP_WIDTH (1<<EG_DP_BITS)
+
+/* Bits for Pitch and Amp modulator */
+#define PM_PG_BITS 8
+#define PM_PG_WIDTH (1<<PM_PG_BITS)
+#define PM_DP_BITS 16
+#define PM_DP_WIDTH (1<<PM_DP_BITS)
+#define AM_PG_BITS 8
+#define AM_PG_WIDTH (1<<AM_PG_BITS)
+#define AM_DP_BITS 16
+#define AM_DP_WIDTH (1<<AM_DP_BITS)
+
+/* PM table is calcurated by PM_AMP * pow(2,PM_DEPTH*sin(x)/1200) */
+#define PM_AMP_BITS 8
+#define PM_AMP (1<<PM_AMP_BITS)
+
+/* PM speed(Hz) and depth(cent) */
+#define PM_SPEED 6.4
+#define PM_DEPTH 13.75
+
+/* AM speed(Hz) and depth(dB) */
+#define AM_SPEED 3.7
+//#define AM_DEPTH 4.8
+#define AM_DEPTH 2.4
+
+/* Cut the lower b bit(s) off. */
+#define HIGHBITS(c,b) ((c)>>(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_BITS)-1) to Liner(0 -- DB2LIN_AMP_WIDTH) */
+static void
+makeDB2LinTable (void)
+{
+ e_int32 i;
+
+ for (i = 0; i < DB_MUTE + DB_MUTE; i++)
+ {
+ DB2LIN_TABLE[i] = (e_int16) ((double) ((1 << DB2LIN_AMP_BITS) - 1) * pow (10, -(double) i * DB_STEP / 20));
+ if(i >= 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<<DB_BITS) - 1 -- 0) */
+static e_int32
+lin2db (double d)
+{
+ if(d == 0)
+ return (DB_MUTE - 1);
+ else
+ return Min (-(e_int32) (20.0 * log10 (d) / DB_STEP), DB_MUTE-1); /* 0 -- 127 */
+}
+
+
+/* Sin Table */
+static void
+makeSinTable (void)
+{
+ e_int32 i;
+
+ for (i = 0; i < PG_WIDTH / 4; i++)
+ {
+ fullsintable[i] = (e_uint32) lin2db (sin (2.0 * PI * i / PG_WIDTH) );
+ }
+
+ for (i = 0; i < PG_WIDTH / 4; i++)
+ {
+ fullsintable[PG_WIDTH / 2 - 1 - i] = fullsintable[i];
+ }
+
+ for (i = 0; i < PG_WIDTH / 2; i++)
+ {
+ fullsintable[PG_WIDTH / 2 + i] = (e_uint32) (DB_MUTE + DB_MUTE + fullsintable[i]);
+ }
+
+ for (i = 0; i < PG_WIDTH / 2; i++)
+ halfsintable[i] = fullsintable[i];
+ for (i = PG_WIDTH / 2; i < PG_WIDTH; i++)
+ halfsintable[i] = fullsintable[0];
+}
+
+/* Table for Pitch Modulator */
+static void
+makePmTable (void)
+{
+ e_int32 i;
+
+ for (i = 0; i < PM_PG_WIDTH; i++)
+ pmtable[i] = (e_int32) ((double) PM_AMP * pow (2, (double) PM_DEPTH * sin (2.0 * PI * i / PM_PG_WIDTH) / 1200));
+}
+
+/* Table for Amp Modulator */
+static void
+makeAmTable (void)
+{
+ e_int32 i;
+
+ for (i = 0; i < AM_PG_WIDTH; i++)
+ amtable[i] = (e_int32) ((double) AM_DEPTH / 2 / DB_STEP * (1.0 + sin (2.0 * PI * i / PM_PG_WIDTH)));
+}
+
+/* Phase increment counter table */
+static void
+makeDphaseTable (void)
+{
+ e_uint32 fnum, block, ML;
+ e_uint32 mltable[16] =
+ { 1, 1 * 2, 2 * 2, 3 * 2, 4 * 2, 5 * 2, 6 * 2, 7 * 2, 8 * 2, 9 * 2, 10 * 2, 10 * 2, 12 * 2, 12 * 2, 15 * 2, 15 * 2 };
+
+ for (fnum = 0; fnum < 512; fnum++)
+ for (block = 0; block < 8; block++)
+ for (ML = 0; ML < 16; ML++)
+ dphaseTable[fnum][block][ML] = rate_adjust (((fnum * mltable[ML]) << block) >> (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)<<shift;
+ buf++;
+ len--;
+ }
+}
+
+#ifdef EMU2413_COMPACTION
+e_int16
+OPLL_calc (OPLL * opll)
+{
+ return calc (opll);
+}
+#else
+e_int16
+OPLL_calc (OPLL * opll)
+{
+ if(!opll->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 00000000..906b4c5a
--- /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 00000000..fdef420f
--- /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/mapinc.h b/mappers/mapinc.h
new file mode 100644
index 00000000..694a7c9c
--- /dev/null
+++ b/mappers/mapinc.h
@@ -0,0 +1,11 @@
+#include "../types.h"
+#include "../x6502.h"
+#include "../fceu.h"
+#include "../ppu.h"
+#define INESPRIV
+#include "../cart.h"
+#include "../ines.h"
+#include "../memory.h"
+#include "../sound.h"
+#include "../state.h"
+#include <string.h>
diff --git a/mappers/mmc2and4.c b/mappers/mmc2and4.c
new file mode 100644
index 00000000..022d7369
--- /dev/null
+++ b/mappers/mmc2and4.c
@@ -0,0 +1,121 @@
+/* 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"
+
+#define MMC4reg mapbyte1
+#define latcha1 mapbyte2[0]
+#define latcha2 mapbyte2[1]
+
+
+static void FP_FASTAPASS(1) latchcheck(uint32 VAddr)
+{
+ uint8 l,h;
+
+ h=VAddr>>8;
+
+ if(h>=0x20 || ((h&0xF)!=0xF))
+ return;
+
+ l=VAddr&0xF0;
+
+ if(h<0x10)
+ {
+ if(l==0xD0)
+ {
+ VROM_BANK4(0x0000,MMC4reg[0]);
+ latcha1=0xFD;
+ }
+ else if(l==0xE0)
+ {
+ VROM_BANK4(0x0000,MMC4reg[1]);
+ latcha1=0xFE;
+ }
+ }
+ else
+ {
+ if(l==0xD0)
+ {
+ VROM_BANK4(0x1000,MMC4reg[2]);
+ latcha2=0xFD;
+ }
+ else if(l==0xE0)
+ {
+ VROM_BANK4(0x1000,MMC4reg[3]);
+ latcha2=0xFE;
+ }
+ }
+}
+
+DECLFW(Mapper9_write) // $Axxx
+{
+ ROM_BANK8(0x8000,V);
+}
+
+DECLFW(Mapper10_write)
+{
+ ROM_BANK16(0x8000,V);
+}
+
+DECLFW(Mapper9and10_write)
+{
+ switch(A&0xF000)
+ {
+ case 0xB000:
+ if(latcha1==0xFD) { VROM_BANK4(0x0000,V);}
+ MMC4reg[0]=V;
+ break;
+ case 0xC000:
+ if(latcha1==0xFE) {VROM_BANK4(0x0000,V);}
+ MMC4reg[1]=V;
+ break;
+ case 0xD000:
+ if(latcha2==0xFD) {VROM_BANK4(0x1000,V);}
+ MMC4reg[2]=V;
+ break;
+ case 0xE000:
+ if(latcha2==0xFE) {VROM_BANK4(0x1000,V);}
+ MMC4reg[3]=V;
+ break;
+ case 0xF000:
+ MIRROR_SET(V&1);
+ break;
+ }
+}
+
+void Mapper9_init(void)
+{
+ latcha1=0xFE;
+ latcha2=0xFE;
+ ROM_BANK8(0xA000,~2);
+ ROM_BANK8(0x8000,0);
+ SetWriteHandler(0xA000,0xAFFF,Mapper9_write);
+ SetWriteHandler(0xB000,0xFFFF,Mapper9and10_write);
+ PPU_hook=latchcheck;
+}
+
+void Mapper10_init(void)
+{
+ latcha1=latcha2=0xFE;
+ SetWriteHandler(0xA000,0xAFFF,Mapper10_write);
+ SetWriteHandler(0xB000,0xFFFF,Mapper9and10_write);
+ PPU_hook=latchcheck;
+}
+
diff --git a/mappers/simple.c b/mappers/simple.c
new file mode 100644
index 00000000..c393d095
--- /dev/null
+++ b/mappers/simple.c
@@ -0,0 +1,100 @@
+/* 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 uint8 latche;
+
+static DECLFW(Mapper34_write)
+{
+ switch(A)
+ {
+ 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);
+}
+
+void Mapper34_init(void)
+{
+ ROM_BANK32(0);
+ SetWriteHandler(0x7ffd,0xffff,Mapper34_write);
+}
+
+/* I might want to add some code to the mapper 96 PPU hook function
+ to not change CHR banks if the attribute table is being accessed,
+ if I make emulation a little more accurate in the future.
+*/
+
+static uint8 M96LA;
+static DECLFW(Mapper96_write)
+{
+ latche=V;
+ setprg32(0x8000,V&3);
+ setchr4r(0x10,0x0000,(latche&4)|M96LA);
+ setchr4r(0x10,0x1000,(latche&4)|3);
+}
+
+static void FP_FASTAPASS(1) M96Hook(uint32 A)
+{
+ if((A&0x3000)!=0x2000) return;
+ //if((A&0x3ff)>=0x3c0) return;
+ M96LA=(A>>8)&3;
+ setchr4r(0x10,0x0000,(latche&4)|M96LA);
+}
+
+static void M96Sync(int v)
+{
+ setprg32(0x8000,latche&3);
+ setchr4r(0x10,0x0000,(latche&4)|M96LA);
+ setchr4r(0x10,0x1000,(latche&4)|3);
+}
+
+void Mapper96_init(void)
+{
+ SetWriteHandler(0x8000,0xffff,Mapper96_write);
+ PPU_hook=M96Hook;
+ AddExState(&latche, 1, 0, "LATC");
+ AddExState(&M96LA, 1, 0, "LAVA");
+ SetupCartCHRMapping(0x10, MapperExRAM, 32768, 1);
+ latche=M96LA=0;
+ M96Sync(0);
+ setmirror(MI_0);
+ GameStateRestore=M96Sync;
+}
+
+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);
+}
diff --git a/mappers/vrc7tone.h b/mappers/vrc7tone.h
new file mode 100644
index 00000000..d1363073
--- /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 00000000..174d3ee2
--- /dev/null
+++ b/md5.c
@@ -0,0 +1,246 @@
+/*
+ * RFC 1321 compliant MD5 implementation,
+ * by Christophe Devine <devine@cr0.net>;
+ * 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 <string.h>
+#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 00000000..39c01ec7
--- /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.c b/memory.c
new file mode 100644
index 00000000..a0a33e2d
--- /dev/null
+++ b/memory.c
@@ -0,0 +1,100 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdlib.h>
+
+#include "types.h"
+#include "fceu.h"
+#include "memory.h"
+#include "general.h"
+
+void *FCEU_gmalloc(uint32 size)
+{
+ void *ret;
+ ret=malloc(size);
+ if(!ret)
+ {
+ FCEU_PrintError("Error allocating memory! Doing a hard exit.");
+ exit(1);
+ }
+ return ret;
+}
+
+void *FCEU_malloc(uint32 size)
+{
+ void *ret;
+ ret=malloc(size);
+ if(!ret)
+ {
+ FCEU_PrintError("Error allocating memory!");
+ return(0);
+ }
+ return ret;
+}
+
+void FCEU_free(void *ptr) // Might do something with this and FCEU_malloc later...
+{
+ free(ptr);
+}
+
+void FCEU_gfree(void *ptr)
+{
+ free(ptr);
+}
+
+void FASTAPASS(3) FCEU_memmove(void *d, void *s, uint32 l)
+{
+ uint32 x;
+ int t;
+
+ /* Type really doesn't matter. */
+ t=(int)d;
+ t|=(int)s;
+ t|=(int)l;
+
+ if(t&3) // Not 4-byte aligned and/or length is not a multiple of 4.
+ {
+ uint8 *tmpd, *tmps;
+
+ tmpd = d;
+ tmps = s;
+
+ for(x=l;x;x--) // This could be optimized further, though(more tests could be performed).
+ {
+ *tmpd=*tmps;
+ tmpd++;
+ tmps++;
+ }
+ }
+ else
+ {
+ uint32 *tmpd, *tmps;
+
+ tmpd = d;
+ tmps = s;
+
+ for(x=l>>2;x;x--)
+ {
+ *tmpd=*tmps;
+ tmpd++;
+ tmps++;
+ }
+ }
+}
diff --git a/memory.h b/memory.h
new file mode 100644
index 00000000..1c96f012
--- /dev/null
+++ b/memory.h
@@ -0,0 +1,31 @@
+/* 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
+ */
+
+/* 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_gmalloc(uint32 size);
+void FCEU_gfree(void *ptr);
+void FCEU_free(void *ptr);
+void FASTAPASS(3) FCEU_memmove(void *d, void *s, uint32 l);
diff --git a/movie.c b/movie.c
new file mode 100644
index 00000000..1844beb7
--- /dev/null
+++ b/movie.c
@@ -0,0 +1,1447 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef WIN32
+#include <windows.h>
+#endif
+
+#include "types.h"
+#include "endian.h"
+#include "palette.h"
+#include "input.h"
+#include "fceu.h"
+#include "driver.h"
+#include "state.h"
+#include "general.h"
+#include "video.h"
+#include "movie.h"
+
+#define MOVIE_MAGIC 0x1a4d4346 // FCM\x1a
+#define MOVIE_VERSION 2 // still at 2 since the format itself is still compatible - to detect which version the movie was made with, check the fceu version stored in the movie header (e.g against FCEU_VERSION_NUMERIC)
+
+#define MOVIE_FLAG_NOSYNCHACK (1<<4) // set in newer version, used for old movie compatibility
+
+// backwards compat
+static void FCEUI_LoadMovie_v1(char *fname, int _read_only);
+static int FCEUI_MovieGetInfo_v1(const char* fname, MOVIE_INFO* info);
+
+extern char FileBase[];
+
+/*
+struct MovieHeader
+{
+ uint32 magic; // +0
+ uint32 version=2; // +4
+ uint8 flags[4]; // +8
+ uint32 length_frames; // +12
+ uint32 rerecord_count; // +16
+ uint32 movie_data_size; // +20
+ uint32 offset_to_savestate; // +24, should be 4-byte-aligned
+ uint32 offset_to_movie_data; // +28, should be 4-byte-aligned
+ uint8 md5_of_rom_used[16]; // +32
+ uint32 version_of_emu_used // +48
+ char name_of_rom_used[] // +52, utf-8, null-terminated
+ char metadata[]; // utf-8, null-terminated
+ uint8 padding[];
+ uint8 savestate[]; // always present, even in a "from reset" recording
+ uint8 padding[]; // used for byte-alignment
+ uint8 movie_data[];
+}
+*/
+
+static int current = 0; // > 0 for recording, < 0 for playback
+static FILE *slots[10]={0};
+static uint8 joop[4];
+static uint32 framets = 0;
+static uint32 frameptr = 0;
+static uint8* moviedata = NULL;
+static uint32 moviedatasize = 0;
+static uint32 firstframeoffset = 0;
+static uint32 savestate_offset = 0;
+static uint32 framecount = 0;
+static uint32 rerecord_count = 0;
+/*static*/ int movie_readonly = 1;
+static uint32 stopframe = 0;
+int frame_display = 0;
+static uint32 last_frame_display = ~0;
+int input_display = 0;
+uint32 cur_input_display = 0;
+static uint32 last_input_display = ~0;
+
+int resetDMCacc=0;
+
+/* Cache variables used for playback. */
+static uint32 nextts = 0;
+static int32 nextd = 0;
+
+SFORMAT FCEUMOV_STATEINFO[]={
+ { joop, 4,"JOOP"},
+ { &framets, 4|FCEUSTATE_RLSB, "FTS "},
+ { &nextts, 4|FCEUSTATE_RLSB, "NXTS"},
+ { &nextd, 4|FCEUSTATE_RLSB, "NXTD"},
+ { &frameptr, 4|FCEUSTATE_RLSB, "FPTR"},
+ { &framecount, 4|FCEUSTATE_RLSB, "FCNT"},
+
+ { 0 }
+};
+
+static int CurrentMovie = 1;
+static int MovieShow = 0;
+
+static int MovieStatus[10];
+
+static void DoEncode(int joy, int button, int);
+
+int FCEUMOV_GetFrame(void)
+{
+ return framecount;
+}
+
+int FCEUMOV_IsPlaying(void)
+{
+ if(current < 0) return(1);
+ else return(0);
+}
+
+int FCEUMOV_IsRecording(void)
+{
+ if(current > 0) return(1);
+ else return(0);
+}
+
+int FCEUMOV_ShouldPause(void)
+{
+ if(stopframe && framecount == stopframe)
+ {
+ stopframe = 0; //only pause once!
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int suppressMovieStop=0;
+int movieConvertOffset1=0, movieConvertOffset2=0,movieConvertOK=0,movieSyncHackOn=0;
+
+static void StopPlayback(void)
+{
+ if(suppressMovieStop)
+ return;
+ resetDMCacc=movieSyncHackOn=0;
+ fclose(slots[-1 - current]);
+ current=0;
+ FCEU_DispMessage("Movie playback stopped.");
+}
+
+void MovieFlushHeader(void)
+{
+ if(current <= 0)
+ return;// only write header data if recording
+
+ FILE* fp = slots[current - 1];
+ if(fp == 0)
+ return;
+
+ unsigned long loc = ftell(fp);
+ fseek(fp, 4, SEEK_SET);
+ write32le(MOVIE_VERSION, fp);
+ fseek(fp, 12, SEEK_SET);
+ write32le(framecount, fp);
+ write32le(rerecord_count, fp);
+ write32le(frameptr, fp);
+ fseek(fp, 32, SEEK_SET);
+ fwrite(FCEUGameInfo->MD5, 1, 16, fp); // write ROM checksum
+ write32le(FCEU_VERSION_NUMERIC, fp); // write emu version used
+
+ // write ROM name used
+ fseek(fp, 52, SEEK_SET);
+ char str[512];
+ fgets(str,512,fp);
+ str[511]='\0';
+ int strdiff=strlen(FileBase)-strlen(str);
+ if(strdiff)
+ {
+ // resize the whole damn movie because the ROM name in the header is of variable length
+ int off=52;
+ fseek(fp, 52, SEEK_SET);
+ do { off++;
+ } while(fgetc(fp) && !feof(fp) && !ferror(fp));
+
+ if(feof(fp) || ferror(fp))
+ {
+ fseek(fp, loc, SEEK_SET);
+ return;
+ }
+
+ fseek(fp, 0, SEEK_END);
+ uint32 fsize=ftell(fp)-off;
+ char* ctemp=(char*)FCEU_malloc(fsize*sizeof(char)+4);
+ if(!ctemp)
+ {
+ fseek(fp, loc, SEEK_SET);
+ return;
+ }
+ fseek(fp, off, SEEK_SET);
+ fread(ctemp, 1,fsize, fp);
+ fseek(fp, 52+strlen(FileBase)+1, SEEK_SET);
+ int wrote = fwrite(ctemp, fsize,1, fp);
+ FCEU_free(ctemp);
+ if(!wrote)
+ {
+ fseek(fp, loc, SEEK_SET);
+ return;
+ }
+
+ if(loc >= firstframeoffset)
+ loc += strdiff;
+ savestate_offset += strdiff;
+ firstframeoffset += strdiff;
+ fseek(fp, 24, SEEK_SET);
+ write32le(savestate_offset, fp);
+ write32le(firstframeoffset, fp);
+ }
+ fseek(fp, 52, SEEK_SET);
+ fputs(FileBase, fp);
+ fputc('\0', fp);
+
+ fseek(fp, loc, SEEK_SET);
+}
+
+static void StopRecording(void)
+{
+ if(suppressMovieStop)
+ return;
+ resetDMCacc=movieSyncHackOn=0;
+ DoEncode(0,0,1); /* Write a dummy timestamp value so that the movie will keep
+ "playing" after user input has stopped. */
+ // finish header
+ MovieFlushHeader();
+
+ // FIXME: truncate movie to length
+ // ftruncate();
+ fclose(slots[current - 1]);
+ MovieStatus[current - 1] = 1;
+ current=0;
+ FCEU_DispMessage("Movie recording stopped.");
+}
+
+void FCEUI_StopMovie(void)
+{
+ if(current < 0) StopPlayback();
+ if(current > 0) StopRecording();
+}
+
+#ifdef WIN32
+#include "process.h"
+void executeCommand(const char* cmd)
+{
+ if(!cmd || !*cmd)
+ return;
+
+ const char *argv[4];
+ argv[0] = getenv("COMSPEC");
+ argv[1] = "/c";
+ argv[2] = cmd;
+ argv[3] = NULL;
+ if(*argv && *(*argv))
+ _spawnve(_P_WAIT, argv[0], argv, NULL);
+}
+#endif
+
+int justAutoConverted=0;
+static const char* convertToFCM(const char *fname, char *buffer)
+{
+#ifdef WIN32
+ justAutoConverted=0;
+
+ // convert to fcm if not already
+ const char* dot = strrchr(fname, '.');
+ if(dot)
+ {
+ int fmv = !stricmp(dot, ".fmv");
+ int nmv = !stricmp(dot, ".nmv");
+ int vmv = !stricmp(dot, ".vmv");
+ if(fmv || nmv || vmv)
+ {
+ strcpy(buffer, fname);
+ buffer[dot-fname]='\0';
+ strcat(buffer,"-autoconverted.fcm");
+
+ int fceuver=0;
+ if(fmv)
+ fceuver=1;
+ else if(nmv)
+ fceuver=2;
+ else if(vmv)
+ fceuver=3;
+
+ extern char lastLoadedGameName [2048];
+ char cmd [1024], offset[64], romInfo[1024];
+ if(movieConvertOK)
+ sprintf(romInfo, "-smd5=\"%s\" -sromname=\"%s (MAYBE)\" -s", lastLoadedGameName, FileBase);
+ else
+ sprintf(romInfo, "-sromname=\"(unknown)\" -s");
+ if(movieConvertOffset2) sprintf(offset, "-o %d:%d", movieConvertOffset2,movieConvertOffset1);
+ else sprintf(offset, "-o %d", movieConvertOffset1);
+ sprintf(cmd, ".\\util\\nesmock\\nesmock.exe %s %s -spal=%c -sfceuver=%d \"%s\" \"%s\" ", offset, romInfo, FCEUI_GetCurrentVidSystem(0,0)?'1':'0', fceuver, fname, buffer);
+// FCEU_PrintError(cmd);
+ executeCommand(cmd);
+
+ FILE* file = FCEUD_UTF8fopen(buffer,"rb");
+ if(file)
+ {
+ fseek(file, 12, SEEK_SET);
+ int frames=0;
+ read32le(&frames, file);
+ if(frames)
+ {
+ fname = buffer;
+ justAutoConverted=1;
+ }
+ else
+ {
+ static int errAlready=0;
+ if(!errAlready)
+ {
+ errAlready=1;
+ FCEU_PrintError("For some reason, nesmock was unable to create a valid FCM from the given file.\nThe command given was:\n%s\nPerhaps the file specified is not a movie file or contains no input data,\nor perhaps it is a movie file of a version unsupported by nesmock.\n\n(This error message will self-destruct until you restart FCEU.)", cmd);
+ }
+ }
+ fclose(file);
+ }
+ else
+ {
+ char str [512];
+ str[0] = '\0';
+ GetCurrentDirectory(512,str);
+ strcat(str, "\\util\\nesmock\\nesmock.exe");
+ file = FCEUD_UTF8fopen(str, "rb");
+ if(file)
+ {
+ static int errAlready=0;
+ if(!errAlready)
+ {
+ errAlready=1;
+ FCEU_PrintError("For some reason, nesmock was unable to convert the movie to FCM format.\nThe command given was:\n%s\n\n(This error message will self-destruct until you restart FCEU.)", cmd);
+ fclose(file);
+ }
+ }
+ else
+ {
+ static int errAlready=0;
+ if(!errAlready)
+ {
+ errAlready=1;
+ FCEU_PrintError("Nesmock not found, so the movie could not be converted to FCM format.\nYou must place nesmock.exe at this location so FCEU can find it:\n%s\n\n(This error message will self-destruct until you restart FCEU.)", str);
+ }
+ }
+ }
+ }
+ }
+#endif
+ return fname;
+}
+
+static void ResetInputTypes()
+{
+#ifdef WIN32
+ extern int UsrInputType[3];
+ UsrInputType[0] = SI_GAMEPAD;
+ UsrInputType[1] = SI_GAMEPAD;
+ UsrInputType[2] = SIFC_NONE;
+
+ ParseGIInput(NULL/*FCEUGameInfo*/);
+ extern int cspec, gametype;
+ cspec=FCEUGameInfo->cspecial;
+ gametype=FCEUGameInfo->type;
+
+ InitOtherInput();
+#endif
+}
+
+char curMovieFilename[512];
+
+
+// PlayMovie / MoviePlay function
+void FCEUI_LoadMovie(char *fname, int _read_only, int _stopframe)
+{
+ char buffer [512];
+ fname = (char*)convertToFCM(fname,buffer);
+
+ FILE *fp;
+ char *fn = NULL;
+
+ FCEUI_StopMovie();
+
+ if(!fname)
+ fname = fn = FCEU_MakeFName(FCEUMKF_MOVIE,CurrentMovie,0);
+
+char origname[512];
+strcpy(origname,fname);
+
+ stopframe = _stopframe;
+
+ // check movie_readonly
+ movie_readonly = _read_only;
+ if(access(fname, W_OK))
+ movie_readonly = 2;
+
+ fp = FCEUD_UTF8fopen(fname, (movie_readonly>=2) ? "rb" : "r+b");
+
+ if(fn)
+ {
+ free(fn);
+ fname = NULL;
+ }
+
+ if(!fp) return;
+
+ // read header
+
+ uint32 magic;
+ uint32 version;
+ uint8 flags[4];
+
+ read32le(&magic, fp);
+ if(magic != MOVIE_MAGIC)
+ {
+ fclose(fp);
+ return;
+ }
+//DEBUG_COMPARE_RAM(__LINE__);
+
+ read32le(&version, fp);
+ if(version == 1)
+ {
+ // attempt to load previous version's format
+ fclose(fp);
+ FCEUI_LoadMovie_v1(fname, _read_only);
+ return;
+ }
+ else if(version == MOVIE_VERSION)
+ {}
+ else
+ {
+ // unsupported version
+ fclose(fp);
+ return;
+ }
+
+ fread(flags, 1, 4, fp);
+ read32le(&framecount, fp);
+ read32le(&rerecord_count, fp);
+ read32le(&moviedatasize, fp);
+ read32le(&savestate_offset, fp);
+ read32le(&firstframeoffset, fp);
+ if(fseek(fp, savestate_offset, SEEK_SET))
+ {
+ fclose(fp);
+ return;
+ }
+
+// FCEU_PrintError("flags[0] & MOVIE_FLAG_NOSYNCHACK=%d",flags[0] & MOVIE_FLAG_NOSYNCHACK);
+ if(flags[0] & MOVIE_FLAG_NOSYNCHACK)
+ movieSyncHackOn=0;
+ else
+ movieSyncHackOn=1;
+
+ if(flags[0] & MOVIE_FLAG_PAL)
+ {
+ FCEUI_SetVidSystem(1);
+ }
+ else
+ {
+ FCEUI_SetVidSystem(0);
+ }
+
+
+ // fully reload the game to reinitialize everything before playing any movie
+ // to try fixing nondeterministic playback of some games
+ {
+ extern char lastLoadedGameName [2048];
+ extern int disableBatteryLoading, suppressAddPowerCommand;
+ suppressAddPowerCommand=1;
+ suppressMovieStop=1;
+ {
+ FCEUGI * gi = FCEUI_LoadGame(lastLoadedGameName, 0);
+ if(!gi)
+ PowerNES();
+ }
+ suppressMovieStop=0;
+ suppressAddPowerCommand=0;
+ }
+
+ if(!FCEUSS_LoadFP(fp,1)) return;
+ if(flags[0] & MOVIE_FLAG_PAL)
+ {
+ FCEUI_SetVidSystem(1);
+ }
+ else
+ {
+ FCEUI_SetVidSystem(0);
+ }
+ ResetInputTypes();
+
+ fseek(fp, firstframeoffset, SEEK_SET);
+ moviedata = (uint8*)realloc(moviedata, moviedatasize);
+ fread(moviedata, 1, moviedatasize, fp);
+
+ framecount = 0; // movies start at frame 0!
+ frameptr = 0;
+ current = CurrentMovie;
+ slots[current] = fp;
+
+ memset(joop,0,sizeof(joop));
+ current = -1 - current;
+ framets=0;
+ nextts=0;
+ nextd = -1;
+
+ MovieStatus[CurrentMovie] = 1;
+ if(!fname)
+ FCEUI_SelectMovie(CurrentMovie,1); /* Quick hack to display status. */
+ else
+ FCEU_DispMessage("Movie playback started.");
+
+ strcpy(curMovieFilename, origname);
+}
+
+void FCEUI_SaveMovie(char *fname, uint8 flags, const char* metadata)
+{
+ FILE *fp;
+ char *fn;
+ int poweron=0;
+ uint8 padding[4] = {0,0,0,0};
+ int n_padding;
+
+ FCEUI_StopMovie();
+
+ char origname[512];
+ if(fname)
+ {
+ fp = FCEUD_UTF8fopen(fname, "wb");
+ strcpy(origname,fname);
+ }
+ else
+ {
+ fp=FCEUD_UTF8fopen(fn=FCEU_MakeFName(FCEUMKF_MOVIE,CurrentMovie,0),"wb");
+ strcpy(origname,fn);
+ free(fn);
+ }
+
+ if(!fp) return;
+
+ // don't need the movieSyncHackOn sync hack for newly recorded movies
+ flags |= MOVIE_FLAG_NOSYNCHACK;
+ resetDMCacc=movieSyncHackOn=0;
+
+ // add PAL flag
+ if(FCEUI_GetCurrentVidSystem(0,0))
+ flags |= MOVIE_FLAG_PAL;
+
+ if(flags & MOVIE_FLAG_FROM_POWERON)
+ {
+ poweron=1;
+ flags &= ~MOVIE_FLAG_FROM_POWERON;
+ flags |= MOVIE_FLAG_FROM_RESET;
+ }
+
+ // write header
+ write32le(MOVIE_MAGIC, fp);
+ write32le(MOVIE_VERSION, fp);
+ fputc(flags, fp);
+ fputc(0, fp); // reserved
+ fputc(0, fp); // reserved
+ fputc(0, fp); // reserved
+ write32le(0, fp); // leave room for length frames
+ write32le(0, fp); // leave room for rerecord count
+ write32le(0, fp); // leave room for movie data size
+ write32le(0, fp); // leave room for savestate_offset
+ write32le(0, fp); // leave room for offset_to_controller_data
+ fwrite(FCEUGameInfo->MD5, 1, 16, fp); // write ROM checksum
+ write32le(FCEU_VERSION_NUMERIC, fp); // write emu version used
+ fputs(FileBase, fp); // write ROM name used
+ fputc(0, fp);
+ if(metadata)
+ {
+ if(strlen(metadata) < MOVIE_MAX_METADATA)
+ fputs(metadata, fp);
+ else
+ fwrite(metadata, 1, MOVIE_MAX_METADATA-1, fp);
+ }
+ fputc(0, fp);
+
+ // add padding
+ n_padding = (4 - (ftell(fp) & 0x3)) & 0x3;
+ fwrite(padding, 1, n_padding, fp);
+
+ if(flags & MOVIE_FLAG_FROM_RESET)
+ {
+ if(poweron)
+ {
+ // make a for-movie-recording power-on clear the game's save data, too
+ // (note: FCEU makes a save state immediately after this and that loads that on movie playback)
+ extern char lastLoadedGameName [2048];
+ extern int disableBatteryLoading, suppressAddPowerCommand;
+ suppressAddPowerCommand=1;
+ disableBatteryLoading=1;
+ suppressMovieStop=1;
+ {
+ // NOTE: this will NOT write an FCEUNPCMD_POWER into the movie file
+ FCEUGI * gi = FCEUI_LoadGame(lastLoadedGameName, 0);
+ if(!gi)
+ PowerNES(); // and neither will this, if it can even happen
+ }
+ suppressMovieStop=0;
+ disableBatteryLoading=0;
+ suppressAddPowerCommand=0;
+ }
+ }
+
+ savestate_offset = ftell(fp);
+ FCEUSS_SaveFP(fp);
+ fseek(fp, 0, SEEK_END);
+
+ ResetInputTypes();
+
+ // add padding
+ n_padding = (4 - (ftell(fp) & 0x3)) & 0x3;
+ fwrite(padding, 1, n_padding, fp);
+
+ firstframeoffset = ftell(fp);
+
+ // finish header
+ fseek(fp, 24, SEEK_SET); // offset_to_savestate offset
+ write32le(savestate_offset, fp);
+ write32le(firstframeoffset, fp);
+
+ fseek(fp, firstframeoffset, SEEK_SET);
+
+ // set recording flag
+ current=CurrentMovie;
+
+ movie_readonly = 0;
+ frameptr = 0;
+ framecount = 0;
+ rerecord_count = 0;
+ slots[current] = fp;
+ memset(joop,0,sizeof(joop));
+ current++;
+ framets=0;
+ nextd = -1;
+
+ // trigger a reset
+ if(flags & MOVIE_FLAG_FROM_RESET)
+ {
+ if(poweron)
+ {
+ PowerNES(); // NOTE: this will write an FCEUNPCMD_POWER into the movie file
+ }
+ else
+ ResetNES(); // NOTE: this will write an FCEUNPCMD_RESET into the movie file
+ }
+ if(!fname)
+ FCEUI_SelectMovie(CurrentMovie,1); /* Quick hack to display status. */
+ else
+ FCEU_DispMessage("Movie recording started.");
+
+ strcpy(curMovieFilename, origname);
+}
+
+static void movie_writechar(int c)
+{
+ if(frameptr == moviedatasize)
+ {
+ moviedatasize += 4096;
+ moviedata = (uint8*)realloc(moviedata, moviedatasize);
+ }
+ moviedata[frameptr++] = (uint8)(c & 0xff);
+ fputc(c, slots[current - 1]);
+}
+
+static int movie_readchar()
+{
+ if(frameptr >= moviedatasize)
+ {
+ return -1;
+ }
+ return (int)(moviedata[frameptr++]);
+}
+
+static void DoEncode(int joy, int button, int dummy)
+{
+ uint8 d;
+
+ d = 0;
+
+ if(framets >= 65536)
+ d = 3 << 5;
+ else if(framets >= 256)
+ d = 2 << 5;
+ else if(framets > 0)
+ d = 1 << 5;
+
+ if(dummy) d|=0x80;
+
+ d |= joy << 3;
+ d |= button;
+
+ movie_writechar(d);
+ //printf("Wr: %02x, %d\n",d,slots[current-1]);
+ while(framets)
+ {
+ movie_writechar(framets & 0xff);
+ //printf("Wrts: %02x\n",framets & 0xff);
+ framets >>= 8;
+ }
+}
+
+// TODO: make this function legible! (what are all these magic numbers and weirdly named variables and crazy unexplained loops?)
+void FCEUMOV_AddJoy(uint8 *js, int SkipFlush)
+{
+ int x,y;
+
+// if(!current) return; // Not playback nor recording.
+
+ if(current < 0) // Playback
+ {
+ while(nextts == framets || nextd == -1)
+ {
+ int tmp,ti;
+ uint8 d;
+
+ if(nextd != -1)
+ {
+ if(nextd&0x80)
+ {
+ //puts("Egads");
+ FCEU_DoSimpleCommand(nextd&0x1F);
+ }
+ else
+ joop[(nextd >> 3)&0x3] ^= 1 << (nextd&0x7);
+ }
+
+
+ tmp = movie_readchar();
+ d = tmp;
+
+ if(tmp < 0)
+ {
+ StopPlayback();
+ memcpy(&cur_input_display,js,4);
+ return;
+ }
+
+ nextts = 0;
+ tmp >>= 5;
+ tmp &= 0x3;
+ ti=0;
+
+ int tmpfix = tmp;
+ while(tmp--) { nextts |= movie_readchar() << (ti * 8); ti++; }
+
+ // This fixes a bug in movies recorded before version 0.98.11
+ // It's probably not necessary, but it may keep away CRAZY PEOPLE who recorded
+ // movies on <= 0.98.10 and don't work on playback.
+ if(tmpfix == 1 && !nextts)
+ {nextts |= movie_readchar()<<8; }
+ else if(tmpfix == 2 && !nextts) {nextts |= movie_readchar()<<16; }
+
+ if(nextd != -1)
+ framets = 0;
+ nextd = d;
+ }
+
+ memcpy(js,joop,4);
+ }
+ else if(current > 0) // Recording
+ {
+ // flush header info every 300 frames in case of crash
+ //Don't if in bot mode--we don't need extra overhead
+ if(!SkipFlush)
+ {
+ static int fcounter=0;
+ fcounter++;
+ if(!(fcounter%300))
+ MovieFlushHeader();
+ }
+
+ for(x=0;x<4;x++)
+ {
+ if(js[x] != joop[x])
+ {
+ for(y=0;y<8;y++)
+ if((js[x] ^ joop[x]) & (1 << y))
+ DoEncode(x, y, 0);
+ joop[x] = js[x];
+ }
+ else if(framets == ((1<<24)-1)) DoEncode(0,0,1); // Overflow will happen, so do dummy update.
+ }
+ }
+
+ if(current)
+ {
+ framets++;
+ framecount++;
+ }
+
+ memcpy(&cur_input_display,js,4);
+
+ //Stop the movie at a specified frame
+ if(current < 0 && FCEUMOV_ShouldPause() && FCEUI_EmulationPaused()==0)
+ {
+ FCEUI_ToggleEmulationPause();
+ }
+
+}
+
+void FCEUMOV_AddCommand(int cmd)
+{
+ if(current <= 0) return; // Return if not recording a movie
+ //printf("%d\n",cmd);
+ DoEncode((cmd>>3)&0x3,cmd&0x7,1);
+}
+
+void FCEUMOV_CheckMovies(void)
+{
+ FILE *st=NULL;
+ char *fn;
+ int ssel;
+
+ for(ssel=0;ssel<10;ssel++)
+ {
+ st=FCEUD_UTF8fopen(fn=FCEU_MakeFName(FCEUMKF_MOVIE,ssel,0),"rb");
+ free(fn);
+ if(st)
+ {
+ MovieStatus[ssel]=1;
+ fclose(st);
+ }
+ else
+ MovieStatus[ssel]=0;
+ }
+
+}
+
+void FCEUI_SelectMovieNext(int n)
+{
+ if(n>0)
+ CurrentMovie=(CurrentMovie+1)%10;
+ else
+ CurrentMovie=(CurrentMovie+9)%10;
+ FCEUI_SelectMovie(CurrentMovie, 1);
+}
+
+
+int FCEUI_SelectMovie(int w, int show)
+{
+ int oldslot=CurrentMovie;
+ if(w == -1) { MovieShow = 0; return; }
+ FCEUI_SelectState(-1,0);
+
+ CurrentMovie=w;
+ MovieShow=180;
+
+ if(show)
+ {
+ MovieShow=180;
+ if(current > 0)
+ FCEU_DispMessage("-recording movie %d-",current-1);
+ else if (current < 0)
+ FCEU_DispMessage("-playing movie %d-",-1 - current);
+ else
+ FCEU_DispMessage("-select movie-");
+ }
+}
+
+int movcounter=0;
+
+void FCEU_DrawMovies(uint8 *XBuf)
+{
+ int frameDisplayOn = current != 0 && frame_display;
+ extern int howlong;
+#if WIN32
+ extern int32 fps_scale;
+#else
+ int32 fps_scale=256;
+#endif
+ int howl=(180-(FCEUI_EmulationPaused()?(60):(20*fps_scale/256)));
+ if(howl>176) howl=180;
+ if(howl<1) howl=1;
+ if((howlong<howl || movcounter)
+ && (frameDisplayOn &&
+ (!movcounter || last_frame_display!=framecount)))
+ //|| input_display && (!movcounter || last_input_display!=cur_input_display)))
+ {
+ //Old input display code
+ /*
+ char inputstr [32];
+ if(input_display)
+ {
+ uint32 c = cur_input_display;
+ sprintf(inputstr, "%c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c",
+ (c&0x40)?'<':' ', (c&0x10)?'^':' ', (c&0x80)?'>':' ', (c&0x20)?'v':' ',
+ (c&0x01)?'A':' ', (c&0x02)?'B':' ', (c&0x08)?'S':' ', (c&0x04)?'s':' ',
+ (c&0x4000)?'<':' ', (c&0x1000)?'^':' ', (c&0x8000)?'>':' ', (c&0x2000)?'v':' ',
+ (c&0x0100)?'A':' ', (c&0x0200)?'B':' ', (c&0x0800)?'S':' ', (c&0x0400)?'s':' ');
+ if(!(c&0xff00))
+ inputstr[8] = '\0';
+ }
+ if(frameDisplayOn && !input_display)
+ FCEU_DispMessage("%s frame %u",current >= 0?"Recording":"Playing",framecount);
+ else if(input_display && !frameDisplayOn)
+ FCEU_DispMessage("Input: %s",inputstr);
+ else //if(input_display && frame_display)
+ FCEU_DispMessage("%s %u %s",current >= 0?"Recording":"Playing",framecount,inputstr);
+ */
+ if(frameDisplayOn)
+ {
+ FCEU_DispMessage("%s frame %u",current >= 0?"Recording":"Playing",framecount);
+ }
+ last_frame_display = framecount;
+ last_input_display = cur_input_display;
+ movcounter=180-1;
+ return;
+ }
+
+ if(movcounter) movcounter--;
+
+ if(!MovieShow) return;
+
+ FCEU_DrawNumberRow(XBuf,MovieStatus, CurrentMovie);
+ MovieShow--;
+}
+
+int FCEUMOV_WriteState(FILE* st)
+{
+ uint32 to_write = 0;
+ if(current < 0)
+ to_write = moviedatasize;
+ else if(current > 0)
+ to_write = frameptr;
+
+ if(!st)
+ return to_write;
+
+ if(to_write)
+ fwrite(moviedata, 1, to_write, st);
+ return to_write;
+}
+
+static int load_successful;
+
+int FCEUMOV_ReadState(FILE* st, uint32 size)
+{
+ // if this savestate was made while replaying,
+ // we need to "undo" nextd and nextts
+ if(nextd != -1)
+ {
+ int d = 1;
+ if(nextts > 65536)
+ d = 4;
+ else if(nextts > 256)
+ d = 3;
+ else if(nextts > 0)
+ d = 2;
+ frameptr -= d;
+ nextd = -1;
+ }
+
+// if(current > 0 || (!movie_readonly && current < 0)) /* Recording or Playback (!read-only) */
+ if(current!=0 && !movie_readonly)
+ {
+ // copy movie data from savestate
+ moviedata = (uint8*)realloc(moviedata, size);
+ moviedatasize = size;
+ if(size && fread(moviedata, 1, size, st)<size)
+ return 0;
+ if(current < 0) // switch to recording
+ current = -current;
+ fseek(slots[current - 1], firstframeoffset, SEEK_SET);
+ fwrite(moviedata, 1, frameptr, slots[current - 1]);
+ if(!FCEU_BotMode())
+ {
+ rerecord_count++;
+ }
+ }
+// else if(current < 0) /* Playback (read-only) */
+ else if(current!=0 && movie_readonly)
+ {
+ if(current > 0) // switch to playback
+ current = -current;
+ // allow frameptr to be updated but keep movie data
+ fseek(st, size, SEEK_CUR);
+ // prevent seeking beyond the end of the movie
+ if(frameptr > moviedatasize)
+ frameptr = moviedatasize;
+ }
+ else /* Neither recording or replaying */
+ {
+ // skip movie data
+ fseek(st, size, SEEK_CUR);
+ }
+
+ load_successful=1;
+ return 1;
+}
+
+void FCEUMOV_PreLoad(void)
+{
+ load_successful=0;
+}
+
+int FCEUMOV_PostLoad(void)
+{
+ if(!FCEUI_IsMovieActive())
+ return 1;
+ else
+ return load_successful;
+}
+
+char* FCEUI_MovieGetCurrentName(int addSlotNumber)
+{
+ return FCEU_MakeFName(FCEUMKF_MOVIE,(addSlotNumber ? CurrentMovie : -1),0);
+}
+
+int FCEUI_IsMovieActive(void)
+{
+ return current;
+}
+
+void FCEUI_MovieToggleFrameDisplay(void)
+{
+ frame_display=!frame_display;
+ if(!(current != 0 && frame_display))// && !input_display)
+ FCEU_ResetMessages();
+ else
+ {
+ last_frame_display = ~framecount;
+ last_input_display = ~cur_input_display;
+ }
+}
+
+void FCEUI_ToggleInputDisplay(void)
+{
+ switch(input_display)
+ {
+ case 0:
+ input_display = 1;
+ break;
+ case 1:
+ input_display = 2;
+ break;
+ case 2:
+ input_display = 4;
+ break;
+ default:
+ input_display = 0;
+ break;
+ }
+
+ //if(!input_display && !(current != 0 && frame_display))
+ //FCEU_ResetMessages();
+ //else
+ if(input_display)
+ {
+ last_frame_display = ~framecount;
+ last_input_display = ~cur_input_display;
+ }
+}
+
+void FCEUI_MovieToggleReadOnly(void)
+{
+ if(movie_readonly < 2)
+ {
+ movie_readonly = !movie_readonly;
+ if(movie_readonly)
+ FCEU_DispMessage("Movie is now Read-Only.");
+ else
+ FCEU_DispMessage("Movie is now Read+Write.");
+ }
+ else
+ {
+ FCEU_DispMessage("Movie file is Read-Only.");
+ }
+}
+
+char lastMovieInfoFilename [512] = {'\0',};
+int FCEUI_MovieGetInfo(const char* fname, MOVIE_INFO* info)
+{
+ MovieFlushHeader();
+
+ char buffer [512];
+ fname = (const char*)convertToFCM(fname,buffer);
+ strncpy(lastMovieInfoFilename, fname, 512);
+
+// main get info part of function
+{
+ uint32 magic;
+ uint32 version;
+ uint8 _flags[4];
+
+ FILE* fp = FCEUD_UTF8fopen(fname, "rb");
+ if(!fp)
+ return 0;
+
+ read32le(&magic, fp);
+ if(magic != MOVIE_MAGIC)
+ {
+ fclose(fp);
+ return 0;
+ }
+
+ read32le(&version, fp);
+ if(version != MOVIE_VERSION)
+ {
+ fclose(fp);
+ if(version == 1)
+ return FCEUI_MovieGetInfo_v1(fname, info);
+ else
+ return 0;
+ }
+
+ info->movie_version = MOVIE_VERSION;
+
+ fread(_flags, 1, 4, fp);
+
+ info->flags = _flags[0];
+ read32le(&info->num_frames, fp);
+ read32le(&info->rerecord_count, fp);
+
+ if(access(fname, W_OK))
+ info->read_only = 1;
+ else
+ info->read_only = 0;
+
+ fseek(fp, 12, SEEK_CUR); // skip movie_data_size, offset_to_savestate, and offset_to_movie_data
+
+ fread(info->md5_of_rom_used, 1, 16, fp);
+ info->md5_of_rom_used_present = 1;
+
+ read32le(&info->emu_version_used, fp);
+
+ // I probably could have planned this better...
+ {
+ char str[256];
+ size_t r;
+ int p;
+ int p2=0;
+ char last_c=32;
+
+ if(info->name_of_rom_used && info->name_of_rom_used_size)
+ info->name_of_rom_used[0]='\0';
+
+ r=fread(str, 1, 256, fp);
+ while(r > 0)
+ {
+ for(p=0; p<r && last_c != '\0'; ++p)
+ {
+ if(info->name_of_rom_used && info->name_of_rom_used_size && (p2 < info->name_of_rom_used_size-1))
+ {
+ info->name_of_rom_used[p2]=str[p];
+ p2++;
+ last_c=str[p];
+ }
+ }
+ if(p<r)
+ {
+ memmove(str, str+p, r-p);
+ r -= p;
+ break;
+ }
+ r=fread(str, 1, 256, fp);
+ }
+
+ p2=0;
+ last_c=32;
+
+ if(info->metadata && info->metadata_size)
+ info->metadata[0]='\0';
+
+ while(r > 0)
+ {
+ for(p=0; p<r && last_c != '\0'; ++p)
+ {
+ if(info->metadata && info->metadata_size && (p2 < info->metadata_size-1))
+ {
+ info->metadata[p2]=str[p];
+ p2++;
+ last_c=str[p];
+ }
+ }
+ if(p != r)
+ break;
+ r=fread(str, 1, 256, fp);
+ }
+
+ if(r<=0)
+ {
+ // somehow failed to read romname and metadata
+ fclose(fp);
+ return 0;
+ }
+ }
+
+ // check what hacks are necessary
+ fseek(fp, 24, SEEK_SET); // offset_to_savestate offset
+ uint32 temp_savestate_offset;
+ read32le(&temp_savestate_offset, fp);
+ if(fseek(fp, temp_savestate_offset, SEEK_SET))
+ {
+ fclose(fp);
+ return 0;
+ }
+ if(!FCEUSS_LoadFP(fp,2)) return 0; // 2 -> don't really load, just load to find what's there then load backup
+
+ fclose(fp);
+ return 1;
+}
+}
+/*
+ Backwards compat
+*/
+
+
+/*
+struct MovieHeader_v1
+{
+ uint32 magic;
+ uint32 version=1;
+ uint8 flags[4];
+ uint32 length_frames;
+ uint32 rerecord_count;
+ uint32 movie_data_size;
+ uint32 offset_to_savestate;
+ uint32 offset_to_movie_data;
+ uint16 metadata_ucs2[]; // ucs-2, ick! sizeof(metadata) = offset_to_savestate - MOVIE_HEADER_SIZE
+}
+*/
+
+#define MOVIE_V1_HEADER_SIZE 32
+
+static void FCEUI_LoadMovie_v1(char *fname, int _read_only)
+{
+ FILE *fp;
+ char *fn = NULL;
+
+ FCEUI_StopMovie();
+
+ if(!fname)
+ fname = fn = FCEU_MakeFName(FCEUMKF_MOVIE,CurrentMovie,0);
+
+ // check movie_readonly
+ movie_readonly = _read_only;
+ if(access(fname, W_OK))
+ movie_readonly = 2;
+
+ fp = FCEUD_UTF8fopen(fname, (movie_readonly>=2) ? "rb" : "r+b");
+
+ if(fn)
+ {
+ free(fn);
+ fname = NULL;
+ }
+
+ if(!fp) return;
+
+ // read header
+ {
+ uint32 magic;
+ uint32 version;
+ uint8 flags[4];
+ uint32 fc;
+
+ read32le(&magic, fp);
+ if(magic != MOVIE_MAGIC)
+ {
+ fclose(fp);
+ return;
+ }
+
+ read32le(&version, fp);
+ if(version != 1)
+ {
+ fclose(fp);
+ return;
+ }
+
+ fread(flags, 1, 4, fp);
+ read32le(&fc, fp);
+ read32le(&rerecord_count, fp);
+ read32le(&moviedatasize, fp);
+ read32le(&savestate_offset, fp);
+ read32le(&firstframeoffset, fp);
+ if(fseek(fp, savestate_offset, SEEK_SET))
+ {
+ fclose(fp);
+ return;
+ }
+
+ if(flags[0] & MOVIE_FLAG_NOSYNCHACK)
+ movieSyncHackOn=0;
+ else
+ movieSyncHackOn=1;
+ }
+
+ // fully reload the game to reinitialize everything before playing any movie
+ // to try fixing nondeterministic playback of some games
+ {
+ extern char lastLoadedGameName [2048];
+ extern int disableBatteryLoading, suppressAddPowerCommand;
+ suppressAddPowerCommand=1;
+ suppressMovieStop=1;
+ {
+ FCEUGI * gi = FCEUI_LoadGame(lastLoadedGameName, 0);
+ if(!gi)
+ PowerNES();
+ }
+ suppressMovieStop=0;
+ suppressAddPowerCommand=0;
+ }
+
+ if(!FCEUSS_LoadFP(fp,1)) return;
+
+ ResetInputTypes();
+
+ fseek(fp, firstframeoffset, SEEK_SET);
+ moviedata = (uint8*)realloc(moviedata, moviedatasize);
+ fread(moviedata, 1, moviedatasize, fp);
+
+ framecount = 0; // movies start at frame 0!
+ frameptr = 0;
+ current = CurrentMovie;
+ slots[current] = fp;
+
+ memset(joop,0,sizeof(joop));
+ current = -1 - current;
+ framets=0;
+ nextts=0;
+ nextd = -1;
+ MovieStatus[CurrentMovie] = 1;
+ if(!fname)
+ FCEUI_SelectMovie(CurrentMovie,1); /* Quick hack to display status. */
+ else
+ FCEU_DispMessage("Movie playback started.");
+}
+
+static int FCEUI_MovieGetInfo_v1(const char* fname, MOVIE_INFO* info)
+{
+ uint32 magic;
+ uint32 version;
+ uint8 _flags[4];
+ uint32 savestateoffset;
+ uint8 tmp[MOVIE_MAX_METADATA<<1];
+ int metadata_length;
+
+ FILE* fp = FCEUD_UTF8fopen(fname, "rb");
+ if(!fp)
+ return 0;
+
+ read32le(&magic, fp);
+ if(magic != MOVIE_MAGIC)
+ {
+ fclose(fp);
+ return 0;
+ }
+
+ read32le(&version, fp);
+ if(version != 1)
+ {
+ fclose(fp);
+ return 0;
+ }
+
+ info->movie_version = 1;
+ info->emu_version_used = 0; // unknown
+
+ fread(_flags, 1, 4, fp);
+
+ info->flags = _flags[0];
+ read32le(&info->num_frames, fp);
+ read32le(&info->rerecord_count, fp);
+
+ if(access(fname, W_OK))
+ info->read_only = 1;
+ else
+ info->read_only = 0;
+
+ fseek(fp, 4, SEEK_CUR);
+ read32le(&savestateoffset, fp);
+
+ metadata_length = (int)savestateoffset - MOVIE_V1_HEADER_SIZE;
+ if(metadata_length > 0)
+ {
+ int i;
+
+ metadata_length >>= 1;
+ if(metadata_length >= MOVIE_MAX_METADATA)
+ metadata_length = MOVIE_MAX_METADATA-1;
+
+ fseek(fp, MOVIE_V1_HEADER_SIZE, SEEK_SET);
+ fread(tmp, 1, metadata_length<<1, fp);
+ }
+
+ // turn old ucs2 metadata into utf8
+ if(info->metadata && info->metadata_size)
+ {
+ char* ptr=info->metadata;
+ char* ptr_end=info->metadata+info->metadata_size-1;
+ int c_ptr=0;
+ while(ptr<ptr_end && c_ptr<metadata_length)
+ {
+ uint16 c=(tmp[c_ptr<<1] | (tmp[(c_ptr<<1)+1] << 8));
+ switch(c)
+ {
+ case 0 ... 0x7f:
+ *ptr++ = (char)(c&0x7f);
+ break;
+ case 0x80 ... 0x7ff:
+ if(ptr+1>=ptr_end)
+ ptr_end=ptr;
+ else
+ {
+ *ptr++=(0xc0 | (c>>6));
+ *ptr++=(0x80 | (c & 0x3f));
+ }
+ break;
+ case 0x800 ... 0xffff:
+ if(ptr+2>=ptr_end)
+ ptr_end=ptr;
+ else
+ {
+ *ptr++=(0xe0 | (c>>12));
+ *ptr++=(0x80 | ((c>>6) & 0x3f));
+ *ptr++=(0x80 | (c & 0x3f));
+ }
+ break;
+ }
+ c_ptr++;
+ }
+ *ptr='\0';
+ }
+
+ // md5 info not available from v1
+ info->md5_of_rom_used_present = 0;
+ // rom name used for the movie not available from v1
+ if(info->name_of_rom_used && info->name_of_rom_used_size)
+ info->name_of_rom_used[0] = '\0';
+
+ // check what hacks are necessary
+ fseek(fp, 24, SEEK_SET); // offset_to_savestate offset
+ uint32 temp_savestate_offset;
+ read32le(&temp_savestate_offset, fp);
+ if(fseek(fp, temp_savestate_offset, SEEK_SET))
+ {
+ fclose(fp);
+ return 0;
+ }
+ if(!FCEUSS_LoadFP(fp,2)) return 0; // 2 -> don't really load, just load to find what's there then load backup
+
+
+ fclose(fp);
+ return 1;
+}
+
diff --git a/movie.h b/movie.h
new file mode 100644
index 00000000..c48f05ae
--- /dev/null
+++ b/movie.h
@@ -0,0 +1,19 @@
+#ifndef __MOVIE_H_
+#define __MOVIE_H_
+
+void FCEUMOV_AddJoy(uint8 *, int SkipFlush);
+void FCEUMOV_CheckMovies(void);
+void FCEUMOV_AddCommand(int cmd);
+void FCEU_DrawMovies(uint8 *);
+int FCEUMOV_IsPlaying(void);
+int FCEUMOV_IsRecording(void);
+int FCEUMOV_ShouldPause(void);
+int FCEUMOV_GetFrame(void);
+
+int FCEUMOV_WriteState(FILE* st);
+int FCEUMOV_ReadState(FILE* st, uint32 size);
+void FCEUMOV_PreLoad(void);
+int FCEUMOV_PostLoad(void);
+void MovieFlushHeader(void);
+
+#endif /* __MOVIE_H_ */
diff --git a/netplay.c b/netplay.c
new file mode 100644
index 00000000..6b3e7d9a
--- /dev/null
+++ b/netplay.c
@@ -0,0 +1,331 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <zlib.h>
+
+#include "types.h"
+#include "netplay.h"
+#include "fceu.h"
+#include "general.h"
+#include "state.h"
+#include "cheat.h"
+#include "input.h"
+#include "endian.h"
+
+int FCEUnetplay=0;
+
+static uint8 netjoy[4]; /* Controller cache. */
+static int numlocal;
+static int netdivisor;
+static int netdcount;
+
+/* NetError should only be called after a FCEUD_*Data function returned 0, in the function
+ that called FCEUD_*Data, to prevent it from being called twice.
+*/
+
+static void NetError(void)
+{
+ FCEU_DispMessage("Network error/connection lost!");
+ FCEUD_NetworkClose();
+}
+
+void FCEUI_NetplayStop(void)
+{
+ if(FCEUnetplay)
+ {
+ FCEUnetplay = 0;
+ FCEU_FlushGameCheats(0,1); /* Don't save netplay cheats. */
+ FCEU_LoadGameCheats(0); /* Reload our original cheats. */
+ }
+ else puts("Check your code!");
+}
+
+int FCEUI_NetplayStart(int nlocal, int divisor)
+{
+ FCEU_FlushGameCheats(0, 0); /* Save our pre-netplay cheats. */
+ FCEU_LoadGameCheats(0); /* Load them again, for pre-multiplayer
+ action.
+ */
+ FCEUnetplay = 1;
+ memset(netjoy,0,sizeof(netjoy));
+ numlocal = nlocal;
+ netdivisor = divisor;
+ netdcount = 0;
+ return(1);
+}
+
+int FCEUNET_SendCommand(uint8 cmd, uint32 len)
+{
+ uint8 buf[numlocal + 1 + 4];
+
+ buf[0] = 0xFF;
+ FCEU_en32lsb(&buf[numlocal], len);
+ buf[numlocal + 4] = cmd;
+ #ifdef NETWORK
+ if(!FCEUD_SendData(buf,numlocal + 1 + 4))
+ {
+ NetError();
+ return(0);
+ }
+ #endif
+ return(1);
+}
+
+void FCEUI_NetplayText(uint8 *text)
+{
+ uint32 len;
+
+ len = strlen(text);
+
+ if(!FCEUNET_SendCommand(FCEUNPCMD_TEXT,len)) return;
+
+ if(!FCEUD_SendData(text,len))
+ NetError();
+}
+
+int FCEUNET_SendFile(uint8 cmd, char *fn)
+{
+ uint32 len;
+ uLongf clen;
+ char *buf, *cbuf;
+ FILE *fp;
+ struct stat sb;
+
+ if(!(fp=FCEUD_UTF8fopen(fn,"rb"))) return(0);
+
+ fstat(fileno(fp),&sb);
+ len = sb.st_size;
+ buf = malloc(len);
+ fread(buf, 1, len, fp);
+ fclose(fp);
+
+ cbuf = malloc(4 + len + len / 1000 + 12);
+ FCEU_en32lsb(cbuf, len);
+ compress2(cbuf + 4, &clen, buf, len, 7);
+ free(buf);
+
+ //printf("Sending file: %s, %d, %d\n",fn,len,clen);
+
+ len = clen + 4;
+
+ #ifdef NETWORK
+ if(!FCEUNET_SendCommand(cmd,len))
+ {
+ free(cbuf);
+ return(0);
+ }
+ if(!FCEUD_SendData(cbuf, len))
+ {
+ NetError();
+ free(cbuf);
+ return(0);
+ }
+ #endif
+ free(cbuf);
+
+ return(1);
+}
+
+static FILE *FetchFile(uint32 remlen)
+{
+ uint32 clen = remlen;
+ char *cbuf;
+ uLongf len;
+ char *buf;
+ FILE *fp;
+ char *fn;
+
+ if(clen > 500000) // Sanity check
+ {
+ NetError();
+ return(0);
+ }
+
+ //printf("Receiving file: %d...\n",clen);
+ fn = FCEU_MakeFName(FCEUMKF_NPTEMP,0,0);
+ if((fp = fopen(fn,"w+b")))
+ {
+ cbuf = malloc(clen);
+ if(!FCEUD_RecvData(cbuf, clen))
+ {
+ NetError();
+ unlink(fn);
+ fclose(fp);
+ free(cbuf);
+ free(fn);
+ return(0);
+ }
+
+ len = FCEU_de32lsb(cbuf);
+ if(len > 500000) // Another sanity check
+ {
+ NetError();
+ unlink(fn);
+ fclose(fp);
+ free(cbuf);
+ free(fn);
+ return(0);
+ }
+ buf = malloc(len);
+ uncompress(buf, &len, cbuf + 4, clen - 4);
+
+ fwrite(buf, 1, len, fp);
+ free(buf);
+ fseek(fp, 0, SEEK_SET);
+ unlink(fn);
+ free(fn);
+ return(fp);
+ }
+ free(fn);
+ return(0);
+}
+
+void NetplayUpdate(uint8 *joyp)
+{
+ static uint8 buf[5]; /* 4 play states, + command/extra byte */
+ static uint8 joypb[4];
+
+ memcpy(joypb,joyp,4);
+
+ /* This shouldn't happen, but just in case. 0xFF is used as a command escape elsewhere. */
+ if(joypb[0] == 0xFF)
+ joypb[0] = 0xF;
+ #ifdef NETWORK
+ if(!netdcount)
+ if(!FCEUD_SendData(joypb,numlocal))
+ {
+ NetError();
+ return;
+ }
+
+ if(!netdcount)
+ do
+ {
+ if(!FCEUD_RecvData(buf,5))
+ {
+ NetError();
+ return;
+ }
+
+ switch(buf[4])
+ {
+ default: FCEU_DoSimpleCommand(buf[4]);break;
+ case FCEUNPCMD_TEXT:
+ {
+ uint8 *tbuf;
+ uint32 len = FCEU_de32lsb(buf);
+
+ if(len > 100000) // Insanity check!
+ {
+ NetError();
+ return;
+ }
+ tbuf = malloc(len + 1);
+ tbuf[len] = 0;
+ if(!FCEUD_RecvData(tbuf, len))
+ {
+ NetError();
+ free(tbuf);
+ return;
+ }
+ FCEUD_NetplayText(tbuf);
+ free(tbuf);
+ }
+ break;
+ case FCEUNPCMD_SAVESTATE:
+ {
+ char *fn;
+ FILE *fp;
+
+ /* Send the cheats first, then the save state, since
+ there might be a frame or two in between the two sendfile
+ commands on the server side.
+ */
+ fn = FCEU_MakeFName(FCEUMKF_CHEAT,0,0);
+ //if(!
+ FCEUNET_SendFile(FCEUNPCMD_LOADCHEATS,fn);
+
+ // {
+ // free(fn);
+ // return;
+ // }
+ free(fn);
+ if(!FCEUnetplay) return;
+
+ fn = FCEU_MakeFName(FCEUMKF_NPTEMP,0,0);
+ fp = fopen(fn, "wb");
+ if(FCEUSS_SaveFP(fp))
+ {
+ fclose(fp);
+ if(!FCEUNET_SendFile(FCEUNPCMD_LOADSTATE, fn))
+ {
+ unlink(fn);
+ free(fn);
+ return;
+ }
+ unlink(fn);
+ free(fn);
+ }
+ else
+ {
+ fclose(fp);
+ FCEUD_PrintError("File error. (K)ill, (M)aim, (D)estroy? Now!");
+ unlink(fn);
+ free(fn);
+ return;
+ }
+
+ }
+ break;
+ case FCEUNPCMD_LOADCHEATS:
+ {
+ FILE *fp = FetchFile(FCEU_de32lsb(buf));
+ if(!fp) return;
+ FCEU_FlushGameCheats(0,1);
+ FCEU_LoadGameCheats(fp);
+ }
+ break;
+ case FCEUNPCMD_LOADSTATE:
+ {
+ FILE *fp = FetchFile(FCEU_de32lsb(buf));
+ if(!fp) return;
+ if(FCEUSS_LoadFP(fp,1))
+ {
+ fclose(fp);
+ FCEU_DispMessage("Remote state loaded.");
+ } else FCEUD_PrintError("File error. (K)ill, (M)aim, (D)estroy?");
+ }
+ break;
+ }
+ } while(buf[4]);
+ #endif
+
+ netdcount=(netdcount+1)%netdivisor;
+
+ memcpy(netjoy,buf,4);
+ *(uint32 *)joyp=*(uint32 *)netjoy;
+}
diff --git a/netplay.h b/netplay.h
new file mode 100644
index 00000000..83852551
--- /dev/null
+++ b/netplay.h
@@ -0,0 +1,23 @@
+int InitNetplay(void);
+void NetplayUpdate(uint8 *joyp);
+extern int FCEUnetplay;
+
+
+#define FCEUNPCMD_RESET 0x01
+#define FCEUNPCMD_POWER 0x02
+
+#define FCEUNPCMD_VSUNICOIN 0x07
+#define FCEUNPCMD_VSUNIDIP0 0x08
+#define FCEUNPCMD_FDSINSERTx 0x10
+#define FCEUNPCMD_FDSINSERT 0x18
+//#define FCEUNPCMD_FDSEJECT 0x19
+#define FCEUNPCMD_FDSSELECT 0x1A
+
+#define FCEUNPCMD_LOADSTATE 0x80
+
+#define FCEUNPCMD_SAVESTATE 0x81 /* Sent from server to client. */
+#define FCEUNPCMD_LOADCHEATS 0x82
+#define FCEUNPCMD_TEXT 0x90
+
+int FCEUNET_SendCommand(uint8, uint32);
+int FCEUNET_SendFile(uint8 cmd, char *);
diff --git a/nsf.c b/nsf.c
new file mode 100644
index 00000000..1eeeec10
--- /dev/null
+++ b/nsf.c
@@ -0,0 +1,568 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "types.h"
+#include "x6502.h"
+#include "fceu.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"
+
+#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(FCEUFILE *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<<x))
+ {
+ FCEU_printf(" Expansion hardware: %s\n",tab[x]);
+ NSFHeader.SoundChip=1<<x; /* Prevent confusing weirdness if more than one bit is set. */
+ break;
+ }
+ }
+ if(BSon)
+ FCEU_printf(" Bank-switched.\n");
+ FCEU_printf(" Load address: $%04x\n Init address: $%04x\n Play address: $%04x\n",LoadAddr,InitAddr,PlayAddr);
+ FCEU_printf(" %s\n",(NSFHeader.VideoSystem&1)?"PAL":"NTSC");
+ FCEU_printf(" Starting song: %d / %d\n\n",NSFHeader.StartingSong,NSFHeader.TotalSongs);
+
+ if(NSFHeader.SoundChip&4)
+ ExWRAM=FCEU_gmalloc(32768+8192);
+ else
+ ExWRAM=FCEU_gmalloc(8192);
+
+ FCEUI_SetVidSystem(NSFHeader.VideoSystem);
+
+ return 1;
+}
+
+static DECLFR(NSFVectorRead)
+{
+ if(((NSFNMIFlags&1) && SongReload) || (NSFNMIFlags&2) || doreset)
+ {
+ if(A==0xFFFA) return(0x00);
+ else if(A==0xFFFB) return(0x38);
+ else if(A==0xFFFC) return(0x20);
+ else if(A==0xFFFD) {doreset=0;return(0x38);}
+ return(X.DB);
+ }
+ else
+ return(CartBR(A));
+}
+
+void NSFVRC6_Init(void);
+void NSFVRC7_Init(void);
+void NSFMMC5_Init(void);
+void NSFN106_Init(void);
+void NSFAY_Init(void);
+
+void NSF_init(void)
+{
+ doreset=1;
+
+ ResetCartMapping();
+ if(NSFHeader.SoundChip&4)
+ {
+ SetupCartPRGMapping(0,ExWRAM,32768+8192,1);
+ setprg32(0x6000,0);
+ setprg8(0xE000,4);
+ memset(ExWRAM,0x00,32768+8192);
+ SetWriteHandler(0x6000,0xDFFF,CartBW);
+ SetReadHandler(0x6000,0xFFFF,CartBR);
+ }
+ else
+ {
+ memset(ExWRAM,0x00,8192);
+ SetReadHandler(0x6000,0x7FFF,CartBR);
+ SetWriteHandler(0x6000,0x7FFF,CartBW);
+ SetupCartPRGMapping(0,NSFDATA,((NSFMaxBank+1)*4096),0);
+ SetupCartPRGMapping(1,ExWRAM,8192,1);
+ setprg8r(1,0x6000,0);
+ SetReadHandler(0x8000,0xFFFF,CartBR);
+ }
+
+ if(BSon)
+ {
+ int32 x;
+ for(x=0;x<8;x++)
+ {
+ if(NSFHeader.SoundChip&4 && x>=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(CurrentSong<NSFHeader.TotalSongs)
+ {
+ CurrentSong++;
+ SongReload=0xFF;
+ }
+ }
+ else if((tmp&JOY_LEFT) && !(last&JOY_LEFT))
+ {
+ if(CurrentSong>1)
+ {
+ 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(name,NSFHeader.SongName,maxlen);
+ strncpy(artist,NSFHeader.Artist,maxlen);
+ strncpy(copyright,NSFHeader.Copyright,maxlen);
+ return(NSFHeader.TotalSongs);
+}
diff --git a/nsf.h b/nsf.h
new file mode 100644
index 00000000..c7bbb19b
--- /dev/null
+++ b/nsf.h
@@ -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
+ */
+
+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/ops.h b/ops.h
new file mode 100644
index 00000000..0d66b632
--- /dev/null
+++ b/ops.h
@@ -0,0 +1,485 @@
+/* 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
+ */
+
+case 0x00: /* BRK */
+ _PC++;
+ PUSH(_PC>>8);
+ PUSH(_PC);
+ PUSH(_P|U_FLAG|B_FLAG);
+ _P|=I_FLAG;
+ _PI|=I_FLAG;
+ _PC=RdMem(0xFFFE);
+ _PC|=RdMem(0xFFFF)<<8;
+ break;
+
+case 0x40: /* RTI */
+ _P=POP();
+ /* _PI=_P; This is probably incorrect, so it's commented out. */
+ _PI = _P;
+ _PC=POP();
+ _PC|=POP()<<8;
+ break;
+
+case 0x60: /* RTS */
+ _PC=POP();
+ _PC|=POP()<<8;
+ _PC++;
+ break;
+
+case 0x48: /* PHA */
+ PUSH(_A);
+ break;
+case 0x08: /* PHP */
+ PUSH(_P|U_FLAG|B_FLAG);
+ break;
+case 0x68: /* PLA */
+ _A=POP();
+ X_ZN(_A);
+ break;
+case 0x28: /* PLP */
+ _P=POP();
+ break;
+case 0x4C:
+ {
+ uint16 ptmp=_PC;
+ unsigned int npc;
+
+ npc=RdMem(ptmp);
+ ptmp++;
+ npc|=RdMem(ptmp)<<8;
+ _PC=npc;
+ }
+ break; /* JMP ABSOLUTE */
+case 0x6C:
+ {
+ uint32 tmp;
+ GetAB(tmp);
+ _PC=RdMem(tmp);
+ _PC|=RdMem( ((tmp+1)&0x00FF) | (tmp&0xFF00))<<8;
+ }
+ break;
+case 0x20: /* JSR */
+ {
+ uint8 npc;
+ npc=RdMem(_PC);
+ _PC++;
+ PUSH(_PC>>8);
+ PUSH(_PC);
+ _PC=RdMem(_PC)<<8;
+ _PC|=npc;
+ }
+ break;
+
+case 0xAA: /* TAX */
+ _X=_A;
+ X_ZN(_A);
+ break;
+
+case 0x8A: /* TXA */
+ _A=_X;
+ X_ZN(_A);
+ break;
+
+case 0xA8: /* TAY */
+ _Y=_A;
+ X_ZN(_A);
+ break;
+case 0x98: /* TYA */
+ _A=_Y;
+ X_ZN(_A);
+ break;
+
+case 0xBA: /* TSX */
+ _X=_S;
+ X_ZN(_X);
+ break;
+case 0x9A: /* TXS */
+ _S=_X;
+ break;
+
+case 0xCA: /* DEX */
+ _X--;
+ X_ZN(_X);
+ break;
+case 0x88: /* DEY */
+ _Y--;
+ X_ZN(_Y);
+ break;
+
+case 0xE8: /* INX */
+ _X++;
+ X_ZN(_X);
+ break;
+case 0xC8: /* INY */
+ _Y++;
+ X_ZN(_Y);
+ break;
+
+case 0x18: /* CLC */
+ _P&=~C_FLAG;
+ break;
+case 0xD8: /* CLD */
+ _P&=~D_FLAG;
+ break;
+case 0x58: /* CLI */
+ _P&=~I_FLAG;
+ break;
+case 0xB8: /* CLV */
+ _P&=~V_FLAG;
+ break;
+
+case 0x38: /* SEC */
+ _P|=C_FLAG;
+ break;
+case 0xF8: /* SED */
+ _P|=D_FLAG;
+ break;
+case 0x78: /* SEI */
+ _P|=I_FLAG;
+ break;
+
+case 0xEA: /* NOP */
+ break;
+
+case 0x0A: RMW_A(ASL);
+case 0x06: RMW_ZP(ASL);
+case 0x16: RMW_ZPX(ASL);
+case 0x0E: RMW_AB(ASL);
+case 0x1E: RMW_ABX(ASL);
+
+case 0xC6: RMW_ZP(DEC);
+case 0xD6: RMW_ZPX(DEC);
+case 0xCE: RMW_AB(DEC);
+case 0xDE: RMW_ABX(DEC);
+
+case 0xE6: RMW_ZP(INC);
+case 0xF6: RMW_ZPX(INC);
+case 0xEE: RMW_AB(INC);
+case 0xFE: RMW_ABX(INC);
+
+case 0x4A: RMW_A(LSR);
+case 0x46: RMW_ZP(LSR);
+case 0x56: RMW_ZPX(LSR);
+case 0x4E: RMW_AB(LSR);
+case 0x5E: RMW_ABX(LSR);
+
+case 0x2A: RMW_A(ROL);
+case 0x26: RMW_ZP(ROL);
+case 0x36: RMW_ZPX(ROL);
+case 0x2E: RMW_AB(ROL);
+case 0x3E: RMW_ABX(ROL);
+
+case 0x6A: RMW_A(ROR);
+case 0x66: RMW_ZP(ROR);
+case 0x76: RMW_ZPX(ROR);
+case 0x6E: RMW_AB(ROR);
+case 0x7E: RMW_ABX(ROR);
+
+case 0x69: LD_IM(ADC);
+case 0x65: LD_ZP(ADC);
+case 0x75: LD_ZPX(ADC);
+case 0x6D: LD_AB(ADC);
+case 0x7D: LD_ABX(ADC);
+case 0x79: LD_ABY(ADC);
+case 0x61: LD_IX(ADC);
+case 0x71: LD_IY(ADC);
+
+case 0x29: LD_IM(AND);
+case 0x25: LD_ZP(AND);
+case 0x35: LD_ZPX(AND);
+case 0x2D: LD_AB(AND);
+case 0x3D: LD_ABX(AND);
+case 0x39: LD_ABY(AND);
+case 0x21: LD_IX(AND);
+case 0x31: LD_IY(AND);
+
+case 0x24: LD_ZP(BIT);
+case 0x2C: LD_AB(BIT);
+
+case 0xC9: LD_IM(CMP);
+case 0xC5: LD_ZP(CMP);
+case 0xD5: LD_ZPX(CMP);
+case 0xCD: LD_AB(CMP);
+case 0xDD: LD_ABX(CMP);
+case 0xD9: LD_ABY(CMP);
+case 0xC1: LD_IX(CMP);
+case 0xD1: LD_IY(CMP);
+
+case 0xE0: LD_IM(CPX);
+case 0xE4: LD_ZP(CPX);
+case 0xEC: LD_AB(CPX);
+
+case 0xC0: LD_IM(CPY);
+case 0xC4: LD_ZP(CPY);
+case 0xCC: LD_AB(CPY);
+
+case 0x49: LD_IM(EOR);
+case 0x45: LD_ZP(EOR);
+case 0x55: LD_ZPX(EOR);
+case 0x4D: LD_AB(EOR);
+case 0x5D: LD_ABX(EOR);
+case 0x59: LD_ABY(EOR);
+case 0x41: LD_IX(EOR);
+case 0x51: LD_IY(EOR);
+
+case 0xA9: LD_IM(LDA);
+case 0xA5: LD_ZP(LDA);
+case 0xB5: LD_ZPX(LDA);
+case 0xAD: LD_AB(LDA);
+case 0xBD: LD_ABX(LDA);
+case 0xB9: LD_ABY(LDA);
+case 0xA1: LD_IX(LDA);
+case 0xB1: LD_IY(LDA);
+
+case 0xA2: LD_IM(LDX);
+case 0xA6: LD_ZP(LDX);
+case 0xB6: LD_ZPY(LDX);
+case 0xAE: LD_AB(LDX);
+case 0xBE: LD_ABY(LDX);
+
+case 0xA0: LD_IM(LDY);
+case 0xA4: LD_ZP(LDY);
+case 0xB4: LD_ZPX(LDY);
+case 0xAC: LD_AB(LDY);
+case 0xBC: LD_ABX(LDY);
+
+case 0x09: LD_IM(ORA);
+case 0x05: LD_ZP(ORA);
+case 0x15: LD_ZPX(ORA);
+case 0x0D: LD_AB(ORA);
+case 0x1D: LD_ABX(ORA);
+case 0x19: LD_ABY(ORA);
+case 0x01: LD_IX(ORA);
+case 0x11: LD_IY(ORA);
+
+case 0xEB: /* (undocumented) */
+case 0xE9: LD_IM(SBC);
+case 0xE5: LD_ZP(SBC);
+case 0xF5: LD_ZPX(SBC);
+case 0xED: LD_AB(SBC);
+case 0xFD: LD_ABX(SBC);
+case 0xF9: LD_ABY(SBC);
+case 0xE1: LD_IX(SBC);
+case 0xF1: LD_IY(SBC);
+
+case 0x85: ST_ZP(_A);
+case 0x95: ST_ZPX(_A);
+case 0x8D: ST_AB(_A);
+case 0x9D: ST_ABX(_A);
+case 0x99: ST_ABY(_A);
+case 0x81: ST_IX(_A);
+case 0x91: ST_IY(_A);
+
+case 0x86: ST_ZP(_X);
+case 0x96: ST_ZPY(_X);
+case 0x8E: ST_AB(_X);
+
+case 0x84: ST_ZP(_Y);
+case 0x94: ST_ZPX(_Y);
+case 0x8C: ST_AB(_Y);
+
+/* BCC */
+case 0x90: JR(!(_P&C_FLAG)); break;
+
+/* BCS */
+case 0xB0: JR(_P&C_FLAG); break;
+
+/* BEQ */
+case 0xF0: JR(_P&Z_FLAG); break;
+
+/* BNE */
+case 0xD0: JR(!(_P&Z_FLAG)); break;
+
+/* BMI */
+case 0x30: JR(_P&N_FLAG); break;
+
+/* BPL */
+case 0x10: JR(!(_P&N_FLAG)); break;
+
+/* BVC */
+case 0x50: JR(!(_P&V_FLAG)); break;
+
+/* BVS */
+case 0x70: JR(_P&V_FLAG); break;
+
+//default: printf("Bad %02x at $%04x\n",b1,X.PC);break;
+//ifdef moo
+/* Here comes the undocumented instructions block. Note that this implementation
+ may be "wrong". If so, please tell me.
+*/
+
+/* AAC */
+case 0x2B:
+case 0x0B: LD_IM(AND;_P&=~C_FLAG;_P|=_A>>7);
+
+/* AAX */
+case 0x87: ST_ZP(_A&_X);
+case 0x97: ST_ZPY(_A&_X);
+case 0x8F: ST_AB(_A&_X);
+case 0x83: ST_IX(_A&_X);
+
+/* ARR - ARGH, MATEY! */
+case 0x6B: {
+ uint8 arrtmp;
+ LD_IM(AND;_P&=~V_FLAG;_P|=(_A^(_A>>1))&0x40;arrtmp=_A>>7;_A>>=1;_A|=(_P&C_FLAG)<<7;_P&=~C_FLAG;_P|=arrtmp;X_ZN(_A));
+ }
+/* ASR */
+case 0x4B: LD_IM(AND;LSRA);
+
+/* ATX(OAL) Is this(OR with $EE) correct? */
+case 0xAB: LD_IM(_A|=0xEE;AND;_X=_A);
+
+/* AXS */
+case 0xCB: LD_IM(AXS);
+
+/* DCP */
+case 0xC7: RMW_ZP(DEC;CMP);
+case 0xD7: RMW_ZPX(DEC;CMP);
+case 0xCF: RMW_AB(DEC;CMP);
+case 0xDF: RMW_ABX(DEC;CMP);
+case 0xDB: RMW_ABY(DEC;CMP);
+case 0xC3: RMW_IX(DEC;CMP);
+case 0xD3: RMW_IY(DEC;CMP);
+
+/* ISB */
+case 0xE7: RMW_ZP(INC;SBC);
+case 0xF7: RMW_ZPX(INC;SBC);
+case 0xEF: RMW_AB(INC;SBC);
+case 0xFF: RMW_ABX(INC;SBC);
+case 0xFB: RMW_ABY(INC;SBC);
+case 0xE3: RMW_IX(INC;SBC);
+case 0xF3: RMW_IY(INC;SBC);
+
+/* DOP */
+
+case 0x04: _PC++;break;
+case 0x14: _PC++;break;
+case 0x34: _PC++;break;
+case 0x44: _PC++;break;
+case 0x54: _PC++;break;
+case 0x64: _PC++;break;
+case 0x74: _PC++;break;
+
+case 0x80: _PC++;break;
+case 0x82: _PC++;break;
+case 0x89: _PC++;break;
+case 0xC2: _PC++;break;
+case 0xD4: _PC++;break;
+case 0xE2: _PC++;break;
+case 0xF4: _PC++;break;
+
+/* KIL */
+
+case 0x02:
+case 0x12:
+case 0x22:
+case 0x32:
+case 0x42:
+case 0x52:
+case 0x62:
+case 0x72:
+case 0x92:
+case 0xB2:
+case 0xD2:
+case 0xF2:ADDCYC(0xFF);
+ _jammed=1;
+ _PC--;
+ break;
+
+/* LAR */
+case 0xBB: RMW_ABY(_S&=x;_A=_X=_S;X_ZN(_X));
+
+/* LAX */
+case 0xA7: LD_ZP(LDA;LDX);
+case 0xB7: LD_ZPY(LDA;LDX);
+case 0xAF: LD_AB(LDA;LDX);
+case 0xBF: LD_ABY(LDA;LDX);
+case 0xA3: LD_IX(LDA;LDX);
+case 0xB3: LD_IY(LDA;LDX);
+
+/* NOP */
+case 0x1A:
+case 0x3A:
+case 0x5A:
+case 0x7A:
+case 0xDA:
+case 0xFA: break;
+
+/* RLA */
+case 0x27: RMW_ZP(ROL;AND);
+case 0x37: RMW_ZPX(ROL;AND);
+case 0x2F: RMW_AB(ROL;AND);
+case 0x3F: RMW_ABX(ROL;AND);
+case 0x3B: RMW_ABY(ROL;AND);
+case 0x23: RMW_IX(ROL;AND);
+case 0x33: RMW_IY(ROL;AND);
+
+/* RRA */
+case 0x67: RMW_ZP(ROR;ADC);
+case 0x77: RMW_ZPX(ROR;ADC);
+case 0x6F: RMW_AB(ROR;ADC);
+case 0x7F: RMW_ABX(ROR;ADC);
+case 0x7B: RMW_ABY(ROR;ADC);
+case 0x63: RMW_IX(ROR;ADC);
+case 0x73: RMW_IY(ROR;ADC);
+
+/* SLO */
+case 0x07: RMW_ZP(ASL;ORA);
+case 0x17: RMW_ZPX(ASL;ORA);
+case 0x0F: RMW_AB(ASL;ORA);
+case 0x1F: RMW_ABX(ASL;ORA);
+case 0x1B: RMW_ABY(ASL;ORA);
+case 0x03: RMW_IX(ASL;ORA);
+case 0x13: RMW_IY(ASL;ORA);
+
+/* SRE */
+case 0x47: RMW_ZP(LSR;EOR);
+case 0x57: RMW_ZPX(LSR;EOR);
+case 0x4F: RMW_AB(LSR;EOR);
+case 0x5F: RMW_ABX(LSR;EOR);
+case 0x5B: RMW_ABY(LSR;EOR);
+case 0x43: RMW_IX(LSR;EOR);
+case 0x53: RMW_IY(LSR;EOR);
+
+/* AXA - SHA */
+case 0x93: ST_IY(_A&_X&(((A-_Y)>>8)+1));
+case 0x9F: ST_ABY(_A&_X&(((A-_Y)>>8)+1));
+
+/* SYA */
+case 0x9C: ST_ABX(_Y&(((A-_X)>>8)+1));
+
+/* SXA */
+case 0x9E: ST_ABY(_X&(((A-_Y)>>8)+1));
+
+/* XAS */
+case 0x9B: _S=_A&_X;ST_ABY(_S& (((A-_Y)>>8)+1) );
+
+/* TOP */
+case 0x0C: LD_AB(;);
+case 0x1C:
+case 0x3C:
+case 0x5C:
+case 0x7C:
+case 0xDC:
+case 0xFC: LD_ABX(;);
+
+/* XAA - BIG QUESTION MARK HERE */
+case 0x8B: _A|=0xEE; _A&=_X; LD_IM(AND);
+//endif
diff --git a/palette.c b/palette.c
new file mode 100644
index 00000000..3e5b23ce
--- /dev/null
+++ b/palette.c
@@ -0,0 +1,366 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002,2003 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "types.h"
+#include "fceu.h"
+#include "general.h"
+#include "driver.h"
+
+#include "palette.h"
+#include "palettes/palettes.h"
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+static int ntsccol=0;
+static int ntsctint=46+10;
+static int ntschue=72;
+
+/* These are dynamically filled/generated palettes: */
+pal palettei[64]; // Custom palette for an individual game.
+pal palettec[64]; // Custom "global" palette.
+pal paletten[64]; // Mathematically generated palette.
+
+static void CalculatePalette(void);
+static void ChoosePalette(void);
+static void WritePalette(void);
+uint8 pale=0;
+
+pal *palo;
+static pal *palpoint[8]=
+ {
+ palette,
+ rp2c04001,
+ rp2c04002,
+ rp2c04003,
+ rp2c05004,
+ };
+
+void FCEUI_SetPaletteArray(uint8 *pal)
+{
+ if(!pal)
+ palpoint[0]=palette;
+ else
+ {
+ int x;
+ palpoint[0]=palettec;
+ for(x=0;x<64;x++)
+ {
+ palpoint[0][x].r=*((uint8 *)pal+x+x+x);
+ palpoint[0][x].g=*((uint8 *)pal+x+x+x+1);
+ palpoint[0][x].b=*((uint8 *)pal+x+x+x+2);
+ }
+ }
+ FCEU_ResetPalette();
+}
+
+
+void FCEUI_SetNTSCTH(int n, int tint, int hue)
+{
+ ntsctint=tint;
+ ntschue=hue;
+ ntsccol=n;
+ FCEU_ResetPalette();
+}
+
+static uint8 lastd=0;
+void SetNESDeemph(uint8 d, int force)
+{
+ static uint16 rtmul[7]={32768*1.239,32768*.794,32768*1.019,32768*.905,32768*1.023,32768*.741,32768*.75};
+ static uint16 gtmul[7]={32768*.915,32768*1.086,32768*.98,32768*1.026,32768*.908,32768*.987,32768*.75};
+ static uint16 btmul[7]={32768*.743,32768*.882,32768*.653,32768*1.277,32768*.979,32768*.101,32768*.75};
+ uint32 r,g,b;
+ int x;
+
+ /* If it's not forced(only forced when the palette changes),
+ don't waste cpu time if the same deemphasis bits are set as the last call.
+ */
+ if(!force)
+ {
+ if(d==lastd)
+ return;
+ }
+ else /* Only set this when palette has changed. */
+ {
+ r=rtmul[6];
+ g=rtmul[6];
+ b=rtmul[6];
+
+ for(x=0;x<0x40;x++)
+ {
+ uint32 m,n,o;
+ m=palo[x].r;
+ n=palo[x].g;
+ o=palo[x].b;
+ m=(m*r)>>15;
+ n=(n*g)>>15;
+ o=(o*b)>>15;
+ if(m>0xff) m=0xff;
+ if(n>0xff) n=0xff;
+ if(o>0xff) o=0xff;
+ FCEUD_SetPalette(x|0xC0,m,n,o);
+ }
+ }
+ if(!d) return; /* No deemphasis, so return. */
+
+ r=rtmul[d-1];
+ g=gtmul[d-1];
+ b=btmul[d-1];
+
+ for(x=0;x<0x40;x++)
+ {
+ uint32 m,n,o;
+
+ m=palo[x].r;
+ n=palo[x].g;
+ o=palo[x].b;
+ m=(m*r)>>15;
+ n=(n*g)>>15;
+ o=(o*b)>>15;
+ if(m>0xff) m=0xff;
+ if(n>0xff) n=0xff;
+ if(o>0xff) o=0xff;
+
+ FCEUD_SetPalette(x|0x40,m,n,o);
+ }
+
+ lastd=d;
+}
+
+/* Converted from Kevin Horton's qbasic palette generator. */
+static void CalculatePalette(void)
+{
+ int x,z;
+ int r,g,b;
+ double s,luma,theta;
+ static uint8 cols[16]={0,24,21,18,15,12,9,6,3,0,33,30,27,0,0,0};
+ static uint8 br1[4]={6,9,12,12};
+ static double br2[4]={.29,.45,.73,.9};
+ static double br3[4]={0,.24,.47,.77};
+
+ for(x=0;x<=3;x++)
+ for(z=0;z<16;z++)
+ {
+ s=(double)ntsctint/128;
+ luma=br2[x];
+ if(z==0) {s=0;luma=((double)br1[x])/12;}
+
+ if(z>=13)
+ {
+ s=luma=0;
+ if(z==13)
+ luma=br3[x];
+ }
+
+ theta=(double)M_PI*(double)(((double)cols[z]*10+ (((double)ntschue/2)+300) )/(double)180);
+ r=(int)((luma+s*sin(theta))*256);
+ g=(int)((luma-(double)27/53*s*sin(theta)+(double)10/53*s*cos(theta))*256);
+ b=(int)((luma-s*cos(theta))*256);
+
+
+ if(r>255) r=255;
+ if(g>255) g=255;
+ if(b>255) b=255;
+ if(r<0) r=0;
+ if(g<0) g=0;
+ if(b<0) b=0;
+
+ paletten[(x<<4)+z].r=r;
+ paletten[(x<<4)+z].g=g;
+ paletten[(x<<4)+z].b=b;
+ }
+ WritePalette();
+}
+
+static int ipalette=0;
+
+void FCEU_LoadGamePalette(void)
+{
+ uint8 ptmp[192];
+ FILE *fp;
+ char *fn;
+
+ ipalette=0;
+
+ fn=FCEU_MakeFName(FCEUMKF_PALETTE,0,0);
+
+ if((fp=FCEUD_UTF8fopen(fn,"rb")))
+ {
+ int x;
+ fread(ptmp,1,192,fp);
+ fclose(fp);
+ for(x=0;x<64;x++)
+ {
+ palettei[x].r=ptmp[x+x+x];
+ palettei[x].g=ptmp[x+x+x+1];
+ palettei[x].b=ptmp[x+x+x+2];
+ }
+ ipalette=1;
+ }
+ free(fn);
+}
+
+void FCEU_ResetPalette(void)
+{
+ if(FCEUGameInfo)
+ {
+ ChoosePalette();
+ WritePalette();
+ }
+}
+
+static void ChoosePalette(void)
+{
+ if(FCEUGameInfo->type==GIT_NSF)
+ palo=0;
+ else if(ipalette)
+ palo=palettei;
+ else if(ntsccol && !PAL && FCEUGameInfo->type!=GIT_VSUNI)
+ {
+ palo=paletten;
+ CalculatePalette();
+ }
+ else
+ palo=palpoint[pale];
+}
+
+void WritePalette(void)
+{
+ int x;
+
+ for(x=0;x<7;x++)
+ FCEUD_SetPalette(x,unvpalette[x].r,unvpalette[x].g,unvpalette[x].b);
+ if(FCEUGameInfo->type==GIT_NSF)
+ {
+ //for(x=0;x<128;x++)
+ // FCEUD_SetPalette(x,x,0,x);
+ }
+ else
+ {
+ for(x=0;x<64;x++)
+ FCEUD_SetPalette(128+x,palo[x].r,palo[x].g,palo[x].b);
+ SetNESDeemph(lastd,1);
+ }
+}
+
+void FCEUI_GetNTSCTH(int *tint, int *hue)
+{
+ *tint=ntsctint;
+ *hue=ntschue;
+}
+
+static int controlselect=0;
+static int controllength=0;
+
+void FCEUI_NTSCDEC(void)
+{
+ if(ntsccol && FCEUGameInfo->type!=GIT_VSUNI &&!PAL && FCEUGameInfo->type!=GIT_NSF)
+ {
+ int which;
+ if(controlselect)
+ {
+ if(controllength)
+ {
+ which=controlselect==1?ntschue:ntsctint;
+ which--;
+ if(which<0) which=0;
+ if(controlselect==1)
+ ntschue=which;
+ else ntsctint=which;
+ CalculatePalette();
+ }
+ controllength=360;
+ }
+ }
+}
+
+void FCEUI_NTSCINC(void)
+{
+ if(ntsccol && FCEUGameInfo->type!=GIT_VSUNI && !PAL && FCEUGameInfo->type!=GIT_NSF)
+ if(controlselect)
+ {
+ if(controllength)
+ {
+ switch(controlselect)
+ {
+ case 1:ntschue++;
+ if(ntschue>128) ntschue=128;
+ CalculatePalette();
+ break;
+ case 2:ntsctint++;
+ if(ntsctint>128) ntsctint=128;
+ CalculatePalette();
+ break;
+ }
+ }
+ controllength=360;
+ }
+}
+
+void FCEUI_NTSCSELHUE(void)
+{
+ if(ntsccol && FCEUGameInfo->type!=GIT_VSUNI && !PAL && FCEUGameInfo->type!=GIT_NSF){controlselect=1;controllength=360;}
+}
+
+void FCEUI_NTSCSELTINT(void)
+{
+ if(ntsccol && FCEUGameInfo->type!=GIT_VSUNI && !PAL && FCEUGameInfo->type!=GIT_NSF){controlselect=2;controllength=360;}
+}
+
+void FCEU_DrawNTSCControlBars(uint8 *XBuf)
+{
+ uint8 *XBaf;
+ int which=0;
+ int x,x2;
+
+ if(!controllength) return;
+ controllength--;
+ if(!XBuf) return;
+
+ if(controlselect==1)
+ {
+ DrawTextTrans(XBuf+128-12+180*256, 256, (uint8 *)"Hue", 0x85);
+ which=ntschue<<1;
+ }
+ else if(controlselect==2)
+ {
+ DrawTextTrans(XBuf+128-16+180*256, 256, (uint8 *)"Tint", 0x85);
+ which=ntsctint<<1;
+ }
+
+ XBaf=XBuf+200*256;
+ for(x=0;x<which;x+=2)
+ {
+ for(x2=6;x2>=-6;x2--)
+ {
+ XBaf[x-256*x2]=0x85;
+ }
+ }
+ for(;x<256;x+=2)
+ {
+ for(x2=2;x2>=-2;x2--)
+ XBaf[x-256*x2]=0x85;
+ }
+}
diff --git a/palette.h b/palette.h
new file mode 100644
index 00000000..ac7ddce3
--- /dev/null
+++ b/palette.h
@@ -0,0 +1,11 @@
+typedef struct {
+ uint8 r,g,b;
+} pal;
+
+extern pal *palo;
+void FCEU_ResetPalette(void);
+
+void FCEU_ResetPalette(void);
+void FCEU_ResetMessages();
+void FCEU_LoadGamePalette(void);
+void FCEU_DrawNTSCControlBars(uint8 *XBuf);
diff --git a/palettes/conv.c b/palettes/conv.c
new file mode 100644
index 00000000..13e4d8f0
--- /dev/null
+++ b/palettes/conv.c
@@ -0,0 +1,74 @@
+/* Quick conversion stuff for MAME->FCE Ultra */
+
+#include <stdio.h>
+#include "../types.h"
+#include "../palette.h"
+#include "palettes.h"
+
+/* check 0x08 */
+static uint8 rp2c04001_colortable[] =
+{
+ 0x35, 0x23, 0x16, 0x22, 0x1c, 0x09, 0xff, 0x15, /* 0x00 - 0x07 */
+ 0x20, 0x00, 0x27, 0x05, 0x04, 0x27, 0x08, 0x30, /* 0x08 - 0x0f */
+ 0x21, 0xff, 0xff, 0x29, 0x3c, 0x32, 0x36, 0x12, /* 0x10 - 0x17 */
+ 0xff, 0x2b, 0x0f, 0xff, 0x20, 0x10, 0x24, 0x01, /* 0x18 - 0x1f */
+ 0xff, 0x31, 0xff, 0x2a, 0x2c, 0x0c, 0xff, 0xff, /* 0x20 - 0x27 */
+ 0xff, 0x07, 0x34, 0x06, 0x13, 0x02, 0x26, 0x0f, /* 0x28 - 0x2f */
+ 0xff, 0x19, 0x10, 0x0a, 0x39, 0xff, 0x37, 0x17, /* 0x30 - 0x37 */
+ 0xff, 0x11, 0x09, 0xff, 0x39, 0x25, 0x18, 0xff /* 0x38 - 0x3f */
+};
+
+/* RP2C04-002 */
+static uint8 rp2c04002_colortable[] =
+{
+ 0x0f, 0x27, 0x18, 0xff, 0x3a, 0x25, 0xff, 0x31, /* 0x00 - 0x07 */
+ 0x16, 0x13, 0x38, 0x34, 0x20, 0x23, 0xff, 0x0b, /* 0x08 - 0x0f */
+ 0xff, 0x21, 0x06, 0xff, 0x1b, 0x29, 0xff, 0x22, /* 0x10 - 0x17 */
+ 0xff, 0x24, 0xff, 0x2b, 0xff, 0x08, 0xff, 0x03, /* 0x18 - 0x1f */
+ 0xff, 0x36, 0x26, 0x33, 0x11, 0xff, 0x10, 0x02, /* 0x20 - 0x27 */
+ 0x14, 0xff, 0x00, 0x09, 0x12, 0x0f, 0x37, 0x30, /* 0x28 - 0x2f */
+ 0xff, 0xff, 0x2a, 0x17, 0x0c, 0x01, 0x15, 0x19, /* 0x30 - 0x37 */
+ 0xff, 0x2c, 0x07, 0x37, 0xff, 0x05, 0x0a, 0x00 /* 0x38 - 0x3f */
+};
+
+/* RP2C04-003 */
+/* Check 0x00. Used in Dr Mario. */
+static uint8 rp2c04003_colortable[] =
+{
+ 0x03, 0xff, 0xff, 0x00, 0x1a, 0x30, 0x31, 0x09, /* 0x00 - 0x07 */
+ 0x01, 0x0f, 0x36, 0x08, 0x15, 0xff, 0xff, 0x30, /* 0x08 - 0x0f */
+ 0x22, 0x1c, 0xff, 0x12, 0x19, 0x18, 0x17, 0x1b, /* 0x10 - 0x17 */
+ 0x00, 0xff, 0xff, 0x02, 0x16, 0x06, 0xff, 0x35, /* 0x18 - 0x1f */
+ 0x23, 0xff, 0x0f, 0x37, 0xff, 0x27, 0x26, 0x30, /* 0x20 - 0x27 */
+ 0x29, 0xff, 0x21, 0x24, 0x11, 0xff, 0x0f, 0xff, /* 0x28 - 0x2f */
+ 0x2c, 0xff, 0xff, 0xff, 0x07, 0x2a, 0x28, 0xff, /* 0x30 - 0x37 */
+ 0x0a, 0xff, 0x32, 0x37, 0x13, 0xff, 0xff, 0x0c /* 0x38 - 0x3f */
+};
+
+/* RP2C05-004 */
+/* check 0x1d, 0x38 */
+static uint8 rp2c05004_colortable[] =
+{
+ 0x18, 0xff, 0x1c, 0x28, 0xff, 0xff, 0x01, 0x17, /* 0x00 - 0x07 */
+ 0x10, 0x0f, 0x2a, 0x0f, 0x36, 0x37, 0x1a, 0xff, /* 0x08 - 0x0f */
+ 0x25, 0xff, 0x12, 0xff, 0x0f, 0xff, 0xff, 0x26, /* 0x10 - 0x17 */
+ 0xff, 0xff, 0x22, 0x19, 0xff, 0x0f, 0x3a, 0x21, /* 0x18 - 0x1f */
+ 0x05, 0x0a, 0x07, 0x01, 0x13, 0xff, 0x00, 0x15, /* 0x20 - 0x27 */
+ 0x0c, 0xff, 0x11, 0xff, 0xff, 0x38, 0xff, 0xff, /* 0x28 - 0x2f */
+ 0xff, 0xff, 0x08, 0x16, 0xff, 0xff, 0x30, 0x3c, /* 0x30 - 0x37 */
+ 0x0f, 0x27, 0xff, 0x31, 0x29, 0xff, 0x30, 0x09 /* 0x38 - 0x3f */
+};
+
+
+main()
+{
+ int x;
+ for(x=0;x<64;x++)
+ {
+ // if(x <= 0x20)
+// if(rp2c04002_colortable[x] == 0xFF) rp2c04002_colortable[x]= 0x30;
+ printf("{0x%02x, 0x%02x, 0x%02x},\n",palette[rp2c04001_colortable[x]&0x3F].r,
+ palette[rp2c04001_colortable[x]&0x3F].g,
+ palette[rp2c04001_colortable[x]&0x3F].b);
+ }
+}
diff --git a/palettes/palettes.h b/palettes/palettes.h
new file mode 100644
index 00000000..7556220c
--- /dev/null
+++ b/palettes/palettes.h
@@ -0,0 +1,229 @@
+pal rp2c04001[64] = {
+ #include "rp2c04001.h"
+};
+
+pal rp2c04002[64] = {
+ #include "rp2c04002.h"
+};
+
+pal rp2c04003[64] = {
+ #include "rp2c04003.h"
+};
+pal rp2c05004[64] = {
+ #include "rp2c05004.h"
+};
+
+pal unvpalette[7] = {
+{ 0x00<<2,0x00<<2,0x00<<2}, // Black
+{ 0x3F<<2,0x3F<<2,0x34<<2}, // White
+{ 0x00<<2,0x00<<2,0x00<<2}, // Black
+{ 0x1d<<2,0x1d<<2,0x24<<2}, // Greyish
+{ 190,0,0 }, // Redish
+{ 51,255,51}, // Bright green
+{ 49,14,200},
+};
+
+
+/* Default palette */
+pal palette[64] = {
+
+ {0x60, 0x60, 0x60}, /* Value 0 */
+ {0x00, 0x00, 0x70}, /* Value 1 */
+ {0x14, 0x00, 0x80}, /* Value 2 */
+ {0x2C, 0x00, 0x6E}, /* Value 3 */
+ {0x4A, 0x00, 0x4E}, /* Value 4 */
+ {0x6C, 0x00, 0x18}, /* Value 5 */
+ {0x5A, 0x03, 0x02}, /* Value 6 */
+ {0x51, 0x18, 0x00}, /* Value 7 */
+ {0x34, 0x24, 0x00}, /* Value 8 */
+ {0x00, 0x34, 0x00}, /* Value 9 */
+ {0x00, 0x32, 0x00}, /* Value 10 */
+ {0x00, 0x34, 0x20}, /* Value 11 */
+ {0x00, 0x2C, 0x78}, /* Value 12 */
+ {0x00, 0x00, 0x00}, /* Value 13 */
+ {0x02, 0x02, 0x02}, /* Value 14 */
+ {0x02, 0x02, 0x02}, /* Value 15 */
+ {0xC4, 0xC4, 0xC4}, /* Value 16 */
+ {0x00, 0x58, 0xDE}, /* Value 17 */
+ {0x30, 0x1F, 0xFC}, /* Value 18 */
+ {0x7F, 0x14, 0xE0}, /* Value 19 */
+ {0xA8, 0x00, 0xB0}, /* Value 20 */
+ {0xC0, 0x06, 0x5C}, /* Value 21 */
+ {0xC0, 0x2B, 0x0E}, /* Value 22 */
+ {0xA6, 0x40, 0x10}, /* Value 23 */
+ {0x6F, 0x61, 0x00}, /* Value 24 */
+ {0x30, 0x80, 0x00}, /* Value 25 */
+ {0x00, 0x7C, 0x00}, /* Value 26 */
+ {0x00, 0x7C, 0x3C}, /* Value 27 */
+ {0x00, 0x6E, 0x84}, /* Value 28 */
+ {0x14, 0x14, 0x14}, /* Value 29 */
+ {0x04, 0x04, 0x04}, /* Value 30 */
+ {0x04, 0x04, 0x04}, /* Value 31 */
+ {0xF0, 0xF0, 0xF0}, /* Value 32 */
+ {0x4C, 0xAA, 0xFF}, /* Value 33 */
+ {0x6F, 0x73, 0xF5}, /* Value 34 */
+ {0xB0, 0x70, 0xFF}, /* Value 35 */
+ {0xDA, 0x5A, 0xFF}, /* Value 36 */
+ {0xF0, 0x60, 0xC0}, /* Value 37 */
+ {0xF8, 0x83, 0x6D}, /* Value 38 */
+ {0xD0, 0x90, 0x30}, /* Value 39 */
+ {0xD4, 0xC0, 0x30}, /* Value 40 */
+ {0x66, 0xD0, 0x00}, /* Value 41 */
+ {0x26, 0xDD, 0x1A}, /* Value 42 */
+ {0x2E, 0xC8, 0x66}, /* Value 43 */
+ {0x34, 0xC2, 0xBE}, /* Value 44 */
+ {0x54, 0x54, 0x54}, /* Value 45 */
+ {0x06, 0x06, 0x06}, /* Value 46 */
+ {0x06, 0x06, 0x06}, /* Value 47 */
+ {0xFF, 0xFF, 0xFF}, /* Value 48 */
+ {0xB6, 0xDA, 0xFF}, /* Value 49 */
+ {0xC8, 0xCA, 0xFF}, /* Value 50 */
+ {0xDA, 0xC2, 0xFF}, /* Value 51 */
+ {0xF0, 0xBE, 0xFF}, /* Value 52 */
+ {0xFC, 0xBC, 0xEE}, /* Value 53 */
+ {0xFF, 0xD0, 0xB4}, /* Value 54 */
+ {0xFF, 0xDA, 0x90}, /* Value 55 */
+ {0xEC, 0xEC, 0x92}, /* Value 56 */
+ {0xDC, 0xF6, 0x9E}, /* Value 57 */
+ {0xB8, 0xFF, 0xA2}, /* Value 58 */
+ {0xAE, 0xEA, 0xBE}, /* Value 59 */
+ {0x9E, 0xEF, 0xEF}, /* Value 60 */
+ {0xBE, 0xBE, 0xBE}, /* Value 61 */
+ {0x08, 0x08, 0x08}, /* Value 62 */
+ {0x08, 0x08, 0x08}, /* Value 63 */
+/*
+// old palette:
+74, 74, 74
+24, 18, 8C
+00, 00, A8
+44, 00, 9C
+8C, 00, 74
+A8, 00, 10
+A4, 00, 00
+7C, 08, 00
+40, 2C, 00
+00, 44, 00
+00, 50, 00
+00, 3C, 14
+18, 3C, 5C
+00, 00, 00
+00, 00, 00
+00, 00, 00
+BC, BC, BC
+00, 70, EC
+20, 38, EC
+80, 00, F0
+BC, 00, BC
+E4, 00, 58
+D8, 28, 00
+C8, 4C, 0C
+88, 70, 00
+00, 94, 00
+00, A8, 00
+00, 90, 38
+00, 80, 88
+00, 00, 00
+00, 00, 00
+00, 00, 00
+FC, FC, FC
+3C, BC, FC
+5C, 94, FC
+40, 88, FC
+F4, 78, FC
+FC, 74, B4
+FC, 74, 60
+FC, 98, 38
+F0, BC, 3C
+80, D0, 10
+4C, DC, 48
+58, F8, 98
+00, E8, D8
+78, 78, 78
+00, 00, 00
+00, 00, 00
+FC, FC, FC
+A8, E4, FC
+C4, D4, FC
+D4, C8, FC
+FC, C4, FC
+FC, C4, D8
+FC, BC, B0
+FC, D8, A8
+FC, E4, A0
+E0, FC, A0
+A8, F0, BC
+B0, FC, CC
+9C, FC, F0
+C4, C4, C4
+00, 00, 00
+00, 00, 00
+
+slightly better but too dark:
+0x5C, 0x5C, 0x5C
+0x00, 0x20, 0x74
+0x00, 0x00, 0x98
+0x30, 0x00, 0x84
+0x58, 0x00, 0x68
+0x68, 0x00, 0x30
+0x60, 0x00, 0x00
+0x48, 0x10, 0x00
+0x28, 0x18, 0x00
+0x20, 0x28, 0x00
+0x00, 0x40, 0x00
+0x00, 0x38, 0x30
+0x00, 0x38, 0x48
+0x00, 0x00, 0x00
+0x10, 0x10, 0x10
+0x10, 0x10, 0x10
+0xAA, 0xAA, 0xAA
+0x18, 0x54, 0xBC
+0x28, 0x30, 0xF8
+0x68, 0x20, 0xD8
+0xA8, 0x00, 0xB8
+0xB8, 0x14, 0x5C
+0xB8, 0x18, 0x10
+0x8C, 0x38, 0x0C
+0x60, 0x50, 0x00
+0x3C, 0x60, 0x00
+0x00, 0x78, 0x00
+0x00, 0x70, 0x4C
+0x00, 0x70, 0x80
+0xFF, 0xFF, 0x10
+0x10, 0xFF, 0xFF
+0x10, 0x10, 0xFF
+0xFF, 0xFF, 0xFF
+0x4C, 0x9C, 0xEC
+0x78, 0x80, 0xFF
+0xAC, 0x70, 0xFF
+0xE0, 0x60, 0xF0
+0xFC, 0x68, 0xA4
+0xFF, 0x70, 0x68
+0xE2, 0x92, 0x38
+0xBB, 0xAB, 0x00
+0x7E, 0xC2, 0x1C
+0x40, 0xD0, 0x30
+0x28, 0xC4, 0x80
+0x20, 0xB8, 0xC0
+0x48, 0x48, 0x48
+0x10, 0x10, 0x10
+0x10, 0x10, 0x10
+0xFF, 0xFF, 0xFF
+0xB4, 0xD4, 0xFF
+0xC0, 0xC8, 0xFF
+0xD8, 0xC4, 0xFF
+0xF0, 0xC0, 0xFF
+0xFF, 0xC4, 0xD8
+0xFF, 0xC8, 0xC0
+0xF8, 0xD4, 0xAC
+0xE8, 0xE0, 0x98
+0xD0, 0xE8, 0xA0
+0xB8, 0xF0, 0xA8
+0xA8, 0xE8, 0xD0
+0xA8, 0xE0, 0xE8
+0xB2, 0xB2, 0xB2
+0x10, 0xFF, 0x10
+0xFF, 0x10, 0x10
+
+*/
+
+};
diff --git a/palettes/rp2c04001.h b/palettes/rp2c04001.h
new file mode 100644
index 00000000..a7bdb7c0
--- /dev/null
+++ b/palettes/rp2c04001.h
@@ -0,0 +1,64 @@
+{0xfc, 0xc4, 0xd8},
+{0x40, 0x88, 0xfc},
+{0xd8, 0x28, 0x00},
+{0x5c, 0x94, 0xfc},
+{0x00, 0x80, 0x88},
+{0x00, 0x44, 0x00},
+{0x00, 0x00, 0x00},
+{0xe4, 0x00, 0x58},
+{0xfc, 0xfc, 0xfc},
+{0x74, 0x74, 0x74},
+{0xfc, 0x98, 0x38},
+{0xa8, 0x00, 0x10},
+{0x8c, 0x00, 0x74},
+{0xfc, 0x98, 0x38},
+{0x40, 0x2c, 0x00},
+{0xfc, 0xfc, 0xfc},
+{0x3c, 0xbc, 0xfc},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x80, 0xd0, 0x10},
+{0x9c, 0xfc, 0xf0},
+{0xc4, 0xd4, 0xfc},
+{0xfc, 0xbc, 0xb0},
+{0x20, 0x38, 0xec},
+{0x00, 0x00, 0x00},
+{0x58, 0xf8, 0x98},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0xfc, 0xfc, 0xfc},
+{0xbc, 0xbc, 0xbc},
+{0xf4, 0x78, 0xfc},
+{0x24, 0x18, 0x8c},
+{0x00, 0x00, 0x00},
+{0xa8, 0xe4, 0xfc},
+{0x00, 0x00, 0x00},
+{0x4c, 0xdc, 0x48},
+{0x00, 0xe8, 0xd8},
+{0x18, 0x3c, 0x5c},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x7c, 0x08, 0x00},
+{0xfc, 0xc4, 0xfc},
+{0xa4, 0x00, 0x00},
+{0x80, 0x00, 0xf0},
+{0x00, 0x00, 0xa8},
+{0xfc, 0x74, 0x60},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x00, 0x94, 0x00},
+{0xbc, 0xbc, 0xbc},
+{0x00, 0x50, 0x00},
+{0xe0, 0xfc, 0xa0},
+{0x00, 0x00, 0x00},
+{0xfc, 0xd8, 0xa8},
+{0xc8, 0x4c, 0x0c},
+{0x00, 0x00, 0x00},
+{0x00, 0x70, 0xec},
+{0x00, 0x44, 0x00},
+{0x00, 0x00, 0x00},
+{0xe0, 0xfc, 0xa0},
+{0xfc, 0x74, 0xb4},
+{0x88, 0x70, 0x00},
+{0x00, 0x00, 0x00},
diff --git a/palettes/rp2c04002.h b/palettes/rp2c04002.h
new file mode 100644
index 00000000..a6e448c7
--- /dev/null
+++ b/palettes/rp2c04002.h
@@ -0,0 +1,64 @@
+{0x00, 0x00, 0x00},
+{0xfc, 0x98, 0x38},
+{0x88, 0x70, 0x00},
+{0x00, 0x00, 0x00},
+{0xa8, 0xf0, 0xbc},
+{0xfc, 0x74, 0xb4},
+{0x00, 0x00, 0x00},
+{0xa8, 0xe4, 0xfc},
+{0xd8, 0x28, 0x00},
+{0x80, 0x00, 0xf0},
+{0xfc, 0xe4, 0xa0},
+{0xfc, 0xc4, 0xfc},
+{0xfc, 0xfc, 0xfc},
+{0x40, 0x88, 0xfc},
+{0x00, 0x00, 0x00},
+{0x00, 0x3c, 0x14},
+{0x00, 0x00, 0x00},
+{0x3c, 0xbc, 0xfc},
+{0xa4, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x00, 0x90, 0x38},
+{0x80, 0xd0, 0x10},
+{0x00, 0x00, 0x00},
+{0x5c, 0x94, 0xfc},
+{0x00, 0x00, 0x00},
+{0xf4, 0x78, 0xfc},
+{0x00, 0x00, 0x00},
+{0x58, 0xf8, 0x98},
+{0x00, 0x00, 0x00},
+{0x40, 0x2c, 0x00},
+{0x00, 0x00, 0x00},
+{0x44, 0x00, 0x9c},
+{0x00, 0x00, 0x00},
+{0xfc, 0xbc, 0xb0},
+{0xfc, 0x74, 0x60},
+{0xd4, 0xc8, 0xfc},
+{0x00, 0x70, 0xec},
+{0x00, 0x00, 0x00},
+{0xbc, 0xbc, 0xbc},
+{0x00, 0x00, 0xa8},
+{0xbc, 0x00, 0xbc},
+{0x00, 0x00, 0x00},
+{0x74, 0x74, 0x74},
+{0x00, 0x44, 0x00},
+{0x20, 0x38, 0xec},
+{0x00, 0x00, 0x00},
+{0xfc, 0xd8, 0xa8},
+{0xfc, 0xfc, 0xfc},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x4c, 0xdc, 0x48},
+{0xc8, 0x4c, 0x0c},
+{0x18, 0x3c, 0x5c},
+{0x24, 0x18, 0x8c},
+{0xe4, 0x00, 0x58},
+{0x00, 0x94, 0x00},
+{0x00, 0x00, 0x00},
+{0x00, 0xe8, 0xd8},
+{0x7c, 0x08, 0x00},
+{0xfc, 0xd8, 0xa8},
+{0x00, 0x00, 0x00},
+{0xa8, 0x00, 0x10},
+{0x00, 0x50, 0x00},
+{0x74, 0x74, 0x74},
diff --git a/palettes/rp2c04003.h b/palettes/rp2c04003.h
new file mode 100644
index 00000000..71170876
--- /dev/null
+++ b/palettes/rp2c04003.h
@@ -0,0 +1,64 @@
+{0x44, 0x00, 0x9c},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x74, 0x74, 0x74},
+{0x00, 0xa8, 0x00},
+{0xfc, 0xfc, 0xfc},
+{0xa8, 0xe4, 0xfc},
+{0x00, 0x44, 0x00},
+{0x24, 0x18, 0x8c},
+{0x00, 0x00, 0x00},
+{0xfc, 0xbc, 0xb0},
+{0x40, 0x2c, 0x00},
+{0xe4, 0x00, 0x58},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0xfc, 0xfc, 0xfc},
+{0x5c, 0x94, 0xfc},
+{0x00, 0x80, 0x88},
+{0x00, 0x00, 0x00},
+{0x20, 0x38, 0xec},
+{0x00, 0x94, 0x00},
+{0x88, 0x70, 0x00},
+{0xc8, 0x4c, 0x0c},
+{0x00, 0x90, 0x38},
+{0x74, 0x74, 0x74},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0xa8},
+{0xd8, 0x28, 0x00},
+{0xa4, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0xfc, 0xc4, 0xd8},
+{0x40, 0x88, 0xfc},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0xfc, 0xd8, 0xa8},
+{0x00, 0x00, 0x00},
+{0xfc, 0x98, 0x38},
+{0xfc, 0x74, 0x60},
+{0xfc, 0xfc, 0xfc},
+{0x80, 0xd0, 0x10},
+{0x00, 0x00, 0x00},
+{0x3c, 0xbc, 0xfc},
+{0xf4, 0x78, 0xfc},
+{0x00, 0x70, 0xec},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x00, 0xe8, 0xd8},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x7c, 0x08, 0x00},
+{0x4c, 0xdc, 0x48},
+{0xf0, 0xbc, 0x3c},
+{0x00, 0x00, 0x00},
+{0x00, 0x50, 0x00},
+{0x00, 0x00, 0x00},
+{0xc4, 0xd4, 0xfc},
+{0xfc, 0xd8, 0xa8},
+{0x80, 0x00, 0xf0},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x18, 0x3c, 0x5c},
diff --git a/palettes/rp2c05004.h b/palettes/rp2c05004.h
new file mode 100644
index 00000000..a50ed704
--- /dev/null
+++ b/palettes/rp2c05004.h
@@ -0,0 +1,64 @@
+{0x88, 0x70, 0x00},
+{0x00, 0x00, 0x00},
+{0x00, 0x80, 0x88},
+{0xf0, 0xbc, 0x3c},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x24, 0x18, 0x8c},
+{0xc8, 0x4c, 0x0c},
+{0xbc, 0xbc, 0xbc},
+{0x00, 0x00, 0x00},
+{0x4c, 0xdc, 0x48},
+{0x00, 0x00, 0x00},
+{0xfc, 0xbc, 0xb0},
+{0xfc, 0xd8, 0xa8},
+{0x00, 0xa8, 0x00},
+{0x00, 0x00, 0x00},
+{0xfc, 0x74, 0xb4},
+{0x00, 0x00, 0x00},
+{0x20, 0x38, 0xec},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0xfc, 0x74, 0x60},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x5c, 0x94, 0xfc},
+{0x00, 0x94, 0x00},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0xa8, 0xf0, 0xbc},
+{0x3c, 0xbc, 0xfc},
+{0xa8, 0x00, 0x10},
+{0x00, 0x50, 0x00},
+{0x7c, 0x08, 0x00},
+{0x00, 0x00, 0xa8},
+{0x80, 0x00, 0xf0},
+{0x00, 0x00, 0x00},
+{0x74, 0x74, 0x74},
+{0xe4, 0x00, 0x58},
+{0x18, 0x3c, 0x5c},
+{0x00, 0x00, 0x00},
+{0x00, 0x70, 0xec},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0xfc, 0xe4, 0xa0},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0x40, 0x2c, 0x00},
+{0xd8, 0x28, 0x00},
+{0x00, 0x00, 0x00},
+{0x00, 0x00, 0x00},
+{0xfc, 0xfc, 0xfc},
+{0x9c, 0xfc, 0xf0},
+{0x00, 0x00, 0x00},
+{0xfc, 0x98, 0x38},
+{0x00, 0x00, 0x00},
+{0xa8, 0xe4, 0xfc},
+{0x80, 0xd0, 0x10},
+{0x00, 0x00, 0x00},
+{0xfc, 0xfc, 0xfc},
+{0x00, 0x44, 0x00},
diff --git a/ppu.c b/ppu.c
new file mode 100644
index 00000000..705880ac
--- /dev/null
+++ b/ppu.c
@@ -0,0 +1,1428 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 1998 BERO
+ * 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 <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "types.h"
+#include "x6502.h"
+#include "fceu.h"
+#include "ppu.h"
+#include "nsf.h"
+#include "sound.h"
+#include "general.h"
+#include "endian.h"
+#include "memory.h"
+#ifdef WIN32
+#include "ppuview.h"
+#endif
+
+#include "cart.h"
+#include "palette.h"
+#include "state.h"
+#include "video.h"
+#include "input.h"
+
+#define VBlankON (PPU[0]&0x80) /* Generate VBlank NMI */
+#define Sprite16 (PPU[0]&0x20) /* Sprites 8x16/8x8 */
+#define BGAdrHI (PPU[0]&0x10) /* BG pattern adr $0000/$1000 */
+#define SpAdrHI (PPU[0]&0x08) /* Sprite pattern adr $0000/$1000 */
+#define INC32 (PPU[0]&0x04) /* auto increment 1/32 */
+
+#define SpriteON (PPU[1]&0x10) /* Show Sprite */
+#define ScreenON (PPU[1]&0x08) /* Show screen */
+
+#define PPU_status (PPU[2])
+
+#define Pal (PALRAM)
+
+static void FetchSpriteData(void);
+static void FASTAPASS(1) RefreshLine(int lastpixel);
+static void RefreshSprites(void);
+static void CopySprites(uint8 *target);
+
+static void Fixit1(void);
+static uint32 ppulut1[256];
+static uint32 ppulut2[256];
+static uint32 ppulut3[128];
+
+static void makeppulut(void)
+{
+ int x;
+ int y;
+
+ for(x=0;x<256;x++)
+ {
+ ppulut1[x]=0;
+ for(y=0;y<8;y++)
+ ppulut1[x]|=((x>>(7-y))&1)<<(y*4);
+ ppulut2[x]=ppulut1[x]<<1;
+ }
+
+ {
+
+ int cc,xo,pixel;
+
+ for(cc=0;cc<16;cc++)
+ {
+ for(xo=0;xo<8;xo++)
+ {
+ ppulut3[xo|(cc<<3)]=0;
+ for(pixel=0;pixel<8;pixel++)
+ {
+ int shiftr;
+ shiftr=(pixel+xo)/8;
+ shiftr*=2;
+ ppulut3[xo|(cc<<3)]|=(( cc>>shiftr )&3)<<(2+pixel*4);
+ }
+// printf("%08x\n",ppulut3[xo|(cc<<3)]);
+ }
+ }
+
+ }
+}
+
+static int ppudead=1;
+static int kook=0;
+int fceuindbg=0;
+
+int MMC5Hack=0;
+uint32 MMC5HackVROMMask=0;
+uint8 *MMC5HackExNTARAMPtr=0;
+uint8 *MMC5HackVROMPTR=0;
+uint8 MMC5HackCHRMode=0;
+uint8 MMC5HackSPMode=0;
+uint8 MMC5HackSPScroll=0;
+uint8 MMC5HackSPPage=0;
+
+
+uint8 VRAMBuffer=0,PPUGenLatch=0;
+uint8 *vnapage[4];
+uint8 PPUNTARAM=0;
+uint8 PPUCHRRAM=0;
+
+/* Color deemphasis emulation. Joy... */
+static uint8 deemp=0;
+static int deempcnt[8];
+
+void (*GameHBIRQHook)(void), (*GameHBIRQHook2)(void);
+void FP_FASTAPASS(1) (*PPU_hook)(uint32 A);
+
+uint8 vtoggle=0;
+uint8 XOffset=0;
+
+uint32 TempAddr=0,RefreshAddr=0;
+
+static int maxsprites=8;
+
+/* scanline is equal to the current visible scanline we're on. */
+
+int scanline;
+static uint32 scanlines_per_frame;
+
+uint8 PPU[4];
+uint8 PPUSPL;
+uint8 NTARAM[0x800],PALRAM[0x20],SPRAM[0x100],SPRBUF[0x100];
+
+
+#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V)>>10][(V)]
+#define MMC5BGVRAMADR(V) &MMC5BGVPage[(V)>>10][(V)]
+#define VRAMADR(V) &VPage[(V)>>10][(V)]
+
+
+static DECLFR(A2002)
+{
+ uint8 ret;
+
+ FCEUPPU_LineUpdate();
+ ret = PPU_status;
+ ret|=PPUGenLatch&0x1F;
+
+ #ifdef FCEUDEF_DEBUGGER
+ if(!fceuindbg)
+ #endif
+ {
+ vtoggle=0;
+ PPU_status&=0x7F;
+ PPUGenLatch=ret;
+ }
+ return ret;
+}
+
+static DECLFR(A200x) /* Not correct for $2004 reads. */
+{
+ FCEUPPU_LineUpdate();
+ return PPUGenLatch;
+}
+
+/*
+static DECLFR(A2004)
+{
+ uint8 ret;
+
+ FCEUPPU_LineUpdate();
+ ret = SPRAM[PPU[3]];
+
+ if(PPUSPL>=8)
+ {
+ if(PPU[3]>=8)
+ ret = SPRAM[PPU[3]];
+ }
+ else
+ {
+ //printf("$%02x:$%02x\n",PPUSPL,V);
+ ret = SPRAM[PPUSPL];
+ }
+ PPU[3]++;
+ PPUSPL++;
+ PPUGenLatch = ret;
+ printf("%d, %02x\n",scanline,ret);
+ return(ret);
+}
+*/
+static DECLFR(A2007)
+{
+ uint8 ret;
+ uint32 tmp=RefreshAddr&0x3FFF;
+
+ FCEUPPU_LineUpdate();
+
+ ret=VRAMBuffer;
+
+ #ifdef FCEUDEF_DEBUGGER
+ if(!fceuindbg)
+ #endif
+ {
+ if(PPU_hook) PPU_hook(tmp);
+ PPUGenLatch=VRAMBuffer;
+ if(tmp<0x2000)
+ {
+ VRAMBuffer=VPage[tmp>>10][tmp];
+ }
+ else
+ {
+ VRAMBuffer=vnapage[(tmp>>10)&0x3][tmp&0x3FF];
+ }
+ }
+ #ifdef FCEUDEF_DEBUGGER
+ if(!fceuindbg)
+ #endif
+ {
+ if(INC32) RefreshAddr+=32;
+ else RefreshAddr++;
+ if(PPU_hook) PPU_hook(RefreshAddr&0x3fff);
+ }
+ return ret;
+}
+
+static DECLFW(B2000)
+{
+// FCEU_printf("%04x:%02x, (%d) %02x, %02x\n",A,V,scanline,PPU[0],PPU_status);
+
+ FCEUPPU_LineUpdate();
+ PPUGenLatch=V;
+ if(!(PPU[0]&0x80) && (V&0x80) && (PPU_status&0x80))
+ {
+// FCEU_printf("Trigger NMI, %d, %d\n",timestamp,ppudead);
+ TriggerNMI2();
+ }
+ PPU[0]=V;
+ TempAddr&=0xF3FF;
+ TempAddr|=(V&3)<<10;
+}
+
+static DECLFW(B2001)
+{
+ //printf("%04x:$%02x, %d\n",A,V,scanline);
+ FCEUPPU_LineUpdate();
+ PPUGenLatch=V;
+ PPU[1]=V;
+ if(V&0xE0)
+ deemp=V>>5;
+}
+
+static DECLFW(B2002)
+{
+ PPUGenLatch=V;
+}
+
+static DECLFW(B2003)
+{
+ //printf("$%04x:$%02x, %d, %d\n",A,V,timestamp,scanline);
+ PPUGenLatch=V;
+ PPU[3]=V;
+ PPUSPL=V&0x7;
+}
+
+static DECLFW(B2004)
+{
+ //printf("Wr: %04x:$%02x\n",A,V);
+
+ PPUGenLatch=V;
+ if(PPUSPL>=8)
+ {
+ if(PPU[3]>=8)
+ SPRAM[PPU[3]]=V;
+ }
+ else
+ {
+ //printf("$%02x:$%02x\n",PPUSPL,V);
+ SPRAM[PPUSPL]=V;
+ }
+ PPU[3]++;
+ PPUSPL++;
+
+}
+
+static DECLFW(B2005)
+{
+ uint32 tmp=TempAddr;
+ FCEUPPU_LineUpdate();
+ PPUGenLatch=V;
+ if(!vtoggle)
+ {
+ tmp&=0xFFE0;
+ tmp|=V>>3;
+ XOffset=V&7;
+ }
+ else
+ {
+ tmp&=0x8C1F;
+ tmp|=((V&~0x7)<<2);
+ tmp|=(V&7)<<12;
+ }
+ TempAddr=tmp;
+ vtoggle^=1;
+}
+
+
+static DECLFW(B2006)
+{
+ FCEUPPU_LineUpdate();
+
+ PPUGenLatch=V;
+ if(!vtoggle)
+ {
+ TempAddr&=0x00FF;
+ TempAddr|=(V&0x3f)<<8;
+ }
+ else
+ {
+ TempAddr&=0xFF00;
+ TempAddr|=V;
+
+ RefreshAddr=TempAddr;
+ if(PPU_hook)
+ PPU_hook(RefreshAddr);
+ //printf("%d, %04x\n",scanline,RefreshAddr);
+ }
+ vtoggle^=1;
+}
+
+static DECLFW(B2007)
+{
+ uint32 tmp=RefreshAddr&0x3FFF;
+ PPUGenLatch=V;
+ if(tmp>=0x3F00)
+ {
+ // hmmm....
+ if(!(tmp&0xf))
+ PALRAM[0x00]=PALRAM[0x04]=PALRAM[0x08]=PALRAM[0x0C]=V&0x3F;
+ else if(tmp&3) PALRAM[(tmp&0x1f)]=V&0x3f;
+ }
+ else if(tmp<0x2000)
+ {
+ if(PPUCHRRAM&(1<<(tmp>>10)))
+ VPage[tmp>>10][tmp]=V;
+ }
+ else
+ {
+ if(PPUNTARAM&(1<<((tmp&0xF00)>>10)))
+ vnapage[((tmp&0xF00)>>10)][tmp&0x3FF]=V;
+ }
+// FCEU_printf("ppu (%04x) %04x:%04x %d, %d\n",X.PC,RefreshAddr,PPUGenLatch,scanline,timestamp);
+ if(INC32) RefreshAddr+=32;
+ else RefreshAddr++;
+ if(PPU_hook) PPU_hook(RefreshAddr&0x3fff);
+}
+
+static DECLFW(B4014)
+{
+ uint32 t=V<<8;
+ int x;
+
+ for(x=0;x<256;x++)
+ X6502_DMW(0x2004,X6502_DMR(t+x));
+}
+
+#define PAL(c) ((c)+cc)
+
+#define GETLASTPIXEL (PAL?((timestamp*48-linestartts)/15) : ((timestamp*48-linestartts)>>4) )
+
+static uint8 *Pline,*Plinef;
+static int firsttile;
+static int linestartts;
+static int tofix=0;
+
+static void ResetRL(uint8 *target)
+{
+ memset(target,0xFF,256);
+ if(InputScanlineHook)
+ InputScanlineHook(0,0,0,0);
+ Plinef=target;
+ Pline=target;
+ firsttile=0;
+ linestartts=timestamp*48+X.count;
+ tofix=0;
+ FCEUPPU_LineUpdate();
+ tofix=1;
+}
+static uint8 sprlinebuf[256+8];
+
+void FCEUPPU_LineUpdate(void)
+{
+ #ifdef FCEUDEF_DEBUGGER
+ if(!fceuindbg)
+ #endif
+ if(Pline)
+ {
+ int l=GETLASTPIXEL;
+ RefreshLine(l);
+ }
+}
+
+static int tileview=0;
+static int rendis = 0;
+
+void FCEUI_ToggleTileView(void)
+{
+ tileview^=1;
+}
+
+void FCEUI_SetRenderDisable(int sprites, int bg)
+{
+ //printf("%d, %d\n",sprites,bg);
+ if(sprites >= 0)
+ {
+ if(sprites == 2) rendis ^= 1;
+ else rendis = (rendis &~1) | sprites?1:0;
+ }
+ if(bg >= 0)
+ {
+ if(bg == 2) rendis ^= 2;
+ else rendis = (rendis &~2) | bg?2:0;
+ }
+}
+/*
+static void TileView(void)
+{
+ uint8 *P=XBuf+16*256;
+ int bgh;
+ int y;
+ int X1;
+ for(bgh=0;bgh<2;bgh++)
+ for(y=0;y<16*8;y++)
+ for(P=XBuf+bgh*128+(16+y)*256,X1=16;X1;X1--,P+=8)
+ {
+ uint8 *C;
+ register uint8 cc;
+ uint32 vadr;
+
+ vadr=((((16-X1)|((y>>3)<<4))<<4)|(y&7))+bgh*0x1000;
+ //C= ROM+vadr+turt*8192;
+ C = VRAMADR(vadr);
+ //if((vadr+turt*8192)>=524288)
+ //printf("%d ",vadr+turt*8192);
+ cc=0;
+ //#include "pputile.h"
+ }
+}
+*/
+static void CheckSpriteHit(int p);
+
+static void EndRL(void)
+{
+ RefreshLine(272);
+ if(tofix)
+ Fixit1();
+ CheckSpriteHit(272);
+ Pline=0;
+}
+
+static int32 sphitx;
+static uint8 sphitdata;
+
+static void CheckSpriteHit(int p)
+{
+ int l=p-16;
+ int x;
+
+ if(sphitx==0x100) return;
+
+ for(x=sphitx;x<(sphitx+8) && x<l;x++)
+ {
+ if((sphitdata&(0x80>>(x-sphitx))) && !(Plinef[x]&64))
+ {
+ PPU_status|=0x40;
+ //printf("Ha: %d, %d, Hita: %d, %d, %d, %d, %d\n",p,p&~7,scanline,GETLASTPIXEL-16,&Plinef[x],Pline,Pline-Plinef);
+ //printf("%d\n",GETLASTPIXEL-16);
+ //if(Plinef[x] == 0xFF)
+ //printf("PL: %d, %02x\n",scanline, Plinef[x]);
+ sphitx=0x100;
+ break;
+ }
+ }
+}
+static int spork=0; /* spork the world. Any sprites on this line?
+ Then this will be set to 1. Needed for zapper
+ emulation and *gasp* sprite emulation.
+ */
+
+// lasttile is really "second to last tile."
+static void FASTAPASS(1) RefreshLine(int lastpixel)
+{
+ static uint32 pshift[2];
+ static uint32 atlatch;
+ uint32 smorkus=RefreshAddr;
+
+ #define RefreshAddr smorkus
+ uint32 vofs;
+ int X1;
+
+ register uint8 *P=Pline;
+ int lasttile=lastpixel>>3;
+ int numtiles;
+ static int norecurse=0; /* Yeah, recursion would be bad.
+ PPU_hook() functions can call
+ mirroring/chr bank switching functions,
+ which call FCEUPPU_LineUpdate, which call this
+ function. */
+ if(norecurse) return;
+
+ if(sphitx != 0x100 && !(PPU_status&0x40))
+ {
+ if((sphitx < (lastpixel-16)) && !(sphitx < ((lasttile - 2)*8)))
+ {
+ //printf("OK: %d\n",scanline);
+ lasttile++;
+ }
+
+ }
+
+ if(lasttile>34) lasttile=34;
+ numtiles=lasttile-firsttile;
+
+ if(numtiles<=0) return;
+
+ P=Pline;
+
+ vofs=0;
+
+ vofs=((PPU[0]&0x10)<<8) | ((RefreshAddr>>12)&7);
+
+ if(!ScreenON && !SpriteON)
+ {
+ uint32 tem;
+ tem=Pal[0]|(Pal[0]<<8)|(Pal[0]<<16)|(Pal[0]<<24);
+ tem|=0x40404040;
+ FCEU_dwmemset(Pline,tem,numtiles*8);
+ P+=numtiles*8;
+ Pline=P;
+
+ firsttile=lasttile;
+
+ #define TOFIXNUM (272-0x4)
+ if(lastpixel>=TOFIXNUM && tofix)
+ {
+ Fixit1();
+ tofix=0;
+ }
+
+ if(InputScanlineHook && (lastpixel-16)>=0)
+ {
+ InputScanlineHook(Plinef,spork?sprlinebuf:0,linestartts,lasttile*8-16);
+ }
+ return;
+ }
+
+ /* Priority bits, needed for sprite emulation. */
+ Pal[0]|=64;
+ Pal[4]|=64;
+ Pal[8]|=64;
+ Pal[0xC]|=64;
+
+ /* This high-level graphics MMC5 emulation code was written
+ for MMC5 carts in "CL" mode. It's probably not totally
+ correct for carts in "SL" mode.
+ */
+
+ #define PPUT_MMC5
+ if(MMC5Hack && geniestage!=1)
+ {
+ if(MMC5HackCHRMode==0 && (MMC5HackSPMode&0x80))
+ {
+ int tochange=MMC5HackSPMode&0x1F;
+ tochange-=firsttile;
+ for(X1=firsttile;X1<lasttile;X1++)
+ {
+ if((tochange<=0 && MMC5HackSPMode&0x40) || (tochange>0 && !(MMC5HackSPMode&0x40)))
+ {
+ #define PPUT_MMC5SP
+ #include "pputile.h"
+ #undef PPUT_MMC5SP
+ }
+ else
+ {
+ #include "pputile.h"
+ }
+ tochange--;
+ }
+ }
+ else if(MMC5HackCHRMode==1 && (MMC5HackSPMode&0x80))
+ {
+ int tochange=MMC5HackSPMode&0x1F;
+ tochange-=firsttile;
+
+ #define PPUT_MMC5SP
+ #define PPUT_MMC5CHR1
+ for(X1=firsttile;X1<lasttile;X1++)
+ {
+ #include "pputile.h"
+ }
+ #undef PPUT_MMC5CHR1
+ #undef PPUT_MMC5SP
+ }
+ else if(MMC5HackCHRMode==1)
+ {
+ #define PPUT_MMC5CHR1
+ for(X1=firsttile;X1<lasttile;X1++)
+ {
+ #include "pputile.h"
+ }
+ #undef PPUT_MMC5CHR1
+ }
+ else
+ {
+ for(X1=firsttile;X1<lasttile;X1++)
+ {
+ #include "pputile.h"
+ }
+ }
+ }
+ #undef PPUT_MMC5
+ else if(PPU_hook)
+ {
+ norecurse=1;
+ #define PPUT_HOOK
+ for(X1=firsttile;X1<lasttile;X1++)
+ {
+ #include "pputile.h"
+ }
+ #undef PPUT_HOOK
+ norecurse=0;
+ }
+ else
+ {
+ for(X1=firsttile;X1<lasttile;X1++)
+ {
+ #include "pputile.h"
+ }
+ }
+
+ #undef vofs
+ #undef RefreshAddr
+
+ /* Reverse changes made before. */
+ Pal[0]&=63;
+ Pal[4]&=63;
+ Pal[8]&=63;
+ Pal[0xC]&=63;
+
+ RefreshAddr=smorkus;
+ if(firsttile<=2 && 2<lasttile && !(PPU[1]&2))
+ {
+ uint32 tem;
+ tem=Pal[0]|(Pal[0]<<8)|(Pal[0]<<16)|(Pal[0]<<24);
+ tem|=0x40404040;
+ *(uint32 *)Plinef=*(uint32 *)(Plinef+4)=tem;
+ }
+
+ if(!ScreenON)
+ {
+ uint32 tem;
+ int tstart,tcount;
+ tem=Pal[0]|(Pal[0]<<8)|(Pal[0]<<16)|(Pal[0]<<24);
+ tem|=0x40404040;
+
+ tcount=lasttile-firsttile;
+ tstart=firsttile-2;
+ if(tstart<0)
+ {
+ tcount+=tstart;
+ tstart=0;
+ }
+ if(tcount>0)
+ FCEU_dwmemset(Plinef+tstart*8,tem,tcount*8);
+ }
+
+ if(lastpixel>=TOFIXNUM && tofix)
+ {
+ //puts("Fixed");
+ Fixit1();
+ tofix=0;
+ }
+
+ //CheckSpriteHit(lasttile*8); //lasttile*8); //lastpixel);
+
+ CheckSpriteHit(lastpixel); /* This only works right because
+ of a hack earlier in this function.
+ */
+ if(InputScanlineHook && (lastpixel-16)>=0)
+ {
+ InputScanlineHook(Plinef,spork?sprlinebuf:0,linestartts,lasttile*8-16);
+ }
+ Pline=P;
+ firsttile=lasttile;
+}
+
+static INLINE void Fixit2(void)
+{
+ if(ScreenON || SpriteON)
+ {
+ uint32 rad=RefreshAddr;
+ rad&=0xFBE0;
+ rad|=TempAddr&0x041f;
+ RefreshAddr=rad;
+ //PPU_hook(RefreshAddr);
+ //PPU_hook(RefreshAddr,-1);
+ }
+}
+
+static void Fixit1(void)
+{
+ if(ScreenON || SpriteON)
+ {
+ uint32 rad=RefreshAddr;
+
+ if((rad&0x7000)==0x7000)
+ {
+ rad^=0x7000;
+ if((rad&0x3E0)==0x3A0)
+ {
+ rad^=0x3A0;
+ rad^=0x800;
+ }
+ else
+ {
+ if((rad&0x3E0)==0x3e0)
+ rad^=0x3e0;
+ else rad+=0x20;
+ }
+ }
+ else
+ rad+=0x1000;
+ RefreshAddr=rad;
+ //PPU_hook(RefreshAddr); //,-1);
+ }
+}
+
+void MMC5_hb(int); /* Ugh ugh ugh. */
+static void DoLine(void)
+{
+ int x;
+ uint8 *target=XBuf+(scanline<<8);
+
+ if(MMC5Hack && (ScreenON || SpriteON)) MMC5_hb(scanline);
+
+ X6502_Run(256);
+ EndRL();
+
+ if(rendis & 2) /* User asked to not display background data. */
+ {
+ uint32 tem;
+ tem=Pal[0]|(Pal[0]<<8)|(Pal[0]<<16)|(Pal[0]<<24);
+ tem|=0x40404040;
+ FCEU_dwmemset(target,tem,256);
+ }
+
+ if(SpriteON)
+ CopySprites(target);
+
+ if(ScreenON || SpriteON) // Yes, very el-cheapo.
+ {
+ if(PPU[1]&0x01)
+ {
+ for(x=63;x>=0;x--)
+ *(uint32 *)&target[x<<2]=(*(uint32*)&target[x<<2])&0x30303030;
+ }
+ }
+ if((PPU[1]>>5)==0x7)
+ {
+ for(x=63;x>=0;x--)
+ *(uint32 *)&target[x<<2]=((*(uint32*)&target[x<<2])&0x3f3f3f3f)|0xc0c0c0c0;
+ }
+ else if(PPU[1]&0xE0)
+ for(x=63;x>=0;x--)
+ *(uint32 *)&target[x<<2]=(*(uint32*)&target[x<<2])|0x40404040;
+ else
+ for(x=63;x>=0;x--)
+ *(uint32 *)&target[x<<2]=((*(uint32*)&target[x<<2])&0x3f3f3f3f)|0x80808080;
+
+ sphitx=0x100;
+
+ if(ScreenON || SpriteON)
+ FetchSpriteData();
+
+ if(GameHBIRQHook && (ScreenON || SpriteON) && ((PPU[0]&0x38)!=0x18))
+ {
+ X6502_Run(6);
+ Fixit2();
+ X6502_Run(4);
+ GameHBIRQHook();
+ X6502_Run(85-16-10);
+ }
+ else
+ {
+ X6502_Run(6); // Tried 65, caused problems with Slalom(maybe others)
+ Fixit2();
+ X6502_Run(85-6-16);
+
+ // A semi-hack for Star Trek: 25th Anniversary
+ if(GameHBIRQHook && (ScreenON || SpriteON) && ((PPU[0]&0x38)!=0x18))
+ GameHBIRQHook();
+ }
+
+ if(SpriteON)
+ RefreshSprites();
+ if(GameHBIRQHook2 && (ScreenON || SpriteON))
+ GameHBIRQHook2();
+ scanline++;
+ if(scanline<240)
+ {
+ ResetRL(XBuf+(scanline<<8));
+ }
+ X6502_Run(16);
+}
+
+#define V_FLIP 0x80
+#define H_FLIP 0x40
+#define SP_BACK 0x20
+
+typedef struct {
+ uint8 y,no,atr,x;
+} SPR;
+
+typedef struct {
+ uint8 ca[2],atr,x;
+} SPRB;
+
+void FCEUI_DisableSpriteLimitation(int a)
+{
+ maxsprites=a?64:8;
+}
+
+static uint8 numsprites,SpriteBlurp;
+static void FetchSpriteData(void)
+{
+ uint8 ns,sb;
+ SPR *spr;
+ uint8 H;
+ int n;
+ int vofs;
+ uint8 P0=PPU[0];
+
+ spr=(SPR *)SPRAM;
+ H=8;
+
+ ns=sb=0;
+
+ vofs=(unsigned int)(P0&0x8&(((P0&0x20)^0x20)>>2))<<9;
+ H+=(P0&0x20)>>2;
+
+ if(!PPU_hook)
+ for(n=63;n>=0;n--,spr++)
+ {
+ if((unsigned int)(scanline-spr->y)>=H) continue;
+ //printf("%d, %u\n",scanline,(unsigned int)(scanline-spr->y));
+ if(ns<maxsprites)
+ {
+ if(n==63) sb=1;
+
+ {
+ SPRB dst;
+ uint8 *C;
+ int t;
+ unsigned int vadr;
+
+ t = (int)scanline-(spr->y);
+
+ if(Sprite16)
+ vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
+ else
+ vadr = (spr->no<<4)+vofs;
+
+ if(spr->atr&V_FLIP)
+ {
+ vadr+=7;
+ vadr-=t;
+ vadr+=(P0&0x20)>>1;
+ vadr-=t&8;
+ }
+ else
+ {
+ vadr+=t;
+ vadr+=t&8;
+ }
+
+ /* Fix this geniestage hack */
+ if(MMC5Hack && geniestage!=1) C = MMC5SPRVRAMADR(vadr);
+ else C = VRAMADR(vadr);
+
+
+ dst.ca[0]=C[0];
+ dst.ca[1]=C[8];
+ dst.x=spr->x;
+ dst.atr=spr->atr;
+
+ *(uint32 *)&SPRBUF[ns<<2]=*(uint32 *)&dst;
+ }
+
+ ns++;
+ }
+ else
+ {
+ PPU_status|=0x20;
+ break;
+ }
+ }
+ else
+ for(n=63;n>=0;n--,spr++)
+ {
+ if((unsigned int)(scanline-spr->y)>=H) continue;
+
+ if(ns<maxsprites)
+ {
+ if(n==63) sb=1;
+
+ {
+ SPRB dst;
+ uint8 *C;
+ int t;
+ unsigned int vadr;
+
+ t = (int)scanline-(spr->y);
+
+ if(Sprite16)
+ vadr = ((spr->no&1)<<12) + ((spr->no&0xFE)<<4);
+ else
+ vadr = (spr->no<<4)+vofs;
+
+ if(spr->atr&V_FLIP)
+ {
+ vadr+=7;
+ vadr-=t;
+ vadr+=(P0&0x20)>>1;
+ vadr-=t&8;
+ }
+ else
+ {
+ vadr+=t;
+ vadr+=t&8;
+ }
+
+ if(MMC5Hack) C = MMC5SPRVRAMADR(vadr);
+ else C = VRAMADR(vadr);
+ dst.ca[0]=C[0];
+ if(ns<8)
+ {
+ PPU_hook(0x2000);
+ PPU_hook(vadr);
+ }
+ dst.ca[1]=C[8];
+ dst.x=spr->x;
+ dst.atr=spr->atr;
+
+
+ *(uint32 *)&SPRBUF[ns<<2]=*(uint32 *)&dst;
+ }
+
+ ns++;
+ }
+ else
+ {
+ PPU_status|=0x20;
+ break;
+ }
+ }
+ //if(ns>=7)
+ //printf("%d %d\n",scanline,ns);
+ if(ns>8) PPU_status|=0x20; /* Handle case when >8 sprites per
+ scanline option is enabled. */
+ else if(PPU_hook)
+ {
+ for(n=0;n<(8-ns);n++)
+ {
+ PPU_hook(0x2000);
+ PPU_hook(vofs);
+ }
+ }
+ numsprites=ns;
+ SpriteBlurp=sb;
+}
+
+static void RefreshSprites(void)
+{
+ int n;
+ SPRB *spr;
+
+ spork=0;
+ if(!numsprites) return;
+
+ FCEU_dwmemset(sprlinebuf,0x80808080,256);
+ numsprites--;
+ spr = (SPRB*)SPRBUF+numsprites;
+
+ for(n=numsprites;n>=0;n--,spr--)
+ {
+ //#ifdef C80x86
+ //register uint32 pixdata asm ("eax");
+ //register uint8 J, atr;
+ //#else
+ register uint32 pixdata;
+ register uint8 J,atr;
+ //#endif
+
+ int x=spr->x;
+ uint8 *C;
+ uint8 *VB;
+
+ pixdata=ppulut1[spr->ca[0]]|ppulut2[spr->ca[1]];
+ J=spr->ca[0]|spr->ca[1];
+ atr=spr->atr;
+
+ if(J)
+ {
+ if(n==0 && SpriteBlurp && !(PPU_status&0x40))
+ {
+ sphitx=x;
+ sphitdata=J;
+ if(atr&H_FLIP)
+ sphitdata= ((J<<7)&0x80) |
+ ((J<<5)&0x40) |
+ ((J<<3)&0x20) |
+ ((J<<1)&0x10) |
+ ((J>>1)&0x08) |
+ ((J>>3)&0x04) |
+ ((J>>5)&0x02) |
+ ((J>>7)&0x01);
+ }
+
+ C = sprlinebuf+x;
+ VB = (PALRAM+0x10)+((atr&3)<<2);
+
+ if(atr&SP_BACK)
+ {
+ if(atr&H_FLIP)
+ {
+ if(J&0x80) C[7]=VB[pixdata&3]|0x40;
+ pixdata>>=4;
+ if(J&0x40) C[6]=VB[pixdata&3]|0x40;
+ pixdata>>=4;
+ if(J&0x20) C[5]=VB[pixdata&3]|0x40;
+ pixdata>>=4;
+ if(J&0x10) C[4]=VB[pixdata&3]|0x40;
+ pixdata>>=4;
+ if(J&0x08) C[3]=VB[pixdata&3]|0x40;
+ pixdata>>=4;
+ if(J&0x04) C[2]=VB[pixdata&3]|0x40;
+ pixdata>>=4;
+ if(J&0x02) C[1]=VB[pixdata&3]|0x40;
+ pixdata>>=4;
+ if(J&0x01) C[0]=VB[pixdata]|0x40;
+ } else {
+ if(J&0x80) C[0]=VB[pixdata&3]|0x40;
+ pixdata>>=4;
+ if(J&0x40) C[1]=VB[pixdata&3]|0x40;
+ pixdata>>=4;
+ if(J&0x20) C[2]=VB[pixdata&3]|0x40;
+ pixdata>>=4;
+ if(J&0x10) C[3]=VB[pixdata&3]|0x40;
+ pixdata>>=4;
+ if(J&0x08) C[4]=VB[pixdata&3]|0x40;
+ pixdata>>=4;
+ if(J&0x04) C[5]=VB[pixdata&3]|0x40;
+ pixdata>>=4;
+ if(J&0x02) C[6]=VB[pixdata&3]|0x40;
+ pixdata>>=4;
+ if(J&0x01) C[7]=VB[pixdata]|0x40;
+ }
+ } else {
+ if(atr&H_FLIP)
+ {
+ if(J&0x80) C[7]=VB[pixdata&3];
+ pixdata>>=4;
+ if(J&0x40) C[6]=VB[pixdata&3];
+ pixdata>>=4;
+ if(J&0x20) C[5]=VB[pixdata&3];
+ pixdata>>=4;
+ if(J&0x10) C[4]=VB[pixdata&3];
+ pixdata>>=4;
+ if(J&0x08) C[3]=VB[pixdata&3];
+ pixdata>>=4;
+ if(J&0x04) C[2]=VB[pixdata&3];
+ pixdata>>=4;
+ if(J&0x02) C[1]=VB[pixdata&3];
+ pixdata>>=4;
+ if(J&0x01) C[0]=VB[pixdata];
+ }else{
+ if(J&0x80) C[0]=VB[pixdata&3];
+ pixdata>>=4;
+ if(J&0x40) C[1]=VB[pixdata&3];
+ pixdata>>=4;
+ if(J&0x20) C[2]=VB[pixdata&3];
+ pixdata>>=4;
+ if(J&0x10) C[3]=VB[pixdata&3];
+ pixdata>>=4;
+ if(J&0x08) C[4]=VB[pixdata&3];
+ pixdata>>=4;
+ if(J&0x04) C[5]=VB[pixdata&3];
+ pixdata>>=4;
+ if(J&0x02) C[6]=VB[pixdata&3];
+ pixdata>>=4;
+ if(J&0x01) C[7]=VB[pixdata];
+ }
+ }
+ }
+ }
+ SpriteBlurp=0;
+ spork=1;
+}
+
+static void CopySprites(uint8 *target)
+{
+ uint8 n=((PPU[1]&4)^4)<<1;
+ uint8 *P=target;
+
+ if(!spork) return;
+ spork=0;
+
+ if(rendis & 1) return; /* User asked to not display sprites. */
+
+ loopskie:
+ {
+ uint32 t=*(uint32 *)(sprlinebuf+n);
+
+ if(t!=0x80808080)
+ {
+ #ifdef LSB_FIRST
+ if(!(t&0x80))
+ {
+ if(!(t&0x40) || (P[n]&0x40)) // Normal sprite || behind bg sprite
+ P[n]=sprlinebuf[n];
+ }
+
+ if(!(t&0x8000))
+ {
+ if(!(t&0x4000) || (P[n+1]&0x40)) // Normal sprite || behind bg sprite
+ P[n+1]=(sprlinebuf+1)[n];
+ }
+
+ if(!(t&0x800000))
+ {
+ if(!(t&0x400000) || (P[n+2]&0x40)) // Normal sprite || behind bg sprite
+ P[n+2]=(sprlinebuf+2)[n];
+ }
+
+ if(!(t&0x80000000))
+ {
+ if(!(t&0x40000000) || (P[n+3]&0x40)) // Normal sprite || behind bg sprite
+ P[n+3]=(sprlinebuf+3)[n];
+ }
+ #else
+ /* TODO: Simplify */
+ if(!(t&0x80000000))
+ {
+ if(!(t&0x40000000)) // Normal sprite
+ P[n]=sprlinebuf[n];
+ else if(P[n]&64) // behind bg sprite
+ P[n]=sprlinebuf[n];
+ }
+
+ if(!(t&0x800000))
+ {
+ if(!(t&0x400000)) // Normal sprite
+ P[n+1]=(sprlinebuf+1)[n];
+ else if(P[n+1]&64) // behind bg sprite
+ P[n+1]=(sprlinebuf+1)[n];
+ }
+
+ if(!(t&0x8000))
+ {
+ if(!(t&0x4000)) // Normal sprite
+ P[n+2]=(sprlinebuf+2)[n];
+ else if(P[n+2]&64) // behind bg sprite
+ P[n+2]=(sprlinebuf+2)[n];
+ }
+
+ if(!(t&0x80))
+ {
+ if(!(t&0x40)) // Normal sprite
+ P[n+3]=(sprlinebuf+3)[n];
+ else if(P[n+3]&64) // behind bg sprite
+ P[n+3]=(sprlinebuf+3)[n];
+ }
+ #endif
+ }
+ }
+ n+=4;
+ if(n) goto loopskie;
+}
+
+void FCEUPPU_SetVideoSystem(int w)
+{
+ if(w)
+ {
+ scanlines_per_frame=312;
+ FSettings.FirstSLine=FSettings.UsrFirstSLine[1];
+ FSettings.LastSLine=FSettings.UsrLastSLine[1];
+ }
+ else
+ {
+ scanlines_per_frame=262;
+ FSettings.FirstSLine=FSettings.UsrFirstSLine[0];
+ FSettings.LastSLine=FSettings.UsrLastSLine[0];
+ }
+}
+
+void FCEUPPU_Init(void)
+{
+ makeppulut();
+}
+
+void FCEUPPU_Reset(void)
+{
+ VRAMBuffer=PPU[0]=PPU[1]=PPU_status=PPU[3]=0;
+ PPUSPL=0;
+ PPUGenLatch=0;
+ RefreshAddr=TempAddr=0;
+ vtoggle = 0;
+ ppudead = 2;
+ kook = 0;
+
+// XOffset=0;
+}
+
+void FCEUPPU_Power(void)
+{
+ int x;
+
+ memset(NTARAM,0x00,0x800);
+ memset(PALRAM,0x00,0x20);
+ memset(SPRAM,0x00,0x100);
+ FCEUPPU_Reset();
+
+ for(x=0x2000;x<0x4000;x+=8)
+ {
+ ARead[x]=A200x;
+ BWrite[x]=B2000;
+ ARead[x+1]=A200x;
+ BWrite[x+1]=B2001;
+ ARead[x+2]=A2002;
+ BWrite[x+2]=B2002;
+ ARead[x+3]=A200x;
+ BWrite[x+3]=B2003;
+ ARead[x+4]=A200x; //A2004;
+ BWrite[x+4]=B2004;
+ ARead[x+5]=A200x;
+ BWrite[x+5]=B2005;
+ ARead[x+6]=A200x;
+ BWrite[x+6]=B2006;
+ ARead[x+7]=A2007;
+ BWrite[x+7]=B2007;
+ }
+ BWrite[0x4014]=B4014;
+}
+
+
+int FCEUPPU_Loop(int skip)
+{
+ if(ppudead) /* Needed for Knight Rider, possibly others. */
+ {
+ memset(XBuf, 0x80, 256*240);
+ X6502_Run(scanlines_per_frame*(256+85));
+ ppudead--;
+ }
+ else
+ {
+ X6502_Run(256+85);
+ PPU_status |= 0x80;
+ PPU[3]=PPUSPL=0; /* Not sure if this is correct. According
+ to Matt Conte and my own tests, it is. Timing is probably
+ off, though. NOTE: Not having this here
+ breaks a Super Donkey Kong game. */
+ /* I need to figure out the true nature and length
+ of this delay.
+ */
+ X6502_Run(12);
+ if(FCEUGameInfo->type==GIT_NSF)
+ DoNSFFrame();
+ else
+ {
+ if(VBlankON)
+ TriggerNMI();
+ }
+ X6502_Run((scanlines_per_frame-242)*(256+85)-12); //-12);
+ PPU_status&=0x1f;
+ X6502_Run(256);
+
+ {
+ int x;
+
+ if(ScreenON || SpriteON)
+ {
+ if(GameHBIRQHook && ((PPU[0]&0x38)!=0x18))
+ GameHBIRQHook();
+ if(PPU_hook)
+ for(x=0;x<42;x++) {PPU_hook(0x2000); PPU_hook(0);}
+ if(GameHBIRQHook2)
+ GameHBIRQHook2();
+ }
+ X6502_Run(85-16);
+ if(ScreenON || SpriteON)
+ {
+ RefreshAddr=TempAddr;
+ if(PPU_hook) PPU_hook(RefreshAddr&0x3fff);
+ }
+
+ /* Clean this stuff up later. */
+ spork=numsprites=0;
+ ResetRL(XBuf);
+
+ X6502_Run(16-kook);
+ kook ^= 1;
+ }
+ if(FCEUGameInfo->type==GIT_NSF)
+ X6502_Run((256+85)*240);
+ #ifdef FRAMESKIP
+ else if(skip)
+ {
+ int y;
+
+ y=SPRAM[0];
+ y++;
+
+ PPU_status|=0x20; // Fixes "Bee 52". Does it break anything?
+ if(GameHBIRQHook)
+ {
+ X6502_Run(256);
+ for(scanline=0;scanline<240;scanline++)
+ {
+ if(ScreenON || SpriteON)
+ GameHBIRQHook();
+ if(scanline==y && SpriteON) PPU_status|=0x40;
+ X6502_Run((scanline==239)?85:(256+85));
+ }
+ }
+ else if(y<240)
+ {
+ X6502_Run((256+85)*y);
+ if(SpriteON) PPU_status|=0x40; // Quick and very dirty hack.
+ X6502_Run((256+85)*(240-y));
+ }
+ else
+ X6502_Run((256+85)*240);
+ }
+ #endif
+ else
+ {
+ int x,max,maxref;
+
+ deemp=PPU[1]>>5;
+ for(scanline=0;scanline<240;) //scanline is incremented in DoLine. Evil. :/
+ {
+ deempcnt[deemp]++;
+#ifdef WIN32
+ if((PPUViewer) && (scanline == PPUViewScanline)) UpdatePPUView(1);
+#endif
+ DoLine();
+ }
+ if(MMC5Hack && (ScreenON || SpriteON)) MMC5_hb(scanline);
+ for(x=1,max=0,maxref=0;x<7;x++)
+ {
+ if(deempcnt[x]>max)
+ {
+ max=deempcnt[x];
+ maxref=x;
+ }
+ deempcnt[x]=0;
+ }
+ //FCEU_DispMessage("%2x:%2x:%2x:%2x:%2x:%2x:%2x:%2x %d",deempcnt[0],deempcnt[1],deempcnt[2],deempcnt[3],deempcnt[4],deempcnt[5],deempcnt[6],deempcnt[7],maxref);
+ //memset(deempcnt,0,sizeof(deempcnt));
+ SetNESDeemph(maxref,0);
+ }
+ } /* else... to if(ppudead) */
+
+ #ifdef FRAMESKIP
+ if(skip)
+ {
+ FCEU_PutImageDummy();
+ return(0);
+ }
+ else
+ #endif
+ {
+ //if(tileview) TileView();
+ FCEU_PutImage();
+ return(1);
+ }
+}
+
+static uint16 TempAddrT,RefreshAddrT;
+
+void FCEUPPU_LoadState(int version)
+{
+ TempAddr=TempAddrT;
+ RefreshAddr=RefreshAddrT;
+}
+
+SFORMAT FCEUPPU_STATEINFO[]={
+ { NTARAM, 0x800, "NTAR"},
+ { PALRAM, 0x20, "PRAM"},
+ { SPRAM, 0x100, "SPRA"},
+ { PPU, 0x4, "PPUR"},
+ { &kook, 1, "KOOK"},
+ { &ppudead, 1, "DEAD"},
+ { &PPUSPL, 1, "PSPL"},
+ { &XOffset, 1, "XOFF"},
+ { &vtoggle, 1, "VTOG"},
+ { &RefreshAddrT, 2|FCEUSTATE_RLSB, "RADD"},
+ { &TempAddrT, 2|FCEUSTATE_RLSB, "TADD"},
+ { &VRAMBuffer, 1, "VBUF"},
+ { &PPUGenLatch, 1, "PGEN"},
+ { 0 }
+ };
+
+void FCEUPPU_SaveState(void)
+{
+ TempAddrT=TempAddr;
+ RefreshAddrT=RefreshAddr;
+}
diff --git a/ppu.h b/ppu.h
new file mode 100644
index 00000000..217ad458
--- /dev/null
+++ b/ppu.h
@@ -0,0 +1,20 @@
+void FCEUPPU_Init(void);
+void FCEUPPU_Reset(void);
+void FCEUPPU_Power(void);
+int FCEUPPU_Loop(int skip);
+
+void FCEUPPU_LineUpdate();
+void FCEUPPU_SetVideoSystem(int w);
+
+extern void FP_FASTAPASS(1) (*PPU_hook)(uint32 A);
+extern void (*GameHBIRQHook)(void), (*GameHBIRQHook2)(void);
+
+/* For cart.c and banksw.h, mostly */
+extern uint8 NTARAM[0x800],*vnapage[4];
+extern uint8 PPUNTARAM;
+extern uint8 PPUCHRRAM;
+
+void FCEUPPU_SaveState(void);
+void FCEUPPU_LoadState(int version);
+
+extern int scanline;
diff --git a/pputile.h b/pputile.h
new file mode 100644
index 00000000..8123f303
--- /dev/null
+++ b/pputile.h
@@ -0,0 +1,157 @@
+ uint8 *C;
+ register uint8 cc;
+ uint32 vadr;
+
+ #ifndef PPUT_MMC5SP
+ register uint8 zz;
+ #else
+ uint8 xs,ys;
+ xs=X1;
+ ys=((scanline>>3)+MMC5HackSPScroll)&0x1F;
+ if(ys>=0x1E) ys-=0x1E;
+ #endif
+
+ if(X1>=2)
+ {
+ uint8 *S=PALRAM;
+ uint32 pixdata;
+
+ pixdata=ppulut1[(pshift[0]>>(8-XOffset))&0xFF]|ppulut2[(pshift[1]>>(8-XOffset))&0xFF];
+
+ pixdata|=ppulut3[XOffset|(atlatch<<3)];
+ //printf("%02x ",ppulut3[XOffset|(atlatch<<3)]);
+
+ #ifdef C80x86
+ asm volatile(
+ "movl %%ebx,%%eax\n\t"
+ "andl $15,%%eax\n\t"
+ "movb (%%esi,%%eax),%%cl\n\t"
+ "shrl $4, %%ebx\n\t"
+ "movb %%cl, (%%edi)\n\t"
+
+ "movl %%ebx,%%eax\n\t"
+ "andl $15,%%eax\n\t"
+ "movb (%%esi,%%eax),%%cl\n\t"
+ "shrl $4, %%ebx\n\t"
+ "movb %%cl, 1(%%edi)\n\t"
+
+ "movl %%ebx,%%eax\n\t"
+ "andl $15,%%eax\n\t"
+ "movb (%%esi,%%eax),%%cl\n\t"
+ "shrl $4, %%ebx\n\t"
+ "movb %%cl, 2(%%edi)\n\t"
+
+ "movl %%ebx,%%eax\n\t"
+ "andl $15,%%eax\n\t"
+ "movb (%%esi,%%eax),%%cl\n\t"
+ "shrl $4, %%ebx\n\t"
+ "movb %%cl, 3(%%edi)\n\t"
+
+ "movl %%ebx,%%eax\n\t"
+ "andl $15,%%eax\n\t"
+ "movb (%%esi,%%eax),%%cl\n\t"
+ "shrl $4, %%ebx\n\t"
+ "movb %%cl, 4(%%edi)\n\t"
+
+ "movl %%ebx,%%eax\n\t"
+ "andl $15,%%eax\n\t"
+ "movb (%%esi,%%eax),%%cl\n\t"
+ "shrl $4, %%ebx\n\t"
+ "movb %%cl, 5(%%edi)\n\t"
+
+ "movl %%ebx,%%eax\n\t"
+ "andl $15,%%eax\n\t"
+ "movb (%%esi,%%eax),%%cl\n\t"
+ "shrl $4, %%ebx\n\t"
+ "movb %%cl, 6(%%edi)\n\t"
+
+ //"movl %%ebx,%%eax\n\t"
+ //"andl $15,%%eax\n\t"
+ //"movb (%%esi,%%eax),%%cl\n\t"
+ //"movb %%cl, 7(%%edi)\n\t"
+ "movb (%%esi, %%ebx),%%cl\n\t"
+ "movb %%cl, 7(%%edi)\n\t"
+ :
+ : "S" (S), "D" (P), "b" (pixdata)
+ : "eax", "cl" );
+ #else
+ P[0]=S[pixdata&0xF];
+ pixdata>>=4;
+ P[1]=S[pixdata&0xF];
+ pixdata>>=4;
+ P[2]=S[pixdata&0xF];
+ pixdata>>=4;
+ P[3]=S[pixdata&0xF];
+ pixdata>>=4;
+ P[4]=S[pixdata&0xF];
+ pixdata>>=4;
+ P[5]=S[pixdata&0xF];
+ pixdata>>=4;
+ P[6]=S[pixdata&0xF];
+ pixdata>>=4;
+ P[7]=S[pixdata&0xF];
+ #endif
+ P+=8;
+ }
+
+ #ifdef PPUT_MMC5SP
+ vadr=(MMC5HackExNTARAMPtr[xs|(ys<<5)]<<4)+(vofs&7);
+ #else
+ zz=RefreshAddr&0x1F;
+ C=vnapage[(RefreshAddr>>10)&3];
+ vadr=(C[RefreshAddr&0x3ff]<<4)+vofs; /* Fetch name table byte. */
+ #endif
+
+ #ifdef PPUT_HOOK
+ PPU_hook(0x2000|(RefreshAddr&0xfff));
+ #endif
+
+ #ifdef PPUT_MMC5SP
+ cc=MMC5HackExNTARAMPtr[0x3c0+(xs>>2)+((ys&0x1C)<<1)];
+ cc=((cc >> ((xs&2) + ((ys&0x2)<<1))) &3);
+ #else
+ #ifdef PPUT_MMC5CHR1
+ cc=(MMC5HackExNTARAMPtr[RefreshAddr & 0x3ff] & 0xC0)>>6;
+ #else
+ cc=C[0x3c0+(zz>>2)+((RefreshAddr&0x380)>>4)]; /* Fetch attribute table byte. */
+ cc=((cc >> ((zz&2) + ((RefreshAddr&0x40)>>4))) &3);
+ #endif
+ #endif
+
+ atlatch>>=2;
+ atlatch|=cc<<2;
+
+ pshift[0]<<=8;
+ pshift[1]<<=8;
+
+ #ifdef PPUT_MMC5SP
+ C = MMC5HackVROMPTR+vadr;
+ C += ((MMC5HackSPPage & 0x3f & MMC5HackVROMMask) << 12);
+ #else
+ #ifdef PPUT_MMC5CHR1
+ C = MMC5HackVROMPTR;
+ C += (((MMC5HackExNTARAMPtr[RefreshAddr & 0x3ff]) & 0x3f &
+ MMC5HackVROMMask) << 12) + (vadr & 0xfff);
+ #elif defined(PPUT_MMC5)
+ C=MMC5BGVRAMADR(vadr);
+ #else
+ C = VRAMADR(vadr);
+ #endif
+ #endif
+
+ #ifdef PPUT_HOOK
+ PPU_hook(vadr);
+ #endif
+
+ pshift[0]|=C[0];
+ pshift[1]|=C[8];
+
+ if((RefreshAddr&0x1f)==0x1f)
+ RefreshAddr^=0x41F;
+ else
+ RefreshAddr++;
+
+ #ifdef PPUT_HOOK
+ PPU_hook(0x2000|(RefreshAddr&0xfff));
+ #endif
+
diff --git a/ppuview.h b/ppuview.h
new file mode 100644
index 00000000..55c44ba0
--- /dev/null
+++ b/ppuview.h
@@ -0,0 +1,6 @@
+extern int PPUViewScanline;
+extern int PPUViewer;
+extern int scanline;
+
+void UpdatePPUView(int refreshchr);
+
diff --git a/sound.c b/sound.c
new file mode 100644
index 00000000..d1ed5268
--- /dev/null
+++ b/sound.c
@@ -0,0 +1,1280 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <string.h>
+
+#include "types.h"
+#include "x6502.h"
+
+#include "fceu.h"
+#include "sound.h"
+#include "filter.h"
+#include "state.h"
+#include "wave.h"
+
+static uint32 wlookup1[32];
+static uint32 wlookup2[203];
+
+int32 Wave[2048+512];
+int32 WaveHi[40000];
+int32 WaveFinal[2048+512];
+
+EXPSOUND GameExpSound={0,0,0};
+
+static uint8 TriCount=0;
+static uint8 TriMode=0;
+
+static int32 tristep=0;
+
+static int32 wlcount[4]={0,0,0,0}; /* Wave length counters. */
+
+static uint8 IRQFrameMode=0; /* $4017 / xx000000 */
+static uint8 PSG[0x10];
+static uint8 RawDALatch=0; /* $4011 0xxxxxxx */
+
+uint8 EnabledChannels=0; /* Byte written to $4015 */
+
+typedef struct {
+ uint8 Speed;
+ uint8 Mode; /* Fixed volume(1), and loop(2) */
+ uint8 DecCountTo1;
+ uint8 decvolume;
+ int reloaddec;
+} ENVUNIT;
+
+static ENVUNIT EnvUnits[3];
+
+static const int RectDuties[4]={1,2,4,6};
+
+static int32 RectDutyCount[2];
+static uint8 sweepon[2];
+static int32 curfreq[2];
+static uint8 SweepCount[2];
+
+static uint16 nreg=0;
+
+static uint8 fcnt=0;
+static int32 fhcnt=0;
+static int32 fhinc=0;
+
+uint32 soundtsoffs=0;
+
+/* Variables exclusively for low-quality sound. */
+int32 nesincsize=0;
+uint32 soundtsinc=0;
+uint32 soundtsi=0;
+static int32 sqacc[2];
+/* LQ variables segment ends. */
+
+static int32 lengthcount[4];
+static const uint8 lengthtable[0x20]=
+{
+ 0x5*2,0x7f*2,0xA*2,0x1*2,0x14*2,0x2*2,0x28*2,0x3*2,0x50*2,0x4*2,0x1E*2,0x5*2,0x7*2,0x6*2,0x0E*2,0x7*2,
+ 0x6*2,0x08*2,0xC*2,0x9*2,0x18*2,0xa*2,0x30*2,0xb*2,0x60*2,0xc*2,0x24*2,0xd*2,0x8*2,0xe*2,0x10*2,0xf*2
+};
+
+static const uint32 NoiseFreqTable[0x10]=
+{
+ 2,4,8,0x10,0x20,0x30,0x40,0x50,0x65,0x7f,0xbe,0xfe,0x17d,0x1fc,0x3f9,0x7f2
+};
+
+static const uint32 NTSCDMCTable[0x10]=
+{
+ 428,380,340,320,286,254,226,214,
+ 190,160,142,128,106, 84 ,72,54
+};
+
+static const uint32 PALDMCTable[0x10]=
+{
+ 397, 353, 315, 297, 265, 235, 209, 198,
+ 176, 148, 131, 118, 98, 78, 66, 50,
+};
+
+// $4010 - Frequency
+// $4011 - Actual data outputted
+// $4012 - Address register: $c000 + V*64
+// $4013 - Size register: Size in bytes = (V+1)*64
+
+/*static*/ int32 DMCacc=1;
+static int32 DMCPeriod=0;
+/*static*/ uint8 DMCBitCount=0;
+
+static uint8 DMCAddressLatch=0,DMCSizeLatch=0; /* writes to 4012 and 4013 */
+static uint8 DMCFormat=0; /* Write to $4010 */
+
+static uint32 DMCAddress=0;
+static int32 DMCSize=0;
+static uint8 DMCShift=0;
+static uint8 SIRQStat=0;
+
+static char DMCHaveDMA=0;
+static uint8 DMCDMABuf=0;
+static char DMCHaveSample=0;
+
+static void Dummyfunc(void) {};
+static void (*DoNoise)(void)=Dummyfunc;
+static void (*DoTriangle)(void)=Dummyfunc;
+static void (*DoPCM)(void)=Dummyfunc;
+static void (*DoSQ1)(void)=Dummyfunc;
+static void (*DoSQ2)(void)=Dummyfunc;
+
+static uint32 ChannelBC[5];
+
+static void LoadDMCPeriod(uint8 V)
+{
+ if(PAL)
+ DMCPeriod=PALDMCTable[V];
+ else
+ DMCPeriod=NTSCDMCTable[V];
+}
+
+static void PrepDPCM()
+{
+ DMCAddress=0x4000+(DMCAddressLatch<<6);
+ DMCSize=(DMCSizeLatch<<4)+1;
+}
+
+/* Instantaneous? Maybe the new freq value is being calculated all of the time... */
+
+static int FASTAPASS(2) CheckFreq(uint32 cf, uint8 sr)
+{
+ uint32 mod;
+ if(!(sr&0x8))
+ {
+ mod=cf>>(sr&7);
+ if((mod+cf)&0x800)
+ return(0);
+ }
+ return(1);
+}
+
+static void SQReload(int x, uint8 V)
+{
+ if(EnabledChannels&(1<<x))
+ {
+ if(x)
+ DoSQ2();
+ else
+ DoSQ1();
+ lengthcount[x]=lengthtable[(V>>3)&0x1f];
+ }
+
+ sweepon[x]=PSG[(x<<2)|1]&0x80;
+ curfreq[x]=PSG[(x<<2)|0x2]|((V&7)<<8);
+ SweepCount[x]=((PSG[(x<<2)|0x1]>>4)&7)+1;
+
+ RectDutyCount[x]=7;
+ EnvUnits[x].reloaddec=1;
+ //reloadfreq[x]=1;
+}
+
+static DECLFW(Write_PSG)
+{
+ A&=0x1F;
+ switch(A)
+ {
+ case 0x0:DoSQ1();
+ EnvUnits[0].Mode=(V&0x30)>>4;
+ EnvUnits[0].Speed=(V&0xF);
+ break;
+ case 0x1:
+ sweepon[0]=V&0x80;
+ break;
+ case 0x2:
+ DoSQ1();
+ curfreq[0]&=0xFF00;
+ curfreq[0]|=V;
+ break;
+ case 0x3:
+ SQReload(0,V);
+ break;
+ case 0x4:
+ DoSQ2();
+ EnvUnits[1].Mode=(V&0x30)>>4;
+ EnvUnits[1].Speed=(V&0xF);
+ break;
+ case 0x5:
+ sweepon[1]=V&0x80;
+ break;
+ case 0x6:DoSQ2();
+ curfreq[1]&=0xFF00;
+ curfreq[1]|=V;
+ break;
+ case 0x7:
+ SQReload(1,V);
+ break;
+ case 0xa:DoTriangle();
+ break;
+ case 0xb:
+ DoTriangle();
+ if(EnabledChannels&0x4)
+ lengthcount[2]=lengthtable[(V>>3)&0x1f];
+ TriMode=1; // Load mode
+ break;
+ case 0xC:DoNoise();
+ EnvUnits[2].Mode=(V&0x30)>>4;
+ EnvUnits[2].Speed=(V&0xF);
+ break;
+ case 0xE:DoNoise();
+ break;
+ case 0xF:
+ DoNoise();
+ if(EnabledChannels&0x8)
+ lengthcount[3]=lengthtable[(V>>3)&0x1f];
+ EnvUnits[2].reloaddec=1;
+ break;
+ case 0x10:DoPCM();
+ LoadDMCPeriod(V&0xF);
+
+ if(SIRQStat&0x80)
+ {
+ if(!(V&0x80))
+ {
+ X6502_IRQEnd(FCEU_IQDPCM);
+ SIRQStat&=~0x80;
+ }
+ else X6502_IRQBegin(FCEU_IQDPCM);
+ }
+ break;
+ }
+ PSG[A]=V;
+}
+
+static DECLFW(Write_DMCRegs)
+{
+ A&=0xF;
+
+ switch(A)
+ {
+ case 0x00:DoPCM();
+ LoadDMCPeriod(V&0xF);
+
+ if(SIRQStat&0x80)
+ {
+ if(!(V&0x80))
+ {
+ X6502_IRQEnd(FCEU_IQDPCM);
+ SIRQStat&=~0x80;
+ }
+ else X6502_IRQBegin(FCEU_IQDPCM);
+ }
+ DMCFormat=V;
+ break;
+ case 0x01:DoPCM();
+ RawDALatch=V&0x7F;
+ break;
+ case 0x02:DMCAddressLatch=V;break;
+ case 0x03:DMCSizeLatch=V;break;
+ }
+
+
+}
+
+static DECLFW(StatusWrite)
+{
+ int x;
+
+ DoSQ1();
+ DoSQ2();
+ DoTriangle();
+ DoNoise();
+ DoPCM();
+ for(x=0;x<4;x++)
+ if(!(V&(1<<x))) lengthcount[x]=0; /* Force length counters to 0. */
+
+ if(V&0x10)
+ {
+ if(!DMCSize)
+ PrepDPCM();
+ }
+ else
+ {
+ DMCSize=0;
+ }
+ SIRQStat&=~0x80;
+ X6502_IRQEnd(FCEU_IQDPCM);
+ EnabledChannels=V&0x1F;
+}
+
+static DECLFR(StatusRead)
+{
+ int x;
+ uint8 ret;
+
+ ret=SIRQStat;
+
+ for(x=0;x<4;x++) ret|=lengthcount[x]?(1<<x):0;
+ if(DMCSize) ret|=0x10;
+
+ #ifdef FCEUDEF_DEBUGGER
+ if(!fceuindbg)
+ #endif
+ {
+ SIRQStat&=~0x40;
+ X6502_IRQEnd(FCEU_IQFCOUNT);
+ }
+ return ret;
+}
+
+static void FASTAPASS(1) FrameSoundStuff(int V)
+{
+ int P;
+
+ DoSQ1();
+ DoSQ2();
+ DoNoise();
+ DoTriangle();
+
+ if(!(V&1)) /* Envelope decay, linear counter, length counter, freq sweep */
+ {
+ if(!(PSG[8]&0x80))
+ if(lengthcount[2]>0)
+ lengthcount[2]--;
+
+ if(!(PSG[0xC]&0x20)) /* Make sure loop flag is not set. */
+ if(lengthcount[3]>0)
+ lengthcount[3]--;
+
+ for(P=0;P<2;P++)
+ {
+ if(!(PSG[P<<2]&0x20)) /* Make sure loop flag is not set. */
+ if(lengthcount[P]>0)
+ lengthcount[P]--;
+
+ /* Frequency Sweep Code Here */
+ /* xxxx 0000 */
+ /* xxxx = hz. 120/(x+1)*/
+ if(sweepon[P])
+ {
+ int32 mod=0;
+
+ if(SweepCount[P]>0) SweepCount[P]--;
+ if(SweepCount[P]<=0)
+ {
+ SweepCount[P]=((PSG[(P<<2)+0x1]>>4)&7)+1; //+1;
+ if(PSG[(P<<2)+0x1]&0x8)
+ {
+ mod-=(P^1)+((curfreq[P])>>(PSG[(P<<2)+0x1]&7));
+ if(curfreq[P] && (PSG[(P<<2)+0x1]&7)/* && sweepon[P]&0x80*/)
+ {
+ curfreq[P]+=mod;
+ }
+ }
+ else
+ {
+ mod=curfreq[P]>>(PSG[(P<<2)+0x1]&7);
+ if((mod+curfreq[P])&0x800)
+ {
+ sweepon[P]=0;
+ curfreq[P]=0;
+ }
+ else
+ {
+ if(curfreq[P] && (PSG[(P<<2)+0x1]&7)/* && sweepon[P]&0x80*/)
+ {
+ curfreq[P]+=mod;
+ }
+ }
+ }
+ }
+ }
+ else /* Sweeping is disabled: */
+ {
+ //curfreq[P]&=0xFF00;
+ //curfreq[P]|=PSG[(P<<2)|0x2]; //|((PSG[(P<<2)|3]&7)<<8);
+ }
+ }
+ }
+
+ /* Now do envelope decay + linear counter. */
+
+ if(TriMode) // In load mode?
+ TriCount=PSG[0x8]&0x7F;
+ else if(TriCount)
+ TriCount--;
+
+ if(!(PSG[0x8]&0x80))
+ TriMode=0;
+
+ for(P=0;P<3;P++)
+ {
+ if(EnvUnits[P].reloaddec)
+ {
+ EnvUnits[P].decvolume=0xF;
+ EnvUnits[P].DecCountTo1=EnvUnits[P].Speed+1;
+ EnvUnits[P].reloaddec=0;
+ continue;
+ }
+
+ if(EnvUnits[P].DecCountTo1>0) EnvUnits[P].DecCountTo1--;
+ if(EnvUnits[P].DecCountTo1==0)
+ {
+ EnvUnits[P].DecCountTo1=EnvUnits[P].Speed+1;
+ if(EnvUnits[P].decvolume || (EnvUnits[P].Mode&0x2))
+ {
+ EnvUnits[P].decvolume--;
+ EnvUnits[P].decvolume&=0xF;
+ }
+ }
+ }
+}
+
+void FrameSoundUpdate(void)
+{
+ // Linear counter: Bit 0-6 of $4008
+ // Length counter: Bit 4-7 of $4003, $4007, $400b, $400f
+
+ if(!fcnt && !(IRQFrameMode&0x3))
+ {
+ SIRQStat|=0x40;
+ X6502_IRQBegin(FCEU_IQFCOUNT);
+ }
+
+ if(fcnt==3)
+ {
+ if(IRQFrameMode&0x2)
+ fhcnt+=fhinc;
+ }
+ FrameSoundStuff(fcnt);
+ fcnt=(fcnt+1)&3;
+}
+
+
+static INLINE void tester(void)
+{
+ if(DMCBitCount==0)
+ {
+ if(!DMCHaveDMA)
+ DMCHaveSample=0;
+ else
+ {
+ DMCHaveSample=1;
+ DMCShift=DMCDMABuf;
+ DMCHaveDMA=0;
+ }
+ }
+}
+
+static INLINE void DMCDMA(void)
+{
+ if(DMCSize && !DMCHaveDMA)
+ {
+ X6502_DMR(0x8000+DMCAddress);
+ X6502_DMR(0x8000+DMCAddress);
+ X6502_DMR(0x8000+DMCAddress);
+ DMCDMABuf=X6502_DMR(0x8000+DMCAddress);
+ DMCHaveDMA=1;
+ DMCAddress=(DMCAddress+1)&0x7fff;
+ DMCSize--;
+ if(!DMCSize)
+ {
+ if(DMCFormat&0x40)
+ PrepDPCM();
+ else
+ {
+ SIRQStat|=0x80;
+ if(DMCFormat&0x80)
+ X6502_IRQBegin(FCEU_IQDPCM);
+ }
+ }
+ }
+}
+
+void FASTAPASS(1) FCEU_SoundCPUHook(int cycles)
+{
+fhcnt-=cycles*48;
+ if(fhcnt<=0)
+ {
+ FrameSoundUpdate();
+ fhcnt+=fhinc;
+ }
+
+ DMCDMA();
+ DMCacc-=cycles;
+
+ while(DMCacc<=0)
+ {
+ if(DMCHaveSample)
+ {
+ uint8 bah=RawDALatch;
+ int t=((DMCShift&1)<<2)-2;
+
+ /* Unbelievably ugly hack */
+ if(FSettings.SndRate)
+ {
+ soundtsoffs+=DMCacc;
+ DoPCM();
+ soundtsoffs-=DMCacc;
+ }
+ RawDALatch+=t;
+ if(RawDALatch&0x80)
+ RawDALatch=bah;
+ }
+
+ DMCacc+=DMCPeriod;
+ DMCBitCount=(DMCBitCount+1)&7;
+ DMCShift>>=1;
+ tester();
+ }
+}
+
+void RDoPCM(void)
+{
+ int32 V;
+
+ for(V=ChannelBC[4];V<SOUNDTS;V++)
+ WaveHi[V]+=RawDALatch<<16;
+
+ ChannelBC[4]=SOUNDTS;
+}
+
+/* This has the correct phase. Don't mess with it. */
+static INLINE void RDoSQ(int x)
+{
+ int32 V;
+ int32 amp;
+ int32 rthresh;
+ int32 *D;
+ int32 currdc;
+ int32 cf;
+ int32 rc;
+
+ if(curfreq[x]<8 || curfreq[x]>0x7ff)
+ goto endit;
+ if(!CheckFreq(curfreq[x],PSG[(x<<2)|0x1]))
+ goto endit;
+ if(!lengthcount[x])
+ goto endit;
+
+ if(EnvUnits[x].Mode&0x1)
+ amp=EnvUnits[x].Speed;
+ else
+ amp=EnvUnits[x].decvolume;
+// printf("%d\n",amp);
+ amp<<=24;
+
+ rthresh=RectDuties[(PSG[(x<<2)]&0xC0)>>6];
+
+ D=&WaveHi[ChannelBC[x]];
+ V=SOUNDTS-ChannelBC[x];
+
+ currdc=RectDutyCount[x];
+ cf=(curfreq[x]+1)*2;
+ rc=wlcount[x];
+
+ while(V>0)
+ {
+ if(currdc<rthresh)
+ *D+=amp;
+ rc--;
+ if(!rc)
+ {
+ rc=cf;
+ currdc=(currdc+1)&7;
+ }
+ V--;
+ D++;
+ }
+
+ RectDutyCount[x]=currdc;
+ wlcount[x]=rc;
+
+ endit:
+ ChannelBC[x]=SOUNDTS;
+}
+
+static void RDoSQ1(void)
+{
+ RDoSQ(0);
+}
+
+static void RDoSQ2(void)
+{
+ RDoSQ(1);
+}
+
+static void RDoSQLQ(void)
+{
+ int32 start,end;
+ int32 V;
+ int32 amp[2];
+ int32 rthresh[2];
+ int32 freq[2];
+ int x;
+ int32 inie[2];
+
+ int32 ttable[2][8];
+ int32 totalout;
+
+ start=ChannelBC[0];
+ end=(SOUNDTS<<16)/soundtsinc;
+ if(end<=start) return;
+ ChannelBC[0]=end;
+
+ for(x=0;x<2;x++)
+ {
+ int y;
+
+ inie[x]=nesincsize;
+ if(curfreq[x]<8 || curfreq[x]>0x7ff)
+ inie[x]=0;
+ if(!CheckFreq(curfreq[x],PSG[(x<<2)|0x1]))
+ inie[x]=0;
+ if(!lengthcount[x])
+ inie[x]=0;
+
+ if(EnvUnits[x].Mode&0x1)
+ amp[x]=EnvUnits[x].Speed;
+ else
+ amp[x]=EnvUnits[x].decvolume;
+
+ if(!inie[x]) amp[x]=0; /* Correct? Buzzing in MM2, others otherwise... */
+
+ rthresh[x]=RectDuties[(PSG[x*4]&0xC0)>>6];
+
+ for(y=0;y<8;y++)
+ {
+ if(y < rthresh[x])
+ ttable[x][y] = amp[x];
+ else
+ ttable[x][y] = 0;
+ }
+ freq[x]=(curfreq[x]+1)<<1;
+ freq[x]<<=17;
+ }
+
+ totalout = wlookup1[ ttable[0][RectDutyCount[0]] + ttable[1][RectDutyCount[1]] ];
+
+ if(!inie[0] && !inie[1])
+ {
+ for(V=start;V<end;V++)
+ Wave[V>>4]+=totalout;
+ }
+ else
+ for(V=start;V<end;V++)
+ {
+ //int tmpamp=0;
+ //if(RectDutyCount[0]<rthresh[0])
+ // tmpamp=amp[0];
+ //if(RectDutyCount[1]<rthresh[1])
+ // tmpamp+=amp[1];
+ //tmpamp=wlookup1[tmpamp];
+ //tmpamp = wlookup1[ ttable[0][RectDutyCount[0]] + ttable[1][RectDutyCount[1]] ];
+
+ Wave[V>>4]+=totalout; //tmpamp;
+
+ sqacc[0]-=inie[0];
+ sqacc[1]-=inie[1];
+
+ if(sqacc[0]<=0)
+ {
+ rea:
+ sqacc[0]+=freq[0];
+ RectDutyCount[0]=(RectDutyCount[0]+1)&7;
+ if(sqacc[0]<=0) goto rea;
+ totalout = wlookup1[ ttable[0][RectDutyCount[0]] + ttable[1][RectDutyCount[1]] ];
+ }
+
+ if(sqacc[1]<=0)
+ {
+ rea2:
+ sqacc[1]+=freq[1];
+ RectDutyCount[1]=(RectDutyCount[1]+1)&7;
+ if(sqacc[1]<=0) goto rea2;
+ totalout = wlookup1[ ttable[0][RectDutyCount[0]] + ttable[1][RectDutyCount[1]] ];
+ }
+ }
+}
+
+static void RDoTriangle(void)
+{
+ int32 V;
+ int32 tcout;
+
+ tcout=(tristep&0xF);
+ if(!(tristep&0x10)) tcout^=0xF;
+ tcout=(tcout*3) << 16; //(tcout<<1);
+
+ if(!lengthcount[2] || !TriCount)
+ { /* Counter is halted, but we still need to output. */
+ int32 *start = &WaveHi[ChannelBC[2]];
+ int32 count = SOUNDTS - ChannelBC[2];
+ while(count--)
+ {
+ *start += tcout;
+ start++;
+ }
+ //for(V=ChannelBC[2];V<SOUNDTS;V++)
+ // WaveHi[V]+=tcout;
+ }
+ else
+ for(V=ChannelBC[2];V<SOUNDTS;V++)
+ {
+ WaveHi[V]+=tcout;
+ wlcount[2]--;
+ if(!wlcount[2])
+ {
+ wlcount[2]=(PSG[0xa]|((PSG[0xb]&7)<<8))+1;
+ tristep++;
+ tcout=(tristep&0xF);
+ if(!(tristep&0x10)) tcout^=0xF;
+ tcout=(tcout*3) << 16;
+ }
+ }
+
+ ChannelBC[2]=SOUNDTS;
+}
+
+static void RDoTriangleNoisePCMLQ(void)
+{
+ static uint32 tcout=0;
+ static int32 triacc=0;
+ static int32 noiseacc=0;
+
+ int32 V;
+ int32 start,end;
+ int32 freq[2];
+ int32 inie[2];
+ uint32 amptab[2];
+ uint32 noiseout;
+ int nshift;
+
+ int32 totalout;
+
+ start=ChannelBC[2];
+ end=(SOUNDTS<<16)/soundtsinc;
+ if(end<=start) return;
+ ChannelBC[2]=end;
+
+ inie[0]=inie[1]=nesincsize;
+
+ freq[0]=(((PSG[0xa]|((PSG[0xb]&7)<<8))+1));
+
+ if(!lengthcount[2] || !TriCount || freq[0]<=4)
+ inie[0]=0;
+
+ freq[0]<<=17;
+ if(EnvUnits[2].Mode&0x1)
+ amptab[0]=EnvUnits[2].Speed;
+ else
+ amptab[0]=EnvUnits[2].decvolume;
+ amptab[1]=0;
+ amptab[0]<<=1;
+
+ if(!lengthcount[3])
+ amptab[0]=inie[1]=0; /* Quick hack speedup, set inie[1] to 0 */
+
+ noiseout=amptab[(nreg>>0xe)&1];
+
+ if(PSG[0xE]&0x80)
+ nshift=8;
+ else
+ nshift=13;
+
+
+ totalout = wlookup2[tcout+noiseout+RawDALatch];
+
+ if(inie[0] && inie[1])
+ {
+ for(V=start;V<end;V++)
+ {
+ Wave[V>>4]+=totalout;
+
+ triacc-=inie[0];
+ noiseacc-=inie[1];
+
+ if(triacc<=0)
+ {
+ rea:
+ triacc+=freq[0]; //t;
+ tristep=(tristep+1)&0x1F;
+ if(triacc<=0) goto rea;
+ tcout=(tristep&0xF);
+ if(!(tristep&0x10)) tcout^=0xF;
+ tcout=tcout*3;
+ totalout = wlookup2[tcout+noiseout+RawDALatch];
+ }
+
+ if(noiseacc<=0)
+ {
+ rea2:
+ noiseacc+=NoiseFreqTable[PSG[0xE]&0xF]<<(16+2);
+ nreg=(nreg<<1)+(((nreg>>nshift)^(nreg>>14))&1);
+ nreg&=0x7fff;
+ noiseout=amptab[(nreg>>0xe)];
+ if(noiseacc<=0) goto rea2;
+ totalout = wlookup2[tcout+noiseout+RawDALatch];
+ } /* noiseacc<=0 */
+ } /* for(V=... */
+}
+ else if(inie[0])
+ {
+ for(V=start;V<end;V++)
+ {
+ Wave[V>>4]+=totalout;
+
+ triacc-=inie[0];
+
+ if(triacc<=0)
+ {
+ area:
+ triacc+=freq[0]; //t;
+ tristep=(tristep+1)&0x1F;
+ if(triacc<=0) goto area;
+ tcout=(tristep&0xF);
+ if(!(tristep&0x10)) tcout^=0xF;
+ tcout=tcout*3;
+ totalout = wlookup2[tcout+noiseout+RawDALatch];
+ }
+ }
+ }
+ else if(inie[1])
+ {
+ for(V=start;V<end;V++)
+ {
+ Wave[V>>4]+=totalout;
+ noiseacc-=inie[1];
+ if(noiseacc<=0)
+ {
+ area2:
+ noiseacc+=NoiseFreqTable[PSG[0xE]&0xF]<<(16+2);
+ nreg=(nreg<<1)+(((nreg>>nshift)^(nreg>>14))&1);
+ nreg&=0x7fff;
+ noiseout=amptab[(nreg>>0xe)];
+ if(noiseacc<=0) goto area2;
+ totalout = wlookup2[tcout+noiseout+RawDALatch];
+ } /* noiseacc<=0 */
+ }
+ }
+ else
+ {
+ for(V=start;V<end;V++)
+ Wave[V>>4]+=totalout;
+ }
+}
+
+
+static void RDoNoise(void)
+{
+ int32 V;
+ int32 outo;
+ uint32 amptab[2];
+
+ if(EnvUnits[2].Mode&0x1)
+ amptab[0]=EnvUnits[2].Speed;
+ else
+ amptab[0]=EnvUnits[2].decvolume;
+
+ amptab[0]<<=16;
+ amptab[1]=0;
+
+ amptab[0]<<=1;
+
+ outo=amptab[nreg&1]; //(nreg>>0xe)&1];
+
+ if(!lengthcount[3])
+ {
+ outo=amptab[0]=0;
+ }
+
+ if(PSG[0xE]&0x80) // "short" noise
+ for(V=ChannelBC[3];V<SOUNDTS;V++)
+ {
+ WaveHi[V]+=outo;
+ wlcount[3]--;
+ if(!wlcount[3])
+ {
+ uint8 feedback;
+ wlcount[3]=NoiseFreqTable[PSG[0xE]&0xF]<<1;
+ feedback=((nreg>>8)&1)^((nreg>>14)&1);
+ nreg=(nreg<<1)+feedback;
+ nreg&=0x7fff;
+ outo=amptab[(nreg>>0xe)&1];
+ }
+ }
+ else
+ for(V=ChannelBC[3];V<SOUNDTS;V++)
+ {
+ WaveHi[V]+=outo;
+ wlcount[3]--;
+ if(!wlcount[3])
+ {
+ uint8 feedback;
+ wlcount[3]=NoiseFreqTable[PSG[0xE]&0xF]<<1;
+ feedback=((nreg>>13)&1)^((nreg>>14)&1);
+ nreg=(nreg<<1)+feedback;
+ nreg&=0x7fff;
+ outo=amptab[(nreg>>0xe)&1];
+ }
+ }
+ ChannelBC[3]=SOUNDTS;
+}
+
+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,0x400F,Write_PSG);
+ SetWriteHandler(0x4010,0x4013,Write_DMCRegs);
+ SetWriteHandler(0x4017,0x4017,Write_IRQFM);
+
+ SetWriteHandler(0x4015,0x4015,StatusWrite);
+ SetReadHandler(0x4015,0x4015,StatusRead);
+}
+
+static int32 inbuf=0;
+int FlushEmulateSound(void)
+{
+ int x;
+ int32 end,left;
+
+ if(!timestamp) return(0);
+
+ if(!FSettings.SndRate)
+ {
+ left=0;
+ end=0;
+ goto nosoundo;
+ }
+
+ DoSQ1();
+ DoSQ2();
+ DoTriangle();
+ DoNoise();
+ DoPCM();
+
+ if(FSettings.soundq>=1)
+ {
+ int32 *tmpo=&WaveHi[soundtsoffs];
+
+ if(GameExpSound.HiFill) GameExpSound.HiFill();
+
+ for(x=timestamp;x;x--)
+ {
+ uint32 b=*tmpo;
+ *tmpo=(b&65535)+wlookup2[(b>>16)&255]+wlookup1[b>>24];
+ tmpo++;
+ }
+ end=NeoFilterSound(WaveHi,WaveFinal,SOUNDTS,&left);
+
+ memmove(WaveHi,WaveHi+SOUNDTS-left,left*sizeof(uint32));
+ memset(WaveHi+left,0,sizeof(WaveHi)-left*sizeof(uint32));
+
+ if(GameExpSound.HiSync) GameExpSound.HiSync(left);
+ for(x=0;x<5;x++)
+ ChannelBC[x]=left;
+ }
+ else
+ {
+ end=(SOUNDTS<<16)/soundtsinc;
+ if(GameExpSound.Fill)
+ GameExpSound.Fill(end&0xF);
+
+ SexyFilter(Wave,WaveFinal,end>>4);
+
+ //if(FSettings.lowpass)
+ // SexyFilter2(WaveFinal,end>>4);
+ if(end&0xF)
+ Wave[0]=Wave[(end>>4)];
+ Wave[end>>4]=0;
+ }
+ nosoundo:
+
+ if(FSettings.soundq>=1)
+ {
+ soundtsoffs=left;
+ }
+ else
+ {
+ for(x=0;x<5;x++)
+ ChannelBC[x]=end&0xF;
+ soundtsoffs = (soundtsinc*(end&0xF))>>16;
+ end>>=4;
+ }
+ inbuf=end;
+
+ FCEU_WriteWaveData(WaveFinal, end); /* This function will just return
+ if sound recording is off. */
+ return(end);
+}
+
+int GetSoundBuffer(int32 **W)
+{
+ *W=WaveFinal;
+ return(inbuf);
+}
+
+/* FIXME: Find out what sound registers get reset on reset. I know $4001/$4005 don't,
+due to that whole MegaMan 2 Game Genie thing.
+*/
+
+void FCEUSND_Reset(void)
+{
+ int x;
+
+ IRQFrameMode=0x0;
+ fhcnt=fhinc;
+ fcnt=0;
+
+ nreg=1;
+ for(x=0;x<2;x++)
+ {
+ wlcount[x]=2048;
+ if(nesincsize) // lq mode
+ sqacc[x]=((uint32)2048<<17)/nesincsize;
+ else
+ sqacc[x]=1;
+ sweepon[x]=0;
+ curfreq[x]=0;
+ }
+ wlcount[2]=1; //2048;
+ wlcount[3]=2048;
+ DMCHaveDMA=DMCHaveSample=0;
+ SIRQStat=0x00;
+
+ RawDALatch=0x00;
+ TriCount=0;
+ TriMode=0;
+ tristep=0;
+ EnabledChannels=0;
+ for(x=0;x<4;x++)
+ lengthcount[x]=0;
+
+ DMCAddressLatch=0;
+ DMCSizeLatch=0;
+ DMCFormat=0;
+ DMCAddress=0;
+ DMCSize=0;
+ DMCShift=0;
+
+ // MAJOR BUG WAS HERE: DMCacc and DMCBitCount never got reset...
+ // so, do some ridiculous hackery if a movie's about to play to keep it in sync...
+
+ extern int movieSyncHackOn,resetDMCacc,movieConvertOffset1,movieConvertOffset2;
+ if(movieSyncHackOn)
+ {
+ if(resetDMCacc)
+ {
+ // no value in movie save state
+#ifdef WIN32
+ // use editbox fields
+ DMCacc=movieConvertOffset1;
+ DMCBitCount=movieConvertOffset2;
+#else
+ // no editbox fields, so leave the values alone
+ // and print out a warning that says what they are
+ FCEU_PrintError("Warning: These variables were not found in the save state and will keep their current value: DMCacc=%d, DMCBitCount=%d\n", DMCacc, DMCBitCount);
+#endif
+ }
+ else
+ {
+ // keep values loaded from movie save state or reset earlier
+ }
+ }
+ else
+ {
+ // reset these variables like should have done in the first place
+ DMCacc=1;
+ DMCBitCount=0;
+ }
+
+// FCEU_PrintError("DMCacc=%d, DMCBitCount=%d",DMCacc,DMCBitCount);
+}
+
+void FCEUSND_Power(void)
+{
+ int x;
+
+ SetNESSoundMap();
+ memset(PSG,0x00,sizeof(PSG));
+ FCEUSND_Reset();
+
+ memset(Wave,0,sizeof(Wave));
+ memset(WaveHi,0,sizeof(WaveHi));
+ memset(&EnvUnits,0,sizeof(EnvUnits));
+
+ for(x=0;x<5;x++)
+ ChannelBC[x]=0;
+ soundtsoffs=0;
+ LoadDMCPeriod(DMCFormat&0xF);
+}
+
+
+void SetSoundVariables(void)
+{
+ int x;
+
+ fhinc=PAL?16626:14915; // *2 CPU clock rate
+ fhinc*=24;
+
+ if(FSettings.SndRate)
+ {
+ wlookup1[0]=0;
+ for(x=1;x<32;x++)
+ {
+ wlookup1[x]=(double)16*16*16*4*95.52/((double)8128/(double)x+100);
+ if(!FSettings.soundq) wlookup1[x]>>=4;
+ }
+ wlookup2[0]=0;
+ for(x=1;x<203;x++)
+ {
+ wlookup2[x]=(double)16*16*16*4*163.67/((double)24329/(double)x+100);
+ if(!FSettings.soundq) wlookup2[x]>>=4;
+ }
+ if(FSettings.soundq>=1)
+ {
+ DoNoise=RDoNoise;
+ DoTriangle=RDoTriangle;
+ DoPCM=RDoPCM;
+ DoSQ1=RDoSQ1;
+ DoSQ2=RDoSQ2;
+ }
+ else
+ {
+ DoNoise=DoTriangle=DoPCM=DoSQ1=DoSQ2=Dummyfunc;
+ DoSQ1=RDoSQLQ;
+ DoSQ2=RDoSQLQ;
+ DoTriangle=RDoTriangleNoisePCMLQ;
+ DoNoise=RDoTriangleNoisePCMLQ;
+ DoPCM=RDoTriangleNoisePCMLQ;
+ }
+ }
+ else
+ {
+ DoNoise=DoTriangle=DoPCM=DoSQ1=DoSQ2=Dummyfunc;
+ return;
+ }
+
+ MakeFilters(FSettings.SndRate);
+
+ if(GameExpSound.RChange)
+ GameExpSound.RChange();
+
+ nesincsize=(int64)(((int64)1<<17)*(double)(PAL?PAL_CPU:NTSC_CPU)/(FSettings.SndRate * 16));
+ memset(sqacc,0,sizeof(sqacc));
+ memset(ChannelBC,0,sizeof(ChannelBC));
+
+ LoadDMCPeriod(DMCFormat&0xF); // For changing from PAL to NTSC
+
+ soundtsinc=(uint32)((uint64)(PAL?(long double)PAL_CPU*65536:(long double)NTSC_CPU*65536)/(FSettings.SndRate * 16));
+}
+
+void FCEUI_Sound(int Rate)
+{
+ FSettings.SndRate=Rate;
+ SetSoundVariables();
+}
+
+void FCEUI_SetLowPass(int q)
+{
+ FSettings.lowpass=q;
+}
+
+void FCEUI_SetSoundQuality(int quality)
+{
+ FSettings.soundq=quality;
+ SetSoundVariables();
+}
+
+void FCEUI_SetSoundVolume(uint32 volume)
+{
+ FSettings.SoundVolume=volume;
+}
+
+
+SFORMAT FCEUSND_STATEINFO[]={
+
+ { &fhcnt, 4|FCEUSTATE_RLSB,"FHCN"},
+ { &fcnt, 1, "FCNT"},
+ { PSG, 0x10, "PSG"},
+ { &EnabledChannels, 1, "ENCH"},
+ { &IRQFrameMode, 1, "IQFM"},
+ { &nreg, 2|FCEUSTATE_RLSB, "NREG"},
+ { &TriMode, 1, "TRIM"},
+ { &TriCount, 1, "TRIC"},
+
+ { &EnvUnits[0].Speed, 1, "E0SP"},
+ { &EnvUnits[1].Speed, 1, "E1SP"},
+ { &EnvUnits[2].Speed, 1, "E2SP"},
+
+ { &EnvUnits[0].Mode, 1, "E0MO"},
+ { &EnvUnits[1].Mode, 1, "E1MO"},
+ { &EnvUnits[2].Mode, 1, "E2MO"},
+
+ { &EnvUnits[0].DecCountTo1, 1, "E0D1"},
+ { &EnvUnits[1].DecCountTo1, 1, "E1D1"},
+ { &EnvUnits[2].DecCountTo1, 1, "E2D1"},
+
+ { &EnvUnits[0].decvolume, 1, "E0DV"},
+ { &EnvUnits[1].decvolume, 1, "E1DV"},
+ { &EnvUnits[2].decvolume, 1, "E2DV"},
+
+ { &lengthcount[0], 4|FCEUSTATE_RLSB, "LEN0"},
+ { &lengthcount[1], 4|FCEUSTATE_RLSB, "LEN1"},
+ { &lengthcount[2], 4|FCEUSTATE_RLSB, "LEN2"},
+ { &lengthcount[3], 4|FCEUSTATE_RLSB, "LEN3"},
+ { sweepon, 2, "SWEE"},
+ { &curfreq[0], 4|FCEUSTATE_RLSB,"CRF1"},
+ { &curfreq[1], 4|FCEUSTATE_RLSB,"CRF2"},
+ { SweepCount, 2,"SWCT"},
+
+ { &SIRQStat, 1, "SIRQ"},
+
+ { &DMCacc, 4|FCEUSTATE_RLSB, "5ACC"},
+ { &DMCBitCount, 1, "5BIT"},
+ { &DMCAddress, 4|FCEUSTATE_RLSB, "5ADD"},
+ { &DMCSize, 4|FCEUSTATE_RLSB, "5SIZ"},
+ { &DMCShift, 1, "5SHF"},
+
+ { &DMCHaveDMA, 1, "5HVDM"},
+ { &DMCHaveSample, 1, "5HVSP"},
+
+ { &DMCSizeLatch, 1, "5SZL"},
+ { &DMCAddressLatch, 1, "5ADL"},
+ { &DMCFormat, 1, "5FMT"},
+ { &RawDALatch, 1, "RWDA"},
+ { 0 }
+};
+
+void FCEUSND_SaveState(void)
+{
+
+}
+
+void FCEUSND_LoadState(int version)
+{
+ LoadDMCPeriod(DMCFormat&0xF);
+ RawDALatch&=0x7F;
+ DMCAddress&=0x7FFF;
+}
diff --git a/sound.h b/sound.h
new file mode 100644
index 00000000..ae4e9ce5
--- /dev/null
+++ b/sound.h
@@ -0,0 +1,62 @@
+/* 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 {
+ void (*Fill)(int Count); /* Low quality ext sound. */
+
+ /* NeoFill is for sound devices that are emulated in a more
+ high-level manner(VRC7) in HQ mode. Interestingly,
+ this device has slightly better sound quality(updated more
+ often) in lq mode than in high-quality mode. Maybe that
+ should be fixed. :)
+ */
+ void (*NeoFill)(int32 *Wave, int Count);
+ void (*HiFill)(void);
+ void (*HiSync)(int32 ts);
+
+ void (*RChange)(void);
+ void (*Kill)(void);
+} EXPSOUND;
+
+extern EXPSOUND GameExpSound;
+
+extern int32 nesincsize;
+
+void SetSoundVariables(void);
+
+int GetSoundBuffer(int32 **W);
+int FlushEmulateSound(void);
+extern int32 Wave[2048+512];
+extern int32 WaveFinal[2048+512];
+extern int32 WaveHi[];
+extern uint32 soundtsinc;
+
+extern uint32 soundtsoffs;
+#define SOUNDTS (timestamp + soundtsoffs)
+
+void SetNESSoundMap(void);
+void FrameSoundUpdate(void);
+
+void FCEUSND_Power(void);
+void FCEUSND_Reset(void);
+void FCEUSND_SaveState(void);
+void FCEUSND_LoadState(int version);
+
+void FASTAPASS(1) FCEU_SoundCPUHook(int);
diff --git a/soundexp.c b/soundexp.c
new file mode 100644
index 00000000..d59350f7
--- /dev/null
+++ b/soundexp.c
@@ -0,0 +1,42 @@
+#include <stdio.h>
+
+#include <vorbis/vorbisfile.h>
+
+#include "types.h"
+#include "fceu.h"
+
+static OggVorbis_File cursong;
+
+void InstallSoundExp(void)
+{
+ FILE *fp=fopen("test.ogg","rb");
+
+ ov_open(fp,&cursong,NULL,0);
+ FCEUGameInfo->soundrate=44100;
+ FCEUGameInfo->soundchan=2;
+}
+
+int cur=0;
+
+void UpdateSoundExp(int32 *buf, int32 len)
+{
+ int16 boo[8192];
+ int32 offset=0;
+ int x;
+ int32 tlen=len;
+
+ while(len)
+ {
+ int32 t=ov_read(&cursong,(char *)boo+offset*4,len*4,0,2,1,&cur)/4;
+ len-=t;
+ offset+=t;
+ }
+
+// printf("%d\n",inboo);
+ for(x=0;x<tlen*2;x++)
+ {
+ buf[x]=boo[x];
+ //buf[x]=(x&4)*4096; //(x&3)?0x3FFF:0;
+ }//buf[x]+=boo[x];
+// inboo-=len;
+}
diff --git a/state.c b/state.c
new file mode 100644
index 00000000..eedccdf3
--- /dev/null
+++ b/state.c
@@ -0,0 +1,679 @@
+/* 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
+ */
+
+/* TODO: Add (better) file io error checking */
+/* TODO: Change save state file format. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "types.h"
+#include "x6502.h"
+#include "fceu.h"
+#include "sound.h"
+#include "endian.h"
+#include "fds.h"
+#include "general.h"
+#include "state.h"
+#include "movie.h"
+#include "memory.h"
+#include "ppu.h"
+#include "netplay.h"
+#include "video.h"
+#include "input.h"
+
+static void (*SPreSave)(void);
+static void (*SPostSave)(void);
+
+static int SaveStateStatus[10];
+static int StateShow;
+
+#define SFMDATA_SIZE (64)
+static SFORMAT SFMDATA[SFMDATA_SIZE];
+static int SFEXINDEX;
+
+#define RLSB FCEUSTATE_RLSB //0x80000000
+
+
+extern SFORMAT FCEUPPU_STATEINFO[];
+extern SFORMAT FCEUSND_STATEINFO[];
+extern SFORMAT FCEUCTRL_STATEINFO[];
+extern SFORMAT FCEUMOV_STATEINFO[];
+
+
+SFORMAT SFCPU[]={
+ { &X.PC, 2|RLSB, "PC\0"},
+ { &X.A, 1, "A\0\0"},
+ { &X.P, 1, "P\0\0"},
+ { &X.X, 1, "X\0\0"},
+ { &X.Y, 1, "Y\0\0"},
+ { &X.S, 1, "S\0\0"},
+#ifdef _USE_SHARED_MEMORY_
+ { NULL, 0x800, "RAM"}, //will be initialized later after getting a pointer to RAM
+#else
+ { RAM, 0x800, "RAM"},
+#endif
+ { 0 }
+};
+
+SFORMAT SFCPUC[]={
+ { &X.jammed, 1, "JAMM"},
+ { &X.IRQlow, 4|RLSB, "IQLB"},
+ { &X.tcount, 4|RLSB, "ICoa"},
+ { &X.count, 4|RLSB, "ICou"},
+ { &timestampbase, sizeof(timestampbase) | RLSB, "TSBS"},
+ { &X.mooPI, 1, "MooP"}, // alternative to the "quick and dirty hack"
+ { 0 }
+};
+
+static int SubWrite(FILE *st, SFORMAT *sf)
+{
+ uint32 acc=0;
+
+ while(sf->v)
+ {
+ if(sf->s==~0) /* Link to another struct. */
+ {
+ uint32 tmp;
+
+ if(!(tmp=SubWrite(st,(SFORMAT *)sf->v)))
+ return(0);
+ acc+=tmp;
+ sf++;
+ continue;
+ }
+
+ acc+=8; /* Description + size */
+ acc+=sf->s&(~RLSB);
+
+ if(st) /* Are we writing or calculating the size of this block? */
+ {
+ fwrite(sf->desc,1,4,st);
+ write32le(sf->s&(~RLSB),st);
+
+ #ifndef LSB_FIRST
+ if(sf->s&RLSB)
+ FlipByteOrder(sf->v,sf->s&(~RLSB));
+ #endif
+
+ fwrite((uint8 *)sf->v,1,sf->s&(~RLSB),st);
+ /* Now restore the original byte order. */
+ #ifndef LSB_FIRST
+ if(sf->s&RLSB)
+ FlipByteOrder(sf->v,sf->s&(~RLSB));
+ #endif
+ }
+ sf++;
+ }
+
+ return(acc);
+}
+
+static int WriteStateChunk(FILE *st, int type, SFORMAT *sf)
+{
+ int bsize;
+
+ fputc(type,st);
+
+ bsize=SubWrite(0,sf);
+ write32le(bsize,st);
+
+ if(!SubWrite(st,sf))
+ {
+ return(0);
+ }
+ return (bsize+5);
+}
+
+static SFORMAT *CheckS(SFORMAT *sf, uint32 tsize, char *desc)
+{
+ while(sf->v)
+ {
+ if(sf->s==~0) /* Link to another SFORMAT structure. */
+ {
+ SFORMAT *tmp;
+ if((tmp= CheckS((SFORMAT *)sf->v, tsize, desc) ))
+ return(tmp);
+ sf++;
+ continue;
+ }
+ if(!memcmp(desc,sf->desc,4))
+ {
+ if(tsize!=(sf->s&(~RLSB)))
+ return(0);
+ return(sf);
+ }
+ sf++;
+ }
+ return(0);
+}
+
+static int scan_chunks=0;
+int suppress_scan_chunks=0;
+
+static int ReadStateChunk(FILE *st, SFORMAT *sf, int size)
+{
+ if(scan_chunks)
+ return fseek(st,size,SEEK_CUR) == 0;
+
+ SFORMAT *tmp;
+ int temp;
+ temp=ftell(st);
+
+ while(ftell(st)<temp+size)
+ {
+ uint32 tsize;
+ char toa[4];
+ if(fread(toa,1,4,st)<=0)
+ return 0;
+
+ read32le(&tsize,st);
+
+ if((tmp=CheckS(sf,tsize,toa)))
+ {
+ fread((uint8 *)tmp->v,1,tmp->s&(~RLSB),st);
+
+ #ifndef LSB_FIRST
+ if(tmp->s&RLSB)
+ FlipByteOrder(tmp->v,tmp->s&(~RLSB));
+ #endif
+ }
+ else
+ fseek(st,tsize,SEEK_CUR);
+ } // while(...)
+ return 1;
+}
+
+static int read_sfcpuc=0, read_snd=0;
+
+static int ReadStateChunks(FILE *st, int32 totalsize)
+{
+ int t;
+ uint32 size;
+ int ret=1;
+ int warned=0;
+
+ read_sfcpuc=0;
+ read_snd=0;
+
+// int moo=X.mooPI;
+ if(!scan_chunks)
+ X.mooPI=/*X.P*/0xFF;
+
+ while(totalsize > 0)
+ {
+ t=fgetc(st);
+ if(t==EOF) break;
+ if(!read32le(&size,st)) break;
+ totalsize -= size + 5;
+
+ switch(t)
+ {
+ case 1:if(!ReadStateChunk(st,SFCPU,size)) ret=0;break;
+ case 3:if(!ReadStateChunk(st,FCEUPPU_STATEINFO,size)) ret=0;break;
+ case 4:if(!ReadStateChunk(st,FCEUCTRL_STATEINFO,size)) ret=0;break;
+ case 7:if(!FCEUMOV_ReadState(st,size)) ret=0;break;
+ case 0x10:if(!ReadStateChunk(st,SFMDATA,size)) ret=0; break;
+
+ // now it gets hackier:
+ case 5:
+ if(!ReadStateChunk(st,FCEUSND_STATEINFO,size))
+ ret=0;
+ else
+ read_snd=1;
+ break;
+ case 6:
+ if(FCEUI_IsMovieActive())
+ {
+ if(!ReadStateChunk(st,FCEUMOV_STATEINFO,size)) ret=0;
+ }
+ else
+ {
+ if(fseek(st,size,SEEK_CUR)!=0) ret=0;
+ }
+ break;
+ case 8:
+ // load back buffer
+ {
+ extern uint8 *XBackBuf;
+ if(size != fread(XBackBuf,1,size,st))
+ ret = 0;
+#ifdef WIN32
+ else
+ {
+ FCEUD_BlitScreen(XBuf);
+ UpdateFCEUWindow();
+ }
+#endif
+ }
+ break;
+ case 2:
+ {
+ if(!ReadStateChunk(st,SFCPUC,size))
+ ret=0;
+ else
+ read_sfcpuc=1;
+ } break;
+ default:
+ // for somebody's sanity's sake, at least warn about it:
+ if(!warned && !scan_chunks)
+ {
+ char str [256];
+ sprintf(str, "Warning: Found unknown save chunk of type %d.\nThis could indicate the save state is corrupted\nor made with a different (incompatible) emulator version.", t);
+ FCEUD_PrintError(str);
+ warned=1;
+ }
+ if(fseek(st,size,SEEK_CUR)<0) goto endo;break;
+ }
+ }
+ endo:
+
+ if(X.mooPI==0xFF && !scan_chunks)
+ {
+// FCEU_PrintError("prevmoo=%d, p=%d",moo,X.P);
+ X.mooPI=X.P; // "Quick and dirty hack." //begone
+ }
+
+ extern int resetDMCacc;
+ if(read_snd)
+ resetDMCacc=0;
+ else
+ resetDMCacc=1;
+
+ return ret;
+}
+
+
+int CurrentState=1;
+extern int geniestage;
+
+int FCEUSS_SaveFP(FILE *st)
+{
+ static uint32 totalsize;
+ static uint8 header[16]="FCS";
+ uint32 writeoffset;
+
+ writeoffset = ftell(st);
+ memset(header+4,0,13);
+ header[3]=0xFF;
+ FCEU_en32lsb(header + 8, FCEU_VERSION_NUMERIC);
+ fwrite(header,1,16,st);
+ FCEUPPU_SaveState();
+ FCEUSND_SaveState();
+ totalsize=WriteStateChunk(st,1,SFCPU);
+ totalsize+=WriteStateChunk(st,2,SFCPUC);
+ totalsize+=WriteStateChunk(st,3,FCEUPPU_STATEINFO);
+ totalsize+=WriteStateChunk(st,4,FCEUCTRL_STATEINFO);
+ totalsize+=WriteStateChunk(st,5,FCEUSND_STATEINFO);
+ if(FCEUI_IsMovieActive())
+ {
+ totalsize+=WriteStateChunk(st,6,FCEUMOV_STATEINFO);
+ uint32 size = FCEUMOV_WriteState(0);
+ fputc(7,st);
+ write32le(size, st);
+ FCEUMOV_WriteState(st);
+ totalsize += 5 + size;
+ }
+ // save back buffer
+ {
+ extern uint8 *XBackBuf;
+ uint32 size = 256 * 256 + 8;
+ fputc(8,st);
+ write32le(size, st);
+ fwrite(XBackBuf,1,size,st);
+ totalsize += 5 + size;
+ }
+
+ if(SPreSave) SPreSave();
+ totalsize+=WriteStateChunk(st,0x10,SFMDATA);
+ if(SPreSave) SPostSave();
+
+ fseek(st,writeoffset+4,SEEK_SET);
+ write32le(totalsize,st);
+ return(1);
+}
+
+void FCEUSS_Save(char *fname)
+{
+ FILE *st=NULL;
+ char *fn;
+
+ if(geniestage==1)
+ {
+ FCEU_DispMessage("Cannot save FCS in GG screen.");
+ return;
+ }
+
+ if(fname)
+ st=FCEUD_UTF8fopen(fname, "wb");
+ else
+ {
+// FCEU_PrintError("daCurrentState=%d",CurrentState);
+ st=FCEUD_UTF8fopen(fn=FCEU_MakeFName(FCEUMKF_STATE,CurrentState,0),"wb");
+ free(fn);
+ }
+
+ if(st == NULL)
+ {
+ FCEU_DispMessage("State %d save error.",CurrentState);
+ return;
+ }
+
+ FCEUSS_SaveFP(st);
+
+ fclose(st);
+
+ if(!fname)
+ {
+ SaveStateStatus[CurrentState]=1;
+ FCEU_DispMessage("State %d saved.",CurrentState);
+ }
+}
+
+int FCEUSS_LoadFP(FILE *st, int make_backup)
+{
+ if(make_backup==2 && suppress_scan_chunks)
+ return 1;
+
+ int x;
+ uint8 header[16];
+ int stateversion;
+ char* fn=0;
+
+ /* Make temporary savestate in case something screws up during the load */
+ if(make_backup==1)
+ {
+ fn=FCEU_MakeFName(FCEUMKF_NPTEMP,0,0);
+ FILE *fp;
+
+ if((fp=fopen(fn,"wb")))
+ {
+ if(FCEUSS_SaveFP(fp))
+ {
+ fclose(fp);
+ }
+ else
+ {
+ fclose(fp);
+ unlink(fn);
+ free(fn);
+ fn=0;
+ }
+ }
+ }
+
+ if(make_backup!=2)
+ {
+ FCEUMOV_PreLoad();
+ }
+ fread(&header,1,16,st);
+ if(memcmp(header,"FCS",3))
+ {
+ return(0);
+ }
+ if(header[3] == 0xFF)
+ {
+ stateversion = FCEU_de32lsb(header + 8);
+ }
+ else
+ {
+ stateversion=header[3] * 100;
+ }
+ if(make_backup==2)
+ {
+ scan_chunks=1;
+ }
+ x=ReadStateChunks(st,*(uint32*)(header+4));
+ if(make_backup==2)
+ {
+ scan_chunks=0;
+ return 1;
+ }
+ if(read_sfcpuc && stateversion<9500)
+ {
+ X.IRQlow=0;
+ }
+ if(GameStateRestore)
+ {
+ GameStateRestore(stateversion);
+ }
+ if(x)
+ {
+ FCEUPPU_LoadState(stateversion);
+ FCEUSND_LoadState(stateversion);
+ x=FCEUMOV_PostLoad();
+ }
+
+ if(fn)
+ {
+ if(!x || make_backup==2) //is make_backup==2 possible?? oh well.
+ {
+ /* Oops! Load the temporary savestate */
+ FILE *fp;
+
+ if((fp=fopen(fn,"rb")))
+ {
+ FCEUSS_LoadFP(fp,0);
+ fclose(fp);
+ }
+ unlink(fn);
+ }
+ free(fn);
+ }
+
+ return(x);
+}
+
+int FCEUSS_Load(char *fname)
+{
+ FILE *st;
+ char *fn;
+
+ //Hopefully this fixes read-only toggle problems?
+ if(FCEUMOV_IsRecording()) MovieFlushHeader();
+
+ if(geniestage==1)
+ {
+ FCEU_DispMessage("Cannot load FCS in GG screen.");
+ return(0);
+ }
+ if(fname)
+ {
+ st=FCEUD_UTF8fopen(fname, "rb");
+ }
+ else
+ {
+ st=FCEUD_UTF8fopen(fn=FCEU_MakeFName(FCEUMKF_STATE,CurrentState,fname),"rb");
+ free(fn);
+ }
+
+ if(st == NULL)
+ {
+ FCEU_DispMessage("State %d load error.",CurrentState);
+ SaveStateStatus[CurrentState]=0;
+ return(0);
+ }
+
+ //If in bot mode, don't do a backup when loading.
+ //Otherwise you eat at the hard disk, since so many
+ //states are being loaded.
+ if(FCEUSS_LoadFP(st,FCEU_BotMode()?0:1))
+ {
+ if(!fname)
+ {
+ //This looks redudant to me... but why bother deleting it:)
+ SaveStateStatus[CurrentState]=1;
+
+ FCEU_DispMessage("State %d loaded.",CurrentState);
+ SaveStateStatus[CurrentState]=1;
+ }
+ fclose(st);
+ return(1);
+ }
+ else
+ {
+ if(!fname)
+ {
+ SaveStateStatus[CurrentState]=1;
+ }
+ FCEU_DispMessage("Error(s) reading state %d!",CurrentState);
+ fclose(st);
+ return(0);
+ }
+}
+
+void FCEUSS_CheckStates(void)
+{
+ FILE *st=NULL;
+ char *fn;
+ int ssel;
+
+ for(ssel=0;ssel<10;ssel++)
+ {
+ st=FCEUD_UTF8fopen(fn=FCEU_MakeFName(FCEUMKF_STATE,ssel,0),"rb");
+ free(fn);
+ if(st)
+ {
+ SaveStateStatus[ssel]=1;
+ fclose(st);
+ }
+ else
+ SaveStateStatus[ssel]=0;
+ }
+
+ CurrentState=1;
+ StateShow=0;
+}
+
+void ResetExState(void (*PreSave)(void), void (*PostSave)(void))
+{
+ int x;
+ for(x=0;x<SFEXINDEX;x++)
+ {
+ if(SFMDATA[x].desc)
+ free(SFMDATA[x].desc);
+ }
+ SPreSave = PreSave;
+ SPostSave = PostSave;
+ SFEXINDEX=0;
+}
+
+void AddExState(void *v, uint32 s, int type, char *desc)
+{
+ if(desc)
+ {
+ SFMDATA[SFEXINDEX].desc=(char *)FCEU_malloc(5);
+ strcpy(SFMDATA[SFEXINDEX].desc,desc);
+ }
+ else
+ SFMDATA[SFEXINDEX].desc=0;
+ SFMDATA[SFEXINDEX].v=v;
+ SFMDATA[SFEXINDEX].s=s;
+ if(type) SFMDATA[SFEXINDEX].s|=RLSB;
+ if(SFEXINDEX<SFMDATA_SIZE-1)
+ SFEXINDEX++;
+ else
+ {
+ static int once=1;
+ if(once)
+ {
+ once=0;
+ FCEU_PrintError("Error in AddExState: SFEXINDEX overflow.\nSomebody made SFMDATA_SIZE too small.");
+ }
+ }
+ SFMDATA[SFEXINDEX].v=0; // End marker.
+}
+
+void FCEUI_SelectStateNext(int n)
+{
+ if(n>0)
+ CurrentState=(CurrentState+1)%10;
+ else
+ CurrentState=(CurrentState+9)%10;
+ FCEUI_SelectState(CurrentState, 1);
+}
+
+int FCEUI_SelectState(int w, int show)
+{
+ int oldstate=CurrentState;
+ if(w == -1) { StateShow = 0; return; }
+ FCEUI_SelectMovie(-1,0);
+
+ CurrentState=w;
+ if(show)
+ {
+ StateShow=180;
+ FCEU_DispMessage("-select state-");
+ }
+ return oldstate;
+}
+
+void FCEUI_SaveState(char *fname)
+{
+ StateShow=0;
+ FCEUSS_Save(fname);
+}
+
+int loadStateFailed = 0; // hack, this function should return a value instead
+
+void FCEUI_LoadState(char *fname)
+{
+ StateShow=0;
+ loadStateFailed=0;
+
+ /* For network play, be load the state locally, and then save the state to a temporary file,
+ and send that. This insures that if an older state is loaded that is missing some
+ information expected in newer save states, desynchronization won't occur(at least not
+ from this ;)).
+ */
+ if(FCEUSS_Load(fname))
+ {
+ if(FCEUnetplay)
+ {
+ char *fn=FCEU_MakeFName(FCEUMKF_NPTEMP,0,0);
+ FILE *fp;
+
+ if((fp=fopen(fn,"wb")))
+ {
+ if(FCEUSS_SaveFP(fp))
+ {
+ fclose(fp);
+ FCEUNET_SendFile(FCEUNPCMD_LOADSTATE, fn);
+ }
+ else fclose(fp);
+ unlink(fn);
+ }
+ free(fn);
+ }
+ }
+ else loadStateFailed=1;
+
+}
+
+void FCEU_DrawSaveStates(uint8 *XBuf)
+{
+ if(!StateShow) return;
+
+ FCEU_DrawNumberRow(XBuf,SaveStateStatus,CurrentState);
+ StateShow--;
+}
+
diff --git a/state.h b/state.h
new file mode 100644
index 00000000..3185365e
--- /dev/null
+++ b/state.h
@@ -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 <stdio.h>
+
+void FCEUSS_Save(char *);
+int FCEUSS_Load(char *);
+int FCEUSS_SaveFP(FILE *);
+int FCEUSS_LoadFP(FILE *, int);
+
+extern int CurrentState;
+void FCEUSS_CheckStates(void);
+
+typedef struct {
+ void *v;
+ uint32 s;
+ char *desc;
+} SFORMAT;
+
+void ResetExState(void (*PreSave)(void),void (*PostSave)(void));
+void AddExState(void *v, uint32 s, int type, char *desc);
+
+#define FCEUSTATE_RLSB 0x80000000
+
+void FCEU_DrawSaveStates(uint8 *XBuf);
+
diff --git a/types.h b/types.h
new file mode 100644
index 00000000..01ecbd96
--- /dev/null
+++ b/types.h
@@ -0,0 +1,97 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2001 Aaron Oneal
+ * 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
+ */
+
+#ifndef __FCEU_TYPES
+#define __FCEU_TYPES
+
+#include <inttypes.h>
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
+
+//typedef unsigned char uint8;
+//typedef unsigned short uint16;
+//typedef unsigned long uint32;
+
+
+#ifdef __GNUC__
+ typedef unsigned long long uint64;
+ typedef long long int64;
+ #define INLINE inline
+ #define GINLINE inline
+#elif MSVC
+ typedef __int64 int64;
+ typedef unsigned __int64 uint64;
+ #define INLINE __inline
+ #define GINLINE /* Can't declare a function INLINE
+ and global in MSVC. Bummer.
+ */
+ #define PSS_STYLE 2 /* Does MSVC compile for anything
+ other than Windows/DOS targets?
+ */
+#endif
+
+#if PSS_STYLE==2
+
+#define PSS "\\"
+#define PS '\\'
+
+#elif PSS_STYLE==1
+
+#define PSS "/"
+#define PS '/'
+
+#elif PSS_STYLE==3
+
+#define PSS "\\"
+#define PS '\\'
+
+#elif PSS_STYLE==4
+
+#define PSS ":"
+#define PS ':'
+
+#endif
+
+
+#ifdef __GNUC__
+ #ifdef C80x86
+ #define FASTAPASS(x) __attribute__((regparm(x)))
+ #define FP_FASTAPASS FASTAPASS
+ #else
+ #define FASTAPASS(x)
+ #define FP_FASTAPASS(x)
+ #endif
+#elif MSVC
+ #define FP_FASTAPASS(x)
+ #define FASTAPASS(x) __fastcall
+#else
+ #define FP_FASTAPASS(x)
+ #define FASTAPASS(x)
+#endif
+
+typedef void (FP_FASTAPASS(2) *writefunc)(uint32 A, uint8 V);
+typedef uint8 (FP_FASTAPASS(1) *readfunc)(uint32 A);
+#endif
diff --git a/unif.c b/unif.c
new file mode 100644
index 00000000..46b66a3c
--- /dev/null
+++ b/unif.c
@@ -0,0 +1,571 @@
+/* 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
+ */
+
+/* TODO: Battery backup file saving, mirror force */
+/* **INCOMPLETE** */
+/* Override stuff: CHR RAM instead of CHR ROM, mirroring. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#include "types.h"
+#include "fceu.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"
+
+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)(FCEUFILE *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(size<minimum)
+ return minimum;
+ while(x<size)
+ x<<=1;
+ return x;
+}
+
+static void FreeUNIF(void)
+{
+ int x;
+ if(UNIFchrrama)
+ {free(UNIFchrrama);UNIFchrrama=0;}
+ if(boardname)
+ {free(boardname);boardname=0;}
+ for(x=0;x<32;x++)
+ {
+ if(malloced[x])
+ {free(malloced[x]);malloced[x]=0;}
+ }
+}
+
+static void ResetUNIF(void)
+{
+ int x;
+ for(x=0;x<32;x++)
+ malloced[x]=0;
+ vramo=0;
+ boardname=0;
+ mirrortodo=0;
+ memset(&UNIFCart,0,sizeof(UNIFCart));
+ UNIFchrrama=0;
+}
+
+static uint8 exntar[2048];
+
+static void MooMirroring(void)
+{
+ if(mirrortodo<0x4)
+ SetupCartMirroring(mirrortodo,1,0);
+ else if(mirrortodo==0x4)
+ {
+ SetupCartMirroring(4,1,exntar);
+ AddExState(exntar, 2048, 0,"EXNR");
+ }
+ else
+ SetupCartMirroring(0,0,0);
+}
+
+static int DoMirroring(FCEUFILE *fp)
+{
+ uint8 t;
+ t=FCEU_fgetc(fp);
+ mirrortodo=t;
+
+ {
+ static char *stuffo[6]={"Horizontal","Vertical","$2000","$2400","\"Four-screen\"","Controlled by Mapper Hardware"};
+ if(t<6)
+ FCEU_printf(" Name/Attribute Table Mirroring: %s\n",stuffo[t]);
+ }
+ return(1);
+}
+
+static int NAME(FCEUFILE *fp)
+{
+ char namebuf[100];
+ int index;
+ int t;
+
+ FCEU_printf(" Name: ");
+ index=0;
+
+ while((t=FCEU_fgetc(fp))>0)
+ if(index<99)
+ namebuf[index++]=t;
+
+ namebuf[index]=0;
+ FCEU_printf("%s\n",namebuf);
+
+ if(!FCEUGameInfo->name)
+ {
+ FCEUGameInfo->name=malloc(strlen(namebuf)+1);
+ strcpy(FCEUGameInfo->name,namebuf);
+ }
+ return(1);
+}
+static int DINF(FCEUFILE *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(FCEUFILE *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(FCEUFILE *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(FCEUFILE *fp)
+{
+ FCEU_printf(" Battery-backed.\n");
+ if(FCEU_fgetc(fp)==EOF)
+ return(0);
+ UNIFCart.battery=1;
+ return(1);
+}
+
+static int LoadPRG(FCEUFILE *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(FCEUFILE *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(FCEUFILE *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},
+
+// /* 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
+
+ { "ANROM", ANROM_Init,0},
+
+ { "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},
+ { "NROM", NROM_Init,0 }, //NROM256_Init,0 },
+ { "NROM-128", NROM_Init,0 }, //NROM128_Init,0 },
+ { "NROM-256", NROM_Init,0 }, //NROM256_Init,0 },
+ { "RROM", NROM_Init,0 }, //NROM128_Init,0 },
+ { "RROM-128", NROM_Init,0 }, //NROM128_Init,0 },
+ { "MHROM", MHROM_Init,0},
+ { "UNROM", UNROM_Init,0},
+ { "SUNSOFT_UNROM", SUNSOFT_UNROM_Init,0},
+ { "MARIO1-MALEE2", MALEE_Init,0},
+
+ { "CC-21", UNLCC21_Init,0},
+
+ { "H2288", UNLH2288_Init,0},
+ { "KOF97", UNLKOF97_Init,0},
+ { "SL1632", UNLSL1632_Init,0},
+ { "SHERO", UNLSHeroes_Init,0},
+ { "8237", UNL8237_Init,0},
+ { "8157", UNL8157_Init,0},
+ { "T-262", BMCT262_Init,0},
+ { "FK23C", BMCFK23C_Init,0},
+ { "Supervision16in1", Supervision16_Init,0},
+ { "NovelDiamond9999999in1", Novel_Init,0},
+ { "Super24in1SC03", Super24_Init,0},
+ { "42in1ResetSwitch", BMC42in1r_Init, 0},
+ { "64in1NoRepeat", BMC64in1nr_Init, 0},
+ { "13in1JY110", BMC13in1JY110_Init, 0},
+ { "70in1", BMC70in1_Init, 0},
+ { "70in1B", BMC70in1B_Init, 0},
+ { "GK-192", Mapper58_Init, 0},
+ { "SuperHIK8in1", Mapper45_Init,0},
+
+ { "DREAMTECH01", DreamTech01_Init,0},
+ { "KONAMI-QTAI", Mapper190_Init,0},
+
+ { "TEK90", Mapper90_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(FCEUFILE *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_read32le(&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, FCEUFILE *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_read32le(&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
new file mode 100644
index 00000000..9d7992ef
--- /dev/null
+++ b/unif.h
@@ -0,0 +1,102 @@
+/* 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 ANROM_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 MHROM_Init(CartInfo *info);
+void UNROM_Init(CartInfo *info);
+void SUNSOFT_UNROM_Init(CartInfo *info); // "Shanghi" original version mapper
+void MALEE_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 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 Supervision16_Init(CartInfo *info);
+void Super24_Init(CartInfo *info);
+void Novel_Init(CartInfo *info);
+
+void BMC42in1r_Init(CartInfo *info);
+void BMC64in1nr_Init(CartInfo *info);
+void BMC70in1_Init(CartInfo *info);
+void BMC70in1B_Init(CartInfo *info);
+void BMC13in1JY110_Init(CartInfo *info);
+void BMCT262_Init(CartInfo *info);
+void BMCFK23C_Init(CartInfo *info);
+
+void DreamTech01_Init(CartInfo *info);
+void Mapper190_Init(CartInfo *info);
+void UNLCC21_Init(CartInfo *info);
+void UNLSL1632_Init(CartInfo *info);
+void UNLKOF97_Init(CartInfo *info);
+void UNLSonic_Init(CartInfo *info);
+void UNLSHeroes_Init(CartInfo *info);
+void UNLH2288_Init(CartInfo *info);
+void UNL8237_Init(CartInfo *info);
+void UNL8157_Init(CartInfo *info);
+
+extern uint8 *UNIFchrrama; // Meh. So I can stop CHR RAM
+ // bank switcherooing with certain boards...
diff --git a/unzip.c b/unzip.c
new file mode 100644
index 00000000..d12c6eae
--- /dev/null
+++ b/unzip.c
@@ -0,0 +1,1303 @@
+/* unzip.c -- IO on .zip files using zlib
+ Version 0.15 beta, Mar 19th, 1998,
+
+ Read unzip.h for more info
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "zlib.h"
+#include "unzip.h"
+
+#ifdef STDC
+# include <stddef.h>
+# include <string.h>
+# include <stdlib.h>
+#endif
+#ifdef NO_ERRNO_H
+ extern int errno;
+#else
+# include <errno.h>
+#endif
+
+#include "driver.h"
+
+#ifndef local
+# define local static
+#endif
+/* compile with -Dlocal if your debugger can't find static symbols */
+
+
+
+#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \
+ !defined(CASESENSITIVITYDEFAULT_NO)
+#define CASESENSITIVITYDEFAULT_NO
+#endif
+
+
+#ifndef UNZ_BUFSIZE
+#define UNZ_BUFSIZE (16384)
+#endif
+
+#ifndef UNZ_MAXFILENAMEINZIP
+#define UNZ_MAXFILENAMEINZIP (256)
+#endif
+
+#ifndef ALLOC
+# define ALLOC(size) (malloc(size))
+#endif
+#ifndef TRYFREE
+# define TRYFREE(p) {if (p) free(p);}
+#endif
+
+#define SIZECENTRALDIRITEM (0x2e)
+#define SIZEZIPLOCALHEADER (0x1e)
+
+
+/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
+
+#ifndef SEEK_CUR
+#define SEEK_CUR 1
+#endif
+
+#ifndef SEEK_END
+#define SEEK_END 2
+#endif
+
+#ifndef SEEK_SET
+#define SEEK_SET 0
+#endif
+
+const char unz_copyright[] =
+ " unzip 0.15 Copyright 1998 Gilles Vollant ";
+
+/* unz_file_info_interntal contain internal info about a file in zipfile*/
+typedef struct unz_file_info_internal_s
+{
+ uLong offset_curfile;/* relative offset of local header 4 bytes */
+} unz_file_info_internal;
+
+
+/* file_in_zip_read_info_s contain internal information about a file in zipfile,
+ when reading and decompress it */
+typedef struct
+{
+ char *read_buffer; /* internal buffer for compressed data */
+ z_stream stream; /* zLib stream structure for inflate */
+
+ uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/
+ uLong stream_initialised; /* flag set if stream structure is initialised*/
+
+ uLong offset_local_extrafield;/* offset of the local extra field */
+ uInt size_local_extrafield;/* size of the local extra field */
+ uLong pos_local_extrafield; /* position in the local extra field in read*/
+
+ uLong crc32; /* crc32 of all data uncompressed */
+ uLong crc32_wait; /* crc32 we must obtain after decompress all */
+ uLong rest_read_compressed; /* number of byte to be decompressed */
+ uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/
+ FILE* file; /* io structore of the zipfile */
+ uLong compression_method; /* compression method (0==store) */
+ uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+} file_in_zip_read_info_s;
+
+
+/* unz_s contain internal information about the zipfile
+*/
+typedef struct
+{
+ FILE* file; /* io structore of the zipfile */
+ unz_global_info gi; /* public global information */
+ uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/
+ uLong num_file; /* number of the current file in the zipfile*/
+ uLong pos_in_central_dir; /* pos of the current file in the central dir*/
+ uLong current_file_ok; /* flag about the usability of the current file*/
+ uLong central_pos; /* position of the beginning of the central dir*/
+
+ uLong size_central_dir; /* size of the central directory */
+ uLong offset_central_dir; /* offset of start of central directory with
+ respect to the starting disk number */
+
+ unz_file_info cur_file_info; /* public info about the current file in zip*/
+ unz_file_info_internal cur_file_info_internal; /* private info about it*/
+ file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
+ file if we are decompressing it */
+} unz_s;
+
+
+/* ===========================================================================
+ Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+ for end of file.
+ IN assertion: the stream s has been sucessfully opened for reading.
+*/
+
+
+local int unzlocal_getByte(fin,pi)
+ FILE *fin;
+ int *pi;
+{
+ unsigned char c;
+ int err = fread(&c, 1, 1, fin);
+ if (err==1)
+ {
+ *pi = (int)c;
+ return UNZ_OK;
+ }
+ else
+ {
+ if (ferror(fin))
+ return UNZ_ERRNO;
+ else
+ return UNZ_EOF;
+ }
+}
+
+
+/* ===========================================================================
+ Reads a long in LSB order from the given gz_stream. Sets
+*/
+local int unzlocal_getShort (fin,pX)
+ FILE* fin;
+ uLong *pX;
+{
+ uLong x ;
+ int i;
+ int err;
+
+ err = unzlocal_getByte(fin,&i);
+ x = (uLong)i;
+
+ if (err==UNZ_OK)
+ err = unzlocal_getByte(fin,&i);
+ x += ((uLong)i)<<8;
+
+ if (err==UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+local int unzlocal_getLong (fin,pX)
+ FILE* fin;
+ uLong *pX;
+{
+ uLong x ;
+ int i;
+ int err;
+
+ err = unzlocal_getByte(fin,&i);
+ x = (uLong)i;
+
+ if (err==UNZ_OK)
+ err = unzlocal_getByte(fin,&i);
+ x += ((uLong)i)<<8;
+
+ if (err==UNZ_OK)
+ err = unzlocal_getByte(fin,&i);
+ x += ((uLong)i)<<16;
+
+ if (err==UNZ_OK)
+ err = unzlocal_getByte(fin,&i);
+ x += ((uLong)i)<<24;
+
+ if (err==UNZ_OK)
+ *pX = x;
+ else
+ *pX = 0;
+ return err;
+}
+
+
+/* My own strcmpi / strcasecmp */
+local int strcmpcasenosensitive_internal (fileName1,fileName2)
+ const char* fileName1;
+ const char* fileName2;
+{
+ for (;;)
+ {
+ char c1=*(fileName1++);
+ char c2=*(fileName2++);
+ if ((c1>='a') && (c1<='z'))
+ c1 -= 0x20;
+ if ((c2>='a') && (c2<='z'))
+ c2 -= 0x20;
+ if (c1=='\0')
+ return ((c2=='\0') ? 0 : -1);
+ if (c2=='\0')
+ return 1;
+ if (c1<c2)
+ return -1;
+ if (c1>c2)
+ return 1;
+ }
+}
+
+
+#ifdef CASESENSITIVITYDEFAULT_NO
+#define CASESENSITIVITYDEFAULTVALUE 2
+#else
+#define CASESENSITIVITYDEFAULTVALUE 1
+#endif
+
+#ifndef STRCMPCASENOSENTIVEFUNCTION
+#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
+#endif
+
+/*
+ Compare two filename (fileName1,fileName2).
+ If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+ If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+ or strcasecmp)
+ If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+ (like 1 on Unix, 2 on Windows)
+
+*/
+extern int ZEXPORT unzStringFileNameCompare (fileName1,fileName2,iCaseSensitivity)
+ const char* fileName1;
+ const char* fileName2;
+ int iCaseSensitivity;
+{
+ if (iCaseSensitivity==0)
+ iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
+
+ if (iCaseSensitivity==1)
+ return strcmp(fileName1,fileName2);
+
+ return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
+}
+
+#define BUFREADCOMMENT (0x400)
+
+/*
+ Locate the Central directory of a zipfile (at the end, just before
+ the global comment)
+*/
+local uLong unzlocal_SearchCentralDir(fin)
+ FILE *fin;
+{
+ unsigned char* buf;
+ uLong uSizeFile;
+ uLong uBackRead;
+ uLong uMaxBack=0xffff; /* maximum size of global comment */
+ uLong uPosFound=0;
+
+ if (fseek(fin,0,SEEK_END) != 0)
+ return 0;
+
+
+ uSizeFile = ftell( fin );
+
+ if (uMaxBack>uSizeFile)
+ uMaxBack = uSizeFile;
+
+ buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4);
+ if (buf==NULL)
+ return 0;
+
+ uBackRead = 4;
+ while (uBackRead<uMaxBack)
+ {
+ uLong uReadSize,uReadPos ;
+ int i;
+ if (uBackRead+BUFREADCOMMENT>uMaxBack)
+ uBackRead = uMaxBack;
+ else
+ uBackRead+=BUFREADCOMMENT;
+ uReadPos = uSizeFile-uBackRead ;
+
+ uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ?
+ (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
+ if (fseek(fin,uReadPos,SEEK_SET)!=0)
+ break;
+
+ if (fread(buf,(uInt)uReadSize,1,fin)!=1)
+ break;
+
+ for (i=(int)uReadSize-3; (i--)>0;)
+ if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) &&
+ ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+ {
+ uPosFound = uReadPos+i;
+ break;
+ }
+
+ if (uPosFound!=0)
+ break;
+ }
+ TRYFREE(buf);
+ return uPosFound;
+}
+
+/*
+ Open a Zip file. path contain the full pathname (by example,
+ on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer
+ "zlib/zlib109.zip".
+ If the zipfile cannot be opened (file don't exist or in not valid), the
+ return value is NULL.
+ Else, the return value is a unzFile Handle, usable with other function
+ of this unzip package.
+*/
+extern unzFile ZEXPORT unzOpen(path)
+ const char *path;
+{
+ unz_s us;
+ unz_s *s;
+ uLong central_pos,uL;
+ FILE * fin ;
+
+ uLong number_disk; /* number of the current dist, used for
+ spaning ZIP, unsupported, always 0*/
+ uLong number_disk_with_CD; /* number the the disk with central dir, used
+ for spaning ZIP, unsupported, always 0*/
+ uLong number_entry_CD; /* total number of entries in
+ the central dir
+ (same than number_entry on nospan) */
+
+ int err=UNZ_OK;
+
+ if (unz_copyright[0]!=' ')
+ return NULL;
+
+ fin=FCEUD_UTF8fopen(path,"rb");
+ //fin=fopen(path,"rb");
+ if (fin==NULL)
+ return NULL;
+
+ central_pos = unzlocal_SearchCentralDir(fin);
+ if (central_pos==0)
+ err=UNZ_ERRNO;
+
+ if (fseek(fin,central_pos,SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+ /* the signature, already checked */
+ if (unzlocal_getLong(fin,&uL)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of this disk */
+ if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* number of the disk with the start of the central directory */
+ if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central dir on this disk */
+ if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* total number of entries in the central dir */
+ if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if ((number_entry_CD!=us.gi.number_entry) ||
+ (number_disk_with_CD!=0) ||
+ (number_disk!=0))
+ err=UNZ_BADZIPFILE;
+
+ /* size of the central directory */
+ if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* offset of start of central directory with respect to the
+ starting disk number */
+ if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ /* zipfile comment length */
+ if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if ((central_pos<us.offset_central_dir+us.size_central_dir) &&
+ (err==UNZ_OK))
+ err=UNZ_BADZIPFILE;
+
+ if (err!=UNZ_OK)
+ {
+ fclose(fin);
+ return NULL;
+ }
+
+ us.file=fin;
+ us.byte_before_the_zipfile = central_pos -
+ (us.offset_central_dir+us.size_central_dir);
+ us.central_pos = central_pos;
+ us.pfile_in_zip_read = NULL;
+
+
+ s=(unz_s*)ALLOC(sizeof(unz_s));
+ *s=us;
+ unzGoToFirstFile((unzFile)s);
+ return (unzFile)s;
+}
+
+
+/*
+ Close a ZipFile opened with unzipOpen.
+ If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
+ these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+ return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzClose (file)
+ unzFile file;
+{
+ unz_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+
+ if (s->pfile_in_zip_read!=NULL)
+ unzCloseCurrentFile(file);
+
+ fclose(s->file);
+ TRYFREE(s);
+ return UNZ_OK;
+}
+
+
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem. */
+extern int ZEXPORT unzGetGlobalInfo (file,pglobal_info)
+ unzFile file;
+ unz_global_info *pglobal_info;
+{
+ unz_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ *pglobal_info=s->gi;
+ return UNZ_OK;
+}
+
+
+/*
+ Translate date/time from Dos format to tm_unz (readable more easilty)
+*/
+local void unzlocal_DosDateToTmuDate (ulDosDate, ptm)
+ uLong ulDosDate;
+ tm_unz* ptm;
+{
+ uLong uDate;
+ uDate = (uLong)(ulDosDate>>16);
+ ptm->tm_mday = (uInt)(uDate&0x1f) ;
+ ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ;
+ ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
+
+ ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
+ ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ;
+ ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ;
+}
+
+/*
+ Get Info about the current file in the zipfile, with internal only info
+*/
+local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file,
+ unz_file_info *pfile_info,
+ unz_file_info_internal
+ *pfile_info_internal,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize));
+
+local int unzlocal_GetCurrentFileInfoInternal (file,
+ pfile_info,
+ pfile_info_internal,
+ szFileName, fileNameBufferSize,
+ extraField, extraFieldBufferSize,
+ szComment, commentBufferSize)
+ unzFile file;
+ unz_file_info *pfile_info;
+ unz_file_info_internal *pfile_info_internal;
+ char *szFileName;
+ uLong fileNameBufferSize;
+ void *extraField;
+ uLong extraFieldBufferSize;
+ char *szComment;
+ uLong commentBufferSize;
+{
+ unz_s* s;
+ unz_file_info file_info;
+ unz_file_info_internal file_info_internal;
+ int err=UNZ_OK;
+ uLong uMagic;
+ long lSeek=0;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
+ err=UNZ_ERRNO;
+
+
+ /* we check the magic */
+ if (err==UNZ_OK)
+ {
+ if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if (uMagic!=0x02014b50)
+ err=UNZ_BADZIPFILE;
+ }
+
+ if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
+
+ if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ lSeek+=file_info.size_filename;
+ if ((err==UNZ_OK) && (szFileName!=NULL))
+ {
+ uLong uSizeRead ;
+ if (file_info.size_filename<fileNameBufferSize)
+ {
+ *(szFileName+file_info.size_filename)='\0';
+ uSizeRead = file_info.size_filename;
+ }
+ else
+ uSizeRead = fileNameBufferSize;
+
+ if ((file_info.size_filename>0) && (fileNameBufferSize>0))
+ if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
+ err=UNZ_ERRNO;
+ lSeek -= uSizeRead;
+ }
+
+
+ if ((err==UNZ_OK) && (extraField!=NULL))
+ {
+ uLong uSizeRead ;
+ if (file_info.size_file_extra<extraFieldBufferSize)
+ uSizeRead = file_info.size_file_extra;
+ else
+ uSizeRead = extraFieldBufferSize;
+
+ if (lSeek!=0)
+ {
+ if (fseek(s->file,lSeek,SEEK_CUR)==0)
+ lSeek=0;
+ else
+ err=UNZ_ERRNO;
+ }
+ if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
+ if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1)
+ err=UNZ_ERRNO;
+ lSeek += file_info.size_file_extra - uSizeRead;
+ }
+ else
+ lSeek+=file_info.size_file_extra;
+
+
+ if ((err==UNZ_OK) && (szComment!=NULL))
+ {
+ uLong uSizeRead ;
+ if (file_info.size_file_comment<commentBufferSize)
+ {
+ *(szComment+file_info.size_file_comment)='\0';
+ uSizeRead = file_info.size_file_comment;
+ }
+ else
+ uSizeRead = commentBufferSize;
+
+ if (lSeek!=0)
+ {
+ if (fseek(s->file,lSeek,SEEK_CUR)==0)
+ lSeek=0;
+ else
+ err=UNZ_ERRNO;
+ }
+ if ((file_info.size_file_comment>0) && (commentBufferSize>0))
+ if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
+ err=UNZ_ERRNO;
+ lSeek+=file_info.size_file_comment - uSizeRead;
+ }
+ else
+ lSeek+=file_info.size_file_comment;
+
+ if ((err==UNZ_OK) && (pfile_info!=NULL))
+ *pfile_info=file_info;
+
+ if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
+ *pfile_info_internal=file_info_internal;
+
+ return err;
+}
+
+
+
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem.
+*/
+extern int ZEXPORT unzGetCurrentFileInfo (file,
+ pfile_info,
+ szFileName, fileNameBufferSize,
+ extraField, extraFieldBufferSize,
+ szComment, commentBufferSize)
+ unzFile file;
+ unz_file_info *pfile_info;
+ char *szFileName;
+ uLong fileNameBufferSize;
+ void *extraField;
+ uLong extraFieldBufferSize;
+ char *szComment;
+ uLong commentBufferSize;
+{
+ return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
+ szFileName,fileNameBufferSize,
+ extraField,extraFieldBufferSize,
+ szComment,commentBufferSize);
+}
+
+/*
+ Set the current file of the zipfile to the first file.
+ return UNZ_OK if there is no problem
+*/
+extern int ZEXPORT unzGoToFirstFile (file)
+ unzFile file;
+{
+ int err=UNZ_OK;
+ unz_s* s;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ s->pos_in_central_dir=s->offset_central_dir;
+ s->num_file=0;
+ err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+
+/*
+ Set the current file of the zipfile to the next file.
+ return UNZ_OK if there is no problem
+ return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+extern int ZEXPORT unzGoToNextFile (file)
+ unzFile file;
+{
+ unz_s* s;
+ int err;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+ if (s->num_file+1==s->gi.number_entry)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
+ s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
+ s->num_file++;
+ err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+ &s->cur_file_info_internal,
+ NULL,0,NULL,0,NULL,0);
+ s->current_file_ok = (err == UNZ_OK);
+ return err;
+}
+
+
+/*
+ Try locate the file szFileName in the zipfile.
+ For the iCaseSensitivity signification, see unzipStringFileNameCompare
+
+ return value :
+ UNZ_OK if the file is found. It becomes the current file.
+ UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+extern int ZEXPORT unzLocateFile (file, szFileName, iCaseSensitivity)
+ unzFile file;
+ const char *szFileName;
+ int iCaseSensitivity;
+{
+ unz_s* s;
+ int err;
+
+
+ uLong num_fileSaved;
+ uLong pos_in_central_dirSaved;
+
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+
+ if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
+ return UNZ_PARAMERROR;
+
+ s=(unz_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_END_OF_LIST_OF_FILE;
+
+ num_fileSaved = s->num_file;
+ pos_in_central_dirSaved = s->pos_in_central_dir;
+
+ err = unzGoToFirstFile(file);
+
+ while (err == UNZ_OK)
+ {
+ char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
+ unzGetCurrentFileInfo(file,NULL,
+ szCurrentFileName,sizeof(szCurrentFileName)-1,
+ NULL,0,NULL,0);
+ if (unzStringFileNameCompare(szCurrentFileName,
+ szFileName,iCaseSensitivity)==0)
+ return UNZ_OK;
+ err = unzGoToNextFile(file);
+ }
+
+ s->num_file = num_fileSaved ;
+ s->pos_in_central_dir = pos_in_central_dirSaved ;
+ return err;
+}
+
+
+/*
+ Read the local header of the current zipfile
+ Check the coherency of the local header and info in the end of central
+ directory about this file
+ store in *piSizeVar the size of extra info in local header
+ (filename and size of extra field data)
+*/
+local int unzlocal_CheckCurrentFileCoherencyHeader (s,piSizeVar,
+ poffset_local_extrafield,
+ psize_local_extrafield)
+ unz_s* s;
+ uInt* piSizeVar;
+ uLong *poffset_local_extrafield;
+ uInt *psize_local_extrafield;
+{
+ uLong uMagic,uData,uFlags;
+ uLong size_filename;
+ uLong size_extra_field;
+ int err=UNZ_OK;
+
+ *piSizeVar = 0;
+ *poffset_local_extrafield = 0;
+ *psize_local_extrafield = 0;
+
+ if (fseek(s->file,s->cur_file_info_internal.offset_curfile +
+ s->byte_before_the_zipfile,SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+
+ if (err==UNZ_OK)
+ {
+ if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if (uMagic!=0x04034b50)
+ err=UNZ_BADZIPFILE;
+ }
+
+ if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
+ err=UNZ_ERRNO;
+/*
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
+ err=UNZ_BADZIPFILE;
+*/
+ if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
+ err=UNZ_BADZIPFILE;
+
+ if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
+ (s->cur_file_info.compression_method!=Z_DEFLATED))
+ err=UNZ_BADZIPFILE;
+
+ if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
+ err=UNZ_ERRNO;
+
+ if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
+ ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+ if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
+ ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+ if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) &&
+ ((uFlags & 8)==0))
+ err=UNZ_BADZIPFILE;
+
+
+ if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
+ err=UNZ_ERRNO;
+ else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
+ err=UNZ_BADZIPFILE;
+
+ *piSizeVar += (uInt)size_filename;
+
+ if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
+ err=UNZ_ERRNO;
+ *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
+ SIZEZIPLOCALHEADER + size_filename;
+ *psize_local_extrafield = (uInt)size_extra_field;
+
+ *piSizeVar += (uInt)size_extra_field;
+
+ return err;
+}
+
+/*
+ Open for reading data the current file in the zipfile.
+ If there is no error and the file is opened, the return value is UNZ_OK.
+*/
+extern int ZEXPORT unzOpenCurrentFile (file)
+ unzFile file;
+{
+ int err=UNZ_OK;
+ int Store;
+ uInt iSizeVar;
+ unz_s* s;
+ file_in_zip_read_info_s* pfile_in_zip_read_info;
+ uLong offset_local_extrafield; /* offset of the local extra field */
+ uInt size_local_extrafield; /* size of the local extra field */
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ if (!s->current_file_ok)
+ return UNZ_PARAMERROR;
+
+ if (s->pfile_in_zip_read != NULL)
+ unzCloseCurrentFile(file);
+
+ if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
+ &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
+ return UNZ_BADZIPFILE;
+
+ pfile_in_zip_read_info = (file_in_zip_read_info_s*)
+ ALLOC(sizeof(file_in_zip_read_info_s));
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_INTERNALERROR;
+
+ pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE);
+ pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
+ pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
+ pfile_in_zip_read_info->pos_local_extrafield=0;
+
+ if (pfile_in_zip_read_info->read_buffer==NULL)
+ {
+ TRYFREE(pfile_in_zip_read_info);
+ return UNZ_INTERNALERROR;
+ }
+
+ pfile_in_zip_read_info->stream_initialised=0;
+
+ if ((s->cur_file_info.compression_method!=0) &&
+ (s->cur_file_info.compression_method!=Z_DEFLATED))
+ err=UNZ_BADZIPFILE;
+ Store = s->cur_file_info.compression_method==0;
+
+ pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
+ pfile_in_zip_read_info->crc32=0;
+ pfile_in_zip_read_info->compression_method =
+ s->cur_file_info.compression_method;
+ pfile_in_zip_read_info->file=s->file;
+ pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
+
+ pfile_in_zip_read_info->stream.total_out = 0;
+
+ if (!Store)
+ {
+ pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+ pfile_in_zip_read_info->stream.zfree = (free_func)0;
+ pfile_in_zip_read_info->stream.opaque = (voidpf)0;
+
+ err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
+ if (err == Z_OK)
+ pfile_in_zip_read_info->stream_initialised=1;
+ /* windowBits is passed < 0 to tell that there is no zlib header.
+ * Note that in this case inflate *requires* an extra "dummy" byte
+ * after the compressed stream in order to complete decompression and
+ * return Z_STREAM_END.
+ * In unzip, i don't wait absolutely Z_STREAM_END because I known the
+ * size of both compressed and uncompressed data
+ */
+ }
+ pfile_in_zip_read_info->rest_read_compressed =
+ s->cur_file_info.compressed_size ;
+ pfile_in_zip_read_info->rest_read_uncompressed =
+ s->cur_file_info.uncompressed_size ;
+
+
+ pfile_in_zip_read_info->pos_in_zipfile =
+ s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER +
+ iSizeVar;
+
+ pfile_in_zip_read_info->stream.avail_in = (uInt)0;
+
+
+ s->pfile_in_zip_read = pfile_in_zip_read_info;
+ return UNZ_OK;
+}
+
+
+/*
+ Read bytes from the current file.
+ buf contain buffer where data must be copied
+ len the size of buf.
+
+ return the number of byte copied if somes bytes are copied
+ return 0 if the end of file was reached
+ return <0 with error code if there is an error
+ (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+extern int ZEXPORT unzReadCurrentFile (file, buf, len)
+ unzFile file;
+ voidp buf;
+ unsigned len;
+{
+ int err=UNZ_OK;
+ uInt iRead = 0;
+ unz_s* s;
+ file_in_zip_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+
+ if ((pfile_in_zip_read_info->read_buffer == NULL))
+ return UNZ_END_OF_LIST_OF_FILE;
+ if (len==0)
+ return 0;
+
+ pfile_in_zip_read_info->stream.next_out = (Bytef*)buf;
+
+ pfile_in_zip_read_info->stream.avail_out = (uInt)len;
+
+ if (len>pfile_in_zip_read_info->rest_read_uncompressed)
+ pfile_in_zip_read_info->stream.avail_out =
+ (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
+
+ while (pfile_in_zip_read_info->stream.avail_out>0)
+ {
+ if ((pfile_in_zip_read_info->stream.avail_in==0) &&
+ (pfile_in_zip_read_info->rest_read_compressed>0))
+ {
+ uInt uReadThis = UNZ_BUFSIZE;
+ if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
+ uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
+ if (uReadThis == 0)
+ return UNZ_EOF;
+ if (fseek(pfile_in_zip_read_info->file,
+ pfile_in_zip_read_info->pos_in_zipfile +
+ pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
+ return UNZ_ERRNO;
+ if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
+ pfile_in_zip_read_info->file)!=1)
+ return UNZ_ERRNO;
+ pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+
+ pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
+
+ pfile_in_zip_read_info->stream.next_in =
+ (Bytef*)pfile_in_zip_read_info->read_buffer;
+ pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
+ }
+
+ if (pfile_in_zip_read_info->compression_method==0)
+ {
+ uInt uDoCopy,i ;
+ if (pfile_in_zip_read_info->stream.avail_out <
+ pfile_in_zip_read_info->stream.avail_in)
+ uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
+ else
+ uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
+
+ for (i=0;i<uDoCopy;i++)
+ *(pfile_in_zip_read_info->stream.next_out+i) =
+ *(pfile_in_zip_read_info->stream.next_in+i);
+
+ pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
+ pfile_in_zip_read_info->stream.next_out,
+ uDoCopy);
+ pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
+ pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
+ pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
+ pfile_in_zip_read_info->stream.next_out += uDoCopy;
+ pfile_in_zip_read_info->stream.next_in += uDoCopy;
+ pfile_in_zip_read_info->stream.total_out += uDoCopy;
+ iRead += uDoCopy;
+ }
+ else
+ {
+ uLong uTotalOutBefore,uTotalOutAfter;
+ const Bytef *bufBefore;
+ uLong uOutThis;
+ int flush=Z_SYNC_FLUSH;
+
+ uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
+ bufBefore = pfile_in_zip_read_info->stream.next_out;
+
+ /*
+ if ((pfile_in_zip_read_info->rest_read_uncompressed ==
+ pfile_in_zip_read_info->stream.avail_out) &&
+ (pfile_in_zip_read_info->rest_read_compressed == 0))
+ flush = Z_FINISH;
+ */
+ err=inflate(&pfile_in_zip_read_info->stream,flush);
+
+ uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
+ uOutThis = uTotalOutAfter-uTotalOutBefore;
+
+ pfile_in_zip_read_info->crc32 =
+ crc32(pfile_in_zip_read_info->crc32,bufBefore,
+ (uInt)(uOutThis));
+
+ pfile_in_zip_read_info->rest_read_uncompressed -=
+ uOutThis;
+
+ iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
+
+ if (err==Z_STREAM_END)
+ return (iRead==0) ? UNZ_EOF : iRead;
+ if (err!=Z_OK)
+ break;
+ }
+ }
+
+ if (err==Z_OK)
+ return iRead;
+ return err;
+}
+
+
+/*
+ Give the current position in uncompressed data
+*/
+extern z_off_t ZEXPORT unztell (file)
+ unzFile file;
+{
+ unz_s* s;
+ file_in_zip_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+ return (z_off_t)pfile_in_zip_read_info->stream.total_out;
+}
+
+
+/*
+ return 1 if the end of file was reached, 0 elsewhere
+*/
+extern int ZEXPORT unzeof (file)
+ unzFile file;
+{
+ unz_s* s;
+ file_in_zip_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+ if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
+ return 1;
+ else
+ return 0;
+}
+
+
+
+/*
+ Read extra field from the current file (opened by unzOpenCurrentFile)
+ This is the local-header version of the extra field (sometimes, there is
+ more info in the local-header version than in the central-header)
+
+ if buf==NULL, it return the size of the local extra field that can be read
+
+ if buf!=NULL, len is the size of the buffer, the extra header is copied in
+ buf.
+ the return value is the number of bytes copied in buf, or (if <0)
+ the error code
+*/
+extern int ZEXPORT unzGetLocalExtrafield (file,buf,len)
+ unzFile file;
+ voidp buf;
+ unsigned len;
+{
+ unz_s* s;
+ file_in_zip_read_info_s* pfile_in_zip_read_info;
+ uInt read_now;
+ uLong size_to_read;
+
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+ size_to_read = (pfile_in_zip_read_info->size_local_extrafield -
+ pfile_in_zip_read_info->pos_local_extrafield);
+
+ if (buf==NULL)
+ return (int)size_to_read;
+
+ if (len>size_to_read)
+ read_now = (uInt)size_to_read;
+ else
+ read_now = (uInt)len ;
+
+ if (read_now==0)
+ return 0;
+
+ if (fseek(pfile_in_zip_read_info->file,
+ pfile_in_zip_read_info->offset_local_extrafield +
+ pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+ if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
+ return UNZ_ERRNO;
+
+ return (int)read_now;
+}
+
+/*
+ Close the file in zip opened with unzipOpenCurrentFile
+ Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+extern int ZEXPORT unzCloseCurrentFile (file)
+ unzFile file;
+{
+ int err=UNZ_OK;
+
+ unz_s* s;
+ file_in_zip_read_info_s* pfile_in_zip_read_info;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+ pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+ if (pfile_in_zip_read_info==NULL)
+ return UNZ_PARAMERROR;
+
+
+ if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
+ {
+ if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
+ err=UNZ_CRCERROR;
+ }
+
+
+ TRYFREE(pfile_in_zip_read_info->read_buffer);
+ pfile_in_zip_read_info->read_buffer = NULL;
+ if (pfile_in_zip_read_info->stream_initialised)
+ inflateEnd(&pfile_in_zip_read_info->stream);
+
+ pfile_in_zip_read_info->stream_initialised = 0;
+ TRYFREE(pfile_in_zip_read_info);
+
+ s->pfile_in_zip_read=NULL;
+
+ return err;
+}
+
+
+/*
+ Get the global comment string of the ZipFile, in the szComment buffer.
+ uSizeBuf is the size of the szComment buffer.
+ return the number of byte copied or an error code <0
+*/
+extern int ZEXPORT unzGetGlobalComment (file, szComment, uSizeBuf)
+ unzFile file;
+ char *szComment;
+ uLong uSizeBuf;
+{
+ unz_s* s;
+ uLong uReadThis ;
+ if (file==NULL)
+ return UNZ_PARAMERROR;
+ s=(unz_s*)file;
+
+ uReadThis = uSizeBuf;
+ if (uReadThis>s->gi.size_comment)
+ uReadThis = s->gi.size_comment;
+
+ if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
+ return UNZ_ERRNO;
+
+ if (uReadThis>0)
+ {
+ *szComment='\0';
+ if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
+ return UNZ_ERRNO;
+ }
+
+ if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
+ *(szComment+s->gi.size_comment)='\0';
+ return (int)uReadThis;
+}
diff --git a/unzip.h b/unzip.h
new file mode 100644
index 00000000..eaad06b0
--- /dev/null
+++ b/unzip.h
@@ -0,0 +1,279 @@
+/* unzip.h -- IO for uncompress .zip files using zlib
+ Version 0.15 beta, Mar 19th, 1998,
+
+ Copyright (C) 1998 Gilles Vollant
+
+ This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
+ WinZip, InfoZip tools and compatible.
+ Encryption and multi volume ZipFile (span) are not supported.
+ Old compressions used by old PKZip 1.x are not supported
+
+ THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE
+ CAN CHANGE IN FUTURE VERSION !!
+ I WAIT FEEDBACK at mail info@winimage.com
+ Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
+
+ Condition of use and distribution are the same than zlib :
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+
+
+*/
+/* for more info about .ZIP format, see
+ ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip
+ PkWare has also a specification at :
+ ftp://ftp.pkware.com/probdesc.zip */
+
+#ifndef _unz_H
+#define _unz_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _ZLIB_H
+#include "zlib.h"
+#endif
+
+#ifndef OF
+#define OF(a) a
+#endif
+
+#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+ from (void*) without cast */
+typedef struct TagunzFile__ { int unused; } unzFile__;
+typedef unzFile__ *unzFile;
+#else
+typedef voidp unzFile;
+#endif
+
+
+#define UNZ_OK (0)
+#define UNZ_END_OF_LIST_OF_FILE (-100)
+#define UNZ_ERRNO (Z_ERRNO)
+#define UNZ_EOF (0)
+#define UNZ_PARAMERROR (-102)
+#define UNZ_BADZIPFILE (-103)
+#define UNZ_INTERNALERROR (-104)
+#define UNZ_CRCERROR (-105)
+
+/* tm_unz contain date/time info */
+typedef struct tm_unz_s
+{
+ uInt tm_sec; /* seconds after the minute - [0,59] */
+ uInt tm_min; /* minutes after the hour - [0,59] */
+ uInt tm_hour; /* hours since midnight - [0,23] */
+ uInt tm_mday; /* day of the month - [1,31] */
+ uInt tm_mon; /* months since January - [0,11] */
+ uInt tm_year; /* years - [1980..2044] */
+} tm_unz;
+
+/* unz_global_info structure contain global data about the ZIPfile
+ These data comes from the end of central dir */
+typedef struct unz_global_info_s
+{
+ uLong number_entry; /* total number of entries in
+ the central dir on this disk */
+ uLong size_comment; /* size of the global comment of the zipfile */
+} unz_global_info;
+
+
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_info_s
+{
+ uLong version; /* version made by 2 bytes */
+ uLong version_needed; /* version needed to extract 2 bytes */
+ uLong flag; /* general purpose bit flag 2 bytes */
+ uLong compression_method; /* compression method 2 bytes */
+ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
+ uLong crc; /* crc-32 4 bytes */
+ uLong compressed_size; /* compressed size 4 bytes */
+ uLong uncompressed_size; /* uncompressed size 4 bytes */
+ uLong size_filename; /* filename length 2 bytes */
+ uLong size_file_extra; /* extra field length 2 bytes */
+ uLong size_file_comment; /* file comment length 2 bytes */
+
+ uLong disk_num_start; /* disk number start 2 bytes */
+ uLong internal_fa; /* internal file attributes 2 bytes */
+ uLong external_fa; /* external file attributes 4 bytes */
+
+ tm_unz tmu_date;
+} unz_file_info;
+
+extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
+ const char* fileName2,
+ int iCaseSensitivity));
+/*
+ Compare two filename (fileName1,fileName2).
+ If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+ If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+ or strcasecmp)
+ If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+ (like 1 on Unix, 2 on Windows)
+*/
+
+
+extern unzFile ZEXPORT unzOpen OF((const char *path));
+/*
+ Open a Zip file. path contain the full pathname (by example,
+ on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
+ "zlib/zlib111.zip".
+ If the zipfile cannot be opened (file don't exist or in not valid), the
+ return value is NULL.
+ Else, the return value is a unzFile Handle, usable with other function
+ of this unzip package.
+*/
+
+extern int ZEXPORT unzClose OF((unzFile file));
+/*
+ Close a ZipFile opened with unzipOpen.
+ If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+ these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+ return UNZ_OK if there is no problem. */
+
+extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
+ unz_global_info *pglobal_info));
+/*
+ Write info about the ZipFile in the *pglobal_info structure.
+ No preparation of the structure is needed
+ return UNZ_OK if there is no problem. */
+
+
+extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
+ char *szComment,
+ uLong uSizeBuf));
+/*
+ Get the global comment string of the ZipFile, in the szComment buffer.
+ uSizeBuf is the size of the szComment buffer.
+ return the number of byte copied or an error code <0
+*/
+
+
+/***************************************************************************/
+/* Unzip package allow you browse the directory of the zipfile */
+
+extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
+/*
+ Set the current file of the zipfile to the first file.
+ return UNZ_OK if there is no problem
+*/
+
+extern int ZEXPORT unzGoToNextFile OF((unzFile file));
+/*
+ Set the current file of the zipfile to the next file.
+ return UNZ_OK if there is no problem
+ return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+
+extern int ZEXPORT unzLocateFile OF((unzFile file,
+ const char *szFileName,
+ int iCaseSensitivity));
+/*
+ Try locate the file szFileName in the zipfile.
+ For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+ return value :
+ UNZ_OK if the file is found. It becomes the current file.
+ UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+
+
+extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
+ unz_file_info *pfile_info,
+ char *szFileName,
+ uLong fileNameBufferSize,
+ void *extraField,
+ uLong extraFieldBufferSize,
+ char *szComment,
+ uLong commentBufferSize));
+/*
+ Get Info about the current file
+ if pfile_info!=NULL, the *pfile_info structure will contain somes info about
+ the current file
+ if szFileName!=NULL, the filemane string will be copied in szFileName
+ (fileNameBufferSize is the size of the buffer)
+ if extraField!=NULL, the extra field information will be copied in extraField
+ (extraFieldBufferSize is the size of the buffer).
+ This is the Central-header version of the extra field
+ if szComment!=NULL, the comment string of the file will be copied in szComment
+ (commentBufferSize is the size of the buffer)
+*/
+
+/***************************************************************************/
+/* for reading the content of the current zipfile, you can open it, read data
+ from it, and close it (you can close it before reading all the file)
+ */
+
+extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
+/*
+ Open for reading data the current file in the zipfile.
+ If there is no error, the return value is UNZ_OK.
+*/
+
+extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
+/*
+ Close the file in zip opened with unzOpenCurrentFile
+ Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+
+
+extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
+ voidp buf,
+ unsigned len));
+/*
+ Read bytes from the current file (opened by unzOpenCurrentFile)
+ buf contain buffer where data must be copied
+ len the size of buf.
+
+ return the number of byte copied if somes bytes are copied
+ return 0 if the end of file was reached
+ return <0 with error code if there is an error
+ (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+
+extern z_off_t ZEXPORT unztell OF((unzFile file));
+/*
+ Give the current position in uncompressed data
+*/
+
+extern int ZEXPORT unzeof OF((unzFile file));
+/*
+ return 1 if the end of file was reached, 0 elsewhere
+*/
+
+extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
+ voidp buf,
+ unsigned len));
+/*
+ Read extra field from the current file (opened by unzOpenCurrentFile)
+ This is the local-header version of the extra field (sometimes, there is
+ more info in the local-header version than in the central-header)
+
+ if buf==NULL, it return the size of the local extra field
+
+ if buf!=NULL, len is the size of the buffer, the extra header is copied in
+ buf.
+ the return value is the number of bytes copied in buf, or (if <0)
+ the error code
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _unz_H */
diff --git a/vc8/fceuxdsp.ncb b/vc8/fceuxdsp.ncb
new file mode 100644
index 00000000..b22a6ff4
--- /dev/null
+++ b/vc8/fceuxdsp.ncb
Binary files differ
diff --git a/vc8/fceuxdsp.sln b/vc8/fceuxdsp.sln
new file mode 100644
index 00000000..4db4ec10
--- /dev/null
+++ b/vc8/fceuxdsp.sln
@@ -0,0 +1,26 @@
+
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fceuxdsp", "fceuxdsp.vcproj", "{6893EF44-FEA3-46DF-B236-C4C200F54294}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {6893EF44-FEA3-46DF-B236-C4C200F54294}.Debug|Win32.ActiveCfg = Debug|Win32
+ {6893EF44-FEA3-46DF-B236-C4C200F54294}.Debug|Win32.Build.0 = Debug|Win32
+ {6893EF44-FEA3-46DF-B236-C4C200F54294}.Debug|x64.ActiveCfg = Debug|x64
+ {6893EF44-FEA3-46DF-B236-C4C200F54294}.Debug|x64.Build.0 = Debug|x64
+ {6893EF44-FEA3-46DF-B236-C4C200F54294}.Release|Win32.ActiveCfg = Release|Win32
+ {6893EF44-FEA3-46DF-B236-C4C200F54294}.Release|Win32.Build.0 = Release|Win32
+ {6893EF44-FEA3-46DF-B236-C4C200F54294}.Release|x64.ActiveCfg = Release|x64
+ {6893EF44-FEA3-46DF-B236-C4C200F54294}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/vc8/fceuxdsp.suo b/vc8/fceuxdsp.suo
new file mode 100644
index 00000000..b585d4cc
--- /dev/null
+++ b/vc8/fceuxdsp.suo
Binary files differ
diff --git a/vc8/fceuxdsp.vcproj b/vc8/fceuxdsp.vcproj
new file mode 100644
index 00000000..dc004f5e
--- /dev/null
+++ b/vc8/fceuxdsp.vcproj
@@ -0,0 +1,1778 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="fceuxdsp"
+ ProjectGUID="{6893EF44-FEA3-46DF-B236-C4C200F54294}"
+ RootNamespace="fceuxdsp"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ <Platform
+ Name="x64"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../zlib"
+ PreprocessorDefinitions="WIN32;_DEBUG;MSVC;_CRT_SECURE_NO_DEPRECATE;_WIN32_WINDOWS=0x0410;WINVER=0x0410;NETWORK;LSB_FIRST;_USE_32BIT_TIME_T;FCEUDEF_DEBUGGER"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ DisableLanguageExtensions="false"
+ ForceConformanceInForLoopScope="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="false"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="dxguid.lib winmm.lib dinput.lib ws2_32.lib ddraw.lib dsound.lib"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ EntryPointSymbol="mainCRTStartup"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../zlib"
+ PreprocessorDefinitions="WIN32;_DEBUG;MSVC;_CRT_SECURE_NO_DEPRECATE;_WIN32_WINDOWS=0x0410;WINVER=0x0410;NETWORK;LSB_FIRST"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ DisableLanguageExtensions="false"
+ ForceConformanceInForLoopScope="false"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="dxguid.lib winmm.lib dinput.lib ws2_32.lib ddraw.lib dsound.lib"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ EntryPointSymbol="mainCRTStartup"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="../zlib"
+ PreprocessorDefinitions="WIN32;NDEBUG;MSVC;_CRT_SECURE_NO_DEPRECATE;_WIN32_WINDOWS=0x0410;WINVER=0x0410;NETWORK;LSB_FIRST;_USE_32BIT_TIME_T;FCEUDEF_DEBUGGER"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="dxguid.lib winmm.lib dinput.lib ws2_32.lib ddraw.lib dsound.lib"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ EntryPointSymbol="mainCRTStartup"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ OutputDirectory="$(SolutionDir)$(PlatformName)\$(ConfigurationName)"
+ IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ TargetEnvironment="3"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ InlineFunctionExpansion="2"
+ EnableIntrinsicFunctions="true"
+ FavorSizeOrSpeed="1"
+ OmitFramePointers="true"
+ AdditionalIncludeDirectories="../zlib"
+ PreprocessorDefinitions="WIN32;NDEBUG;MSVC;_CRT_SECURE_NO_DEPRECATE;_WIN32_WINDOWS=0x0410;WINVER=0x0410;NETWORK;LSB_FIRST"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="dxguid.lib winmm.lib dinput.lib ws2_32.lib ddraw.lib dsound.lib"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ EntryPointSymbol="mainCRTStartup"
+ TargetMachine="17"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCWebDeploymentTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="src"
+ >
+ <File
+ RelativePath="..\src\cart.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\cheat.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\conddebug.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\crc32.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\debug.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\endian.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\fceu.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\fds.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\file.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\filter.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\general.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\ines.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\md5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\memory.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\movie.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\netplay.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\nsf.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\palette.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\ppu.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sound.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\state.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\unif.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\video.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\vsuni.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\wave.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x6502.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\xstring.c"
+ >
+ </File>
+ <Filter
+ Name="boards"
+ >
+ <File
+ RelativePath="..\src\boards\01-222.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\112.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\117.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\164.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\183.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\185.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\186.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\187.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\189.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\199.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\208.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\222.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\235.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\43.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\57.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\603-5052.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\8157.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\8237.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\88.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\90.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\95.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\__dummy_mapper.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\a9711.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\addrlatch.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\bmc13in1jy110.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\bmc42in1r.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\bmc64in1nr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\bmc70in1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\bonza.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\datalatch.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\deirom.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\dream.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\edu2000.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\fk23c.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\h2288.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\karaoke.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\kof97.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\konami-qtai.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\malee.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\mapinc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\mmc1.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\mmc3.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\mmc3.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\mmc5.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\n-c22m.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\n106.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\novel.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\sachen.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\sheroes.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\sl1632.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\subor.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\super24.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\supervision.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\t-262.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\boards\tengen.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="mappers"
+ >
+ <File
+ RelativePath="..\src\mappers\15.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\151.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\16.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\17.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\18.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\193.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\200.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\201.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\202.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\203.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\204.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\21.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\212.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\213.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\214.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\215.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\217.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\22.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\225.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\227.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\228.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\229.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\23.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\230.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\231.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\232.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\234.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\240.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\241.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\242.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\244.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\246.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\24and26.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\25.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\255.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\27.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\33.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\40.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\41.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\42.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\43.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\mappers\46.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\50.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\51.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\59.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\6.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\60.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\61.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\62.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\65.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\67.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\68.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\69.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\71.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\72.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\73.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\75.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\76.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\77.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\79.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\8.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\80.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\82.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\83.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\85.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\86.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\89.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\91.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\92.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\97.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\99.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\__226.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\emu2413.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\emu2413.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\emutypes.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\mapinc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\mmc2and4.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\simple.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\mappers\vrc7tone.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="fir"
+ >
+ <File
+ RelativePath="..\src\fir\c44100ntsc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\fir\c44100pal.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\fir\c48000ntsc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\fir\c48000pal.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\fir\c96000ntsc.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\fir\c96000pal.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="input"
+ >
+ <File
+ RelativePath="..\src\input\arkanoid.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\bworld.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\cursor.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\fkb.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\fkb.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\ftrainer.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\hypershot.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\mahjong.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\mouse.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\oekakids.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\pads.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\powerpad.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\quiz.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\shadow.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\share.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\suborkb.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\suborkb.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\toprider.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input\zapper.c"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="drivers"
+ >
+ <Filter
+ Name="common"
+ >
+ <File
+ RelativePath="..\src\drivers\common\args.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\args.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\cheat.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\cheat.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\config.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\config.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\hq2x.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\hq2x.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\hq3x.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\hq3x.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\scale2x.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\scale2x.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\scale3x.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\scale3x.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\scalebit.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\scalebit.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\vidblit.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\common\vidblit.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="win"
+ >
+ <File
+ RelativePath="..\src\drivers\win\cdlogger.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\cheat.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)2.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)2.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\cheat.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\common.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\debugger.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\debuggersp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\debuggersp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\input.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\input.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\joystick.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\joystick.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\keyboard.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\keyboard.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\keyscan.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\log.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\log.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\main.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\memview.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\memviewsp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\netplay.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|x64"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\netplay.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\ntview.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\ppuview.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\pref.c"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\pref.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\res.rc"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drivers\win\tracer.c"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="include files"
+ >
+ <File
+ RelativePath="..\src\cart.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\cdlogger.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\cheat.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\conddebug.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\crc32.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\debug.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\debugger.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\drawing.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\driver.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\endian.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\fceu.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\fcoeffs.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\fds.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\file.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\filter.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\general.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\git.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\ines-bad.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\ines-correct.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\ines.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\input.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\md5.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\memory.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\memview.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\movie.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\netplay.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\nsf.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\ntview.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\ops.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\palette.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\ppu.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\pputile.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\ppuview.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\sound.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\state.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\tracer.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\types.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\unif.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\video.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\vsuni.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\wave.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x6502.h"
+ >
+ </File>
+ <File
+ RelativePath="..\src\x6502struct.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="zlib"
+ >
+ <File
+ RelativePath="..\zlib\adler32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zlib\compress.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zlib\crc32.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zlib\deflate.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zlib\gzio.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zlib\infblock.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zlib\infcodes.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zlib\inffast.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zlib\inflate.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zlib\inftrees.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zlib\infutil.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zlib\trees.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zlib\uncompr.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zlib\unzip.c"
+ >
+ </File>
+ <File
+ RelativePath="..\zlib\zutil.c"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/vc8/fceuxdsp.vcproj.ZERO-XP.Administrator.user b/vc8/fceuxdsp.vcproj.ZERO-XP.Administrator.user
new file mode 100644
index 00000000..10437778
--- /dev/null
+++ b/vc8/fceuxdsp.vcproj.ZERO-XP.Administrator.user
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioUserFile
+ ProjectType="Visual C++"
+ Version="8.00"
+ ShowAllFiles="false"
+ >
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ >
+ <DebugSettings
+ Command="$(TargetPath)"
+ WorkingDirectory=""
+ CommandArguments=""
+ Attach="false"
+ DebuggerType="3"
+ Remote="1"
+ RemoteMachine="ZERO-XP"
+ RemoteCommand=""
+ HttpUrl=""
+ PDBPath=""
+ SQLDebugging=""
+ Environment=""
+ EnvironmentMerge="true"
+ DebuggerFlavor=""
+ MPIRunCommand=""
+ MPIRunArguments=""
+ MPIRunWorkingDirectory=""
+ ApplicationCommand=""
+ ApplicationArguments=""
+ ShimCommand=""
+ MPIAcceptMode=""
+ MPIAcceptFilter=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug|x64"
+ >
+ <DebugSettings
+ Command="$(TargetPath)"
+ WorkingDirectory=""
+ CommandArguments=""
+ Attach="false"
+ DebuggerType="3"
+ Remote="1"
+ RemoteMachine="ZERO-XP"
+ RemoteCommand=""
+ HttpUrl=""
+ PDBPath=""
+ SQLDebugging=""
+ Environment=""
+ EnvironmentMerge="true"
+ DebuggerFlavor=""
+ MPIRunCommand=""
+ MPIRunArguments=""
+ MPIRunWorkingDirectory=""
+ ApplicationCommand=""
+ ApplicationArguments=""
+ ShimCommand=""
+ MPIAcceptMode=""
+ MPIAcceptFilter=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ >
+ <DebugSettings
+ Command="$(TargetPath)"
+ WorkingDirectory=""
+ CommandArguments=""
+ Attach="false"
+ DebuggerType="3"
+ Remote="1"
+ RemoteMachine="ZERO-XP"
+ RemoteCommand=""
+ HttpUrl=""
+ PDBPath=""
+ SQLDebugging=""
+ Environment=""
+ EnvironmentMerge="true"
+ DebuggerFlavor=""
+ MPIRunCommand=""
+ MPIRunArguments=""
+ MPIRunWorkingDirectory=""
+ ApplicationCommand=""
+ ApplicationArguments=""
+ ShimCommand=""
+ MPIAcceptMode=""
+ MPIAcceptFilter=""
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|x64"
+ >
+ <DebugSettings
+ Command="$(TargetPath)"
+ WorkingDirectory=""
+ CommandArguments=""
+ Attach="false"
+ DebuggerType="3"
+ Remote="1"
+ RemoteMachine="ZERO-XP"
+ RemoteCommand=""
+ HttpUrl=""
+ PDBPath=""
+ SQLDebugging=""
+ Environment=""
+ EnvironmentMerge="true"
+ DebuggerFlavor=""
+ MPIRunCommand=""
+ MPIRunArguments=""
+ MPIRunWorkingDirectory=""
+ ApplicationCommand=""
+ ApplicationArguments=""
+ ShimCommand=""
+ MPIAcceptMode=""
+ MPIAcceptFilter=""
+ />
+ </Configuration>
+ </Configurations>
+</VisualStudioUserFile>
diff --git a/video.c b/video.c
new file mode 100644
index 00000000..c38b372d
--- /dev/null
+++ b/video.c
@@ -0,0 +1,494 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <zlib.h>
+
+#ifdef _USE_SHARED_MEMORY_
+#include <windows.h>
+#endif
+
+#include "types.h"
+#include "video.h"
+#include "fceu.h"
+#include "general.h"
+#include "memory.h"
+#include "crc32.h"
+#include "state.h"
+#include "movie.h"
+#include "palette.h"
+#include "nsf.h"
+#include "input.h"
+#include "vsuni.h"
+
+uint8 *XBuf=NULL;
+uint8 *XBackBuf=NULL;
+static uint8 *xbsave=NULL;
+
+//for input display
+extern int input_display;
+extern uint32 cur_input_display;
+
+#ifdef _USE_SHARED_MEMORY_
+HANDLE mapXBuf;
+#endif
+
+void FCEU_KillVirtualVideo(void)
+{
+ if(xbsave)
+ {
+ free(xbsave);
+ xbsave=0;
+ }
+ if(XBuf)
+ {
+ UnmapViewOfFile(XBuf);
+ CloseHandle(mapXBuf);
+ mapXBuf=NULL;
+ }
+ if(XBackBuf)
+ {
+ free(XBackBuf);
+ XBackBuf=0;
+ }
+}
+
+int FCEU_InitVirtualVideo(void)
+{
+ if(!XBuf) /* Some driver code may allocate XBuf externally. */
+ /* 256 bytes per scanline, * 240 scanline maximum, +8 for alignment,
+ */
+#ifdef _USE_SHARED_MEMORY_
+ mapXBuf = CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,PAGE_READWRITE, 0, 256 * 256 + 8,"fceu.XBuf");
+ if(mapXBuf == NULL || GetLastError() == ERROR_ALREADY_EXISTS)
+ {
+ CloseHandle(mapXBuf);
+ mapXBuf = NULL;
+ XBuf= (uint8*) (FCEU_malloc(256 * 256 + 8));
+ XBackBuf= (uint8*) (FCEU_malloc(256 * 256 + 8));
+ }
+ else
+ {
+ XBuf = (uint8 *)MapViewOfFile(mapXBuf, FILE_MAP_WRITE, 0, 0, 0);
+
+ XBackBuf = (uint8*) (FCEU_malloc(256 * 256 + 8));
+ }
+
+ if (!XBuf || !XBackBuf)
+ return 0;
+#else
+ if(!(XBuf= (uint8*) (FCEU_malloc(256 * 256 + 8))) ||
+ !(XBackBuf= (uint8*) (FCEU_malloc(256 * 256 + 8))))
+ return 0;
+#endif //_USE_SHARED_MEMORY_
+ xbsave=XBuf;
+
+ if(sizeof(uint8*)==4)
+ {
+ uint32 m;
+ m=(uint32)XBuf;
+ m=(4-m)&3;
+ XBuf+=m;
+ }
+ memset(XBuf,128,256*256); //*240);
+ memset(XBackBuf,128,256*256);
+ return 1;
+}
+
+int howlong;
+static char errmsg[65];
+
+#include "drawing.h"
+#ifdef FRAMESKIP
+
+//#define SHOWFPS
+void ShowFPS(void);
+void FCEU_PutImageDummy(void)
+{
+ #ifdef SHOWFPS
+ ShowFPS();
+ #endif
+ if(FCEUGameInfo->type!=GIT_NSF)
+ {
+ FCEU_DrawNTSCControlBars(XBuf);
+ FCEU_DrawSaveStates(XBuf);
+ FCEU_DrawMovies(XBuf);
+ }
+ if(howlong) howlong--; /* DrawMessage() */
+}
+#endif
+
+static int dosnapsave=0;
+void FCEUI_SaveSnapshot(void)
+{
+ dosnapsave=1;
+}
+
+static void FCEU_DrawRecordingStatus(uint8* XBuf)
+{
+ int n=0;
+ if(FCEUD_ShowStatusIcon())
+ {
+ if(FCEUI_EmulationPaused())
+ n=3;
+ else if(FCEUI_IsMovieActive()>0)
+ n=2;
+ else if(FCEUI_IsMovieActive()<0)
+ n=1;
+ }
+
+ if(n)
+ FCEU_DrawRecordingStatusN(XBuf, n);
+}
+
+static void ReallySnap(void)
+{
+ int x=SaveSnapshot();
+ if(!x)
+ FCEU_DispMessage("Error saving screen snapshot.");
+ else
+ FCEU_DispMessage("Screen snapshot %d saved.",x-1);
+}
+
+void FCEU_PutImage(void)
+{
+ #ifdef SHOWFPS
+ ShowFPS();
+ #endif
+/*
+ // HACK to record input and/or frame counter into AVI
+ extern int frame_display, input_display, movcounter;
+ int movieDrawInAVI = FCEUI_AviIsRecording() && (frame_display || input_display) && movcounter;
+ if(movieDrawInAVI)
+ {
+ FCEU_DrawMovies(XBuf);
+ DrawMessage();
+ }
+*/
+ if(FCEUGameInfo->type==GIT_NSF)
+ {
+ DrawNSF(XBuf);
+ /* Save snapshot after NSF screen is drawn. Why would we want to
+ do it before?
+ */
+ if(dosnapsave)
+ {
+ ReallySnap();
+ dosnapsave=0;
+ }
+ }
+ else
+ {
+ /* Update AVI before overlay stuff is written */
+ if(!FCEUI_EmulationPaused())
+ FCEUI_AviVideoUpdate(XBuf);
+ /* Save backbuffer before overlay stuff is written. */
+ if(!FCEUI_EmulationPaused())
+ memcpy(XBackBuf, XBuf, 256*256);
+ /* Save snapshot before overlay stuff is written. */
+ if(dosnapsave)
+ {
+ ReallySnap();
+ dosnapsave=0;
+ }
+ if(FCEUGameInfo->type==GIT_VSUNI)
+ FCEU_VSUniDraw(XBuf);
+ FCEU_DrawSaveStates(XBuf);
+ FCEU_DrawMovies(XBuf);
+ FCEU_DrawNTSCControlBars(XBuf);
+ FCEU_DrawRecordingStatus(XBuf);
+ }
+// if(!movieDrawInAVI)
+ DrawMessage();
+ FCEU_DrawInput(XBuf);
+
+ //Fancy input display code
+ if(input_display)
+ {
+ int controller, c, color;
+ int i, j;
+ char * t=XBuf+(FSettings.LastSLine-9)*256 + 20;
+ if(input_display > 4) input_display = 4;
+ for(controller = 0; controller < input_display; controller++, t += 56)
+ {
+ for(i = 0; i < 34;i++)
+ for(j = 0; j <9 ; j++)
+ t[i+j*256] = (t[i+j*256] & 15) | 0xC0;
+ for(i = 3; i < 6; i++)
+ for(j = 3; j< 6; j++)
+ t[i+j*256] = 3;
+ c = cur_input_display >> (controller * 8);
+ c &= 255;
+ //A
+ color = c&1?4:3;
+ for(i=0; i < 4; i++)
+ {
+ for(j = 0; j < 4; j++)
+ {
+ if(i%3==0 && j %3 == 0)
+ continue;
+ t[30+4*256+i+j*256] = color;
+ }
+ }
+ //B
+ color = c&2?4:3;
+ for(i=0; i < 4; i++)
+ {
+ for(j = 0; j < 4; j++)
+ {
+ if(i%3==0 && j %3 == 0)
+ continue;
+ t[24+4*256+i+j*256] = color;
+ }
+ }
+ //Select
+ color = c&4?4:3;
+ for(i = 0; i < 4; i++)
+ {
+ t[11+5*256+i] = color;
+ t[11+6*256+i] = color;
+ }
+ //Start
+ color = c&8?4:3;
+ for(i = 0; i < 4; i++)
+ {
+ t[17+5*256+i] = color;
+ t[17+6*256+i] = color;
+ }
+ //Up
+ color = c&16?4:3;
+ for(i = 0; i < 3; i++)
+ {
+ for(j = 0; j < 3; j++)
+ {
+ t[3+i+256*j] = color;
+ }
+ }
+ //Down
+ color = c&32?4:3;
+ for(i = 0; i < 3; i++)
+ {
+ for(j = 0; j < 3; j++)
+ {
+ t[3+i+256*j+6*256] = color;
+ }
+ }
+ //Left
+ color = c&64?4:3;
+ for(i = 0; i < 3; i++)
+ {
+ for(j = 0; j < 3; j++)
+ {
+ t[3*256+i+256*j] = color;
+ }
+ }
+ //Right
+ color = c&128?4:3;
+ for(i = 0; i < 3; i++)
+ {
+ for(j = 0; j < 3; j++)
+ {
+ t[6+3*256+i+256*j] = color;
+ }
+ }
+ }
+ }
+}
+
+void FCEU_DispMessage(char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap,format);
+ vsprintf(errmsg,format,ap);
+ va_end(ap);
+
+ howlong=180;
+
+ extern int movcounter;
+ movcounter=0;
+}
+
+void FCEU_ResetMessages(void)
+{
+ howlong=0;
+}
+
+
+static int WritePNGChunk(FILE *fp, uint32 size, char *type, uint8 *data)
+{
+ uint32 crc;
+
+ uint8 tempo[4];
+
+ tempo[0]=size>>24;
+ tempo[1]=size>>16;
+ tempo[2]=size>>8;
+ tempo[3]=size;
+
+ if(fwrite(tempo,4,1,fp)!=1)
+ return 0;
+ if(fwrite(type,4,1,fp)!=1)
+ return 0;
+
+ if(size)
+ if(fwrite(data,1,size,fp)!=size)
+ return 0;
+
+ crc=CalcCRC32(0,(uint8 *)type,4);
+ if(size)
+ crc=CalcCRC32(crc,data,size);
+
+ tempo[0]=crc>>24;
+ tempo[1]=crc>>16;
+ tempo[2]=crc>>8;
+ tempo[3]=crc;
+
+ if(fwrite(tempo,4,1,fp)!=1)
+ return 0;
+ return 1;
+}
+
+int SaveSnapshot(void)
+{
+ static unsigned int lastu=0;
+
+ char *fn=0;
+ int totallines=FSettings.LastSLine-FSettings.FirstSLine+1;
+ int x,u,y;
+ FILE *pp=NULL;
+ uint8 *compmem=NULL;
+ uLongf compmemsize=totallines*263+12;
+
+ if(!(compmem=(uint8 *)FCEU_malloc(compmemsize)))
+ return 0;
+
+ for(u=lastu;u<99999;u++)
+ {
+ pp=FCEUD_UTF8fopen((fn=FCEU_MakeFName(FCEUMKF_SNAP,u,"png")),"rb");
+ if(pp==NULL) break;
+ fclose(pp);
+ }
+
+ lastu=u;
+
+ if(!(pp=FCEUD_UTF8fopen(fn,"wb")))
+ {
+ free(fn);
+ return 0;
+ }
+ free(fn);
+ {
+ static uint8 header[8]={137,80,78,71,13,10,26,10};
+ if(fwrite(header,8,1,pp)!=1)
+ goto PNGerr;
+ }
+
+ {
+ uint8 chunko[13];
+
+ chunko[0]=chunko[1]=chunko[3]=0;
+ chunko[2]=0x1; // Width of 256
+
+ chunko[4]=chunko[5]=chunko[6]=0;
+ chunko[7]=totallines; // Height
+
+ chunko[8]=8; // bit depth
+ chunko[9]=3; // Color type; indexed 8-bit
+ chunko[10]=0; // compression: deflate
+ chunko[11]=0; // Basic adapative filter set(though none are used).
+ chunko[12]=0; // No interlace.
+
+ if(!WritePNGChunk(pp,13,"IHDR",chunko))
+ goto PNGerr;
+ }
+
+ {
+ uint8 pdata[256*3];
+ for(x=0;x<256;x++)
+ FCEUD_GetPalette(x,pdata+x*3,pdata+x*3+1,pdata+x*3+2);
+ if(!WritePNGChunk(pp,256*3,"PLTE",pdata))
+ goto PNGerr;
+ }
+
+ {
+ uint8 *tmp=XBuf+FSettings.FirstSLine*256;
+ uint8 *dest,*mal,*mork;
+
+ if(!(mal=mork=dest=(uint8 *)malloc((totallines<<8)+totallines)))
+ goto PNGerr;
+ // mork=dest=XBuf;
+
+ for(y=0;y<totallines;y++)
+ {
+ *dest=0; // No filter.
+ dest++;
+ for(x=256;x;x--,tmp++,dest++)
+ *dest=*tmp;
+ }
+
+ if(compress(compmem,&compmemsize,mork,(totallines<<8)+totallines)!=Z_OK)
+ {
+ if(mal) free(mal);
+ goto PNGerr;
+ }
+ if(mal) free(mal);
+ if(!WritePNGChunk(pp,compmemsize,"IDAT",compmem))
+ goto PNGerr;
+ }
+ if(!WritePNGChunk(pp,0,"IEND",0))
+ goto PNGerr;
+
+ free(compmem);
+ fclose(pp);
+
+ return u+1;
+
+
+ PNGerr:
+ if(compmem)
+ free(compmem);
+ if(pp)
+ fclose(pp);
+ return(0);
+}
+#ifdef SHOWFPS
+uint64 FCEUD_GetTime(void);
+uint64 FCEUD_GetTimeFreq(void);
+
+static uint64 boop[60];
+static int boopcount = 0;
+
+void ShowFPS(void)
+{
+ uint64 da = FCEUD_GetTime() - boop[boopcount];
+ char fpsmsg[16];
+ int booplimit = PAL?50:60;
+ boop[boopcount] = FCEUD_GetTime();
+
+ sprintf(fpsmsg, "%8.1f",(double)booplimit / ((double)da / FCEUD_GetTimeFreq()));
+ DrawTextTrans(XBuf + (256-8-8*8) + (FSettings.FirstSLine+4)*256,256,fpsmsg,4);
+ // It's not averaging FPS over exactly 1 second, but it's close enough.
+ boopcount = (boopcount + 1) % booplimit;
+}
+#endif
diff --git a/video.h b/video.h
new file mode 100644
index 00000000..e872155a
--- /dev/null
+++ b/video.h
@@ -0,0 +1,6 @@
+int FCEU_InitVirtualVideo(void);
+void FCEU_KillVirtualVideo(void);
+int SaveSnapshot(void);
+extern uint8 *XBuf;
+extern uint8 *XBackBuf;
+void FCEU_DrawNumberRow(uint8 *XBuf, int *nstatus, int cur);
diff --git a/vsuni.c b/vsuni.c
new file mode 100644
index 00000000..dc93c80c
--- /dev/null
+++ b/vsuni.c
@@ -0,0 +1,417 @@
+/* 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 <string.h>
+#include <stdio.h>
+
+#include "types.h"
+#include "x6502.h"
+#include "fceu.h"
+#include "input.h"
+#include "netplay.h"
+#include "vsuni.h"
+#include "state.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;
+}
+
+void FCEUI_VSUniSetDIP(int w, int state)
+{
+ if(((vsdip >> 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 00000000..14fb715f
--- /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/wave.c b/wave.c
new file mode 100644
index 00000000..43b21e88
--- /dev/null
+++ b/wave.c
@@ -0,0 +1,131 @@
+#include <stdio.h>
+
+#include "types.h"
+#include "fceu.h"
+
+#include "driver.h"
+#include "sound.h"
+#include "wave.h"
+
+static FILE *soundlog=0;
+static long wsize;
+
+/* Checking whether the file exists before wiping it out is left up to the
+ reader..err...I mean, the driver code, if it feels so inclined(I don't feel
+ so).
+*/
+void FCEU_WriteWaveData(int32 *Buffer, int Count)
+{
+ int16 temp[Count]; /* Yay. Is this the first use of this "feature" of C in FCE Ultra? */
+ int16 *dest;
+ int x;
+
+#ifndef WIN32
+ if(!soundlog) return;
+#else
+ if(!soundlog && !FCEUI_AviIsRecording()) return;
+#endif
+
+ dest=temp;
+ x=Count;
+
+ while(x--)
+ {
+ int16 tmp=*Buffer;
+
+ *(uint8 *)dest=(((uint16)tmp)&255);
+ *(((uint8 *)dest)+1)=(((uint16)tmp)>>8);
+ dest++;
+ Buffer++;
+ }
+ if(soundlog)
+ wsize+=fwrite(temp,1,Count*sizeof(int16),soundlog);
+
+#ifdef WIN32
+ if(FCEUI_AviIsRecording())
+ {
+ extern int bittage;
+ if(!bittage)
+ {
+ int8 temp2[Count];
+ int P;
+ for(P=0;P<Count;P++)
+ *(((uint8*)temp2)+P)=((int8)(temp[P]>>8))^128;
+ FCEUI_AviSoundUpdate((void*)temp2, Count);
+ }
+ else
+ FCEUI_AviSoundUpdate((void*)temp, Count);
+ }
+#endif
+}
+
+int FCEUI_EndWaveRecord(void)
+{
+ long s;
+
+ if(!soundlog) return 0;
+ s=ftell(soundlog)-8;
+ fseek(soundlog,4,SEEK_SET);
+ fputc(s&0xFF,soundlog);
+ fputc((s>>8)&0xFF,soundlog);
+ fputc((s>>16)&0xFF,soundlog);
+ fputc((s>>24)&0xFF,soundlog);
+
+ fseek(soundlog,0x28,SEEK_SET);
+ s=wsize;
+ fputc(s&0xFF,soundlog);
+ fputc((s>>8)&0xFF,soundlog);
+ fputc((s>>16)&0xFF,soundlog);
+ fputc((s>>24)&0xFF,soundlog);
+
+ fclose(soundlog);
+ soundlog=0;
+ return 1;
+}
+
+
+int FCEUI_BeginWaveRecord(char *fn)
+{
+ int r;
+
+ if(!(soundlog=FCEUD_UTF8fopen(fn,"wb")))
+ return 0;
+ wsize=0;
+
+
+ /* Write the header. */
+ fputs("RIFF",soundlog);
+ fseek(soundlog,4,SEEK_CUR); // Skip size
+ fputs("WAVEfmt ",soundlog);
+
+ fputc(0x10,soundlog);
+ fputc(0,soundlog);
+ fputc(0,soundlog);
+ fputc(0,soundlog);
+
+ fputc(1,soundlog); // PCM
+ fputc(0,soundlog);
+
+ fputc(1,soundlog); // Monophonic
+ fputc(0,soundlog);
+
+ r=FSettings.SndRate;
+ fputc(r&0xFF,soundlog);
+ fputc((r>>8)&0xFF,soundlog);
+ fputc((r>>16)&0xFF,soundlog);
+ fputc((r>>24)&0xFF,soundlog);
+ r<<=1;
+ fputc(r&0xFF,soundlog);
+ fputc((r>>8)&0xFF,soundlog);
+ fputc((r>>16)&0xFF,soundlog);
+ fputc((r>>24)&0xFF,soundlog);
+ fputc(2,soundlog);
+ fputc(0,soundlog);
+ fputc(16,soundlog);
+ fputc(0,soundlog);
+
+ fputs("data",soundlog);
+ fseek(soundlog,4,SEEK_CUR);
+
+ return(1);
+}
diff --git a/wave.h b/wave.h
new file mode 100644
index 00000000..c2947a73
--- /dev/null
+++ b/wave.h
@@ -0,0 +1 @@
+void FCEU_WriteWaveData(int32 *Buffer, int Count);
diff --git a/x6502.c b/x6502.c
new file mode 100644
index 00000000..89a6f9fe
--- /dev/null
+++ b/x6502.c
@@ -0,0 +1,705 @@
+/* FCE Ultra - NES/Famicom Emulator
+ *
+ * Copyright notice for this file:
+ * Copyright (C) 2002 Xodnizel
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <string.h>
+
+#include "types.h"
+#include "x6502.h"
+#include "fceu.h"
+#include "sound.h"
+
+X6502 X;
+
+#ifdef FCEUDEF_DEBUGGER
+void (*X6502_Run)(int32 cycles);
+#endif
+
+uint32 timestamp;
+void FP_FASTAPASS(1) (*MapIRQHook)(int a);
+
+#define _PC X.PC
+#define _A X.A
+#define _X X.X
+#define _Y X.Y
+#define _S X.S
+#define _P X.P
+#define _PI X.mooPI
+#define _DB X.DB
+#define _count X.count
+#define _tcount X.tcount
+#define _IRQlow X.IRQlow
+#define _jammed X.jammed
+
+#define ADDCYC(x) \
+{ \
+ int __x=x; \
+ _tcount+=__x; \
+ _count-=__x*48; \
+ timestamp+=__x; \
+}
+
+static INLINE uint8 RdMemNorm(unsigned int A)
+{
+ return(_DB=ARead[A](A));
+}
+
+static INLINE void WrMemNorm(unsigned int A, uint8 V)
+{
+ BWrite[A](A,V);
+}
+
+#ifdef FCEUDEF_DEBUGGER
+X6502 XSave; /* This is getting ugly. */
+//#define RdMemHook(A) ( X.ReadHook?(_DB=X.ReadHook(&X,A)):(_DB=ARead[A](A)) )
+//#define WrMemHook(A,V) { if(X.WriteHook) X.WriteHook(&X,A,V); else BWrite[A](A,V); }
+
+static INLINE uint8 RdMemHook(unsigned int A)
+{
+ if(X.ReadHook)
+ return(_DB = X.ReadHook(&X,A) );
+ else
+ return(_DB=ARead[A](A));
+}
+
+static INLINE void WrMemHook(unsigned int A, uint8 V)
+{
+ if(X.WriteHook)
+ X.WriteHook(&X,A,V);
+ else
+ BWrite[A](A,V);
+}
+#endif
+
+//#define RdRAMFast(A) (_DB=RAM[(A)])
+//#define WrRAMFast(A,V) RAM[(A)]=(V)
+
+static INLINE uint8 RdRAMFast(unsigned int A)
+{
+ return(_DB=RAM[A]);
+}
+
+static INLINE void WrRAMFast(unsigned int A, uint8 V)
+{
+ RAM[A]=V;
+}
+
+uint8 FASTAPASS(1) X6502_DMR(uint32 A)
+{
+ ADDCYC(1);
+ return(X.DB=ARead[A](A));
+}
+
+void FASTAPASS(2) X6502_DMW(uint32 A, uint8 V)
+{
+ ADDCYC(1);
+ BWrite[A](A,V);
+}
+
+#define PUSH(V) \
+{ \
+ uint8 VTMP=V; \
+ WrRAM(0x100+_S,VTMP); \
+ _S--; \
+}
+
+#define POP() RdRAM(0x100+(++_S))
+
+static uint8 ZNTable[256];
+/* Some of these operations will only make sense if you know what the flag
+ constants are. */
+
+#define X_ZN(zort) _P&=~(Z_FLAG|N_FLAG);_P|=ZNTable[zort]
+#define X_ZNT(zort) _P|=ZNTable[zort]
+
+#define JR(cond); \
+{ \
+ if(cond) \
+ { \
+ uint32 tmp; \
+ int32 disp; \
+ disp=(int8)RdMem(_PC); \
+ _PC++; \
+ ADDCYC(1); \
+ tmp=_PC; \
+ _PC+=disp; \
+ if((tmp^_PC)&0x100) \
+ ADDCYC(1); \
+ } \
+ else _PC++; \
+}
+
+
+#define LDA _A=x;X_ZN(_A)
+#define LDX _X=x;X_ZN(_X)
+#define LDY _Y=x;X_ZN(_Y)
+
+/* All of the freaky arithmetic operations. */
+#define AND _A&=x;X_ZN(_A)
+#define BIT _P&=~(Z_FLAG|V_FLAG|N_FLAG);_P|=ZNTable[x&_A]&Z_FLAG;_P|=x&(V_FLAG|N_FLAG)
+#define EOR _A^=x;X_ZN(_A)
+#define ORA _A|=x;X_ZN(_A)
+
+#define ADC { \
+ uint32 l=_A+x+(_P&1); \
+ _P&=~(Z_FLAG|C_FLAG|N_FLAG|V_FLAG); \
+ _P|=((((_A^x)&0x80)^0x80) & ((_A^l)&0x80))>>1; \
+ _P|=(l>>8)&C_FLAG; \
+ _A=l; \
+ X_ZNT(_A); \
+ }
+
+#define SBC { \
+ uint32 l=_A-x-((_P&1)^1); \
+ _P&=~(Z_FLAG|C_FLAG|N_FLAG|V_FLAG); \
+ _P|=((_A^l)&(_A^x)&0x80)>>1; \
+ _P|=((l>>8)&C_FLAG)^C_FLAG; \
+ _A=l; \
+ X_ZNT(_A); \
+ }
+
+#define CMPL(a1,a2) { \
+ uint32 t=a1-a2; \
+ X_ZN(t&0xFF); \
+ _P&=~C_FLAG; \
+ _P|=((t>>8)&C_FLAG)^C_FLAG; \
+ }
+
+/* Special undocumented operation. Very similar to CMP. */
+#define AXS { \
+ uint32 t=(_A&_X)-x; \
+ X_ZN(t&0xFF); \
+ _P&=~C_FLAG; \
+ _P|=((t>>8)&C_FLAG)^C_FLAG; \
+ _X=t; \
+ }
+
+#define CMP CMPL(_A,x)
+#define CPX CMPL(_X,x)
+#define CPY CMPL(_Y,x)
+
+/* The following operations modify the byte being worked on. */
+#define DEC x--;X_ZN(x)
+#define INC x++;X_ZN(x)
+
+#define ASL _P&=~C_FLAG;_P|=x>>7;x<<=1;X_ZN(x)
+#define LSR _P&=~(C_FLAG|N_FLAG|Z_FLAG);_P|=x&1;x>>=1;X_ZNT(x)
+
+/* For undocumented instructions, maybe for other things later... */
+#define LSRA _P&=~(C_FLAG|N_FLAG|Z_FLAG);_P|=_A&1;_A>>=1;X_ZNT(_A)
+
+#define ROL { \
+ uint8 l=x>>7; \
+ x<<=1; \
+ x|=_P&C_FLAG; \
+ _P&=~(Z_FLAG|N_FLAG|C_FLAG); \
+ _P|=l; \
+ X_ZNT(x); \
+ }
+#define ROR { \
+ uint8 l=x&1; \
+ x>>=1; \
+ x|=(_P&C_FLAG)<<7; \
+ _P&=~(Z_FLAG|N_FLAG|C_FLAG); \
+ _P|=l; \
+ X_ZNT(x); \
+ }
+
+/* Icky icky thing for some undocumented instructions. Can easily be
+ broken if names of local variables are changed.
+*/
+
+/* Absolute */
+#define GetAB(target) \
+{ \
+ target=RdMem(_PC); \
+ _PC++; \
+ target|=RdMem(_PC)<<8; \
+ _PC++; \
+}
+
+/* Absolute Indexed(for reads) */
+#define GetABIRD(target, i) \
+{ \
+ unsigned int tmp; \
+ GetAB(tmp); \
+ target=tmp; \
+ target+=i; \
+ if((target^tmp)&0x100) \
+ { \
+ target&=0xFFFF; \
+ RdMem(target^0x100); \
+ ADDCYC(1); \
+ } \
+}
+
+/* Absolute Indexed(for writes and rmws) */
+#define GetABIWR(target, i) \
+{ \
+ unsigned int rt; \
+ GetAB(rt); \
+ target=rt; \
+ target+=i; \
+ target&=0xFFFF; \
+ RdMem((target&0x00FF)|(rt&0xFF00)); \
+}
+
+/* Zero Page */
+#define GetZP(target) \
+{ \
+ target=RdMem(_PC); \
+ _PC++; \
+}
+
+/* Zero Page Indexed */
+#define GetZPI(target,i) \
+{ \
+ target=i+RdMem(_PC); \
+ _PC++; \
+}
+
+/* Indexed Indirect */
+#define GetIX(target) \
+{ \
+ uint8 tmp; \
+ tmp=RdMem(_PC); \
+ _PC++; \
+ tmp+=_X; \
+ target=RdRAM(tmp); \
+ tmp++; \
+ target|=RdRAM(tmp)<<8; \
+}
+
+/* Indirect Indexed(for reads) */
+#define GetIYRD(target) \
+{ \
+ unsigned int rt; \
+ uint8 tmp; \
+ tmp=RdMem(_PC); \
+ _PC++; \
+ rt=RdRAM(tmp); \
+ tmp++; \
+ rt|=RdRAM(tmp)<<8; \
+ target=rt; \
+ target+=_Y; \
+ if((target^rt)&0x100) \
+ { \
+ target&=0xFFFF; \
+ RdMem(target^0x100); \
+ ADDCYC(1); \
+ } \
+}
+
+/* Indirect Indexed(for writes and rmws) */
+#define GetIYWR(target) \
+{ \
+ unsigned int rt; \
+ uint8 tmp; \
+ tmp=RdMem(_PC); \
+ _PC++; \
+ rt=RdRAM(tmp); \
+ tmp++; \
+ rt|=RdRAM(tmp)<<8; \
+ target=rt; \
+ target+=_Y; \
+ target&=0xFFFF; \
+ RdMem((target&0x00FF)|(rt&0xFF00)); \
+}
+
+/* Now come the macros to wrap up all of the above stuff addressing mode functions
+ and operation macros. Note that operation macros will always operate(redundant
+ redundant) on the variable "x".
+*/
+
+#define RMW_A(op) {uint8 x=_A; op; _A=x; break; } /* Meh... */
+#define RMW_AB(op) {unsigned int A; uint8 x; GetAB(A); x=RdMem(A); WrMem(A,x); op; WrMem(A,x); break; }
+#define RMW_ABI(reg,op) {unsigned int A; uint8 x; GetABIWR(A,reg); x=RdMem(A); WrMem(A,x); op; WrMem(A,x); break; }
+#define RMW_ABX(op) RMW_ABI(_X,op)
+#define RMW_ABY(op) RMW_ABI(_Y,op)
+#define RMW_IX(op) {unsigned int A; uint8 x; GetIX(A); x=RdMem(A); WrMem(A,x); op; WrMem(A,x); break; }
+#define RMW_IY(op) {unsigned int A; uint8 x; GetIYWR(A); x=RdMem(A); WrMem(A,x); op; WrMem(A,x); break; }
+#define RMW_ZP(op) {uint8 A; uint8 x; GetZP(A); x=RdRAM(A); op; WrRAM(A,x); break; }
+#define RMW_ZPX(op) {uint8 A; uint8 x; GetZPI(A,_X); x=RdRAM(A); op; WrRAM(A,x); break;}
+
+#define LD_IM(op) {uint8 x; x=RdMem(_PC); _PC++; op; break;}
+#define LD_ZP(op) {uint8 A; uint8 x; GetZP(A); x=RdRAM(A); op; break;}
+#define LD_ZPX(op) {uint8 A; uint8 x; GetZPI(A,_X); x=RdRAM(A); op; break;}
+#define LD_ZPY(op) {uint8 A; uint8 x; GetZPI(A,_Y); x=RdRAM(A); op; break;}
+#define LD_AB(op) {unsigned int A; uint8 x; GetAB(A); x=RdMem(A); op; break; }
+#define LD_ABI(reg,op) {unsigned int A; uint8 x; GetABIRD(A,reg); x=RdMem(A); op; break;}
+#define LD_ABX(op) LD_ABI(_X,op)
+#define LD_ABY(op) LD_ABI(_Y,op)
+#define LD_IX(op) {unsigned int A; uint8 x; GetIX(A); x=RdMem(A); op; break;}
+#define LD_IY(op) {unsigned int A; uint8 x; GetIYRD(A); x=RdMem(A); op; break;}
+
+#define ST_ZP(r) {uint8 A; GetZP(A); WrRAM(A,r); break;}
+#define ST_ZPX(r) {uint8 A; GetZPI(A,_X); WrRAM(A,r); break;}
+#define ST_ZPY(r) {uint8 A; GetZPI(A,_Y); WrRAM(A,r); break;}
+#define ST_AB(r) {unsigned int A; GetAB(A); WrMem(A,r); break;}
+#define ST_ABI(reg,r) {unsigned int A; GetABIWR(A,reg); WrMem(A,r); break; }
+#define ST_ABX(r) ST_ABI(_X,r)
+#define ST_ABY(r) ST_ABI(_Y,r)
+#define ST_IX(r) {unsigned int A; GetIX(A); WrMem(A,r); break; }
+#define ST_IY(r) {unsigned int A; GetIYWR(A); WrMem(A,r); break; }
+
+static uint8 CycTable[256] =
+{
+/*0x00*/ 7,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,
+/*0x10*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
+/*0x20*/ 6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,
+/*0x30*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
+/*0x40*/ 6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,
+/*0x50*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
+/*0x60*/ 6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,
+/*0x70*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
+/*0x80*/ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
+/*0x90*/ 2,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,
+/*0xA0*/ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
+/*0xB0*/ 2,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,
+/*0xC0*/ 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,
+/*0xD0*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
+/*0xE0*/ 2,6,3,8,3,3,5,5,2,2,2,2,4,4,6,6,
+/*0xF0*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
+};
+
+void FASTAPASS(1) X6502_IRQBegin(int w)
+{
+ _IRQlow|=w;
+}
+
+void FASTAPASS(1) X6502_IRQEnd(int w)
+{
+ _IRQlow&=~w;
+}
+
+void TriggerNMI(void)
+{
+ _IRQlow|=FCEU_IQNMI;
+}
+
+void TriggerNMI2(void)
+{
+ _IRQlow|=FCEU_IQNMI2;
+}
+
+#ifdef FCEUDEF_DEBUGGER
+/* Called from debugger. */
+void FCEUI_NMI(void)
+{
+ _IRQlow|=FCEU_IQNMI;
+}
+
+void FCEUI_IRQ(void)
+{
+ _IRQlow|=FCEU_IQTEMP;
+}
+
+void FCEUI_GetIVectors(uint16 *reset, uint16 *irq, uint16 *nmi)
+{
+ fceuindbg=1;
+
+ *reset=RdMemNorm(0xFFFC);
+ *reset|=RdMemNorm(0xFFFD)<<8;
+ *nmi=RdMemNorm(0xFFFA);
+ *nmi|=RdMemNorm(0xFFFB)<<8;
+ *irq=RdMemNorm(0xFFFE);
+ *irq|=RdMemNorm(0xFFFF)<<8;
+ fceuindbg=0;
+}
+static int debugmode;
+#endif
+
+void X6502_Reset(void)
+{
+ _IRQlow=FCEU_IQRESET;
+}
+
+void X6502_Init(void)
+{
+ int x;
+
+ memset((void *)&X,0,sizeof(X));
+ for(x=0;x<256;x++)
+ if(!x) ZNTable[x]=Z_FLAG;
+ else if(x&0x80) ZNTable[x]=N_FLAG;
+ else ZNTable[x]=0;
+ #ifdef FCEUDEF_DEBUGGER
+ X6502_Debug(0,0,0);
+ #endif
+}
+
+void X6502_Power(void)
+{
+ _count=_tcount=_IRQlow=_PC=_A=_X=_Y=_S=_P=_PI=_DB=_jammed=0;
+ timestamp=0;
+ X6502_Reset();
+}
+
+#ifdef FCEUDEF_DEBUGGER
+static void X6502_RunDebug(int32 cycles)
+{
+ #define RdRAM RdMemHook
+ #define WrRAM WrMemHook
+ #define RdMem RdMemHook
+ #define WrMem WrMemHook
+
+ if(PAL)
+ cycles*=15; // 15*4=60
+ else
+ cycles*=16; // 16*4=64
+
+ _count+=cycles;
+
+ while(_count>0)
+ {
+ int32 temp;
+ uint8 b1;
+
+ if(_IRQlow)
+ {
+ if(_IRQlow&FCEU_IQRESET)
+ {
+ _PC=RdMem(0xFFFC);
+ _PC|=RdMem(0xFFFD)<<8;
+ _jammed=0;
+ _PI=_P=I_FLAG;
+ _IRQlow&=~FCEU_IQRESET;
+ }
+ else if(_IRQlow&FCEU_IQNMI2)
+ {
+ _IRQlow&=~FCEU_IQNMI2;
+ _IRQlow|=FCEU_IQNMI;
+ }
+ else if(_IRQlow&FCEU_IQNMI)
+ {
+ if(!_jammed)
+ {
+ ADDCYC(7);
+ PUSH(_PC>>8);
+ PUSH(_PC);
+ PUSH((_P&~B_FLAG)|(U_FLAG));
+ _P|=I_FLAG;
+ _PC=RdMem(0xFFFA);
+ _PC|=RdMem(0xFFFB)<<8;
+ _IRQlow&=~FCEU_IQNMI;
+ }
+ }
+ else
+ {
+ if(!(_PI&I_FLAG) && !_jammed)
+ {
+ ADDCYC(7);
+ PUSH(_PC>>8);
+ PUSH(_PC);
+ PUSH((_P&~B_FLAG)|(U_FLAG));
+ _P|=I_FLAG;
+ _PC=RdMem(0xFFFE);
+ _PC|=RdMem(0xFFFF)<<8;
+ }
+ }
+ _IRQlow&=~(FCEU_IQTEMP);
+ if(_count<=0)
+ {
+ _PI=_P;
+ return;
+ } /* Should increase accuracy without a */
+ /* major speed hit. */
+ }
+
+ if(X.CPUHook) X.CPUHook(&X);
+ /* Ok, now the real fun starts. */
+ /* Do the pre-exec voodoo. */
+ if(X.ReadHook || X.WriteHook)
+ {
+ uint32 tsave=timestamp;
+ XSave=X;
+
+ fceuindbg=1;
+ X.preexec=1;
+ b1=RdMem(_PC);
+ _PC++;
+ switch(b1)
+ {
+ #include "ops.h"
+ }
+
+ timestamp=tsave;
+
+ /* In case an NMI/IRQ/RESET was triggered by the debugger. */
+ /* Should we also copy over the other hook variables? */
+ XSave.IRQlow=X.IRQlow;
+ XSave.ReadHook=X.ReadHook;
+ XSave.WriteHook=X.WriteHook;
+ XSave.CPUHook=X.CPUHook;
+ X=XSave;
+ fceuindbg=0;
+ }
+
+ _PI=_P;
+ b1=RdMem(_PC);
+ ADDCYC(CycTable[b1]);
+
+ temp=_tcount;
+ _tcount=0;
+ if(MapIRQHook) MapIRQHook(temp);
+
+ FCEU_SoundCPUHook(temp);
+
+ _PC++;
+ switch(b1)
+ {
+ #include "ops.h"
+ }
+ }
+ #undef RdRAM
+ #undef WrRAM
+ #undef RdMem
+ #undef WrMem
+
+}
+
+static void X6502_RunNormal(int32 cycles)
+#else
+void X6502_Run(int32 cycles)
+#endif
+{
+ #define RdRAM RdRAMFast
+ #define WrRAM WrRAMFast
+ #define RdMem RdMemNorm
+ #define WrMem WrMemNorm
+
+ #if(defined(C80x86) && defined(__GNUC__))
+ /* Gives a nice little speed boost. */
+ register uint16 pbackus asm ("edi");
+ #else
+ uint16 pbackus;
+ #endif
+
+ pbackus=_PC;
+
+ #undef _PC
+ #define _PC pbackus
+
+ if(PAL)
+ cycles*=15; // 15*4=60
+ else
+ cycles*=16; // 16*4=64
+
+ _count+=cycles;
+
+ while(_count>0)
+ {
+ int32 temp;
+ uint8 b1;
+
+// XI.PC=pbackus;
+ if(_IRQlow)
+ {
+ if(_IRQlow&FCEU_IQRESET)
+ {
+ _PC=RdMem(0xFFFC);
+ _PC|=RdMem(0xFFFD)<<8;
+ _jammed=0;
+ _PI=_P=I_FLAG;
+ _IRQlow&=~FCEU_IQRESET;
+ }
+ else if(_IRQlow&FCEU_IQNMI2)
+ {
+ _IRQlow&=~FCEU_IQNMI2;
+ _IRQlow|=FCEU_IQNMI;
+ }
+ else if(_IRQlow&FCEU_IQNMI)
+ {
+ if(!_jammed)
+ {
+ ADDCYC(7);
+ PUSH(_PC>>8);
+ PUSH(_PC);
+ PUSH((_P&~B_FLAG)|(U_FLAG));
+ _P|=I_FLAG;
+ _PC=RdMem(0xFFFA);
+ _PC|=RdMem(0xFFFB)<<8;
+ _IRQlow&=~FCEU_IQNMI;
+ }
+ }
+ else
+ {
+ if(!(_PI&I_FLAG) && !_jammed)
+ {
+ ADDCYC(7);
+ PUSH(_PC>>8);
+ PUSH(_PC);
+ PUSH((_P&~B_FLAG)|(U_FLAG));
+ _P|=I_FLAG;
+ _PC=RdMem(0xFFFE);
+ _PC|=RdMem(0xFFFF)<<8;
+ }
+ }
+ _IRQlow&=~(FCEU_IQTEMP);
+ if(_count<=0)
+ {
+ _PI=_P;
+ X.PC=pbackus;
+ return;
+ } /* Should increase accuracy without a */
+ /* major speed hit. */
+ }
+
+ _PI=_P;
+ b1=RdMem(_PC);
+
+ ADDCYC(CycTable[b1]);
+
+ temp=_tcount;
+ _tcount=0;
+ if(MapIRQHook) MapIRQHook(temp);
+ FCEU_SoundCPUHook(temp);
+ //printf("%04x\n",X.PC);
+ X.PC=pbackus;
+ _PC++;
+ switch(b1)
+ {
+ #include "ops.h"
+ }
+ }
+
+ #undef _PC
+ #define _PC X.PC
+ _PC=pbackus;
+ #undef RdRAM
+ #undef WrRAM
+}
+
+#ifdef FCEUDEF_DEBUGGER
+void X6502_Debug(void (*CPUHook)(X6502 *),
+ uint8 (*ReadHook)(X6502 *, unsigned int),
+ void (*WriteHook)(X6502 *, unsigned int, uint8))
+{
+ debugmode=(ReadHook || WriteHook || CPUHook)?1:0;
+ X.ReadHook=ReadHook;
+ X.WriteHook=WriteHook;
+ X.CPUHook=CPUHook;
+
+ if(!debugmode)
+ X6502_Run=X6502_RunNormal;
+ else
+ X6502_Run=X6502_RunDebug;
+}
+
+#endif
diff --git a/x6502.h b/x6502.h
new file mode 100644
index 00000000..129e341c
--- /dev/null
+++ b/x6502.h
@@ -0,0 +1,76 @@
+/* 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
+ */
+
+#ifndef _X6502H
+
+#include "x6502struct.h"
+
+#ifdef FCEUDEF_DEBUGGER
+void X6502_Debug(void (*CPUHook)(X6502 *),
+ uint8 (*ReadHook)(X6502 *, unsigned int),
+ void (*WriteHook)(X6502 *, unsigned int, uint8));
+
+extern void (*X6502_Run)(int32 cycles);
+#else
+void X6502_Run(int32 cycles);
+#endif
+
+extern uint32 timestamp;
+extern X6502 X;
+
+#define N_FLAG 0x80
+#define V_FLAG 0x40
+#define U_FLAG 0x20
+#define B_FLAG 0x10
+#define D_FLAG 0x08
+#define I_FLAG 0x04
+#define Z_FLAG 0x02
+#define C_FLAG 0x01
+
+extern void FP_FASTAPASS(1) (*MapIRQHook)(int a);
+
+#define NTSC_CPU 1789772.7272727272727272
+#define PAL_CPU 1662607.125
+
+#define FCEU_IQEXT 0x001
+#define FCEU_IQEXT2 0x002
+/* ... */
+#define FCEU_IQRESET 0x020
+#define FCEU_IQNMI2 0x040 // Delayed NMI, gets converted to *_IQNMI
+#define FCEU_IQNMI 0x080
+#define FCEU_IQDPCM 0x100
+#define FCEU_IQFCOUNT 0x200
+#define FCEU_IQTEMP 0x800
+
+void X6502_Init(void);
+void X6502_Reset(void);
+void X6502_Power(void);
+
+void TriggerNMI(void);
+void TriggerNMI2(void);
+
+uint8 FASTAPASS(1) X6502_DMR(uint32 A);
+void FASTAPASS(2) X6502_DMW(uint32 A, uint8 V);
+
+void FASTAPASS(1) X6502_IRQBegin(int w);
+void FASTAPASS(1) X6502_IRQEnd(int w);
+
+#define _X6502H
+#endif
diff --git a/x6502struct.h b/x6502struct.h
new file mode 100644
index 00000000..31e726f5
--- /dev/null
+++ b/x6502struct.h
@@ -0,0 +1,28 @@
+#ifndef _X6502STRUCTH
+
+#include "fceu.h"
+
+typedef struct __X6502 {
+ int32 tcount; /* Temporary cycle counter */
+ uint16 PC; /* I'll change this to uint32 later... */
+ /* I'll need to AND PC after increments to 0xFFFF */
+ /* when I do, though. Perhaps an IPC() macro? */
+ uint8 A,X,Y,S,P,mooPI;
+ uint8 jammed;
+
+ int32 count;
+ uint32 IRQlow; /* Simulated IRQ pin held low(or is it high?).
+ And other junk hooked on for speed reasons.*/
+ uint8 DB; /* Data bus "cache" for reads from certain areas */
+
+ int preexec; /* Pre-exec'ing for debug breakpoints. */
+
+ #ifdef FCEUDEF_DEBUGGER
+ void (*CPUHook)(struct __X6502 *);
+ uint8 (*ReadHook)(struct __X6502 *, unsigned int);
+ void (*WriteHook)(struct __X6502 *, unsigned int, uint8);
+ #endif
+
+} X6502;
+#define _X6502STRUCTH
+#endif