From 7e6caac57dc5736828271ff63093b2c1b297de53 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 30 Mar 2014 22:15:17 +0200 Subject: [PATCH] Initial commit - http://sourceforge.net/p/fceumm/code/160/ --- Authors | 25 + Copying | 341 ++ Fceuwin.dev | 3169 ++++++++++++++++ Makefile.libretro | 139 + changelog.txt | 2237 +++++++++++ src/boards/01-222.c | 109 + src/boards/09-034a.c | 97 + src/boards/103.c | 115 + src/boards/106.c | 108 + src/boards/108.c | 64 + src/boards/112.c | 89 + src/boards/116.c | 324 ++ src/boards/117.c | 91 + src/boards/120.c | 62 + src/boards/121.c | 129 + src/boards/12in1.c | 73 + src/boards/15.c | 109 + src/boards/151.c | 59 + src/boards/156.c | 119 + src/boards/164.c | 526 +++ src/boards/168.c | 81 + src/boards/170.c | 62 + src/boards/175.c | 79 + src/boards/177.c | 80 + src/boards/178.c | 176 + src/boards/18.c | 132 + src/boards/183.c | 111 + src/boards/185.c | 107 + src/boards/186.c | 94 + src/boards/187.c | 88 + src/boards/189.c | 44 + src/boards/193.c | 74 + src/boards/199.c | 97 + src/boards/206.c | 78 + src/boards/208.c | 78 + src/boards/222.c | 99 + src/boards/225.c | 89 + src/boards/228.c | 84 + src/boards/230.c | 78 + src/boards/232.c | 68 + src/boards/234.c | 79 + src/boards/235.c | 63 + src/boards/244.c | 77 + src/boards/246.c | 85 + src/boards/252.c | 134 + src/boards/253.c | 151 + src/boards/32.c | 101 + src/boards/33.c | 117 + src/boards/34.c | 92 + src/boards/36.c | 63 + src/boards/3d-block.c | 95 + src/boards/40.c | 85 + src/boards/41.c | 69 + src/boards/411120-c.c | 64 + src/boards/42.c | 83 + src/boards/43.c | 91 + src/boards/46.c | 69 + src/boards/50.c | 84 + src/boards/51.c | 84 + src/boards/57.c | 84 + src/boards/603-5052.c | 49 + src/boards/62.c | 69 + src/boards/65.c | 104 + src/boards/67.c | 105 + src/boards/68.c | 163 + src/boards/69.c | 277 ++ src/boards/71.c | 64 + src/boards/72.c | 64 + src/boards/77.c | 74 + src/boards/79.c | 60 + src/boards/80.c | 192 + src/boards/8157.c | 85 + src/boards/82.c | 97 + src/boards/8237.c | 173 + src/boards/830118C.c | 68 + src/boards/88.c | 83 + src/boards/90.c | 474 +++ src/boards/91.c | 85 + src/boards/96.c | 77 + src/boards/99.c | 77 + src/boards/KS7012.c | 86 + src/boards/KS7013.c | 77 + src/boards/KS7017.c | 114 + src/boards/KS7030.c | 140 + src/boards/KS7031.c | 80 + src/boards/KS7032.c | 91 + src/boards/KS7037.c | 125 + src/boards/KS7057.c | 92 + src/boards/SA-9602B.c | 61 + src/boards/__dummy_mapper.c | 99 + src/boards/__serial.c | 150 + src/boards/__serial.h | 36 + src/boards/a9746.c | 75 + src/boards/ac-08.c | 71 + src/boards/addrlatch.c | 505 +++ src/boards/ax5705.c | 111 + src/boards/bandai.c | 463 +++ src/boards/bb.c | 68 + src/boards/bmc13in1jy110.c | 97 + src/boards/bmc42in1r.c | 86 + src/boards/bmc64in1nr.c | 83 + src/boards/bmc70in1.c | 121 + src/boards/bonza.c | 133 + src/boards/bs-5.c | 84 + src/boards/cityfighter.c | 124 + src/boards/copyfami_emu.c | 355 ++ src/boards/copyfami_hwi.c | 587 +++ src/boards/dance2000.c | 112 + src/boards/datalatch.c | 483 +++ src/boards/dream.c | 51 + src/boards/edu2000.c | 77 + src/boards/emu2413.c | 1075 ++++++ src/boards/emu2413.h | 138 + src/boards/famicombox.c | 115 + src/boards/ffe.c | 152 + src/boards/fk23c.c | 203 + src/boards/ghostbusters63in1.c | 96 + src/boards/gs-2004.c | 63 + src/boards/gs-2013.c | 63 + src/boards/h2288.c | 70 + src/boards/karaoke.c | 63 + src/boards/kof97.c | 46 + src/boards/le05.c | 62 + src/boards/lh32.c | 78 + src/boards/lh53.c | 107 + src/boards/malee.c | 43 + src/boards/mapinc.h | 11 + src/boards/mihunche.c | 68 + src/boards/mmc1.c | 388 ++ src/boards/mmc2and4.c | 135 + src/boards/mmc3.c | 1326 +++++++ src/boards/mmc3.h | 26 + src/boards/mmc5.c | 806 ++++ src/boards/n106.c | 427 +++ src/boards/n625092.c | 95 + src/boards/novel.c | 50 + src/boards/onebus.c | 302 ++ src/boards/pec-586.c | 127 + src/boards/sachen.c | 409 ++ src/boards/sc-127.c | 114 + src/boards/sheroes.c | 79 + src/boards/sl1632.c | 111 + src/boards/subor.c | 88 + src/boards/super24.c | 93 + src/boards/supervision.c | 87 + src/boards/t-227-1.c | 100 + src/boards/t-262.c | 73 + src/boards/tengen.c | 139 + src/boards/tf-1201.c | 109 + src/boards/transformer.c | 96 + src/boards/vrc1.c | 70 + src/boards/vrc2and4.c | 270 ++ src/boards/vrc3.c | 133 + src/boards/vrc5.c | 225 ++ src/boards/vrc6.c | 376 ++ src/boards/vrc7.c | 201 + src/boards/vrc7p.c | 120 + src/boards/yoko.c | 236 ++ src/cart.c | 556 +++ src/cart.h | 90 + src/cheat.c | 727 ++++ src/cheat.h | 7 + src/crc32.c | 31 + src/crc32.h | 1 + src/debug.c | 497 +++ src/debug.h | 25 + src/drawing.h | 222 ++ src/driver.h | 250 ++ src/drivers/common/args.c | 86 + src/drivers/common/args.h | 12 + src/drivers/common/cheat.c | 467 +++ src/drivers/common/cheat.h | 21 + src/drivers/common/config.c | 134 + src/drivers/common/config.h | 40 + src/drivers/common/hq2x.c | 2434 ++++++++++++ src/drivers/common/hq2x.h | 4 + src/drivers/common/hq3x.c | 3318 +++++++++++++++++ src/drivers/common/hq3x.h | 4 + src/drivers/common/scale2x.c | 911 +++++ src/drivers/common/scale2x.h | 51 + src/drivers/common/scale3x.c | 373 ++ src/drivers/common/scale3x.h | 33 + src/drivers/common/scalebit.c | 376 ++ src/drivers/common/scalebit.h | 43 + src/drivers/common/vidblit.c | 726 ++++ src/drivers/common/vidblit.h | 25 + src/drivers/libretro/jni/Android.mk | 21 + src/drivers/libretro/libretro.c | 590 +++ src/drivers/libretro/libretro.h | 223 ++ src/drivers/libretro/link.T | 5 + src/drivers/libretro/memstream.c | 118 + src/drivers/libretro/memstream.h | 30 + src/drivers/libretro/msvc/msvc-2003-xbox1.sln | 30 + .../msvc-2003-xbox1/msvc-2003-xbox1.vcproj | 846 +++++ .../libretro/msvc/msvc-2003-xbox1/stdint.h | 249 ++ src/drivers/libretro/msvc/msvc-2010-360.sln | 32 + .../msvc/msvc-2010-360/msvc-2010-360.vcxproj | 1935 ++++++++++ .../msvc-2010-360.vcxproj.filters | 788 ++++ src/drivers/libretro/msvc/msvc-2010.sln | 20 + .../libretro/msvc/msvc-2010/libretro.def | 27 + .../libretro/msvc/msvc-2010/msvc-2010.vcxproj | 944 +++++ .../msvc/msvc-2010/msvc-2010.vcxproj.filters | 780 ++++ src/drivers/win/args.c | 38 + src/drivers/win/cheat.c | 445 +++ src/drivers/win/cheat.h | 2 + src/drivers/win/common.h | 43 + src/drivers/win/config.c | 122 + src/drivers/win/debug.c | 672 ++++ src/drivers/win/debug.h | 5 + src/drivers/win/ffb.c | 303 ++ src/drivers/win/ffb.h | 195 + src/drivers/win/input.c | 1038 ++++++ src/drivers/win/input.h | 46 + src/drivers/win/joystick.c | 355 ++ src/drivers/win/joystick.h | 11 + src/drivers/win/keyboard.c | 85 + src/drivers/win/keyboard.h | 6 + src/drivers/win/keyscan.h | 127 + src/drivers/win/log.c | 92 + src/drivers/win/log.h | 2 + src/drivers/win/main.c | 459 +++ src/drivers/win/netplay.c | 434 +++ src/drivers/win/netplay.h | 1 + src/drivers/win/ppuview.c | 347 ++ src/drivers/win/ppuview.h | 0 src/drivers/win/res.rc | 738 ++++ src/drivers/win/res/EXE.ico | Bin 0 -> 8854 bytes src/drivers/win/res/FAM.ico | Bin 0 -> 4150 bytes src/drivers/win/res/FDS.ico | Bin 0 -> 8854 bytes src/drivers/win/res/NES.ico | Bin 0 -> 8854 bytes src/drivers/win/sound.c | 483 +++ src/drivers/win/state.c | 36 + src/drivers/win/throttle.c | 84 + src/drivers/win/video.c | 994 +++++ src/drivers/win/wave.c | 44 + src/drivers/win/window.c | 1055 ++++++ src/endian.c | 95 + src/endian.h | 7 + src/fceu-endian.c | 99 + src/fceu-endian.h | 14 + src/fceu-types.h | 94 + src/fceu.c | 525 +++ src/fceu.h | 108 + src/fceustr.c | 29 + src/fceustr.h | 4 + src/fcoeffs.h | 1589 ++++++++ src/fds.c | 772 ++++ src/fds.h | 7 + src/file.c | 514 +++ src/file.h | 18 + src/filter.c | 190 + src/filter.h | 3 + src/fir/Makefile | 15 + src/fir/c44100ntsc.coef | 1039 ++++++ src/fir/c44100ntsc.h | 512 +++ src/fir/c44100ntsc.scm | 12 + src/fir/c44100pal.coef | 1039 ++++++ src/fir/c44100pal.h | 512 +++ src/fir/c44100pal.scm | 12 + src/fir/c48000ntsc.coef | 1039 ++++++ src/fir/c48000ntsc.h | 512 +++ src/fir/c48000ntsc.scm | 12 + src/fir/c48000pal.coef | 1039 ++++++ src/fir/c48000pal.h | 512 +++ src/fir/c48000pal.scm | 12 + src/fir/c96000ntsc.coef | 1039 ++++++ src/fir/c96000ntsc.h | 512 +++ src/fir/c96000ntsc.scm | 12 + src/fir/c96000pal.coef | 1039 ++++++ src/fir/c96000pal.h | 512 +++ src/fir/c96000pal.scm | 12 + src/fir/toh.c | 24 + src/general.c | 208 ++ src/general.h | 17 + src/git.h | 28 + src/ines-bad.h | 40 + src/ines-correct.h | 260 ++ src/ines.c | 842 +++++ src/ines.h | 211 ++ src/input.c | 425 +++ src/input.h | 26 + src/input/arkanoid.c | 106 + src/input/bbox.c | 194 + src/input/bworld.c | 65 + src/input/cursor.c | 79 + src/input/fkb.c | 89 + src/input/fkb.h | 72 + src/input/ftrainer.c | 69 + src/input/hypershot.c | 46 + src/input/mahjong.c | 71 + src/input/mouse.c | 86 + src/input/oekakids.c | 85 + src/input/pads.c | 136 + src/input/pec586kb.c | 96 + src/input/powerpad.c | 80 + src/input/quiz.c | 66 + src/input/shadow.c | 136 + src/input/share.h | 12 + src/input/suborkb.c | 84 + src/input/suborkb.h | 102 + src/input/toprider.c | 52 + src/input/zapper.c | 151 + src/md5.c | 237 ++ src/md5.h | 17 + src/memory.c | 88 + src/memory.h | 55 + src/movie.c | 253 ++ src/movie.h | 7 + src/netplay.c | 307 ++ src/netplay.h | 23 + src/nsf.c | 519 +++ src/nsf.h | 47 + src/ops.h | 485 +++ src/palette.c | 326 ++ src/palette.h | 11 + src/palettes/conv.c | 72 + src/palettes/palettes.h | 93 + src/palettes/rp2c04001.h | 64 + src/palettes/rp2c04002.h | 64 + src/palettes/rp2c04003.h | 64 + src/palettes/rp2c05004.h | 64 + src/ppu.c | 1278 +++++++ src/ppu.h | 20 + src/pputile.h | 109 + src/ppuview.h | 8 + src/sound.c | 1145 ++++++ src/sound.h | 62 + src/state.c | 437 +++ src/state.h | 47 + src/unif.c | 622 +++ src/unif.h | 152 + src/unzip.h | 272 ++ src/video.c | 299 ++ src/video.h | 5 + src/vsuni.c | 370 ++ src/vsuni.h | 7 + src/wave.c | 104 + src/wave.h | 1 + src/x6502.c | 635 ++++ src/x6502.h | 76 + src/x6502struct.h | 25 + src/zlib/adler32.c | 48 + src/zlib/compress.c | 68 + src/zlib/crc32.c | 162 + src/zlib/deflate.c | 1350 +++++++ src/zlib/deflate.h | 318 ++ src/zlib/gzio.c | 875 +++++ src/zlib/infblock.c | 403 ++ src/zlib/infblock.h | 39 + src/zlib/infcodes.c | 251 ++ src/zlib/infcodes.h | 27 + src/zlib/inffast.c | 183 + src/zlib/inffast.h | 17 + src/zlib/inffixed.h | 151 + src/zlib/inflate.c | 366 ++ src/zlib/inftrees.c | 454 +++ src/zlib/inftrees.h | 58 + src/zlib/infutil.c | 87 + src/zlib/infutil.h | 98 + src/zlib/trees.c | 1214 ++++++ src/zlib/trees.h | 128 + src/zlib/uncompr.c | 58 + src/zlib/unzip.c | 1301 +++++++ src/zlib/unzip.h | 275 ++ src/zlib/zconf.h | 279 ++ src/zlib/zlib.h | 893 +++++ src/zlib/zutil.c | 225 ++ src/zlib/zutil.h | 220 ++ whatsnew.txt | 186 + zzz_todo.txt | 282 ++ 370 files changed, 90364 insertions(+) create mode 100644 Authors create mode 100644 Copying create mode 100644 Fceuwin.dev create mode 100644 Makefile.libretro create mode 100644 changelog.txt create mode 100644 src/boards/01-222.c create mode 100644 src/boards/09-034a.c create mode 100644 src/boards/103.c create mode 100644 src/boards/106.c create mode 100644 src/boards/108.c create mode 100644 src/boards/112.c create mode 100644 src/boards/116.c create mode 100644 src/boards/117.c create mode 100644 src/boards/120.c create mode 100644 src/boards/121.c create mode 100644 src/boards/12in1.c create mode 100644 src/boards/15.c create mode 100644 src/boards/151.c create mode 100644 src/boards/156.c create mode 100644 src/boards/164.c create mode 100644 src/boards/168.c create mode 100644 src/boards/170.c create mode 100644 src/boards/175.c create mode 100644 src/boards/177.c create mode 100644 src/boards/178.c create mode 100644 src/boards/18.c create mode 100644 src/boards/183.c create mode 100644 src/boards/185.c create mode 100644 src/boards/186.c create mode 100644 src/boards/187.c create mode 100644 src/boards/189.c create mode 100644 src/boards/193.c create mode 100644 src/boards/199.c create mode 100644 src/boards/206.c create mode 100644 src/boards/208.c create mode 100644 src/boards/222.c create mode 100644 src/boards/225.c create mode 100644 src/boards/228.c create mode 100644 src/boards/230.c create mode 100644 src/boards/232.c create mode 100644 src/boards/234.c create mode 100644 src/boards/235.c create mode 100644 src/boards/244.c create mode 100644 src/boards/246.c create mode 100644 src/boards/252.c create mode 100644 src/boards/253.c create mode 100644 src/boards/32.c create mode 100644 src/boards/33.c create mode 100644 src/boards/34.c create mode 100644 src/boards/36.c create mode 100644 src/boards/3d-block.c create mode 100644 src/boards/40.c create mode 100644 src/boards/41.c create mode 100644 src/boards/411120-c.c create mode 100644 src/boards/42.c create mode 100644 src/boards/43.c create mode 100644 src/boards/46.c create mode 100644 src/boards/50.c create mode 100644 src/boards/51.c create mode 100644 src/boards/57.c create mode 100644 src/boards/603-5052.c create mode 100644 src/boards/62.c create mode 100644 src/boards/65.c create mode 100644 src/boards/67.c create mode 100644 src/boards/68.c create mode 100644 src/boards/69.c create mode 100644 src/boards/71.c create mode 100644 src/boards/72.c create mode 100644 src/boards/77.c create mode 100644 src/boards/79.c create mode 100644 src/boards/80.c create mode 100644 src/boards/8157.c create mode 100644 src/boards/82.c create mode 100644 src/boards/8237.c create mode 100644 src/boards/830118C.c create mode 100644 src/boards/88.c create mode 100644 src/boards/90.c create mode 100644 src/boards/91.c create mode 100644 src/boards/96.c create mode 100644 src/boards/99.c create mode 100644 src/boards/KS7012.c create mode 100644 src/boards/KS7013.c create mode 100644 src/boards/KS7017.c create mode 100644 src/boards/KS7030.c create mode 100644 src/boards/KS7031.c create mode 100644 src/boards/KS7032.c create mode 100644 src/boards/KS7037.c create mode 100644 src/boards/KS7057.c create mode 100644 src/boards/SA-9602B.c create mode 100644 src/boards/__dummy_mapper.c create mode 100644 src/boards/__serial.c create mode 100644 src/boards/__serial.h create mode 100644 src/boards/a9746.c create mode 100644 src/boards/ac-08.c create mode 100644 src/boards/addrlatch.c create mode 100644 src/boards/ax5705.c create mode 100644 src/boards/bandai.c create mode 100644 src/boards/bb.c create mode 100644 src/boards/bmc13in1jy110.c create mode 100644 src/boards/bmc42in1r.c create mode 100644 src/boards/bmc64in1nr.c create mode 100644 src/boards/bmc70in1.c create mode 100644 src/boards/bonza.c create mode 100644 src/boards/bs-5.c create mode 100644 src/boards/cityfighter.c create mode 100644 src/boards/copyfami_emu.c create mode 100644 src/boards/copyfami_hwi.c create mode 100644 src/boards/dance2000.c create mode 100644 src/boards/datalatch.c create mode 100644 src/boards/dream.c create mode 100644 src/boards/edu2000.c create mode 100644 src/boards/emu2413.c create mode 100644 src/boards/emu2413.h create mode 100644 src/boards/famicombox.c create mode 100644 src/boards/ffe.c create mode 100644 src/boards/fk23c.c create mode 100644 src/boards/ghostbusters63in1.c create mode 100644 src/boards/gs-2004.c create mode 100644 src/boards/gs-2013.c create mode 100644 src/boards/h2288.c create mode 100644 src/boards/karaoke.c create mode 100644 src/boards/kof97.c create mode 100644 src/boards/le05.c create mode 100644 src/boards/lh32.c create mode 100644 src/boards/lh53.c create mode 100644 src/boards/malee.c create mode 100644 src/boards/mapinc.h create mode 100644 src/boards/mihunche.c create mode 100644 src/boards/mmc1.c create mode 100644 src/boards/mmc2and4.c create mode 100644 src/boards/mmc3.c create mode 100644 src/boards/mmc3.h create mode 100644 src/boards/mmc5.c create mode 100644 src/boards/n106.c create mode 100644 src/boards/n625092.c create mode 100644 src/boards/novel.c create mode 100644 src/boards/onebus.c create mode 100644 src/boards/pec-586.c create mode 100644 src/boards/sachen.c create mode 100644 src/boards/sc-127.c create mode 100644 src/boards/sheroes.c create mode 100644 src/boards/sl1632.c create mode 100644 src/boards/subor.c create mode 100644 src/boards/super24.c create mode 100644 src/boards/supervision.c create mode 100644 src/boards/t-227-1.c create mode 100644 src/boards/t-262.c create mode 100644 src/boards/tengen.c create mode 100644 src/boards/tf-1201.c create mode 100644 src/boards/transformer.c create mode 100644 src/boards/vrc1.c create mode 100644 src/boards/vrc2and4.c create mode 100644 src/boards/vrc3.c create mode 100644 src/boards/vrc5.c create mode 100644 src/boards/vrc6.c create mode 100644 src/boards/vrc7.c create mode 100644 src/boards/vrc7p.c create mode 100644 src/boards/yoko.c create mode 100644 src/cart.c create mode 100644 src/cart.h create mode 100644 src/cheat.c create mode 100644 src/cheat.h create mode 100644 src/crc32.c create mode 100644 src/crc32.h create mode 100644 src/debug.c create mode 100644 src/debug.h create mode 100644 src/drawing.h create mode 100644 src/driver.h create mode 100644 src/drivers/common/args.c create mode 100644 src/drivers/common/args.h create mode 100644 src/drivers/common/cheat.c create mode 100644 src/drivers/common/cheat.h create mode 100644 src/drivers/common/config.c create mode 100644 src/drivers/common/config.h create mode 100644 src/drivers/common/hq2x.c create mode 100644 src/drivers/common/hq2x.h create mode 100644 src/drivers/common/hq3x.c create mode 100644 src/drivers/common/hq3x.h create mode 100644 src/drivers/common/scale2x.c create mode 100644 src/drivers/common/scale2x.h create mode 100644 src/drivers/common/scale3x.c create mode 100644 src/drivers/common/scale3x.h create mode 100644 src/drivers/common/scalebit.c create mode 100644 src/drivers/common/scalebit.h create mode 100644 src/drivers/common/vidblit.c create mode 100644 src/drivers/common/vidblit.h create mode 100644 src/drivers/libretro/jni/Android.mk create mode 100644 src/drivers/libretro/libretro.c create mode 100644 src/drivers/libretro/libretro.h create mode 100644 src/drivers/libretro/link.T create mode 100644 src/drivers/libretro/memstream.c create mode 100644 src/drivers/libretro/memstream.h create mode 100644 src/drivers/libretro/msvc/msvc-2003-xbox1.sln create mode 100644 src/drivers/libretro/msvc/msvc-2003-xbox1/msvc-2003-xbox1.vcproj create mode 100644 src/drivers/libretro/msvc/msvc-2003-xbox1/stdint.h create mode 100644 src/drivers/libretro/msvc/msvc-2010-360.sln create mode 100644 src/drivers/libretro/msvc/msvc-2010-360/msvc-2010-360.vcxproj create mode 100644 src/drivers/libretro/msvc/msvc-2010-360/msvc-2010-360.vcxproj.filters create mode 100644 src/drivers/libretro/msvc/msvc-2010.sln create mode 100644 src/drivers/libretro/msvc/msvc-2010/libretro.def create mode 100644 src/drivers/libretro/msvc/msvc-2010/msvc-2010.vcxproj create mode 100644 src/drivers/libretro/msvc/msvc-2010/msvc-2010.vcxproj.filters create mode 100644 src/drivers/win/args.c create mode 100644 src/drivers/win/cheat.c create mode 100644 src/drivers/win/cheat.h create mode 100644 src/drivers/win/common.h create mode 100644 src/drivers/win/config.c create mode 100644 src/drivers/win/debug.c create mode 100644 src/drivers/win/debug.h create mode 100644 src/drivers/win/ffb.c create mode 100644 src/drivers/win/ffb.h create mode 100644 src/drivers/win/input.c create mode 100644 src/drivers/win/input.h create mode 100644 src/drivers/win/joystick.c create mode 100644 src/drivers/win/joystick.h create mode 100644 src/drivers/win/keyboard.c create mode 100644 src/drivers/win/keyboard.h create mode 100644 src/drivers/win/keyscan.h create mode 100644 src/drivers/win/log.c create mode 100644 src/drivers/win/log.h create mode 100644 src/drivers/win/main.c create mode 100644 src/drivers/win/netplay.c create mode 100644 src/drivers/win/netplay.h create mode 100644 src/drivers/win/ppuview.c create mode 100644 src/drivers/win/ppuview.h create mode 100644 src/drivers/win/res.rc create mode 100644 src/drivers/win/res/EXE.ico create mode 100644 src/drivers/win/res/FAM.ico create mode 100644 src/drivers/win/res/FDS.ico create mode 100644 src/drivers/win/res/NES.ico create mode 100644 src/drivers/win/sound.c create mode 100644 src/drivers/win/state.c create mode 100644 src/drivers/win/throttle.c create mode 100644 src/drivers/win/video.c create mode 100644 src/drivers/win/wave.c create mode 100644 src/drivers/win/window.c create mode 100644 src/endian.c create mode 100644 src/endian.h create mode 100644 src/fceu-endian.c create mode 100644 src/fceu-endian.h create mode 100644 src/fceu-types.h create mode 100644 src/fceu.c create mode 100644 src/fceu.h create mode 100644 src/fceustr.c create mode 100644 src/fceustr.h create mode 100644 src/fcoeffs.h create mode 100644 src/fds.c create mode 100644 src/fds.h create mode 100644 src/file.c create mode 100644 src/file.h create mode 100644 src/filter.c create mode 100644 src/filter.h create mode 100644 src/fir/Makefile create mode 100644 src/fir/c44100ntsc.coef create mode 100644 src/fir/c44100ntsc.h create mode 100644 src/fir/c44100ntsc.scm create mode 100644 src/fir/c44100pal.coef create mode 100644 src/fir/c44100pal.h create mode 100644 src/fir/c44100pal.scm create mode 100644 src/fir/c48000ntsc.coef create mode 100644 src/fir/c48000ntsc.h create mode 100644 src/fir/c48000ntsc.scm create mode 100644 src/fir/c48000pal.coef create mode 100644 src/fir/c48000pal.h create mode 100644 src/fir/c48000pal.scm create mode 100644 src/fir/c96000ntsc.coef create mode 100644 src/fir/c96000ntsc.h create mode 100644 src/fir/c96000ntsc.scm create mode 100644 src/fir/c96000pal.coef create mode 100644 src/fir/c96000pal.h create mode 100644 src/fir/c96000pal.scm create mode 100644 src/fir/toh.c create mode 100644 src/general.c create mode 100644 src/general.h create mode 100644 src/git.h create mode 100644 src/ines-bad.h create mode 100644 src/ines-correct.h create mode 100644 src/ines.c create mode 100644 src/ines.h create mode 100644 src/input.c create mode 100644 src/input.h create mode 100644 src/input/arkanoid.c create mode 100644 src/input/bbox.c create mode 100644 src/input/bworld.c create mode 100644 src/input/cursor.c create mode 100644 src/input/fkb.c create mode 100644 src/input/fkb.h create mode 100644 src/input/ftrainer.c create mode 100644 src/input/hypershot.c create mode 100644 src/input/mahjong.c create mode 100644 src/input/mouse.c create mode 100644 src/input/oekakids.c create mode 100644 src/input/pads.c create mode 100644 src/input/pec586kb.c create mode 100644 src/input/powerpad.c create mode 100644 src/input/quiz.c create mode 100644 src/input/shadow.c create mode 100644 src/input/share.h create mode 100644 src/input/suborkb.c create mode 100644 src/input/suborkb.h create mode 100644 src/input/toprider.c create mode 100644 src/input/zapper.c create mode 100644 src/md5.c create mode 100644 src/md5.h create mode 100644 src/memory.c create mode 100644 src/memory.h create mode 100644 src/movie.c create mode 100644 src/movie.h create mode 100644 src/netplay.c create mode 100644 src/netplay.h create mode 100644 src/nsf.c create mode 100644 src/nsf.h create mode 100644 src/ops.h create mode 100644 src/palette.c create mode 100644 src/palette.h create mode 100644 src/palettes/conv.c create mode 100644 src/palettes/palettes.h create mode 100644 src/palettes/rp2c04001.h create mode 100644 src/palettes/rp2c04002.h create mode 100644 src/palettes/rp2c04003.h create mode 100644 src/palettes/rp2c05004.h create mode 100644 src/ppu.c create mode 100644 src/ppu.h create mode 100644 src/pputile.h create mode 100644 src/ppuview.h create mode 100644 src/sound.c create mode 100644 src/sound.h create mode 100644 src/state.c create mode 100644 src/state.h create mode 100644 src/unif.c create mode 100644 src/unif.h create mode 100644 src/unzip.h create mode 100644 src/video.c create mode 100644 src/video.h create mode 100644 src/vsuni.c create mode 100644 src/vsuni.h create mode 100644 src/wave.c create mode 100644 src/wave.h create mode 100644 src/x6502.c create mode 100644 src/x6502.h create mode 100644 src/x6502struct.h create mode 100644 src/zlib/adler32.c create mode 100644 src/zlib/compress.c create mode 100644 src/zlib/crc32.c create mode 100644 src/zlib/deflate.c create mode 100644 src/zlib/deflate.h create mode 100644 src/zlib/gzio.c create mode 100644 src/zlib/infblock.c create mode 100644 src/zlib/infblock.h create mode 100644 src/zlib/infcodes.c create mode 100644 src/zlib/infcodes.h create mode 100644 src/zlib/inffast.c create mode 100644 src/zlib/inffast.h create mode 100644 src/zlib/inffixed.h create mode 100644 src/zlib/inflate.c create mode 100644 src/zlib/inftrees.c create mode 100644 src/zlib/inftrees.h create mode 100644 src/zlib/infutil.c create mode 100644 src/zlib/infutil.h create mode 100644 src/zlib/trees.c create mode 100644 src/zlib/trees.h create mode 100644 src/zlib/uncompr.c create mode 100644 src/zlib/unzip.c create mode 100644 src/zlib/unzip.h create mode 100644 src/zlib/zconf.h create mode 100644 src/zlib/zlib.h create mode 100644 src/zlib/zutil.c create mode 100644 src/zlib/zutil.h create mode 100644 whatsnew.txt create mode 100644 zzz_todo.txt diff --git a/Authors b/Authors new file mode 100644 index 0000000..9d35a13 --- /dev/null +++ b/Authors @@ -0,0 +1,25 @@ +A list of people who have contributed code to FCE Ultra follows. +Please note that the "Contributions" field may not be all inclusive; +the coder may have done more than what is listed. + +Name/Alias Contributions Contact Information +------------------------------------------------------------------------------ +Aaron Oneal Many changes to compile http://www.morphgear.com + with MSVC and first frame + skipping code. + +BERO Base FCE code. bero at geocities.co.jp + +CaH4e3 Some mapper code. CaH4e3 at mail dot ru + +Joe Nahmias man pages. + +Mitsutaka YM2413 emulator. + Okazaki + +Paul Various code for the official kuliniew at purdue.edu + Kuliniewicz SDL port. + +Quietust VRC7 "translation" code. quietust at ircN dot org + +Xodnizel Most of the FCE Ultra code. http://xodnizel.net/ diff --git a/Copying b/Copying new file mode 100644 index 0000000..afd5a94 --- /dev/null +++ b/Copying @@ -0,0 +1,341 @@ + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/Fceuwin.dev b/Fceuwin.dev new file mode 100644 index 0000000..7a42135 --- /dev/null +++ b/Fceuwin.dev @@ -0,0 +1,3169 @@ +[Project] +FileName=Fceuwin.dev +Name=Fceu +UnitCount=295 +Type=0 +Ver=1 +ObjFiles= +Includes=C:\dev-cpp\include +Libs=C:\dev-cpp\lib +PrivateResource=src\drivers\win\Fceuwin_private.rc +ResourceIncludes=.\ +MakeIncludes= +Compiler=-m32_@@_-malign-double_@@_-O3_@@_-fomit-frame-pointer_@@_-Wall_@@_-DLSB_FIRST_@@_-DWIN32_@@_-DPSS_STYLE=2_@@_-DZLIB_@@_-DNETWORK_@@_-DUSE_SEXYAL_@@_-DFCEU_VERSION_NUMERIC=9813_@@_-DFCEU_VERSION=\"0.98.13mm\"_@@_-DFCEUDEF_DEBUGGER_@@_-DDEBUG_MAPPER_@@_-D_COPYFAMI_@@_ +CppCompiler= +Linker=-lddraw_@@_-ldinput_@@_-ldsound_@@_-lgdi32_@@_-ldxguid_@@_-lwinmm_@@_-lshell32_@@_-lwsock32_@@_-lcomdlg32_@@_-lole32_@@_-lz_@@__@@_ +IsCpp=0 +Icon= +ExeOutput=release +ObjectOutput= +OverrideOutput=1 +OverrideOutputName=fceu.exe +HostApplication= +Folders=_Headers,boards,"boards/fds conversions","boards/mmc3 based","boards/multigame boards","boards/vrc based",drv_common,drv_win,input,Zlib +CommandLine= +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=0000000001001000000100 +UseCustomMakefile=0 +CustomMakefile= + +[Unit2] +FileName=src\crc32.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=src\debug.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=src\fceu-endian.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=src\fceu.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=src\fceustr.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=src\fds.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit8] +FileName=src\file.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit9] +FileName=src\filter.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit10] +FileName=src\general.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit11] +FileName=src\ines.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit12] +FileName=src\input.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit13] +FileName=src\md5.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit14] +FileName=src\memory.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit15] +FileName=src\movie.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit16] +FileName=src\cart.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit17] +FileName=src\nsf.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit18] +FileName=src\palette.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit19] +FileName=src\ppu.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit20] +FileName=src\sound.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit21] +FileName=src\state.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit22] +FileName=src\unif.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit24] +FileName=src\vsuni.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit25] +FileName=src\wave.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit26] +FileName=src\x6502.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit27] +FileName=src\input\arkanoid.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit29] +FileName=src\input\cursor.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit30] +FileName=src\input\fkb.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit31] +FileName=src\input\ftrainer.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit32] +FileName=src\input\hypershot.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit33] +FileName=src\input\mahjong.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit34] +FileName=src\input\oekakids.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit35] +FileName=src\input\powerpad.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit36] +FileName=src\input\quiz.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit37] +FileName=src\input\shadow.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit38] +FileName=src\input\toprider.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit39] +FileName=src\input\zapper.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit44] +FileName=src\drivers\common\scalebit.c +CompileCpp=0 +Folder=drv_common +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit54] +FileName=src\fceu.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit58] +FileName=src\file.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit61] +FileName=src\git.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit62] +FileName=src\ines.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit63] +FileName=src\input.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit64] +FileName=src\md5.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit65] +FileName=src\memory.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit66] +FileName=src\netplay.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit67] +FileName=src\nsf.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit69] +FileName=src\palette.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit71] +FileName=src\pputile.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit72] +FileName=src\sound.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit73] +FileName=src\state.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit74] +FileName=src\fceu-types.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit76] +FileName=src\video.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit77] +FileName=src\vsuni.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit78] +FileName=src\wave.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit79] +FileName=src\x6502.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit80] +FileName=src\drivers\common\hq3x.c +CompileCpp=0 +Folder=drv_common +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit81] +FileName=src\drivers\common\scale2x.c +CompileCpp=0 +Folder=drv_common +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit82] +FileName=src\drivers\common\scale3x.c +CompileCpp=0 +Folder=drv_common +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit94] +FileName=src\drivers\win\args.c +CompileCpp=0 +Folder=drv_win +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c args.c -o args.o $(CFLAGS) + +[Unit95] +FileName=src\drivers\win\video.c +CompileCpp=0 +Folder=drv_win +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c video.c -o video.o $(CFLAGS) + +[Unit96] +FileName=src\drivers\win\window.c +CompileCpp=0 +Folder=drv_win +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c window.c -o window.o $(CFLAGS) + +[Unit97] +FileName=src\drivers\win\netplay.c +CompileCpp=0 +Folder=drv_win +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit98] +FileName=src\input\suborkb.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit99] +FileName=src\drivers\win\input.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit100] +FileName=src\input\suborkb.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit101] +FileName=src\drivers\win\keyscan.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit102] +FileName=src\drivers\win\keyboard.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit103] +FileName=src\input\fkb.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit104] +FileName=src\drivers\win\ppuview.c +CompileCpp=0 +Folder=drv_win +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit106] +FileName=src\input\share.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit107] +FileName=src\ines-correct.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit108] +FileName=src\ines-bad.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit109] +FileName=src\boards\90.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit110] +FileName=src\boards\164.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit113] +FileName=src\boards\8237.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit115] +FileName=src\boards\206.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit116] +FileName=src\boards\dream.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit117] +FileName=src\boards\karaoke.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit118] +FileName=src\boards\vrc5.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit121] +FileName=src\boards\mmc3.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit122] +FileName=src\boards\mmc5.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit123] +FileName=src\boards\n106.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit125] +FileName=src\boards\sachen.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit126] +FileName=src\boards\datalatch.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit127] +FileName=src\boards\subor.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit128] +FileName=src\boards\super24.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit129] +FileName=src\boards\supervision.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit135] +FileName=src\input\pads.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit137] +FileName=src\boards\bmc42in1r.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit140] +FileName=src\boards\187.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit141] +FileName=src\boards\222.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit142] +FileName=src\boards\208.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit143] +FileName=src\boards\bmc13in1jy110.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit144] +FileName=src\boards\189.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit145] +FileName=src\boards\kof97.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit146] +FileName=zzz_todo.txt +CompileCpp=0 +Folder= +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit147] +FileName=src\boards\185.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit149] +FileName=src\boards\sl1632.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit151] +FileName=src\boards\117.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit152] +FileName=src\drivers\win\res.rc +CompileCpp=0 +Folder=drv_win +Compile=1 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit156] +FileName=src\boards\__dummy_mapper.c +CompileCpp=0 +Folder=boards +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c __dummy_mapper.c -o __dummy_mapper.o $(CFLAGS) + +[Unit159] +FileName=src\boards\01-222.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit160] +FileName=src\input\mouse.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit162] +FileName=src\boards\603-5052.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit163] +FileName=src\boards\68.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit164] +FileName=src\input\bbox.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit165] +FileName=src\boards\n625092.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion= +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 + +[Unit161] +FileName=src\boards\edu2000.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit1] +FileName=src\cheat.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit154] +FileName=src\boards\t-262.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit166] +FileName=src\boards\15.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit167] +FileName=src\boards\3d-block.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit168] +FileName=src\boards\tf-1201.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit169] +FileName=src\boards\09-034a.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit170] +FileName=src\boards\gs-2004.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit171] +FileName=src\boards\a9746.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit172] +FileName=src\boards\KS7032.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit173] +FileName=src\boards\108.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit174] +FileName=src\boards\vrc2and4.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit175] +FileName=src\boards\121.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit176] +FileName=src\boards\bandai.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit177] +FileName=src\boards\ax5705.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit178] +FileName=src\boards\ghostbusters63in1.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit180] +FileName=src\boards\120.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit182] +FileName=src\boards\gs-2013.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit183] +FileName=src\boards\177.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit184] +FileName=src\boards\copyfami_emu.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit185] +FileName=src\boards\bs-5.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit186] +FileName=src\boards\411120-c.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit187] +FileName=src\boards\830118C.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit188] +FileName=src\zlib\adler32.c +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit189] +FileName=src\zlib\compress.c +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit190] +FileName=src\zlib\crc32.c +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit191] +FileName=src\zlib\deflate.c +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit192] +FileName=src\zlib\infblock.c +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit193] +FileName=src\zlib\infcodes.c +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit194] +FileName=src\zlib\inffast.c +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit195] +FileName=src\zlib\inflate.c +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit196] +FileName=src\zlib\inftrees.c +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit200] +FileName=src\zlib\unzip.c +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit201] +FileName=src\zlib\zutil.c +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit202] +FileName=src\zlib\deflate.h +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit203] +FileName=src\zlib\infblock.h +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit204] +FileName=src\zlib\infcodes.h +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit205] +FileName=src\zlib\inffast.h +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit206] +FileName=src\zlib\inffixed.h +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit207] +FileName=src\zlib\inftrees.h +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit208] +FileName=src\zlib\infutil.h +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit150] +FileName=src\boards\sheroes.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit158] +FileName=src\boards\199.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit209] +FileName=src\zlib\trees.h +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit217] +FileName=src\boards\sc-127.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit210] +FileName=src\zlib\unzip.h +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit211] +FileName=src\zlib\zconf.h +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit213] +FileName=src\zlib\zutil.h +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit214] +FileName=src\zlib\gzio.c +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit56] +FileName=src\fcoeffs.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit216] +FileName=src\boards\175.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit220] +FileName=src\drivers\common\vidblit.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit221] +FileName=src\input\pec586kb.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit223] +FileName=src\boards\193.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit225] +FileName=src\boards\vrc7p.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit227] +FileName=src\boards\168.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit155] +FileName=src\boards\fk23c.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit230] +FileName=src\boards\copyfami_hwi.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit197] +FileName=src\zlib\infutil.c +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit229] +FileName=src\boards\onebus.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit231] +FileName=src\boards\__serial.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit157] +FileName=src\boards\43.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit233] +FileName=src\boards\transformer.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit136] +FileName=src\boards\57.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit28] +FileName=src\input\bworld.c +CompileCpp=0 +Folder=input +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit124] +FileName=src\boards\novel.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit130] +FileName=src\boards\tengen.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit133] +FileName=src\boards\h2288.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit198] +FileName=src\zlib\trees.c +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit215] +FileName=src\boards\t-227-1.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit219] +FileName=src\boards\pec-586.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit224] +FileName=src\boards\253.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit226] +FileName=src\boards\dance2000.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit119] +FileName=src\boards\malee.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit228] +FileName=src\boards\KS7012.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit120] +FileName=src\boards\mmc1.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit212] +FileName=src\zlib\zlib.h +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit232] +FileName=src\boards\__serial.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit199] +FileName=src\zlib\uncompr.c +CompileCpp=0 +Folder=Zlib +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit134] +FileName=src\boards\8157.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit234] +FileName=src\boards\KS7037.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit236] +FileName=src\boards\yoko.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit237] +FileName=src\boards\le05.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit235] +FileName=src\boards\ac-08.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit238] +FileName=src\boards\116.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit239] +FileName=src\boards\KS7057.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit68] +FileName=src\ops.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit240] +FileName=src\boards\156.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit241] +FileName=src\boards\KS7013.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit242] +FileName=src\boards\225.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit43] +FileName=src\drivers\common\hq2x.c +CompileCpp=0 +Folder=drv_common +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit105] +FileName=src\ppuview.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit244] +FileName=src\boards\SA-9602B.c +CompileCpp=0 +Folder=boards/mmc3 based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit83] +FileName=src\drivers\win\main.c +CompileCpp=0 +Folder=drv_win +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit222] +FileName=src\boards\12in1.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit247] +FileName=src\boards\151.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit87] +FileName=src\drivers\win\keyboard.c +CompileCpp=0 +Folder=drv_win +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit55] +FileName=src\fceustr.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit111] +FileName=src\boards\183.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit112] +FileName=src\boards\186.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit114] +FileName=src\boards\bonza.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit243] +FileName=src\boards\170.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit75] +FileName=src\unif.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit245] +FileName=src\boards\famicombox.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit250] +FileName=src\boards\99.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit57] +FileName=src\fds.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit246] +FileName=src\boards\cityfighter.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit248] +FileName=src\boards\34.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit249] +FileName=src\boards\96.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit251] +FileName=src\boards\91.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit252] +FileName=src\boards\82.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit253] +FileName=src\boards\lh53.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit255] +FileName=src\boards\KS7031.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit256] +FileName=src\boards\KS7030.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit257] +FileName=src\boards\ffe.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit258] +FileName=src\boards\18.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit259] +FileName=src\boards\bb.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit60] +FileName=src\general.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit260] +FileName=src\boards\addrlatch.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit266] +FileName=src\boards\246.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit270] +FileName=src\boards\40.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit272] +FileName=src\boards\42.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit273] +FileName=src\boards\46.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit275] +FileName=src\boards\51.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit276] +FileName=src\boards\62.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit277] +FileName=src\boards\80.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit278] +FileName=src\boards\79.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit279] +FileName=src\boards\77.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit280] +FileName=src\boards\vrc1.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit281] +FileName=src\boards\vrc3.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit282] +FileName=src\boards\72.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit284] +FileName=src\boards\36.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit285] +FileName=src\boards\65.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit274] +FileName=src\boards\50.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit283] +FileName=src\boards\71.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit23] +FileName=src\video.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit138] +FileName=src\boards\bmc64in1nr.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit261] +FileName=src\boards\228.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit262] +FileName=src\boards\230.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit264] +FileName=src\boards\234.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit265] +FileName=src\boards\244.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit267] +FileName=src\boards\32.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit268] +FileName=src\boards\33.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit269] +FileName=src\boards\252.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit271] +FileName=src\boards\41.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit263] +FileName=src\boards\232.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit254] +FileName=src\boards\lh32.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit287] +FileName=src\boards\vrc6.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit288] +FileName=src\boards\mmc2and4.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit289] +FileName=src\boards\69.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit290] +FileName=src\boards\vrc7.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit291] +FileName=src\boards\emu2413.c +CompileCpp=0 +Folder=boards/vrc based +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit292] +FileName=src\boards\mapinc.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit297] +FileName=src\boards\246.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit298] +FileName=src\boards\addrlatch.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit286] +FileName=src\boards\67.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit299] +FileName=src\boards\addrlatch.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit301] +FileName=src\boards\addrlatch.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit302] +FileName=src\boards\addrlatch.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit303] +FileName=src\boards\addrlatch.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit304] +FileName=src\boards\addrlatch.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit218] +FileName=src\boards\KS7017.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit305] +FileName=src\boards\addrlatch.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit306] +FileName=src\boards\addrlatch.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit307] +FileName=src\boards\addrlatch.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit308] +FileName=src\boards\bb.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit309] +FileName=src\boards\bb.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit310] +FileName=src\boards\bb.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit311] +FileName=src\boards\bb.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit312] +FileName=src\boards\bb.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit314] +FileName=src\boards\99.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit315] +FileName=src\boards\99.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit93] +FileName=src\drivers\win\sound.c +CompileCpp=0 +Folder=drv_win +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c sound.c -o sound.o $(CFLAGS) + +[Unit92] +FileName=src\drivers\win\config.c +CompileCpp=0 +Folder=drv_win +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c config.c -o config.o $(CFLAGS) + +[Unit91] +FileName=src\drivers\win\throttle.c +CompileCpp=0 +Folder=drv_win +Compile=0 +Link=0 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c throttle.c -o throttle.o $(CFLAGS) + +[Unit90] +FileName=src\netplay.c +CompileCpp=0 +Folder= +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit89] +FileName=src\drivers\win\cheat.c +CompileCpp=0 +Folder=drv_win +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit88] +FileName=src\drivers\win\log.c +CompileCpp=0 +Folder=drv_win +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit85] +FileName=src\drivers\win\input.c +CompileCpp=0 +Folder=drv_win +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit53] +FileName=src\fceu-endian.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit181] +FileName=src\boards\103.c +CompileCpp=0 +Folder=boards/fds conversions +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit148] +FileName=src\boards\235.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit139] +FileName=src\boards\bmc70in1.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit86] +FileName=src\drivers\win\joystick.c +CompileCpp=0 +Folder=drv_win +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit84] +FileName=src\drivers\win\debug.c +CompileCpp=0 +Folder=drv_win +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit59] +FileName=src\filter.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit70] +FileName=src\ppu.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit42] +FileName=src\drivers\common\config.c +CompileCpp=0 +Folder=drv_common +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit52] +FileName=src\driver.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit51] +FileName=src\drawing.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit50] +FileName=src\debug.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit49] +FileName=src\crc32.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit48] +FileName=src\cheat.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit47] +FileName=src\cart.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit46] +FileName=src\x6502struct.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit45] +FileName=src\drivers\common\args.c +CompileCpp=0 +Folder=drv_common +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit153] +FileName=src\boards\88.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit293] +FileName=src\boards\emu2413.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit294] +FileName=src\boards\178.c +CompileCpp=0 +Folder=boards/multigame boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit41] +FileName=src\drivers\common\cheat.c +CompileCpp=0 +Folder=drv_common +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit40] +FileName=src\drivers\common\vidblit.c +CompileCpp=0 +Folder=drv_common +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit131] +FileName=src\boards\112.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit132] +FileName=src\boards\mmc3.h +CompileCpp=0 +Folder=_Headers +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit179] +FileName=src\boards\106.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit295] +FileName=src\boards\mihunche.c +CompileCpp=0 +Folder=boards +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/Makefile.libretro b/Makefile.libretro new file mode 100644 index 0000000..986df9c --- /dev/null +++ b/Makefile.libretro @@ -0,0 +1,139 @@ +DEBUG = 0 + +ifeq ($(platform),) +platform = unix +ifeq ($(shell uname -a),) + platform = win +else ifneq ($(findstring MINGW,$(shell uname -a)),) + platform = win +else ifneq ($(findstring Darwin,$(shell uname -a)),) + platform = osx +else ifneq ($(findstring win,$(shell uname -a)),) + platform = win +endif +endif + +# system platform +system_platform = unix +ifeq ($(shell uname -a),) +EXE_EXT = .exe + system_platform = win +else ifneq ($(findstring Darwin,$(shell uname -a)),) + system_platform = osx +else ifneq ($(findstring MINGW,$(shell uname -a)),) + system_platform = win +endif + +ifeq ($(platform), unix) + TARGET := libretro.so + fpic := -fPIC + SHARED := -shared -Wl,--version-script=src/drivers/libretro/link.T -Wl,-no-undefined + ENDIANNESS_DEFINES = -DLSB_FIRST -DLOCAL_LE=1 + ZLIB_DIR := ./src/zlib +else ifeq ($(platform), osx) + TARGET := libretro.dylib + fpic := -fPIC + SHARED := -dynamiclib + ENDIANNESS_DEFINES = -DLSB_FIRST -DLOCAL_LE=1 + CFLAGS += -DHAVE_ASPRINTF +else ifeq ($(platform), ps3) + TARGET := libretro_ps3.a + CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe + AR = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ar.exe + PLATFORM_DEFINES := -D__CELLOS_LV2 +else ifeq ($(platform), sncps3) + TARGET := libretro_ps3.a + CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe + AR = $(CELL_SDK)/host-win32/sn/bin/ps3snarl.exe + PLATFORM_DEFINES := -D__CELLOS_LV2 +else ifeq ($(platform), psl1ght) + TARGET := libretro_psl1ght.a + CC = $(PS3DEV)/ppu/bin/ppu-gcc$(EXE_EXT) + AR = $(PS3DEV)/ppu/bin/ppu-ar$(EXE_EXT) + PLATFORM_DEFINES := -D__CELLOS_LV2 -DHAVE_ASPRINTF +else ifeq ($(platform), xenon) + TARGET := libretro_xenon360.a + CC = xenon-gcc$(EXE_EXT) + AR = xenon-ar$(EXE_EXT) + PLATFORM_DEFINES := -D__LIBXENON__ + CFLAGS += -DHAVE_ASPRINTF +else ifeq ($(platform), ngc) + TARGET := libretro_ngc.a + CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) + AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) + PLATFORM_DEFINES := -DGEKKO -DHW_DOL -mrvl -mcpu=750 -meabi -mhard-float + CFLAGS += -DHAVE_ASPRINTF +else ifeq ($(platform), wii) + TARGET := libretro_wii.a + CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc$(EXE_EXT) + AR = $(DEVKITPPC)/bin/powerpc-eabi-ar$(EXE_EXT) + PLATFORM_DEFINES := -DGEKKO -DHW_RVL -mrvl -mcpu=750 -meabi -mhard-float + CFLAGS += -DHAVE_ASPRINTF +else + TARGET := retro.dll + CC = gcc + SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=src/drivers/libretro/link.T + ENDIANNESS_DEFINES = -DLSB_FIRST -DLOCAL_LE=1 + ZLIB_DIR := ./src/zlib +endif + +ifeq ($(DEBUG), 1) + CFLAGS += -O0 -g +else + CFLAGS += -O3 -DNDEBUG +endif + +LIBRETRO_DIR := ./src/drivers/libretro +FCEU_DIR := ./src + +FCEU_SRC_DIRS := $(LIBRETRO_DIR) $(FCEU_DIR) $(FCEU_DIR)/boards $(FCEU_DIR)/input $(FCEU_DIR)/mappers $(ZLIB_DIR) + +FCEU_CSRCS := $(foreach dir,$(FCEU_SRC_DIRS),$(wildcard $(dir)/*.c)) +FCEU_COBJ := $(FCEU_CSRCS:.c=.o) + +OBJS := $(FCEU_COBJ) + +FCEU_DEFINES := -D__LIBRETRO__ -DSOUND_QUALITY=0 -DPATH_MAX=1024 -DINLINE=inline -DPSS_STYLE=1 -DFCEU_VERSION_NUMERIC=9813 $(PLATFORM_DEFINES) + +ifeq ($(platform), sncps3) +CODE_DEFINES = +WARNING_DEFINES = +else +CODE_DEFINES = -std=gnu99 +WARNING_DEFINES = -Wno-write-strings +endif + +CFLAGS += $(CODE_DEFINES) $(fpic) $(WARNING_DEFINES) $(FCEU_DEFINES) $(ENDIANNESS_DEFINES) +LDFLAGS += -lm + +INCDIRS := -I$(LIBRETRO_DIR) -I$(FCEU_DIR) -I$(FCEU_DIR)/input -I$(FCEU_DIR)/boards -I$(FCEU_DIR)/mappers +LIBS := + +$(TARGET): $(OBJS) +ifeq ($(platform), ps3) + $(AR) rcs $@ $(OBJS) +else ifeq ($(platform), sncps3) + $(AR) rcs $@ $(OBJS) +else ifeq ($(platform), psl1ght) + $(AR) rcs $@ $(OBJS) +else ifeq ($(platform), xenon) + $(AR) rcs $@ $(OBJS) +else ifeq ($(platform), ngc) + $(AR) rcs $@ $(OBJS) +else ifeq ($(platform), wii) + $(AR) rcs $@ $(OBJS) +else + $(CC) -o $@ $(SHARED) $(OBJS) $(CFLAGS) $(LDFLAGS) $(LIBS) +endif + +%.o: %.c + $(CC) -c -o $@ $< $(CFLAGS) $(INCDIRS) + +clean-objs: + rm -f $(OBJS) + +clean: + rm -f $(OBJS) + rm -f $(TARGET) + +.PHONY: clean clean-objs diff --git a/changelog.txt b/changelog.txt new file mode 100644 index 0000000..e9c72e8 --- /dev/null +++ b/changelog.txt @@ -0,0 +1,2237 @@ +0.98.13: + + SDL: Fixed button configuration when using joystick hats. Thanks to + ShaolinMan for pointing out the code errors. + + Readded checks in ines.c for some common bad dumps and non-working hacked + games. + + Sprite hit emulation is more precise(as it was in 0.97.5). + + Fixed mapper 185 emulation to work properly with the Japanese + version of "Spy vs Spy", and hopefully with the GOOD dump + of Banana(I don't think one exists). + + Added per-game hacks for Shougi Meikan '92 and Shougi Meikan '93. + + Fixed a bug in SetupCartMirroring() that could cause some games to have corrupted + mirroring if loaded in a certain order. This was a rather major, long-standing + bug. :/ + + Added many iNES header corrections. + + Fixed emulation of the "ISB" and "DCP" invalid opcodes. + + Optimized the PPU background drawing code with inline assembly. Older/some(?) versions + of gcc may produce bad code(from previous experience with inline + assembly in gcc), but 3.4.1 seems to do ok. + + Optimized some of the low-quality sound emulation code. + + Added a command-line option to the configure script to enable the FCE Ultra + debugger(disabled by default). It reduces executable size, and may increase speed + of execution slightly. + + In unix-netplay.c, replaced the ioctl() on a socket to read the number of bytes available to read + with a select(). I've also added some "BEOS" #ifdefs. I don't know if they will + work properly. + + Replaced archaic include of "malloc.h" in unix-netplay.c with "stdlib.h". + Also in unix-netplay.c, I've added: + + #ifndef SOL_TCP + #define SOL_TCP IPPROTO_TCP + #endif + + Fixed a bug in sdl-sound.c that would prevent FCE Ultra from being compiled + on certain platforms(Mac OS X). + + Fixed variable declarations in the following files to be compatible + with C compilers that don't adhere to C99(or was it C98...): + movie.c + drivers/sexyal/convertgen.c and drivers/sexyal/convert.inc + drivers/pc/unix-netplay.c + +0.98.12: + + Win32: Fixed the behavior of the sound logging function. + + Fixed a bug that was causing 2xscale/3xscale to be broken + when clipping the leftmost and rightmost 8 columns. + + Added an iNES header correction entry for JustBreed. + + Modified the MMC5 "ELROM" board emulation to not emulate WRAM. + + Corrected various pieces of code that were causing compiler warnings. + + Win32: Scaling settings(x, y, stretch to fill screen) are now respected while + using a special scaler in full screen mode, though if x or y scale is + less than what is needed for a particular scaler, it will be + adjusted. + + Win32: The window will be reblitted when it becomes invalidated while + a game is loaded(such as when you're resizing the window). + + When the PPU is in a "dead" state after starting up, the graphics + buffer is now cleared. Previously, particularly in the Windows port, when + a game was closed, and a new game was loaded, the last image from + the previous game would be displayed for a short time. + + Win32: Blit skipping will now occur when sound is disabled and FCE Ultra is + running behind the desired frame rate. + + Win32: Blit-skipping behavior can now be configured to some extent in the "Timing" configuration + window. + + Win32: Added a "Recent Directories" submenu to the "File" menu. + + Removed some debugging code that shouldn't have been enabled in 0.98.11. + +0.98.11: + + Win32: Special scalers are now also supported in windowed mode. For Scale2x/Scale3x, + the fastest "desktop" bit depth is 16bpp. For hq2x/hq3x, it is 32bpp. + + The shared video blitting code(drivers/common/vidblit.c) can now blit using Scale2x + and Scale3x to any target bit depth(8bpp, 16bpp, 24bpp, and 32bpp) instead of just + 8bpp, as it was before. + HQ2x and HQ3x can now blit to 16bpp, 24bpp(untested), and 32bpp. The 16bpp and + 24bpp targets are done doing post-processing conversion, after HQ2x/HQ3x, which + really does hurt speed. + + Changed a few names in the credits section of the documentation to their + aliases. Names you didn't get to pick to have are so troublesome. :b + I also made various fixes/updates to the documentation. + + Updated the FAQ with some information regard video mode bit depths and speed. + + SDL: Disabled the fast-forward-key speed-limiting code. I thought I had + done this before... + + Fixed a major bug in the movie recording code, and added some code to automatically detect + and fix playback of broken movies from earlier versions. + + Did a little swapping thing with mapper 90 and 209. I moved back Mortal Kombat 3 + to mapper 90, and moved Shin Samurai Spirits 2 to mapper 209. Sorry for any confusion. + Mapper 90 should be considered as having the fancy nametable select mode disabled, with + mapper 209 having it enabled. + + Added support for mapper 160, which turns out to be the same hardware as mapper + 90. Joy. + + Improved mapper 90 emulation. This mapper really needs low-level + emulation for IRQs to work right, though. :/ + + Win32: Fixed the "hide left/right 8 video columns" feature. + + Since FCE Ultra is ending(or has already exceeded? :b) its actively-updated life, + I've gone ahead and added per-game hacks for "Kick Master" and the PAL version + of "Star Wars". See the documentation for more details. + + Minor optimizations to the high-quality sound emulation code. The FIR filter + code is the bottleneck, though, so these changes won't have much of an effect + on overall speed. + + Altered MMC3 IRQ emulation(and the hooks in ppu.c for it). + + Fixed a rather major typo in the VRC7-emulation code. + +0.98.10: + + Reimplemented network play. It now requires a standalone network play server, which + will be released as a later time. For fun, "starmen.net" is running this server, + which is publicly accessible. + I also made various code fixes/improvements to allow for network play, particularly + with the command handling code. + + Reworked much of the VS Unisystem emulation code, partially based on information from + MAME. The following games are now supported: + + Battle City + Castlevania + Clu Clu Land + Dr. Mario + Duck Hunt + Excitebike + Excitebike (Japanese) + Freedom Force + Goonies, The + Gradius + Gumshoe + Hogan's Alley + Ice Climber + Ladies Golf + Mach Rider + Mach Rider (Japanese) + Mighty Bomb Jack (Japanese) + Ninja Jajamaru Kun (Japanese) + Pinball + Pinball (Japanese) + Platoon + RBI Baseball + Slalom + Soccer + Star Luster + Stroke and Match Golf + Stroke and Match Golf - Ladies + Stroke and Match Golf (Japanese) + Super Mario Bros. + Super Sky Kid + Super Xevious + Tetris + TKO Boxing + Top Gun + + Win32-native: Fixed a bug in the debugger's breakpoint list that appeared when + one tried to delete a breakpoint(the control accidentally had auto-sort enabled, + causing a discrepancy between what was displayed and what was contained in internal + data structures). + + The current disk image XOR original disk image is now stored in save states. This + should greatly increase compressability(important for network play), and make + it a little more legal to distribute such save states now. + + Modified the save state format to allow for more precise and larger version numbers. + + Various minor code changes. + + Fixed initialization of the FCEUGameInfo structure, which previously led + to problems with sound output on the SexyAL-using ports(Linux). + + Apparently I added support for mapper 255 a while back. Documentation updated. + + Added iNES header correction information for Armored Scrum Object and Alpha Mission. + + Merged banksw.h into ines.c, fixed some of its prototypes in ines.h. + +0.98.9: + + Win32-native: Fixed the speed throttling used when sound is disabled. In previous + 0.98.x Win32-native releases, emulation was running at 1/2 the speed it should + have been when sound was disabled. + + Win32-native: Moved settings in the "Miscellaneous" configuration window + to where they should have been in the first place, and added "GUI" and "Timing" + configuration windows to accommodate some. + + Win32-native: Fixed the handling of the "Scroll Lock" key used to disable and + enable Family BASIC Keyboard input. + + Updated documentation to handle some slight differences in the Win32-native + port("Win32-native" is what the Win32 port using native APIs, as opposed to something + like GTK+ and SDL, will be referred to in documentation now). I also made + some other minor wording adjustments to the documentation. + + Added an iNES header correction for Dragonball. + +0.98.8: + + Fixed a typo in sound.c that caused only part of the sound registers + to be saved in save states. + + Win32: Switched over to the DirectDraw7 interface, from DirectDraw4's. + The surface Flip() method will now block, which results in somewhat + smoother animation/scrolling, especially when combined with the + auto blit-skip implemented in 0.98.6 when sound is enabled. + + Win32: Undid a change made in the last release that limited the + speed of fast-forwarding when using the tilde key. I really do + need to implement some sort of unified timing/blit skip system... + + Win32: Added an option, disabled by default, to ask for confirmation + before exiting FCE Ultra. + + Win32: Added an option, enabled by default, to disable the system + screen saver while a game is loaded. + + Win32: Added a new video synchronization mode, a "lazy" wait for + vblank/vertical retrace. It calls Sleep(0) in its wait loop. This + still uses all available cpu cycles, but it is much more friendly + to other processes than the old-style wait for vblank. + + Win32: Added support for joystick POV hats. + +0.98.7: + + Fixed a bug in the debugger's disassembler when disassembling + opcode 0xBC. + + Fixed the behavior of the right mouse button with zapper emulation, to + correspond with what it is documented as doing. + + Win32: Added proper support for maximizing the window. + + Win32: Rewrote most of the input and input configuration code. + + Win32: Changed the configurable aspect ratio to something sensical, the current + display's pixel aspect ratio, default of 1:1(square pixels). + + Win32: Made the default full-screen video mode the custom video mode. I should have + done this a long time ago to make custom video mode configuration more straighforward + for users... + + Added some JACK audio code to be used by the SDL build. I'll test it and complete + it later. + +0.98.6: Made several code modifications to work with older versions of gcc. + + Fixed more header file network play #ifdef-age. + + Fixed a typo in cart.h. + + Fixed some funky code in FCEU_memmove(). + + Fixed some source code causing compiler warnings. + + Fixed SexyAL's format conversion code to not rely on deprecated casting semantics. + + Readded the native Win32 code, and made many improvements. The major thing + that needs to be done now with it is to rewrite the input handling code and input + configuration code. + +0.98.5: + Added LL to the 64-bit integer constants in ines.c + + Fixed OpenGL support under Mac OS X. + + Added the ability to hide background and/or sprites with the F4 key. + +0.98.4: + Moved NETWORK #ifdef's to netplay.c to simplify things. + + Fixed gzip file loading code(I think). I'm still a bit unsure about the semantics + of dup() and close(), though. + + Corrected FDS code to try loading the FDS image before loading the BIOS. + + Readded "native" SDL sound code, used for Mac OS X(and maybe BeOS). + +0.98.3: + Removed the wxWindows GUI code. GTK+ 2 code will take its place, + once it is ready. + + Added reset and power commands to the movie format. More commands(such as insert + disk, eject disk, flip dip switch, etc.) will be added simultaneously as work + on network play continues. + + Modified SexyAL OSS code to not adjust the number of fragments to a power of 2. + It works fine on my card, allowing finer-grained buffer size control, + but I'm not sure it will work with all chips. + + Fixed parsing of the "-specialfs" command-line argument. + + Added the hq3x scaler. + + Updated to the latest Scale2x code. I also added the Scale3x scaler. + + Changed the keyboard assignments for toggling full screen to "Alt" + "Enter". + + FCEUI_SaveState() and FCEUI_LoadState() changed. Porters should read + driver.h. + + Miscellaneous changes to accommodate new network play plan. It's not close + to being finished. + + Altered RTI emulation. In Paris Dakar Rally's NMI handler, it does "CLI ; RTI". + Previously, FCE Ultra would generate an interrupt right after RTI occured, due to the + presumed latency that RTI had with the I flag. I changed it so there is no latency, so + no interrupt will occur in this case(interrupts kill this game). The interrupt source + is the "frame IRQ", which it never disables, if anyone cares. + This change does break the "Stars SE" demo, though. Hmm. + + "FCEUGameInfo" is now a pointer, rather than just a statically-allocated structure. + This may cause some null-dereferencing-related crashes, but it should help keep + code a little cleaner(maybe?). + + Played around with the FDS FM code some more. It's still not right. Bah. + + Hacked in support for entering Datach/Barcode World barcodes without a GUI, using the + F8 key and the numeric keys. + + Added code to save/load movies. Movie support will only record/play back the + states of the four emulated gamepads. + + Modified the sound code to use timestamp/timestampbase differently. In addition, + timestampbase is now saved in save states("timestamp" doesn't need to be saved, since + it's reset to 0 at the end of each emulated frame). + +0.98.2: + Fixed a few problems with the SDL command-line build code + for Win32. Also, SDL 1.2.7 seems to have a bug that breaks FCE Ultra's + full-screen/windowed switching capabilities(at least under Win32). + Stupid everything. + + Minor SexyAL changes. + + Updated documentation. + +0.98.1: + + Increased the volume of the FME07 sound channels. + + Fixed a bug in the SexyAL endian conversion code. + + Made the SexyAL chunk conversion loop work. + + Replaced the old OPL2 emulator with a modified version of + Mitsutaka Okazaki's YM2413 emulator for the VRC7 sound emulation. + + Decreased the pitch of the FME 07 expansion sound channels by one octave. + + Decreased volume of output of $5011 in MMC5 emulation code. + + +0.98.0: Some changes I made aren't listed below. Ah well. The magnitude + of the changes was too great... + + + Default sound volume is 100(%), which makes a lot more sense than 75%, but not much. + It's multiplied by 3/4 internally now. + + Added support for the Datach barcode reader(GUI interface only). The emulation code + was adapted from the VirtuaNES source code. + + Reassigned the Datach games to mapper 157, from 16, with CRC32 checks. + + Increased the maximum number of screen snapshots in the snapshots directory + to 99999(from 999). + + Reassigned the following games to mapper 210, using CRC32 checks: + Chibi Maruko Chan + Dream Master + Family Circuit '91 + Famista '92 + Famista '93 + Famista '94 + Heisei Tensai Bakabon + Top Striker + Wagyan Land 2 + Wagyan Land 3 + If you use a hack/translation of one or more of these games, you will of course + need to manually change the mapper number in the header for it to work properly in + FCE Ultra. Family Circuit '91 still may not fit in with the rest of these games, + but it's definitely not a "stock" mapper 19 setup. + + Fixed an OpenGL palette bug when using scanlines(previously, I think it was + setting the palette of the scanlines overlay texture instead of the actual image + texture in some instances). The bug showed up on games that make use of the color + deemphasis bits. + + Rewrote a lot of the PPU background rendering code to be more accurate(and + obfuscated!). This eliminates the X-offset hack I made earlier. + + Removed some of the NSF visualization code, and altered the look of the NSF + display slightly. The NSF waveform visualization code will now take into + account the current volume setting. + + Changed the default key bindings for the standard emulated gamepad + to something more compatible with window managers. I may change it back, but probably + not, since it is easily configurable now. + + Updated the MMC5, VRC6, and FME07 low-quality sound emulation code + with the compatible parts of the high-quality sound emulation code for those chips. + + Adjusted timing of horizontal scroll update(near the beginning of hblank. I made + it occur sooner). I also added a hack to allow X-offset(fine X scroll) changes mid + scanline, however, it is extremely ugly, and may not work correctly for everything + (doing it correctly would probably kill speed). + I mainly did it to fix games like F-1 Race and Mach Rider, and other racing + games that are extremely sensitive to horizontal scrolling timing. + + Some FDS IRQ emulation changes to fix some screen corruption problems + in "Kaettekita Mario Bros". + + Removed zlib(the code, not support). + I also removed support for compiling without zlib(it's small, simple, provides + very useful functions, and may provide critical features for fceu in the future). + + *undone, breaks debugger, FIXME.* Replaced some inline functions with macros in x6502.c. + + Increased the speed of Namco 106 sound emulation in HQ sound mode. + + Many many sound emulation changes and adjustments based on blargg's tests. + The default sound volume is about 150% what it was before, because the sound range + has changed(now -soundvol 100 is like -soundvol 200 on older builds), and the + default "soundvol" setting is 75. 100 clips on some Namco games, and 200 clips + on many games, so I'll probably have the configurable volume range as [0:125]. + What exactly is "%" supposed to mean in this case.... 100% of what?! + + When using low-quality sound emulation mode, total emulation speed is about 10% + less than previous builds. The change in speed for high-quality sound emulation + mode is significantly less. + + Added beginnings of SexyAL to source code tree, removed SDL sound support, and + old OSS code. + + Copied over some autoconf/automake stuff from phamicom. It stills needs a bit + of work... + + Fixed DMC IRQ emulation. Fixes many CodeMasters games. Finally. ^_^ + + Restructured a lot of files, changed the interface between driver and + emulator code slightly. + + * Insert stuff here * + +November 28, 2003 - Snapshot + + Removed the DOS, Linux SVGAlib, and Win32 targets. *GASP* + Win32 support will return(eventually), using SDL + wxWindows. + SDL can use svgalib or GGI anyway, so it shouldn't be a huge loss. + DOS support will only return if someone ports SDL to DOS. ^_^ + It would be nice if SDL could accept modelines. Maybe in SDL 2.0... + + Merged fce.c and svga.c into fceu.c, and fce.h and svga.h into fceu.h. + + Reassigned "Mortal Kombat 3 - Special 56 Peoples" to mapper 209. + + Added emulation of the "Oeka Kids" tablet. + + Added emulation of the Family Trainer. + + Added emulation of the "Ultimate Quiz King" buzzers. + + Added emulation of the Mahjong controller. + + Added emulation of HyperShot controllers. + + Fixed loading of NSFs with load addresses below $8000. + + Cleaned and simplified some of the NES APU code. + + Altered mapper 65 emulation. Fixes Kaiketsu Yanchamaru 3. Does it break anything? + + Wrote a small FAQ file. + + Fixed displaying of garbage and other unpleasantness on the first scanline. I need + to clean up that code, though. + + Fixed color deemphasis emulation when all bits are set. For some + reason, I had commented out the code. Bleh. + + NSF player now writes $C0 to $4017 if the FDS is being used(the FDS + BIOS writes $C0 to $4017). $40 for all other NSFs. + + Added support for iNES mapper 58(nnnesterj). + + Added support for iNES mapper 208. + + Reassigned "Fudou Myouou Den" to mapper 207(CRC32 checks). + + Reassigned "Karnov" to mapper 206(CRC32 checks). + + Fixed the mapper 95 code, which was horribly broken. + + Differentiated between mappers 33 and 48. Added CRC checks to assign + some games to mapper 48. "Flintstones 2" and "Don Doko Don 2" are + the games that need to be assigned to 48. Are there others? + + Replaced usage of TriggerIRQ to X6502_IRQBegin/X6502_IRQEnd combos in + various mapper emulation files. 67, 33/48, 40, 73, 42, 65, 6, 182 + Removed function TriggerIRQ() from x6502.c + + Fixed the sound volume of the VRC7 emulation in high-quality sound mode. + Decreased(slightly) the volume of VRC7 emulation in both high-quality sound modes. + + Decreased the volume of the MMC5 expansion sound channels. + + Decreased the volume of the FME-7/mapper 69 expansion sound channels. + + Added FCEU_gmalloc(), which will call exit() if memory allocation fails, + otherwise it is guaranteed to return a memory block. + This will be used in the mapper code mainly. It should only + be used for small memory chunks. The reasoning is that if 64 some like KB of + RAM or less can't be allocated, for example, it'd probably be best to + exit the emulator ASAP. It also helps to simplify code logic, and + help (me) with modularization. + The behavior of this may change in the future. I still need to think about it. + I should probably save the configuration file regularly(or much better, + use the registry) on the Windows port, though. + + Cleaned up the save-state saving/loading code a bit, and added + support for linked save state structures for better modularity and + less code duplication. + + Merged the iNES and UNIF MMC1, MMC3, and MMC5 code more completely. + I may need to sanify CHR RAM and WRAM allocation for pedanticness, + though. Also worked on Tengen RAMBO-1 emulation, and mapper 90 emulation. + ***THIS MAKES SAVE STATES FOR GAMES THAT USE THESE EXPANSION CHIPS INCOMPATIBLE + WITH PREVIOUS VERSIONS*** + I plan on doing the same thing with other mappers/boards in the future, though. + Always on the quest for 1.0... + +November 12, 2003 - 0.97.5 Release + + Windows: Added limited support for arguments that change configuration + to be passed to FCE Ultra. Example: fceu -pal 1 c:\streetgangs.nes + It may be useful in frontends. + + Fixed filename generation for automatic IPS patching when a file + with no extension is loaded. Before this change, FCEU would + look for "game..ips" with a file named "game". + + Converted and updated the cheat guide in(to) HTML. + + Added support for iNES mappers 202,203,231 from info from cah4e3. + Fixed support for mappers 60, 200. + + Fixed various major bugs in the breakpoint deletion code. + + UN*X: Added support for OSS(/dev/dsp) devices that don't support mono + sound. + + Increased PPU startup idle time to 2 frames. Fixes that + unlicensed "Earthworm Jim 3" game. Does it break anything? + +November 9, 2003 - 0.97.4 Release + + Fixed another obscure PPU emulation screen corruption bug. + + Added support for Game Genie cheats in the cheat interface. + + Windows: Reworked the cheat interface, merging the cheat search + and cheat list windows into one. + + Windows: Greatly improved the CPU debugger. + The code still needs a lot of cleaning, though. + + Readjusted VRC6 IRQ emulation timing. + + Added support for the UNIF MMC3 board TEROM. The maximum PRG/CHR sizes + may not be correct in this implementation, though. + +November 8, 2003 - 0.97.3 Release + + Added a control to set the highest quality sound mode in Windows. + This change requires that any users who previously set + "high quality sound" to set it again. + + Fixed the volume of high-quality sound mode again. The changes + I made earlier didn't affect all the filter coefficients. + +November 8, 2003 - 0.97.2 Release + + Made a minor optimization to writes to palette memory. + + Altered VRC6 IRQ emulation timing slightly. + + Fixed a weirdo PPU emulation bug that could cause garbage on the right + side of the screen in certain situations. Thanks to FrenziedPanda for + bugging me enough to make me look into the problem and fix it. + I should be on the lookout to see if the fix breaks anything, though. + + Fixed the volume of high-quality sound mode(-soundq 1). It was + at 1/4 the volume it should have been. I compensated by increasing + the precision of the filter coefficients, which increased the sound + quality of that mode slightly without hurting performance. + +November 7, 2003 - 0.97.1 Release + + Fixed mapper 105 emulation. I had begun merging it into the + rest of the MMC1 code for 0.97, but I hadn't finished it. + + Changed things like RdMem(_PC++); to RdMem(_PC); _PC++; + Darn evil global variables. I need to fix them. Screw speed. + + Expanded checks for the global variable "fceuindbg"(used in debug + mode to prevent reads in the debugger from altering any registers). + +November 6, 2003 - 0.97 Release + * Note: I still had much more I had wanted to get done for 0.97, + but I lost even more interest. The Windows port still doesn't + have a way to enable the "highest" sound emulation mode, nor the + low pass filter code, not to mention that the lowpass filter code + isn't complete(I would need to design a high-order FIR filter from an IIR + filter to work properly-have the correct rolloff, among other + things-at finite playback rates). + + Fixed a bug in the IPS patcher. The recorded size wasn't being updated + after a successful realloc() was made, which could lead to corrupted patch + data from some patches. + + Added support for mappers 200, 201 from submitted code. + + Rewrote mapper 15 support to make more sense(well, depending + on your point of view...). + + Fixed 256KB CHR select support for mapper 115. + + Added support for mapper 12 from code from cah4e3. + +October 16, 2003 - Snapshot + + Fixed support for mapper 245(for nonencrypted/non-smynes-screwed up + ROM images only. Fixes "Yong Zhe Dou E Long [...] Dragon Quest 7". + + Added support for mappers 60, 62, 230, 244 from submitted code. + + Modified mapper 90 emulation to allow game-select on reset + for "Final Fight 3". + + Modified mapper 45 emulation to allow "Super 8-in-1" to work. + + Added a low-pass filter, and an option to enable it(CLI ports). + + 0x00 is now written to $4011 in the NSF player code instead of 0x40. + Fixed some other similar sound register init problems that I had fixed + in Festalon but forgot to fix in FCEU. Grrr. + + Removed some unnecessary 64-bit integer usage from FIR sound filtering + code. + + Added a new sound quality mode. Higher than high, it's highest(in + FCE Ultra, for now). Still need to fix the interface to allow + enabling it in the Windows port. + + Added some code for lower-level MMC3 IRQ emulation. It isn't completed + , and will not work properly as-is. I'm still playing around with + it occasionally. + + Fixed the sprite overflow flag(I think I fixed it), that was broken in an earlier + pre-0.97 release. + + Fixed support for iNES mapper 193. + + Command line arguments "-pal" and "-gg" now take extra arguments(1/0) + and are remembered in the configuration file. + +September 27, 2003 - Snapshot + + Added support for iNES mapper 50. + + Modified the UNIF board initialization code. Hopefully, this + new interface will eventually be used with the iNES code. + + Miscellaneous code cleanups. + + /dev/dsp is now set to 8(previously 9) buffers of 128 samples in length + in the SDL code. + + Tried to make the save state code more expandable and modular. + + Moved a lot of the PPU code into ppu.c. + + Added more extensive debugging code to the 6502 emulator, to allow + for memory read/write hooks(including zero page addressing modes). + + Readadjusted DMC timings when PAL emulation is enabled. It looks + like it was correct before I had made the August 2 change. Thanks + to Bananmos for the information. I think. :/ + + Added support for iNES mapper 193 from information from virtuanes. + I think my dump of it is "bad", though. PRG and CHR pages look + like they are in the wrong order(logical vs physical? Who's to say + what's physical?). + +September 1, 2003 - Snapshot + + Fixed some minor initialization issues with iNES mappers 7 and 34. + + Added support for UNIF board NES-GNROM. + + Removed support for save states created with versions of FCE Ultra + less than 0.56. + + Replaced SDL sound buffering code with a lock-free FIFO implementation + written by David Olofson, with a few modifications by myself. + + Fixed a VRC7 NSF bug(it showed up under the reworked driver/file + loading order in the cli code). + + The board in "Rolling Thunder" has "RAMBO 1" on it, not "RAMBO-1". + +August 9, 2003 - Snapshot + + Removed the old plain text documentation and replaced it with + a new document in HTML. It is not completed yet, though. + + Rewrote the SDL-native audio code to be less wacky and more + thread-safe(hopefully). I'm still waiting for a new SDL audio + API... + + Altered the MMC5 IRQ timing. Fixes minor graphical glitches + in Castlevania 3. Does it break anything? + + Removed some debugging code that got into the last snapshot. + +August 5, 2003 - Snapshot + + Added some code in the IPS patcher to allow for expanding the size of files. + + Fixed a double free() bug with a mapper 51 game(in ines.c). + + Added support for "Alien Syndrome" (US release) as iNES mapper 158. + It looks like a derivative of the normal RAMBO-1 board(or is that + the name of the chip?), similar to TKSROM/TLSROM(mapper 118). + + Improved the "native" SDL sound code. It will now call SDL_Delay(), + among other nice things. The code could probably be improved more, + though. + + Added support for decimal components in xscale/yscale in the SDL + port. Set the default xscale for windowed mode to 2.40(to get a + more correct aspect ratio, assuming the display is currently at + a 4:3 aspect ratio). + + Modified args.c to handle floating-point numbers. + +August 2, 2003 - Snapshot. + + Disabled texture wrapping with OpenGL(there were problems at the edges + of the screen with linear interpolation). Bah. Now the edges + are too bright... + + Improved the accuracy of the DMC timing when PAL emulation is enabled. + I still don't think it's totally correct, though. + + Changed the default settings for the SDL code. Full screen + is now 640x480x8bpp by default, xscale and yscale are 2 for both full + screen and windowed, opengl support is enabled, linear interpolation + for OpenGL is enabled, and X-axis stretching is + enabled(in full screen). + + "Scanlines" were enabled in 8bpp to 8bpp blits in + drivers/common/vidblit.c when they shouldn't have been. Fixed. + + Fixed OpenGL code under big-endian platforms. + +August 1, 2003 - Snapshot. + + Various code clean-ups. + + Played around with adding a GTK+ GUI to the SDL code. + + Rewrote part of the hq sound rectangle wave code. + + Replaced the high-quality sound inline assembly filter code with + slightly faster C code. + + Hacked around with GP32 support. I don't know if the GP32 would + be fast enough, though. + + Skipped frames will now have D5 of $2002 set at the beginning + of the frame. Fixes "Bee 52". I must see if it breaks anything. + + Added OpenGL support to the SDL code. + + Removed the PPU drawing inline assembly code, replacing it with a faster + algorithm written in C. + + "Disabling" the 8-sprite limitation will no longer cause + "Bee 52" to break. However, the "Solstice" wizard will still + have the weird thing growing out of his face in the introduction, + since it depends on no more sprites to be rendered. + + Added entry for that Black Bass game for header corrections in + ines.c + + Strip color burst bit(D0 of $2001) is only "emulated" if bg or + sprite rendering are turned on, at the end of the scanline. + Doing it with pixel/tile granularity would require modifying + the sprite graphics data copying routine, which I don't + feel like doing. Fixes that crazy Sayoonara demo by Chris Covell. + I also modified the NES RAM initialization code. + + Adjusted VRC7 IRQ emulation for better Lagrange Point goodness. + + Added support for iNES mapper 91. (VirtuaNES) + +0.96: + Improved RAMBO-1(mapper 64) emulation. "Skull and Crossbones" is + now playable. + +0.95: + + timestamp and timestampbase are no longer saved/loaded to/from + save states. They were causing too many problems I didn't + want to fix, and I never intended them to be saved in save states + when I wrote the code that uses them. + I think the reason they were being saved was that I wanted to make it + possible to add movie support and network play save state loading + (distributing the save state over the network). So if someone in + the future wants to add these features, the issues(primarily with + zapper emulation and sound emulation) with saving the time stamp will + need to be resolved. + + Fixed some crashing bugs when save states are loaded when + high-quality sound emulation is enabled. It is like patching + holes in a swiss-cheese boat. All the holes may be patched, but + it looks ugly. At least it tastes good... + TODO: Look into saving more data in the save states, especially + data that is based off of "timestamp" and "timestampbase". Also + look into validating this data. Right now, corrupt save state data + might cause memory corruption in FCE Ultra. + + Fixed some bugs in the NSF player. + + Cleaned up more code. + + Reduced the usage of TriggerIRQ(). + + Split the palette code into a new file, palette.c, from svga.c + + Low-G-Man(NTSC and PAL versions) are now recognized by CRC32 value, + and WRAM will be disabled if they are loaded. A warning/status message + will also be printed regarding this issue. + + Decreased the volume of the DMC/PCM channel in low-quality sound + emulation. + + Low-quality sound emulation now uses 32-bit integers for much + better speed. + + FCEUI_CRC32() wasn't returning anything. D'oh. Fixed. + + Added somewhat crude support for games that switch background CHR data + mid-scanline (this is needed in games such as Mother, Pirates!, + Business Wars, and Marble Madness). + + Altered NMI, IRQ, and BRK emulation again. Fixes some games, + like Bases Loaded 2 and Dynamite Bowling, and maybe some others. + I had to increase the size of the IRQlow variable for delayed + NMI execution... I also had to add a delay between PPU reset + and the PPU actually doing anything, to fix "Knight Rider". + + Fixed a mapper 90 save state bug. + + /dev/dsp code now searches for /dev/dsp before /dev/dspX (where X is + a non-negative integer). + + SDL joystick axes configuration is now done from the joystick. + + Tweaked various Konami mappers' IRQ counter emulation. + + Added custom SDL throttle code that gives up time slices instead of + using 100% cpu. + + Fixed an issue with sprite priorities on MSB-first platforms. + + Modified powerpad.c to avoid a symbol conflict when compiling on the + Power PC architecture. + +0.94r3: + sound.c: + Fixed a divide-by-zero bug that occurred when a virtual + reset(like by pressing F10) occurred when sound emulation was + disabled. + +0.94r2: + drivers/common/vidblit.c: + Fixed code for 32bpp blur effect. + + drivers/cli/sdl-video.c: + Added error message for unsupported bit depths. + + mappers/simple.c, ines.c: + Used this bug fix pseudo-release as an excuse to add + support for mapper 107. Information taken from virtuanes. + +0.94(fixed release) +--- + Fixed call to InitUNIXDSPSound in svgalib.c + + Added man pages. + +0.94 +--- + Added support for rapid fire A/B buttons on physical joysticks + in SDL/svgalib/DOS code. + + Implemented "high-quality" Namco 106 emulation(used for hq sound mode). + In this case, "high-quality" means sounding more like it should, + not necessarily cleaner. I'm not certain that it's totally correct, + but it's in the right direction. + + RAM cheats should no longer affect Game Genie emulation. I still + need to completely verify this. There may be some sort of race + condition. + + Removed various minor speed hacks in the name of style and + correctness(and to make maintaining FCE Ultra easier for those + people who are not me). :) + + Removed NSF cpu hacks, as I changed code to make them unnecessary. + + Fixed another FDS IRQ emulation bug. "Famicom Grand Prix II" works + now. + + Fixed a memory leak and a heap corruption bug in "file.c". + + Added support for on-the-fly IPS patching. + Place the IPS file in the same directory as the file to load, + and name it filename.ips. + + Examples: Boat.nes - Boat.nes.ips + Boat.zip - Boat.zip.ips + Boat.nes.gz - Boat.nes.gz.ips + Boat - Boat.ips + + Some operating systems and environments will hide file extensions. + Keep this in mind if you are having trouble. + + Patching is supported for all supported formats(iNES, FDS, UNIF, and + NSF), but it will probably only be useful for the iNES format. It + can be used with the FDS format, but be warned that it will permanently + patch your disk image, as the disk image is written back to disk + when the game is unloaded(unless the disk image is in a zip file, in + which case it isn't written back to disk). UNIF files can't be + patched well with the IPS format because they are chunk-based with no + fixed offsets. Support for a UNIF patching format may be added + in the future(probably by someone else.). + + Added more games to the list in ines.c for having battery-backed + WRAM, for header corrections. + + Copied over the 96KHz filter coefficients from Festalon that I forgot + to do in 0.92. Oops. + + +0.93 +--- + + Reduced the volume of the FDS sound channel. + + Fixed a bug in the FDS IRQ emulation code that caused "Lutter" to not work. + + Fixed a bug in unif.c that would cause a crash if a unif file were + loaded without a board name being specified(as could happen + with a corrupted nsf). + + Fixed a bug in general.c relating to relative filenames(running + fce ultra like "./fceu ../big.nes" would work, but "./fceu ../big" + would not work- it crashed). + + + +0.92r2 +--- + Fixed dpcm irq bug that broke Cobra Triangle. + +.92 +--- + + Removed NSF player background, and added some special effects goodies. + + Changed the NSF player to use the emulated gamepad as input instead + of having special NSF-player-only keys. + + Added support for mapper 249(using nonencrypted games), thanks to SARO + for info. SMYNES sucks. + + Updated video blitting library-thing(vidblit.c) with more special + effects, and removed 24bpp support. + + SDL cleanupification. + + Added support for mapper 61. + + nnnesterj: Added support for mapper 57. + + Fixed mapper number for "Golden Game 150 in 1". Changed it to 235 + from 43. + + DDraw back buffer surfaces are now created in system memory if the + hardware blitter can't do stretching. + + Restructured file wrapping code. + + Added new cheat search methods. + + Fixed a major cheat unloading memory bug(and memory leak). + + Emulated that funky nonlinear DAC effect for hi-quality sound. + + More fixes/cleanups to FDS emulation code. + + Tweaked PPU timing a bit. + + Improved network play. + + Holding the enter key down will no longer do fun stuff to the nsf + player. + + Improved NSF player. It should support streaming pcm nsfs now... + + Changed FDS keyboard keys around a bit. F6 is the disk select key, + and F8 is the disk insert/eject key. + F8 to insert VS Unisystem coin, F6 to view/toggle dip switches. + Hopefully people won't complain after blindly hitting the save state + buttons. :) + + Many fixes and improvements to the Windows port. No more cpu-consuming + wait loops(specifically, sound). Added a message window. + + FDS sound emulation improvements. + + FDS disks are now auto-inserted on power on(or was it loading a new + game...). + + Changed the default last rendered scanline to 231. + + ines header corrections are now printed as status messages, not errors. + + Rearranged input updating code. + + Fixed a sprite transfer bug. Fixes PAL version of Rainbow Islands. + + Debugger hooks added. + + Small optimizations in Refreshline and FetchSpriteData to hopefully + offset the slight slowdown in the cpu core. + + MapperHBIRQHook is now called differently(depending on hi/low bg/spr + addresses). + + Added support for unif board UNL-8237. + + Added support for mapper 144(death race). + + Added partial support for mapper 74. + + Fixed a cpu emulation bug in GETIYWR. It would sometimes set "target" + to 0x10000, which was a BAD THING(overflow; now it wraps). + + Tried to add support for mapper 241. Needs special keyboard emulation. + I think. + + Internal RAM is now initialized to something other than 0. Fixes + Minna no Taabou no Nakayoshi Dai Sakusen. + + Reassigned "The Money Game" to mapper 155. It doesn't seem to + respect the WRAM enable/disable bits. Silly game. And + Tatakae!! Rahmen Man. + + Added support for mapper 115(still needs 256KB CHR select), 241, 114,88. + + Attempted to add support for mappers 91, 187. + + Modified frame IRQ to not break so many damn games. + + Fixed sprite hit detection loop. + + Improved support for mappers 80, 90,117,154, 189. + nnnester and virtuanes. + + Reassigned "Devil Man" to mapper 154. + + Removed bogus Trojan header fix in ines.c. + + + +.81-post: +---- + Fixed/Worked around(?) compilation problems on gcc 3.2.x. + +.81: +---- + + More SDL goodies. + + Renamed "Makefile.olinuxsdl" to "Makefile.unixsdl" + + More SDL fixes and cleanups. + + BeOS port is now compiled with the "-no-fpic" flag, which allows + me to use my inline assembly. The executable work fine as far as + I can tell. + + Added "Makefile.beos". gcc doesn't like my inline assembly + used in RefreshLine(),so this port will likely be slightly slower than + other x86 ports. + + Added a check to make sure SIGBUS is not equal to SIGSEGV in + drivers/cli/main.c. Needed for compiling under BeOS. + + Renamed the "PI" member of the X6502 structure due to conflicts with + a defined symbol with some math header files. + + Merged fcelineasm.h into fceline.h + + Fixed(possibly) a possible problem in fcelineasm.h with input register + clobbering. + + More SDL changes. + + Added speed throttling code to the CLI code, and added a command + line switch "-nothrottle". + + Lots of restructuring/rewriting/merging of the MMC3 code. + + Updated DOS code to use the generic CLI wrapper. + + Reads from $4090 and $4092 now return the current envelope setting + in FDS sound emulation. I'm not sure if this is correct... Affects + "Ai Senshi Nicole" and "Bio Miracle Bokutte Upa". + + Added native SDL sound support to the SDL code. the "olinuxsdl" + now uses this code by default instead of the unixdsp sound code. + + Modified MMC3 IRQ counter emulation. I'll need to watch out to see + if it breaks any games. Fixes: MegaMan 3, Gun Nac, Klax(Japanese). + + Changed a few memory reads in x6502.c to use RdRAM instead of RdMem, + resulting in a slight speed increase. + + Cleaned up mapper 250 emulation code. + + Added support for iNES mapper 51(thanks to Kevin Horton for the + information). + + Merged some iNES mappers corresponding to bootleg multicarts + based on MMC3s with mbshare/mmc3.c. + + Added support for iNES mapper 52(thanks to Kevin Horton for the + information). + + Made some hacks to the MMC3 emulation code so that I can add support + for pirate MMC3 multicarts more easily. I should clean it up later. + Moved mapper 44 emulation code to mbshare/mmc3.c. + + Saving screen snapshots will no longer corrupt the frame buffer + for one frame(unless memory couldn't be allocated). + + Fixed screen snapshot saving(it was sort of broken due to the + changes made to the driver<->emulator interface code; status + messages were being saved to the image). FCEUI_SaveSnapshot() + no longer returns a value(the request to save a screen snapshot is + serviced before status information would be written in the next frame). + + nosprites is now set to 0 before RefreshSprite() returns, to prevent + problems if a game turns off the bg and sprites when FetchSpriteData() + for the next scanline is called but then turns on sprites when + the actual scanline is drawn. + + PPU_hook() is now called more often if PPU_hook is non-null. + Made changes to mappers 118, 95, 9, and 10 to compensate. + No games seem to be broken, and I added support for mapper 96 + (though the games aren't very playable because the special controller + isn't emulated). + + Romance of the 3 Kingdoms is now recognized to use 16KB ex-WRAM. + + Added support for mapper 185...sort of. I think this is another + instance of incompatible hardware being lumped onto one mapper number. + Sigh. + + Added support for "Famicom Jump 2" as iNES mapper 153. + If a good(as far as I can tell) dump is loaded, FCE Ultra will + automatically fix the mapper number. + I also made some changes to the mapper 16 IRQ emulation code. + + BRK now sets the I flag. + + Reads from $4015 no longer reset DPCM IRQ. + + Changed emulation of RTI instruction slightly. + + X.IRQlow is now set to 0 in PowerNES(). + + The VS Unisystem bit in the iNES header is no longer looked at( + I was having too many problems with this bit being set when it + shouldn't have been). Now, VS Unisystem emulation is enabled + when a known VS Unisystem game is loaded. I also rewrote the VS + Unisystem detection function. + + iNES mapper 1 now supports pageable CHR RAM if no CHR ROM is present. + Fixes "Family School". + + Mapper 70 no longer has a mirroring control emulated, and I extended + the number of 8KB CHR pages supported to 16. + + Cleaned up iNES MMC5 save RAM loading/saving code and added + support for MMC1 games with 16KB of RAM(the second 8KB are saved), + via CRC32s(currently only Genghis Khan(USA) and Nobunaga's Ambition( + USA and Japan) are recognized). + + Added support for the MMC5 Koei game "Ishin no Arashi", in the iNES + format(I added an entry with its CRC32 value and the number of 8KB + WRAM banks it needs). + + Better iNES mapper 33/48 IRQ counter emulation. + + Added the game "Uchuusen - Cosmo Carrier" to this list. I'm + beginning to hate the iNES format more and more...or maybe + just Fanwen. :) + + Added the mapper 32 game "Major League" to the list of games + that usually need iNES header correction...but in this case, the + iNES header cannot specify that this game needs to have one-screen + mirroring. + + iNES header information is now printed before any header corrections + are made based on a database. + + Fixed a bug in mapper 32 emulation. "Ai Sensei no Oshiete" + works now. + + Tried to add support for iNES mappers 245 and 249. + + Fixed the MMC5 read handler to return the data last on the data + bus instead of 0xFF when a read was made to an unmapped address. + This seems to fix the lockup problems in "Bandit Kings of Ancient + China". + + Reversed "Modified the time at which the "y scroll" register is updated + during hblank." The changes broke Klax. + + Added an unsigned 64-bit base timestamp variable "timestampbase". + Adding this to the 32-bit variable "timestamp" will return + the number of cycles executed since emulation started(in the future + I'll probably change it to since reset or power toggle). + This allowed me to replace "lastn" hack in the MMC1 code with + something better. + + Changed my mind and undid the removal of support for old save states. + + Removed support for old save states and in general I won't + try to support save states made with previous versions. + + MMC1: Writes to $8000-$FFFF with D7 set will now cause + the first MMC1 register to be OR'ed with 0x0C. I'm not sure + if this is correct, but it doesn't seem to break anything + and it fixes Robocop 3. I'll see if anyone reports games + not working in .81 that worked in .80. + + Worked on a generic driver interface wrapper very similar + to the driver interface FCE Ultra used to use(I'm getting + tired of all of the duplicated driver code). Eventually, + the DOS, SVGAlib, and SDL ports will use this wrapper. + + Similar change to the argument parsing code. + + Changed configuration file saving-loading routines and the + configuration structure to allow for linking config structures + to each other). + + Small fix to the emulation of the MMC5 split screen mode. + + Made Linux SDL code compilable again. + + Changes to MMC5 EXRAM emulation(read/write). + + Fixes to the emulation of the MMC5's split screen mode, based on + observations while using CastleVania 3 and a Game Genie(on a real + NES). + + Fixed a bug in ines.c that caused any calls to AddExState() from + a mapper initialization function to be effectively "erased"(ResetExState() + was called after the mapper was initialized). Fixes the VRC7 sound + state saving/loading stuff. + + Finished adding support for the MMC5's split screen mode(this does + not mean that the support is complete, but at least the intro in + "Uchuu Keibitai SDF" works correctly now). + + Worked on adding support for the MMC5's split screen mode. Not + completed. + + Reverted to .80's FDS sound code. + + Modified the time at which the "y scroll" register is updated + during hblank. + + NSF playing code will now disable FDS sound output on song init + (fixes some problems with the Zelda no Densetsu NSF rip). + + Increased the emulated clock speed of the FDS sound emulation code + to give better quality output. + + Modified NMI to occur a few cycles later. Fixes BattleToads...but + it may have broken other games. Also modified the way NMI's are + handled in x6502.c. + + Modified ines.c to memset() GameMemBlock to 0 on virtual power toggle. + Also, trainers are now loaded into their own buffer instead of + directly into emulated WRAM and copied into emulated WRAM on + power toggle; I've been meaning to do this for quite some time. + + Changes to the way the zapper cursor is drawn on the screen. + + FCEUD_WriteSoundData(), FCEUD_BlitScreen(), and FCEUD_UpdateInput() + have been combined into one function: FCEUD_Update(). + + More fixes to the network play code, and a fix to the Windows network + play driver code that fixes(hopefully) a rather evil bug that caused + lockups when the remote stopped network play. + + Added code to set the battery-backed bit in RAM if a game needs it, + based on CRC32. + + Added more games to the list of games that commonly have bad iNES + headers, in ines.c + + Updated docs and usage.h for DOS and Linux regarding the new video + mode and the new refresh rates. + + Linux: Fixed a bug with video mode 6(a few upper scanlines were being + cut off). Increased the refresh rate of video mode 3 to 120hz. + + Increased the refresh rate of video mode 2 to 65 hz in the Linux port. + + Screen snapshots can now be taken while playing an NSF. + + Added a new sexy tweaked vga mode that I created to the Linux svgalib + port. It's 256x224 at a refresh rate of 103hz. Hopefully it won't + blow up anyone's monitor. ;) + DOS port will follow eventually. + + Modified Makefile.base to produce an executable named "fceu" instead + of "fce". + + The plans(cycle-accurate ppu emulation) for .90 were a bit ambitious, + and I still need to make other fixes before then. + + Fixed some minor(usually) bugs with setting 256x240 tweaked VGA mode + in DOS and Linux ports. + +.80: +---- + + Cleaned/fixed a few things in the mapper 19 emulation code. + Family Circuit '91 still doesn't work quite right... I wonder if + it's a bad dump. + + Added input override code to Windows port. + + Added code to fix iNES header information in RAM and suggest + changes to the user. + + Added support for iNES mapper 152(to be used with games set to + mapper 70, that use one-screen mirroring instead of h/v mirroring). + + Blits using the DirectX blitting function(method?) to the primary + surface are now done with the asynchronous flag set(if that + fails, a "normal" blit is tried). + + The DirectX blit buffer(secondary surface that FCE Ultra writes to + directly and then uses the DirectDraw blit function on to blit + to the primary buffer) is now created without specifying it + should be in system memory or video memory, except in the case + when no hardware blitting is available, and then DDraw is explicitly + told to create the surface in system memory. + + Added Family Keyboard support to the DOS port. + + Cleaned up the VRC7 sound emulation code. I need to find a way + to save the current sound state in a save state. + + Found out the real name of the "Space Shadow" gun; it's + called the "Hyper Shot". I'm still not sure who made it, though. + Possibly Bandai did. The interesting thing is that Konami + also made a Famicom accessory(dual square boxy things with two buttons + on each) with the same name(though there might not be a space in the + name). + + Only the upper two bits read from $4016/$4017 are undefined. + Bit5 is always 0, though. Fixed the bug in "input.c". + Silly kevtris' old documents. New kevtris' brain is always good. + + Family Keyboard support for the Windows port. + + Added support for the Family Basic Keyboard to the Linux port, other + ports todo. + Might want to add support for the tape recorder at some time. + Also mapped the "Scroll Lock" key to disable/enable command keys + so that the FBK is more useable. It doesn't disable CTRL C, + though... + + Changed a lot of inlined functions in x6502.c to macros so that + I could test out some optimization ideas. + + DOS code updates for game input override support. + + Small optimzation to opcode $4c, and relative jumps. + + Added some code to ines.c to set controller information in + FCEUGameInfo(returned by FCEUI_LoadGame()) based on crc32 values. + + Updated user documentation and usage.h for DOS and SVGAlib input + command-line changes. + + Added an option to disable the four-score(to Windows and Linux ports + so far). + + Updated Windows interface to support the new Famicom expansion + devices. + + (Re)Added support for the Famicom 4-player device. + + Improved Zapper emulation...sort of. It still needs a lot of work. :/ + + Added *partial* support for the "Space Shadow" gun. + + Added support for the Arkanoid controller(both NES and Famicom style). + + Added code to support the extension Famicom input devices. + + Added PAL scanline start/end drawing settings to Windows port. + + Added pause emulation key(F2) to Windows port. + + In the process of rewriting/fixing up input code stuff. + + Minor bug fix to Power Pad emulation code. + + VS Hogan's Alley and VS Duck Hunt automatically select the zapper + now(though it only works on the SVGAlib port). + + Undid some FDS sound code changes introduced in 0.76 that totally + screwed up sound. Oops. + + Added code to allow different settings for first/last scanline + drawn while in PAL emulation mode, to the Linux and DOS ports. + + Added convenience(it's not necessary, but it reduces redundant and + confusing code in the driver code) function + FCEUI_GetCurrentVidSystem(int *slstart, int *slend). + + Updated file "TODO". + + Changed #include to #include "zlib/unzip.h" + in file.c. + + NSF 6502 player now initialized the stack pointer on reset. + + Worked on de-emphasis emulation code quite a bit. + The deemphasized palette calculated at the end of the frame is now + based on what deemphasis bits were set for the longest during + the screen(sampling interval is a scanline) update loop. + Added a "static" deemphasized palette at $40-$7F in the palette table. + This corresponds to the colors when all of the deemphasis bits are set. + I did this to fix the PAL game "Noah's Ark", without breaking + anything else. The only downside is a slight speed loss(~2% on + my system when sound is disabled), but this is acceptable to me, + at least. + Maybe it's time to write hi/true-color ppu drawing code... + + + Fixed an out of bounds array access in svga.c in SetNESDeemph(). + The variable "lastd" in svga.c was being initialized to the wrong value. + Thanks to "Jarod CANAL" for pointing this out. + + Removed FCEUI_SetFirstRenderedLine or whatever it was called and + the function to set the last line. Replaced with: + void FCEUI_SetRenderedLines(int ntscf, int ntscl, int palf, int pall); + + Changed SetVidSys(int w) to ResetVidSys() in fce.c. Reenabled + PAL/NTSC emulation overrides based on game loaded(really only useful + for NSFs and UNIFs now). + + UNIF loading code now recognizes the chunk "CTRL" and tries + to use it. Only the svgalib code supports overriding of input + settings based on game loaded, now, though... + The user is still going to have to configure powerpad settings + on his/her own. + + Fixed return values of FCEU_fseek() and fixed a problem in unif.c + related to it. + + Changed mechanism for how FCE Ultra tells the driver + code what type of system is being emulated. A structure of + type "FCEUGI" is returned from FCEUI_LoadGame(). + + Fixed a major mapper 64 emulation bug introduced in 0.76. + + Modified BlitVidHi() in drivers/win/video.c to speed it up. + + Added support for loading the iNES-format Game Genie ROM image. + + Removed ggrom.h and added code to load the Game Genie ROM + image from a file. + + Added Windows netplay.c. (new: the user exiting the emulator + while stuck in a blocking recv() or send() loop now works.) + + Fixed a vram address register bug in fce.c that I created when I got + rid of the pair/dpair data types. + + Added new mappers/92.c + + Removed mappers/92.c until I can contact LULU or rewrite it. + + drivers/win changes. Removed netplay.c until I can rewrite it. + + Got rid of pair/dpair data types. + + Got rid of silly "TempArray" thing. + + Began adding GPL headers to files. FCE Ultra is going to be in + a state of legal limbo for the next few days... + + Replaced crc32.c and crc32.h, and added some #ifdef's and #defines + to use the crc32 code in zlib instead if zlib is linked with + FCE Ultra. + + More fixes to sb.c. + + Cleaned up drawing.h and ggrom.h(even though ggrom.h will *probably* + be removed before the next release). + + Redid frameskip code. + + Rewrote necessary pieces of sb.c and sb.h and fixed quite a few + bugs. I still need to test it on various other sound cards, though. + + Rewrote(more like "recreated in my own image") DOS keyboard driver. + Removed unused "keyscan.h" from drivers/svgalib + + Rewrote part of(the parts that Marat wrote - the connection and + closing parts) the Linux TCP/IP network play code. I guess it works, + but I haven't tested it very much. In any case, it's still dangerous + to use network play in FCE Ultra with SVGAlib, since recv() or send() + might block and since the keyboard is in raw mode, you have a problem. + Maybe a future SVGAlib will fix the general problem of lockups if + keyboard_update() isn't called, though it is only partly SVGAlib's + problem... + + Fixed FCEU_fseek() when used with a compressed file in the PKZIP + format that has been loaded. Fixes a UNIF loading problem. + Also added a check to the return value of FCEU_fseek() in unif.c. + + Replaced Marat's 6502 emulation core with my own. + It should be fully functional, but as always, I don't know if + I implemented the undocumented instructions correctly. + Several things are correct in this new core that were not in + Marat's(D flag is no longer cleared by interrupts, for example). + + Altered mapper 16 irq counter emulation slightly. + + Fixed the behavior of the SXA, SYA, and XAS opcodes based on the + documentation I have. I'm not sure what happens when page crossing + occurs with those instructions on a real NES, though. + Also CHANGED(not fixed) emulation of opcode $8B("XAA"). + + Changed some of the M* functions(absolute indexed and maybe some others) + to perform dummy reads. + + Changed some of the macros in m6502.c to inlined functions so + that I can modify and examine them more easily. + +.77: +---- + + Fixed a silly network play bug(in the global network play code) + that caused excessive lag. + + Added a "niceness" setting to the sound configuration dialog. + Removed obsolete information from the dialog. + + Fixed speed throttling code in Windows port when PAL emulation is + disabled/enabled and a new game hasn't been loaded yet. + + Commented out a printf() to debug stuff in fds.c(oops). + + Applied PK's joystick patch to the osdl code. It allows the user + to map axes and it fixes a joystick button mapping configuration saving + bug. + + Added two command line options new to Linux port to DOS port. + Just need to test them... + + Added some stuff to unif.c to allow for boards that can support + CHR RAM instead of CHR ROM(darn Sachen boards...). Fixes UNIF + version of "Q-Boy". + + Added command line option "-snapname" to Linux port. I'll add it + to the Windows port as well, but probably not to the DOS port. + + Added clip option to Linux port. + + Fixed sound logging(in Windows port) so that multiple recording + sessions now work. + + Added an option to clip the leftmost and rightmost 8 columns + of graphics in the Windows port. + + Added a submenu that lists recently opened files, in the Windows + port. + +.76: +---- + + Updated porting.txt. + + Added speed throttling code to Windows port that's used when sound is + disabled(and an option in the "Miscellaneous" + configuration window to disable it). + + Added cheat interface to DOS build. + + A few tweaks to the text cheat interface code in the cheat listing code. + Added a command to quickly toggle the status of the cheat(though a + cheat can still be disabled/enabled by (M)odifying the cheat). + + Support for UNIF UNL-TC-U01-1.5M board added. Same credits as below. + + Rewrote mapper 228 code just for the heck of it(actually, I couldn't + figure out why some(about two) of the games in the Action 52 cart + weren't working in .75(and .76). I traced it back to .71, where an apparent bug in + the undocumented 6502 opcode emulation allowed it to work, which + was later fixed for the .72 release(opcode 0x7C)). I'm thinking + that the dump is bad... + + Added a few crc32 checks to ines.c to check for and report when + a known(by me) bad(hacked or bad dump) game is loaded. + + Added support for the following UNIF boards. Thanks to Quietust + and Kevin Horton for the information. Some problems still exist + with a few games that use these boards, though... + + UNL-Sachen-8259B + UNL-Sachen-8259A + UNL-Sachen-74LS374N + UNL-SA-016-1M + UNL-SA-72007 + UNL-SA-72008 + UNL-SA-0036 + UNL-SA-0037 + + Fixes to some stuff in cart.c(for example, calling setprg32() when + only 16kb of prg data is present now works). + + Added support for iNES mapper 189. + + Tried to add support for the UNIF board "UNL-H2288". Failed. + + Updated "cheat.txt" to fix a few typos and added an example of finding + and adding a cheat using the Linux port's text interface. The actual + section on the Linux cheat interface still needs to be written, however. + + Changed network play code in the Windows port and fixed a bug. + Fixed a similar bug in the Linux netplay code....sort of. + + A few cosmetic changes to the dialogs in the Windows port. + + Fixed sound initialization on the Windows port(it was being initialized + when FCE Ultra started even if it was disabled by the user. Oops.). + + Joystick button configuration code in Windows port changed slightly + to be more useable. + + Changed reference to video mode 5 in the linux port to "1 per 4". + It may not be very meaningful, but it is certainly better + than "TV Emulation". I'll change the Windows port reference later. + + Documented video mode 7(320x240) for the Linux port. Also added + a check for the FBDev driver in order to use this mode instead + of a tweaked vga mode if that driver is being used. + + Added/Fixed cheat interface for Linux port. It's still not perfect, + though. The code is ugly... + + Callback function for FCEUI_ListCheats() now receives + status information(enabled/disabled). + + Callback functions for cheat functions now must return 0 to + stop listing cheats or 1 to continue. + + Fixed a problem(the cheat code was reading in cheats + for address $0000 from cheat files if any blank lines were present). + + SDL port zlib changes(linked dynamically to zlib now). + + More changes to envelope decay + looping on code. No longer + depends on value @ $4017. It now sounds correct based on some + tests I did with SMB3 and a GG, but Goonies 2 doesn't sound right( + based on a sound file sent to me by another person). + + Added support for iNES mapper 140. Thanks to Quietust for the + information. + + I need to figure out how to deal with the problem of so many + bad NSFs that most people consider good... + + Changed envelope decays a bit. Their behavior now depends on bit + 7 of $4017. I don't know if this is right... + + Addition of debug.c for some debugging stuff. + + Updated zlib to 1.1.4. + + Modified code in various files to allow UNIF games to override + current selected video system emulation(NTSC or PAL). Need to + make sure this really works. + + Changed sound.c to prevent desynchronization during network play. + This might slow down sound emulation slightly, especially when + sound emulation is disabled. I really don't care... + + Updating network play code. More info later... + + Moved the sound/video/etc output code in EmLoop() to the top of the + for(;;) loop so that initialization prior to calling EmLoop() will + be the same as initialization done during a call to a FCEUD_* function. + + A few very small changes to sound emulation in fds.c. + + Changed unlink() to remove() in cheat.c and removed the including + of the header file unistd.h. + + Split up the cc=... statement in RefreshLine() to make it easier + to read and not ambiguous(to Borland's C compiler). + + Changed a lot of the function declarations in cheat.c. I'll need + to verify that cheat searching still works ok and that cheats still work + ok. I'll also need to update the Windows(and Linux console) cheat code + to prevent compiler warnings. + + Fixed various minor code problems(not minor if you want to use a + compiler besides gcc). This is an ongoing process... + + Removed bit fields after reading about and thinking about possible + portability problems, though I kept some optimizations in fceline.h + + Minor code simplification in drivers/win/joystick.c(replaced + "case 200 ... 207" and "case 208 ... 215". + + Modified some code to use bit-fields in the graphics rendering code + in fce.c and fceline.h. gcc seems to be able to optimize the new + code to run faster. + + Fixed m6502.c and fce.c to initialize variables on virtual power + toggle. This should fix network play on the Windows port. + I'm also in the process of cleaning up fce.c. + +.75: +---- + Fixed directories configuration stuff in Windows port(corresponds + to .75r2). + + More changes to square wave channel envelope/volume emulation... + Changes described in the large paragraph some lines down have been + abandoned. + + Added a command line switch to set the volume in the dos port. + + Changed Windows sound configuration dialog. Now buffer length is + specified in time, not samples. I also added a volume control. + + Reduced the volume on 8-bit sound output on all ports by 1/2. + + Added a function FCEUI_SetSoundVolume(). Added support for setting + the volume via the command line in the Linux port, other ports coming + soon. + + Changed FCEUD_WriteSoundData() again. No longer has a "Check" + argument. All clipping(ugh) is done internally now. + + Added a directories configuration dialog to the Windows port. I worked + on it too long and I became a zombie, so it might have a few bugs. + That's what guine...err...users are for. ;) Don't expect me to do + anything like this for any other port, though. I don't feel like + doing it on the DOS port, and the Linux and other UNIXy ports shouldn't + really need it. + + Made some changes to the rectangle/square wave channel emulation to + fix the pops in SMB. I have no idea if what I did is correct. To + be honest, I'm not sure I know EXACTLY what I did, but it's something + like this: Writes to $4003/$4007 now reset the duty cycle count + and reload the cycle counter with the current wavelength. Writes to + $4003/$4007 now do not update the amplitude output of the channels; they + will be updated after the cycle counter hits 0(or below). + + More information in iNES informational output. + + Minor changes to mappers/16.c. + + Increased the volume of the VRC6's sawtooth wave channel. + + Added more information to the RAM cheat guide. + + Changed the triangle wave generation code slightly. I decided + to remove support for the higher-frequency triangle waves, as they + are too cpu-costly to create and are probably not very audible on a + real NES anyway. + + Major changes to how sound is mixed. This necessitated a high pass + DC-offset removing filter, and a low-pass filter just to make things + sound better. ^_^ + Note: FCEUD_WriteSoundData() no longer needs to clear the waveform + data referenced by the passed pointer; it's done internally now. + + Fixed JMP ($xxxx) - now handles wrapping like it occurs on a real 6502 + (hopefully; I'm assuming that the same holds true for the NES' cpu). + + Added the ability to load a custom global palette in the DOS port. + + Fixed bug in drivers/common/unixdsp.c(wrong return value if sample + rate was out of range). + + Many sound fixes... - Frequency sweeps, length counter stuff,... + + Changed Windows port to use IDirectInput7 and IDirectInputDevice7 + interfaces. + + Fixed a Game Genie bug in the core emulation code. It only appeared + in the Windows port, though. (Enabling gg emulation, loading a game, + and then disabling gg emulation and loading a new game while in the + gg code entry screen would cause the new loaded game to not work + correctly). + + Modified windows port to use the config saving/loading stuff in + drivers/common/config.c + + Mapper 45 cleanups/fixes. + + Added the ability to load a custom global palette in the Linux port. + Yay. + + Fixed a large number of overcomplicated code and silly bugs in + drivers/common/config.c. This changes the format of the configuration + structure, too. Also added support for saving/loading strings with + automatic memory allocation when strings are loaded. + + Minor change in InitNetplay(). + + Fixed bad type conversions for pointers to functions and fixed + some bad declarations of functions. + + Reenabled zlib support for the sdl build. I need to pay attention + to patches that modify lines than don't fit on my screen. + + Fixed vidblit.c to not emit so many warnings when compiling. + +.74: +---- + + Stop sound in Windows port when user clicks l/m/r mouse buttons + in the non-client area of the window. + + Added "Drag and drop" file open support to Windows port. + + Various code cleanups. + + mappers/33.c optimization. + + Rewrote the function "FCEU_MakeFName()". + + Removed crc32.h from mappers directory. + + Modified some of the window resizing code in the Windows port. + + Added support for waiting for vblank/double buffering to the Windows + port. + + Added/Fixed support for iNES mapper 248. + + After an NSF file is loaded, information about its header is now + displayed. + + Fixed a typo in the Namco 106 extra ram handling code. + + Improved the quality of the Namco 106's extra sound channels. + - Thank Mamiya and Applepie(real name?) for info. + + When an NSF file is being played, FCE Ultra will no longer go through + its scanline rendering loop. This speeds up NSF playback considerably. + + Updated "porting.txt". + + Moved some stuff from DriverInterface() to their own functions. + + Fixed some iNES mapper 18 IRQ counter emulation bugs. "Ninja Jajamaru - + Ginga Dai Sakusen" now works. + + Rewrote large pieces of the mapper 64 code. "Skull and Crossbones" + still doesn't work, though. + + Changed format of iNES header information output, added "ROM CRC32" info. + + Modified the way cycle timing is done slightly. No change + for NTSC emulation, but PAL emulation is a little more accurate. + + Changed the behavior of indirect indexed(I hope I got that right ;)) + instructions to behave more like a real 6502(junk reads are now + performed). + + A few optimizations/cleanups in m6502.c. + +0.73 +---- + + * Fixed several bugs with sprite emulation. Several games(such + as "Trojan" and "VS Duck Hunt") that were broken in .71 and .72 now + work ok. + * Added support for iNES mapper 82. Thanks to those who work on + "unofficial nester". + * Added support for iNES mapper 250(used by "Time Diver Avenger"). + * Fixed the documentation to show that iNES mappers 48, 83, and 232 + are supported. + * Removed various pieces of stale code and fixed a few minor bugs. + * Fixed a triangle wave channel bug(the channel was sometimes enabled + when it shouldn't have been). + * Writing to $4010 with the upper bit clear now acknowledges the DPCM + IRQ. This appears to fix "Stunt Buggies". + * Rewrote pieces of the Zapper emulation code to be cleaner and more + accurate. + * Rewrote the VS Unisystem dip switch drawing code. + * Simplified the setting of VS Unisystem dip switches. The "V" key + now toggles viewing AND editing of dip switches. + +0.72 +---- + + * Various minor bug fixes. + * Various code cleanups and size and speed optimizations. + * Removed some (apparently) unused MMC5 sound emulation code. + * Changed the behavior of $2003 and $4014 to better simulate what occurs + in a real NES. + * Fixed a few bugs in the undocumented 6502 opcode emulation code. + The Game Genie code "NUTANT" for SMB 3 works correctly now, at + least(previously it caused the game to lock up at the end of levels). + * Rewrote large pieces of the 6502 memory fetching code, resulting + in a slight slowdown in the speed of emulation. Benefits include: + Game Genie emulation now works(again) and 6502 emulation is more + accurate. + * Added support for iNES mapper 72. Thanks to rinao for the information. + * Fixed support for iNES mapper 77(used by Napoleon Senki). + * Fixed/Added support for iNES mapper 226. Apparently I made a mistake + in the documentation. Thanks to Mark K. for the information. + * Added support for iNES mapper 227. Thanks to Mark K. for the + information. + * Added support for iNES mapper 234(used by the Maxi-15). Thanks + to Mark K. for the information. Note that many of the Maxi-15 + ROM images on the Internet have corrupt CHR data(graphics), or the + mapper number is set incorrectly(usually to 11). Use a utility to + fix the mapper number. + * Added support for the following UNIF boards(prefixes omitted): + - EKROM (and fixed the reference to "Gemfire" in the documentation). + - HKROM + * Added the ability to enable and disable individual RAM cheats. + * Fixed some problems with the cheat search code(the NES' internal + RAM was being searched differently than any external RAM, which + was being search incorrectly). + +0.71 +---- + + * Fixed a 6502 emulation bug that was causing some Koei games + (ex: Nobunaga's Ambition, Genghis Khan) to not work. + * Extensive PPU/CPU timing adjustments. + * Fixed support for iNES mapper 40. + * Added support for the following UNIF boards(prefixes omitted): + - ETROM + - ELROM + - EWROM + * Fixed a few bugs in the UNIF code. + * Added support for loading and saving cheat files and an interface + to search for/add/delete/list cheats(no interface yet on Linux/DOS). + * Fixed a few minor bugs in the Windows DX code. + * Command line options to control the number of sound fragments + and the fragment size have been added(Linux). + +0.70 +---- + + * Adjusted PPU/CPU timing. + * Removed(until I understand the problem) a hack to get one of the + games in the Caltron 6-in-1 to work. + * Fixed an MMC3 IRQ emulation bug("Project Q" works better now). + * Fixed a problem/misunderstanding regarding the upper scanline. + It can now be displayed again. + * More accurate sprite hit emulation(fixes the title screen of + "Ultimate Stuntman"). + * VRAM bank switching for iNES mapper 4 is now possible(and enabled + for all mapper 4 games without CHR ROM). Fixes "Tenchi o Kurau 2". + * Added support for the Famicom's four-player adapter and the ability + to enable it(it is disabled by default to prevent compatibility + problems). + * Added an option(under miscellaneous configuration) to automatically + open the "File Open" dialog box when FCE Ultra is started. + * Sound sampling rate is now configurable. + * Fixed some bugs in the DirectSound code. + * Joystick button configuration is a little more user friendly(and + stable, hopefully) (Linux). + +0.62 +---- + + * Added support for the Famicom Disk System's extra sound channel. + * Updated the version of Tatsuyuki Satoh's OPL2 emulator used in + FCE Ultra from .36f to .37a. The sound quality in "Lagrange Point" + seems to have improved. + * Added support for iNES mapper 242(used by "Wai Xing Zhan Shi"). + * Fixed a network play bug that could cause desynchronizations + if more than one network play session occured since FCE Ultra + was started. This bug only showed up on the Windows port, though. + * Increased the volume of the noise and triangle sound channels. + * Fixed a save state loading bug. + * Fixed a small memory leak that was being caused by the VRC7 + state loading code. + * Fixed a bug that could cause FCE Ultra to crash if a virtual disk + was being read and the user ejected the virtual disk. + * Various minor bug fixes/code cleanups. + * NTSC color "emulation" can now be enabled again(the code to + enable it was broken in the last version). (Linux) + +0.61 +---- + + * Speed optimizations in sprite rendering code. + * Screen snapshots are now saved in the PNG format instead of the PCX + format. + * Fixed Game Genie emulation(it wasn't working in the last release). + Also added support for Game Genie emulation to the UNIF code. + * Rewrote command line option parsing code. + * Fixed a problem(if FCE Ultra was configured to connect to a remote + host and the remote host was given as an IP address, and the IP + address couldn't be reverse resolved, which is commonly the case + on home LANs, the connection attempt would fail) in the network + play code. I had misinterpreted the Winsock API documentation + when I wrote the code. (Windows) + +0.60 +---- + + * Various speed optimizations. + * Sound is no longer messed up when a JAM/KIL opcode is emulated. + * Fixed an overflow bug that occured when $4014 was written to + during certain(rare) conditions. + * Fixed a few save state bugs. + * Fixed a MMC1 CHR bank switching bug. + * Added emulation of the MMC5's WRAM write-enable/disable registers. + * Fixed a sound frame IRQ emulation bug. "Qix" works now. + * Added UNIF support. Some of the board emulation is still a bit + buggy, though. Look at the documentation for a list of supported + boards. + * Updated the "Palette Notes" section of the documentation. Also + fixed a few other problems with the documentation. + * Added support for loading files in the PKZIP and gzip + compressed file formats via zlib. + * Added the ability to configure the first scanline and the last + scanline to draw to the screen. Enabling PAL emulation no longer + will cause all 239 scanlines to be displayed, though an option + to override these settings for when PAL emulation is enabled may + be in the next version. + * Fixed a bug that would cause the emulated D-pad of virtual gamepads + emulated through the keyboard to be duplicated through "higher" + virtual gamepads(gamepad 1 would affect 2,3,4; gamepad 2 would + affect 3,4; etc.). (Windows) + +0.55 +---- + * Rewrote window resizing code. The window will now resize itself + to a multiple of the NES' screen dimensions nearest to the user + selected dimensions. (Windows) + * Added an option to use buttons instead of axes on physical joysticks + for the emulated D-Pad. This is useful for some digital joysticks. (Windows) + * Fixed a bug that would cause FCE Ultra to crash if sound were + disabled during emulation. (Windows) + * Added the ability to "fast forward" emulation. + * Added an option to allow more than 8 sprites per scanline to be + displayed. + * Added an option to save all extra non-volatile game data + (such as battery-backed RAM) in a directory under FCE Ultra's + base directory(as opposed to the directory the game is located in). + * Added an option to allow the emulator to change to a full screen + video mode once a new game is loaded. (Windows) + * Rewrote pieces of DirectInput joystick handling code. Hopefully + it should increase compatibility. (Windows) + * Added the ability to automatically obtain button numbers when + configuring joysticks, by pressing buttons on the joystick. + * Added the ability to close the current game(decreases CPU usage). (windows) + * Increased the speed of various function calls by passing + arguments to functions through registers instead of through the + stack. + * Added emulation of the MMC5's raw PCM register. + * Added the ability to save/load save states while network play + is occuring. + * Having PAL emulation enabled will no longer override the + NTSC/PAL settings in NSF headers. + * Fixed a bug that got into the .54 release. Extraneous data was + being returned on reads from $2002, which caused problems + with some games(such as "Choujin Sentai Jetman"). + +0.54 +---- + * Fixed a bug that would cause a wrong battery-backed WRAM file + name to be produced if FCE Ultra was passed a file name without + any directory component(such as "fceu SuperBlah.nes"). + * Fixed an iNES mapper 118 emulation bug that got into the code + in a recent code cleanup. "Armadillo" is playable again. + * Fixed a typo(and bug) in the MMC5 emulation code. + * Data returned from emulated reads to "unmapped" areas or + memory locations where bits are undefined should now be correct. + * Fixed emulation of the sprite memory transfer register $4014. + It now takes into account the last value written to $2003 and + starts the transfer to that location in sprite memory(like on + a real NES). + * Added a video configuration dialog box. (Windows) + * Added the ability to configure a custom video mode. Aspects + that are configurable include width, height, bits per pixel, + and size transforming(stretching and scaling). (Windows) + +0.53 +---- + + * Fixed a bug with joysticks that occured on systems with multiple + joysticks. (Windows) + * Added support for iNES mappers 77 and 92(thanks to LULU for the code for both). + * Added partial(timer is non-configurable) support for iNES mapper 105. + * Changed save state format again. Save states made with previous + versions should still be compatible, though this may change in + future versions. + * Small optimization to sprite emulation code. + * Rewrote color-deemphasis code to use integer math instead of + floating-point math. + * Rewrote and restructured input code. (Linux) + * Added command line option "-f8bit" to force 8-bit sound. (Linux) + * Rewrote and restructured input code. Among other new features, + keyboard keys are now somewhat configurable. (Windows) + * Writes to $4003/$4007 will now reset the emulated square wave + duty cycle generator. + * Added emulation of the Power Pad. + * Rewrote joystick device reading code to use the event-driven + interface. This should fix various problems regarding support + for joysticks with many buttons. (linux) + +0.52 +---- + + * Fixed a PCM emulation bug(digitized voices in "Ikari Warriors 2" + and "The Immortal", among others, work now). + * Fixed noise channel's LSFR update frequencies(hopefully). + * Various minor bug fixes. + +0.51 +---- + + * Added support for iNES mappers 86 and 89. + * Reduced byte size of the NSF player's background. + * Adjusted CPU/PPU timing. + * Fixed sound channel frequency calculations for when PAL emulation is enabled. + * Rewrote large pieces of the sound code and got rid of the sound queue. Sound quality should be slightly better now. + * Various minor bug fixes. + + Windows: + + * Fixed an FDS side reset bug when a new game is loaded. + * Screen width/depth/height changes while FCE Ultra is in windowed mode are handled now. + * Changed the configuration file format. + * Added a palette configuration dialog. + * Added the ability to load a custom NES palette. + * Added an option to double 16-bit sound volume. + * Added an option to force 8-bit sound. + * Added an option to use a secondary sound buffer(versus the primary). + * Added an option to wait for vertical blank if sound is disabled. + * Added an option to run while focus is lost. + +0.50 +---- + + * Many bug fixes. + * Sound code partially rewritten to improve quality(near-perfect + raw PCM now) and eliminate the need for a separate thread. + This created a small problem with network play, though, so read + the network play notes section. Also, synchronizing to + vertical blank has been removed. + * Rewrote other pieces of sound code. No more "buzzing" in MegaMan 2, + Codemasters games' intros, etc. + * Added support for the NES Zapper and the VS Unisystem's light + gun. Be sure to read "Light Gun Notes". + * Changed save state format. Save states should now be much + smaller for most games. Most(not all) save states created with + an older version should work. + * Added support for VS Duck Hunt and VS Hogan's Alley. + diff --git a/src/boards/01-222.c b/src/boards/01-222.c new file mode 100644 index 0000000..64d2c96 --- /dev/null +++ b/src/boards/01-222.c @@ -0,0 +1,109 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * TXC mappers, originally much complex banksitching + * + * 01-22111-000 (05-00002-010) (132, 22211) - MGC-001 Qi Wang + * 01-22110-000 (52S ) - MGC-002 2-in-1 Gun + * 01-22111-100 (02-00002-010) (173 ) - MGC-008 Mahjong Block + * (079 ) - MGC-012 Poke Block + * 01-22110-200 (05-00002-010) (036 ) - MGC-014 Strike Wolf + * 01-22000-400 (05-00002-010) (036 ) - MGC-015 Policeman + * 01-22017-000 (05-PT017-080) (189 ) - MGC-017 Thunder Warrior + * 01-11160-000 (04-02310-000) ( , 11160) - MGC-023 6-in-1 + * 01-22270-000 (05-00002-010) (132, 22211) - MGC-xxx Creatom + * 01-22200-400 (------------) (079 ) - ET.03 F-15 City War + * (172 ) - 1991 Du Ma Racing + * + */ + +#include "mapinc.h" + +static uint8 reg[4], cmd, is172, is173; +static SFORMAT StateRegs[] = +{ + { reg, 4, "REGS" }, + { &cmd, 1, "CMD" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, (reg[2] >> 2) & 1); + if (is172) + setchr8((((cmd ^ reg[2]) >> 3) & 2) | (((cmd ^ reg[2]) >> 5) & 1)); // 1991 DU MA Racing probably CHR bank sequence is WRONG, so it is possible to + // rearrange CHR banks for normal UNIF board and mapper 172 is unneccessary + else + setchr8(reg[2] & 3); +} + +static DECLFW(UNL22211WriteLo) { +// FCEU_printf("bs %04x %02x\n",A,V); + reg[A & 3] = V; +} + +static DECLFW(UNL22211WriteHi) { +// FCEU_printf("bs %04x %02x\n",A,V); + cmd = V; + Sync(); +} + +static DECLFR(UNL22211ReadLo) { + return (reg[1] ^ reg[2]) | (is173 ? 0x01 : 0x40); +// if(reg[3]) +// return reg[2]; +// else +// return X.DB; +} + +static void UNL22211Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x4100, UNL22211ReadLo); + SetWriteHandler(0x4100, 0x4103, UNL22211WriteLo); + SetWriteHandler(0x8000, 0xFFFF, UNL22211WriteHi); +} + +static void StateRestore(int version) { + Sync(); +} + +void UNL22211_Init(CartInfo *info) { + is172 = 0; + is173 = 0; + info->Power = UNL22211Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +void Mapper172_Init(CartInfo *info) { + is172 = 1; + is173 = 0; + info->Power = UNL22211Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +void Mapper173_Init(CartInfo *info) { + is172 = 0; + is173 = 1; + info->Power = UNL22211Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + diff --git a/src/boards/09-034a.c b/src/boards/09-034a.c new file mode 100644 index 0000000..1609a81 --- /dev/null +++ b/src/boards/09-034a.c @@ -0,0 +1,97 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversions + * + * Super Mario Bros 2j (Alt Full) is a BAD incomplete dump, should be mapper 43 + * + * Both Voleyball and Zanac by Whirlind Manu shares the same PCB, but with + * some differences: Voleyball has 8K CHR ROM and 8K ROM at 6000K, Zanac + * have 8K CHR RAM and banked 16K ROM mapper at 6000 as two 8K banks. +* + * Super Mario Bros 2j (Alt Small) uses additionally IRQ timer to drive framerate + * + * PCB for this mapper is "09-034A" + */ + +#include "mapinc.h" + +static uint8 prg; +static uint32 IRQCount, IRQa; + +static SFORMAT StateRegs[] = +{ + { &IRQCount, 4, "IRQC" }, + { &IRQa, 4, "IRQA" }, + { &prg, 1, "PRG" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(1, 0x6000, prg); + setprg32(0x8000, 0); + setchr8(0); +} + +static DECLFW(UNLSMB2JWrite1) { + prg = V & 1; + Sync(); +} + +static DECLFW(UNLSMB2JWrite2) { + IRQa = V & 1; + IRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); +} + +static DECLFR(UNLSMB2JRead) { + return 0xFF; +} + +static void UNLSMB2JPower(void) { + prg = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetReadHandler(0x4042, 0x4055, UNLSMB2JRead); + SetWriteHandler(0x4068, 0x4068, UNLSMB2JWrite2); + SetWriteHandler(0x4027, 0x4027, UNLSMB2JWrite1); +} + +static void FP_FASTAPASS(1) UNLSMB2JIRQHook(int a) { + if (IRQa) + { + if (IRQCount < 5750) // completely by guess + IRQCount += a; + else { + IRQa = 0; + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLSMB2J_Init(CartInfo *info) { + info->Power = UNLSMB2JPower; + MapIRQHook = UNLSMB2JIRQHook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/103.c b/src/boards/103.c new file mode 100644 index 0000000..fc56621 --- /dev/null +++ b/src/boards/103.c @@ -0,0 +1,115 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg0, reg1, reg2; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { ®0, 1, "REG0" }, + { ®1, 1, "REG1" }, + { ®2, 1, "REG2" }, + { 0 } +}; + +static void Sync(void) { + setchr8(0); + setprg8(0x8000, 0xc); + setprg8(0xe000, 0xf); + if (reg2 & 0x10) { + setprg8(0x6000, reg0); + setprg8(0xa000, 0xd); + setprg8(0xc000, 0xe); + } else { + setprg8r(0x10, 0x6000, 0); + setprg4(0xa000, (0xd << 1)); + setprg2(0xb000, (0xd << 2) + 2); + setprg2r(0x10, 0xb800, 4); + setprg2r(0x10, 0xc000, 5); + setprg2r(0x10, 0xc800, 6); + setprg2r(0x10, 0xd000, 7); + setprg2(0xd800, (0xe << 2) + 3); + } + setmirror(reg1 ^ 1); +} + +static DECLFW(M103RamWrite0) { + WRAM[A & 0x1FFF] = V; +} + +static DECLFW(M103RamWrite1) { + WRAM[0x2000 + ((A - 0xB800) & 0x1FFF)] = V; +} + +static DECLFW(M103Write0) { + reg0 = V & 0xf; + Sync(); +} + +static DECLFW(M103Write1) { + reg1 = (V >> 3) & 1; + Sync(); +} + +static DECLFW(M103Write2) { + reg2 = V; + Sync(); +} + +static void M103Power(void) { + reg0 = reg1 = 0; reg2 = 0; + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, M103RamWrite0); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0xB800, 0xD7FF, M103RamWrite1); + SetWriteHandler(0x8000, 0x8FFF, M103Write0); + SetWriteHandler(0xE000, 0xEFFF, M103Write1); + SetWriteHandler(0xF000, 0xFFFF, M103Write2); +} + +static void M103Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper103_Init(CartInfo *info) { + info->Power = M103Power; + info->Close = M103Close; + GameStateRestore = StateRestore; + + WRAMSIZE = 16384; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/106.c b/src/boards/106.c new file mode 100644 index 0000000..3ecdf09 --- /dev/null +++ b/src/boards/106.c @@ -0,0 +1,108 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[16], IRQa; +static uint32 IRQCount; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { &IRQa, 1, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { reg, 16, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setchr1(0x0000, reg[0] & 0xfe); + setchr1(0x0400, reg[1] | 1); + setchr1(0x0800, reg[2] & 0xfe); + setchr1(0x0c00, reg[3] | 1); + setchr1(0x1000, reg[4]); + setchr1(0x1400, reg[5]); + setchr1(0x1800, reg[6]); + setchr1(0x1c00, reg[7]); + setprg8r(0x10, 0x6000, 0); + setprg8(0x8000, (reg[0x8] & 0xf) | 0x10); + setprg8(0xA000, (reg[0x9] & 0x1f)); + setprg8(0xC000, (reg[0xa] & 0x1f)); + setprg8(0xE000, (reg[0xb] & 0xf) | 0x10); + setmirror((reg[0xc] & 1) ^ 1); +} + +static DECLFW(M106Write) { + A &= 0xF; + switch (A) { + case 0xD: IRQa = 0; IRQCount = 0; X6502_IRQEnd(FCEU_IQEXT); break; + case 0xE: IRQCount = (IRQCount & 0xFF00) | V; break; + case 0xF: IRQCount = (IRQCount & 0x00FF) | (V << 8); IRQa = 1; break; + default: reg[A] = V; Sync(); break; + } +} + +static void M106Power(void) { + reg[8] = reg[9] = reg[0xa] = reg[0xb] = -1; + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, M106Write); +} + +static void M106Reset(void) { +} + +static void M106Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +void FP_FASTAPASS(1) M106CpuHook(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount > 0x10000) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper106_Init(CartInfo *info) { + info->Reset = M106Reset; + info->Power = M106Power; + info->Close = M106Close; + MapIRQHook = M106CpuHook; + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/108.c b/src/boards/108.c new file mode 100644 index 0000000..a8eda01 --- /dev/null +++ b/src/boards/108.c @@ -0,0 +1,64 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + * Meikyuu Jin Dababa + * Bubble Bobble Kaiser + * + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REG" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, reg); + setprg32(0x8000, ~0); + setchr8(0); +} + +static DECLFW(M108Write) { + reg = V; + Sync(); +} + +static void M108Power(void) { + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0x8FFF, M108Write); // regular 108 + SetWriteHandler(0xF000, 0xFFFF, M108Write); // simplified Kaiser BB Hack +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper108_Init(CartInfo *info) { + info->Power = M108Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/112.c b/src/boards/112.c new file mode 100644 index 0000000..6c184b1 --- /dev/null +++ b/src/boards/112.c @@ -0,0 +1,89 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * NTDEC, ASDER games + * + */ + +#include "mapinc.h" + +static uint8 reg[8]; +static uint8 mirror, cmd, bank; +static uint8 *WRAM = NULL; + +static SFORMAT StateRegs[] = +{ + { &cmd, 1, "CMD" }, + { &mirror, 1, "MIRR" }, + { &bank, 1, "BANK" }, + { 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, ((bank & 0x10) << 4) | reg[4]); + setchr1(0x1400, ((bank & 0x20) << 3) | reg[5]); + setchr1(0x1800, ((bank & 0x40) << 2) | reg[6]); + setchr1(0x1C00, ((bank & 0x80) << 1) | 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; + case 0xc000: bank = V; Sync(); break; + } +} + +static void M112Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void M112Power(void) { + bank = 0; + setprg16(0xC000, ~0); + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M112Write); + SetWriteHandler(0x4020, 0x5FFF, 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/src/boards/116.c b/src/boards/116.c new file mode 100644 index 0000000..b3efed8 --- /dev/null +++ b/src/boards/116.c @@ -0,0 +1,324 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * SL12 Protected 3-in-1 mapper hardware (VRC2, MMC3, MMC1) + * the same as 603-5052 board (TODO: add reading registers, merge) + * SL1632 2-in-1 protected board, similar to SL12 (TODO: find difference) + * + * Known PCB: + * + * Garou Densetsu Special (G0904.PCB, Huang-1, GAL dip: W conf.) + * Kart Fighter (008, Huang-1, GAL dip: W conf.) + * Somari (008, C5052-13, GAL dip: P conf., GK2-P/GK2-V maskroms) + * Somari (008, Huang-1, GAL dip: W conf., GK1-P/GK1-V maskroms) + * AV Mei Shao Nv Zhan Shi (aka AV Pretty Girl Fighting) (SL-12 PCB, Hunag-1, GAL dip: unk conf. SL-11A/SL-11B maskroms) + * Samurai Spirits (Full version) (Huang-1, GAL dip: unk conf. GS-2A/GS-4A maskroms) + * Contra Fighter (603-5052 PCB, C5052-3, GAL dip: unk conf. SC603-A/SCB603-B maskroms) + * + */ + +#include "mapinc.h" + +static uint8 mode; +static uint8 vrc2_chr[8], vrc2_prg[2], vrc2_mirr; +static uint8 mmc3_regs[10], mmc3_ctrl, mmc3_mirr; +static uint8 IRQCount, IRQLatch, IRQa; +static uint8 IRQReload; +static uint8 mmc1_regs[4], mmc1_buffer, mmc1_shift; + +static SFORMAT StateRegs[] = +{ + { &mode, 1, "MODE" }, + { vrc2_chr, 8, "VRCC" }, + { vrc2_prg, 2, "VRCP" }, + { &vrc2_mirr, 1, "VRCM" }, + { mmc3_regs, 10, "M3RG" }, + { &mmc3_ctrl, 1, "M3CT" }, + { &mmc3_mirr, 1, "M3MR" }, + { &IRQReload, 1, "IRQR" }, + { &IRQCount, 1, "IRQC" }, + { &IRQLatch, 1, "IRQL" }, + { &IRQa, 1, "IRQA" }, + { mmc1_regs, 4, "M1RG" }, + { &mmc1_buffer, 1, "M1BF" }, + { &mmc1_shift, 1, "M1MR" }, + { 0 } +}; + +static void SyncPRG(void) { + switch (mode & 3) { + case 0: + setprg8(0x8000, vrc2_prg[0]); + setprg8(0xA000, vrc2_prg[1]); + setprg8(0xC000, ~1); + setprg8(0xE000, ~0); + break; + case 1: + { + uint32 swap = (mmc3_ctrl >> 5) & 2; + setprg8(0x8000, mmc3_regs[6 + swap]); + setprg8(0xA000, mmc3_regs[7]); + setprg8(0xC000, mmc3_regs[6 + (swap ^ 2)]); + setprg8(0xE000, mmc3_regs[9]); + break; + } + case 2: + case 3: + { + uint8 bank = mmc1_regs[3] & 0xF; + if (mmc1_regs[0] & 8) { + if (mmc1_regs[0] & 4) { + setprg16(0x8000, bank); + setprg16(0xC000, 0x0F); + } else { + setprg16(0x8000, 0); + setprg16(0xC000, bank); + } + } else + setprg32(0x8000, bank >> 1); + break; + } + } +} + +static void SyncCHR(void) { + uint32 base = (mode & 4) << 6; + switch (mode & 3) { + case 0: + setchr1(0x0000, base | vrc2_chr[0]); + setchr1(0x0400, base | vrc2_chr[1]); + setchr1(0x0800, base | vrc2_chr[2]); + setchr1(0x0c00, base | vrc2_chr[3]); + setchr1(0x1000, base | vrc2_chr[4]); + setchr1(0x1400, base | vrc2_chr[5]); + setchr1(0x1800, base | vrc2_chr[6]); + setchr1(0x1c00, base | vrc2_chr[7]); + break; + case 1: { + uint32 swap = (mmc3_ctrl & 0x80) << 5; + setchr1(0x0000 ^ swap, base | ((mmc3_regs[0]) & 0xFE)); + setchr1(0x0400 ^ swap, base | (mmc3_regs[0] | 1)); + setchr1(0x0800 ^ swap, base | ((mmc3_regs[1]) & 0xFE)); + setchr1(0x0c00 ^ swap, base | (mmc3_regs[1] | 1)); + setchr1(0x1000 ^ swap, base | mmc3_regs[2]); + setchr1(0x1400 ^ swap, base | mmc3_regs[3]); + setchr1(0x1800 ^ swap, base | mmc3_regs[4]); + setchr1(0x1c00 ^ swap, base | mmc3_regs[5]); + break; + } + case 2: + case 3: + if (mmc1_regs[0] & 0x10) { + setchr4(0x0000, mmc1_regs[1]); + setchr4(0x1000, mmc1_regs[2]); + } else + setchr8(mmc1_regs[1] >> 1); + break; + } +} + +static void SyncMIR(void) { + switch (mode & 3) { + case 0: { + setmirror((vrc2_mirr & 1) ^ 1); + break; + } + case 1: { + setmirror((mmc3_mirr & 1) ^ 1); + break; + } + case 2: + case 3: { + switch (mmc1_regs[0] & 3) { + case 0: setmirror(MI_0); break; + case 1: setmirror(MI_1); break; + case 2: setmirror(MI_V); break; + case 3: setmirror(MI_H); break; + } + break; + } + } +} + +static void Sync(void) { + SyncPRG(); + SyncCHR(); + SyncMIR(); +} + +static DECLFW(UNLSL12ModeWrite) { +// FCEU_printf("%04X:%02X\n",A,V); + if ((A & 0x4100) == 0x4100) { + mode = V; + if (A & 1) { // hacky hacky, there are two configuration modes on SOMARI HUANG-1 PCBs + // Solder pads with P1/P2 shorted called SOMARI P, + // Solder pads with W1/W2 shorted called SOMARI W + // Both identical 3-in-1 but W wanted MMC1 registers + // to be reset when switch to MMC1 mode P one - doesn't + // There is issue with W version of Somari at starting copyrights + mmc1_regs[0] = 0xc; + mmc1_regs[3] = 0; + mmc1_buffer = 0; + mmc1_shift = 0; + } + Sync(); + } +} + +static DECLFW(UNLSL12Write) { +// FCEU_printf("%04X:%02X\n",A,V); + switch (mode & 3) { + case 0: { + if ((A >= 0xB000) && (A <= 0xE003)) { + int32 ind = ((((A & 2) | (A >> 10)) >> 1) + 2) & 7; + int32 sar = ((A & 1) << 2); + vrc2_chr[ind] = (vrc2_chr[ind] & (0xF0 >> sar)) | ((V & 0x0F) << sar); + SyncCHR(); + } else + switch (A & 0xF000) { + case 0x8000: vrc2_prg[0] = V; SyncPRG(); break; + case 0xA000: vrc2_prg[1] = V; SyncPRG(); break; + case 0x9000: vrc2_mirr = V; SyncMIR(); break; + } + break; + } + case 1: { + switch (A & 0xE001) { + case 0x8000: { + uint8 old_ctrl = mmc3_ctrl; + mmc3_ctrl = V; + if ((old_ctrl & 0x40) != (mmc3_ctrl & 0x40)) + SyncPRG(); + if ((old_ctrl & 0x80) != (mmc3_ctrl & 0x80)) + SyncCHR(); + break; + } + case 0x8001: + mmc3_regs[mmc3_ctrl & 7] = V; + if ((mmc3_ctrl & 7) < 6) + SyncCHR(); + else + SyncPRG(); + break; + case 0xA000: + mmc3_mirr = V; + SyncMIR(); + 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; + } + break; + } + case 2: + case 3: { + if (V & 0x80) { + mmc1_regs[0] |= 0xc; + mmc1_buffer = mmc1_shift = 0; + SyncPRG(); + } else { + uint8 n = (A >> 13) - 4; + mmc1_buffer |= (V & 1) << (mmc1_shift++); + if (mmc1_shift == 5) { + mmc1_regs[n] = mmc1_buffer; + mmc1_buffer = mmc1_shift = 0; + switch (n) { + case 0: SyncMIR(); + case 2: SyncCHR(); + case 3: + case 1: SyncPRG(); + } + } + } + break; + } + } +} + +static void UNLSL12HBIRQ(void) { + if ((mode & 3) == 1) { + int32 count = IRQCount; + 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 UNLSL12Power(void) { + mode = 0; + vrc2_chr[0] = ~0; + vrc2_chr[1] = ~0; + vrc2_chr[2] = ~0; + vrc2_chr[3] = ~0; // W conf. of Somari wanted CHR3 has to be set to BB bank (or similar), but doesn't do that directly + vrc2_chr[4] = 4; + vrc2_chr[5] = 5; + vrc2_chr[6] = 6; + vrc2_chr[7] = 7; + vrc2_prg[0] = 0; + vrc2_prg[1] = 1; + vrc2_mirr = 0; + mmc3_regs[0] = 0; + mmc3_regs[1] = 2; + mmc3_regs[2] = 4; + mmc3_regs[3] = 5; + mmc3_regs[4] = 6; + mmc3_regs[5] = 7; + mmc3_regs[6] = ~3; + mmc3_regs[7] = ~2; + mmc3_regs[8] = ~1; + mmc3_regs[9] = ~0; + mmc3_ctrl = mmc3_mirr = IRQCount = IRQLatch = IRQa = 0; + mmc1_regs[0] = 0xc; + mmc1_regs[1] = 0; + mmc1_regs[2] = 0; + mmc1_regs[3] = 0; + mmc1_buffer = 0; + mmc1_shift = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0x7FFF, UNLSL12ModeWrite); + SetWriteHandler(0x8000, 0xFFFF, UNLSL12Write); +} + +void UNLSL12_Init(CartInfo *info) { + info->Power = UNLSL12Power; + GameHBIRQHook = UNLSL12HBIRQ; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/117.c b/src/boards/117.c new file mode 100644 index 0000000..3a50ce2 --- /dev/null +++ b/src/boards/117.c @@ -0,0 +1,91 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 prgreg[4], chrreg[8], mirror; +static uint8 IRQa, IRQCount, IRQLatch; + +static SFORMAT StateRegs[] = +{ + { &IRQa, 1, "IRQA" }, + { &IRQCount, 1, "IRQC" }, + { &IRQLatch, 1, "IRQL" }, + { prgreg, 4, "PREG" }, + { chrreg, 8, "CREG" }, + { &mirror, 1, "MREG" }, + { 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]); + setmirror(mirror ^ 1); +} + +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; + case 0xd000: mirror = V & 1; + } +} + +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/src/boards/120.c b/src/boards/120.c new file mode 100644 index 0000000..eabe47d --- /dev/null +++ b/src/boards/120.c @@ -0,0 +1,62 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REG" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, reg); + setprg32(0x8000, 2); + setchr8(0); +} + +static DECLFW(M120Write) { + if (A == 0x41FF) { + reg = V & 7; + Sync(); + } +} + +static void M120Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0x5FFF, M120Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper120_Init(CartInfo *info) { + info->Power = M120Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/121.c b/src/boards/121.c new file mode 100644 index 0000000..aa4e5c2 --- /dev/null +++ b/src/boards/121.c @@ -0,0 +1,129 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007-2008 Mad Dumper, 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Panda prince pirate. + * MK4, MK6, A9711/A9713 board + * 6035052 seems to be the same too, but with prot array in reverse + * A9746 seems to be the same too, check + * 187 seems to be the same too, check (A98402 board) + * + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void Sync() { + switch (EXPREGS[5] & 0x3F) { + case 0x20: EXPREGS[7] = 1; EXPREGS[0] = EXPREGS[6]; break; + case 0x29: EXPREGS[7] = 1; EXPREGS[0] = EXPREGS[6]; break; + case 0x26: EXPREGS[7] = 0; EXPREGS[0] = EXPREGS[6]; break; + case 0x2B: EXPREGS[7] = 1; EXPREGS[0] = EXPREGS[6]; break; + case 0x2C: EXPREGS[7] = 1; if (EXPREGS[6]) EXPREGS[0] = EXPREGS[6]; break; + case 0x3C: + case 0x3F: EXPREGS[7] = 1; EXPREGS[0] = EXPREGS[6]; break; + case 0x28: EXPREGS[7] = 0; EXPREGS[1] = EXPREGS[6]; break; + case 0x2A: EXPREGS[7] = 0; EXPREGS[2] = EXPREGS[6]; break; + case 0x2F: break; + default: EXPREGS[5] = 0; break; + } +} + +static void M121CW(uint32 A, uint8 V) { + if (PRGsize[0] == CHRsize[0]) { // A9713 multigame extension hack! + setchr1(A, V | ((EXPREGS[3] & 0x80) << 1)); + } else { + if ((A & 0x1000) == ((MMC3_cmd & 0x80) << 5)) + setchr1(A, V | 0x100); + else + setchr1(A, V); + } +} + +static void M121PW(uint32 A, uint8 V) { + if (EXPREGS[5] & 0x3F) { +// FCEU_printf("prot banks: %02x %02x %02x %02x\n",V,EXPREGS[2],EXPREGS[1],EXPREGS[0]); + setprg8(A, (V & 0x1F) | ((EXPREGS[3] & 0x80) >> 2)); + setprg8(0xE000, (EXPREGS[0]) | ((EXPREGS[3] & 0x80) >> 2)); + setprg8(0xC000, (EXPREGS[1]) | ((EXPREGS[3] & 0x80) >> 2)); + setprg8(0xA000, (EXPREGS[2]) | ((EXPREGS[3] & 0x80) >> 2)); + } else { +// FCEU_printf("gen banks: %04x %02x\n",A,V); + setprg8(A, (V & 0x1F) | ((EXPREGS[3] & 0x80) >> 2)); + } +} + +static DECLFW(M121Write) { +// FCEU_printf("write: %04x:%04x\n",A&0xE003,V); + switch (A & 0xE003) { + case 0x8000: +// EXPREGS[5] = 0; +// FCEU_printf("gen: %02x\n",V); + MMC3_CMDWrite(A, V); + FixMMC3PRG(MMC3_cmd); + break; + case 0x8001: + EXPREGS[6] = ((V & 1) << 5) | ((V & 2) << 3) | ((V & 4) << 1) | ((V & 8) >> 1) | ((V & 0x10) >> 3) | ((V & 0x20) >> 5); +// FCEU_printf("bank: %02x (%02x)\n",V,EXPREGS[6]); + if (!EXPREGS[7]) Sync(); + MMC3_CMDWrite(A, V); + FixMMC3PRG(MMC3_cmd); + break; + case 0x8003: + EXPREGS[5] = V; +// EXPREGS[7] = 0; +// FCEU_printf("prot: %02x\n",EXPREGS[5]); + Sync(); + MMC3_CMDWrite(0x8000, V); + FixMMC3PRG(MMC3_cmd); + break; + } +} + +static uint8 prot_array[16] = { 0x83, 0x83, 0x42, 0x00 }; +static DECLFW(M121LoWrite) { + EXPREGS[4] = prot_array[V & 3]; // 0x100 bit in address seems to be switch arrays 0, 2, 2, 3 (Contra Fighter) + if ((A & 0x5180) == 0x5180) { // A9713 multigame extension + EXPREGS[3] = V; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } +// FCEU_printf("write: %04x:%04x\n",A,V); +} + +static DECLFR(M121Read) { +// FCEU_printf("read: %04x->\n",A,EXPREGS[0]); + return EXPREGS[4]; +} + +static void M121Power(void) { + EXPREGS[3] = 0x80; + EXPREGS[5] = 0; + GenMMC3Power(); + SetReadHandler(0x5000, 0x5FFF, M121Read); + SetWriteHandler(0x5000, 0x5FFF, M121LoWrite); + SetWriteHandler(0x8000, 0x9FFF, M121Write); +} + +void Mapper121_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 256, 8, 0); + pwrap = M121PW; + cwrap = M121CW; + info->Power = M121Power; + AddExState(EXPREGS, 8, 0, "EXPR"); +} diff --git a/src/boards/12in1.c b/src/boards/12in1.c new file mode 100644 index 0000000..add67cc --- /dev/null +++ b/src/boards/12in1.c @@ -0,0 +1,73 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * 7-in-1 Darkwing Duck, Snake, MagicBlock (PCB marked as "12 in 1") + * 12-in-1 1991 New Star Co. Ltd. + * + */ + +#include "mapinc.h" + +static uint8 prgchr[2], ctrl; +static SFORMAT StateRegs[] = +{ + { prgchr, 2, "REGS" }, + { &ctrl, 1, "CTRL" }, + { 0 } +}; + +static void Sync(void) { + uint8 bank = (ctrl & 3) << 3; + setchr4(0x0000, (prgchr[0] >> 3) | (bank << 2)); + setchr4(0x1000, (prgchr[1] >> 3) | (bank << 2)); + if (ctrl & 8) { + setprg16(0x8000, bank | (prgchr[0] & 6) | 0); // actually, both 0 and 1 registers used, but they will switch each PA12 transition + setprg16(0xc000, bank | (prgchr[0] & 6) | 1); // if bits are different for both registers, so they must be programmed strongly the same! + } else { + setprg16(0x8000, bank | (prgchr[0] & 7)); + setprg16(0xc000, bank | 7 ); + } + setmirror(((ctrl & 4) >> 2) ^ 1); +} + +static DECLFW(BMC12IN1Write) { + switch (A & 0xE000) { + case 0xA000: prgchr[0] = V; Sync(); break; + case 0xC000: prgchr[1] = V; Sync(); break; + case 0xE000: ctrl = V & 0x0F; Sync(); break; + } +} + +static void BMC12IN1Power(void) { + prgchr[0] = prgchr[1] = ctrl = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, BMC12IN1Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void BMC12IN1_Init(CartInfo *info) { + info->Power = BMC12IN1Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + diff --git a/src/boards/15.c b/src/boards/15.c new file mode 100644 index 0000000..4aee608 --- /dev/null +++ b/src/boards/15.c @@ -0,0 +1,109 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" + +static uint16 latchea; +static uint8 latched; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; +static SFORMAT StateRegs[] = +{ + { &latchea, 2, "AREG" }, + { &latched, 1, "DREG" }, + { 0 } +}; + +static void Sync(void) { + int i; + setmirror(((latched >> 6) & 1) ^ 1); + switch (latchea) { + case 0x8000: + for (i = 0; i < 4; i++) + setprg8(0x8000 + (i << 13), (((latched & 0x7F) << 1) + i) ^ (latched >> 7)); + break; + case 0x8002: + for (i = 0; i < 4; i++) + setprg8(0x8000 + (i << 13), ((latched & 0x7F) << 1) + (latched >> 7)); + break; + case 0x8001: + case 0x8003: + for (i = 0; i < 4; i++) { + unsigned int b; + b = latched & 0x7F; + if (i >= 2 && !(latchea & 0x2)) + b = 0x7F; + setprg8(0x8000 + (i << 13), (i & 1) + ((b << 1) ^ (latched >> 7))); + } + break; + } +} + +static DECLFW(M15Write) { + latchea = A; + latched = V; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +static void M15Power(void) { + latchea = 0x8000; + latched = 0; + setchr8(0); + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, M15Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); + Sync(); +} + +static void M15Reset(void) { + latchea = 0x8000; + latched = 0; + Sync(); +} + +static void M15Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +void Mapper15_Init(CartInfo *info) { + info->Power = M15Power; + info->Reset = M15Reset; + info->Close = M15Close; + GameStateRestore = StateRestore; + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + AddExState(&StateRegs, ~0, 0, 0); +} + diff --git a/src/boards/151.c b/src/boards/151.c new file mode 100644 index 0000000..2d9335f --- /dev/null +++ b/src/boards/151.c @@ -0,0 +1,59 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 regs[8]; + +static SFORMAT StateRegs[] = +{ + { regs, 8, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, regs[0]); + setprg8(0xA000, regs[2]); + setprg8(0xC000, regs[4]); + setprg8(0xE000, ~0); + setchr4(0x0000, regs[6]); + setchr4(0x1000, regs[7]); +} + +static DECLFW(M151Write) { + regs[(A >> 12) & 7] = V; + Sync(); +} + +static void M151Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M151Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper151_Init(CartInfo *info) { + info->Power = M151Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/156.c b/src/boards/156.c new file mode 100644 index 0000000..a484299 --- /dev/null +++ b/src/boards/156.c @@ -0,0 +1,119 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * DIS23C01 DAOU ROM CONTROLLER, Korea + * Metal Force (K) + * Buzz and Waldog (K) + * General's Son (K) + * + */ + +#include "mapinc.h" + +static uint8 chrlo[8], chrhi[8], prg, mirr, mirrisused = 0; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { &prg, 1, "PREG" }, + { chrlo, 8, "CRGL" }, + { chrhi, 8, "CRGH" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + uint32 i; + for (i = 0; i < 8; i++) + setchr1(i << 10, chrlo[i] | (chrhi[i] << 8)); + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, prg); + setprg16(0xC000, ~0); + if (mirrisused) + setmirror(mirr ^ 1); + else + setmirror(MI_0); +} + +static DECLFW(M156Write) { + switch (A) { + case 0xC000: + case 0xC001: + case 0xC002: + case 0xC003: chrlo[A & 3] = V; Sync(); break; + case 0xC004: + case 0xC005: + case 0xC006: + case 0xC007: chrhi[A & 3] = V; Sync(); break; + case 0xC008: + case 0xC009: + case 0xC00A: + case 0xC00B: chrlo[4 + (A & 3)] = V; Sync(); break; + case 0xC00C: + case 0xC00D: + case 0xC00E: + case 0xC00F: chrhi[4 + (A & 3)] = V; Sync(); break; + case 0xC010: prg = V; Sync(); break; + case 0xC014: mirr = V; mirrisused = 1; Sync(); break; + } +} + +static void M156Reset(void) { + uint32 i; + for (i = 0; i < 8; i++) { + chrlo[i] = 0; + chrhi[i] = 0; + } + prg = 0; + mirr = 0; + mirrisused = 0; +} + +static void M156Power(void) { + M156Reset(); + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0xC000, 0xCFFF, M156Write); +} + +static void M156Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper156_Init(CartInfo *info) { + info->Reset = M156Reset; + info->Power = M156Power; + info->Close = M156Close; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/164.c b/src/boards/164.c new file mode 100644 index 0000000..c4d9fdd --- /dev/null +++ b/src/boards/164.c @@ -0,0 +1,526 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * It seems that 162/163/164 mappers are the same mapper with just different + * mapper modes enabled or disabled in software or hardware, need more nanjing + * carts + */ + +#include "mapinc.h" + +static uint8 laststrobe, trigger; +static uint8 reg[8]; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static writefunc pcmwrite; + +static void (*WSync)(void); + +static SFORMAT StateRegs[] = +{ + { &laststrobe, 1, "STB" }, + { &trigger, 1, "TRG" }, + { reg, 8, "REGS" }, + { 0 } +}; + +static int16 step_size[49] = { + 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, + 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, + 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, + 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, + 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552 +}; //49 items +static int32 step_adj[16] = { -1, -1, -1, -1, 2, 5, 7, 9, -1, -1, -1, -1, 2, 5, 7, 9 }; + +//decode stuff +static int32 jedi_table[16 * 49]; +static int32 acc = 0; //ADPCM accumulator, initial condition must be 0 +static int32 decstep = 0; //ADPCM decoding step, initial condition must be 0 + +static void jedi_table_init() { + int step, nib; + + for (step = 0; step < 49; step++) { + for (nib = 0; nib < 16; nib++) { + int value = (2 * (nib & 0x07) + 1) * step_size[step] / 8; + jedi_table[step * 16 + nib] = ((nib & 0x08) != 0) ? -value : value; + } + } +} + +static uint8 decode(uint8 code) { + acc += jedi_table[decstep + code]; + if ((acc & ~0x7ff) != 0) // acc is > 2047 + acc |= ~0xfff; + else acc &= 0xfff; + decstep += step_adj[code & 7] * 16; + if (decstep < 0) decstep = 0; + if (decstep > 48 * 16) decstep = 48 * 16; + return (acc >> 8) & 0xff; +} + +/* +const EEPROM_interface eeprom_interface. = +{ + 9, // address bits 9 + 8, // data bits 8 + "*110", // read 1 10 aaaaaaaaa + "*101", // write 1 01 aaaaaaaaa dddddddd + "*10000xxxxxxx", // lock 1 00 00xxxxxxx + "*10011xxxxxxx", // unlock 1 00 11xxxxxxx + 1, + 5 +}; + +static const EEPROM_interface *intf; + +static int serial_count = 0; +static u8 serial_buffer[SERIAL_BUFFER_LENGTH]; + +static int eeprom_data_bits; +static int eeprom_clock_count; +static int eeprom_read_address; +static u8 *eeprom_data; + +static int latch = 0; +static int locked = 1; +static int sending = 0; +static int reset_line = ASSERT_LINE; +static int clock_line = ASSERT_LINE; +static int reset_delay; + +void EEPROM_Init(u8 *data, u8 bit) +{ + eeprom_data = data; + if(bit == 8) + intf = &eeprom_interface_93C46_8; + else + intf = &eeprom_interface_93C46_16; +} + +u8 *EEPROM_GetData() +{ + return eeprom_data; +} + +static int EEPROM_command_match(const char *buf, const char *cmd, int len) +{ + if ( cmd == 0 ) return 0; + if ( len == 0 ) return 0; + + for (;len>0;) + { + char b = *buf; + char c = *cmd; + + if ((b==0) || (c==0)) + return (b==c); + + switch ( c ) + { + case '0': + case '1': + if (b != c) return 0; + case 'X': + case 'x': + buf++; + len--; + cmd++; + break; + + case '*': + c = cmd[1]; + switch( c ) + { + case '0': + case '1': + if (b == c) { cmd++; } + else { buf++; len--; } + break; + default: return 0; + } + } + } + return (*cmd==0); +} + +static void EEPROM_write(int bit) +{ + if (serial_count >= SERIAL_BUFFER_LENGTH-1) + { + return; + } + + serial_buffer[serial_count++] = (bit ? '1' : '0'); + serial_buffer[serial_count] = 0; + + if ( (serial_count > intf->address_bits) && + EEPROM_command_match((char*)serial_buffer,intf->cmd_read,(int)strlen((char*)serial_buffer)-intf->address_bits) ) + { + int i,address; + + address = 0; + for (i = serial_count-intf->address_bits;i < serial_count;i++) + { + address <<= 1; + if (serial_buffer[i] == '1') address |= 1; + } + if (intf->data_bits == 16) + eeprom_data_bits = (eeprom_data[2*address+0] << 8) + eeprom_data[2*address+1]; + else + eeprom_data_bits = eeprom_data[address]; + eeprom_read_address = address; + eeprom_clock_count = 0; + sending = 1; + serial_count = 0; + } + else if ( (serial_count > intf->address_bits) && + EEPROM_command_match((char*)serial_buffer,intf->cmd_erase,(int)strlen((char*)serial_buffer)-intf->address_bits) ) + { + int i,address; + + address = 0; + for (i = serial_count-intf->address_bits;i < serial_count;i++) + { + address <<= 1; + if (serial_buffer[i] == '1') address |= 1; + } + + if (locked == 0) + { + if (intf->data_bits == 16) + { + eeprom_data[2*address+0] = 0x00; + eeprom_data[2*address+1] = 0x00; + } + else + eeprom_data[address] = 0x00; + } + else + serial_count = 0; + } + else if ( (serial_count > (intf->address_bits + intf->data_bits)) && + EEPROM_command_match((char*)serial_buffer,intf->cmd_write,(int)strlen((char*)serial_buffer)-(intf->address_bits + intf->data_bits)) ) + { + int i,address,data; + + address = 0; + for (i = serial_count-intf->data_bits-intf->address_bits;i < (serial_count-intf->data_bits);i++) + { + address <<= 1; + if (serial_buffer[i] == '1') address |= 1; + } + data = 0; + for (i = serial_count-intf->data_bits;i < serial_count;i++) + { + data <<= 1; + if (serial_buffer[i] == '1') data |= 1; + } + if (locked == 0) + { + if (intf->data_bits == 16) + { + eeprom_data[2*address+0] = data >> 8; + eeprom_data[2*address+1] = data & 0xff; + } + else + eeprom_data[address] = data; + } + else + serial_count = 0; + } + else if ( EEPROM_command_match((char*)serial_buffer,intf->cmd_lock,(int)strlen((char*)serial_buffer)) ) + { + locked = 1; + serial_count = 0; + } + else if ( EEPROM_command_match((char*)serial_buffer,intf->cmd_unlock,(int)strlen((char*)serial_buffer)) ) + { + locked = 0; + serial_count = 0; + } +} + +static void EEPROM_reset() +{ + serial_count = 0; + sending = 0; + reset_delay = intf->reset_delay; +} + +void EEPROM_set_cs_line(int state) +{ + reset_line = state; + + if (reset_line != CLEAR_LINE) + EEPROM_reset(); +} + +void EEPROM_set_clock_line(int state) +{ + if (state == PULSE_LINE || (clock_line == CLEAR_LINE && state != CLEAR_LINE)) + { + if (reset_line == CLEAR_LINE) + { + if (sending) + { + if (eeprom_clock_count == intf->data_bits) + { + if(intf->enable_multi_read) + { + eeprom_read_address = (eeprom_read_address + 1) & ((1 << intf->address_bits) - 1); + if (intf->data_bits == 16) + eeprom_data_bits = (eeprom_data[2*eeprom_read_address+0] << 8) + eeprom_data[2*eeprom_read_address+1]; + else + eeprom_data_bits = eeprom_data[eeprom_read_address]; + eeprom_clock_count = 0; + } + else + { + sending = 0; + } + } + eeprom_data_bits = (eeprom_data_bits << 1) | 1; + eeprom_clock_count++; + } + else + EEPROM_write(latch); + } + } + + clock_line = state; +} + + +void EEPROM_write_bit(int bit) +{ + latch = bit; +} + +int EEPROM_read_bit(void) +{ + int res; + + if (sending) + res = (eeprom_data_bits >> intf->data_bits) & 1; + else + { + if (reset_delay > 0) + { + reset_delay--; + res = 0; + } + else + res = 1; + } + + return res; +} +*/ + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, (reg[0] << 4) | (reg[1] & 0xF)); + setchr8(0); +} + +static void StateRestore(int version) { + WSync(); +} + +static DECLFR(ReadLow) { + switch (A & 0x7700) { + case 0x5100: return reg[2] | reg[0] | reg[1] | reg[3] ^ 0xff; break; + case 0x5500: + if (trigger) + return reg[2] | reg[1]; // Lei Dian Huang Bi Ka Qiu Chuan Shuo (NJ046) may broke other games + else + return 0; + } + return 4; +} + +static void M163HB(void) { + if (reg[1] & 0x80) { + if (scanline == 239) { + setchr4(0x0000, 0); + setchr4(0x1000, 0); + } else if (scanline == 127) { + setchr4(0x0000, 1); + setchr4(0x1000, 1); + } +/* + if(scanline>=127) // Hu Lu Jin Gang (NJ039) (Ch) [!] don't like it + { + setchr4(0x0000,1); + setchr4(0x1000,1); + } + else + { + setchr4(0x0000,0); + setchr4(0x1000,0); + } +*/ + } +} + +static DECLFW(Write) { + switch (A & 0x7300) { + case 0x5100: reg[0] = V; WSync(); break; + case 0x5000: reg[1] = V; WSync(); break; + case 0x5300: reg[2] = V; break; + case 0x5200: reg[3] = V; WSync(); break; + } +} + +static void Power(void) { + memset(reg, 0, 8); + reg[1] = 0xFF; + SetWriteHandler(0x5000, 0x5FFF, Write); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + WSync(); +} + +static void Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +void Mapper164_Init(CartInfo *info) { + info->Power = Power; + info->Close = Close; + WSync = Sync; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +static DECLFW(Write2) { + if (A == 0x5101) { + if (laststrobe && !V) { + trigger ^= 1; + } + laststrobe = V; + } else if (A == 0x5100 && V == 6) //damn thoose protected games + setprg32(0x8000, 3); + else + switch (A & 0x7300) { + case 0x5200: /*FCEU_printf("%04x %02x (5000 = %02x)\n", A, V, reg[1]); */ reg[0] = V; WSync(); break; + case 0x5000: reg[1] = V; WSync(); if (!(reg[1] & 0x80) && (scanline < 128)) setchr8(0); /* setchr8(0); */ break; + case 0x5300: /*FCEU_printf("%04x %02x (5000 = %02x)\n", A, V, reg[1]);*/ reg[2] = V; break; + case 0x5100: /*FCEU_printf("%04x %02x (5000 = %02x)\n", A, V, reg[1]);*/ reg[3] = V; /*pcmwrite(0x4011, (decode(reg[0]) & 0xf) << 3);*/ WSync(); break; + } +} + +static void Power2(void) { + memset(reg, 0, 8); + laststrobe = 1; + pcmwrite = GetWriteHandler(0x4011); + SetReadHandler(0x5000, 0x5FFF, ReadLow); + SetWriteHandler(0x5000, 0x5FFF, Write2); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + WSync(); +} + +void Mapper163_Init(CartInfo *info) { + info->Power = Power2; + info->Close = Close; + WSync = Sync; + GameHBIRQHook = M163HB; + +// jedi_table_init(); + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +static void Sync3(void) { + setchr8(0); + setprg8r(0x10, 0x6000, 0); + switch (reg[3] & 7) { + case 0: + case 2: setprg32(0x8000, (reg[0] & 0xc) | (reg[1] & 2) | ((reg[2] & 0xf) << 4)); break; + case 1: + case 3: setprg32(0x8000, (reg[0] & 0xc) | (reg[2] & 0xf) << 4); break; + case 4: + case 6: setprg32(0x8000, (reg[0] & 0xe) | ((reg[1] >> 1) & 1) | ((reg[2] & 0xf) << 4)); break; + case 5: + case 7: setprg32(0x8000, (reg[0] & 0xf) | ((reg[2] & 0xf) << 4)); break; + } +} + +static DECLFW(Write3) { +// FCEU_printf("bs %04x %02x\n",A,V); + reg[(A >> 8) & 3] = V; + WSync(); +} + +static void Power3(void) { + reg[0] = 3; + reg[1] = 0; + reg[2] = 0; + reg[3] = 7; + SetWriteHandler(0x5000, 0x5FFF, Write3); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + WSync(); +} + +void UNLFS304_Init(CartInfo *info) { + info->Power = Power3; + info->Close = Close; + WSync = Sync3; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/168.c b/src/boards/168.c new file mode 100644 index 0000000..751f0b1 --- /dev/null +++ b/src/boards/168.c @@ -0,0 +1,81 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * RacerMate Chalenge II + * + */ + +#include "mapinc.h" + +static uint8 reg; +static uint8 *CHRRAM = NULL; +static uint32 CHRRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setchr4r(0x10, 0x0000, 0); + setchr4r(0x10, 0x1000, reg & 0x0f); + setprg16(0x8000, reg >> 6); + setprg16(0xc000, ~0); +} + +static DECLFW(M168Write) { + reg = V; + Sync(); +} + +static DECLFW(M168Dummy) { +} + +static void M168Power(void) { + reg = 0; + Sync(); + SetWriteHandler(0x4020, 0x7fff, M168Dummy); + SetWriteHandler(0xB000, 0xB000, M168Write); + SetWriteHandler(0xF000, 0xF000, M168Dummy); + SetWriteHandler(0xF080, 0xF080, M168Dummy); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void MNNNClose(void) { + if (CHRRAM) + FCEU_gfree(CHRRAM); + CHRRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper168_Init(CartInfo *info) { + info->Power = M168Power; + info->Close = MNNNClose; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); + + CHRRAMSIZE = 8192 * 8; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); +} diff --git a/src/boards/170.c b/src/boards/170.c new file mode 100644 index 0000000..9a8a8e5 --- /dev/null +++ b/src/boards/170.c @@ -0,0 +1,62 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, 0); + setprg16(0xc000, ~0); + setchr8(0); +} + +static DECLFW(M170ProtW) { + reg = V << 1 & 0x80; +} + +static DECLFR(M170ProtR) { + return reg | (X.DB & 0x7F); +} + +static void M170Power(void) { + Sync(); + SetWriteHandler(0x6502, 0x6502, M170ProtW); + SetWriteHandler(0x7000, 0x7000, M170ProtW); + SetReadHandler(0x7001, 0x7001, M170ProtR); + SetReadHandler(0x7777, 0x7777, M170ProtR); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper170_Init(CartInfo *info) { + info->Power = M170Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/175.c b/src/boards/175.c new file mode 100644 index 0000000..8278607 --- /dev/null +++ b/src/boards/175.c @@ -0,0 +1,79 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg, delay, mirr; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REG" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setchr8(reg); + if (!delay) { + setprg16(0x8000, reg); + setprg8(0xC000, reg << 1); + } + setprg8(0xE000, (reg << 1) + 1); + setmirror(((mirr & 4) >> 2) ^ 1); +} + +static DECLFW(M175Write1) { + mirr = V; + delay = 1; + Sync(); +} + +static DECLFW(M175Write2) { + reg = V & 0x0F; + delay = 1; + Sync(); +} + +static DECLFR(M175Read) { + if (A == 0xFFFC) { + delay = 0; + Sync(); + } + return CartBR(A); +} + +static void M175Power(void) { + reg = mirr = delay = 0; + SetReadHandler(0x8000, 0xFFFF, M175Read); + SetWriteHandler(0x8000, 0x8000, M175Write1); + SetWriteHandler(0xA000, 0xA000, M175Write2); + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper175_Init(CartInfo *info) { + info->Power = M175Power; + GameStateRestore = StateRestore; + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/177.c b/src/boards/177.c new file mode 100644 index 0000000..04fd9c8 --- /dev/null +++ b/src/boards/177.c @@ -0,0 +1,80 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg; + +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REG" }, + { 0 } +}; + +static void Sync(void) { + setchr8(0); + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, reg & 0x1f); + setmirror(((reg & 0x20) >> 5) ^ 1); +} + +static DECLFW(M177Write) { + reg = V; + Sync(); +} + +static void M177Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x6000, 0x7fff, CartBR); + SetWriteHandler(0x6000, 0x7fff, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M177Write); +} + +static void M177Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper177_Init(CartInfo *info) { + info->Power = M177Power; + info->Close = M177Close; + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/178.c b/src/boards/178.c new file mode 100644 index 0000000..cfd0392 --- /dev/null +++ b/src/boards/178.c @@ -0,0 +1,176 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * DSOUNDV1/FL-TR8MA boards (32K WRAM, 8/16M), 178 mapper boards (8K WRAM, 4/8M) + * Various Education Cartridges + * + */ + +#include "mapinc.h" + +static uint8 reg[4]; + +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +// SND Registers +static uint8 pcm_enable = 0; +static int16 pcm_latch = 0x3F6, pcm_clock = 0x3F6; +static writefunc pcmwrite; + +static SFORMAT StateRegs[] = +{ + { reg, 4, "REGS" }, + { 0 } +}; + +static int16 step_size[49] = { + 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, + 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, + 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, + 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, + 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552 +}; //49 items +static int32 step_adj[16] = { -1, -1, -1, -1, 2, 5, 7, 9, -1, -1, -1, -1, 2, 5, 7, 9 }; + +//decode stuff +static int32 jedi_table[16 * 49]; +static int32 acc = 0; //ADPCM accumulator, initial condition must be 0 +static int32 decstep = 0; //ADPCM decoding step, initial condition must be 0 + +static void jedi_table_init() { + int step, nib; + + for (step = 0; step < 49; step++) { + for (nib = 0; nib < 16; nib++) { + int value = (2 * (nib & 0x07) + 1) * step_size[step] / 8; + jedi_table[step * 16 + nib] = ((nib & 0x08) != 0) ? -value : value; + } + } +} + +static uint8 decode(uint8 code) { + acc += jedi_table[decstep + code]; + if ((acc & ~0x7ff) != 0) // acc is > 2047 + acc |= ~0xfff; + else acc &= 0xfff; + decstep += step_adj[code & 7] * 16; + if (decstep < 0) decstep = 0; + if (decstep > 48 * 16) decstep = 48 * 16; + return (acc >> 8) & 0xff; +} + +static void Sync(void) { + uint32 sbank = reg[1] & 0x7; + uint32 bbank = reg[2]; + setchr8(0); + setprg8r(0x10, 0x6000, reg[3] & 3); + if (reg[0] & 2) { // UNROM mode + setprg16(0x8000, (bbank << 3) | sbank); + if (reg[0] & 4) + setprg16(0xC000, (bbank << 3) | 6 | (reg[1] & 1)); + else + setprg16(0xC000, (bbank << 3) | 7); + } else { // NROM mode + uint32 bank = (bbank << 3) | sbank; + if (reg[0] & 4) { + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } else + setprg32(0x8000, bank >> 1); + } + setmirror((reg[0] & 1) ^ 1); +} + +static DECLFW(M178Write) { + reg[A & 3] = V; +// FCEU_printf("cmd %04x:%02x\n", A, V); + Sync(); +} + +static DECLFW(M178WriteSnd) { + if (A == 0x5800) { + if (V & 0xF0) { + pcm_enable = 1; +// pcmwrite(0x4011, (V & 0xF) << 3); + pcmwrite(0x4011, decode(V & 0xf)); + } else + pcm_enable = 0; + } else + FCEU_printf("misc %04x:%02x\n", A, V); +} + +static DECLFR(M178ReadSnd) { + if (A == 0x5800) + return (X.DB & 0xBF) | ((pcm_enable ^ 1) << 6); + else + return X.DB; +} + +static void M178Power(void) { + reg[0] = reg[1] = reg[2] = reg[3] = 0; + Sync(); + pcmwrite = GetWriteHandler(0x4011); + SetWriteHandler(0x4800, 0x4fff, M178Write); + SetWriteHandler(0x5800, 0x5fff, M178WriteSnd); + SetReadHandler(0x5800, 0x5fff, M178ReadSnd); + SetReadHandler(0x6000, 0x7fff, CartBR); + SetWriteHandler(0x6000, 0x7fff, CartBW); + SetReadHandler(0x8000, 0xffff, CartBR); +} + +static void M178SndClk(int a) { + if (pcm_enable) { + pcm_latch -= a; + if (pcm_latch <= 0) { + pcm_latch += pcm_clock; + pcm_enable = 0; + } + } +} + +static void M178Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper178_Init(CartInfo *info) { + info->Power = M178Power; + info->Close = M178Close; + GameStateRestore = StateRestore; + MapIRQHook = M178SndClk; + + jedi_table_init(); + + WRAMSIZE = 32768; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/18.c b/src/boards/18.c new file mode 100644 index 0000000..43b4515 --- /dev/null +++ b/src/boards/18.c @@ -0,0 +1,132 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 preg[4], creg[8]; +static uint8 IRQa, mirr; +static int32 IRQCount, IRQLatch; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { preg, 4, "PREG" }, + { creg, 8, "CREG" }, + { &mirr, 1, "MIRR" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { &IRQLatch, 4, "IRQL" }, + { 0 } +}; + +static void Sync(void) { + int i; + for (i = 0; i < 8; i++) setchr1(i << 10, creg[i]); + setprg8r(0x10, 0x6000, 0); + setprg8(0x8000, preg[0]); + setprg8(0xA000, preg[1]); + setprg8(0xC000, preg[2]); + setprg8(0xE000, ~0); + if (mirr & 2) + setmirror(MI_0); + else + setmirror(mirr & 1); +} + +static DECLFW(M18WriteIRQ) { + switch (A & 0xF003) { + case 0xE000: IRQLatch &= 0xFFF0; IRQLatch |= (V & 0x0f) << 0x0; break; + case 0xE001: IRQLatch &= 0xFF0F; IRQLatch |= (V & 0x0f) << 0x4; break; + case 0xE002: IRQLatch &= 0xF0FF; IRQLatch |= (V & 0x0f) << 0x8; break; + case 0xE003: IRQLatch &= 0x0FFF; IRQLatch |= (V & 0x0f) << 0xC; break; + case 0xF000: IRQCount = IRQLatch; break; + case 0xF001: IRQa = V & 1; X6502_IRQEnd(FCEU_IQEXT); break; + case 0xF002: mirr = V & 3; Sync(); break; + } +} + +static DECLFW(M18WritePrg) { + uint32 i = ((A >> 1) & 1) | ((A - 0x8000) >> 11); + preg[i] &= (0xF0) >> ((A & 1) << 2); + preg[i] |= (V & 0xF) << ((A & 1) << 2); + Sync(); +} + +static DECLFW(M18WriteChr) { + uint32 i = ((A >> 1) & 1) | ((A - 0xA000) >> 11); + creg[i] &= (0xF0) >> ((A & 1) << 2); + creg[i] |= (V & 0xF) << ((A & 1) << 2); + Sync(); +} + +static void M18Power(void) { + IRQa = 0; + preg[0] = 0; + preg[1] = 1; + preg[2] = ~1; + preg[3] = ~0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0x9FFF, M18WritePrg); + SetWriteHandler(0xA000, 0xDFFF, M18WriteChr); + SetWriteHandler(0xE000, 0xFFFF, M18WriteIRQ); +} + +static void FP_FASTAPASS(1) M18IRQHook(int a) { + if (IRQa && IRQCount) { + IRQCount -= a; + if (IRQCount <= 0) { + X6502_IRQBegin(FCEU_IQEXT); + IRQCount = 0; + IRQa = 0; + } + } +} + +static void M18Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper18_Init(CartInfo *info) { + info->Power = M18Power; + info->Close = M18Close; + MapIRQHook = M18IRQHook; + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + + AddExState(&StateRegs, ~0, 0, 0); +} + diff --git a/src/boards/183.c b/src/boards/183.c new file mode 100644 index 0000000..9ba8c2c --- /dev/null +++ b/src/boards/183.c @@ -0,0 +1,111 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Gimmick Bootleg (VRC4 mapper) + */ + +#include "mapinc.h" + +static uint8 prg[4], chr[8], mirr; +static uint8 IRQCount; +static uint8 IRQPre; +static uint8 IRQa; + +static SFORMAT StateRegs[] = +{ + { prg, 4, "PRG" }, + { chr, 8, "CHR" }, + { &mirr, 1, "MIRR" }, + { &IRQCount, 1, "IRQC" }, + { &IRQPre, 1, "IRQP" }, + { &IRQa, 1, "IRQA" }, + { 0 } +}; + +static void SyncPrg(void) { + setprg8(0x6000, prg[3]); + setprg8(0x8000, prg[0]); + setprg8(0xA000, prg[1]); + setprg8(0xC000, prg[2]); + setprg8(0xE000, ~0); +} + +static void SyncMirr(void) { + switch (mirr) { + 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 SyncChr(void) { + int i; + for (i = 0; i < 8; i++) + setchr1(i << 10, chr[i]); +} + +static void StateRestore(int version) { + SyncPrg(); + SyncChr(); + SyncMirr(); +} + +static DECLFW(M183Write) { + if ((A & 0xF800) == 0x6800) { + prg[3] = A & 0x3F; + SyncPrg(); + } else if (((A & 0xF80C) >= 0xB000) && ((A & 0xF80C) <= 0xE00C)) { + int index = (((A >> 11) - 6) | (A >> 3)) & 7; + 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: mirr = V & 3; SyncMirr(); 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(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0xFFFF, M183Write); + SyncPrg(); + SyncChr(); +} + +void Mapper183_Init(CartInfo *info) { + info->Power = M183Power; + GameHBIRQHook = M183IRQCounter; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/185.c b/src/boards/185.c new file mode 100644 index 0000000..f8ffe64 --- /dev/null +++ b/src/boards/185.c @@ -0,0 +1,107 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#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/src/boards/186.c b/src/boards/186.c new file mode 100644 index 0000000..137beaa --- /dev/null +++ b/src/boards/186.c @@ -0,0 +1,94 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Family Study Box by Fukutake Shoten + */ + +#include "mapinc.h" + +static uint8 SWRAM[3072]; +static uint8 *WRAM = NULL; +static uint8 regs[4]; + +static SFORMAT StateRegs[] = +{ + { regs, 4, "DREG" }, + { SWRAM, 3072, "SWRM" }, + { 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, 0x4FFF, ASWRAM); + SetWriteHandler(0x4400, 0x4FFF, 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(32768); + SetupCartPRGMapping(0x10, WRAM, 32768, 1); + AddExState(WRAM, 32768, 0, "WRAM"); + AddExState(StateRegs, ~0, 0, 0); +} diff --git a/src/boards/187.c b/src/boards/187.c new file mode 100644 index 0000000..1507ae9 --- /dev/null +++ b/src/boards/187.c @@ -0,0 +1,88 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * A98402 board, A9711, A9746 similar + * King of Fighters 96, The (Unl), Street Fighter Zero 2 (Unl) + * + */ + +#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) { + if (EXPREGS[0] & 0x40) + setprg32(0x8000, bank >> 2); + else + setprg32(0x8000, bank >> 1); // hacky hacky! two mappers in one! need real hw carts to test + } else { + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } else + setprg8(A, V & 0x3F); +} + +static DECLFW(M187Write8000) { + EXPREGS[1] = 1; + MMC3_CMDWrite(A, V); +} + +static DECLFW(M187Write8001) { + if (EXPREGS[1]) + MMC3_CMDWrite(A, V); +} + +static DECLFW(M187WriteLo) { + if ((A == 0x5000) || (A == 0x6000)) { + 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] = 0; + GenMMC3Power(); + SetReadHandler(0x5000, 0x5FFF, M187Read); + SetWriteHandler(0x5000, 0x6FFF, M187WriteLo); + SetWriteHandler(0x8000, 0x8000, M187Write8000); + SetWriteHandler(0x8001, 0x8001, M187Write8001); +} + +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/src/boards/189.c b/src/boards/189.c new file mode 100644 index 0000000..e0b541d --- /dev/null +++ b/src/boards/189.c @@ -0,0 +1,44 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void M189PW(uint32 A, uint8 V) { + setprg32(0x8000, EXPREGS[0] & 7); +} + +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/src/boards/193.c b/src/boards/193.c new file mode 100644 index 0000000..32b9881 --- /dev/null +++ b/src/boards/193.c @@ -0,0 +1,74 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * MEGA-SOFT WAR IN THE GULF + * + */ + +#include "mapinc.h" + +static uint8 reg[8]; +static uint8 mirror, cmd, bank; + +static SFORMAT StateRegs[] = +{ + { &cmd, 1, "CMD" }, + { &mirror, 1, "MIRR" }, + { &bank, 1, "BANK" }, + { reg, 8, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setmirror(mirror ^ 1); + setprg8(0x8000, reg[3]); + setprg8(0xA000, 0xD); + setprg8(0xC000, 0xE); + setprg8(0xE000, 0xF); + setchr4(0x0000, reg[0] >> 2); + setchr2(0x1000, reg[1] >> 1); + setchr2(0x1800, reg[2] >> 1); +} + +static DECLFW(M193Write) { + reg[A & 3] = V; + Sync(); +} + +static void M193Power(void) { + bank = 0; + Sync(); + SetWriteHandler(0x6000, 0x6003, M193Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, CartBW); +} + +static void M193Reset(void) { +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper193_Init(CartInfo *info) { + info->Reset = M193Reset; + info->Power = M193Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/199.c b/src/boards/199.c new file mode 100644 index 0000000..2a8ad05 --- /dev/null +++ b/src/boards/199.c @@ -0,0 +1,97 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Dragon Ball Z 2 - Gekishin Freeza! (C) + * Dragon Ball Z Gaiden - Saiya Jin Zetsumetsu Keikaku (C) + * San Guo Zhi 2 (C) + * + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 *CHRRAM = NULL; +static uint32 CHRRAMSIZE; + +static void M199PW(uint32 A, uint8 V) { + setprg8(A, V); + setprg8(0xC000, EXPREGS[0]); + setprg8(0xE000, EXPREGS[1]); +} + +static void M199CW(uint32 A, uint8 V) { + setchr1r((V < 8) ? 0x10 : 0x00, A, V); + setchr1r((DRegBuf[0] < 8) ? 0x10 : 0x00, 0x0000, DRegBuf[0]); + setchr1r((EXPREGS[2] < 8) ? 0x10 : 0x00, 0x0400, EXPREGS[2]); + setchr1r((DRegBuf[1] < 8) ? 0x10 : 0x00, 0x0800, DRegBuf[1]); + setchr1r((EXPREGS[3] < 8) ? 0x10 : 0x00, 0x0c00, EXPREGS[3]); +} + +static void M199MW(uint8 V) { +// FCEU_printf("%02x\n",V); + 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; + } +} + +static DECLFW(M199Write) { + if ((A == 0x8001) && (MMC3_cmd & 8)) { + EXPREGS[MMC3_cmd & 3] = V; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } else + if (A < 0xC000) + MMC3_CMDWrite(A, V); + else + MMC3_IRQWrite(A, V); +} + +static void M199Power(void) { + EXPREGS[0] = ~1; + EXPREGS[1] = ~0; + EXPREGS[2] = 1; + EXPREGS[3] = 3; + GenMMC3Power(); + SetWriteHandler(0x8000, 0xFFFF, M199Write); +} + +static void M199Close(void) { + if (CHRRAM) + FCEU_gfree(CHRRAM); + CHRRAM = NULL; +} + +void Mapper199_Init(CartInfo *info) { + GenMMC3_Init(info, 512, 256, 8, info->battery); + cwrap = M199CW; + pwrap = M199PW; + mwrap = M199MW; + info->Power = M199Power; + info->Close = M199Close; + + CHRRAMSIZE = 8192; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); + + AddExState(EXPREGS, 4, 0, "EXPR"); +} diff --git a/src/boards/206.c b/src/boards/206.c new file mode 100644 index 0000000..d013a8f --- /dev/null +++ b/src/boards/206.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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) { + 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]); + setprg8(0xc000, ~1); + setprg8(0xe000, ~0); +} + +static void StateRestore(int version) { + Sync(); +} + +static DECLFW(M206Write) { + 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 M206Power(void) { + cmd = 0; + DRegs[6] = 0; + DRegs[7] = 1; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M206Write); +} + + +void Mapper206_Init(CartInfo *info) { + info->Power = M206Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/208.c b/src/boards/208.c new file mode 100644 index 0000000..d581b1e --- /dev/null +++ b/src/boards/208.c @@ -0,0 +1,78 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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(0x6800, 0x6fff, 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/src/boards/222.c b/src/boards/222.c new file mode 100644 index 0000000..6fa7ff7 --- /dev/null +++ b/src/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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * (VRC4 mapper) + * + */ + +#include "mapinc.h" + +static uint8 IRQCount; //, IRQPre; +static uint8 IRQa; +static uint8 prg_reg[2]; +static uint8 chr_reg[8]; +static uint8 mirr; + +static SFORMAT StateRegs[] = +{ + { &IRQCount, 1, "IRQC" }, + { &IRQa, 1, "IRQA" }, + { prg_reg, 2, "PRG" }, + { chr_reg, 8, "CHR" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void M222IRQ(void) { + if (IRQa) { + IRQCount++; + if (IRQCount >= 238) { + 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]); + setmirror(mirr ^ 1); +} + +static DECLFW(M222Write) { + switch (A & 0xF003) { + case 0x8000: prg_reg[0] = V; break; + case 0x9000: mirr = V & 1; 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: FCEU_printf("%04x:%02x %d\n",A,V,scanline); IRQa=V; if(!V)IRQPre=0; X6502_IRQEnd(FCEU_IQEXT); break; +// case 0xF001: FCEU_printf("%04x:%02x %d\n",A,V,scanline); IRQCount=V; break; +// case 0xF002: FCEU_printf("%04x:%02x %d\n",A,V,scanline); break; +// case 0xD001: IRQa=V; X6502_IRQEnd(FCEU_IQEXT); FCEU_printf("%04x:%02x %d\n",A,V,scanline); break; +// case 0xC001: IRQPre=16; FCEU_printf("%04x:%02x %d\n",A,V,scanline); break; + case 0xF000: IRQa = IRQCount = V; if (scanline < 240) IRQCount -= 8; else IRQCount += 4; 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/src/boards/225.c b/src/boards/225.c new file mode 100644 index 0000000..15fdd60 --- /dev/null +++ b/src/boards/225.c @@ -0,0 +1,89 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * PCB-018 board, discrete multigame cart 110-in-1 + * + */ + +#include "mapinc.h" + +static uint8 prot[4], prg, mode, chr, mirr; + +static SFORMAT StateRegs[] = +{ + { prot, 4, "PROT" }, + { &prg, 1, "PRG" }, + { &chr, 1, "CHR" }, + { &mode, 1, "MODE" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + if (mode) { + setprg16(0x8000, prg); + setprg16(0xC000, prg); + } else + setprg32(0x8000, prg >> 1); + setchr8(chr); + setmirror(mirr ^ 1); +} + +static DECLFW(M225Write) { + uint32 bank = (A >> 14) & 1; + mirr = (A >> 13) & 1; + mode = (A >> 12) & 1; + chr = (A & 0x3f) | (bank << 6); + prg = ((A >> 6) & 0x3f) | (bank << 6); + Sync(); +} + +static DECLFW(M225LoWrite) { +} + +static DECLFR(M225LoRead) { + return 0; +} + +static void M225Power(void) { + prg = 0; + mode = 0; + Sync(); + SetReadHandler(0x5000, 0x5fff, M225LoRead); + SetWriteHandler(0x5000, 0x5fff, M225LoWrite); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M225Write); +} + +static void M225Reset(void) { + prg = 0; + mode = 0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper225_Init(CartInfo *info) { + info->Reset = M225Reset; + info->Power = M225Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/228.c b/src/boards/228.c new file mode 100644 index 0000000..bf39739 --- /dev/null +++ b/src/boards/228.c @@ -0,0 +1,84 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 mram[4], vreg; +static uint16 areg; + +static SFORMAT StateRegs[] = +{ + { mram, 4, "MRAM" }, + { &areg, 2, "AREG" }, + { &vreg, 1, "VREG" }, + { 0 } +}; + +static void Sync(void) { + uint32 prgl, prgh, page = (areg >> 7) & 0x3F; + if ((page & 0x30) == 0x30) + page -= 0x10; + prgl = prgh = (page << 1) + (((areg >> 6) & 1) & ((areg >> 5) & 1)); + prgh += ((areg >> 5) & 1) ^ 1; + + setmirror(((areg >> 13) & 1) ^ 1); + setprg16(0x8000, prgl); + setprg16(0xc000, prgh); + setchr8(((vreg & 0x3) | ((areg & 0xF) << 2))); +} + +static DECLFW(M228RamWrite) { + mram[A & 3] = V & 0x0F; +} + +static DECLFR(M228RamRead) { + return mram[A & 3]; +} + +static DECLFW(M228Write) { + areg = A; + vreg = V; + Sync(); +} + +static void M228Reset(void) { + areg = 0x8000; + vreg = 0; + Sync(); +} + +static void M228Power(void) { + M228Reset(); + SetReadHandler(0x5000, 0x5FFF, M228RamRead); + SetWriteHandler(0x5000, 0x5FFF, M228RamWrite); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M228Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper228_Init(CartInfo *info) { + info->Reset = M228Reset; + info->Power = M228Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/230.c b/src/boards/230.c new file mode 100644 index 0000000..174a70c --- /dev/null +++ b/src/boards/230.c @@ -0,0 +1,78 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2009 qeed + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * 22 + Contra Reset based custom mapper... + * + */ + +#include "mapinc.h" + +static uint8 latche, reset; +static SFORMAT StateRegs[] = +{ + { &reset, 1, "RST" }, + { &latche, 1, "LATC" }, + { 0 } +}; + +static void Sync(void) { + if (reset) { + setprg16(0x8000, latche & 7); + setprg16(0xC000, 7); + setmirror(MI_V); + } else { + uint32 bank = (latche & 0x1F) + 8; + if (latche & 0x20) { + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } else + setprg32(0x8000, bank >> 1); + setmirror((latche >> 6) & 1); + } + setchr8(0); +} + +static DECLFW(M230Write) { + latche = V; + Sync(); +} + +static void M230Reset(void) { + reset ^= 1; + Sync(); +} + +static void M230Power(void) { + latche = reset = 0; + Sync(); + SetWriteHandler(0x8000, 0xFFFF, M230Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper230_Init(CartInfo *info) { + info->Power = M230Power; + info->Reset = M230Reset; + AddExState(&StateRegs, ~0, 0, 0); + GameStateRestore = StateRestore; +} diff --git a/src/boards/232.c b/src/boards/232.c new file mode 100644 index 0000000..86bb0d0 --- /dev/null +++ b/src/boards/232.c @@ -0,0 +1,68 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 bank, preg; +static SFORMAT StateRegs[] = +{ + { &bank, 1, "BANK" }, + { &preg, 1, "PREG" }, + { 0 } +}; + +static void Sync(void) { +// uint32 bbank = (bank & 0x18) >> 1; + uint32 bbank = ((bank & 0x10) >> 2) | (bank & 8); // some dumps have bbanks swapped, if swap commands, + // then all roms can be played, but with some swapped + // games in menu. if not, some dumps are unplayable + // make hard dump for both cart types to check + setprg16(0x8000, bbank | (preg & 3)); + setprg16(0xC000, bbank | 3); + setchr8(0); +} + +static DECLFW(M232WriteBank) { + bank = V; + Sync(); +} + +static DECLFW(M232WritePreg) { + preg = V; + Sync(); +} + +static void M232Power(void) { + bank = preg = 0; + Sync(); + SetWriteHandler(0x8000, 0xBFFF, M232WriteBank); + SetWriteHandler(0xC000, 0xFFFF, M232WritePreg); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper232_Init(CartInfo *info) { + info->Power = M232Power; + AddExState(&StateRegs, ~0, 0, 0); + GameStateRestore = StateRestore; +} diff --git a/src/boards/234.c b/src/boards/234.c new file mode 100644 index 0000000..ef255bd --- /dev/null +++ b/src/boards/234.c @@ -0,0 +1,79 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 bank, preg; +static SFORMAT StateRegs[] = +{ + { &bank, 1, "BANK" }, + { &preg, 1, "PREG" }, + { 0 } +}; + +static void Sync(void) { + if (bank & 0x40) { + setprg32(0x8000, (bank & 0xE) | (preg & 1)); + setchr8(((bank & 0xE) << 2) | ((preg >> 4) & 7)); + } else { + setprg32(0x8000, bank & 0xF); + setchr8(((bank & 0xF) << 2) | ((preg >> 4) & 3)); + } + setmirror((bank >> 7) ^ 1); +} + +DECLFR(M234ReadBank) { + uint8 r = CartBR(A); + if (!bank) { + bank = r; + Sync(); + } + return r; +} + +DECLFR(M234ReadPreg) { + uint8 r = CartBR(A); + preg = r; + Sync(); + return r; +} + +static void M234Reset(void) { + bank = preg = 0; + Sync(); +} + +static void M234Power(void) { + M234Reset(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0xFF80, 0xFF9F, M234ReadBank); + SetReadHandler(0xFFE8, 0xFFF7, M234ReadPreg); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper234_Init(CartInfo *info) { + info->Power = M234Power; + info->Reset = M234Reset; + AddExState(&StateRegs, ~0, 0, 0); + GameStateRestore = StateRestore; +} diff --git a/src/boards/235.c b/src/boards/235.c new file mode 100644 index 0000000..98ce11b --- /dev/null +++ b/src/boards/235.c @@ -0,0 +1,63 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint16 cmdreg; +static SFORMAT StateRegs[] = +{ + { &cmdreg, 2, "CREG" }, + { 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/src/boards/244.c b/src/boards/244.c new file mode 100644 index 0000000..67c3369 --- /dev/null +++ b/src/boards/244.c @@ -0,0 +1,77 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 preg, creg; +static SFORMAT StateRegs[] = +{ + { &preg, 1, "PREG" }, + { &creg, 1, "CREG" }, + { 0 } +}; + +static uint8 prg_perm[4][4] = { + { 0, 1, 2, 3, }, + { 3, 2, 1, 0, }, + { 0, 2, 1, 3, }, + { 3, 1, 2, 0, }, +}; + +static uint8 chr_perm[8][8] = { + { 0, 1, 2, 3, 4, 5, 6, 7, }, + { 0, 2, 1, 3, 4, 6, 5, 7, }, + { 0, 1, 4, 5, 2, 3, 6, 7, }, + { 0, 4, 1, 5, 2, 6, 3, 7, }, + { 0, 4, 2, 6, 1, 5, 3, 7, }, + { 0, 2, 4, 6, 1, 3, 5, 7, }, + { 7, 6, 5, 4, 3, 2, 1, 0, }, + { 7, 6, 5, 4, 3, 2, 1, 0, }, +}; + +static void Sync(void) { + setprg32(0x8000, preg); + setchr8(creg); +} + +static DECLFW(M244Write) { + if (V & 8) + creg = chr_perm[(V >> 4) & 7][V & 7]; + else + preg = prg_perm[(V >> 4) & 3][V & 3]; + Sync(); +} + +static void M244Power(void) { + preg = creg = 0; + Sync(); + SetWriteHandler(0x8000, 0xFFFF, M244Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper244_Init(CartInfo *info) { + info->Power = M244Power; + AddExState(&StateRegs, ~0, 0, 0); + GameStateRestore = StateRestore; +} diff --git a/src/boards/246.c b/src/boards/246.c new file mode 100644 index 0000000..fe605e4 --- /dev/null +++ b/src/boards/246.c @@ -0,0 +1,85 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 regs[8]; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { regs, 8, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg2r(0x10, 0x6800, 0); + setprg8(0x8000, regs[0]); + setprg8(0xA000, regs[1]); + setprg8(0xC000, regs[2]); + setprg8(0xE000, regs[3]); + setchr2(0x0000, regs[4]); + setchr2(0x0800, regs[5]); + setchr2(0x1000, regs[6]); + setchr2(0x1800, regs[7]); +} + +static DECLFW(M246Write) { + regs[A & 7] = V; + Sync(); +} + +static void M246Power(void) { + regs[0] = regs[1] = regs[2] = regs[3] = ~0; + Sync(); + SetWriteHandler(0x6000, 0x67FF, M246Write); + SetReadHandler(0x6800, 0x6FFF, CartBR); + SetWriteHandler(0x6800, 0x6FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void M246Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper246_Init(CartInfo *info) { + info->Power = M246Power; + info->Close = M246Close; + GameStateRestore = StateRestore; + + WRAMSIZE = 2048; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/252.c b/src/boards/252.c new file mode 100644 index 0000000..2c4b24b --- /dev/null +++ b/src/boards/252.c @@ -0,0 +1,134 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 creg[8], preg[2]; +static int32 IRQa, IRQCount, IRQClock, IRQLatch; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; +static uint8 *CHRRAM = NULL; +static uint32 CHRRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { creg, 8, "CREG" }, + { preg, 2, "PREG" }, + { &IRQa, 4, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { &IRQLatch, 4, "IRQL" }, + { &IRQClock, 4, "IRQK" }, + { 0 } +}; + +static void Sync(void) { + uint8 i; + setprg8r(0x10, 0x6000, 0); + setprg8(0x8000, preg[0]); + setprg8(0xa000, preg[1]); + setprg8(0xc000, ~1); + setprg8(0xe000, ~0); + for (i = 0; i < 8; i++) + if ((creg[i] == 6) || (creg[i] == 7)) + setchr1r(0x10, i << 10, creg[i] & 1); + else + setchr1(i << 10, creg[i]); +} + +static DECLFW(M252Write) { + if ((A >= 0xB000) && (A <= 0xEFFF)) { + uint8 ind = ((((A & 8) | (A >> 8)) >> 3) + 2) & 7; + uint8 sar = A & 4; + creg[ind] = (creg[ind] & (0xF0 >> sar)) | ((V & 0x0F) << sar); + Sync(); + } else + switch (A & 0xF00C) { + case 0x8000: + case 0x8004: + case 0x8008: + case 0x800C: preg[0] = V; Sync(); break; + case 0xA000: + case 0xA004: + case 0xA008: + case 0xA00C: preg[1] = V; Sync(); break; + case 0xF000: X6502_IRQEnd(FCEU_IQEXT); IRQLatch &= 0xF0; IRQLatch |= V & 0xF; break; + case 0xF004: X6502_IRQEnd(FCEU_IQEXT); IRQLatch &= 0x0F; IRQLatch |= V << 4; break; + case 0xF008: X6502_IRQEnd(FCEU_IQEXT); IRQClock = 0; IRQCount = IRQLatch; IRQa = V & 2; break; + } +} + +static void M252Power(void) { + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M252Write); +} + +static void M252IRQ(int a) { + #define LCYCS 341 + if (IRQa) { + IRQClock += a * 3; + if (IRQClock >= LCYCS) { + while (IRQClock >= LCYCS) { + IRQClock -= LCYCS; + IRQCount++; + if (IRQCount & 0x100) { + X6502_IRQBegin(FCEU_IQEXT); + IRQCount = IRQLatch; + } + } + } + } +} + +static void M252Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + if (CHRRAM) + FCEU_gfree(CHRRAM); + WRAM = CHRRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper252_Init(CartInfo *info) { + info->Power = M252Power; + info->Close = M252Close; + MapIRQHook = M252IRQ; + + CHRRAMSIZE = 2048; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/253.c b/src/boards/253.c new file mode 100644 index 0000000..e79662a --- /dev/null +++ b/src/boards/253.c @@ -0,0 +1,151 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 chrlo[8], chrhi[8], prg[2], mirr, vlock; +static int32 IRQa, IRQCount, IRQLatch, IRQClock; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; +static uint8 *CHRRAM = NULL; +static uint32 CHRRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { chrlo, 8, "CHRL" }, + { chrhi, 8, "CHRH" }, + { prg, 2, "PRGR" }, + { &mirr, 1, "MIRR" }, + { &vlock, 1, "VLCK" }, + { &IRQa, 4, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { &IRQLatch, 4, "IRQL" }, + { &IRQClock, 4, "IRQK" }, + { 0 } +}; + +static void Sync(void) { + uint8 i; + setprg8r(0x10, 0x6000, 0); + setprg8(0x8000, prg[0]); + setprg8(0xa000, prg[1]); + setprg8(0xc000, ~1); + setprg8(0xe000, ~0); + for (i = 0; i < 8; i++) { + uint32 chr = chrlo[i] | (chrhi[i] << 8); + if (((chrlo[i] == 4) || (chrlo[i] == 5)) && !vlock) + setchr1r(0x10, i << 10, chr & 1); + else + setchr1(i << 10, chr); + } + switch (mirr) { + 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 DECLFW(M253Write) { + if ((A >= 0xB000) && (A <= 0xE00C)) { + uint8 ind = ((((A & 8) | (A >> 8)) >> 3) + 2) & 7; + uint8 sar = A & 4; + uint8 clo = (chrlo[ind] & (0xF0 >> sar)) | ((V & 0x0F) << sar); + chrlo[ind] = clo; + if (ind == 0) { + if (clo == 0xc8) + vlock = 0; + else if (clo == 0x88) + vlock = 1; + } + if (sar) + chrhi[ind] = V >> 4; + Sync(); + } else + switch (A) { + case 0x8010: prg[0] = V; Sync(); break; + case 0xA010: prg[1] = V; Sync(); break; + case 0x9400: mirr = V & 3; Sync(); break; + case 0xF000: X6502_IRQEnd(FCEU_IQEXT); IRQLatch &= 0xF0; IRQLatch |= V & 0xF; break; + case 0xF004: X6502_IRQEnd(FCEU_IQEXT); IRQLatch &= 0x0F; IRQLatch |= V << 4; break; + case 0xF008: X6502_IRQEnd(FCEU_IQEXT); IRQClock = 0; IRQCount = IRQLatch; IRQa = V & 2; break; + } +} + +static void M253Power(void) { + vlock = 0; + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M253Write); +} + +static void M253Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + if (CHRRAM) + FCEU_gfree(CHRRAM); + WRAM = CHRRAM = NULL; +} + +static void M253IRQ(int a) { + #define LCYCS 341 + if (IRQa) { + IRQClock += a * 3; + if (IRQClock >= LCYCS) { + while (IRQClock >= LCYCS) { + IRQClock -= LCYCS; + IRQCount++; + if (IRQCount & 0x100) { + X6502_IRQBegin(FCEU_IQEXT); + IRQCount = IRQLatch; + } + } + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper253_Init(CartInfo *info) { + info->Power = M253Power; + info->Close = M253Close; + MapIRQHook = M253IRQ; + GameStateRestore = StateRestore; + + CHRRAMSIZE = 2048; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/32.c b/src/boards/32.c new file mode 100644 index 0000000..ade2d65 --- /dev/null +++ b/src/boards/32.c @@ -0,0 +1,101 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 preg[2], creg[8], mirr; + +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { preg, 4, "PREG" }, + { creg, 8, "CREG" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + uint16 swap = ((mirr & 2) << 13); + setmirror((mirr & 1) ^ 1); + setprg8r(0x10, 0x6000, 0); + setprg8(0x8000 ^ swap, preg[0]); + setprg8(0xA000, preg[1]); + setprg8(0xC000 ^ swap, ~1); + setprg8(0xE000, ~0); + uint8 i; + for (i = 0; i < 8; i++) + setchr1(i << 10, creg[i]); +} + +static DECLFW(M32Write0) { + preg[0] = V; + Sync(); +} + +static DECLFW(M32Write1) { + mirr = V; + Sync(); +} + +static DECLFW(M32Write2) { + preg[1] = V; + Sync(); +} + +static DECLFW(M32Write3) { + creg[A & 7] = V; + Sync(); +} + +static void M32Power(void) { + Sync(); + SetReadHandler(0x6000, 0x7fff, CartBR); + SetWriteHandler(0x6000, 0x7fff, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0x8FFF, M32Write0); + SetWriteHandler(0x9000, 0x9FFF, M32Write1); + SetWriteHandler(0xA000, 0xAFFF, M32Write2); + SetWriteHandler(0xB000, 0xBFFF, M32Write3); +} + +static void M32Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper32_Init(CartInfo *info) { + info->Power = M32Power; + info->Close = M32Close; + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/33.c b/src/boards/33.c new file mode 100644 index 0000000..2243dae --- /dev/null +++ b/src/boards/33.c @@ -0,0 +1,117 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 is48; +static uint8 regs[8], mirr; +static uint8 IRQa; +static int16 IRQCount, IRQLatch; + +static SFORMAT StateRegs[] = +{ + { regs, 8, "PREG" }, + { &mirr, 1, "MIRR" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 2, "IRQC" }, + { &IRQLatch, 2, "IRQL" }, + { 0 } +}; + +static void Sync(void) { + setmirror(mirr); + setprg8(0x8000, regs[0]); + setprg8(0xA000, regs[1]); + setprg8(0xC000, ~1); + setprg8(0xE000, ~0); + setchr2(0x0000, regs[2]); + setchr2(0x0800, regs[3]); + setchr1(0x1000, regs[4]); + setchr1(0x1400, regs[5]); + setchr1(0x1800, regs[6]); + setchr1(0x1C00, regs[7]); +} + +static DECLFW(M33Write) { + A &= 0xF003; + switch (A) { + case 0x8000: regs[0] = V & 0x3F; if (!is48) mirr = ((V >> 6) & 1) ^ 1; Sync(); break; + case 0x8001: regs[1] = V & 0x3F; Sync(); break; + case 0x8002: regs[2] = V; Sync(); break; + case 0x8003: regs[3] = V; Sync(); break; + case 0xA000: regs[4] = V; Sync(); break; + case 0xA001: regs[5] = V; Sync(); break; + case 0xA002: regs[6] = V; Sync(); break; + case 0xA003: regs[7] = V; Sync(); break; + } +} + +static DECLFW(M48Write) { + 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: mirr = ((V >> 6) & 1) ^ 1; Sync(); break; + } +} + +static void M33Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M33Write); +} + +static void M48Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xBFFF, M33Write); + SetWriteHandler(0xC000, 0xFFFF, M48Write); +} + +static void M48IRQ(void) { + if (IRQa) { + IRQCount++; + if (IRQCount == 0x100) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper33_Init(CartInfo *info) { + is48 = 0; + info->Power = M33Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +void Mapper48_Init(CartInfo *info) { + is48 = 1; + info->Power = M48Power; + GameHBIRQHook = M48IRQ; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + diff --git a/src/boards/34.c b/src/boards/34.c new file mode 100644 index 0000000..71f1b30 --- /dev/null +++ b/src/boards/34.c @@ -0,0 +1,92 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Many-in-one hacked mapper crap. + * + * Original BNROM is actually AxROM variations without mirroring control, + * and haven't SRAM on-board, so it must be removed from here + * + * Difficult banking is what NINA board doing, most hacks for 34 mapper are + * NINA hacks, so this is actually 34 mapper + * + */ + +#include "mapinc.h" + +static uint8 regs[3]; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { regs, 3, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, regs[0]); + setchr4(0x0000, regs[1]); + setchr4(0x1000, regs[2]); +} + +static DECLFW(M34Write) { + if (A >= 0x8000) + regs[0] = V; + else + switch (A) { + case 0x7ffd: regs[0] = V; break; + case 0x7ffe: regs[1] = V; break; + case 0x7fff: regs[2] = V; break; + } + Sync(); +} + +static void M34Power(void) { + regs[0] = regs[1] = 0; + regs[2] = 1; + Sync(); + SetReadHandler(0x6000, 0x7ffc, CartBR); + SetWriteHandler(0x6000, 0x7ffc, CartBW); + SetReadHandler(0x8000, 0xffff, CartBR); + SetWriteHandler(0x7ffd, 0xffff, M34Write); +} + +static void M34Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper34_Init(CartInfo *info) { + info->Power = M34Power; + info->Close = M34Close; + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/36.c b/src/boards/36.c new file mode 100644 index 0000000..f4a3cfd --- /dev/null +++ b/src/boards/36.c @@ -0,0 +1,63 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * TXC/Micro Genius simplified mapper + */ + +#include "mapinc.h" + +static uint8 latche; + +static SFORMAT StateRegs[] = +{ + { &latche, 1, "LATC" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, latche >> 4); + setchr8(latche & 0xf); +} + +static DECLFW(M36Write) { + latche = V; + Sync(); +} + +static DECLFR(M36Read) { + return latche; // Need by Strike Wolf, being simplified mapper, this cart still uses some TCX mapper features andrely on it +} + +static void M36Power(void) { + latche = 0; + Sync(); + SetReadHandler(0x4100, 0x4100, M36Read); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFE, M36Write); // Actually, BUS conflict there preventing from triggering the wrong banks +} + +static void M36Restore(int version) { + Sync(); +} + +void Mapper36_Init(CartInfo *info) { + info->Power = M36Power; + GameStateRestore = M36Restore; + AddExState(StateRegs, ~0, 0, 0); +} diff --git a/src/boards/3d-block.c b/src/boards/3d-block.c new file mode 100644 index 0000000..34b9eda --- /dev/null +++ b/src/boards/3d-block.c @@ -0,0 +1,95 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[4], IRQa; +static int16 IRQCount, IRQPause; + +static int16 Count = 0x0000; + +static SFORMAT StateRegs[] = +{ + { reg, 4, "REGS" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 2, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, 0); + setchr8(0); +} + +//#define Count 0x1800 +#define Pause 0x010 + +static DECLFW(UNL3DBlockWrite) { + switch (A) { +//4800 32 +//4900 37 +//4a00 01 +//4e00 18 + case 0x4800: reg[0] = V; break; + case 0x4900: reg[1] = V; break; + case 0x4a00: reg[2] = V; break; + case 0x4e00: reg[3] = V; IRQCount = Count; IRQPause = Pause; IRQa = 1; X6502_IRQEnd(FCEU_IQEXT); break; + } +} + +static void UNL3DBlockPower(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4800, 0x4E00, UNL3DBlockWrite); +} + +static void UNL3DBlockReset(void) { + Count += 0x10; + FCEU_printf("Count=%04x\n", Count); +} + +static void FP_FASTAPASS(1) UNL3DBlockIRQHook(int a) { + if (IRQa) { + if (IRQCount > 0) { + IRQCount -= a; + } else { + if (IRQPause > 0) { + IRQPause -= a; + X6502_IRQBegin(FCEU_IQEXT); + } else { + IRQCount = Count; + IRQPause = Pause; + X6502_IRQEnd(FCEU_IQEXT); + } + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void UNL3DBlock_Init(CartInfo *info) { + info->Power = UNL3DBlockPower; + info->Reset = UNL3DBlockReset; + MapIRQHook = UNL3DBlockIRQHook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/40.c b/src/boards/40.c new file mode 100644 index 0000000..1525a42 --- /dev/null +++ b/src/boards/40.c @@ -0,0 +1,85 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg; +static uint32 IRQCount, IRQa; + +static SFORMAT StateRegs[] = +{ + { &IRQCount, 4, "IRQC" }, + { &IRQa, 4, "IRQA" }, + { ®, 1, "REG" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, ~1); + setprg8(0x8000, ~3); + setprg8(0xa000, ~2); + setprg8(0xc000, reg); + setprg8(0xe000, ~0); + setchr8(0); +} + +static DECLFW(M40Write) { + switch (A & 0xe000) { + case 0x8000: IRQa = 0; IRQCount = 0; X6502_IRQEnd(FCEU_IQEXT); break; + case 0xa000: IRQa = 1; break; + case 0xe000: reg = V & 7; Sync(); break; + } +} + +static void M40Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x6000, 0xffff, CartBR); + SetWriteHandler(0x8000, 0xffff, M40Write); +} + +static void M40Reset(void) { +} + +static void FP_FASTAPASS(1) M40IRQHook(int a) { + if (IRQa) { + if (IRQCount < 4096) + IRQCount += a; + else { + IRQa = 0; + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper40_Init(CartInfo *info) { + info->Reset = M40Reset; + info->Power = M40Power; + MapIRQHook = M40IRQHook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/41.c b/src/boards/41.c new file mode 100644 index 0000000..d0d9083 --- /dev/null +++ b/src/boards/41.c @@ -0,0 +1,69 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 mainreg, chrreg, mirror; + +static SFORMAT StateRegs[] = +{ + { &mainreg, 1, "MREG" }, + { &chrreg, 1, "CREG" }, + { &mirror, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, mainreg & 7); + setchr8(chrreg); + setmirror(mirror); +} + +static DECLFW(M41Write0) { + mainreg = A & 0xFF; + mirror = ((A >> 5) & 1) ^ 1; + chrreg = (chrreg & 3) | ((A >> 1) & 0xC); + Sync(); +} + +static DECLFW(M41Write1) { + if (mainreg & 0x4) { + chrreg = (chrreg & 0xC) | (A & 3); + Sync(); + } +} + +static void M41Power(void) { + mainreg = chrreg = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x67FF, M41Write0); + SetWriteHandler(0x8000, 0xFFFF, M41Write1); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper41_Init(CartInfo *info) { + info->Power = M41Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/411120-c.c b/src/boards/411120-c.c new file mode 100644 index 0000000..ccc490e --- /dev/null +++ b/src/boards/411120-c.c @@ -0,0 +1,64 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2008 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// actually cart ID is 811120-C, sorry ;) K-3094 - another ID + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reset_flag = 0; + +static void BMC411120CCW(uint32 A, uint8 V) { + setchr1(A, V | ((EXPREGS[0] & 3) << 7)); +} + +static void BMC411120CPW(uint32 A, uint8 V) { + if (EXPREGS[0] & (8 | reset_flag)) + setprg32(0x8000, ((EXPREGS[0] >> 4) & 3) | (0x0C)); + else + setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 3) << 4)); +} + +static DECLFW(BMC411120CLoWrite) { + EXPREGS[0] = A; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void BMC411120CReset(void) { + EXPREGS[0] = 0; + reset_flag ^= 4; + MMC3RegReset(); +} + +static void BMC411120CPower(void) { + EXPREGS[0] = 0; + GenMMC3Power(); + SetWriteHandler(0x6000, 0x7FFF, BMC411120CLoWrite); +} + +void BMC411120C_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 128, 8, 0); + pwrap = BMC411120CPW; + cwrap = BMC411120CCW; + info->Power = BMC411120CPower; + info->Reset = BMC411120CReset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/src/boards/42.c b/src/boards/42.c new file mode 100644 index 0000000..7018dc9 --- /dev/null +++ b/src/boards/42.c @@ -0,0 +1,83 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 preg, creg, mirr; +static uint32 IRQCount, IRQa; + +static SFORMAT StateRegs[] = +{ + { &preg, 1, "PREG" }, + { &creg, 1, "CREG" }, + { &mirr, 1, "MIRR" }, + { &IRQCount, 4, "IRQC" }, + { &IRQa, 4, "IRQA" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, preg); + setprg32(0x8000, ~0); + setchr8(creg); + setmirror(mirr); +} + +static DECLFW(M42Write) { + switch (A & 0xE003) { + case 0x8000: creg = V; Sync(); break; + case 0xE000: preg = V & 0x0F; Sync(); break; + case 0xE001: mirr = ((V >> 3) & 1) ^ 1; Sync(); break; + case 0xE002: IRQa = V & 2; if (!IRQa) IRQCount = 0; X6502_IRQEnd(FCEU_IQEXT); break; + } +} + +static void M42Power(void) { + preg = 0; + mirr = 1; // Ai Senshi Nicol actually has fixed mirroring, but mapper forcing it's default value now + Sync(); + SetReadHandler(0x6000, 0xffff, CartBR); + SetWriteHandler(0x6000, 0xffff, M42Write); +} + +static void FP_FASTAPASS(1) M42IRQHook(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 StateRestore(int version) { + Sync(); +} + +void Mapper42_Init(CartInfo *info) { + info->Power = M42Power; + MapIRQHook = M42IRQHook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/43.c b/src/boards/43.c new file mode 100644 index 0000000..4d7f8e4 --- /dev/null +++ b/src/boards/43.c @@ -0,0 +1,91 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg, swap; +static uint32 IRQCount, IRQa; + +static SFORMAT StateRegs[] = +{ + { &IRQCount, 4, "IRQC" }, + { &IRQa, 4, "IRQA" }, + { ®, 1, "REG" }, + { &swap, 1, "SWAP" }, + { 0 } +}; + +static void Sync(void) { + setprg4(0x5000, 8 << 1); // Only YS-612 advanced version + setprg8(0x6000, swap?0:2); + setprg8(0x8000, 1); + setprg8(0xa000, 0); + setprg8(0xc000, reg); + setprg8(0xe000, swap?8:9); // hard dump for mr.Mary is 128K, + // bank 9 is the last 2K ok bank 8 repeated 4 times, then till the end of 128K + // instead used bank A, containing some CHR data, ines rom have unused banks removed, + // and bank A moved to the bank 9 place for compatibility with other crappy dumps + setchr8(0); +} + +static DECLFW(M43Write) { +// int transo[8]={4,3,4,4,4,7,5,6}; + int transo[8] = { 4, 3, 5, 3, 6, 3, 7, 3 }; // According to hardware tests + switch (A & 0xf1ff) { + case 0x4022: reg = transo[V & 7]; Sync(); break; + case 0x4120: swap = V & 1; Sync(); break; + case 0x8122: // hacked version + case 0x4122: IRQa = V & 1; X6502_IRQEnd(FCEU_IQEXT); IRQCount = 0; break; // original version + } +} + +static void M43Power(void) { + reg = swap = 0; + Sync(); + SetReadHandler(0x5000, 0xffff, CartBR); + SetWriteHandler(0x4020, 0xffff, M43Write); +} + +static void M43Reset(void) { +} + +static void FP_FASTAPASS(1) M43IRQHook(int a) { + IRQCount += a; + if (IRQa) + if (IRQCount >= 4096) { + IRQa = 0; + X6502_IRQBegin(FCEU_IQEXT); + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper43_Init(CartInfo *info) { + info->Reset = M43Reset; + info->Power = M43Power; + MapIRQHook = M43IRQHook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/46.c b/src/boards/46.c new file mode 100644 index 0000000..04e0312 --- /dev/null +++ b/src/boards/46.c @@ -0,0 +1,69 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg0, reg1; + +static SFORMAT StateRegs[] = +{ + { ®0, 1, "REG0" }, + { ®1, 1, "REG1" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, (reg1 & 1) + ((reg0 & 0xF) << 1)); + setchr8(((reg1 >> 4) & 7) + ((reg0 & 0xF0) >> 1)); +} + +static DECLFW(M46Write0) { + reg0 = V; + Sync(); +} + +static DECLFW(M46Write1) { + reg1 = V; + Sync(); +} + +static void M46Power(void) { + reg0 = reg1 = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, M46Write0); + SetWriteHandler(0x8000, 0xFFFF, M46Write1); +} + +static void M46Reset(void) { + reg0 = reg1 = 0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper46_Init(CartInfo *info) { + info->Power = M46Power; + info->Reset = M46Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/50.c b/src/boards/50.c new file mode 100644 index 0000000..150c95e --- /dev/null +++ b/src/boards/50.c @@ -0,0 +1,84 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg; +static uint32 IRQCount, IRQa; + +static SFORMAT StateRegs[] = +{ + { &IRQCount, 4, "IRQC" }, + { &IRQa, 4, "IRQA" }, + { ®, 1, "REG" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, 0xF); + setprg8(0x8000, 0x8); + setprg8(0xa000, 0x9); + setprg8(0xc000, reg); + setprg8(0xe000, 0xB); + setchr8(0); +} + +static DECLFW(M50Write) { + switch (A & 0xD160) { + case 0x4120: IRQa = V & 1; if (!IRQa) IRQCount = 0; X6502_IRQEnd(FCEU_IQEXT); break; + case 0x4020: reg = ((V & 1) << 2) | ((V & 2) >> 1) | ((V & 4) >> 1) | (V & 8); Sync(); break; + } +} + +static void M50Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x6000, 0xffff, CartBR); + SetWriteHandler(0x4020, 0x5fff, M50Write); +} + +static void M50Reset(void) { +} + +static void FP_FASTAPASS(1) M50IRQHook(int a) { + if (IRQa) { + if (IRQCount < 4096) + IRQCount += a; + else { + IRQa = 0; + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper50_Init(CartInfo *info) { + info->Reset = M50Reset; + info->Power = M50Power; + MapIRQHook = M50IRQHook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/51.c b/src/boards/51.c new file mode 100644 index 0000000..02d693c --- /dev/null +++ b/src/boards/51.c @@ -0,0 +1,84 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 bank, mode; +static SFORMAT StateRegs[] = +{ + { &bank, 1, "BANK" }, + { &mode, 1, "MODE" }, + { 0 } +}; + +static void Sync(void) { + if (mode & 2) { + setprg8(0x6000, ((bank & 7) << 2) | 0x23); + setprg16(0x8000, (bank << 1) | 0); + setprg16(0xC000, (bank << 1) | 1); + } else { + setprg8(0x6000, ((bank & 4) << 2) | 0x2F); + setprg16(0x8000, (bank << 1) | (mode >> 4)); + setprg16(0xC000, ((bank & 0xC) << 1) | 7); + } + if (mode == 0x12) + setmirror(MI_H); + else + setmirror(MI_V); + setchr8(0); +} + +static DECLFW(M51WriteMode) { + mode = V & 0x12; + Sync(); +} + +static DECLFW(M51WriteBank) { + bank = V & 0x0F; + if (A & 0x4000) + mode = (mode & 2) | (V & 0x10); + Sync(); +} + +static void M51Power(void) { + bank = 0; + mode = 2; + Sync(); + SetWriteHandler(0x6000, 0x7FFF, M51WriteMode); + SetWriteHandler(0x8000, 0xFFFF, M51WriteBank); + SetReadHandler(0x6000, 0xFFFF, CartBR); +} + +static void M51Reset(void) { + bank = 0; + mode = 2; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper51_Init(CartInfo *info) { + info->Power = M51Power; + info->Reset = M51Reset; + AddExState(&StateRegs, ~0, 0, 0); + GameStateRestore = StateRestore; +} diff --git a/src/boards/57.c b/src/boards/57.c new file mode 100644 index 0000000..d5f8636 --- /dev/null +++ b/src/boards/57.c @@ -0,0 +1,84 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" + +static uint8 prg_reg; +static uint8 chr_reg; +static uint8 hrd_flag; + +static SFORMAT StateRegs[] = +{ + { &hrd_flag, 1, "DPSW" }, + { &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() { + hrd_flag++; + hrd_flag &= 3; + 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/src/boards/603-5052.c b/src/boards/603-5052.c new file mode 100644 index 0000000..2372603 --- /dev/null +++ b/src/boards/603-5052.c @@ -0,0 +1,49 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * SL12 Protected 3-in-1 mapper hardware (VRC2, MMC3, MMC1) + * the same as 603-5052 board (TODO: add reading registers, merge) + * + * Contra Fighter prot board + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 lut[4] = { 0x00, 0x02, 0x02, 0x03 }; + +static DECLFW(UNL6035052ProtWrite) { + EXPREGS[0] = lut[V & 3]; +} + +static DECLFR(UNL6035052ProtRead) { + return EXPREGS[0]; +} + +static void UNL6035052Power(void) { + GenMMC3Power(); + SetWriteHandler(0x4020, 0x7FFF, UNL6035052ProtWrite); + SetReadHandler(0x4020, 0x7FFF, UNL6035052ProtRead); +} + +void UNL6035052_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 256, 0, 0); + info->Power = UNL6035052Power; + AddExState(EXPREGS, 6, 0, "EXPR"); +} diff --git a/src/boards/62.c b/src/boards/62.c new file mode 100644 index 0000000..0dc2a63 --- /dev/null +++ b/src/boards/62.c @@ -0,0 +1,69 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 bank; +static uint16 mode; +static SFORMAT StateRegs[] = +{ + { &bank, 1, "BANK" }, + { &mode, 2, "MODE" }, + { 0 } +}; + +static void Sync(void) { + setchr8(((mode & 0x1F) << 2) | (bank & 0x03)); + if (mode & 0x20) { + setprg16(0x8000, (mode & 0x40) | ((mode >> 8) & 0x3F)); + setprg16(0xc000, (mode & 0x40) | ((mode >> 8) & 0x3F)); + } else + setprg32(0x8000, ((mode & 0x40) | ((mode >> 8) & 0x3F)) >> 1); + setmirror(((mode >> 7) & 1) ^ 1); +} + +static DECLFW(M62Write) { + mode = A & 0x3FFF; + bank = V & 3; + Sync(); +} + +static void M62Power(void) { + bank = mode = 0; + Sync(); + SetWriteHandler(0x8000, 0xFFFF, M62Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void M62Reset(void) { + bank = mode = 0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper62_Init(CartInfo *info) { + info->Power = M62Power; + info->Reset = M62Reset; + AddExState(&StateRegs, ~0, 0, 0); + GameStateRestore = StateRestore; +} diff --git a/src/boards/65.c b/src/boards/65.c new file mode 100644 index 0000000..aca3f64 --- /dev/null +++ b/src/boards/65.c @@ -0,0 +1,104 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 preg[3], creg[8], mirr; +static uint8 IRQa; +static int16 IRQCount, IRQLatch; + +static SFORMAT StateRegs[] = +{ + { preg, 3, "PREG" }, + { creg, 8, "CREG" }, + { &mirr, 1, "MIRR" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 2, "IRQC" }, + { &IRQLatch, 2, "IRQL" }, + { 0 } +}; + +static void Sync(void) { + setmirror(mirr); + setprg8(0x8000, preg[0]); + setprg8(0xA000, preg[1]); + setprg8(0xC000, preg[2]); + setprg8(0xE000, ~0); + setchr1(0x0000, creg[0]); + setchr1(0x0400, creg[1]); + setchr1(0x0800, creg[2]); + setchr1(0x0C00, creg[3]); + setchr1(0x1000, creg[4]); + setchr1(0x1400, creg[5]); + setchr1(0x1800, creg[6]); + setchr1(0x1C00, creg[7]); + setmirror(mirr); +} + +static DECLFW(M65Write) { + switch (A) { + case 0x8000: preg[0] = V; Sync(); break; + case 0xA000: preg[1] = V; Sync(); break; + case 0xC000: preg[2] = V; Sync(); break; + case 0x9001: mirr = ((V >> 7) & 1) ^ 1; Sync(); 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: creg[0] = V; Sync(); break; + case 0xB001: creg[1] = V; Sync(); break; + case 0xB002: creg[2] = V; Sync(); break; + case 0xB003: creg[3] = V; Sync(); break; + case 0xB004: creg[4] = V; Sync(); break; + case 0xB005: creg[5] = V; Sync(); break; + case 0xB006: creg[6] = V; Sync(); break; + case 0xB007: creg[7] = V; Sync(); break; + } +} + +static void M65Power(void) { + preg[2] = ~1; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M65Write); +} + +void FP_FASTAPASS(1) M65IRQ(int a) { + if (IRQa) { + IRQCount -= a; + if (IRQCount < -4) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + IRQCount = 0xFFFF; + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper65_Init(CartInfo *info) { + info->Power = M65Power; + MapIRQHook = M65IRQ; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + diff --git a/src/boards/67.c b/src/boards/67.c new file mode 100644 index 0000000..73b5333 --- /dev/null +++ b/src/boards/67.c @@ -0,0 +1,105 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 preg, creg[4], mirr, suntoggle = 0; +static uint8 IRQa; +static int16 IRQCount, IRQLatch; + +static SFORMAT StateRegs[] = +{ + { &preg, 1, "PREG" }, + { &suntoggle, 1, "STOG" }, + { creg, 4, "CREG" }, + { &mirr, 1, "MIRR" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 2, "IRQC" }, + { &IRQLatch, 2, "IRQL" }, + { 0 } +}; + +static void Sync(void) { + setmirror(mirr); + setprg16(0x8000, preg); + setprg16(0xC000, ~0); + setchr2(0x0000, creg[0]); + setchr2(0x0800, creg[1]); + setchr2(0x1000, creg[2]); + setchr2(0x1800, creg[3]); + switch (mirr) { + 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 DECLFW(M67Write) { + switch (A & 0xF800) { + case 0x8800: creg[0] = V; Sync(); break; + case 0x9800: creg[1] = V; Sync(); break; + case 0xA800: creg[2] = V; Sync(); break; + case 0xB800: creg[3] = V; Sync(); break; + case 0xC000: + case 0xC800: + IRQCount &= 0xFF << (suntoggle << 3); + IRQCount |= V << ((suntoggle ^ 1) << 3); + suntoggle ^= 1; + break; + case 0xD800: + suntoggle = 0; + IRQa = V & 0x10; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xE800: mirr = V & 3; Sync(); break; + case 0xF800: preg = V; Sync(); break; + } +} + +static void M67Power(void) { + suntoggle = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M67Write); +} + +void FP_FASTAPASS(1) M67IRQ(int a) { + if (IRQa) { + IRQCount -= a; + if (IRQCount <= 0) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + IRQCount = 0xFFFF; + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper67_Init(CartInfo *info) { + info->Power = M67Power; + MapIRQHook = M67IRQ; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + diff --git a/src/boards/68.c b/src/boards/68.c new file mode 100644 index 0000000..a38e567 --- /dev/null +++ b/src/boards/68.c @@ -0,0 +1,163 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 chr_reg[4]; +static uint8 kogame, prg_reg, nt1, nt2, mirr; + +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE, count; + +static SFORMAT StateRegs[] = +{ + { &nt1, 1, "NT1" }, + { &nt2, 1, "NT2" }, + { &mirr, 1, "MIRR" }, + { &prg_reg, 1, "PRG" }, + { &kogame, 1, "KGME" }, + { &count, 4, "CNT" }, + { chr_reg, 4, "CHR" }, + { 0 } +}; + +static void M68NTfix(void) { + if ((!UNIFchrrama) && (mirr & 0x10)) { + PPUNTARAM = 0; + switch (mirr & 3) { + case 0: + vnapage[0] = vnapage[2] = CHRptr[0] + (((nt1 | 128) & CHRmask1[0]) << 10); + vnapage[1] = vnapage[3] = CHRptr[0] + (((nt2 | 128) & CHRmask1[0]) << 10); + break; + case 1: + vnapage[0] = vnapage[1] = CHRptr[0] + (((nt1 | 128) & CHRmask1[0]) << 10); + vnapage[2] = vnapage[3] = CHRptr[0] + (((nt2 | 128) & CHRmask1[0]) << 10); + break; + case 2: + vnapage[0] = vnapage[1] = vnapage[2] = vnapage[3] = CHRptr[0] + (((nt1 | 128) & CHRmask1[0]) << 10); + break; + case 3: + vnapage[0] = vnapage[1] = vnapage[2] = vnapage[3] = CHRptr[0] + (((nt2 | 128) & CHRmask1[0]) << 10); + break; + } + } else + switch (mirr & 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 Sync(void) { + setchr2(0x0000, chr_reg[0]); + setchr2(0x0800, chr_reg[1]); + setchr2(0x1000, chr_reg[2]); + setchr2(0x1800, chr_reg[3]); + setprg8r(0x10, 0x6000, 0); + setprg16r((PRGptr[1]) ? kogame : 0, 0x8000, prg_reg); + setprg16(0xC000, ~0); +} + +static DECLFR(M68Read) { + if (!(kogame & 8)) { + count++; + if (count == 1784) + setprg16r(0, 0x8000, prg_reg); + } + return CartBR(A); +} + +static DECLFW(M68WriteLo) { + if (!V) { + count = 0; + setprg16r((PRGptr[1]) ? kogame : 0, 0x8000, prg_reg); + } + CartBW(A, V); +} + +static DECLFW(M68WriteCHR) { + chr_reg[(A >> 12) & 3] = V; + Sync(); +} + +static DECLFW(M68WriteNT1) { + nt1 = V; + M68NTfix(); +} + +static DECLFW(M68WriteNT2) { + nt2 = V; + M68NTfix(); +} + +static DECLFW(M68WriteMIR) { + mirr = V; + M68NTfix(); +} + +static DECLFW(M68WriteROM) { + prg_reg = V & 7; + kogame = ((V >> 3) & 1) ^ 1; + Sync(); +} + +static void M68Power(void) { + prg_reg = 0; + kogame = 0; + Sync(); + M68NTfix(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetReadHandler(0x8000, 0xBFFF, M68Read); + SetReadHandler(0xC000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xBFFF, M68WriteCHR); + SetWriteHandler(0xC000, 0xCFFF, M68WriteNT1); + SetWriteHandler(0xD000, 0xDFFF, M68WriteNT2); + SetWriteHandler(0xE000, 0xEFFF, M68WriteMIR); + SetWriteHandler(0xF000, 0xFFFF, M68WriteROM); + SetWriteHandler(0x6000, 0x6000, M68WriteLo); + SetWriteHandler(0x6001, 0x7FFF, CartBW); +} + +static void M68Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); + M68NTfix(); +} + +void Mapper68_Init(CartInfo *info) { + info->Power = M68Power; + info->Close = M68Close; + GameStateRestore = StateRestore; + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/69.c b/src/boards/69.c new file mode 100644 index 0000000..3babcd6 --- /dev/null +++ b/src/boards/69.c @@ -0,0 +1,277 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 cmdreg, preg[4], creg[8], mirr; +static uint8 IRQa; +static int32 IRQCount; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { &cmdreg, 1, "CMDR" }, + { preg, 4, "PREG" }, + { creg, 8, "CREG" }, + { &mirr, 1, "MIRR" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + uint8 i; + if ((preg[3] & 0xC0) == 0xC0) + setprg8r(0x10, 0x6000, 0); + else + setprg8(0x6000, preg[3] & 0x3F); + setprg8(0x8000, preg[0]); + setprg8(0xA000, preg[1]); + setprg8(0xC000, preg[2]); + setprg8(0xE000, ~0); + for (i = 0; i < 8; i++) + setchr1(i << 10, creg[i]); + switch (mirr & 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 DECLFW(M69WRAMWrite) { + if ((preg[3] & 0xC0) == 0xC0) + CartBW(A, V); +} + +static DECLFR(M69WRAMRead) { + if ((preg[3] & 0xC0) == 0x40) + return X.DB; + else + return CartBR(A); +} + +static DECLFW(M69Write0) { + cmdreg = V & 0xF; +} + +static DECLFW(M69Write1) { + switch (cmdreg) { + case 0x0: creg[0] = V; Sync(); break; + case 0x1: creg[1] = V; Sync(); break; + case 0x2: creg[2] = V; Sync(); break; + case 0x3: creg[3] = V; Sync(); break; + case 0x4: creg[4] = V; Sync(); break; + case 0x5: creg[5] = V; Sync(); break; + case 0x6: creg[6] = V; Sync(); break; + case 0x7: creg[7] = V; Sync(); break; + case 0x8: preg[3] = V; Sync(); break; + case 0x9: preg[0] = V; Sync(); break; + case 0xA: preg[1] = V; Sync(); break; + case 0xB: preg[2] = V; Sync(); break; + case 0xC: mirr = V & 3; Sync();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; + } +} + +// SUNSOFT-5/FME-7 Sound + +static void AYSound(int Count); +static void AYSoundHQ(void); +static void DoAYSQ(int x); +static void DoAYSQHQ(int x); + +static uint8 sndcmd, sreg[14]; +static int32 vcount[3]; +static int32 dcount[3]; +static int CAYBC[3]; + +static SFORMAT SStateRegs[] = +{ + { &sndcmd, 1, "SCMD" }, + { sreg, 14, "SREG" }, + { 0 } +}; + +static DECLFW(M69SWrite0) { + sndcmd = V % 14; +} + +static DECLFW(M69SWrite1) { + int x; + GameExpSound.Fill = AYSound; + GameExpSound.HiFill = AYSoundHQ; + if (FSettings.SndRate) + switch (sndcmd) { + 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; + } + sreg[sndcmd] = V; +} + +static void DoAYSQ(int x) { + int32 freq = ((sreg[x << 1] | ((sreg[(x << 1) + 1] & 15) << 8)) + 1) << (4 + 17); + int32 amp = (sreg[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 && !(sreg[0x7] & (1 << x))) + 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 = ((sreg[x << 1] | ((sreg[(x << 1) + 1] & 15) << 8)) + 1) << 4; + int32 amp = (sreg[0x8 + x] & 15) << 6; + + amp += amp >> 1; + + if (!(sreg[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; +} + +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)); + AddExState(&SStateRegs, ~0, 0, 0); +} + +// SUNSOFT-5/FME-7 Sound + +static void M69Power(void) { + cmdreg = sndcmd = 0; + IRQCount = 0xFFFF; + IRQa = 0; + Sync(); + SetReadHandler(0x6000, 0x7FFF, M69WRAMRead); + SetWriteHandler(0x6000, 0x7FFF, M69WRAMWrite); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0x9FFF, M69Write0); + SetWriteHandler(0xA000, 0xBFFF, M69Write1); + SetWriteHandler(0xC000, 0xDFFF, M69SWrite0); + SetWriteHandler(0xE000, 0xFFFF, M69SWrite1); +} + +static void M69Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void M69IRQHook(int a) { + if (IRQa) { + IRQCount -= a; + if (IRQCount <= 0) { + X6502_IRQBegin(FCEU_IQEXT); IRQa = 0; IRQCount = 0xFFFF; + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper69_Init(CartInfo *info) { + info->Power = M69Power; + info->Close = M69Close; + MapIRQHook = M69IRQHook; + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + GameStateRestore = StateRestore; + Mapper69_ESI(); + AddExState(&StateRegs, ~0, 0, 0); +} + +void NSFAY_Init(void) { + sndcmd = 0; + SetWriteHandler(0xC000, 0xDFFF, M69SWrite0); + SetWriteHandler(0xE000, 0xFFFF, M69SWrite1); + Mapper69_ESI(); +} diff --git a/src/boards/71.c b/src/boards/71.c new file mode 100644 index 0000000..6a79211 --- /dev/null +++ b/src/boards/71.c @@ -0,0 +1,64 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 preg, mirr; + +static SFORMAT StateRegs[] = +{ + { &preg, 1, "PREG" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, preg); + setprg16(0xC000, ~0); + setchr8(0); + if (mirr) + setmirror(mirr); +} + +static DECLFW(M71Write) { + if ((A & 0xF000) == 0x9000) + mirr = MI_0 + ((V >> 4) & 1); // 2-in-1, some carts are normal hardwire V/H mirror, some uses mapper selectable 0/1 mirror + else + preg = V; + Sync(); +} + +static void M71Power(void) { + mirr = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M71Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper71_Init(CartInfo *info) { + info->Power = M71Power; + GameStateRestore = StateRestore; + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/72.c b/src/boards/72.c new file mode 100644 index 0000000..de5ec91 --- /dev/null +++ b/src/boards/72.c @@ -0,0 +1,64 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Moero!! Pro Tennis have ADPCM codec on-board, PROM isn't dumped, emulation isn't + * possible just now. + */ + +#include "mapinc.h" + +static uint8 preg, creg; + +static SFORMAT StateRegs[] = +{ + { &preg, 1, "PREG" }, + { &creg, 1, "CREG" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, preg); + setprg16(0xC000, ~0); + setchr8(creg); +} + +static DECLFW(M72Write) { + if (V & 0x80) + preg = V & 0xF; + if (V & 0x40) + creg = V & 0xF; + Sync(); +} + +static void M72Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0xFFFF, M72Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper72_Init(CartInfo *info) { + info->Power = M72Power; + GameStateRestore = StateRestore; + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/77.c b/src/boards/77.c new file mode 100644 index 0000000..577ab4d --- /dev/null +++ b/src/boards/77.c @@ -0,0 +1,74 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 latche; + +static uint8 *CHRRAM = NULL; +static uint32 CHRRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { &latche, 1, "LATC" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, latche & 7); + setchr2(0x0000, latche >> 4); + setchr2r(0x10, 0x0800, 2); + setchr4r(0x10, 0x1000, 0); +} + +static DECLFW(M77Write) { + latche = V; + Sync(); +} + +static void M77Power(void) { + latche = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M77Write); +} + +static void M77Close(void) { + if (CHRRAM) + FCEU_gfree(CHRRAM); + CHRRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper77_Init(CartInfo *info) { + info->Power = M77Power; + info->Close = M77Close; + GameStateRestore = StateRestore; + + CHRRAMSIZE = 6 * 1024; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/79.c b/src/boards/79.c new file mode 100644 index 0000000..0aa35e2 --- /dev/null +++ b/src/boards/79.c @@ -0,0 +1,60 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 creg, preg; +static SFORMAT StateRegs[] = +{ + { &creg, 1, "CREG" }, + { &preg, 1, "PREG" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, preg); + setchr8(creg); +} + +static DECLFW(M79Write) { + if ((A < 0x8000) && ((A ^ 0x4100) == 0)) { + preg = (V >> 3) & 1; + } + creg = V & 7; + Sync(); +} + +static void M79Power(void) { + preg = ~0; + Sync(); + SetWriteHandler(0x4100, 0x5FFF, M79Write); + SetWriteHandler(0x8000, 0xFFFF, M79Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper79_Init(CartInfo *info) { + info->Power = M79Power; + AddExState(&StateRegs, ~0, 0, 0); + GameStateRestore = StateRestore; +} diff --git a/src/boards/80.c b/src/boards/80.c new file mode 100644 index 0000000..7b81702 --- /dev/null +++ b/src/boards/80.c @@ -0,0 +1,192 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 preg[3], creg[6], isExMirr; +static uint8 mirr, cmd, wram_enable, wram[256]; +static uint8 mcache[8]; +static uint32 lastppu; + +static SFORMAT StateRegs80[] = +{ + { preg, 3, "PREG" }, + { creg, 6, "CREG" }, + { wram, 256, "WRAM" }, + { &mirr, 1, "MIRR" }, + { &wram_enable, 1, "WRME" }, + { 0 } +}; + +static SFORMAT StateRegs95[] = +{ + { &cmd, 1, "CMDR" }, + { preg, 3, "PREG" }, + { creg, 6, "CREG" }, + { mcache, 8, "MCCH" }, + { &lastppu, 4, "LPPU" }, + { 0 } +}; + +static SFORMAT StateRegs207[] = +{ + { preg, 3, "PREG" }, + { creg, 6, "CREG" }, + { mcache, 8, "MCCH" }, + { &lastppu, 4, "LPPU" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, preg[0]); + setprg8(0xA000, preg[1]); + setprg8(0xC000, preg[2]); + setprg8(0xE000, ~0); + setchr2(0x0000, (creg[0] >> 1) & 0x3F); + setchr2(0x0800, (creg[1] >> 1) & 0x3F); + setchr1(0x1000, creg[2]); + setchr1(0x1400, creg[3]); + setchr1(0x1800, creg[4]); + setchr1(0x1C00, creg[5]); + if (isExMirr) { + setmirror(MI_0 + mcache[lastppu]); + } else + setmirror(mirr); +} + +static DECLFW(M80RamWrite) { + if (wram_enable == 0xA3) + wram[A & 0xFF] = V; +} + +static DECLFR(M80RamRead) { + if (wram_enable == 0xA3) + return wram[A & 0xFF]; + else + return 0xFF; +} + +static DECLFW(M80Write) { + switch (A) { + case 0x7EF0: creg[0] = V; mcache[0] = mcache[1] = V >> 7; Sync(); break; + case 0x7EF1: creg[1] = V; mcache[2] = mcache[3] = V >> 7; Sync(); break; + case 0x7EF2: creg[2] = V; mcache[4] = V >> 7; Sync(); break; + case 0x7EF3: creg[3] = V; mcache[5] = V >> 7; Sync(); break; + case 0x7EF4: creg[4] = V; mcache[6] = V >> 7; Sync(); break; + case 0x7EF5: creg[5] = V; mcache[7] = V >> 7; Sync(); break; + case 0x7EF6: mirr = V & 1; Sync(); break; + case 0x7EF8: wram_enable = V; break; + case 0x7EFA: + case 0x7EFB: preg[0] = V; Sync(); break; + case 0x7EFC: + case 0x7EFD: preg[1] = V; Sync(); break; + case 0x7EFE: + case 0x7EFF: preg[2] = V; Sync(); break; + } +} + +static DECLFW(M95Write) { + switch (A & 0xF001) { + case 0x8000: cmd = V; break; + case 0x8001: + switch (cmd & 0x07) { + case 0: creg[0] = V & 0x1F; mcache[0] = mcache[1] = (V >> 5) & 1; Sync(); break; + case 1: creg[1] = V & 0x1F; mcache[2] = mcache[3] = (V >> 5) & 1; Sync(); break; + case 2: creg[2] = V & 0x1F; mcache[4] = (V >> 5) & 1; Sync(); break; + case 3: creg[3] = V & 0x1F; mcache[5] = (V >> 5) & 1; Sync(); break; + case 4: creg[4] = V & 0x1F; mcache[6] = (V >> 5) & 1; Sync(); break; + case 5: creg[5] = V & 0x1F; mcache[7] = (V >> 5) & 1; Sync(); break; + case 6: preg[0] = V; Sync(); break; + case 7: preg[1] = V; Sync(); break; + } + Sync(); + } +} + +static void FP_FASTAPASS(1) MExMirrPPU(uint32 A) { + static int8 lastmirr = -1, curmirr; + if (A < 0x2000) { + lastppu = A >> 10; + curmirr = mcache[lastppu]; + if (curmirr != lastmirr) { + setmirror(MI_0 + curmirr); + lastmirr = curmirr; + } + } +} + +static void M80Power(void) { + wram_enable = 0xFF; + Sync(); + SetReadHandler(0x7F00, 0x7FFF, M80RamRead); + SetWriteHandler(0x7F00, 0x7FFF, M80RamWrite); + SetWriteHandler(0x7EF0, 0x7EFF, M80Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void M207Power(void) { + mcache[0] = mcache[1] = mcache[2] = mcache[3] = 0; + mcache[4] = mcache[5] = mcache[6] = mcache[7] = 0; + Sync(); + SetWriteHandler(0x7EF0, 0x7EFF, M80Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void M95Power(void) { + preg[2] = ~1; + mcache[0] = mcache[1] = mcache[2] = mcache[3] = 0; + mcache[4] = mcache[5] = mcache[6] = mcache[7] = 0; + Sync(); + SetWriteHandler(0x8000, 0xFFFF, M95Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper80_Init(CartInfo *info) { + isExMirr = 0; + info->Power = M80Power; + GameStateRestore = StateRestore; + + if (info->battery) { + info->SaveGame[0] = wram; + info->SaveGameLen[0] = 256; + } + + AddExState(&StateRegs80, ~0, 0, 0); +} + +void Mapper95_Init(CartInfo *info) { + isExMirr = 1; + info->Power = M95Power; + PPU_hook = MExMirrPPU; + GameStateRestore = StateRestore; + AddExState(&StateRegs95, ~0, 0, 0); +} + +void Mapper207_Init(CartInfo *info) { + isExMirr = 1; + info->Power = M207Power; + PPU_hook = MExMirrPPU; + GameStateRestore = StateRestore; + AddExState(&StateRegs207, ~0, 0, 0); +} diff --git a/src/boards/8157.c b/src/boards/8157.c new file mode 100644 index 0000000..287be08 --- /dev/null +++ b/src/boards/8157.c @@ -0,0 +1,85 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * GG1 boards, similar to T-262, with no Data latch + * + */ + +#include "mapinc.h" + +static uint16 cmdreg; +static uint8 reset; +static SFORMAT StateRegs[] = +{ + { &reset, 1, "REST" }, + { &cmdreg, 2, "CREG" }, + { 0 } +}; + +static void Sync(void) { + uint32 base = ((cmdreg & 0x060) | ((cmdreg & 0x100) >> 1)) >> 2; + uint32 bank = (cmdreg & 0x01C) >> 2; + uint32 lbank = (cmdreg & 0x200) ? 7 : ((cmdreg & 0x80) ? bank : 0); + if (PRGptr[1]) { + setprg16r(base >> 3, 0x8000, bank); // for versions with split ROMs + setprg16r(base >> 3, 0xC000, lbank); + } else { + setprg16(0x8000, base | bank); + setprg16(0xC000, base | lbank); + } + setmirror(((cmdreg & 2) >> 1) ^ 1); +} + +static DECLFR(UNL8157Read) { + if ((cmdreg & 0x100) && (PRGsize[0] < (1024 * 1024))) { + A = (A & 0xFFF0) + reset; + } + return CartBR(A); +} + +static DECLFW(UNL8157Write) { + cmdreg = A; + Sync(); +} + +static void UNL8157Power(void) { + setchr8(0); + SetWriteHandler(0x8000, 0xFFFF, UNL8157Write); + SetReadHandler(0x8000, 0xFFFF, UNL8157Read); + cmdreg = reset = 0; + Sync(); +} + +static void UNL8157Reset(void) { + cmdreg = reset = 0; + reset++; + reset &= 0x1F; + 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/src/boards/82.c b/src/boards/82.c new file mode 100644 index 0000000..c073997 --- /dev/null +++ b/src/boards/82.c @@ -0,0 +1,97 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Taito X1-017 board, battery backed + * + */ + +#include "mapinc.h" + +static uint8 regs[9], ctrl; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { regs, 9, "REGS" }, + { &ctrl, 1, "CTRL" }, + { 0 } +}; + +static void Sync(void) { + uint32 swap = ((ctrl & 2) << 11); + setchr2(0x0000 ^ swap, regs[0] >> 1); + setchr2(0x0800 ^ swap, regs[1] >> 1); + setchr1(0x1000 ^ swap, regs[2]); + setchr1(0x1400 ^ swap, regs[3]); + setchr1(0x1800 ^ swap, regs[4]); + setchr1(0x1c00 ^ swap, regs[5]); + setprg8r(0x10, 0x6000, 0); + setprg8(0x8000, regs[6]); + setprg8(0xA000, regs[7]); + setprg8(0xC000, regs[8]); + setprg8(0xE000, ~0); + setmirror(ctrl & 1); +} + +static DECLFW(M82Write) { + if (A <= 0x7ef5) + regs[A & 7] = V; + else + switch (A) { + case 0x7ef6: ctrl = V & 3; break; + case 0x7efa: regs[6] = V >> 2; break; + case 0x7efb: regs[7] = V >> 2; break; + case 0x7efc: regs[8] = V >> 2; break; + } + Sync(); +} + +static void M82Power(void) { + Sync(); + SetReadHandler(0x6000, 0xffff, CartBR); + SetWriteHandler(0x6000, 0x7fff, CartBW); + SetWriteHandler(0x7ef0, 0x7efc, M82Write); // external WRAM might end at $73FF +} + +static void M82Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper82_Init(CartInfo *info) { + info->Power = M82Power; + info->Close = M82Close; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/8237.c b/src/boards/8237.c new file mode 100644 index 0000000..e67d29c --- /dev/null +++ b/src/boards/8237.c @@ -0,0 +1,173 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Super Game (Sugar Softec) protected mapper + * Pocahontas 2 (Unl) [U][!], etc. + * TODO: 9in1 LION KING HANGS! + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 cmdin; + +static uint8 regperm[8][8] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7 }, + { 0, 2, 6, 1, 7, 3, 4, 5 }, + { 0, 5, 4, 1, 7, 2, 6, 3 }, // unused + { 0, 6, 3, 7, 5, 2, 4, 1 }, + { 0, 2, 5, 3, 6, 1, 7, 4 }, + { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty + { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty + { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty +}; + +static uint8 adrperm[8][8] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7 }, + { 3, 2, 0, 4, 1, 5, 6, 7 }, + { 0, 1, 2, 3, 4, 5, 6, 7 }, // unused + { 5, 0, 1, 2, 3, 7, 6, 4 }, + { 3, 1, 0, 5, 2, 4, 6, 7 }, + { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty + { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty + { 0, 1, 2, 3, 4, 5, 6, 7 }, // empty +}; + +static void UNL8237CW(uint32 A, uint8 V) { + if (EXPREGS[0] & 0x40) + setchr1(A, ((EXPREGS[1] & 0xc) << 6) | (V & 0x7F) | ((EXPREGS[1] & 0x20) << 2)); + else + setchr1(A, ((EXPREGS[1] & 0xc) << 6) | V); +} + +static void UNL8237PW(uint32 A, uint8 V) { + if (EXPREGS[0] & 0x40) { + uint8 sbank = (EXPREGS[1] & 0x10); + if (EXPREGS[0] & 0x80) { + uint8 bank = ((EXPREGS[1] & 3) << 4) | (EXPREGS[0] & 0x7) | (sbank >> 1); + if (EXPREGS[0] & 0x20) + setprg32(0x8000, bank >> 1); + else { + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } else + setprg8(A, ((EXPREGS[1] & 3) << 5) | (V & 0x0F) | sbank); + } else { + if (EXPREGS[0] & 0x80) { + uint8 bank = ((EXPREGS[1] & 3) << 4) | (EXPREGS[0] & 0xF); + if (EXPREGS[0] & 0x20) + setprg32(0x8000, bank >> 1); + else { + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } else + setprg8(A, ((EXPREGS[1] & 3) << 5) | (V & 0x1F)); + } +} + +static void UNL8237ACW(uint32 A, uint8 V) { + if (EXPREGS[0] & 0x40) + setchr1(A, ((EXPREGS[1] & 0xE) << 7) | (V & 0x7F) | ((EXPREGS[1] & 0x20) << 2)); + else + setchr1(A, ((EXPREGS[1] & 0xE) << 7) | V); +} + +static void UNL8237APW(uint32 A, uint8 V) { + if (EXPREGS[0] & 0x40) { + uint8 sbank = (EXPREGS[1] & 0x10); + if (EXPREGS[0] & 0x80) { + uint8 bank = ((EXPREGS[1] & 3) << 4) | ((EXPREGS[1] & 8) << 3) | (EXPREGS[0] & 0x7) | (sbank >> 1); + if (EXPREGS[0] & 0x20) { +// FCEU_printf("8000:%02X\n",bank>>1); + setprg32(0x8000, bank >> 1); + } else { +// FCEU_printf("8000-C000:%02X\n",bank); + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } else { +// FCEU_printf("%04x:%02X\n",A,((EXPREGS[1]&3)<<5)|((EXPREGS[1]&8)<<4)|(V&0x0F)|sbank); + setprg8(A, ((EXPREGS[1] & 3) << 5) | ((EXPREGS[1] & 8) << 4) | (V & 0x0F) | sbank); + } + } else { + if (EXPREGS[0] & 0x80) { + uint8 bank = ((EXPREGS[1] & 3) << 4) | ((EXPREGS[1] & 8) << 3) | (EXPREGS[0] & 0xF); + if (EXPREGS[0] & 0x20) { +// FCEU_printf("8000:%02X\n",(bank>>1)&0x07); + setprg32(0x8000, bank >> 1); + } else { +// FCEU_printf("8000-C000:%02X\n",bank&0x0F); + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + } else { +// FCEU_printf("%04X:%02X\n",A,(((EXPREGS[1]&3)<<5)|((EXPREGS[1]&8)<<4)|(V&0x1F))&0x1F); + setprg8(A, ((EXPREGS[1] & 3) << 5) | ((EXPREGS[1] & 8) << 4) | (V & 0x1F)); + } + } +} +static DECLFW(UNL8237Write) { + uint8 dat = V; + uint8 adr = adrperm[EXPREGS[2]][((A >> 12) & 6) | (A & 1)]; + uint16 addr = (adr & 1) | ((adr & 6) << 12) | 0x8000; + if (adr < 4) { + if (!adr) + dat = (dat & 0xC0) | (regperm[EXPREGS[2]][dat & 7]); + MMC3_CMDWrite(addr, dat); + } else + MMC3_IRQWrite(addr, dat); +} + +static DECLFW(UNL8237ExWrite) { + switch (A) { + case 0x5000: EXPREGS[0] = V; FixMMC3PRG(MMC3_cmd); break; + case 0x5001: EXPREGS[1] = V; FixMMC3PRG(MMC3_cmd); FixMMC3CHR(MMC3_cmd); break; + case 0x5007: EXPREGS[2] = V; break; + } +} + +static void UNL8237Power(void) { + EXPREGS[0] = EXPREGS[2] = 0; + EXPREGS[1] = 3; + 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, "CMDI"); +} + +void UNL8237A_Init(CartInfo *info) { + GenMMC3_Init(info, 256, 256, 0, 0); + cwrap = UNL8237ACW; + pwrap = UNL8237APW; + info->Power = UNL8237Power; + AddExState(EXPREGS, 3, 0, "EXPR"); + AddExState(&cmdin, 1, 0, "CMDI"); +} diff --git a/src/boards/830118C.c b/src/boards/830118C.c new file mode 100644 index 0000000..f04d9db --- /dev/null +++ b/src/boards/830118C.c @@ -0,0 +1,68 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2008 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// M-022 MMC3 based 830118C T-106 4M + 4M + +#include "mapinc.h" +#include "mmc3.h" + +static void BMC830118CCW(uint32 A, uint8 V) { + setchr1(A, (V & 0x7F) | ((EXPREGS[0] & 0x0c) << 5)); +} + +static void BMC830118CPW(uint32 A, uint8 V) { + if ((EXPREGS[0] & 0x0C) == 0x0C) { + if (A == 0x8000) { + setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 0x0c) << 2)); + setprg8(0xC000, (V & 0x0F) | 0x32); + } else if (A == 0xA000) { + setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 0x0c) << 2)); + setprg8(0xE000, (V & 0x0F) | 0x32); + } + } else { + setprg8(A, (V & 0x0F) | ((EXPREGS[0] & 0x0c) << 2)); + } +} + +static DECLFW(BMC830118CLoWrite) { + EXPREGS[0] = V; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void BMC830118CReset(void) { + EXPREGS[0] = 0; + MMC3RegReset(); +} + +static void BMC830118CPower(void) { + EXPREGS[0] = 0; + GenMMC3Power(); + SetWriteHandler(0x6800, 0x68FF, BMC830118CLoWrite); +} + +void BMC830118C_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 128, 8, 0); + pwrap = BMC830118CPW; + cwrap = BMC830118CCW; + info->Power = BMC830118CPower; + info->Reset = BMC830118CReset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/src/boards/88.c b/src/boards/88.c new file mode 100644 index 0000000..7341f25 --- /dev/null +++ b/src/boards/88.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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]); + setprg8(0xC000, ~1); + setprg8(0xE000, ~0); +} + +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) { + reg[0] = reg[1] = reg[2] = reg[3] = reg[4] = reg[5] = reg[6] = reg[7] = 0; + Sync(); + MSync(); + 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/src/boards/90.c b/src/boards/90.c new file mode 100644 index 0000000..9f144d3 --- /dev/null +++ b/src/boards/90.c @@ -0,0 +1,474 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +//#define DEBUG90 + +// Mapper 090 is simpliest mapper hardware and have not extended nametable control and latched chr banks in 4k mode +// Mapper 209 much compicated hardware with decribed above features disabled by default and switchable by command +// Mapper 211 the same mapper 209 but with forced nametable control + +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 uint8 chr[2]; + +static uint16 names[4]; +static uint8 tekker; + +static SFORMAT Tek_StateRegs[] = { + { &IRQMode, 1, "IRQM" }, + { &IRQPre, 1, "IRQP" }, + { &IRQPreSize, 1, "IRQR" }, + { &IRQCount, 1, "IRQC" }, + { &IRQXOR, 1, "IRQX" }, + { &IRQa, 1, "IRQA" }, + { mul, 2, "MUL" }, + { ®ie, 1, "REGI" }, + { tkcom, 4, "TKCO" }, + { prgb, 4, "PRGB" }, + { chr, 2, "CLTC" }, + { 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) { // TODO: verify for single, small multi and large multi + 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, (prgb[3] & 7) | ((tkcom[3] & 7) << 3)); + break; + case 01: + if (tkcom[0] & 0x80) + setprg8(0x6000, (((prgb[3] << 1) + 1) & 0x3F) | bankmode); + setprg16(0x8000, (prgb[1] & 0x0F) | ((tkcom[3] & 7) << 4)); + setprg16(0xC000, 0x0F | ((tkcom[3] & 7) << 4)); + break; + case 03: // bit reversion + case 02: + if (tkcom[0] & 0x80) + setprg8(0x6000, (prgb[3] & 0x1F) | ((tkcom[3] & 7) << 5)); // 45in1 multy has different bits, seems board was hacked to support big data banks + setprg8(0x8000, (prgb[0] & 0x1F) | ((tkcom[3] & 7) << 5)); + setprg8(0xa000, (prgb[1] & 0x1F) | ((tkcom[3] & 7) << 5)); + setprg8(0xc000, (prgb[2] & 0x1F) | ((tkcom[3] & 7) << 5)); + setprg8(0xe000, 0x1F | ((tkcom[3] & 7) << 5)); +// setprg8(0xe000,(prgb[3]&0x0F)|((tkcom[3]&6)<<3)); +// setprg32(0x8000,((prgb[0]&0x0F)>>2)|((tkcom[3]&6)<<3)); + 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); + setchr4(0x0000, ((chrlow[chr[0]] | (chrhigh[chr[0]] << 8)) & mask) | bank); + setchr4(0x1000, ((chrlow[chr[1]] | (chrhigh[chr[1]] << 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 & 0x5C03) { + case 0x5800: mul[0] = V; break; + case 0x5801: mul[1] = V; break; + case 0x5803: regie = V; break; + } +} + +static DECLFR(M90TekRead) { + switch (A & 0x5C03) { + case 0x5800: return(mul[0] * mul[1]); + case 0x5801: return((mul[0] * mul[1]) >> 8); + case 0x5803: return(regie); + default: return tekker; + } + return(0xff); +} + +static DECLFW(M90PRGWrite) { +// FCEU_printf("bs %04x %02x\n",A,V); + prgb[A & 3] = V; + tekprom(); +} + +static DECLFW(M90CHRlowWrite) { +// FCEU_printf("bs %04x %02x\n",A,V); + chrlow[A & 7] = V; + tekvrom(); +} + +static DECLFW(M90CHRhiWrite) { +// FCEU_printf("bs %04x %02x\n",A,V); + chrhigh[A & 7] = V; + tekvrom(); +} + +static DECLFW(M90NTWrite) { +// FCEU_printf("bs %04x %02x\n",A,V); + 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) { +// FCEU_printf("bs %04x %02x\n",A,V); + 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) { +// FCEU_printf("bs %04x %02x\n",A,V); + 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 DECLFW(M90DummyWrite) { +// FCEU_printf("bs %04x %02x\n",A,V); +} + +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; + } + + if (is209) { + uint8 l, h; + h = A >> 8; + if (h < 0x20 && ((h & 0x0F) == 0xF)) { + l = A & 0xF0; + if (l == 0xD0) { + chr[(h & 0x10) >> 4] = ((h & 0x10) >> 2); + tekvrom(); + } else if (l == 0xE0) { + chr[(h & 0x10) >> 4] = ((h & 0x10) >> 2) | 2; + tekvrom(); + } + } + } else { + chr[0] = 0; + chr[1] = 4; + } +} + +static void togglie() { + tekker += 0x40; + tekker &= 0xC0; + FCEU_printf("tekker=%02x\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, 0x8ff0, M90PRGWrite); + SetWriteHandler(0x9000, 0x9fff, M90CHRlowWrite); + SetWriteHandler(0xA000, 0xAfff, M90CHRhiWrite); + SetWriteHandler(0xB000, 0xBfff, M90NTWrite); + SetWriteHandler(0xC000, 0xCfff, M90IRQWrite); + SetWriteHandler(0xD000, 0xD5ff, M90ModeWrite); + SetWriteHandler(0xE000, 0xFfff, M90DummyWrite); + + 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; + MapIRQHook = CPUWrap; + GameHBIRQHook2 = SLWrap; + GameStateRestore = M90Restore; + AddExState(Tek_StateRegs, ~0, 0, 0); +} + +void Mapper209_Init(CartInfo *info) { + is211 = 0; + is209 = 1; + info->Reset = togglie; + info->Power = M90Power; + PPU_hook = M90PPU; + MapIRQHook = CPUWrap; + GameHBIRQHook2 = SLWrap; + GameStateRestore = M90Restore; + AddExState(Tek_StateRegs, ~0, 0, 0); +} + +void Mapper211_Init(CartInfo *info) { + is211 = 1; + info->Reset = togglie; + info->Power = M90Power; + PPU_hook = M90PPU; + MapIRQHook = CPUWrap; + GameHBIRQHook2 = SLWrap; + GameStateRestore = M90Restore; + AddExState(Tek_StateRegs, ~0, 0, 0); +} diff --git a/src/boards/91.c b/src/boards/91.c new file mode 100644 index 0000000..d1ed61b --- /dev/null +++ b/src/boards/91.c @@ -0,0 +1,85 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 cregs[4], pregs[2]; +static uint8 IRQCount, IRQa; + +static SFORMAT StateRegs[] = +{ + { cregs, 4, "CREG" }, + { pregs, 2, "PREG" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 1, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, pregs[0]); + setprg8(0xa000, pregs[1]); + setprg8(0xc000, ~1); + setprg8(0xe000, ~0); + setchr2(0x0000, cregs[0]); + setchr2(0x0800, cregs[1]); + setchr2(0x1000, cregs[2]); + setchr2(0x1800, cregs[3]); +} + +static DECLFW(M91Write0) { + cregs[A & 3] = V; + Sync(); +} + +static DECLFW(M91Write1) { + switch (A & 3) { + case 0: + case 1: pregs[A & 1] = V; Sync(); break; + case 2: IRQa = IRQCount = 0; X6502_IRQEnd(FCEU_IQEXT); break; + case 3: IRQa = 1; X6502_IRQEnd(FCEU_IQEXT); break; + } +} + +static void M91Power(void) { + Sync(); + SetWriteHandler(0x6000, 0x6fff, M91Write0); + SetWriteHandler(0x7000, 0x7fff, M91Write1); + SetReadHandler(0x8000, 0xffff, CartBR); +} + +static void M91IRQHook(void) { + if (IRQCount < 8 && IRQa) { + IRQCount++; + if (IRQCount >= 8) { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper91_Init(CartInfo *info) { + info->Power = M91Power; + GameHBIRQHook = M91IRQHook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/96.c b/src/boards/96.c new file mode 100644 index 0000000..d3f24e9 --- /dev/null +++ b/src/boards/96.c @@ -0,0 +1,77 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 1998 BERO + * Copyright (C) 2002 Xodnizel + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Oeka-kids board + * + * 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. + * + */ + +#include "mapinc.h" + +static uint8 reg, ppulatch; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REG" }, + { &ppulatch, 1, "PPUL" }, + { 0 } +}; + +static void Sync(void) { + setmirror(MI_0); + setprg32(0x8000, reg & 3); + setchr4(0x0000, (reg & 4) | ppulatch); + setchr4(0x1000, (reg & 4) | 3); +} + +static DECLFW(M96Write) { + reg = V; + Sync(); +} + +static void FP_FASTAPASS(1) M96Hook(uint32 A) { + if ((A & 0x3000) == 0x2000) { + ppulatch = (A >> 8) & 3; + Sync(); + } +} + +static void M96Power(void) { + reg = ppulatch = 0; + Sync(); + SetReadHandler(0x8000, 0xffff, CartBR); + SetWriteHandler(0x8000, 0xffff, M96Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper96_Init(CartInfo *info) { + info->Power = M96Power; + PPU_hook = M96Hook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + diff --git a/src/boards/99.c b/src/boards/99.c new file mode 100644 index 0000000..e54ebd7 --- /dev/null +++ b/src/boards/99.c @@ -0,0 +1,77 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 latch; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; +static writefunc old4016; + +static SFORMAT StateRegs[] = +{ + { &latch, 1, "LATC" }, + { 0 } +}; + +static void Sync(void) { + setchr8((latch >> 2) & 1); + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, 0); + setprg8(0x8000, latch & 4); /* Special for VS Gumshoe */ +} + +static DECLFW(M99Write) { + latch = V; + Sync(); + old4016(A, V); +} + +static void M99Power(void) { + latch = 0; + Sync(); + old4016 = GetWriteHandler(0x4016); + SetWriteHandler(0x4016, 0x4016, M99Write); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); +} + +static void M99Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper99_Init(CartInfo *info) { + info->Power = M99Power; + info->Close = M99Close; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/KS7012.c b/src/boards/KS7012.c new file mode 100644 index 0000000..63550af --- /dev/null +++ b/src/boards/KS7012.c @@ -0,0 +1,86 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, reg & 1); + setchr8(0); +} + +static DECLFW(UNLKS7012Write) { +// FCEU_printf("bs %04x %02x\n",A,V); + switch (A) { + case 0xE0A0: reg = 0; Sync(); break; + case 0xEE36: reg = 1; Sync(); break; + } +} + +static void UNLKS7012Power(void) { + reg = ~0; + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, UNLKS7012Write); +} + +static void UNLKS7012Reset(void) { + reg = ~0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +static void UNLKS7012Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +void UNLKS7012_Init(CartInfo *info) { + info->Power = UNLKS7012Power; + info->Reset = UNLKS7012Reset; + info->Close = UNLKS7012Close; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/KS7013.c b/src/boards/KS7013.c new file mode 100644 index 0000000..fe8349e --- /dev/null +++ b/src/boards/KS7013.c @@ -0,0 +1,77 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Just another pirate cart with pirate mapper, instead of original MMC1 + * Kaiser Highway Star + * + */ + +#include "mapinc.h" + +static uint8 reg, mirr; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REGS" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, reg); + setprg16(0xc000, ~0); + setmirror(mirr); + setchr8(0); +} + +static DECLFW(UNLKS7013BLoWrite) { + reg = V; + Sync(); +} + +static DECLFW(UNLKS7013BHiWrite) { + mirr = (V & 1) ^ 1; + Sync(); +} + +static void UNLKS7013BPower(void) { + reg = 0; + mirr = 0; + Sync(); + SetWriteHandler(0x6000, 0x7FFF, UNLKS7013BLoWrite); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, UNLKS7013BHiWrite); +} + +static void UNLKS7013BReset(void) { + reg = 0; + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLKS7013B_Init(CartInfo *info) { + info->Power = UNLKS7013BPower; + info->Reset = UNLKS7013BReset; + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/KS7017.c b/src/boards/KS7017.c new file mode 100644 index 0000000..8f4c072 --- /dev/null +++ b/src/boards/KS7017.c @@ -0,0 +1,114 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg, mirr; +static int32 IRQa, IRQCount, IRQLatch; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { &mirr, 1, "MIRR" }, + { ®, 1, "REGS" }, + { &IRQa, 4, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { &IRQLatch, 4, "IRQL" }, + { 0 } +}; + +static void Sync(void) { + setprg16(0x8000, reg); + setprg16(0xC000, 2); + setmirror(mirr); +} + +static DECLFW(UNLKS7017Write) { +// FCEU_printf("bs %04x %02x\n",A,V); + if ((A & 0xFF00) == 0x4A00) { + reg = ((A >> 2) & 3) | ((A >> 4) & 4); + } else if ((A & 0xFF00) == 0x5100) { + Sync(); + } else if (A == 0x4020) { + X6502_IRQEnd(FCEU_IQEXT); + IRQCount &= 0xFF00; + IRQCount |= V; + } else if (A == 0x4021) { + X6502_IRQEnd(FCEU_IQEXT); + IRQCount &= 0xFF; + IRQCount |= V << 8; + IRQa = 1; + } else if (A == 0x4025) { + mirr = ((V & 8) >> 3) ^ 1; + } +} +static DECLFR(FDSRead4030) { + X6502_IRQEnd(FCEU_IQEXT); + return X.IRQlow & FCEU_IQEXT ? 1 : 0; +} + +static void FP_FASTAPASS(1) UNL7017IRQ(int a) { + if (IRQa) { + IRQCount -= a; + if (IRQCount <= 0) { + IRQa = 0; + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void UNLKS7017Power(void) { + Sync(); + setchr8(0); + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4030, 0x4030, FDSRead4030); + SetWriteHandler(0x4020, 0x5FFF, UNLKS7017Write); +} + +static void UNLKS7017Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLKS7017_Init(CartInfo *info) { + info->Power = UNLKS7017Power; + info->Close = UNLKS7017Close; + MapIRQHook = UNL7017IRQ; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/KS7030.c b/src/boards/KS7030.c new file mode 100644 index 0000000..8e6a592 --- /dev/null +++ b/src/boards/KS7030.c @@ -0,0 +1,140 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + * Logical bank layot 32 K BANK 0, 64K BANK 1, 32K ~0 hardwired, 8K is missing + * need redump from MASKROM! + * probably need refix mapper after hard dump + * + */ + +#include "mapinc.h" + +static uint8 reg0, reg1; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { ®0, 1, "REG0" }, + { ®1, 1, "REG1" }, + { 0 } +}; + +static void Sync(void) { + setchr8(0); + setprg32(0x8000, ~0); + setprg4(0xb800, reg0); + setprg4(0xc800, 8 + reg1); +} + +// 6000 - 6BFF - RAM +// 6C00 - 6FFF - BANK 1K REG1 +// 7000 - 7FFF - BANK 4K REG0 + +static DECLFW(UNLKS7030RamWrite0) { + if ((A >= 0x6000) && A <= 0x6BFF) { + WRAM[A - 0x6000] = V; + } else if ((A >= 0x6C00) && A <= 0x6FFF) { + CartBW(0xC800 + (A - 0x6C00), V); + } else if ((A >= 0x7000) && A <= 0x7FFF) { + CartBW(0xB800 + (A - 0x7000), V); + } +} + +static DECLFR(UNLKS7030RamRead0) { + if ((A >= 0x6000) && A <= 0x6BFF) { + return WRAM[A - 0x6000]; + } else if ((A >= 0x6C00) && A <= 0x6FFF) { + return CartBR(0xC800 + (A - 0x6C00)); + } else if ((A >= 0x7000) && A <= 0x7FFF) { + return CartBR(0xB800 + (A - 0x7000)); + } + return 0; +} + +// B800 - BFFF - RAM +// C000 - CBFF - BANK 3K +// CC00 - D7FF - RAM + +static DECLFW(UNLKS7030RamWrite1) { + if ((A >= 0xB800) && A <= 0xBFFF) { + WRAM[0x0C00 + (A - 0xB800)] = V; + } else if ((A >= 0xC000) && A <= 0xCBFF) { + CartBW(0xCC00 + (A - 0xC000), V); + } else if ((A >= 0xCC00) && A <= 0xD7FF) { + WRAM[0x1400 + (A - 0xCC00)] = V; + } +} + +static DECLFR(UNLKS7030RamRead1) { + if ((A >= 0xB800) && A <= 0xBFFF) { + return WRAM[0x0C00 + (A - 0xB800)]; + } else if ((A >= 0xC000) && A <= 0xCBFF) { + return CartBR(0xCC00 + (A - 0xC000)); + } else if ((A >= 0xCC00) && A <= 0xD7FF) { + return WRAM[0x1400 + (A - 0xCC00)]; + } + return 0; +} + +static DECLFW(UNLKS7030Write0) { + reg0 = A & 7; + Sync(); +} + +static DECLFW(UNLKS7030Write1) { + reg1 = A & 15; + Sync(); +} + +static void UNLKS7030Power(void) { + reg0 = reg1 = ~0; + Sync(); + SetReadHandler(0x6000, 0x7FFF, UNLKS7030RamRead0); + SetWriteHandler(0x6000, 0x7FFF, UNLKS7030RamWrite0); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0x8FFF, UNLKS7030Write0); + SetWriteHandler(0x9000, 0x9FFF, UNLKS7030Write1); + SetReadHandler(0xB800, 0xD7FF, UNLKS7030RamRead1); + SetWriteHandler(0xB800, 0xD7FF, UNLKS7030RamWrite1); +} + +static void UNLKS7030Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLKS7030_Init(CartInfo *info) { + info->Power = UNLKS7030Power; + info->Close = UNLKS7030Close; + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/KS7031.c b/src/boards/KS7031.c new file mode 100644 index 0000000..f994434 --- /dev/null +++ b/src/boards/KS7031.c @@ -0,0 +1,80 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg[4]; + +static SFORMAT StateRegs[] = +{ + { reg, 4, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg2(0x6000, reg[0]); + setprg2(0x6800, reg[1]); + setprg2(0x7000, reg[2]); + setprg2(0x7800, reg[3]); + + setprg2(0x8000, 15); + setprg2(0x8800, 14); + setprg2(0x9000, 13); + setprg2(0x9800, 12); + setprg2(0xa000, 11); + setprg2(0xa800, 10); + setprg2(0xb000, 9); + setprg2(0xb800, 8); + + setprg2(0xc000, 7); + setprg2(0xc800, 6); + setprg2(0xd000, 5); + setprg2(0xd800, 4); + setprg2(0xe000, 3); + setprg2(0xe800, 2); + setprg2(0xf000, 1); + setprg2(0xf800, 0); + + setchr8(0); +} + +static DECLFW(UNLKS7031Write) { + reg[(A >> 11) & 3] = V; + Sync(); +} + +static void UNLKS7031Power(void) { + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xffff, UNLKS7031Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLKS7031_Init(CartInfo *info) { + info->Power = UNLKS7031Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/KS7032.c b/src/boards/KS7032.c new file mode 100644 index 0000000..743efb4 --- /dev/null +++ b/src/boards/KS7032.c @@ -0,0 +1,91 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg[8], cmd, IRQa = 0, isirqused = 0; +static int32 IRQCount; + +static SFORMAT StateRegs[] = +{ + { &cmd, 1, "CMD" }, + { reg, 8, "REGS" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, reg[4]); + setprg8(0x8000, reg[1]); + setprg8(0xA000, reg[2]); + setprg8(0xC000, reg[3]); + setprg8(0xE000, ~0); + setchr8(0); +} + +static DECLFW(UNLKS7032Write) { +// FCEU_printf("bs %04x %02x\n",A,V); + switch (A & 0xF000) { +// case 0x8FFF: reg[4]=V; Sync(); break; + case 0x8000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0x000F) | (V & 0x0F); isirqused = 1; break; + case 0x9000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0x00F0) | ((V & 0x0F) << 4); isirqused = 1; break; + case 0xA000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0x0F00) | ((V & 0x0F) << 8); isirqused = 1; break; + case 0xB000: X6502_IRQEnd(FCEU_IQEXT); IRQCount = (IRQCount & 0xF000) | (V << 12); isirqused = 1; break; + case 0xC000: if (isirqused) { + X6502_IRQEnd(FCEU_IQEXT); IRQa = 1; + } + break; + case 0xE000: cmd = V & 7; break; + case 0xF000: reg[cmd] = V; Sync(); break; + } +} + +static void FP_FASTAPASS(1) UNLSMB2JIRQHook(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount >= 0xFFFF) { + IRQa = 0; + IRQCount = 0; + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void UNLKS7032Power(void) { + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4020, 0xFFFF, UNLKS7032Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLKS7032_Init(CartInfo *info) { + info->Power = UNLKS7032Power; + MapIRQHook = UNLSMB2JIRQHook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/KS7037.c b/src/boards/KS7037.c new file mode 100644 index 0000000..efe43f2 --- /dev/null +++ b/src/boards/KS7037.c @@ -0,0 +1,125 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg[8], cmd; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static void (*WSync)(void); + +static SFORMAT StateRegs[] = +{ + { &cmd, 1, "CMD" }, + { reg, 8, "REGS" }, + { 0 } +}; + +static void SyncKS7037(void) { + setprg4r(0x10, 0x6000, 0); + setprg4(0x7000, 15); + setprg8(0x8000, reg[6]); + setprg4(0xA000, ~3); + setprg4r(0x10, 0xB000, 1); + setprg8(0xC000, reg[7]); + setprg8(0xE000, ~0); + setchr8(0); + setmirrorw(reg[2] & 1, reg[4] & 1, reg[3] & 1, reg[5] & 1); +} + +static void SyncLH10(void) { + setprg8(0x6000, ~1); + setprg8(0x8000, reg[6]); + setprg8(0xA000, reg[7]); + setprg8r(0x10, 0xC000, 0); + setprg8(0xE000, ~0); + setchr8(0); + setmirror(0); +} + +static DECLFW(UNLKS7037Write) { + switch (A & 0xE001) { + case 0x8000: cmd = V & 7; break; + case 0x8001: reg[cmd] = V; WSync(); break; + } +} + +static void UNLKS7037Power(void) { + reg[0] = reg[1] = reg[2] = reg[3] = reg[4] = reg[5] = reg[6] = reg[7] = 0; + WSync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0x9FFF, UNLKS7037Write); + SetWriteHandler(0xA000, 0xBFFF, CartBW); + SetWriteHandler(0xC000, 0xFFFF, UNLKS7037Write); +} + +static void LH10Power(void) { + reg[0] = reg[1] = reg[2] = reg[3] = reg[4] = reg[5] = reg[6] = reg[7] = 0; + WSync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xBFFF, UNLKS7037Write); + SetWriteHandler(0xC000, 0xDFFF, CartBW); + SetWriteHandler(0xE000, 0xFFFF, UNLKS7037Write); +} + +static void Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + WSync(); +} + +void UNLKS7037_Init(CartInfo *info) { + info->Power = UNLKS7037Power; + info->Close = Close; + + WSync = SyncKS7037; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +void LH10_Init(CartInfo *info) { + info->Power = LH10Power; + info->Close = Close; + + WSync = SyncLH10; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/KS7057.c b/src/boards/KS7057.c new file mode 100644 index 0000000..a9c4796 --- /dev/null +++ b/src/boards/KS7057.c @@ -0,0 +1,92 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg[8], mirror; +static SFORMAT StateRegs[] = +{ + { reg, 8, "PRG" }, + { &mirror, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg2(0x6000, reg[4]); + setprg2(0x6800, reg[5]); + setprg2(0x7000, reg[6]); + setprg2(0x7800, reg[7]); + setprg2(0x8000, reg[0]); + setprg2(0x8800, reg[1]); + setprg2(0x9000, reg[2]); + setprg2(0x9800, reg[3]); + setprg8(0xA000, 0xd); + setprg16(0xC000, 7); + setchr8(0); + setmirror(mirror); +} + +static DECLFW(UNLKS7057Write) { + switch (A & 0xF003) { + case 0x8000: + case 0x8001: + case 0x8002: + case 0x8003: + case 0x9000: + case 0x9001: + case 0x9002: + case 0x9003: mirror = V & 1; Sync(); break; + case 0xB000: reg[0] = (reg[0] & 0xF0) | (V & 0x0F); Sync(); break; + case 0xB001: reg[0] = (reg[0] & 0x0F) | (V << 4); Sync(); break; + case 0xB002: reg[1] = (reg[1] & 0xF0) | (V & 0x0F); Sync(); break; + case 0xB003: reg[1] = (reg[1] & 0x0F) | (V << 4); Sync(); break; + case 0xC000: reg[2] = (reg[2] & 0xF0) | (V & 0x0F); Sync(); break; + case 0xC001: reg[2] = (reg[2] & 0x0F) | (V << 4); Sync(); break; + case 0xC002: reg[3] = (reg[3] & 0xF0) | (V & 0x0F); Sync(); break; + case 0xC003: reg[3] = (reg[3] & 0x0F) | (V << 4); Sync(); break; + case 0xD000: reg[4] = (reg[4] & 0xF0) | (V & 0x0F); Sync(); break; + case 0xD001: reg[4] = (reg[4] & 0x0F) | (V << 4); Sync(); break; + case 0xD002: reg[5] = (reg[5] & 0xF0) | (V & 0x0F); Sync(); break; + case 0xD003: reg[5] = (reg[5] & 0x0F) | (V << 4); Sync(); break; + case 0xE000: reg[6] = (reg[6] & 0xF0) | (V & 0x0F); Sync(); break; + case 0xE001: reg[6] = (reg[6] & 0x0F) | (V << 4); Sync(); break; + case 0xE002: reg[7] = (reg[7] & 0xF0) | (V & 0x0F); Sync(); break; + case 0xE003: reg[7] = (reg[7] & 0x0F) | (V << 4); Sync(); break; + } +} + +static void UNLKS7057Power(void) { + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, UNLKS7057Write); +} + +static void UNLKS7057Reset(void) { + Sync(); +} + +void UNLKS7057_Init(CartInfo *info) { + info->Power = UNLKS7057Power; + info->Reset = UNLKS7057Reset; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/SA-9602B.c b/src/boards/SA-9602B.c new file mode 100644 index 0000000..a6a19bb --- /dev/null +++ b/src/boards/SA-9602B.c @@ -0,0 +1,61 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static void SA9602BPW(uint32 A, uint8 V) { + setprg8r(EXPREGS[1], A, V & 0x3F); + if (MMC3_cmd & 0x40) + setprg8r(0, 0x8000, ~(1)); + else + setprg8r(0, 0xc000, ~(1)); + setprg8r(0, 0xe000, ~(0)); +} + +static DECLFW(SA9602BWrite) { + switch (A & 0xe001) { + case 0x8000: EXPREGS[0] = V; break; + case 0x8001: + if ((EXPREGS[0] & 7) < 6) { + EXPREGS[1] = V >> 6; + FixMMC3PRG(MMC3_cmd); + } + break; + } + MMC3_CMDWrite(A, V); +} + +static void SA9602BPower(void) { + EXPREGS[0] = EXPREGS[1] = 0; + GenMMC3Power(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xBFFF, SA9602BWrite); +} + +void SA9602B_Init(CartInfo *info) { + GenMMC3_Init(info, 512, 0, 0, 0); + pwrap = SA9602BPW; + mmc3opts |= 2; + info->SaveGame[0] = UNIFchrrama; + info->SaveGameLen[0] = 32 * 1024; + info->Power = SA9602BPower; + AddExState(EXPREGS, 2, 0, "EXPR"); +} diff --git a/src/boards/__dummy_mapper.c b/src/boards/__dummy_mapper.c new file mode 100644 index 0000000..70793ef --- /dev/null +++ b/src/boards/__dummy_mapper.c @@ -0,0 +1,99 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[8]; +static uint8 IRQa; +static int16 IRQCount, IRQLatch; +/* +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; +static uint8 *CHRRAM = NULL; +static uint32 CHRRAMSIZE; +*/ + +static SFORMAT StateRegs[] = +{ + { reg, 8, "REGS" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 2, "IRQC" }, + { &IRQLatch, 2, "IRQL" }, + { 0 } +}; + +static void Sync(void) { +} + +static DECLFW(MNNNWrite) { +} + +static void MNNNPower(void) { +// SetReadHandler(0x6000, 0x7fff, CartBR); +// SetWriteHandler(0x6000, 0x7fff, CartBW); + 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() { + 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); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); +*/ +/* + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } +*/ + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/__serial.c b/src/boards/__serial.c new file mode 100644 index 0000000..09c858f --- /dev/null +++ b/src/boards/__serial.c @@ -0,0 +1,150 @@ +#include "__serial.h" + +#if defined(_WIN32) && !defined(_XBOX) + +HANDLE SerialPort = NULL; // Handle of SerialPort itself. + +BOOL SerialOpen(int port, int baud) { + HANDLE Comport; + DCB myDCB; + COMMTIMEOUTS CTout; + char str[100]; + + if (port > 9) + sprintf(str, "\\\\.\\COM%d", port); + else + sprintf(str, "COM%d", port); + + // Open the serial port + if ((Comport = CreateFile(str, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE) + return FALSE; + + // Configure Serial port (Setup Comm) + + // Buffer sizes + if (!SetupComm(Comport, 128, 128)) + return FALSE; + + // Setup DCB using current values + if (!GetCommState(Comport, &myDCB)) + return FALSE; + + myDCB.fInX = FALSE; // Turn off xon/xoff handler + myDCB.fOutX = FALSE; + myDCB.fOutxDsrFlow = FALSE; + myDCB.fOutxCtsFlow = FALSE; // no hardware flow control. + myDCB.BaudRate = baud; + myDCB.DCBlength = sizeof(DCB); + myDCB.fBinary = 1; + myDCB.fParity = 0; + myDCB.fDtrControl = DTR_CONTROL_DISABLE; + myDCB.fDsrSensitivity = 0; + myDCB.fTXContinueOnXoff = 1; + myDCB.fNull = 0; + myDCB.fRtsControl = RTS_CONTROL_DISABLE; + myDCB.fDummy2 = 0; + myDCB.wReserved = 0; + myDCB.Parity = NOPARITY; + myDCB.StopBits = ONESTOPBIT; + myDCB.wReserved1 = 0; + myDCB.ByteSize = 8; + + if (!SetCommState(Comport, &myDCB)) + return FALSE; + + // Set timeouts + CTout.ReadIntervalTimeout = 0xffffffff; + CTout.ReadTotalTimeoutMultiplier = 0; + CTout.ReadTotalTimeoutConstant = 0; + CTout.WriteTotalTimeoutMultiplier = 0; + CTout.WriteTotalTimeoutConstant = 5000; // don't hang if CTS is locked, for example + + SetCommTimeouts(Comport, &CTout); + EscapeCommFunction(Comport, SETDTR); + PurgeComm(Comport, PURGE_TXCLEAR | PURGE_RXCLEAR); + + SerialPort = Comport; + + return TRUE; +} + +void SerialClose(void) { + if (SerialPort == NULL) return; + + PurgeComm(SerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR); + CloseHandle(SerialPort); + + SerialPort = NULL; +} + +BOOL SerialSendChar(int c) { + DWORD cr; + if (WriteFile(SerialPort, &c, 1, (LPDWORD)&cr, NULL) && cr) + return TRUE; + else + return FALSE; +} + +int SerialIsOpen(void) { + return(SerialPort != NULL); +} + +int SerialGetChar(void) { + uint8 ch; + DWORD cr; + if (SerialPort != NULL) { + if (ReadFile(SerialPort, &ch, 1, (LPDWORD)&cr, NULL) && cr) + return (int)ch; + } + return EOF; +} + +void SendCmd(uint8 *cmd, int size) { + int i; + for (i = 0; i < size; i++) { + SerialSendChar(cmd[i]); + } +} + +int ReadResp(uint8 *resp, int size) { + int i = 0, sum = 0, data; + while (i < size) { + while ((data = SerialGetChar()) == EOF) { + } + resp[i] = data & 0xff; + sum += (data & 0xff); + i++; + } + return sum; +} +#else + +/* code is not portable, so make stubs for now */ + +BOOL SerialOpen(int port, int baud) { + return FALSE; +} + +void SerialClose(void) { +} + +BOOL SerialSendChar(int c) { + return FALSE; +} + +int SerialIsOpen(void) { + return FALSE; +} + +int SerialGetChar(void) { + return EOF; +} + +void SendCmd(uint8 *cmd, int size) { +} + +int ReadResp(uint8 *resp, int size) { + return 0; +} + +#endif diff --git a/src/boards/__serial.h b/src/boards/__serial.h new file mode 100644 index 0000000..b022a6d --- /dev/null +++ b/src/boards/__serial.h @@ -0,0 +1,36 @@ +#ifndef __SERIAL_H +#define __SERIAL_H + +#include + +#ifdef _WIN32 && !defined(_XBOX) +#include +#else +#define BOOL int + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#endif + +#include "../fceu-types.h" + +void SendCmd(uint8 *cmd, int size); +int ReadResp(uint8 *resp, int size); + +#define SEND(cmd) SendCmd((uint8*)&cmd[0], sizeof(cmd)) +#define GET(buf, size) ReadResp((uint8*)&buf, size) +#define SENDGET(cmd, buf, size) SEND(cmd); GET(buf, size) + +BOOL SerialOpen(int port, int baud); +void SerialClose(void); +BOOL SerialSendChar(int c); +int SerialIsOpen(void); +int SerialGetChar(void); + +#endif diff --git a/src/boards/a9746.c b/src/boards/a9746.c new file mode 100644 index 0000000..321ac8a --- /dev/null +++ b/src/boards/a9746.c @@ -0,0 +1,75 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static DECLFW(UNLA9746Write) { +// FCEU_printf("write raw %04x:%02x\n",A,V); + switch (A & 0xE003) { + case 0x8000: EXPREGS[1] = V; EXPREGS[0] = 0; break; + case 0x8002: EXPREGS[0] = V; EXPREGS[1] = 0; break; + case 0x8001: + { + uint8 bits_rev = ((V & 0x20) >> 5) | ((V & 0x10) >> 3) | ((V & 0x08) >> 1) | ((V & 0x04) << 1); + switch (EXPREGS[0]) { + case 0x26: setprg8(0x8000, bits_rev); break; + case 0x25: setprg8(0xA000, bits_rev); break; + case 0x24: setprg8(0xC000, bits_rev); break; + case 0x23: setprg8(0xE000, bits_rev); break; + } + switch (EXPREGS[1]) { + case 0x0a: + case 0x08: EXPREGS[2] = (V << 4); break; + case 0x09: setchr1(0x0000, EXPREGS[2] | (V >> 1)); break; + case 0x0b: setchr1(0x0400, EXPREGS[2] | (V >> 1) | 1); break; + case 0x0c: + case 0x0e: EXPREGS[2] = (V << 4); break; + case 0x0d: setchr1(0x0800, EXPREGS[2] | (V >> 1)); break; + case 0x0f: setchr1(0x0c00, EXPREGS[2] | (V >> 1) | 1); break; + case 0x10: + case 0x12: EXPREGS[2] = (V << 4); break; + case 0x11: setchr1(0x1000, EXPREGS[2] | (V >> 1)); break; + case 0x14: + case 0x16: EXPREGS[2] = (V << 4); break; + case 0x15: setchr1(0x1400, EXPREGS[2] | (V >> 1)); break; + case 0x18: + case 0x1a: EXPREGS[2] = (V << 4); break; + case 0x19: setchr1(0x1800, EXPREGS[2] | (V >> 1)); break; + case 0x1c: + case 0x1e: EXPREGS[2] = (V << 4); break; + case 0x1d: setchr1(0x1c00, EXPREGS[2] | (V >> 1)); break; + } + } + break; + } +} + +static void UNLA9746Power(void) { + GenMMC3Power(); + SetWriteHandler(0x8000, 0xbfff, UNLA9746Write); +} + +void UNLA9746_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 256, 0, 0); + info->Power = UNLA9746Power; + AddExState(EXPREGS, 6, 0, "EXPR"); +} + diff --git a/src/boards/ac-08.c b/src/boards/ac-08.c new file mode 100644 index 0000000..154fe5f --- /dev/null +++ b/src/boards/ac-08.c @@ -0,0 +1,71 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg, mirr; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REG" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, reg); + setprg32r(1, 0x8000, 0); + setchr8(0); + setmirror(mirr); +} + +static DECLFW(AC08Mirr) { + mirr = ((V & 8) >> 3) ^ 1; + Sync(); +} + +static DECLFW(AC08Write) { + if (A == 0x8001) // Green Berret bank switching is only 100x xxxx xxxx xxx1 mask + reg = (V >> 1) & 0xf; + else + reg = V & 0xf; // Sad But True, 2-in-1 mapper, Green Berret need value shifted left one byte, Castlevania doesn't + Sync(); +} + +static void AC08Power(void) { + reg = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x4025, 0x4025, AC08Mirr); + SetWriteHandler(0x8000, 0xFFFF, AC08Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void AC08_Init(CartInfo *info) { + info->Power = AC08Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/addrlatch.c b/src/boards/addrlatch.c new file mode 100644 index 0000000..299f6e4 --- /dev/null +++ b/src/boards/addrlatch.c @@ -0,0 +1,505 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint16 latche, latcheinit; +static uint16 addrreg0, addrreg1; +static uint8 dipswitch; +static void (*WSync)(void); +static readfunc defread; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static DECLFW(LatchWrite) { + latche = A; + WSync(); +} + +static void LatchReset(void) { + latche = latcheinit; + WSync(); +} + +static void LatchPower(void) { + latche = latcheinit; + WSync(); + if (WRAM) { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + } else + SetReadHandler(0x6000, 0xFFFF, defread); + SetWriteHandler(addrreg0, addrreg1, LatchWrite); +} + +static void LatchClose(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + WSync(); +} + +static void Latch_Init(CartInfo *info, void (*proc)(void), readfunc func, uint16 linit, uint16 adr0, uint16 adr1, uint8 wram) { + latcheinit = linit; + addrreg0 = adr0; + addrreg1 = adr1; + WSync = proc; + if (func != NULL) + defread = func; + else + defread = CartBROB; + info->Power = LatchPower; + info->Reset = LatchReset; + info->Close = LatchClose; + if (wram) { + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } + GameStateRestore = StateRestore; + AddExState(&latche, 2, 0, "LATC"); +} + +//------------------ BMCD1038 --------------------------- + +static void BMCD1038Sync(void) { + if (latche & 0x80) { + setprg16(0x8000, (latche & 0x70) >> 4); + setprg16(0xC000, (latche & 0x70) >> 4); + } else + setprg32(0x8000, (latche & 0x60) >> 5); + setchr8(latche & 7); + setmirror(((latche & 8) >> 3) ^ 1); +} + +static DECLFR(BMCD1038Read) { + if (latche & 0x100) + return dipswitch; + else + return CartBR(A); +} + +static void BMCD1038Reset(void) { + dipswitch++; + dipswitch &= 3; +} + +void BMCD1038_Init(CartInfo *info) { + Latch_Init(info, BMCD1038Sync, BMCD1038Read, 0x0000, 0x8000, 0xFFFF, 0); + info->Reset = BMCD1038Reset; + AddExState(&dipswitch, 1, 0, "DIPSW"); +} + +//------------------ UNL43272 --------------------------- +// mapper much complex, including 16K bankswitching +static void UNL43272Sync(void) { + if ((latche & 0x81) == 0x81) { + setprg32(0x8000, (latche & 0x38) >> 3); + } else + FCEU_printf("unrecognized command %04!\n", latche); + setchr8(0); + setmirror(0); +} + +static DECLFR(UNL43272Read) { + if (latche & 0x400) + return CartBR(A & 0xFE); + else + return CartBR(A); +} + +static void UNL43272Reset(void) { + latche = 0; + UNL43272Sync(); +} + +void UNL43272_Init(CartInfo *info) { + Latch_Init(info, UNL43272Sync, UNL43272Read, 0x0081, 0x8000, 0xFFFF, 0); + info->Reset = UNL43272Reset; + AddExState(&dipswitch, 1, 0, "DIPSW"); +} + +//------------------ Map 058 --------------------------- + +static void BMCGK192Sync(void) { + if (latche & 0x40) { + setprg16(0x8000, latche & 7); + setprg16(0xC000, latche & 7); + } else + setprg32(0x8000, (latche >> 1) & 3); + setchr8((latche >> 3) & 7); + setmirror(((latche & 0x80) >> 7) ^ 1); +} + +void BMCGK192_Init(CartInfo *info) { + Latch_Init(info, BMCGK192Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} + +//------------------ Map 059 --------------------------- +// One more forgotten mapper +static void M59Sync(void) { + setprg32(0x8000, (latche >> 4) & 7); + setchr8(latche & 0x7); + setmirror((latche >> 3) & 1); +} + +static DECLFR(M59Read) { + if (latche & 0x100) + return 0; + else + return CartBR(A); +} + +void Mapper59_Init(CartInfo *info) { + Latch_Init(info, M59Sync, M59Read, 0x0000, 0x8000, 0xFFFF, 0); +} + +//------------------ Map 061 --------------------------- +static void M61Sync(void) { + if (((latche & 0x10) << 1) ^ (latche & 0x20)) { + setprg16(0x8000, ((latche & 0xF) << 1) | (((latche & 0x20) >> 4))); + setprg16(0xC000, ((latche & 0xF) << 1) | (((latche & 0x20) >> 4))); + } else + setprg32(0x8000, latche & 0xF); + setchr8(0); + setmirror(((latche >> 7) & 1) ^ 1); +} + +void Mapper61_Init(CartInfo *info) { + Latch_Init(info, M61Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} + +//------------------ Map 092 --------------------------- +// Another two-in-one mapper, two Jaleco carts uses similar +// hardware, but with different wiring. +// Original code provided by LULU +// Additionally, PCB contains DSP extra sound chip, used for voice samples (unemulated) + +static void M92Sync(void) { + uint8 reg = latche & 0xF0; + setprg16(0x8000, 0); + if (latche >= 0x9000) { + switch (reg) { + case 0xD0: setprg16(0xc000, latche & 15); break; + case 0xE0: setchr8(latche & 15); break; + } + } else { + switch (reg) { + case 0xB0: setprg16(0xc000, latche & 15); break; + case 0x70: setchr8(latche & 15); break; + } + } +} + +void Mapper92_Init(CartInfo *info) { + Latch_Init(info, M92Sync, NULL, 0x80B0, 0x8000, 0xFFFF, 0); +} + +//------------------ Map 200 --------------------------- + +static void M200Sync(void) { + setprg16(0x8000, latche & 7); + setprg16(0xC000, latche & 7); + setchr8(latche & 7); + setmirror((latche & 8) >> 3); +} + +void Mapper200_Init(CartInfo *info) { + Latch_Init(info, M200Sync, NULL, 0xFFFF, 0x8000, 0xFFFF, 0); +} + +//------------------ Map 201 --------------------------- + +static void M201Sync(void) { + if (latche & 8) { + setprg32(0x8000, latche & 3); + setchr8(latche & 3); + } else { + setprg32(0x8000, 0); + setchr8(0); + } +} + +void Mapper201_Init(CartInfo *info) { + Latch_Init(info, M201Sync, NULL, 0xFFFF, 0x8000, 0xFFFF, 0); +} + +//------------------ Map 202 --------------------------- + +static void M202Sync(void) { + // According to more carefull hardware tests and PCB study + int32 mirror = latche & 1; + int32 bank = (latche >> 1) & 0x7; + int32 select = (mirror & (bank >> 2)); + setprg16(0x8000, select ? (bank & 6) | 0 : bank); + setprg16(0xc000, select ? (bank & 6) | 1 : bank); + setmirror(mirror ^ 1); + setchr8(bank); +} + +void Mapper202_Init(CartInfo *info) { + Latch_Init(info, M202Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} + +//------------------ Map 204 --------------------------- + +static void M204Sync(void) { + int32 tmp2 = latche & 0x6; + int32 tmp1 = tmp2 + ((tmp2 == 0x6) ? 0 : (latche & 1)); + setprg16(0x8000, tmp1); + setprg16(0xc000, tmp2 + ((tmp2 == 0x6) ? 1 : (latche & 1))); + setchr8(tmp1); + setmirror(((latche >> 4) & 1) ^ 1); +} + +void Mapper204_Init(CartInfo *info) { + Latch_Init(info, M204Sync, NULL, 0xFFFF, 0x8000, 0xFFFF, 0); +} + +//------------------ Map 212 --------------------------- + +static DECLFR(M212Read) { + uint8 ret = CartBROB(A); + if ((A & 0xE010) == 0x6000) + ret |= 0x80; + return ret; +} + +static void M212Sync(void) { + if (latche & 0x4000) { + setprg32(0x8000, (latche >> 1) & 3); + } else { + setprg16(0x8000, latche & 7); + setprg16(0xC000, latche & 7); + } + setchr8(latche & 7); + setmirror(((latche >> 3) & 1) ^ 1); +} + +void Mapper212_Init(CartInfo *info) { + Latch_Init(info, M212Sync, M212Read, 0xFFFF, 0x8000, 0xFFFF, 0); +} + +//------------------ Map 213 --------------------------- + +static void M213Sync(void) { + setprg32(0x8000, (latche >> 1) & 3); + setchr8((latche >> 3) & 7); +} + +void Mapper213_Init(CartInfo *info) { + Latch_Init(info, M213Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} + +//------------------ Map 214 --------------------------- + +static void M214Sync(void) { + setprg16(0x8000, (latche >> 2) & 3); + setprg16(0xC000, (latche >> 2) & 3); + setchr8(latche & 3); +} + +void Mapper214_Init(CartInfo *info) { + Latch_Init(info, M214Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} + +//------------------ Map 217 --------------------------- + +static void M217Sync(void) { + setprg32(0x8000, (latche >> 2) & 3); + setchr8(latche & 7); +} + +void Mapper217_Init(CartInfo *info) { + Latch_Init(info, M217Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} + +//------------------ Map 227 --------------------------- + +static void M227Sync(void) { + uint32 S = latche & 1; + uint32 p = ((latche >> 2) & 0x1F) + ((latche & 0x100) >> 3); + uint32 L = (latche >> 9) & 1; + + if ((latche >> 7) & 1) { + if (S) { + setprg32(0x8000, p >> 1); + } else { + setprg16(0x8000, p); + setprg16(0xC000, p); + } + } else { + if (S) { + if (L) { + setprg16(0x8000, p & 0x3E); + setprg16(0xC000, p | 7); + } else { + setprg16(0x8000, p & 0x3E); + setprg16(0xC000, p & 0x38); + } + } else { + if (L) { + setprg16(0x8000, p); + setprg16(0xC000, p | 7); + } else { + setprg16(0x8000, p); + setprg16(0xC000, p & 0x38); + } + } + } + + setmirror(((latche >> 1) & 1) ^ 1); + setchr8(0); + setprg8r(0x10, 0x6000, 0); +} + +void Mapper227_Init(CartInfo *info) { + Latch_Init(info, M227Sync, NULL, 0x0000, 0x8000, 0xFFFF, 1); +} + +//------------------ Map 229 --------------------------- + +static void M229Sync(void) { + setchr8(latche); + if (!(latche & 0x1e)) + setprg32(0x8000, 0); + else { + setprg16(0x8000, latche & 0x1F); + setprg16(0xC000, latche & 0x1F); + } + setmirror(((latche >> 5) & 1) ^ 1); +} + +void Mapper229_Init(CartInfo *info) { + Latch_Init(info, M229Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} + +//------------------ Map 231 --------------------------- + +static void M231Sync(void) { + setchr8(0); + if (latche & 0x20) + setprg32(0x8000, (latche >> 1) & 0x0F); + else { + setprg16(0x8000, latche & 0x1E); + setprg16(0xC000, latche & 0x1E); + } + setmirror(((latche >> 7) & 1) ^ 1); +} + +void Mapper231_Init(CartInfo *info) { + Latch_Init(info, M231Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} + +//------------------ Map 242 --------------------------- + +static void M242Sync(void) { + setchr8(0); + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, (latche >> 3) & 0xf); + setmirror(((latche >> 1) & 1) ^ 1); +} + +void Mapper242_Init(CartInfo *info) { + Latch_Init(info, M242Sync, NULL, 0x0000, 0x8000, 0xFFFF, 1); +} + +//------------------ 190in1 --------------------------- + +static void BMC190in1Sync(void) { + setprg16(0x8000, (latche >> 2) & 7); + setprg16(0xC000, (latche >> 2) & 7); + setchr8((latche >> 2) & 7); + setmirror((latche & 1) ^ 1); +} + +void BMC190in1_Init(CartInfo *info) { + Latch_Init(info, BMC190in1Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} + +//-------------- BMC810544-C-A1 ------------------------ + +static void BMC810544CA1Sync(void) { + uint32 bank = latche >> 7; + if (latche & 0x40) + setprg32(0x8000, bank); + else { + setprg16(0x8000, (bank << 1) | ((latche >> 5) & 1)); + setprg16(0xC000, (bank << 1) | ((latche >> 5) & 1)); + } + setchr8(latche & 0x0f); + setmirror(((latche >> 4) & 1) ^ 1); +} + +void BMC810544CA1_Init(CartInfo *info) { + Latch_Init(info, BMC810544CA1Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} + +//-------------- BMCNTD-03 ------------------------ + +static void BMCNTD03Sync(void) { + // 1PPP Pmcc spxx xccc + // 1000 0000 0000 0000 v + // 1001 1100 0000 0100 h + // 1011 1010 1100 0100 + uint32 prg = ((latche >> 10) & 0x1e); + uint32 chr = ((latche & 0x0300) >> 5) | (latche & 7); + if (latche & 0x80) { + setprg16(0x8000, prg | ((latche >> 6) & 1)); + setprg16(0xC000, prg | ((latche >> 6) & 1)); + } else + setprg32(0x8000, prg >> 1); + setchr8(chr); + setmirror(((latche >> 10) & 1) ^ 1); +} + +void BMCNTD03_Init(CartInfo *info) { + Latch_Init(info, BMCNTD03Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} + +//-------------- BMCG-146 ------------------------ + +static void BMCG146Sync(void) { + setchr8(0); + if (latche & 0x800) { // UNROM mode + setprg16(0x8000, (latche & 0x1F) | (latche & ((latche & 0x40) >> 6))); + setprg16(0xC000, (latche & 0x18) | 7); + } else { + if (latche & 0x40) { // 16K mode + setprg16(0x8000, latche & 0x1F); + setprg16(0xC000, latche & 0x1F); + } else { + setprg32(0x8000, (latche >> 1) & 0x0F); + } + } + setmirror(((latche & 0x80) >> 7) ^ 1); +} + +void BMCG146_Init(CartInfo *info) { + Latch_Init(info, BMCG146Sync, NULL, 0x0000, 0x8000, 0xFFFF, 0); +} diff --git a/src/boards/ax5705.c b/src/boards/ax5705.c new file mode 100644 index 0000000..780ea4b --- /dev/null +++ b/src/boards/ax5705.c @@ -0,0 +1,111 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Super Bros. Pocker Mali (VRC4 mapper) + */ + +#include "mapinc.h" + +static uint8 IRQCount; //, IRQPre; +static uint8 IRQa; +static uint8 prg_reg[2]; +static uint8 chr_reg[8]; +static uint8 mirr; + +static SFORMAT StateRegs[] = +{ + { &IRQCount, 1, "IRQC" }, + { &IRQa, 1, "IRQA" }, + { prg_reg, 2, "PRG" }, + { chr_reg, 8, "CHR" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +/* +static void UNLAX5705IRQ(void) { + if(IRQa) { + IRQCount++; + if(IRQCount>=238) { + X6502_IRQBegin(FCEU_IQEXT); +// IRQa=0; + } + } +}*/ + +static void Sync(void) { + setprg8(0x8000, prg_reg[0]); + setprg8(0xA000, prg_reg[1]); + setprg8(0xC000, ~1); + setprg8(0xE000, ~0); + int i; + for (i = 0; i < 8; i++) + setchr1(i << 10, chr_reg[i]); + setmirror(mirr ^ 1); +} + +static DECLFW(UNLAX5705Write) { +// if((A>=0xA008)&&(A<=0xE003)) { +// int ind=(((A>>11)-6)|(A&1))&7; +// int sar=((A&2)<<1); +// chr_reg[ind]=(chr_reg[ind]&(0xF0>>sar))|((V&0x0F)<> 2) | (V & 5); break; // EPROM dump have mixed PRG and CHR banks, data lines to mapper seems to be mixed + case 0x8008: mirr = V & 1; break; + case 0xA000: prg_reg[1] = ((V & 2) << 2) | ((V & 8) >> 2) | (V & 5); break; + case 0xA008: chr_reg[0] = (chr_reg[0] & 0xF0) | (V & 0x0F); break; + case 0xA009: chr_reg[0] = (chr_reg[0] & 0x0F) | ((((V & 4) >> 1) | ((V & 2) << 1) | (V & 0x09)) << 4); break; + case 0xA00A: chr_reg[1] = (chr_reg[1] & 0xF0) | (V & 0x0F); break; + case 0xA00B: chr_reg[1] = (chr_reg[1] & 0x0F) | ((((V & 4) >> 1) | ((V & 2) << 1) | (V & 0x09)) << 4); break; + case 0xC000: chr_reg[2] = (chr_reg[2] & 0xF0) | (V & 0x0F); break; + case 0xC001: chr_reg[2] = (chr_reg[2] & 0x0F) | ((((V & 4) >> 1) | ((V & 2) << 1) | (V & 0x09)) << 4); break; + case 0xC002: chr_reg[3] = (chr_reg[3] & 0xF0) | (V & 0x0F); break; + case 0xC003: chr_reg[3] = (chr_reg[3] & 0x0F) | ((((V & 4) >> 1) | ((V & 2) << 1) | (V & 0x09)) << 4); break; + case 0xC008: chr_reg[4] = (chr_reg[4] & 0xF0) | (V & 0x0F); break; + case 0xC009: chr_reg[4] = (chr_reg[4] & 0x0F) | ((((V & 4) >> 1) | ((V & 2) << 1) | (V & 0x09)) << 4); break; + case 0xC00A: chr_reg[5] = (chr_reg[5] & 0xF0) | (V & 0x0F); break; + case 0xC00B: chr_reg[5] = (chr_reg[5] & 0x0F) | ((((V & 4) >> 1) | ((V & 2) << 1) | (V & 0x09)) << 4); break; + case 0xE000: chr_reg[6] = (chr_reg[6] & 0xF0) | (V & 0x0F); break; + case 0xE001: chr_reg[6] = (chr_reg[6] & 0x0F) | ((((V & 4) >> 1) | ((V & 2) << 1) | (V & 0x09)) << 4); break; + case 0xE002: chr_reg[7] = (chr_reg[7] & 0xF0) | (V & 0x0F); break; + case 0xE003: chr_reg[7] = (chr_reg[7] & 0x0F) | ((((V & 4) >> 1) | ((V & 2) << 1) | (V & 0x09)) << 4); break; +// case 0x800A: X6502_IRQEnd(FCEU_IQEXT); IRQa=0; break; +// case 0xE00B: X6502_IRQEnd(FCEU_IQEXT); IRQa=IRQCount=V; /*if(scanline<240) IRQCount-=8; else IRQCount+=4;*/ break; + } + Sync(); +} + +static void UNLAX5705Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, UNLAX5705Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLAX5705_Init(CartInfo *info) { + info->Power = UNLAX5705Power; +// GameHBIRQHook=UNLAX5705IRQ; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/bandai.c b/src/boards/bandai.c new file mode 100644 index 0000000..327add0 --- /dev/null +++ b/src/boards/bandai.c @@ -0,0 +1,463 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Bandai mappers + * + */ + +#include "mapinc.h" + +static uint8 reg[16], is153, x24c02; +static uint8 IRQa; +static int16 IRQCount, IRQLatch; + +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { reg, 16, "REGS" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 2, "IRQC" }, + { &IRQLatch, 2, "IRQL" }, // need for Famicom Jump II - Saikyou no 7 Nin (J) [!] + { 0 } +}; + +// x24C0x interface + +#define X24C0X_STANDBY 0 +#define X24C0X_ADDRESS 1 +#define X24C0X_WORD 2 +#define X24C0X_READ 3 +#define X24C0X_WRITE 4 + +static uint8 x24c0x_data[256], x24c0x_state; +static uint8 x24c0x_addr, x24c0x_word, x24c0x_latch, x24c0x_bitcount; +static uint8 x24c0x_sda, x24c0x_scl, x24c0x_out, x24c0x_oe; + +static SFORMAT x24c0xStateRegs[] = +{ + { &x24c0x_addr, 1, "ADDR" }, + { &x24c0x_word, 1, "WORD" }, + { &x24c0x_latch, 1, "LATC" }, + { &x24c0x_bitcount, 1, "BITC" }, + { &x24c0x_sda, 1, "SDA" }, + { &x24c0x_scl, 1, "SCL" }, + { &x24c0x_out, 1, "OUT" }, + { &x24c0x_oe, 1, "OE" }, + { &x24c0x_state, 1, "STAT" }, + { 0 } +}; + +static void x24c0x_init() { + x24c0x_addr = x24c0x_word = x24c0x_latch = x24c0x_bitcount = x24c0x_sda = x24c0x_scl = x24c0x_oe = 0; + x24c0x_state = X24C0X_STANDBY; +} + +static void x24c0x_write(uint8 data) { + uint8 sda = (data >> 6) & 1; + uint8 scl = (data >> 5) & 1; + x24c0x_oe = (data >> 7); + + if(x24c0x_scl && scl) { + if(x24c0x_sda && !sda) { // START + x24c0x_state = X24C0X_ADDRESS; + x24c0x_bitcount = 0; + x24c0x_addr = 0; + } else if(!x24c0x_sda && sda) { //STOP + x24c0x_state = X24C0X_STANDBY; + } + } else if(!x24c0x_scl && scl) { // RISING EDGE + switch(x24c0x_state) { + case X24C0X_ADDRESS: + if(x24c0x_bitcount < 7) { + x24c0x_addr <<= 1; + x24c0x_addr |= sda; + } else { + if(!x24c02) // X24C01 mode + x24c0x_word = x24c0x_addr; + if(sda) { // READ COMMAND + x24c0x_state = X24C0X_READ; + } else { // WRITE COMMAND + if(x24c02) // X24C02 mode + x24c0x_state = X24C0X_WORD; + else + x24c0x_state = X24C0X_WRITE; + } + } + x24c0x_bitcount++; + break; + case X24C0X_WORD: + if(x24c0x_bitcount == 8) { // ACK + x24c0x_word = 0; + x24c0x_out = 0; + } else { // WORD ADDRESS INPUT + x24c0x_word <<= 1; + x24c0x_word |= sda; + if(x24c0x_bitcount == 16) { // END OF ADDRESS INPUT + x24c0x_bitcount = 7; + x24c0x_state = X24C0X_WRITE; + } + } + x24c0x_bitcount++; + break; + case X24C0X_READ: + if (x24c0x_bitcount == 8) { // ACK + x24c0x_out = 0; + x24c0x_latch = x24c0x_data[x24c0x_word]; + x24c0x_bitcount = 0; + } else { // REAL OUTPUT + x24c0x_out = x24c0x_latch >> 7; + x24c0x_latch <<= 1; + x24c0x_bitcount++; + if(x24c0x_bitcount == 8) { + x24c0x_word++; + x24c0x_word &= 0xff; + } + } + break; + case X24C0X_WRITE: + if (x24c0x_bitcount == 8) { // ACK + x24c0x_out = 0; + x24c0x_latch = 0; + x24c0x_bitcount = 0; + } else { // REAL INPUT + x24c0x_latch <<= 1; + x24c0x_latch |= sda; + x24c0x_bitcount++; + if(x24c0x_bitcount == 8) { + x24c0x_data[x24c0x_word] = x24c0x_latch; + x24c0x_word++; + x24c0x_word &= 0xff; + } + } + break; + } + } + + x24c0x_sda = sda; + x24c0x_scl = scl; +} + +static uint8 x24c0x_read() { + return x24c0x_out << 4; +} + +// + +static void Sync(void) { + if (is153) { + int base = (reg[0] & 1) << 4; + setchr8(0); + setprg16(0x8000, (reg[8] & 0x0F) | base); + setprg16(0xC000, 0x0F | base); + } else { + int i; + for (i = 0; i < 8; i++) setchr1(i << 10, reg[i]); + setprg16(0x8000, reg[8]); + setprg16(0xC000, ~0); + } + switch (reg[9] & 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 DECLFW(BandaiWrite) { + A &= 0x0F; + if (A < 0x0A) { + reg[A & 0x0F] = V; + Sync(); + } else + switch (A) { + case 0x0A: X6502_IRQEnd(FCEU_IQEXT); IRQa = V & 1; IRQCount = IRQLatch; break; + case 0x0B: IRQLatch &= 0xFF00; IRQLatch |= V; break; + case 0x0C: IRQLatch &= 0xFF; IRQLatch |= V << 8; break; + case 0x0D: x24c0x_write(V); break; + } +} + +static DECLFR(BandaiRead) { + return (X.DB & 0xEF) | x24c0x_read(); +} + +static void FP_FASTAPASS(1) BandaiIRQHook(int a) { + if (IRQa) { + IRQCount -= a; + if (IRQCount < 0) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + IRQCount = -1; + } + } +} + +static void BandaiPower(void) { + IRQa = 0; + x24c0x_init(); + Sync(); + SetReadHandler(0x6000, 0x7FFF, BandaiRead); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0xFFFF, BandaiWrite); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper16_Init(CartInfo *info) { + x24c02 = 1; + is153 = 0; + info->Power = BandaiPower; + MapIRQHook = BandaiIRQHook; + + info->battery = 1; + info->SaveGame[0] = x24c0x_data; + info->SaveGameLen[0] = 256; + AddExState(x24c0x_data, 256, 0, "DATA"); + + GameStateRestore = StateRestore; + AddExState(&x24c0xStateRegs, ~0, 0, 0); + AddExState(&StateRegs, ~0, 0, 0); +} + +void Mapper159_Init(CartInfo *info) { + x24c02 = 0; + is153 = 0; + info->Power = BandaiPower; + MapIRQHook = BandaiIRQHook; + + info->battery = 1; + info->SaveGame[0] = x24c0x_data; + info->SaveGameLen[0] = 128; + AddExState(x24c0x_data, 128, 0, "DATA"); + + GameStateRestore = StateRestore; + AddExState(&x24c0xStateRegs, ~0, 0, 0); + AddExState(&StateRegs, ~0, 0, 0); +} + +// 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 M153Power(void) { + Sync(); + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, BandaiWrite); +} + + +static void M153Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +void Mapper153_Init(CartInfo *info) { + is153 = 1; + info->Power = M153Power; + info->Close = M153Close; + MapIRQHook = BandaiIRQHook; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +// Datach Barcode Battler + +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; + 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(BarcodeRead) { + return BarcodeOut; +} + +static void M157Power(void) { + IRQa = 0; + BarcodeData[0] = 0xFF; + BarcodeReadPos = 0; + BarcodeOut = 0; + BarcodeCycleCount = 0; + + Sync(); + + SetWriteHandler(0x6000, 0xFFFF, BandaiWrite); + SetReadHandler(0x6000, 0x7FFF, BarcodeRead); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +void Mapper157_Init(CartInfo *info) { + is153 = 1; + info->Power = M157Power; + MapIRQHook = BarcodeIRQHook; + + GameInfo->cspecial = SIS_DATACH; + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/bb.c b/src/boards/bb.c new file mode 100644 index 0000000..53554a5 --- /dev/null +++ b/src/boards/bb.c @@ -0,0 +1,68 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + * Bubble Bobble CHR-ROM version + * + */ + +#include "mapinc.h" + +static uint8 reg, chr; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REG" }, + { &chr, 1, "CHR" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, reg & 3); + setprg32(0x8000, ~0); + setchr8(chr & 3); +} + +static DECLFW(UNLBBWrite) { + if ((A & 0x9000) == 0x8000) + reg = chr = V; + else + chr = V & 1; // hacky hacky, ProWres simplified FDS conversion 2-in-1 mapper + Sync(); +} + +static void UNLBBPower(void) { + chr = 0; + reg = ~0; + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, UNLBBWrite); +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLBB_Init(CartInfo *info) { + info->Power = UNLBBPower; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/bmc13in1jy110.c b/src/boards/bmc13in1jy110.c new file mode 100644 index 0000000..f419045 --- /dev/null +++ b/src/boards/bmc13in1jy110.c @@ -0,0 +1,97 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * BMC 42-in-1 "reset switch" type + */ + +#include "mapinc.h" + +static uint8 bank_mode; +static uint8 bank_value; +static uint8 prgb[4]; +static SFORMAT StateRegs[] = +{ + { &bank_mode, 1, "BNM" }, + { &bank_value, 1, "BMV" }, + { prgb, 4, "PRGB" }, + { 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/src/boards/bmc42in1r.c b/src/boards/bmc42in1r.c new file mode 100644 index 0000000..036997d --- /dev/null +++ b/src/boards/bmc42in1r.c @@ -0,0 +1,86 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2005 CaH4e3 + * Copyright (C) 2009 qeed + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * BMC 42-in-1 "reset switch" + "select switch" + * + */ + +#include "mapinc.h" + +static uint8 isresetbased = 0; +static uint8 latche[2], reset; +static SFORMAT StateRegs[] = +{ + { &reset, 1, "RST" }, + { latche, 2, "LATC" }, + { 0 } +}; + +static void Sync(void) { + uint8 bank; + if (isresetbased) + bank = (latche[0] & 0x1f) | (reset << 5) | ((latche[1] & 1) << 6); + else + bank = (latche[0] & 0x1f) | ((latche[0] & 0x80) >> 2) | ((latche[1] & 1) << 6); + if (!(latche[0] & 0x20)) + setprg32(0x8000, bank >> 1); + else { + setprg16(0x8000, bank); + setprg16(0xC000, bank); + } + setmirror((latche[0] >> 6) & 1); + setchr8(0); +} + +static DECLFW(M226Write) { + latche[A & 1] = V; + Sync(); +} + +static void M226Power(void) { + latche[0] = latche[1] = reset = 0; + Sync(); + SetWriteHandler(0x8000, 0xFFFF, M226Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper226_Init(CartInfo *info) { + isresetbased = 0; + info->Power = M226Power; + AddExState(&StateRegs, ~0, 0, 0); + GameStateRestore = StateRestore; +} + +static void M233Reset(void) { + reset ^= 1; + Sync(); +} + +void Mapper233_Init(CartInfo *info) { + isresetbased = 1; + info->Power = M226Power; + info->Reset = M233Reset; + AddExState(&StateRegs, ~0, 0, 0); + GameStateRestore = StateRestore; +} diff --git a/src/boards/bmc64in1nr.c b/src/boards/bmc64in1nr.c new file mode 100644 index 0000000..51f7c2b --- /dev/null +++ b/src/boards/bmc64in1nr.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * BMC 42-in-1 "reset switch" type + */ + +#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/src/boards/bmc70in1.c b/src/boards/bmc70in1.c new file mode 100644 index 0000000..95c3437 --- /dev/null +++ b/src/boards/bmc70in1.c @@ -0,0 +1,121 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 is_large_banks, hw_switch; +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" }, + { &hw_switch, 1, "DPSW" }, + { &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) | hw_switch); +// else +// return CartBR((A&0xFFF0)|hw_switch); + 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 BMC70in1Reset(void) { + bank_mode = 0; + large_bank = 0; + Sync(); + hw_switch++; + hw_switch &= 0xf; +} + +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; + hw_switch = 0xd; + info->Power = BMC70in1Power; + info->Reset = BMC70in1Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +void BMC70in1B_Init(CartInfo *info) { + is_large_banks = 1; + hw_switch = 0x6; + info->Power = BMC70in1Power; + info->Reset = BMC70in1Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/bonza.c b/src/boards/bonza.c new file mode 100644 index 0000000..58f04f2 --- /dev/null +++ b/src/boards/bonza.c @@ -0,0 +1,133 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +#define CARD_EXTERNAL_INSERED 0x80 + +static uint8 prg_reg; +static uint8 chr_reg; +static SFORMAT StateRegs[] = +{ + { &prg_reg, 1, "PREG" }, + { &chr_reg, 1, "CREG" }, + { 0 } +}; + +/* + +cmd[0] = response on/off + 0x00 - on + 0x80 - off +cmd[1] = cmd + + +_GET_CHALLENGE: .BYTE 0,$B4, 0, 0,$62 + +_SELECT_FILE_1_0200: .BYTE 0,$A4, 1, 0, 2, 2, 0 +_SELECT_FILE_2_0201: .BYTE 0,$A4, 2, 0, 2, 2, 1 +_SELECT_FILE_2_0203: .BYTE 0,$A4, 2, 0, 2, 2, 3 +_SELECT_FILE_2_0204: .BYTE 0,$A4, 2, 0, 2, 2, 4 +_SELECT_FILE_2_0205: .BYTE 0,$A4, 2, 0, 2, 2, 5 +_SELECT_FILE_2_3F04: .BYTE 0,$A4, 2, 0, 2,$3F, 4 +_SELECT_FILE_2_4F00: .BYTE 0,$A4, 2, 0, 2,$4F, 0 + +_READ_BINARY_5: .BYTE 0,$B0,$85, 0, 2 +_READ_BINARY_6: .BYTE 0,$B0,$86, 0, 4 +_READ_BINARY_6_0: .BYTE 0,$B0,$86, 0,$18 +_READ_BINARY_0: .BYTE 0,$B0, 0, 2, 3 +_READ_BINARY_0_0: .BYTE 0,$B0, 0, 0, 4 +_READ_BINARY_0_1: .BYTE 0,$B0, 0, 0, $C +_READ_BINARY_0_2: .BYTE 0,$B0, 0, 0,$10 + +_UPDATE_BINARY: .BYTE 0,$D6, 0, 0, 4 +_UPDATE_BINARY_0: .BYTE 0,$D6, 0, 0,$10 + +_GET_RESPONSE: .BYTE $80,$C0, 2,$A1, 8 +_GET_RESPONSE_0: .BYTE 0,$C0, 0, 0, 2 +_GET_RESPONSE_1: .BYTE 0,$C0, 0, 0, 6 +_GET_RESPONSE_2: .BYTE 0,$C0, 0, 0, 8 +_GET_RESPONSE_3: .BYTE 0,$C0, 0, 0, $C +_GET_RESPONSE_4: .BYTE 0,$C0, 0, 0,$10 + +byte_8C0B: .BYTE $80,$30, 0, 2, $A, 0, 1 +byte_8C48: .BYTE $80,$32, 0, 1, 4 +byte_8C89: .BYTE $80,$34, 0, 0, 8, 0, 0 +byte_8D01: .BYTE $80,$36, 0, 0, $C +byte_8CA7: .BYTE $80,$38, 0, 2, 4 +byte_8BEC: .BYTE $80,$3A, 0, 3, 0 + +byte_89A0: .BYTE 0,$48, 0, 0, 6 +byte_8808: .BYTE 0,$54, 0, 0,$1C +byte_89BF: .BYTE 0,$58, 0, 0,$1C + +_MANAGE_CHANNEL: .BYTE 0,$70, 0, 0, 8 +byte_8CE5: .BYTE 0,$74, 0, 0,$12 +byte_8C29: .BYTE 0,$76, 0, 0, 8 +byte_8CC6: .BYTE 0,$78, 0, 0,$12 +*/ + +static uint8 sim0reset[0x1F] = { + 0x3B, 0xE9, 0x00, 0xFF, 0xC1, 0x10, 0x31, 0xFE, + 0x55, 0xC8, 0x10, 0x20, 0x55, 0x47, 0x4F, 0x53, + 0x56, 0x53, 0x43, 0xAD, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10 +}; + +static void Sync(void) { + setprg32(0x8000, prg_reg); + setchr8(chr_reg); +} + +static void StateRestore(int version) { + Sync(); +} + +static DECLFW(M216WriteHi) { + prg_reg = A & 1; + chr_reg = (A & 0x0E) >> 1; + Sync(); +} + +static DECLFW(M216Write5000) { +// FCEU_printf("WRITE: %04x:%04x (PC=%02x cnt=%02x)\n",A,V,X.PC,sim0bcnt); +} + +static DECLFR(M216Read5000) { +// FCEU_printf("READ: %04x PC=%04x out=%02x byte=%02x cnt=%02x bit=%02x\n",A,X.PC,sim0out,sim0byte,sim0bcnt,sim0bit); + return 0; +} + +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/src/boards/bs-5.c b/src/boards/bs-5.c new file mode 100644 index 0000000..5e2ff1f --- /dev/null +++ b/src/boards/bs-5.c @@ -0,0 +1,84 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg_prg[4]; +static uint8 reg_chr[4]; +static uint8 dip_switch; + +static SFORMAT StateRegs[] = +{ + { reg_prg, 4, "PREG" }, + { reg_chr, 4, "CREG" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, reg_prg[0]); + setprg8(0xa000, reg_prg[1]); + setprg8(0xc000, reg_prg[2]); + setprg8(0xe000, reg_prg[3]); + setchr2(0x0000, reg_chr[0]); + setchr2(0x0800, reg_chr[1]); + setchr2(0x1000, reg_chr[2]); + setchr2(0x1800, reg_chr[3]); + setmirror(MI_V); +} + +static DECLFW(MBS5Write) { + int bank_sel = (A & 0xC00) >> 10; + switch (A & 0xF000) { + case 0x8000: + reg_chr[bank_sel] = A & 0x1F; + break; + case 0xA000: + if (A & (1 << (dip_switch + 4))) + reg_prg[bank_sel] = A & 0x0F; + break; + } + Sync(); +} + +static void MBS5Reset(void) { + dip_switch++; + dip_switch &= 3; + reg_prg[0] = reg_prg[1] = reg_prg[2] = reg_prg[3] = ~0; + Sync(); +} + +static void MBS5Power(void) { + dip_switch = 0; + reg_prg[0] = reg_prg[1] = reg_prg[2] = reg_prg[3] = ~0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, MBS5Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void BMCBS5_Init(CartInfo *info) { + info->Power = MBS5Power; + info->Reset = MBS5Reset; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/cityfighter.c b/src/boards/cityfighter.c new file mode 100644 index 0000000..3214959 --- /dev/null +++ b/src/boards/cityfighter.c @@ -0,0 +1,124 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * City Fighter IV sith Sound VRC4 hacked + */ + +#include "mapinc.h" + +static int32 IRQCount; +static uint8 IRQa; +static uint8 prg_reg, prg_mode, mirr; +static uint8 chr_reg[8]; +static writefunc pcmwrite; + +static SFORMAT StateRegs[] = +{ + { &IRQCount, 4, "IRQC" }, + { &IRQa, 1, "IRQA" }, + { &prg_reg, 1, "PREG" }, + { &prg_mode, 1, "PMOD" }, + { &mirr, 1, "MIRR" }, + { chr_reg, 8, "CREG" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, prg_reg >> 2); + if (!prg_mode) + setprg8(0xC000, prg_reg); + int i; + for (i = 0; i < 8; i++) + setchr1(i << 10, chr_reg[i]); + switch (mirr) { + 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 DECLFW(UNLCITYFIGHTWrite) { + //FCEU_printf("%04x %02x",A,V); + switch (A & 0xF00C) { + case 0x9000: prg_reg = V & 0xC; mirr = V & 3; break; + case 0x9004: + case 0x9008: + case 0x900C: + if (A & 0x800) + pcmwrite(0x4011, (V & 0xf) << 3); + else + prg_reg = V & 0xC; + break; + case 0xC000: + case 0xC004: + case 0xC008: + case 0xC00C: prg_mode = V & 1; break; + case 0xD000: chr_reg[0] = (chr_reg[0] & 0xF0) | (V & 0x0F); break; + case 0xD004: chr_reg[0] = (chr_reg[0] & 0x0F) | (V << 4); break; + case 0xD008: chr_reg[1] = (chr_reg[1] & 0xF0) | (V & 0x0F); break; + case 0xD00C: chr_reg[1] = (chr_reg[1] & 0x0F) | (V << 4); break; + case 0xA000: chr_reg[2] = (chr_reg[2] & 0xF0) | (V & 0x0F); break; + case 0xA004: chr_reg[2] = (chr_reg[2] & 0x0F) | (V << 4); break; + case 0xA008: chr_reg[3] = (chr_reg[3] & 0xF0) | (V & 0x0F); break; + case 0xA00C: chr_reg[3] = (chr_reg[3] & 0x0F) | (V << 4); break; + case 0xB000: chr_reg[4] = (chr_reg[4] & 0xF0) | (V & 0x0F); break; + case 0xB004: chr_reg[4] = (chr_reg[4] & 0x0F) | (V << 4); break; + case 0xB008: chr_reg[5] = (chr_reg[5] & 0xF0) | (V & 0x0F); break; + case 0xB00C: chr_reg[5] = (chr_reg[5] & 0x0F) | (V << 4); break; + case 0xE000: chr_reg[6] = (chr_reg[6] & 0xF0) | (V & 0x0F); break; + case 0xE004: chr_reg[6] = (chr_reg[6] & 0x0F) | (V << 4); break; + case 0xE008: chr_reg[7] = (chr_reg[7] & 0xF0) | (V & 0x0F); break; + case 0xE00C: chr_reg[7] = (chr_reg[7] & 0x0F) | (V << 4); break; + case 0xF000: IRQCount = ((IRQCount & 0x1E0) | ((V & 0xF) << 1)); break; + case 0xF004: IRQCount = ((IRQCount & 0x1E) | ((V & 0xF) << 5)); break; + case 0xF008: IRQa = V & 2; X6502_IRQEnd(FCEU_IQEXT); break; + default: + break; + } + Sync(); +} + +static void UNLCITYFIGHTIRQ(int a) { + if (IRQa) { + IRQCount -= a; + if (IRQCount <= 0) { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void UNLCITYFIGHTPower(void) { + prg_reg = 0; + Sync(); + pcmwrite = GetWriteHandler(0x4011); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, UNLCITYFIGHTWrite); +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLCITYFIGHT_Init(CartInfo *info) { + info->Power = UNLCITYFIGHTPower; + MapIRQHook = UNLCITYFIGHTIRQ; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/copyfami_emu.c b/src/boards/copyfami_emu.c new file mode 100644 index 0000000..a715a2e --- /dev/null +++ b/src/boards/copyfami_emu.c @@ -0,0 +1,355 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifdef COPYFAMI + +#include "__serial.h" +#include "mapinc.h" +#include "mmc3.h" + +//#define DEBUG_SERIAL + +// *** COPY FAMICOM EMULATION *** + +/* + + + $0000-$1FFF + $2000-$200F PPU + $2010-$3FFB + $3FFC-$3FFF + $4000-$7FFF APU / + $8000-$FFF9 CART/ROM + $FFFA-$FFFB CART/ NMI + $FFFE-$FFFF CART/ IRQ + + + + CTRL R/W $3FFC ---aenic ($00 at reset) + + c - + 0 - + 1 - + i - IRQ + 0 - + 1 - + n - NMI + 0 - + 1 - + e - NMI + 0 - + 1 - + a - AROM + 0 - + 1 - + + BANK R/W $3FFD ---mbbbb + + b - + m - ROM + + USBDATA R/W $3FFE dddddddd + + d - / + + STATUS R $3FFF vmnicptr + + r - USB + 0 - + 1 - + t - USB + 0 - + 1 - + p - USB + 0 - + 1 - + c - + 0 - + 1 - + i - IRQ + 0 - + 1 - + n - NMI + 0 - + 1 - + m - 10 VRAM () + v - VRAM + 0 - + 1 - + + AROM + + VRAM + 8000-FFFF +*/ + +#define CTRL 0x00 +#define CCART 0x01 +#define CVIRQ 0x02 +#define CVNMI 0x04 +#define CDNMI 0x08 +#define CAROM 0x10 +#define BANK 0x01 +#define BMIRR 0x10 +#define USB 0x02 +#define STATUS 0x03 +#define SRX 0x01 +#define STX 0x02 +#define SPEN 0x04 +#define SCART 0x08 +#define SIRQ 0x10 +#define SNMI 0x20 +#define SA10 0x40 +#define SVRAM 0x80 + +#ifdef DEBUG_SERIAL +static uint8 debug_serial_data[] = { + 0xDE, 0xAD, 0xBE, 0xEF, 0x00, + 0xDE, 0xAD, 0xBE, 0xEF, 0x01, + + 0x02, + + 0x14, 0x50, 0xB0, + + 0x02, + + 0x14, 0x50, 0xB0, + + 0x02, +}; +static uint32 debug_serial_data_size = sizeof(debug_serial_data); +static uint32 debug_serial_data_pos; +#endif + +static uint8 *CHRRAM = NULL; +static uint32 CHRRAMSIZE; + +static uint8 regs[4]; + +static readfunc def_read_ram, def_read_rom; +static writefunc def_write_ram; + +static SFORMAT StateRegs[] = +{ + { regs, 4, "CREGS" }, + { 0 } +}; + +static void Sync() { + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void MCopyFamiMMC3PW(uint32 A, uint8 V) { + if (regs[CTRL] & CCART) + setprg8(A, V); + else + setprg32r(1, 0x8000, (regs[BANK] & 0x0F) ^ 0x08); +} + +static void MCopyFamiMMC3CW(uint32 A, uint8 V) { + if ((regs[STATUS] & SCART) && (regs[CTRL] & CAROM)) + setchr8r(0x10, 0); + else + setchr1r(0, A, V); +} + +static void MCopyFamiMMC3MW(uint8 V) { + if (regs[CTRL] & CAROM) { + setmirror(MI_0 + ((regs[BANK] >> 4) & 1)); + } else { + A000B = V; + setmirror((V & 1) ^ 1); + } +} + +static uint32 direction = 0xffffffff; +static uint32 bytes_count = 0; + +static DECLFW(MCopyFamiWriteReg) { + if (((A & 3) == USB) && !fceuindbg) { + if (direction != 0) { + direction = 0; + bytes_count = 0; + FCEU_printf(" >"); + } +#ifndef DEBUG_SERIAL + while (!SerialSendChar(V)) { + } + ; +#endif + bytes_count++; +// FCEU_printf(" %02X",V); + } else { + regs[A & 3] = V; + Sync(); + } +} + +static DECLFR(MCopyFamiReadReg) { +#ifdef DEBUG_SERIAL + if (debug_serial_data_pos == debug_serial_data_size) + regs[STATUS] |= SRX; + else + regs[STATUS] &= ~SRX; +#endif + if (!fceuindbg) { +#ifndef DEBUG_SERIAL + if ((A & 3) == STATUS) { + int data; + if ((data = SerialGetChar()) == EOF) + regs[STATUS] |= SRX; + else + regs[STATUS] &= ~SRX; + regs[USB] = data & 0xff; + } else +#endif + if ((A & 3) == USB) { +#ifdef DEBUG_SERIAL + regs[USB] = debug_serial_data[debug_serial_data_pos++]; +#endif + if (direction != 1) { + if (direction != 0xffffffff) FCEU_printf(" bytes sent: %08x", bytes_count); + direction = 1; + bytes_count = 0; + FCEU_printf("\n<"); + } + FCEU_printf(" %02X", regs[USB]); + } + } + return regs[A & 3]; +} + +static DECLFW(MCopyFamiMMC3Write) { + if (regs[CTRL] & CAROM) { + regs[BANK] = V & 0x1F; + Sync(); + } else { + if (A >= 0xC000) + MMC3_IRQWrite(A, V); + else + MMC3_CMDWrite(A, V); + } +} + +static DECLFW(MCopyFamiMMC3WriteNMI) { + if (regs[CTRL] & CVNMI) + def_write_ram(0x3FFC + (A & 1), V); + else + MCopyFamiMMC3Write(A, V); +} + +static DECLFW(MCopyFamiMMC3WriteIRQ) { + if (regs[CTRL] & CVIRQ) + def_write_ram(0x3FFE + (A & 1), V); + else + MCopyFamiMMC3Write(A, V); +} + +static DECLFR(MCopyFamiReadNMI) { + if (regs[CTRL] & CVNMI) + return def_read_ram(0x3FFC + (A & 1)); + else + return def_read_rom(A); +} + +static DECLFR(MCopyFamiReadIRQ) { + if (regs[CTRL] & CVIRQ) + return def_read_ram(0x3FFE + (A & 1)); + else + return def_read_rom(A); +} + +static void MCopyFamiMMC3Power(void) { + regs[CTRL] = regs[USB] = 0; + regs[STATUS] = SIRQ | SNMI | SVRAM; + regs[BANK] = 0x08; +#ifdef DEBUG_SERIAL + debug_serial_data_pos = 0; +#endif + GenMMC3Power(); + Sync(); + + def_write_ram = GetWriteHandler(0x3FFC); + SetWriteHandler(0x3FFC, 0x3FFF, MCopyFamiWriteReg); + def_read_ram = GetReadHandler(0x3FFC); + SetReadHandler(0x3FFC, 0x3FFF, MCopyFamiReadReg); + + SetWriteHandler(0x8000, 0xFFF9, MCopyFamiMMC3Write); + SetWriteHandler(0xFFFA, 0xFFFB, MCopyFamiMMC3WriteNMI); + SetWriteHandler(0xFFFE, 0xFFFF, MCopyFamiMMC3WriteIRQ); + + def_read_rom = GetReadHandler(0xFFFA); + SetReadHandler(0xFFFA, 0xFFFB, MCopyFamiReadNMI); + SetReadHandler(0xFFFE, 0xFFFF, MCopyFamiReadIRQ); +} + +static void MCopyFamiMMC3Reset(void) { + regs[CTRL] = regs[USB] = 0; + regs[STATUS] = SIRQ | SNMI | SVRAM; + regs[BANK] = 0x08; +#ifdef DEBUG_SERIAL + debug_serial_data_pos = 0; +#endif + MMC3RegReset(); + Sync(); +} + +static void MCopyFamiClose(void) { + if (CHRRAM) + FCEU_gfree(CHRRAM); + CHRRAM = NULL; + SerialClose(); +} + +static void StateRestore(int version) { + Sync(); +} + +void MapperCopyFamiMMC3_Init(CartInfo *info) { + GenMMC3_Init(info, 512, 512, 8, 0); + + cwrap = MCopyFamiMMC3CW; + pwrap = MCopyFamiMMC3PW; + mwrap = MCopyFamiMMC3MW; + + info->Reset = MCopyFamiMMC3Reset; + info->Power = MCopyFamiMMC3Power; + info->Close = MCopyFamiClose; + GameStateRestore = StateRestore; + + CHRRAMSIZE = 8192; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CRAM"); + +#ifndef DEBUG_SERIAL + FCEU_printf("WAITING FOR PORT...\n"); + + while (!SerialOpen(20, 921600)) { + } + + FCEU_printf("PORT READY.\n"); +#endif + + AddExState(&StateRegs, ~0, 0, 0); +} + +#endif diff --git a/src/boards/copyfami_hwi.c b/src/boards/copyfami_hwi.c new file mode 100644 index 0000000..8ddb9c6 --- /dev/null +++ b/src/boards/copyfami_hwi.c @@ -0,0 +1,587 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// *** COPY FAMICOM HARDWARE INTERFACE *** + +#ifdef COPYFAMI + +#define MESSAGE_LOG +#define NO_CACHE +#define NO_RAM + +#include "__serial.h" +#include "mapinc.h" + +#define FNV_32_PRIME ((uint32)0x01000193) + +#define CHR_CACHE_SIZE (1024 * 4) +#define WRAM_CACHE_SIZE (1024 / 2) +#define PRG_CACHE_SIZE (1024 / 4) +#define CMD_CACHE_SIZE (1024 * 128) + +#define CMD_MAX_SIZE (5) +#define CMD_MAX_RETEST (16) +#define CMD_MAX_VERIFY (16) + +static uint8 *WRAM = NULL; + +uint8 InitVector[] = { 0xDE, 0xAD, 0xBE, 0xEF };// args none, return DE AD BE EF +uint8 ResetCmd[] = { 0x00 }; // args none, return none +uint8 StateCmd[] = { 0x01 }; // args none, return 7 bytes status +uint8 StatusCmd[] = { 0x02 }; // args none, return 32 bytes status +uint8 LoadPlugCmd[] = { 0x03, 0x00, 0x00 }; // args 2b size, Nb data return none +uint8 RunPlugCmd[] = { 0x04 }; // args none, return none +uint8 RunGameCmd[] = { 0x05 }; // args none, return none +uint8 NROMSave[] = { 0x06 }; // args none, return 16b + 32kb + 8kb + +uint8 PRGWBCmd[] = { 0x08, 0x00, 0x00, 0x00 }; // args 2b addr, 1b data return none +uint8 PRGRBCmd[] = { 0x09, 0x00, 0x00 }; // args 2b addr return 1b data +uint8 CHRWBCmd[] = { 0x0A, 0x00, 0x00, 0x00 }; // args 2b addr, 1b data return none +uint8 CHRRBCmd[] = { 0x0B, 0x00, 0x00 }; // args 2b addr, return 1b data + +uint8 PRGSUMCmd[] = { 0x10, 0x00, 0x00 }; // args 1b addr, 1b size return (256 * N)b +uint8 PRG32KSUMCmd[] = { 0x10, 0x80, 0x80 }; // args 1b addr, 1b size return 32kb +uint8 PRG16KSUMCmd[] = { 0x10, 0x00, 0x40 }; // args 1b addr, 1b size return 16kb +uint8 PRG8KSUMCmd[] = { 0x10, 0x00, 0x20 }; // args 1b addr, 1b size return 8kb +uint8 PRG4KSUMCmd[] = { 0x10, 0x00, 0x10 }; // args 1b addr, 1b size return 4kb + +uint8 CHRSUMCmd[] = { 0x11, 0x00, 0x00 }; // args 1b addr, 1b size return (256 * N)b +uint8 CHR8KSUMCmd[] = { 0x11, 0x00, 0x20 }; // args 1b addr, 1b size return 8kb +uint8 CHR4KSUMCmd[] = { 0x11, 0x00, 0x10 }; // args 1b addr, 1b size return 4kb +uint8 CHR2KSUMCmd[] = { 0x11, 0x00, 0x08 }; // args 1b addr, 1b size return 2kb +uint8 CHR1KSUMCmd[] = { 0x11, 0x00, 0x04 }; // args 1b addr, 1b size return 1kb + +uint8 PRGGetCmd[] = { 0x12, 0x00, 0x00 }; // args 1b addr, 1b size return (256 * N)b +uint8 PRG32KGetCmd[] = { 0x12, 0x80, 0x80 }; // args 1b addr, 1b size return 32kb +uint8 PRG16KGetCmd[] = { 0x12, 0x00, 0x40 }; // args 1b addr, 1b size return 16kb +uint8 PRG8KGetCmd[] = { 0x12, 0x00, 0x20 }; // args 1b addr, 1b size return 8kb +uint8 PRG4KGetCmd[] = { 0x12, 0x00, 0x10 }; // args 1b addr, 1b size return 4kb + +uint8 CHRGetCmd[] = { 0x13, 0x00, 0x00 }; // args 1b addr, 1b size return (256 * N)b +uint8 CHR8KGetCmd[] = { 0x13, 0x00, 0x20 }; // args 1b addr, 1b size return 8kb +uint8 CHR4KGetCmd[] = { 0x13, 0x00, 0x10 }; // args 1b addr, 1b size return 4kb +uint8 CHR2KGetCmd[] = { 0x13, 0x00, 0x08 }; // args 1b addr, 1b size return 2kb +uint8 CHR1KGetCmd[] = { 0x13, 0x00, 0x04 }; // args 1b addr, 1b size return 1kb + +uint8 CPUTestCmd[] = { 0x14, 0x00, 0x00 }; // args 1b addr, 1b size return (2b + 1b) * N + 3b + +typedef struct { + int32 mirror; + int32 chrsum[8]; + int32 prgsum[4]; +} SYNC_STATE; + +static SYNC_STATE state_cur, state_new, state_def; + +typedef struct { + uint8 *buf; + int32 count; +} DATA_BANKS; + +static DATA_BANKS chr_data; +static int32 chr_bank[0x10000]; +static DATA_BANKS prg_data; +static int32 prg_bank[0x10000]; + +typedef struct { + SYNC_STATE states[CMD_CACHE_SIZE]; + int32 seqs[CMD_CACHE_SIZE][CMD_MAX_SIZE]; + int32 count; +} SYNC_CMDS; + +typedef struct { + int32 seq[CMD_MAX_SIZE]; + int32 size; + int32 found; + uint32 hash; + uint16 hashf; +} SYNC_CMD; + +static SYNC_CMD cmd; +static SYNC_CMDS cmds; + +typedef struct { + int32 index; + int32 size; + int32 retest; + int32 verify; +} CMD_CACHE; + +static CMD_CACHE cmd_cache[0x10000]; + +static SFORMAT StateRegs[] = +{ + { state_cur.chrsum, sizeof(state_cur.chrsum), "CHRREG" }, + { state_cur.prgsum, sizeof(state_cur.prgsum), "ROMREG" }, + { &state_cur.mirror, sizeof(state_cur.mirror), "MIRREG" }, + { 0 } +}; + +#define MI_U 4 + +static char *mirror_names[5] = { "Horizontal", "Vertical", "Mirror 0", "Mirror 1", "Unknown mirror" }; +static int32 mirror_modes[16] = { + MI_0, MI_U, MI_U, MI_H, MI_U, MI_V, MI_U, MI_U, + MI_U, MI_U, MI_U, MI_U, MI_U, MI_U, MI_U, MI_1 +}; + +#define CHRDEF(slot) (chr_bank[state_def.chrsum[slot]]) +#define PRGDEF(slot) (prg_bank[state_def.prgsum[slot]]) +#define CHRCUR(slot) (chr_bank[state_cur.chrsum[slot]]) +#define PRGCUR(slot) (prg_bank[state_cur.prgsum[slot]]) +#define CHRNEW(slot) (chr_bank[state_new.chrsum[slot]]) +#define PRGNEW(slot) (prg_bank[state_new.prgsum[slot]]) + +static void GetStatus(SYNC_STATE *state) { + uint8 resp0; + uint16 resp1, i; + SEND(StatusCmd); + GET(resp0, 1); + state->mirror = resp0; + GET(resp0, 1); + for (i = 0; i < 8; i++) { + GET(resp1, 2); + state->chrsum[i] = resp1; + } + for (i = 0; i < 4; i++) { + GET(resp1, 2); + state->prgsum[i] = resp1; + } +} + +static int32 FetchNewCHRBank(int32 slot) { + FILE *ofile; + char name[256]; + int32 bank = chr_data.count++; + CHR1KGetCmd[1] = slot << 2; + SENDGET(CHR1KGetCmd, chr_data.buf[bank * 1024], 1024); + sprintf(name, "%04x.chr", bank); + ofile = fopen(name, "wb"); + fwrite((void*)&chr_data.buf[bank * 1024], 1, 1024, ofile); + fclose(ofile); + return bank; +} + +static int32 FetchNewPRGBank(int32 slot) { + FILE *ofile; + char name[256]; + int32 bank = prg_data.count++; + PRG8KGetCmd[1] = 0x80 + (slot << 5); + SENDGET(PRG8KGetCmd, prg_data.buf[bank * 8192], 8192); + sprintf(name, "%04x.prg", bank); + ofile = fopen(name, "wb"); + fwrite((void*)&prg_data.buf[bank * 8192], 1, 8192, ofile); + fclose(ofile); + return bank; +} + +static int CheckStatus(void) { + int32 i, ischanged = 0; + GetStatus(&state_new); + if (state_cur.mirror != state_new.mirror) { + state_cur.mirror = state_new.mirror; +#ifdef MESSAGE_LOG + FCEU_printf(">> mirror changed to %s (%02X)\n", mirror_names[mirror_modes[state_cur.mirror]], state_cur.mirror); +#endif + ischanged = 1; + } else { + state_new.mirror = -1; + } + for (i = 0; i < 8; i++) { + if (state_cur.chrsum[i] != state_new.chrsum[i]) { + state_cur.chrsum[i] = state_new.chrsum[i]; + if (CHRCUR(i) == -1) { + CHRCUR(i) = FetchNewCHRBank(i); +#ifdef MESSAGE_LOG + FCEU_printf(">> chr[%d] bank %d loaded\n", i, CHRCUR(i)); +#endif + } +#ifdef MESSAGE_LOG + else + FCEU_printf(">> chr[%d] bank %d switched\n", i, CHRCUR(i)); +#endif + ischanged = 1; + } else { + state_new.chrsum[i] = -1; + } + } + for (i = 0; i < 4; i++) { + if (state_cur.prgsum[i] != state_new.prgsum[i]) { + state_cur.prgsum[i] = state_new.prgsum[i]; + if (PRGCUR(i) == -1) { + PRGCUR(i) = FetchNewPRGBank(i); +#ifdef MESSAGE_LOG + FCEU_printf(">> prg[%d] bank %d loaded\n", i, PRGCUR(i)); +#endif + } +#ifdef MESSAGE_LOG + else + FCEU_printf(">> prg[%d] bank %d switched\n", i, PRGCUR(i)); +#endif + ischanged = 1; + } else { + state_new.prgsum[i] = -1; + } + } + return ischanged; +} + +#ifndef NO_CACHE +static void ApplyStatus() { + int32 i; + if ((cmds.states[cmd.found].mirror != -1) && (cmds.states[cmd.found].mirror != state_cur.mirror)) { + state_cur.mirror = cmds.states[cmd.found].mirror; + setmirror(mirror_modes[state_cur.mirror]); +#ifdef MESSAGE_LOG + FCEU_printf(">> mirror changed to %s (%02X)\n", mirror_names[mirror_modes[state_cur.mirror]], state_cur.mirror); +#endif + } + for (i = 0; i < 8; i++) { + int32 sum = cmds.states[cmd.found].chrsum[i]; + if (sum != -1) { + if (sum != state_cur.chrsum[i]) { + state_cur.chrsum[i] = sum; + setchr1r(1, i * 1024, CHRCUR(i)); +#ifdef MESSAGE_LOG + FCEU_printf(">> chr[%d] bank %d switched\n", i, chr_bank[sum]); +#endif + } else +#ifdef MESSAGE_LOG + FCEU_printf(">> chr[%d] bank %d switched the same\n", i, chr_bank[sum]); + } +#endif + } + for (i = 0; i < 4; i++) { + int32 sum = cmds.states[cmd.found].prgsum[i]; + if (sum != -1) { + if (sum != state_cur.prgsum[i]) { + state_cur.prgsum[i] = sum; + setprg8r(2, 0x8000 + (i * 8192), PRGCUR(i)); +#ifdef MESSAGE_LOG + FCEU_printf(">> prg[%d] bank %d switched\n", i, prg_bank[sum]); +#endif + } else +#ifdef MESSAGE_LOG + FCEU_printf(">> prg[%d] bank %d switched the same\n", i, prg_bank[sum]); + } +#endif + } + } + + static void LogCmd() { + int32 i; + FCEU_printf(">> new cmd size %d [", cmd_cache[cmd.hashf].size); + for (i = 0; i < cmd_cache[cmd.hashf].size; i++) + FCEU_printf(" %06X", cmds.seqs[cmd.found][i]); + FCEU_printf(" ], switched to ("); + if (cmds.states[cmd.found].mirror != -1) + FCEU_printf(" mirror=%s", mirror_names[mirror_modes[cmds.states[cmd.found].mirror]]); + for (i = 0; i < 8; i++) + if (cmds.states[cmd.found].chrsum[i] != -1) + FCEU_printf(" chr%d=%02X", i, chr_bank[cmds.states[cmd.found].chrsum[i]]); + for (i = 0; i < 4; i++) + if (cmds.states[cmd.found].prgsum[i] != -1) + FCEU_printf(" prg%d=%02X", i, prg_bank[cmds.states[cmd.found].prgsum[i]]); + FCEU_printf(" )\n"); + } +#endif +static void Sync() { + setchr1r(1, 0x0000, CHRCUR(0)); + setchr1r(1, 0x0400, CHRCUR(1)); + setchr1r(1, 0x0800, CHRCUR(2)); + setchr1r(1, 0x0C00, CHRCUR(3)); + setchr1r(1, 0x1000, CHRCUR(4)); + setchr1r(1, 0x1400, CHRCUR(5)); + setchr1r(1, 0x1800, CHRCUR(6)); + setchr1r(1, 0x1C00, CHRCUR(7)); +#ifndef NO_RAM + setprg8r(1, 0x6000, 0); +#endif + setprg8r(2, 0x8000, PRGCUR(0)); + setprg8r(2, 0xA000, PRGCUR(1)); + setprg8r(2, 0xC000, PRGCUR(2)); + setprg8r(2, 0xE000, PRGCUR(3)); + setmirror(mirror_modes[state_cur.mirror]); +} +#ifndef NO_CACHE +static void UpdateCmd(uint32 val) { + int32 index; + if (cmd.size < CMD_MAX_SIZE) { + index = cmd.size++; + } else { + // если достигнут максимум для команды, выбросить последнуюю, добавить новую, + // продолжать до банксвичинга + cmd.hash = 0; + for (index = 0; index < (CMD_MAX_SIZE - 1); index++) { + cmd.seq[index] = cmd.seq[index + 1]; + cmd.hash *= FNV_32_PRIME; + cmd.hash ^= cmd.seq[index]; + } + } + cmd.seq[index] = val; + cmd.hash *= FNV_32_PRIME; + cmd.hash ^= val; + cmd.hashf = (cmd.hash >> 16) ^ (cmd.hash & 0xffff); + cmd.found = cmd_cache[cmd.hashf].index; +} +#endif + +static DECLFW(MCopyFamiWrite) { +#ifndef NO_CACHE + int32 i; +#endif + +#ifdef MESSAGE_LOG + FCEU_printf("> WRITE %04X:%02X\n", A, V); +#endif + + PRGWBCmd[1] = A & 0xFF; + PRGWBCmd[2] = A >> 8; + PRGWBCmd[3] = V & 0xFF; + SEND(PRGWBCmd); +#ifdef NO_CACHE + CheckStatus(); + Sync(); +#else + UpdateCmd((A << 8) | V); + // ищем команду в кеше + if (cmd.found == -1) { + // не найдена, проверяем, изменилось ли состояние банков + // либо не предельной ли она длины для команды + cmd_cache[cmd.hashf].index = cmd.found = cmds.count++; + cmd_cache[cmd.hashf].retest = 0; + cmd_cache[cmd.hashf].verify = 0; + for (i = 0; i < cmd.size; i++) + cmds.seqs[cmd.found][i] = cmd.seq[i]; + cmd_cache[cmd.hashf].size = cmd.size; + if (CheckStatus()) { + cmds.states[cmd.found] = state_new; + LogCmd(); + cmd.size = 0; + cmd.hash = 0; + Sync(); + } else { + // если добавлена полная команда без банксвитчинга + cmd_cache[cmd.hashf].index = -2; + } + } else if (cmd.found == -2) { + // частичное совпадение, если число проверок не превысило лимит + if (cmd_cache[cmd.hashf].retest < CMD_MAX_RETEST) { + // то проверим состояние банков + if (CheckStatus()) { + // изменилось, запишем новую команду + cmd_cache[cmd.hashf].index = cmd.found = cmds.count++; + cmd_cache[cmd.hashf].retest = 0; + cmd_cache[cmd.hashf].verify = 0; + for (i = 0; i < cmd.size; i++) + cmds.seqs[cmd.found][i] = cmd.seq[i]; + cmd_cache[cmd.hashf].size = cmd.size; + cmds.states[cmd.found] = state_new; + LogCmd(); + cmd.size = 0; + cmd.hash = 0; + Sync(); + } else { + // не изменилось, отметим увеличим счетчик проверок + cmd_cache[cmd.hashf].retest++; + } + } + } else { + // найдена, последний рубеж обороны от говна +/* + if(cmd_cache[cmd.hashf].verify < CMD_MAX_VERIFY) { + if(CheckStatus()) { + int32 changed = 0; + // , + if(cmds.states[cmd.found].mirror != state_new.mirror) + changed = 1; + for(i=0; i<8; i++) + if(cmds.states[cmd.found].chrsum[i] != state_new.chrsum[i]) + changed = 1; + for(i=0; i<4; i++) + if(cmds.states[cmd.found].prgsum[i] != state_new.prgsum[i]) + changed = 1; + if(changed) { + cmd_cache[cmd.hashf].index = -1; + cmd_cache[cmd.hashf].retest = 0; + cmd_cache[cmd.hashf].verify = 0; + Sync(); + } + } else + cmd_cache[cmd.hashf].verify++; + } else */{ + // применяем без малейшего зазрения совести + ApplyStatus(); + cmd.size = 0; + cmd.hash = 0; + } + } +#endif +} + +static DECLFR(MCopyFamiRead) { + uint8 result; + PRGRBCmd[1] = A & 0xFF; + PRGRBCmd[2] = A >> 8; + SENDGET(PRGRBCmd, result, 1); +#ifdef MESSAGE_LOG + FCEU_printf("> READ %04X:%02X\n", A, result); +#endif + return result; +} + +static void MCopyFamiReset(void) { + state_cur = state_def; + Sync(); +} + +static void MCopyFamiPower(void) { +// uint32 resp, presp; + + FCEU_printf("NOW POWERING... "); + + Sync(); + + SetWriteHandler(0x4018, 0x7fff, MCopyFamiWrite); + SetReadHandler(0x4018, 0x7fff, MCopyFamiRead); +#ifndef NO_RAM + SetWriteHandler(0x6000, 0x7fff, CartBW); + SetReadHandler(0x6000, 0x7fff, CartBR); +#endif + +/* + FCEU_printf("READING MEMORY MAP...\n"); + CPUTestCmd[1] = 0x50; + CPUTestCmd[2] = 0x30; + SEND(CPUTestCmd); + resp = 0; + presp = 0xffffffff; + while (presp != 0x00ff0000) { + GET(resp, 3); + if(presp != 0xffffffff) { + switch(presp & 0x00FF0000) { + case 0x00000000: // BUS + FCEU_printf(" %04X-%04X OPEN BUS\n",presp & 0x7fff, (resp - 1) & 0x7fff); + break; + case 0x00010000: // RAM + FCEU_printf(" %04X-%04X RAM\n",presp & 0x7fff, (resp - 1) & 0x7fff); + SetWriteHandler(presp & 0x7fff, (resp - 1) & 0x7fff, CartBW); + SetReadHandler(presp & 0x7fff, (resp - 1) & 0x7fff, CartBR); + break; + } + } + presp = resp; + } +*/ + SetWriteHandler(0x8000, 0xffff, MCopyFamiWrite); + SetReadHandler(0x8000, 0xffff, CartBR); + + FCEU_printf("DONE!\nNOW COLLECTING DATA...\n"); +} + +static void MCopyFamiClose(void) { + if (chr_data.buf) + FCEU_gfree(chr_data.buf); + chr_data.buf = NULL; + if (prg_data.buf) + FCEU_gfree(prg_data.buf); + prg_data.buf = NULL; + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; + + SerialClose(); +} + +static void StateRestore(int version) { + Sync(); +} + +void MapperCopyFami_Init(CartInfo *info) { + uint32 resp = 0, i, size; + + memset(chr_bank, -1, sizeof(chr_bank)); + memset(prg_bank, -1, sizeof(chr_bank)); + memset(cmd_cache, -1, sizeof(cmd_cache)); + memset(&cmds, 0, sizeof(cmds)); + memset(&cmd, 0, sizeof(cmd)); + + info->Reset = MCopyFamiReset; + info->Power = MCopyFamiPower; + info->Close = MCopyFamiClose; + GameStateRestore = StateRestore; + + size = 1024 * CHR_CACHE_SIZE; // размер страницы 1кб + chr_data.buf = (uint8*)FCEU_gmalloc(size); + SetupCartCHRMapping(1, chr_data.buf, size, 1); // проверять ппу рам, иначе игра может портить данные + AddExState(chr_data.buf, size, 0, "CCHR"); + + size = 8192; // размер страницы 8кб + WRAM = (uint8*)FCEU_gmalloc(size); + SetupCartPRGMapping(1, WRAM, size, 1); + AddExState(WRAM, size, 0, "CPRM"); + + size = 8192 * PRG_CACHE_SIZE; // размер страницы 8кб + prg_data.buf = (uint8*)FCEU_gmalloc(size); + SetupCartPRGMapping(2, prg_data.buf, size, 0); + AddExState(prg_data.buf, size, 0, "CPPR"); + + + FCEU_printf("WAITING FOR SERIAL PORT... "); + while (!SerialOpen(19, 921600)) { + Sleep(500); + } + FCEU_printf("READY!\n"); + + FCEU_printf("WAITING FOR DEVICE... "); + + while (resp != *(uint32*)&InitVector[0]) { + SEND(ResetCmd); + SENDGET(InitVector, resp, 4); + Sleep(500); + } + + FCEU_printf("READY!\n"); + FCEU_printf("READING STATUS...\n"); + GetStatus(&state_cur); + FCEU_printf("MIRRORING IS %s (%02X)\n", mirror_names[mirror_modes[state_cur.mirror]], state_cur.mirror); + FCEU_printf("READING CHR...\n INITIAL STATE:"); + + for (i = 0; i < 8; i++) { + if (CHRCUR(i) == -1) + CHRCUR(i) = FetchNewCHRBank(i); + FCEU_printf(" CHR%d=%02X", i, CHRCUR(i)); + } + FCEU_printf("\n"); + + FCEU_printf("READING PRG...\n INITIAL STATE:"); + for (i = 0; i < 4; i++) { + if (PRGCUR(i) == -1) + PRGCUR(i) = FetchNewPRGBank(i); + FCEU_printf(" PRG%d=%02X", i, PRGCUR(i)); + } + FCEU_printf("\nDONE!\n"); + + state_def = state_cur; + + AddExState(&StateRegs, ~0, 0, 0); +} + +#endif diff --git a/src/boards/dance2000.c b/src/boards/dance2000.c new file mode 100644 index 0000000..4494f7b --- /dev/null +++ b/src/boards/dance2000.c @@ -0,0 +1,112 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Dance 2000 12-in-1 + * + */ + +#include "mapinc.h" + +static uint8 prg, mode; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; +static uint32 lastnt = 0; + +static SFORMAT StateRegs[] = +{ + { &prg, 1, "REGS" }, + { &mode, 1, "MODE" }, + { &lastnt, 4, "LSNT" }, + { 0 } +}; + +static void Sync(void) { + setmirror((mode ^ 1) & 1); + setprg8r(0x10, 0x6000, 0); + setchr4(0x0000, lastnt); + setchr4(0x1000, 1); + if (mode & 4) + setprg32(0x8000, prg & 7); + else { + setprg16(0x8000, prg & 0x0f); + setprg16(0xC000, 0); + } +} + +static DECLFW(UNLD2000Write) { + switch (A) { + case 0x5000: prg = V; Sync(); break; + case 0x5200: mode = V; if (mode & 4) Sync(); break; + } +} + +static DECLFR(UNLD2000Read) { + if (prg & 0x40) + return X.DB; + else + return CartBR(A); +} + +static void UNLD2000Power(void) { + prg = mode = 0; + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, UNLD2000Read); + SetWriteHandler(0x5000, 0x5FFF, UNLD2000Write); +} + +static void FP_FASTAPASS(1) UNL2000Hook(uint32 A) { + if (mode & 2) { + if ((A & 0x3000) == 0x2000) { + uint32 curnt = A & 0x800; + if (curnt != lastnt) { + setchr4(0x0000, curnt >> 11); + lastnt = curnt; + } + } + } else { + lastnt = 0; + setchr4(0x0000, 0); + } +} + +static void UNLD2000Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLD2000_Init(CartInfo *info) { + info->Power = UNLD2000Power; + info->Close = UNLD2000Close; + PPU_hook = UNL2000Hook; + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/datalatch.c b/src/boards/datalatch.c new file mode 100644 index 0000000..354429b --- /dev/null +++ b/src/boards/datalatch.c @@ -0,0 +1,483 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 latche, latcheinit, bus_conflict; +static uint16 addrreg0, addrreg1; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; +static void (*WSync)(void); + +static DECLFW(LatchWrite) { +// FCEU_printf("bs %04x %02x\n",A,V); + if (bus_conflict) + latche = (V == CartBR(A)) ? V : 0; + else + latche = V; + WSync(); +} + +static void LatchPower(void) { + latche = latcheinit; + WSync(); + if (WRAM) { + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + } else { + SetReadHandler(0x8000, 0xFFFF, CartBR); + } + SetWriteHandler(addrreg0, addrreg1, LatchWrite); +} + +static void LatchClose(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + WSync(); +} + +static void Latch_Init(CartInfo *info, void (*proc)(void), uint8 init, uint16 adr0, uint16 adr1, uint8 wram, uint8 busc) { + bus_conflict = busc; + latcheinit = init; + addrreg0 = adr0; + addrreg1 = adr1; + WSync = proc; + info->Power = LatchPower; + info->Close = LatchClose; + GameStateRestore = StateRestore; + if (wram) { + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } + AddExState(&latche, 1, 0, "LATC"); + AddExState(&bus_conflict, 1, 0, "BUSC"); +} + +//------------------ Map 0 --------------------------- + +#ifdef DEBUG_MAPPER +static DECLFW(NROMWrite) { + FCEU_printf("bs %04x %02x\n", A, V); + CartBW(A, V); +} +#endif + +static void NROMPower(void) { + setprg8r(0x10, 0x6000, 0); // Famili BASIC (v3.0) need it (uses only 4KB), FP-BASIC uses 8KB + setprg16(0x8000, 0); + setprg16(0xC000, ~0); + setchr8(0); + + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + + #ifdef DEBUG_MAPPER + SetWriteHandler(0x4020, 0xFFFF, NROMWrite); + #endif +} + +void NROM_Init(CartInfo *info) { + info->Power = NROMPower; + info->Close = LatchClose; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} + +//------------------ Map 2 --------------------------- + +static void UNROMSync(void) { +// static uint32 mirror_in_use = 0; +// if (PRGsize[0] <= 128 * 1024) { +// setprg16(0x8000, latche & 0x7); +// if ((latche & 0xF8) == 0x08) mirror_in_use = 1; +// if (mirror_in_use) +// setmirror(((latche >> 3) & 1) ^ 1); // Higway Star Hacked mapper to be redefined to another mapper +// } else + setprg16(0x8000, latche); + setprg16(0xc000, ~0); + setchr8(0); +} + +void UNROM_Init(CartInfo *info) { + Latch_Init(info, UNROMSync, 0, 0x8000, 0xFFFF, 0, 1); +} + +//------------------ Map 3 --------------------------- + +static void CNROMSync(void) { + setchr8(latche); + setprg32(0x8000, 0); + setprg8r(0x10, 0x6000, 0); // Hayauchy IGO uses 2Kb or RAM +} + +void CNROM_Init(CartInfo *info) { + Latch_Init(info, CNROMSync, 0, 0x8000, 0xFFFF, 1, 1); +} + +//------------------ Map 7 --------------------------- + +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, 0x4020, 0xFFFF, 0, 0); +} + +//------------------ Map 8 --------------------------- + +static void M8Sync() { + setprg16(0x8000, latche >> 3); + setprg16(0xc000, 1); + setchr8(latche & 3); +} + +void Mapper8_Init(CartInfo *info) { + Latch_Init(info, M8Sync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ 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, 0, 0); +} + +void Mapper144_Init(CartInfo *info) { + Latch_Init(info, M11Sync, 0, 0x8001, 0xFFFF, 0, 0); +} + +//------------------ Map 13 --------------------------- + +static void CPROMSync(void) { + setchr4(0x0000, 0); + setchr4(0x1000, latche & 3); + setprg32(0x8000, 0); +} + +void CPROM_Init(CartInfo *info) { + Latch_Init(info, CPROMSync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 38 --------------------------- + +static void M38Sync(void) { + setprg32(0x8000, latche & 3); + setchr8(latche >> 2); +} + +void Mapper38_Init(CartInfo *info) { + Latch_Init(info, M38Sync, 0, 0x7000, 0x7FFF, 0, 0); +} + +//------------------ Map 66 --------------------------- + +static void MHROMSync(void) { + setprg32(0x8000, latche >> 4); + setchr8(latche & 0xF); +} + +void MHROM_Init(CartInfo *info) { + Latch_Init(info, MHROMSync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ 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, 0, 0); +} + +//------------------ 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, 0, 0); +} + +//------------------ Map 86 --------------------------- + +static void M86Sync(void) { + setprg32(0x8000, (latche >> 4) & 3); + setchr8((latche & 3) | ((latche >> 4) & 4)); +} + +void Mapper86_Init(CartInfo *info) { + Latch_Init(info, M86Sync, ~0, 0x6000, 0x6FFF, 0, 0); +} + +//------------------ Map 87 --------------------------- + +static void M87Sync(void) { + setprg32(0x8000, 0); + setchr8(((latche >> 1) & 1) | ((latche << 1) & 2)); +} + +void Mapper87_Init(CartInfo *info) { + Latch_Init(info, M87Sync, ~0, 0x6000, 0xFFFF, 0, 0); +} + +//------------------ Map 89 --------------------------- + +static void M89Sync(void) { + setprg16(0x8000, (latche >> 4) & 7); + setprg16(0xc000, ~0); + setchr8((latche & 7) | ((latche >> 4) & 8)); + setmirror(MI_0 + ((latche >> 3) & 1)); +} + +void Mapper89_Init(CartInfo *info) { + Latch_Init(info, M89Sync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ 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, 0, 0); +} + +//------------------ 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, 0, 0); +} + +//------------------ Map 97 --------------------------- + +static void M97Sync(void) { + setchr8(0); + setprg16(0x8000, ~0); + setprg16(0xc000, latche & 15); + switch (latche >> 6) { + case 0: break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_V); break; + case 3: break; + } + setchr8(((latche >> 1) & 1) | ((latche << 1) & 2)); +} + +void Mapper97_Init(CartInfo *info) { + Latch_Init(info, M97Sync, ~0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 101 --------------------------- + +static void M101Sync(void) { + setprg32(0x8000, 0); + setchr8(latche); +} + +void Mapper101_Init(CartInfo *info) { + Latch_Init(info, M101Sync, ~0, 0x6000, 0x7FFF, 0, 0); +} + +//------------------ 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, 0, 0); +} + +//------------------ Map 113 --------------------------- + +static void M113Sync(void) { + setprg32(0x8000, (latche >> 3) & 7); + setchr8(((latche >> 3) & 8) | (latche & 7)); +// setmirror(latche>>7); // only for HES 6in1 +} + +void Mapper113_Init(CartInfo *info) { + Latch_Init(info, M113Sync, 0, 0x4100, 0x7FFF, 0, 0); +} + +//------------------ Map 140 --------------------------- + +void Mapper140_Init(CartInfo *info) { + Latch_Init(info, MHROMSync, 0, 0x6000, 0x7FFF, 0, 0); +} + +//------------------ 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, 0, 0); +} + +//------------------ Map 180 --------------------------- + +static void M180Sync(void) { + setprg16(0x8000, 0); + setprg16(0xc000, latche); + setchr8(0); +} + +void Mapper180_Init(CartInfo *info) { + Latch_Init(info, M180Sync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 184 --------------------------- + +static void M184Sync(void) { + setchr4(0x0000, latche); + setchr4(0x1000, latche >> 4); + setprg32(0x8000, 0); +} + +void Mapper184_Init(CartInfo *info) { + Latch_Init(info, M184Sync, 0, 0x6000, 0x7FFF, 0, 0); +} + +//------------------ Map 203 --------------------------- + +static void M203Sync(void) { + setprg16(0x8000, (latche >> 2) & 3); + setprg16(0xC000, (latche >> 2) & 3); + setchr8(latche & 3); +} + +void Mapper203_Init(CartInfo *info) { + Latch_Init(info, M203Sync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ Map 240 --------------------------- + +static void M240Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg32(0x8000, latche >> 4); + setchr8(latche & 0xF); +} + +void Mapper240_Init(CartInfo *info) { + Latch_Init(info, M240Sync, 0, 0x4020, 0x5FFF, 1, 0); +} + +//------------------ Map 241 --------------------------- +// Mapper 7 mostly, but with SRAM or maybe prot circuit +// figure out, which games do need 5xxx area reading + +static void M241Sync(void) { + setchr8(0); + setprg8r(0x10, 0x6000, 0); + if (latche & 0x80) + setprg32(0x8000, latche | 8); // no 241 actually, but why not afterall? + else + setprg32(0x8000, latche); +} + +void Mapper241_Init(CartInfo *info) { + Latch_Init(info, M241Sync, 0, 0x8000, 0xFFFF, 1, 0); +} + +//------------------ A65AS --------------------------- + +// actually, there is two cart in one... First have extra mirroring +// mode (one screen) and 32K bankswitching, second one have only +// 16 bankswitching mode and normal mirroring... But there is no any +// correlations between modes and they can be used in one mapper code. + +static void BMCA65ASSync(void) { + if (latche & 0x40) + setprg32(0x8000, (latche >> 1) & 0x0F); + else { + setprg16(0x8000, ((latche & 0x30) >> 1) | (latche & 7)); + setprg16(0xC000, ((latche & 0x30) >> 1) | 7); + } + setchr8(0); + if (latche & 0x80) + setmirror(MI_0 + (((latche >> 5) & 1))); + else + setmirror(((latche >> 3) & 1) ^ 1); +} + +void BMCA65AS_Init(CartInfo *info) { + Latch_Init(info, BMCA65ASSync, 0, 0x8000, 0xFFFF, 0, 0); +} + +//------------------ BMC-11160 --------------------------- +// Simple BMC discrete mapper by TXC + +static void BMC11160Sync(void) { + uint32 bank = (latche >> 4) & 7; + setprg32(0x8000, bank); + setchr8((bank << 2) | (latche & 3)); + setmirror((latche >> 7) & 1); +} + +void BMC11160_Init(CartInfo *info) { + Latch_Init(info, BMC11160Sync, 0, 0x8000, 0xFFFF, 0, 0); +} diff --git a/src/boards/dream.c b/src/boards/dream.c new file mode 100644 index 0000000..c42fa0f --- /dev/null +++ b/src/boards/dream.c @@ -0,0 +1,51 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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, "LATC"); +} diff --git a/src/boards/edu2000.c b/src/boards/edu2000.c new file mode 100644 index 0000000..a872639 --- /dev/null +++ b/src/boards/edu2000.c @@ -0,0 +1,77 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" + +static uint8 *WRAM = NULL; +static uint8 reg; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REG" }, + { 0 } +}; + +static void Sync(void) { + setchr8(0); + setprg8r(0x10, 0x6000, (reg & 0xC0) >> 6); + setprg32(0x8000, reg & 0x1F); +// setmirror(((reg&0x20)>>5)); +} + +static DECLFW(UNLEDU2000HiWrite) { +// FCEU_printf("%04x:%02x\n",A,V); + reg = V; + Sync(); +} + +static void UNLEDU2000Power(void) { + setmirror(MI_0); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0xFFFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, UNLEDU2000HiWrite); + reg = 0; + Sync(); +} + +static void UNLEDU2000Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void UNLEDU2000Restore(int version) { + Sync(); +} + +void UNLEDU2000_Init(CartInfo *info) { + info->Power = UNLEDU2000Power; + info->Close = UNLEDU2000Close; + GameStateRestore = UNLEDU2000Restore; + WRAM = (uint8*)FCEU_gmalloc(32768); + SetupCartPRGMapping(0x10, WRAM, 32768, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = 32768; + } + AddExState(WRAM, 32768, 0, "WRAM"); + AddExState(StateRegs, ~0, 0, 0); +} diff --git a/src/boards/emu2413.c b/src/boards/emu2413.c new file mode 100644 index 0000000..50b8acf --- /dev/null +++ b/src/boards/emu2413.c @@ -0,0 +1,1075 @@ +/*********************************************************************************** + + 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 "emu2413.h" + +static const unsigned char default_inst[15][8] = { + /* 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 }, +}; + +/* 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) * (int32)(EG_STEP / DB_STEP)) +#define TL2EG(d) ((d) * (int32)(TL_STEP / EG_STEP)) +#define SL2EG(d) ((d) * (int32)(SL_STEP / EG_STEP)) + +#define DB_POS(x) (uint32)((x) / DB_STEP) +#define DB_NEG(x) (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 : (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 uint32 clk = 844451141; +/* Sampling rate */ +static uint32 rate = 3354932; + +/* WaveTable for each envelope amp */ +static uint16 fullsintable[PG_WIDTH]; +static uint16 halfsintable[PG_WIDTH]; + +static uint16 *waveform[2] = { fullsintable, halfsintable }; + +/* LFO Table */ +static int32 pmtable[PM_PG_WIDTH]; +static int32 amtable[AM_PG_WIDTH]; + +/* Phase delta for LFO */ +static uint32 pm_dphase; +static uint32 am_dphase; + +/* dB to Liner table */ +static int16 DB2LIN_TABLE[(DB_MUTE + DB_MUTE) * 2]; + +/* Liner to Log curve conversion table (for Attack rate). */ +static 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 uint32 dphaseARTable[16][16]; +/* Phase incr table for Decay and Release */ +static uint32 dphaseDRTable[16][16]; + +/* KSL + TL Table */ +static uint32 tllTable[16][8][1 << TL_BITS][4]; +static int32 rksTable[2][8][2]; + +/* Phase incr table for PG */ +static uint32 dphaseTable[512][8][16]; + +/*************************************************** + + Create tables + +****************************************************/ +INLINE static int32 Min(int32 i, int32 j) { + if (i < j) + return i; + else + return j; +} + +/* Table for AR to LogCurve. */ +static void makeAdjustTable(void) { + int32 i; + + AR_ADJUST_TABLE[0] = (1 << EG_BITS); + for (i = 1; i < 128; i++) + AR_ADJUST_TABLE[i] = (uint16)((double)(1 << EG_BITS) - 1 - (1 << EG_BITS) * log(i) / log(128)); +} + + +/* Table for dB(0 -- (1<= DB_MUTE) DB2LIN_TABLE[i] = 0; + DB2LIN_TABLE[i + DB_MUTE + DB_MUTE] = (int16)(-DB2LIN_TABLE[i]); + } +} + +/* Liner(+0.0 - +1.0) to dB((1<> (20 - DP_BITS)); +} + +static void makeTllTable(void) { +#define dB2(x) ((x) * 2) + + static double kltable[16] = { + dB2(0.000), dB2(9.000), dB2(12.000), dB2(13.875), dB2(15.000), dB2(16.125), dB2(16.875), dB2(17.625), + dB2(18.000), dB2(18.750), dB2(19.125), dB2(19.500), dB2(19.875), dB2(20.250), dB2(20.625), dB2(21.000) + }; + + int32 tmp; + 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 = (int32)(kltable[fnum] - dB2(3.000) * (7 - block)); + if (tmp <= 0) + tllTable[fnum][block][TL][KL] = TL2EG(TL); + else + tllTable[fnum][block][TL][KL] = (uint32)((tmp >> (3 - KL)) / EG_STEP) + TL2EG(TL); + } + } +} + +/* Rate Table for Attack */ +static void makeDphaseARTable(void) { + int32 AR, Rks, RM, RL; + 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: + dphaseARTable[AR][Rks] = rate_adjust((3 * (RL + 4) << (RM + 1))); + break; + } + } +} + +/* Rate Table for Decay and Release */ +static void makeDphaseDRTable(void) { + int32 DR, Rks, RM, RL; + + 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: + dphaseDRTable[DR][Rks] = rate_adjust((RL + 4) << (RM - 1)); + break; + } + } +} + +static void makeRksTable(void) { + 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 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, 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, 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, int32 c, 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, int32 c, int32 volume) { + CAR(opll, c)->volume = volume; +} + +INLINE static void setSlotVolume(OPLL_SLOT * slot, int32 volume) { + slot->volume = volume; +} + +/* Set F-Number ( fnum : 9bit ) */ +INLINE static void setFnumber(OPLL * opll, int32 c, int32 fnum) { + CAR(opll, c)->fnum = fnum; + MOD(opll, c)->fnum = fnum; +} + +/* Set Block data (block : 3bit ) */ +INLINE static void setBlock(OPLL * opll, int32 c, 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 = (uint32)rate_adjust(PM_SPEED * PM_DP_WIDTH / (clk / 72)); + am_dphase = (uint32)rate_adjust(AM_SPEED * AM_DP_WIDTH / (clk / 72)); +} + +static void maketables(uint32 c, 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(uint32 clk, 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) { + 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); + + opll->realstep = (uint32)((1 << 31) / rate); + opll->opllstep = (uint32)((1 << 31) / (clk / 72)); + opll->oplltime = 0; +} + +/* Force Refresh (When external program changes some parameters). */ +void OPLL_forceRefresh(OPLL * opll) { + 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, uint32 r) { + if (opll->quality) + rate = 49716; + else + rate = r; + internal_refresh(); + rate = r; +} + +void OPLL_set_quality(OPLL * opll, 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, 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, int32 lfo) { +#define S2E(x) (SL2EG((int32)(x / SL_STEP)) << (EG_DP_BITS - EG_BITS)) + + static 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) + }; + + 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 int32 calc_slot_car(OPLL_SLOT * slot, 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 int32 calc_slot_mod(OPLL_SLOT * slot) { + 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 int16 calc(OPLL * opll) { + int32 inst = 0, out = 0; + 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 (int16)out; +} + +void OPLL_fillbuf(OPLL* opll, int32 *buf, int32 len, int shift) { + while (len > 0) { + *buf += (calc(opll) + 32768) << shift; + buf++; + len--; + } +} + +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 = (int16)(((double)opll->next * (opll->opllstep - opll->oplltime) + + (double)opll->prev * opll->oplltime) / opll->opllstep); + + return (int16)opll->out; +} + +uint32 OPLL_setMask(OPLL * opll, uint32 mask) { + uint32 ret; + + if (opll) { + ret = opll->mask; + opll->mask = mask; + return ret; + } else + return 0; +} + +uint32 OPLL_toggleMask(OPLL * opll, uint32 mask) { + uint32 ret; + + if (opll) { + ret = opll->mask; + opll->mask ^= mask; + return ret; + } else + return 0; +} + +/**************************************************** + + I/O Ctrl + +*****************************************************/ + +static void setInstrument(OPLL * opll, uint32 i, uint32 inst) { + const 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, uint32 reg, uint32 data) { + 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, uint32 adr, uint32 val) { + if (adr & 1) + OPLL_writeReg(opll, opll->adr, val); + else + opll->adr = val; +} + diff --git a/src/boards/emu2413.h b/src/boards/emu2413.h new file mode 100644 index 0000000..06eccd8 --- /dev/null +++ b/src/boards/emu2413.h @@ -0,0 +1,138 @@ +#ifndef _EMU2413_H_ +#define _EMU2413_H_ + +#include +#include +#include +#include +#include "../fceu-types.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 + + +#ifdef __cplusplus +extern "C" { +#endif + +#define PI 3.14159265358979323846 + +enum { OPLL_VRC7_TONE=0 }; + +/* voice data */ +typedef struct { + uint32 TL, FB, EG, ML, AR, DR, SL, RR, KR, KL, AM, PM, WF; +} OPLL_PATCH; + +/* slot */ +typedef struct { + OPLL_PATCH patch; + + int32 type; /* 0 : modulator 1 : carrier */ + + /* OUTPUT */ + int32 feedback; + int32 output[2]; /* Output value of slot */ + + /* for Phase Generator (PG) */ + uint16 *sintbl; /* Wavetable */ + uint32 phase; /* Phase */ + uint32 dphase; /* Phase increment amount */ + uint32 pgout; /* output */ + + /* for Envelope Generator (EG) */ + int32 fnum; /* F-Number */ + int32 block; /* Block */ + int32 volume; /* Current volume */ + int32 sustine; /* Sustine 1 = ON, 0 = OFF */ + uint32 tll; /* Total Level + Key scale level*/ + uint32 rks; /* Key scale offset (Rks) */ + int32 eg_mode; /* Current state */ + uint32 eg_phase; /* Phase */ + uint32 eg_dphase; /* Phase increment amount */ + uint32 egout; /* output */ +} OPLL_SLOT; + +/* Mask */ +#define OPLL_MASK_CH(x) (1 << (x)) + +/* opll */ +typedef struct { + uint32 adr; + int32 out; + + uint32 realstep; + uint32 oplltime; + uint32 opllstep; + int32 prev, next; + + /* Register */ + uint8 LowFreq[6]; + uint8 HiFreq[6]; + uint8 InstVol[6]; + + uint8 CustInst[8]; + + int32 slot_on_flag[6 * 2]; + + /* Pitch Modulator */ + uint32 pm_phase; + int32 lfo_pm; + + /* Amp Modulator */ + int32 am_phase; + int32 lfo_am; + + uint32 quality; + + /* Channel Data */ + int32 patch_number[6]; + int32 key_status[6]; + + /* Slot */ + OPLL_SLOT slot[6 * 2]; + + uint32 mask; +} OPLL; + +/* Create Object */ +OPLL *OPLL_new(uint32 clk, uint32 rate); +void OPLL_delete(OPLL *); + +/* Setup */ +void OPLL_reset(OPLL *); +void OPLL_set_rate(OPLL *opll, uint32 r); +void OPLL_set_quality(OPLL *opll, uint32 q); + +/* Port/Register access */ +void OPLL_writeIO(OPLL *, uint32 reg, uint32 val); +void OPLL_writeReg(OPLL *, uint32 reg, uint32 val); + +/* Synthsize */ +int16 OPLL_calc(OPLL *); + +/* Misc */ +void OPLL_forceRefresh(OPLL *); + +/* Channel Mask */ +uint32 OPLL_setMask(OPLL *, uint32 mask); +uint32 OPLL_toggleMask(OPLL *, uint32 mask); + + +void OPLL_fillbuf(OPLL* opll, int32 *buf, int32 len, int shift); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/boards/famicombox.c b/src/boards/famicombox.c new file mode 100644 index 0000000..1930ad9 --- /dev/null +++ b/src/boards/famicombox.c @@ -0,0 +1,115 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 regs[8]; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { regs, 8, "REGS" }, + { 0 } +}; + +static void Sync(void) { + setprg2r(0x10, 0x0800, 0); + setprg2r(0x10, 0x1000, 1); + setprg2r(0x10, 0x1800, 2); + setprg8r(0x10, 0x6000, 1); + setprg16(0x8000, 0); + setprg16(0xC000, ~0); + setchr8(0); +} + +//static DECLFW(SSSNROMWrite) +//{ +// CartBW(A,V); +//} + +static DECLFW(SSSNROMWrite) { +// FCEU_printf("write %04x %02x\n",A,V); +// regs[A&7] = V; +} + +static DECLFR(SSSNROMRead) { +// FCEU_printf("read %04x\n",A); + switch (A & 7) { + case 0: return regs[0] = 0xff; // clear all exceptions + case 2: return 0xc0; // DIP selftest + freeplay + case 3: return 0x00; // 0, 1 - attract + // 2 + // 4 - menu + // 8 - self check and game casette check + // 10 - lock? + // 20 - game title & count display + case 7: return 0x22; // TV type, key not turned, relay B + default: return 0; + } +} + +static void SSSNROMPower(void) { + regs[0] = regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = regs[6] = 0; + regs[7] = 0xff; + Sync(); + memset(WRAM, 0x00, WRAMSIZE); +// SetWriteHandler(0x0000,0x1FFF,SSSNROMRamWrite); + SetReadHandler(0x0800, 0x1FFF, CartBR); + SetWriteHandler(0x0800, 0x1FFF, CartBW); + SetReadHandler(0x5000, 0x5FFF, SSSNROMRead); + SetWriteHandler(0x5000, 0x5FFF, SSSNROMWrite); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void SSSNROMReset(void) { + regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = regs[6] = 0; +} + +static void SSSNROMClose(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void SSSNROMIRQHook(void) { +// X6502_IRQBegin(FCEU_IQEXT); +} + +static void StateRestore(int version) { + Sync(); +} + +void SSSNROM_Init(CartInfo *info) { + info->Reset = SSSNROMReset; + info->Power = SSSNROMPower; + info->Close = SSSNROMClose; + GameHBIRQHook = SSSNROMIRQHook; + GameStateRestore = StateRestore; + + WRAMSIZE = 16384; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/ffe.c b/src/boards/ffe.c new file mode 100644 index 0000000..48b1c70 --- /dev/null +++ b/src/boards/ffe.c @@ -0,0 +1,152 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FFE Copier Mappers + * + */ + +#include "mapinc.h" + +static uint8 preg[4], creg[8], latch, ffemode; +static uint8 IRQa, mirr; +static int32 IRQCount, IRQLatch; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { preg, 4, "PREG" }, + { creg, 8, "CREG" }, + { &mirr, 1, "MIRR" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { &IRQLatch, 4, "IRQL" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + if (ffemode) { + int i; + for (i = 0; i < 8; i++) setchr1(i << 10, creg[i]); + setprg8(0x8000, preg[0]); + setprg8(0xA000, preg[1]); + setprg8(0xC000, preg[2]); + setprg8(0xE000, preg[3]); + } else { + setchr8(latch & 3); + setprg16(0x8000, (latch >> 2) & 0x3F); + setprg16(0xc000, 0x7); + } + switch (mirr) { + case 0: setmirror(MI_0); break; + case 1: setmirror(MI_1); break; + case 2: setmirror(MI_V); break; + case 3: setmirror(MI_H); break; + } +} + +static DECLFW(FFEWriteMirr) { + mirr = ((A << 1) & 2) | ((V >> 4) & 1); + Sync(); +} + +static DECLFW(FFEWriteIRQ) { + switch (A) { + case 0x4501: IRQa = 0; X6502_IRQEnd(FCEU_IQEXT); break; + case 0x4502: IRQCount &= 0xFF00; IRQCount |= V; X6502_IRQEnd(FCEU_IQEXT); break; + case 0x4503: IRQCount &= 0x00FF; IRQCount |= V << 8; IRQa = 1; X6502_IRQEnd(FCEU_IQEXT); break; + } +} + +static DECLFW(FFEWritePrg) { + preg[A & 3] = V; + Sync(); +} + +static DECLFW(FFEWriteChr) { + creg[A & 7] = V; + Sync(); +} + +static DECLFW(FFEWriteLatch) { + latch = V; + Sync(); +} + +static void FFEPower(void) { + preg[3] = ~0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x42FE, 0x42FF, FFEWriteMirr); + SetWriteHandler(0x4500, 0x4503, FFEWriteIRQ); + SetWriteHandler(0x4504, 0x4507, FFEWritePrg); + SetWriteHandler(0x4510, 0x4517, FFEWriteChr); + SetWriteHandler(0x4510, 0x4517, FFEWriteChr); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, FFEWriteLatch); +} + +static void FP_FASTAPASS(1) FFEIRQHook(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount >= 0x10000) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + IRQCount = 0; + } + } +} + +static void FFEClose(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper6_Init(CartInfo *info) { + ffemode = 0; + mirr = ((info->mirror & 1) ^ 1) | 2; + + info->Power = FFEPower; + info->Close = FFEClose; + MapIRQHook = FFEIRQHook; + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + + AddExState(&StateRegs, ~0, 0, 0); +} + +void Mapper17_Init(CartInfo *info) { + ffemode = 1; + Mapper6_Init(info); +} diff --git a/src/boards/fk23c.c b/src/boards/fk23c.c new file mode 100644 index 0000000..66e0044 --- /dev/null +++ b/src/boards/fk23c.c @@ -0,0 +1,203 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 unromchr; +static uint32 dipswitch = 0; +static uint8 *CHRRAM = NULL; +static uint32 CHRRAMSize; + +static void BMCFK23CCW(uint32 A, uint8 V) { + if (EXPREGS[0] & 0x40) + setchr8(EXPREGS[2] | unromchr); + else if (EXPREGS[0] & 0x20) { + setchr1r(0x10, A, V); + } else { + uint16 base = (EXPREGS[2] & 0x7F) << 3; + if (EXPREGS[3] & 2) { + int cbase = (MMC3_cmd & 0x80) << 5; + setchr1(A, V | base); + setchr1(0x0000 ^ cbase, DRegBuf[0] | base); + setchr1(0x0400 ^ cbase, EXPREGS[6] | base); + setchr1(0x0800 ^ cbase, DRegBuf[1] | base); + setchr1(0x0c00 ^ cbase, EXPREGS[7] | base); + } else + setchr1(A, V | base); + } +} + +static void BMCFK23CPW(uint32 A, uint8 V) { + uint32 bank = (EXPREGS[1] & 0x1F); + uint32 hiblock = ((EXPREGS[0] & 8) << 4) | ((EXPREGS[0] & 0x80) << 1) | (UNIFchrrama ? ((EXPREGS[2] & 0x40) << 3) : 0); + uint32 block = (EXPREGS[1] & 0x60) | hiblock; + uint32 extra = (EXPREGS[3] & 2); + switch (EXPREGS[0] & 7) { + case 0: + setprg8(A, (block << 1) | (V & 0x3F)); + if (extra) { + setprg8(0xC000, EXPREGS[4]); + setprg8(0xE000, EXPREGS[5]); + } + break; + case 1: + setprg8(A, ((hiblock | (EXPREGS[1] & 0x70)) << 1) | (V & 0x1F)); + if (extra) { + setprg8(0xC000, EXPREGS[4]); + setprg8(0xE000, EXPREGS[5]); + } + break; + case 2: + setprg8(A, ((hiblock | (EXPREGS[1] & 0x78)) << 1) | (V & 0x0F)); + if (extra) { + setprg8(0xC000, EXPREGS[4]); + setprg8(0xE000, EXPREGS[5]); + } + break; + case 3: + setprg16(0x8000, (bank | block)); + setprg16(0xC000, (bank | block)); + break; + case 4: + setprg32(0x8000, (bank | block) >> 1); + break; + } + setprg8r(0x10, 0x6000, A001B & 3); +} + +static DECLFW(BMCFK23CHiWrite) { + if (EXPREGS[0] & 0x40) { + if (EXPREGS[0] & 0x30) + unromchr = 0; + else { + 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 + if (A < 0xC000) { + if (UNIFchrrama) { // hacky... strange behaviour, must be bit scramble due to pcb layot restrictions + // check if it not interfer with other dumps + if ((A == 0x8000) && (V == 0x46)) + V = 0x47; + else if ((A == 0x8000) && (V == 0x47)) + V = 0x46; + } + MMC3_CMDWrite(A, V); + FixMMC3PRG(MMC3_cmd); + } else + MMC3_IRQWrite(A, V); + } +} + +static DECLFW(BMCFK23CWrite) { +// FCEU_printf("lo %04x:%02x\n",A,V); + if (dipswitch) { // нулевой дип берет любые записи по дефолту, дальше идет выбор + if (A & (1 << (dipswitch + 3))) { + EXPREGS[A & 3] = V; +// FCEU_printf(" reg %d set!\n",A&3); + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } + } else { + EXPREGS[A & 3] = V; +// FCEU_printf(" reg %d set!\n",A&3); + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } + if (EXPREGS[3] & 2) + EXPREGS[0] &= ~7; // hacky hacky! if someone wants extra banking, then for sure doesn't want mode 4 for it! (allow to run A version boards on normal mapper) +} + +static void BMCFK23CReset(void) { + if (dipswitch <= 8) + dipswitch++; + else + dipswitch = 0; + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; + EXPREGS[4] = EXPREGS[5] = EXPREGS[6] = EXPREGS[7] = 0xFF; + MMC3RegReset(); + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void BMCFK23CPower(void) { + GenMMC3Power(); + EXPREGS[0] = 4; + EXPREGS[1] = 0xFF; + EXPREGS[2] = EXPREGS[3] = 0; + dipswitch = 0; + EXPREGS[4] = EXPREGS[5] = EXPREGS[6] = EXPREGS[7] = 0xFF; + SetWriteHandler(0x5000, 0x5fff, BMCFK23CWrite); + SetWriteHandler(0x8000, 0xFFFF, BMCFK23CHiWrite); + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void BMCFK23CAPower(void) { + GenMMC3Power(); + dipswitch = 0; + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = 0; + EXPREGS[4] = EXPREGS[5] = EXPREGS[6] = EXPREGS[7] = 0xFF; + SetWriteHandler(0x5000, 0x5fff, BMCFK23CWrite); + SetWriteHandler(0x8000, 0xFFFF, BMCFK23CHiWrite); + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void BMCFK23CAClose(void) { + if (CHRRAM) + FCEU_gfree(CHRRAM); + CHRRAM = NULL; +} + +void BMCFK23C_Init(CartInfo *info) { + GenMMC3_Init(info, 512, 256, 128, 0); + cwrap = BMCFK23CCW; + pwrap = BMCFK23CPW; + info->Power = BMCFK23CPower; + info->Reset = BMCFK23CReset; + AddExState(EXPREGS, 8, 0, "EXPR"); + AddExState(&unromchr, 1, 0, "UCHR"); + AddExState(&dipswitch, 1, 0, "DPSW"); +} + +void BMCFK23CA_Init(CartInfo *info) { + GenMMC3_Init(info, 512, 256, 128, 0); + cwrap = BMCFK23CCW; + pwrap = BMCFK23CPW; + info->Power = BMCFK23CAPower; + info->Reset = BMCFK23CReset; + info->Close = BMCFK23CAClose; + + CHRRAMSize = 8192; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSize, 1); + AddExState(CHRRAM, CHRRAMSize, 0, "CRAM"); + + AddExState(EXPREGS, 8, 0, "EXPR"); + AddExState(&unromchr, 1, 0, "UCHR"); + AddExState(&dipswitch, 1, 0, "DPSW"); +} diff --git a/src/boards/ghostbusters63in1.c b/src/boards/ghostbusters63in1.c new file mode 100644 index 0000000..c4ca48a --- /dev/null +++ b/src/boards/ghostbusters63in1.c @@ -0,0 +1,96 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * 63in1 ghostbusters + */ + +#include "mapinc.h" + +static uint8 reg[2], bank; +static uint8 banks[4] = { 0, 0, 1, 2 }; +static uint8 *CHRROM = NULL; +static uint32 CHRROMSIZE; + +static SFORMAT StateRegs[] = +{ + { reg, 2, "REGS" }, + { &bank, 1, "BANK" }, + { 0 } +}; + +static void Sync(void) { + if (reg[0] & 0x20) { + setprg16r(banks[bank], 0x8000, reg[0] & 0x1F); + setprg16r(banks[bank], 0xC000, reg[0] & 0x1F); + } else + setprg32r(banks[bank], 0x8000, (reg[0] >> 1) & 0x0F); + if (reg[1] & 2) + setchr8r(0x10, 0); + else + setchr8(0); + setmirror((reg[0] & 0x40) >> 6); +} + +static DECLFW(BMCGhostbusters63in1Write) { + reg[A & 1] = V; + bank = ((reg[0] & 0x80) >> 7) | ((reg[1] & 1) << 1); +// FCEU_printf("reg[0]=%02x, reg[1]=%02x, bank=%02x\n",reg[0],reg[1],bank); + Sync(); +} + +static DECLFR(BMCGhostbusters63in1Read) { + if (bank == 1) + return X.DB; + else + return CartBR(A); +} + +static void BMCGhostbusters63in1Power(void) { + reg[0] = reg[1] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, BMCGhostbusters63in1Read); + SetWriteHandler(0x8000, 0xFFFF, BMCGhostbusters63in1Write); +} + +static void BMCGhostbusters63in1Reset(void) { + reg[0] = reg[1] = 0; +} + +static void StateRestore(int version) { + Sync(); +} + +static void BMCGhostbusters63in1Close(void) { + if (CHRROM) + FCEU_gfree(CHRROM); + CHRROM = NULL; +} + +void BMCGhostbusters63in1_Init(CartInfo *info) { + info->Reset = BMCGhostbusters63in1Reset; + info->Power = BMCGhostbusters63in1Power; + info->Close = BMCGhostbusters63in1Close; + + CHRROMSIZE = 8192; // dummy CHRROM, VRAM disable + CHRROM = (uint8*)FCEU_gmalloc(CHRROMSIZE); + SetupCartPRGMapping(0x10, CHRROM, CHRROMSIZE, 0); + AddExState(CHRROM, CHRROMSIZE, 0, "CROM"); + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/gs-2004.c b/src/boards/gs-2004.c new file mode 100644 index 0000000..43f7068 --- /dev/null +++ b/src/boards/gs-2004.c @@ -0,0 +1,63 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg, mirr; +static SFORMAT StateRegs[] = +{ + { ®, 1, "REGS" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(1, 0x6000, 0); + setprg32(0x8000, reg); + setchr8(0); +} + +static DECLFW(BMCGS2004Write) { + reg = V; + Sync(); +} + +static void BMCGS2004Power(void) { + reg = ~0; + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, BMCGS2004Write); +} + +static void BMCGS2004Reset(void) { + reg = ~0; +} + +static void StateRestore(int version) { + Sync(); +} + +void BMCGS2004_Init(CartInfo *info) { + info->Reset = BMCGS2004Reset; + info->Power = BMCGS2004Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/gs-2013.c b/src/boards/gs-2013.c new file mode 100644 index 0000000..704a8cf --- /dev/null +++ b/src/boards/gs-2013.c @@ -0,0 +1,63 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg, mirr; +static SFORMAT StateRegs[] = +{ + { ®, 1, "REGS" }, + { &mirr, 1, "MIRR" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0, 0x6000, ~0); + setprg32r((reg & 8) >> 3, 0x8000, reg); + setchr8(0); +} + +static DECLFW(BMCGS2013Write) { + reg = V; + Sync(); +} + +static void BMCGS2013Power(void) { + reg = ~0; + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, BMCGS2013Write); +} + +static void BMCGS2013Reset(void) { + reg = ~0; +} + +static void StateRestore(int version) { + Sync(); +} + +void BMCGS2013_Init(CartInfo *info) { + info->Reset = BMCGS2013Reset; + info->Power = BMCGS2013Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/h2288.c b/src/boards/h2288.c new file mode 100644 index 0000000..1fb72af --- /dev/null +++ b/src/boards/h2288.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 void H2288Power(void) { + EXPREGS[0] = EXPREGS[1] = 0; + GenMMC3Power(); +// SetReadHandler(0x5000,0x5FFF,H2288Read); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x5FFF, H2288WriteLo); + SetWriteHandler(0x8000, 0x9FFF, 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/src/boards/karaoke.c b/src/boards/karaoke.c new file mode 100644 index 0000000..81d9dbc --- /dev/null +++ b/src/boards/karaoke.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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, "LATC"); +} diff --git a/src/boards/kof97.c b/src/boards/kof97.c new file mode 100644 index 0000000..eb6c484 --- /dev/null +++ b/src/boards/kof97.c @@ -0,0 +1,46 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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/src/boards/le05.c b/src/boards/le05.c new file mode 100644 index 0000000..efbe13f --- /dev/null +++ b/src/boards/le05.c @@ -0,0 +1,62 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2011 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 chr; +static SFORMAT StateRegs[] = +{ + { &chr, 1, "CHR" }, + { 0 } +}; + +static void Sync(void) { + setprg2r(0, 0xE000, 0); + setprg2r(0, 0xE800, 0); + setprg2r(0, 0xF000, 0); + setprg2r(0, 0xF800, 0); + + setprg8r(1, 0x6000, 3); + setprg8r(1, 0x8000, 0); + setprg8r(1, 0xA000, 1); + setprg8r(1, 0xC000, 2); + + setchr8(chr & 1); + setmirror(MI_V); +} + +static DECLFW(LE05Write) { + chr = V; + Sync(); +} + +static void LE05Power(void) { + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, LE05Write); +} + +void LE05_Init(CartInfo *info) { + info->Power = LE05Power; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/lh32.c b/src/boards/lh32.c new file mode 100644 index 0000000..2150aee --- /dev/null +++ b/src/boards/lh32.c @@ -0,0 +1,78 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REG" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x6000, reg); + setprg8(0x8000, ~3); + setprg8(0xa000, ~2); + setprg8r(0x10, 0xc000, 0); + setprg8(0xe000, ~0); + setchr8(0); +} + +static DECLFW(LH32Write) { + reg = V; + Sync(); +} + +static void LH32Power(void) { + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0xC000, 0xDFFF, CartBW); + SetWriteHandler(0x6000, 0x6000, LH32Write); +} + +static void LH32Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void LH32_Init(CartInfo *info) { + info->Power = LH32Power; + info->Close = LH32Close; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/lh53.c b/src/boards/lh53.c new file mode 100644 index 0000000..a0c56b0 --- /dev/null +++ b/src/boards/lh53.c @@ -0,0 +1,107 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 reg, IRQa; +static int32 IRQCount; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { ®, 1, "REG" }, + { &IRQa, 1, "IRQA" }, + { &IRQCount, 4, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + setchr8(0); + setprg8(0x6000, reg); + setprg8(0x8000, 0xc); + setprg4(0xa000, (0xd << 1)); + setprg2(0xb000, (0xd << 2) + 2); + setprg2r(0x10, 0xb800, 4); + setprg2r(0x10, 0xc000, 5); + setprg2r(0x10, 0xc800, 6); + setprg2r(0x10, 0xd000, 7); + setprg2(0xd800, (0xe << 2) + 3); + setprg8(0xe000, 0xf); +} + +static DECLFW(LH53RamWrite) { + WRAM[(A - 0xB800) & 0x1FFF] = V; +} + +static DECLFW(LH53Write) { + reg = V; + Sync(); +} + +static DECLFW(LH53IRQaWrite) { + IRQa = V & 2; + IRQCount = 0; + if (!IRQa) + X6502_IRQEnd(FCEU_IQEXT); +} + +static void FP_FASTAPASS(1) LH53IRQ(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount > 7560) + X6502_IRQBegin(FCEU_IQEXT); + } +} + +static void LH53Power(void) { + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0xB800, 0xD7FF, LH53RamWrite); + SetWriteHandler(0xE000, 0xEFFF, LH53IRQaWrite); + SetWriteHandler(0xF000, 0xFFFF, LH53Write); +} + +static void LH53Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void LH53_Init(CartInfo *info) { + info->Power = LH53Power; + info->Close = LH53Close; + MapIRQHook = LH53IRQ; + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/malee.c b/src/boards/malee.c new file mode 100644 index 0000000..84c353a --- /dev/null +++ b/src/boards/malee.c @@ -0,0 +1,43 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2002 Xodnizel + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * FDS Conversion + * + */ + +#include "mapinc.h" + +static uint8 WRAM[2048]; + +static void MALEEPower(void) { + setprg2r(0x10, 0x7000, 0); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x6000, 0x67FF, CartBR); + SetReadHandler(0x7000, 0x77FF, CartBR); + SetWriteHandler(0x7000, 0x77FF, CartBW); + setprg2r(1, 0x6000, 0); + setprg32(0x8000, 0); + setchr8(0); +} + +void MALEE_Init(CartInfo *info) { + info->Power = MALEEPower; + SetupCartPRGMapping(0x10, WRAM, 2048, 1); + AddExState(WRAM, 2048, 0, "WRAM"); +} diff --git a/src/boards/mapinc.h b/src/boards/mapinc.h new file mode 100644 index 0000000..7301928 --- /dev/null +++ b/src/boards/mapinc.h @@ -0,0 +1,11 @@ +#include "../fceu-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 diff --git a/src/boards/mihunche.c b/src/boards/mihunche.c new file mode 100644 index 0000000..512aa0f --- /dev/null +++ b/src/boards/mihunche.c @@ -0,0 +1,68 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint16 latche; + +static SFORMAT StateRegs[] = +{ + { &latche, 2, "LATC" }, + { 0 } +}; + +static void Sync(void) { + setprg32(0x8000, 0); + if(CHRsize[0] == 8192) { + setchr4(0x0000, latche & 1); + setchr4(0x1000, latche & 1); + } else { + setchr8(latche & 1); // actually, my bad, overdumped roms, the real CHR size if 8K + } + setmirror(MI_0 + (latche & 1)); +} + +static DECLFW(UNLCC21Write1) { + latche = A; + Sync(); +} + +static DECLFW(UNLCC21Write2) { + latche = V; + Sync(); +} + +static void UNLCC21Power(void) { + latche = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8001, 0xFFFF, UNLCC21Write1); + SetWriteHandler(0x8000, 0x8000, UNLCC21Write2); // another one many-in-1 mapper, there is a lot of similar carts with little different wirings +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLCC21_Init(CartInfo *info) { + info->Power = UNLCC21Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/mmc1.c b/src/boards/mmc1.c new file mode 100644 index 0000000..41877fe --- /dev/null +++ b/src/boards/mmc1.c @@ -0,0 +1,388 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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, is171; + +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) { + if (!is171) + 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; + + /* 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; +// FCEU_printf("Write %04x:%02x\n",A,V); + if (V & 0x80) { + DRegs[0] |= 0xC; + BufferShift = Buffer = 0; + MMC1PRG(); + lreset = timestampbase + timestamp; + return; + } + + Buffer |= (V & 1) << (BufferShift++); + + if (BufferShift == 5) { +// FCEU_printf("REG[%d]=%02x\n",n,Buffer); + 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 NWCIRQHook(int a) { + if (!(NWCRec & 0x10)) { + NWCIRQCount += a; + if ((NWCIRQCount | (NWCDIP << 25)) >= 0x3e000000) { + NWCIRQCount = 0; + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void NWCCHRHook(uint32 A, uint8 V) { + if ((V & 0x10)) { // && !(NWCRec&0x10)) + NWCIRQCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + } + + NWCRec = V; + if (V & 0x08) + MMC1PRG(); + else + setprg32(0x8000, (V >> 1) & 3); +} + +static void NWCPRGHook(uint32 A, uint8 V) { + if (NWCRec & 0x8) + setprg16(A, 8 | (V & 0x7)); + else + setprg32(0x8000, (NWCRec >> 1) & 3); +} + +static void NWCPower(void) { + GenMMC1Power(); + setchr8r(0, 0); +} + +void Mapper105_Init(CartInfo *info) { + GenMMC1Init(info, 256, 256, 8, 0); + MMC1CHRHook4 = NWCCHRHook; + MMC1PRGHook16 = NWCPRGHook; + MapIRQHook = NWCIRQHook; + info->Power = NWCPower; +} + +static void GenMMC1Power(void) { + lreset = 0; + if (mmc1opts & 1) { + FCEU_CheatAddRAM(8, 0x6000, WRAM); + if (mmc1opts & 4) + FCEU_dwmemset(WRAM, 0, 8192) + else if (!(mmc1opts & 2)) + FCEU_dwmemset(WRAM, 0, 8192); + } + SetWriteHandler(0x8000, 0xFFFF, MMC1_write); + SetReadHandler(0x8000, 0xFFFF, CartBR); + + if (mmc1opts & 1) { + SetReadHandler(0x6000, 0x7FFF, MAWRAM); + SetWriteHandler(0x6000, 0x7FFF, MBWRAM); + setprg8r(0x10, 0x6000, 0); + } + + MMC1CMReset(); +} + +static void GenMMC1Close(void) { + if (CHRRAM) + FCEU_gfree(CHRRAM); + if (WRAM) + FCEU_gfree(WRAM); + CHRRAM = WRAM = NULL; +} + +static void GenMMC1Init(CartInfo *info, int prg, int chr, int wram, int battery) { + is155 = 0; + + info->Close = GenMMC1Close; + MMC1PRGHook16 = MMC1CHRHook4 = 0; + mmc1opts = 0; + PRGmask16[0] &= (prg >> 14) - 1; + CHRmask4[0] &= (chr >> 12) - 1; + CHRmask8[0] &= (chr >> 13) - 1; + + if (wram) { + WRAM = (uint8*)FCEU_gmalloc(wram * 1024); + mmc1opts |= 1; + if (wram > 8) mmc1opts |= 4; + SetupCartPRGMapping(0x10, WRAM, wram * 1024, 1); + AddExState(WRAM, wram * 1024, 0, "WRAM"); + if (battery) { + mmc1opts |= 2; + info->SaveGame[0] = WRAM + ((mmc1opts & 4) ? 8192 : 0); + info->SaveGameLen[0] = 8192; + } + } + if (!chr) { + CHRRAM = (uint8*)FCEU_gmalloc(8192); + SetupCartCHRMapping(0, CHRRAM, 8192, 1); + AddExState(CHRRAM, 8192, 0, "CHRR"); + } + AddExState(DRegs, 4, 0, "DREG"); + + info->Power = GenMMC1Power; + GameStateRestore = MMC1_Restore; + AddExState(&lreset, 8, 1, "LRST"); + AddExState(&Buffer, 1, 1, "BFFR"); + AddExState(&BufferShift, 1, 1, "BFRS"); +} + +void Mapper1_Init(CartInfo *info) { + int ws = DetectMMC1WRAMSize(info->CRC32); + GenMMC1Init(info, 512, 256, ws, info->battery); +} + +/* Same as mapper 1, without respect for WRAM enable bit. */ +void Mapper155_Init(CartInfo *info) { + GenMMC1Init(info, 512, 256, 8, info->battery); + is155 = 1; +} + +/* Same as mapper 1, with different (or without) mirroring control. */ +/* Kaiser KS7058 board, KS203 custom chip */ +void Mapper171_Init(CartInfo *info) { + GenMMC1Init(info, 32, 32, 0, 0); + is171 = 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/src/boards/mmc2and4.c b/src/boards/mmc2and4.c new file mode 100644 index 0000000..194163b --- /dev/null +++ b/src/boards/mmc2and4.c @@ -0,0 +1,135 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include "mapinc.h" + +static uint8 is10; +static uint8 creg[4], latch0, latch1, preg, mirr; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { creg, 4, "CREG" }, + { &preg, 1, "PREG" }, + { &mirr, 1, "MIRR" }, + { &latch0, 1, "LAT0" }, + { &latch1, 1, "LAT1" }, + { 0 } +}; + +static void Sync(void) { + if (is10) { + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, preg); + setprg16(0xC000, ~0); + } else { + setprg8(0x8000, preg); + setprg8(0xA000, ~2); + setprg8(0xC000, ~1); + setprg8(0xE000, ~0); + } + setchr4(0x0000, creg[latch0]); + setchr4(0x1000, creg[latch1 + 2]); + setmirror(mirr); +} + +DECLFW(MMC2and4Write) { + switch (A & 0xF000) { + case 0xA000: preg = V; Sync(); break; + case 0xB000: creg[0] = V; Sync(); break; + case 0xC000: creg[1] = V; Sync(); break; + case 0xD000: creg[2] = V; Sync(); break; + case 0xE000: creg[3] = V; Sync(); break; + case 0xF000: mirr = (V & 1) ^ 1; Sync(); break; + } +} + +static void FP_FASTAPASS(1) MMC2and4PPUHook(uint32 A) { + uint8 l, h = A >> 8; + if (h >= 0x20 || ((h & 0xF) != 0xF)) + return; + l = A & 0xF0; + if (h < 0x10) { + if (l == 0xD0) { + latch0 = 0; + setchr4(0x0000, creg[0]); + } else if (l == 0xE0) { + latch0 = 1; + setchr4(0x0000, creg[1]); + } + } else { + if (l == 0xD0) { + latch1 = 0; + setchr4(0x1000, creg[2]); + } else if (l == 0xE0) { + latch1 = 1; + setchr4(0x1000, creg[3]); + } + } +} + +static void MMC2and4Power(void) { + preg = 0; + latch0 = latch1 = 1; + Sync(); + if (is10) { + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + } + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0xA000, 0xFFFF, MMC2and4Write); +} + +static void StateRestore(int version) { + Sync(); +} + +static void MMC2and4Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +void Mapper9_Init(CartInfo *info) { + is10 = 0; + info->Power = MMC2and4Power; + PPU_hook = MMC2and4PPUHook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +void Mapper10_Init(CartInfo *info) { + is10 = 1; + info->Power = MMC2and4Power; + info->Close = MMC2and4Close; + PPU_hook = MMC2and4PPUHook; + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/mmc3.c b/src/boards/mmc3.c new file mode 100644 index 0000000..9a3f1b4 --- /dev/null +++ b/src/boards/mmc3.c @@ -0,0 +1,1326 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Code for emulating iNES mappers 4,12,44,45,47,49,52,74,114,115,116,118, + 119,165,205,245,249,250,254 +*/ + +#include "mapinc.h" +#include "mmc3.h" + +uint8 MMC3_cmd; +uint8 *WRAM; +uint32 WRAMSIZE; +uint8 *CHRRAM; +uint32 CHRRAMSIZE; +uint8 DRegBuf[8]; +uint8 EXPREGS[8]; /* For bootleg games, mostly. */ +uint8 A000B, A001B; +uint8 mmc3opts = 0; + +#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 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]); + + if (mwrap) mwrap(A000B); +} + +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("bs %04x %02x\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); + break; + case 0xA001: + A001B = V; + 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) { + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static void GENCWRAP(uint32 A, uint8 V) { + setchr1(A, V); // Business Wars NEEDS THIS for 8K CHR-RAM +} + +static void GENPWRAP(uint32 A, uint8 V) { + setprg8(A, V & 0x7F); // [NJ102] Mo Dao Jie (C) has 1024Mb MMC3 BOARD, maybe something other will be broken +} + +static void GENMWRAP(uint8 V) { + A000B = V; + setmirror((V & 1) ^ 1); +} + +static void GENNOMWRAP(uint8 V) { + A000B = V; +} + +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 (WRAMSIZE == 1024) { + FCEU_CheatAddRAM(1, 0x7000, WRAM); + SetReadHandler(0x7000, 0x7FFF, MAWRAMMMC6); + SetWriteHandler(0x7000, 0x7FFF, MBWRAMMMC6); + } else { + FCEU_CheatAddRAM((WRAMSIZE & 0x1fff) >> 10, 0x6000, WRAM); + SetWriteHandler(0x6000, 0x6000 + ((WRAMSIZE - 1) & 0x1fff), CartBW); + SetReadHandler(0x6000, 0x6000 + ((WRAMSIZE - 1) & 0x1fff), CartBR); + setprg8r(0x10, 0x6000, 0); + } + if (!(mmc3opts & 2)) + FCEU_dwmemset(WRAM, 0, WRAMSIZE); + } + MMC3RegReset(); + if (CHRRAM) + FCEU_dwmemset(CHRRAM, 0, CHRRAMSIZE); +} + +static void GenMMC3Close(void) { + if (CHRRAM) + FCEU_gfree(CHRRAM); + if (WRAM) + FCEU_gfree(WRAM); + CHRRAM = WRAM = NULL; +} + +void GenMMC3_Init(CartInfo *info, int prg, int chr, int wram, int battery) { + pwrap = GENPWRAP; + cwrap = GENCWRAP; + mwrap = GENMWRAP; + + WRAMSIZE = 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(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + } + + if (battery) { + mmc3opts |= 2; + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + + AddExState(MMC3_StateRegs, ~0, 0, 0); + + info->Power = GenMMC3Power; + info->Reset = MMC3RegReset; + info->Close = GenMMC3Close; + + if (info->CRC32 == 0x5104833e) // Kick Master + GameHBIRQHook = MMC3_hb_KickMasterHack; + else if (info->CRC32 == 0x5a6860f1 || info->CRC32 == 0xae280e20)// Shougi Meikan '92/'93 + GameHBIRQHook = MMC3_hb_KickMasterHack; + else if (info->CRC32 == 0xfcd772eb) // PAL Star Wars, similar problem as Kick Master. + GameHBIRQHook = MMC3_hb_PALStarWarsHack; + else + GameHBIRQHook = MMC3_hb; + GameStateRestore = GenMMC3Restore; +} + +// ---------------------------------------------------------------------- +// -------------------------- MMC3 Based Code --------------------------- +// ---------------------------------------------------------------------- + +// ---------------------------- Mapper 4 -------------------------------- + +static int hackm4 = 0; /* For Karnov, maybe others. BLAH. Stupid iNES format.*/ + +static void M4Power(void) { + GenMMC3Power(); + A000B = (hackm4 ^ 1) & 1; + setmirror(hackm4); +} + +void Mapper4_Init(CartInfo *info) { + int ws = 8; + + if ((info->CRC32 == 0x93991433 || info->CRC32 == 0xaf65aa84)) { + FCEU_printf("Low-G-Man can not work normally in the iNES format.\nThis game has been recognized by its CRC32 value, and the appropriate changes will be made so it will run.\nIf you wish to hack this game, you should use the UNIF format for your hack.\n\n"); + ws = 0; + } + GenMMC3_Init(info, 512, 256, ws, info->battery); + info->Power = M4Power; + hackm4 = info->mirror; +} + +// ---------------------------- Mapper 12 ------------------------------- + +static void M12CW(uint32 A, uint8 V) { + setchr1(A, (EXPREGS[(A & 0x1000) >> 12] << 8) + V); +} + +static DECLFW(M12Write) { + EXPREGS[0] = V & 0x01; + EXPREGS[1] = (V & 0x10) >> 4; +} + +static DECLFR(M12Read) { + return EXPREGS[2]; +} + +static void M12Power(void) { + EXPREGS[0] = EXPREGS[1] = 0; + EXPREGS[2] = 1; // chinese is default + GenMMC3Power(); + SetWriteHandler(0x4100, 0x5FFF, M12Write); + SetReadHandler(0x4100, 0x5FFF, M12Read); +} + +static void M12Reset(void) { + EXPREGS[0] = EXPREGS[1] = 0; + EXPREGS[2] ^= 1; + MMC3RegReset(); +} + +void Mapper12_Init(CartInfo *info) { + GenMMC3_Init(info, 512, 256, 8, info->battery); + cwrap = M12CW; + isRevB = 0; + + info->Power = M12Power; + info->Reset = M12Reset; + 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 + if (EXPREGS[2]) + NV &= 0; // hack ;( don't know exactly how it should be + 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; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static DECLFR(M45Read) { + uint32 addr = 1 << (EXPREGS[5] + 4); + if (A & (addr | (addr - 1))) + return X.DB | 1; + else + return X.DB; +} + +static void M45Reset(void) { + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = EXPREGS[4] = 0; + EXPREGS[5]++; + EXPREGS[5] &= 7; + MMC3RegReset(); +} + +static void M45Power(void) { + setchr8(0); + GenMMC3Power(); + EXPREGS[0] = EXPREGS[1] = EXPREGS[2] = EXPREGS[3] = EXPREGS[4] = EXPREGS[5] = 0; + SetWriteHandler(0x5000, 0x7FFF, M45Write); + SetReadHandler(0x5000, 0x5FFF, M45Read); +} + +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, 0); + 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 mask = 0x1F ^ ((EXPREGS[0] & 8) << 1); + uint32 bank = ((EXPREGS[0] & 6) | ((EXPREGS[0] >> 3) & EXPREGS[0] & 1)) << 4; + setprg8(A, bank | (V & mask)); +} + +static void M52CW(uint32 A, uint8 V) { + uint32 mask = 0xFF ^ ((EXPREGS[0] & 0x40) << 1); +// uint32 bank = (((EXPREGS[0]>>3)&4)|((EXPREGS[0]>>1)&2)|((EXPREGS[0]>>6)&(EXPREGS[0]>>4)&1))<<7; + uint32 bank = (((EXPREGS[0] >> 4) & 2) | (EXPREGS[0] & 4) | ((EXPREGS[0] >> 6) & (EXPREGS[0] >> 4) & 1)) << 7; // actually 256K CHR banks index bits is inverted! + setchr1(A, bank | (V & mask)); +} + +static DECLFW(M52Write) { + if (EXPREGS[1]) { + WRAM[A - 0x6000] = V; + return; + } + EXPREGS[1] = V & 0x80; + 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, 256, 256, 8, info->battery); + cwrap = M52CW; + pwrap = M52PW; + info->Reset = M52Reset; + info->Power = M52Power; + AddExState(EXPREGS, 2, 0, "EXPR"); +} + +// ---------------------------- Mapper 76 ------------------------------- + +static void M76CW(uint32 A, uint8 V) { + if (A >= 0x1000) + setchr2((A & 0xC00) << 1, V); +} + +void Mapper76_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 128, 0, 0); + cwrap = M76CW; +} + +// ---------------------------- 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) { +// FCEU_printf("8000-C000:%02X\n",EXPREGS[0]&0xF); + setprg16(0x8000, EXPREGS[0] & 0xF); + setprg16(0xC000, EXPREGS[0] & 0xF); + } else { +// FCEU_printf("%04X:%02X\n",A,V&0x3F); + setprg8(A, V & 0x3F); + } +} + +static DECLFW(M114Write) { + switch (A & 0xE001) { + case 0x8001: MMC3_CMDWrite(0xA000, V); 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; + case 0xA001: IRQLatch = V; break; + case 0xC001: IRQReload = 1; break; + case 0xE000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; break; + case 0xE001: IRQa = 1; 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) { + isRevB = 0; + GenMMC3_Init(info, 256, 256, 0, 0); + pwrap = M114PWRAP; + info->Power = M114Power; + info->Reset = M114Reset; + AddExState(EXPREGS, 1, 0, "EXPR"); + AddExState(&cmdin, 1, 0, "CMDI"); +} + +// ---------------------------- Mapper 115 KN-658 board ------------------------------ + +static void M115PW(uint32 A, uint8 V) { + if (EXPREGS[0] & 0x80) { + if (EXPREGS[0] & 0x20) + setprg32(0x8000, (EXPREGS[0] & 0x0F) >> 1); // real hardware tests, info 100% now lol + else { + setprg16(0x8000, (EXPREGS[0] & 0x0F)); + setprg16(0xC000, (EXPREGS[0] & 0x0F)); + } + } else + setprg8(A, V); +} + +static void M115CW(uint32 A, uint8 V) { + setchr1(A, (uint32)V | ((EXPREGS[1] & 1) << 8)); +} + +static DECLFW(M115Write) { + if (A == 0x5080) + EXPREGS[2] = V; // Extra prot hardware 2-in-1 mode + else if (A == 0x6000) + EXPREGS[0] = V; + else if (A == 0x6001) + EXPREGS[1] = V; + FixMMC3PRG(MMC3_cmd); +} + +static DECLFR(M115Read) { + return EXPREGS[2]; +} + +static void M115Power(void) { + GenMMC3Power(); + SetWriteHandler(0x4100, 0x7FFF, M115Write); + SetReadHandler(0x5000, 0x5FFF, M115Read); +} + +void Mapper115_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 512, 0, 0); + cwrap = M115CW; + pwrap = M115PW; + info->Power = M115Power; + AddExState(EXPREGS, 3, 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)); +} + +// ---------------------------- 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 134 ------------------------------ + +static void M134PW(uint32 A, uint8 V) { + setprg8(A, (V & 0x1F) | ((EXPREGS[0] & 2) << 4)); +} + +static void M134CW(uint32 A, uint8 V) { + setchr1(A, (V & 0xFF) | ((EXPREGS[0] & 0x20) << 3)); +} + +static DECLFW(M134Write) { + EXPREGS[0] = V; + FixMMC3CHR(MMC3_cmd); + FixMMC3PRG(MMC3_cmd); +} + +static void M134Power(void) { + EXPREGS[0] = 0; + GenMMC3Power(); + SetWriteHandler(0x6001, 0x6001, M134Write); +} + +static void M134Reset(void) { + EXPREGS[0] = 0; + MMC3RegReset(); +} + +void Mapper134_Init(CartInfo *info) { + GenMMC3_Init(info, 256, 256, 0, 0); + pwrap = M134PW; + cwrap = M134CW; + info->Power = M134Power; + info->Reset = M134Reset; + AddExState(EXPREGS, 4, 0, "EXPR"); +} + +// ---------------------------- 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 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 195 ------------------------------- +static void M195CW(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 M195Power(void) { + GenMMC3Power(); + setprg4r(0x10, 0x5000, 2); + SetWriteHandler(0x5000, 0x5fff, CartBW); + SetReadHandler(0x5000, 0x5fff, CartBR); +} + +void Mapper195_Init(CartInfo *info) { + GenMMC3_Init(info, 512, 256, 16, info->battery); + cwrap = M195CW; + info->Power = M195Power; + CHRRAMSIZE = 4096; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRRAMSIZE, 1); + AddExState(CHRRAM, CHRRAMSIZE, 0, "CHRR"); +} + +// ---------------------------- Mapper 196 ------------------------------- +// MMC3 board with optional command address line connection, allows to +// make three-four different wirings to IRQ address lines and separately to +// CMD address line, Mali Boss additionally check if wiring are correct for +// game + +static void M196PW(uint32 A, uint8 V) { + if (EXPREGS[0]) + setprg32(0x8000, EXPREGS[1]); + else + setprg8(A, V); +} + +static DECLFW(Mapper196Write) { + if (A >= 0xC000) { + A = (A & 0xFFFE) | ((A >> 2) & 1) | ((A >> 3) & 1); + MMC3_IRQWrite(A, V); + } else { + A = (A & 0xFFFE) | ((A >> 2) & 1) | ((A >> 3) & 1) | ((A >> 1) & 1); + MMC3_CMDWrite(A, V); + } +} + +static DECLFW(Mapper196WriteLo) { + EXPREGS[0] = 1; + EXPREGS[1] = (V & 0xf) | (V >> 4); + FixMMC3PRG(MMC3_cmd); +} + +static void Mapper196Power(void) { + GenMMC3Power(); + EXPREGS[0] = EXPREGS[1] = 0; + SetWriteHandler(0x6000, 0x6FFF, Mapper196WriteLo); + SetWriteHandler(0x8000, 0xFFFF, Mapper196Write); +} + +void Mapper196_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 128, 0, 0); + pwrap = M196PW; + info->Power = Mapper196Power; +} + +// ---------------------------- Mali Splash Bomb---------------------------- +// The same board as for 196 mapper games, but with additional data bit swap +// Also, it is impossible to work on the combined 196 mapper source with +// all data bits merged, because it's using one of them as 8000 reg... + +static void UNLMaliSBPW(uint32 A, uint8 V) { + setprg8(A, (V & 3) | ((V & 8) >> 1) | ((V & 4) << 1)); +} + +static void UNLMaliSBCW(uint32 A, uint8 V) { + setchr1(A, (V & 0xDD) | ((V & 0x20) >> 4) | ((V & 2) << 4)); +} + +static DECLFW(UNLMaliSBWrite) { + if (A >= 0xC000) { + A = (A & 0xFFFE) | ((A >> 2) & 1) | ((A >> 3) & 1); + MMC3_IRQWrite(A, V); + } else { + A = (A & 0xFFFE) | ((A >> 3) & 1); + MMC3_CMDWrite(A, V); + } +} + +static void UNLMaliSBPower(void) { + GenMMC3Power(); + SetWriteHandler(0x8000, 0xFFFF, UNLMaliSBWrite); +} + +void UNLMaliSB_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 128, 0, 0); + pwrap = UNLMaliSBPW; + cwrap = UNLMaliSBCW; + info->Power = UNLMaliSBPower; +} + +// ---------------------------- Mapper 197 ------------------------------- + +static void M197CW(uint32 A, uint8 V) { + if (A == 0x0000) + setchr4(0x0000, V >> 1); + else if (A == 0x1000) + setchr2(0x1000, V); + else if (A == 0x1400) + setchr2(0x1800, V); +} + +void Mapper197_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 512, 8, 0); + cwrap = M197CW; +} + +// ---------------------------- Mapper 198 ------------------------------- + +static void M198PW(uint32 A, uint8 V) { + if (V >= 0x50) // Tenchi o Kurau II - Shokatsu Koumei Den (J) (C).nes + setprg8(A, V & 0x4F); + else + setprg8(A, V); +} + +void Mapper198_Init(CartInfo *info) { + GenMMC3_Init(info, 1024, 0, 16, info->battery); + pwrap = M198PW; + info->Power = M195Power; +} + +// ---------------------------- Mapper 205 ------------------------------ +// GN-45 BOARD + +static void M205PW(uint32 A, uint8 V) { +// GN-30A - начальная маска должна быть 1F + аппаратный переключатель на шине адреса + setprg8(A, (V & 0x0f) | EXPREGS[0]); +} + +static void M205CW(uint32 A, uint8 V) { +// GN-30A - начальная маска должна быть FF + setchr1(A, (V & 0x7F) | (EXPREGS[0] << 3)); +} + +static DECLFW(M205Write0) { + if (EXPREGS[2] == 0) { + EXPREGS[0] = A & 0x30; + EXPREGS[2] = A & 0x80; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } else + CartBW(A, V); +} + +static DECLFW(M205Write1) { + if (EXPREGS[2] == 0) { + EXPREGS[0] = V & 0x30; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } else + CartBW(A, V); +} + +static void M205Reset(void) { + EXPREGS[0] = EXPREGS[2] = 0; + MMC3RegReset(); +} + +static void M205Power(void) { + GenMMC3Power(); + SetWriteHandler(0x6000, 0x6fff, M205Write0); + SetWriteHandler(0x7000, 0x7fff, M205Write1); // OK-411 boards, the same logic, but data latched, 2-in-1 frankenstein +} + +void Mapper205_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 128, 8, 0); + pwrap = M205PW; + cwrap = M205CW; + info->Power = M205Power; + info->Reset = M205Reset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} + +// ---------------------------- Mapper 245 ------------------------------ + +static void M245CW(uint32 A, uint8 V) { + if (!UNIFchrrama) // Yong Zhe Dou E Long - Dragon Quest VI (As).nes NEEDS THIS for RAM cart + 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; break; + } + 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 TBROM_Init(CartInfo *info) { + GenMMC3_Init(info, 64, 64, 0, 0); +} + +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/src/boards/mmc3.h b/src/boards/mmc3.h new file mode 100644 index 0000000..d8b4b01 --- /dev/null +++ b/src/boards/mmc3.h @@ -0,0 +1,26 @@ +extern uint8 MMC3_cmd; +extern uint8 mmc3opts; +extern uint8 A000B; +extern uint8 A001B; +extern uint8 EXPREGS[8]; +extern uint8 DRegBuf[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/src/boards/mmc5.c b/src/boards/mmc5.c new file mode 100644 index 0000000..f0258f2 --- /dev/null +++ b/src/boards/mmc5.c @@ -0,0 +1,806 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 uint16 CHRBanksA[8], CHRBanksB[4]; +static uint8 WRAMMaskEnable[2]; +uint8 mmc5ABMode; /* 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; + +cartdata MMC5CartList[] = +{ + { 0x6f4e4312, 4 }, /* Aoki Ookami to Shiroki Mejika - Genchou Hishi */ + { 0x15fe6d0f, 2 }, /* Bandit Kings of Ancient China */ + { 0x671f23a8, 0 }, /* Castlevania III - Dracula's Curse (E) */ + { 0xcd4e7430, 0 }, /* Castlevania III - Dracula's Curse (KC) */ + { 0xed2465be, 0 }, /* Castlevania III - Dracula's Curse (U) */ + { 0xfe3488d1, 2 }, /* Daikoukai Jidai */ + { 0x0ec6c023, 1 }, /* Gemfire */ + { 0x0afb395e, 0 }, /* Gun Sight */ + { 0x1ced086f, 2 }, /* Ishin no Arashi */ + { 0x9cbadc25, 1 }, /* Just Breed */ + { 0x6396b988, 2 }, /* L'Empereur (J) */ + { 0x9c18762b, 2 }, /* L'Empereur (U) */ + { 0xb0480ae9, 0 }, /* Laser Invasion */ + { 0xb4735fac, 0 }, /* Metal Slader Glory */ + { 0xf540677b, 4 }, /* Nobunaga no Yabou - Bushou Fuuun Roku */ + { 0xeee9a682, 2 }, /* Nobunaga no Yabou - Sengoku Gunyuu Den (J) (PRG0) */ + { 0xf9b4240f, 2 }, /* Nobunaga no Yabou - Sengoku Gunyuu Den (J) (PRG1) */ + { 0x8ce478db, 2 }, /* Nobunaga's Ambition 2 */ + { 0xf011e490, 4 }, /* Romance of The Three Kingdoms II */ + { 0xbc80fb52, 1 }, /* Royal Blood */ + { 0x184c2124, 4 }, /* Sangokushi II (J) (PRG0) */ + { 0xee8e6553, 4 }, /* Sangokushi II (J) (PRG1) */ + { 0xd532e98f, 1 }, /* Shin 4 Nin Uchi Mahjong - Yakuman Tengoku */ + { 0x39f2ce4b, 2 }, /* Suikoden - Tenmei no Chikai */ + { 0xbb7f829a, 0 }, /* Uchuu Keibitai SDF */ + { 0xaca15643, 2 }, /* Uncharted Waters */ +}; + +#define MMC5_NOCARTS (sizeof(MMC5CartList) / sizeof(MMC5CartList[0])) +int DetectMMC5WRAMSize(uint32 crc32) { + int x; + for (x = 0; x < MMC5_NOCARTS; x++) { + if (crc32 == MMC5CartList[x].crc32) { + if (MMC5CartList[x].size > 1) + FCEU_printf(" >8KB external WRAM present. Use UNIF if you hack the ROM image.\n"); + return(MMC5CartList[x].size * 8); + } + } + return 64; +} + +static void BuildWRAMSizeTable(void) { + int x; + for (x = 0; x < 8; x++) { + switch (MMC5WRAMsize) { + case 0: MMC5WRAMIndex[x] = 255; break; //X,X,X,X,X,X,X,X + case 1: MMC5WRAMIndex[x] = (x > 3) ? 255 : 0; break; //0,0,0,0,X,X,X,X + case 2: MMC5WRAMIndex[x] = (x & 4) >> 2; break; //0,0,0,0,1,1,1,1 + case 4: MMC5WRAMIndex[x] = (x > 3) ? 255 : (x & 3); break; //0,1,2,3,X,X,X,X + case 8: MMC5WRAMIndex[x] = x; break; //0,1,2,3,4,5,6,7 + } + } +} + +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) { + 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) { + switch (A) { + case 0x5100: + mmc5psize = V; + MMC5PRG(); + break; + case 0x5101: + mmc5vsize = V; + if (!mmc5ABMode) { + MMC5CHRB(); + MMC5CHRA(); + } else { + MMC5CHRA(); + MMC5CHRB(); + } + break; + case 0x5102: + WRAMMaskEnable[0] = V; + break; + case 0x5103: + WRAMMaskEnable[1] = V; + break; + case 0x5104: + CHRMode = V; + MMC5HackCHRMode = V & 3; + break; + 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 0x5106: + if (V != NTFill) + FCEU_dwmemset(MMC5fill, (V | (V << 8) | (V << 16) | (V << 24)), 0x3c0); + NTFill = V; + break; + case 0x5107: + if (V != ATFill) { + unsigned char moop = V | (V << 2) | (V << 4) | (V << 6); + FCEU_dwmemset(MMC5fill + 0x3c0, moop | (moop << 8) | (moop << 16) | (moop << 24), 0x40); + } + ATFill = V; + break; + case 0x5113: + WRAMPage = V; + MMC5WRAM(0x6000, V & 7); + break; + case 0x5114: + case 0x5115: + case 0x5116: + case 0x5117: + PRGBanks[A & 3] = V; + MMC5PRG(); + break; + case 0x5120: + case 0x5121: + case 0x5122: + case 0x5123: + case 0x5124: + case 0x5125: + case 0x5126: + case 0x5127: + mmc5ABMode = 0; + CHRBanksA[A & 7] = V; + MMC5CHRA(); + break; + case 0x5128: + case 0x5129: + case 0x512a: + case 0x512b: + mmc5ABMode = 1; + CHRBanksB[A & 3] = V; + MMC5CHRB(); + 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) && (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) { + return ExRAM[A & 0x3ff]; +} + +static DECLFR(MMC5_read) { + switch (A) { + case 0x5204: { + uint8 x; + X6502_IRQEnd(FCEU_IQEXT); + x = MMC5IRQR; + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + 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 (!mmc5ABMode) { + MMC5CHRB(); + MMC5CHRA(); + } else { + MMC5CHRA(); + MMC5CHRB(); + } + FCEU_dwmemset(MMC5fill, NTFill | (NTFill << 8) | (NTFill << 16) | (NTFill << 24), 0x3c0); + { + unsigned char moop = ATFill | (ATFill << 2) | (ATFill << 4) | (ATFill << 6); + FCEU_dwmemset(MMC5fill + 0x3c0, moop | (moop << 8) | (moop << 16) | (moop << 24), 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() { + uint32 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: + 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: + 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; + 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 }; + uint32 V; + int32 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, 16, "CHRA" }, + { CHRBanksB, 8, "CHRB" }, + { &WRAMPage, 1, "WRMP" }, + { WRAMMaskEnable, 2, "WRME" }, + { &mmc5ABMode, 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(ExRAM, 1024, 0, "ERAM"); + AddExState(&MMC5HackSPMode, 1, 0, "SPLM"); + AddExState(&MMC5HackSPScroll, 1, 0, "SPLS"); + AddExState(&MMC5HackSPPage, 1, 0, "SPLP"); + AddExState(MMC5_StateRegs, ~0, 0, 0); + + 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, battery-backed +// ETROM seems to have 16KB of WRAM, battery-backed +// EWROM seems to have 32KB of WRAM, battery-backed + +void ELROM_Init(CartInfo *info) { + GenMMC5_Init(info, 0, 0); +} + +void EKROM_Init(CartInfo *info) { + GenMMC5_Init(info, 8, info->battery); +} + +void ETROM_Init(CartInfo *info) { + GenMMC5_Init(info, 16, info->battery); +} + +void EWROM_Init(CartInfo *info) { + GenMMC5_Init(info, 32, info->battery); +} diff --git a/src/boards/n106.c b/src/boards/n106.c new file mode 100644 index 0000000..4eac0d9 --- /dev/null +++ b/src/boards/n106.c @@ -0,0 +1,427 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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? */ + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + 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, "IRAM"); + 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"); + AddExState(N106_StateRegs, ~0, 0, 0); +} diff --git a/src/boards/n625092.c b/src/boards/n625092.c new file mode 100644 index 0000000..058cd3d --- /dev/null +++ b/src/boards/n625092.c @@ -0,0 +1,95 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * 700in1 and 400in1 carts + * + */ + + +#include "mapinc.h" + +static uint16 cmd, bank; + +static SFORMAT StateRegs[] = +{ + { &cmd, 2, "CMD" }, + { &bank, 2, "BANK" }, + { 0 } +}; + +static void Sync(void) { + setmirror((cmd & 1) ^ 1); + setchr8(0); + if (cmd & 2) { + if (cmd & 0x100) { + setprg16(0x8000, ((cmd & 0xfc) >> 2) | bank); + setprg16(0xC000, ((cmd & 0xfc) >> 2) | 7); + } else { + setprg16(0x8000, ((cmd & 0xfc) >> 2) | (bank & 6)); + setprg16(0xC000, ((cmd & 0xfc) >> 2) | ((bank & 6) | 1)); + } + } else { + setprg16(0x8000, ((cmd & 0xfc) >> 2) | bank); + setprg16(0xC000, ((cmd & 0xfc) >> 2) | bank); + } +} + +static uint16 ass = 0; + +static DECLFW(UNLN625092WriteCommand) { + cmd = A; + if (A == 0x80F8) { + setprg16(0x8000, ass); + setprg16(0xC000, ass); + } else { + Sync(); + } +} + +static DECLFW(UNLN625092WriteBank) { + bank = A & 7; + Sync(); +} + +static void UNLN625092Power(void) { + cmd = 0; + bank = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xBFFF, UNLN625092WriteCommand); + SetWriteHandler(0xC000, 0xFFFF, UNLN625092WriteBank); +} + +static void UNLN625092Reset(void) { + cmd = 0; + bank = 0; + ass++; + FCEU_printf("%04x\n", ass); +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLN625092_Init(CartInfo *info) { + info->Reset = UNLN625092Reset; + info->Power = UNLN625092Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/novel.c b/src/boards/novel.c new file mode 100644 index 0000000..c6dca06 --- /dev/null +++ b/src/boards/novel.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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/src/boards/onebus.c b/src/boards/onebus.c new file mode 100644 index 0000000..d048167 --- /dev/null +++ b/src/boards/onebus.c @@ -0,0 +1,302 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007-2010 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * VR02/VT03 Console and OneBus System + * + * Street Dance (Dance pad) (Unl) + * 101-in-1 Arcade Action II + * DreamGEAR 75-in-1, etc. + * + */ + +#include "mapinc.h" + +// General Purpose Registers +static uint8 cpu410x[16], ppu201x[16], apu40xx[64]; + +// IRQ Registers +static uint8 IRQCount, IRQa, IRQReload; +#define IRQLatch cpu410x[0x1] // accc cccc, a = 0, AD12 switching, a = 1, HSYNC switching + +// MMC3 Registers +static uint8 inv_hack = 0; // some OneBus Systems have swapped PRG reg commans in MMC3 inplementation, + // trying to autodetect unusual behavior, due not to add a new mapper. +#define mmc3cmd cpu410x[0x5] // pcv- ----, p - program swap, c - video swap, v - internal VRAM enable +#define mirror cpu410x[0x6] // ---- ---m, m = 0 - H, m = 1 - V + +// APU Registers +static uint8 pcm_enable = 0, pcm_irq = 0; +static int16 pcm_addr, pcm_size, pcm_latch, pcm_clock = 0xF6; + +static writefunc defapuwrite[64]; +static readfunc defapuread[64]; + +static SFORMAT StateRegs[] = +{ + { cpu410x, 16, "REGC" }, + { ppu201x, 16, "REGS" }, + { apu40xx, 64, "REGA" }, + { &IRQReload, 1, "IRQR" }, + { &IRQCount, 1, "IRQC" }, + { &IRQa, 1, "IRQA" }, + { &pcm_enable, 1, "PCME" }, + { &pcm_irq, 1, "PCMI" }, + { &pcm_addr, 2, "PCMA" }, + { &pcm_size, 2, "PCMS" }, + { &pcm_latch, 2, "PCML" }, + { &pcm_clock, 2, "PCMC" }, + { 0 } +}; + +static void PSync(void) { + uint8 bankmode = cpu410x[0xb] & 7; + uint8 mask = (bankmode == 0x7) ? (0xff) : (0x3f >> bankmode); + uint32 block = ((cpu410x[0x0] & 0xf0) << 4) + (cpu410x[0xa] & (~mask)); + uint32 pswap = (mmc3cmd & 0x40) << 8; + +// uint8 bank0 = (cpu410x[0xb] & 0x40)?(~1):(cpu410x[0x7]); +// uint8 bank1 = cpu410x[0x8]; +// uint8 bank2 = (cpu410x[0xb] & 0x40)?(cpu410x[0x9]):(~1); +// uint8 bank3 = ~0; + uint8 bank0 = cpu410x[0x7 ^ inv_hack]; + uint8 bank1 = cpu410x[0x8 ^ inv_hack]; + uint8 bank2 = (cpu410x[0xb] & 0x40) ? (cpu410x[0x9]) : (~1); + uint8 bank3 = ~0; + +// FCEU_printf(" PRG OFFSET: %08x\n", (block | (bank0 & mask)) * 8192); +// FCEU_printf(" PRG: %04x [%02x]",0x8000^pswap,block | (bank0 & mask)); + setprg8(0x8000 ^ pswap, block | (bank0 & mask)); +// FCEU_printf(" %04x [%02x]",0xa000^pswap,block | (bank1 & mask)); + setprg8(0xa000, block | (bank1 & mask)); +// FCEU_printf(" %04x [%02x]",0xc000^pswap,block | (bank2 & mask)); + setprg8(0xc000 ^ pswap, block | (bank2 & mask)); +// FCEU_printf(" %04x [%02x]\n",0xe000^pswap,block | (bank3 & mask)); + setprg8(0xe000, block | (bank3 & mask)); +} + +static void CSync(void) { + static const uint8 midx[8] = { 0, 1, 2, 0, 3, 4, 5, 0 }; + uint8 mask = 0xff >> midx[ppu201x[0xa] & 7]; + uint32 block = ((cpu410x[0x0] & 0x0f) << 11) + ((ppu201x[0x8] & 0x70) << 4) + (ppu201x[0xa] & (~mask)); + uint32 cswap = (mmc3cmd & 0x80) << 5; + + uint8 bank0 = ppu201x[0x6] & (~1); + uint8 bank1 = ppu201x[0x6] | 1; + uint8 bank2 = ppu201x[0x7] & (~1); + uint8 bank3 = ppu201x[0x7] | 1; + uint8 bank4 = ppu201x[0x2]; + uint8 bank5 = ppu201x[0x3]; + uint8 bank6 = ppu201x[0x4]; + uint8 bank7 = ppu201x[0x5]; + +// FCEU_printf(" CHR OFFSET: %08x\n", (block | (bank0 & mask)) * 1024); +// FCEU_printf(" CHR: %04x [%02x]", 0x0000^cswap,block | (bank0 & mask)); + setchr1(0x0000 ^ cswap, block | (bank0 & mask)); +// FCEU_printf(" %04x [%02x]",0x0400^cswap,block | (bank1 & mask)); + setchr1(0x0400 ^ cswap, block | (bank1 & mask)); +// FCEU_printf(" %04x [%02x]",0x0800^cswap,block | (bank2 & mask)); + setchr1(0x0800 ^ cswap, block | (bank2 & mask)); +// FCEU_printf(" %04x [%02x]",0x0c00^cswap,block | (bank3 & mask)); + setchr1(0x0c00 ^ cswap, block | (bank3 & mask)); +// FCEU_printf(" %04x [%02x]",0x1000^cswap,block | (bank4 & mask)); + setchr1(0x1000 ^ cswap, block | (bank4 & mask)); +// FCEU_printf(" %04x [%02x]",0x1400^cswap,block | (bank5 & mask)); + setchr1(0x1400 ^ cswap, block | (bank5 & mask)); +// FCEU_printf(" %04x [%02x]",0x1800^cswap,block | (bank6 & mask)); + setchr1(0x1800 ^ cswap, block | (bank6 & mask)); +// FCEU_printf(" %04x [%02x]\n",0x1c00^cswap,block | (bank7 & mask)); + setchr1(0x1c00 ^ cswap, block | (bank7 & mask)); + + setmirror(mirror & 1); +} + +static void Sync(void) { + PSync(); + CSync(); +} + +static DECLFW(UNLOneBusWriteCPU410X) { +// FCEU_printf("CPU %04x:%04x\n",A,V); + switch (A & 0xf) { + case 0x1: IRQLatch = V & 0xfe; break; // не по даташиту + case 0x2: IRQReload = 1; break; + case 0x3: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; break; + case 0x4: IRQa = 1; break; + default: + cpu410x[A & 0xf] = V; + Sync(); + } +} + +static DECLFW(UNLOneBusWritePPU201X) { +// FCEU_printf("PPU %04x:%04x\n",A,V); + ppu201x[A & 0x0f] = V; + Sync(); +} + +static DECLFW(UNLOneBusWriteMMC3) { +// FCEU_printf("MMC %04x:%04x\n",A,V); + switch (A & 0xe001) { + case 0x8000: mmc3cmd = (mmc3cmd & 0x38) | (V & 0xc7); Sync(); break; + case 0x8001: + { + switch (mmc3cmd & 7) { + case 0: ppu201x[0x6] = V; CSync(); break; + case 1: ppu201x[0x7] = V; CSync(); break; + case 2: ppu201x[0x2] = V; CSync(); break; + case 3: ppu201x[0x3] = V; CSync(); break; + case 4: ppu201x[0x4] = V; CSync(); break; + case 5: ppu201x[0x5] = V; CSync(); break; + case 6: cpu410x[0x7] = V; PSync(); break; + case 7: cpu410x[0x8] = V; PSync(); break; + } + break; + } + case 0xa000: mirror = V ^ 1; CSync(); break; + case 0xc000: IRQLatch = V & 0xfe; break; + case 0xc001: IRQReload = 1; break; + case 0xe000: X6502_IRQEnd(FCEU_IQEXT); IRQa = 0; break; + case 0xe001: IRQa = 1; break; + } +} + +static void UNLOneBusIRQHook(void) { + uint32 count = IRQCount; + if (!count || IRQReload) { + IRQCount = IRQLatch; + IRQReload = 0; + } else + IRQCount--; + if (count && !IRQCount) { + if (IRQa) + X6502_IRQBegin(FCEU_IQEXT); + } +} + +static DECLFW(UNLOneBusWriteAPU40XX) { +// FCEU_printf("APU %04x:%04x\n",A,V); + apu40xx[A & 0x3f] = V; + switch (A & 0x3f) { + case 0x12: + if (apu40xx[0x30] & 0x10) { + pcm_addr = V << 6; + } + case 0x13: + if (apu40xx[0x30] & 0x10) { + pcm_size = (V << 4) + 1; + } + case 0x15: + if (apu40xx[0x30] & 0x10) { + pcm_enable = V & 0x10; + if (pcm_irq) { + X6502_IRQEnd(FCEU_IQEXT); + pcm_irq = 0; + } + if (pcm_enable) + pcm_latch = pcm_clock; + V &= 0xef; + } + } + defapuwrite[A & 0x3f](A, V); +} + +static DECLFR(UNLOneBusReadAPU40XX) { + uint8 result = defapuread[A & 0x3f](A); +// FCEU_printf("read %04x, %02x\n",A,result); + switch (A & 0x3f) { + case 0x15: + if (apu40xx[0x30] & 0x10) { + result = (result & 0x7f) | pcm_irq; + } + } + return result; +} + +static void UNLOneBusCpuHook(int a) { + if (pcm_enable) { + pcm_latch -= a; + if (pcm_latch <= 0) { + pcm_latch += pcm_clock; + pcm_size--; + if (pcm_size < 0) { + pcm_irq = 0x80; + pcm_enable = 0; + X6502_IRQBegin(FCEU_IQEXT); + } else { + uint8 raw_pcm = ARead[pcm_addr](pcm_addr) >> 1; + defapuwrite[0x11](0x4011, raw_pcm); + pcm_addr++; + pcm_addr &= 0x7FFF; + } + } + } +} + +static void UNLOneBusPower(void) { + uint32 i; + IRQReload = IRQCount = IRQa = 0; + + memset(cpu410x, 0x00, sizeof(cpu410x)); + memset(ppu201x, 0x00, sizeof(ppu201x)); + memset(apu40xx, 0x00, sizeof(apu40xx)); + + SetupCartCHRMapping(0, PRGptr[0], PRGsize[0], 0); + + for (i = 0; i < 64; i++) { + defapuread[i] = GetReadHandler(0x4000 | i); + defapuwrite[i] = GetWriteHandler(0x4000 | i); + } + SetReadHandler(0x4000, 0x403f, UNLOneBusReadAPU40XX); + SetWriteHandler(0x4000, 0x403f, UNLOneBusWriteAPU40XX); + + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x2010, 0x201f, UNLOneBusWritePPU201X); + SetWriteHandler(0x4100, 0x410f, UNLOneBusWriteCPU410X); + SetWriteHandler(0x8000, 0xffff, UNLOneBusWriteMMC3); + + Sync(); +} + +static void UNLOneBusReset(void) { + IRQReload = IRQCount = IRQa = 0; + + memset(cpu410x, 0x00, sizeof(cpu410x)); + memset(ppu201x, 0x00, sizeof(ppu201x)); + memset(apu40xx, 0x00, sizeof(apu40xx)); + + Sync(); +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLOneBus_Init(CartInfo *info) { + info->Power = UNLOneBusPower; + info->Reset = UNLOneBusReset; + + if (((*(uint32*)&(info->MD5)) == 0x305fcdc3) || // PowerJoy Supermax Carts + ((*(uint32*)&(info->MD5)) == 0x6abfce8e)) + inv_hack = 0xf; + + GameHBIRQHook = UNLOneBusIRQHook; + MapIRQHook = UNLOneBusCpuHook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/pec-586.c b/src/boards/pec-586.c new file mode 100644 index 0000000..6de80af --- /dev/null +++ b/src/boards/pec-586.c @@ -0,0 +1,127 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 reg[8]; +static uint32 lastnt = 0; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { reg, 2, "REG" }, + { &lastnt, 4, "LNT" }, + { 0 } +}; + +static uint8 bs_tbl[128] = { + 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, // 00 + 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, // 10 + 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, 0x03, 0x13, 0x23, 0x33, // 20 + 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, // 30 + 0x02, 0x12, 0x22, 0x32, 0x02, 0x12, 0x22, 0x32, 0x02, 0x12, 0x22, 0x32, 0x02, 0x12, 0x22, 0x32, // 40 + 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, 0x45, 0x67, // 50 + 0x02, 0x12, 0x22, 0x32, 0x02, 0x12, 0x22, 0x32, 0x02, 0x12, 0x22, 0x32, 0x00, 0x10, 0x20, 0x30, // 60 + 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, 0x47, 0x67, // 70 +}; + +static uint8 br_tbl[16] = { + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, +}; + +static void Sync(void) { + setchr8(0); + setprg8r(0x10, 0x6000, 0); + if(PRGsize[0] == 512 * 1024) { + if(reg[0] & 0x010) { + setprg32(0x8000, reg[0] & 7); + } else { + if(reg[0] & 0x40) + setprg8(0x8000, (reg[0] & 0x0F) | 0x20 | ((reg[0] & 0x20) >> 1)); + } + if((reg[0] & 0x18) == 0x18) + setmirror(MI_H); + else + setmirror(MI_V); + } else { + setprg16(0x8000, bs_tbl[reg[0] & 0x7f] >> 4); + setprg16(0xc000, bs_tbl[reg[0] & 0x7f] & 0xf); + setmirror(MI_V); + } +} + +static DECLFW(UNLPEC586Write) { + reg[(A & 0x700) >> 8] = V; + PEC586Hack = (reg[0] & 0x80) >> 7; +// FCEU_printf("bs %04x %02x\n", A, V); + Sync(); +} + +static DECLFR(UNLPEC586Read) { +// FCEU_printf("read %04x\n", A); + return (X.DB & 0xD8) | br_tbl[reg[4] >> 4]; +} + +static DECLFR(UNLPEC586ReadHi) { + if((reg[0] & 0x10) || ((reg[0] & 0x40) && (A < 0xA000))) + return CartBR(A); + else + return PRGptr[0][((0x0107 | ((A >> 7) & 0x0F8)) << 10) | (A & 0x3FF)]; +} + +static void UNLPEC586Power(void) { + if(PRGsize[0] == 512 * 1024) + reg[0] = 0x00; + else + reg[0] = 0x0E; + Sync(); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + if(PRGsize[0] == 512 * 1024) + SetReadHandler(0x8000, 0xFFFF, UNLPEC586ReadHi); + else + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x5000, 0x5fff, UNLPEC586Write); + SetReadHandler(0x5000, 0x5fff, UNLPEC586Read); +} + +static void UNLPEC586Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLPEC586Init(CartInfo *info) { + info->Power = UNLPEC586Power; + info->Close = UNLPEC586Close; + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/sachen.c b/src/boards/sachen.c new file mode 100644 index 0000000..ec7da2c --- /dev/null +++ b/src/boards/sachen.c @@ -0,0 +1,409 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 cmd, dip; +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); + ret = ((~cmd) & 0x3F) ^ dip; + else + ret = X.DB; + return ret; +} + +static void S74LS374NPower(void) { + dip = 0; + 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 S74LS374NReset(void) { + dip ^= 1; + latch[0] = latch[1] = latch[2] = latch[3] = latch[4] = 0; + S74LS374NSynco(); +} + +static void S74LS374NRestore(int version) { + S74LS374NSynco(); +} + +void S74LS374N_Init(CartInfo *info) { + info->Power = S74LS374NPower; + info->Reset = S74LS374NReset; + GameStateRestore = S74LS374NRestore; + AddExState(latch, 5, 0, "LATC"); + AddExState(&cmd, 1, 0, "CMD"); + AddExState(&dip, 1, 0, "DIP"); +} + +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 SA009Synco() { + setprg32(0x8000, 0); + setchr8(latch[0] & 1); +} + +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 SA009_Init(CartInfo *info) { + WSync = SA009Synco; + 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] & 0x80) >> 6) | ((latch[0] >> 2) & 1)); + setchr8((latch[0] >> 3) & 0xF); +} + +static DECLFW(TCU01Write) { + if ((A & 0x103) == 0x102) { + latch[0] = V; + TCU01Synco(); + } +} + +static void TCU01Power(void) { + latch[0] = 0; + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x4100, 0xFFFF, TCU01Write); + TCU01Synco(); +} + +static void TCU01Restore(int version) { + TCU01Synco(); +} + +void TCU01_Init(CartInfo *info) { + GameStateRestore = TCU01Restore; + info->Power = TCU01Power; + AddExState(&latch[0], 1, 0, "LATC"); +} + +//----------------------------------------------- + +static void TCU02Synco() { + setprg32(0x8000, 0); + setchr8(latch[0] & 3); +} + +static DECLFW(TCU02Write) { + if ((A & 0x103) == 0x102) { + latch[0] = V + 3; + TCU02Synco(); + } +} + +static DECLFR(TCU02Read) { + return (latch[0] & 0x3F) | (X.DB & 0xC0); +} + +static void TCU02Power(void) { + latch[0] = 0; + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x4100, TCU02Read); + SetWriteHandler(0x4100, 0xFFFF, TCU02Write); + TCU02Synco(); +} + +static void TCU02Restore(int version) { + TCU02Synco(); +} + +void TCU02_Init(CartInfo *info) { + GameStateRestore = TCU02Restore; + info->Power = TCU02Power; + 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 TCA01Power(void) { + setprg16(0x8000, 0); + setprg16(0xC000, 1); + setchr8(0); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetReadHandler(0x4100, 0x5FFF, TCA01Read); +} + +void TCA01_Init(CartInfo *info) { + info->Power = TCA01Power; +} + diff --git a/src/boards/sc-127.c b/src/boards/sc-127.c new file mode 100644 index 0000000..c092510 --- /dev/null +++ b/src/boards/sc-127.c @@ -0,0 +1,114 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Wario Land II (Kirby hack) VRC4 + */ + +#include "mapinc.h" + +static uint8 reg[8], chr[8]; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; +static uint16 IRQCount, IRQa; + +static SFORMAT StateRegs[] = +{ + { reg, 8, "REGS" }, + { chr, 8, "CHRS" }, + { &IRQCount, 16, "IRQc" }, + { &IRQa, 16, "IRQa" }, + { 0 } +}; + +static void Sync(void) { + int i; + setprg8(0x8000, reg[0]); + setprg8(0xA000, reg[1]); + setprg8(0xC000, reg[2]); + for (i = 0; i < 8; i++) + setchr1(i << 10, chr[i]); + setmirror(reg[3] ^ 1); +} + +static DECLFW(UNLSC127Write) { + switch (A) { + case 0x8000: reg[0] = V; break; + case 0x8001: reg[1] = V; break; + case 0x8002: reg[2] = V; break; + case 0x9000: chr[0] = V; break; + case 0x9001: chr[1] = V; break; + case 0x9002: chr[2] = V; break; + case 0x9003: chr[3] = V; break; + case 0x9004: chr[4] = V; break; + case 0x9005: chr[5] = V; break; + case 0x9006: chr[6] = V; break; + case 0x9007: chr[7] = V; break; + case 0xC002: IRQa = 0; X6502_IRQEnd(FCEU_IQEXT); break; + case 0xC005: IRQCount = V; break; + case 0xC003: IRQa = 1; break; + case 0xD001: reg[3] = V; break; + } + Sync(); +} + +static void UNLSC127Power(void) { + Sync(); + setprg8r(0x10, 0x6000, 0); + setprg8(0xE000, ~0); + SetReadHandler(0x6000, 0x7fff, CartBR); + SetWriteHandler(0x6000, 0x7fff, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, UNLSC127Write); +} + +static void UNLSC127IRQ(void) { + if (IRQa) { + IRQCount--; + if (IRQCount == 0) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + } + } +} + +static void UNLSC127Reset(void) { +} + +static void UNLSC127Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLSC127_Init(CartInfo *info) { + info->Reset = UNLSC127Reset; + info->Power = UNLSC127Power; + info->Close = UNLSC127Close; + GameHBIRQHook = UNLSC127IRQ; + GameStateRestore = StateRestore; + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/sheroes.c b/src/boards/sheroes.c new file mode 100644 index 0000000..651671b --- /dev/null +++ b/src/boards/sheroes.c @@ -0,0 +1,79 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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"); + AddExState(&tekker, 1, 0, "DIPSW"); +} diff --git a/src/boards/sl1632.c b/src/boards/sl1632.c new file mode 100644 index 0000000..43b8abb --- /dev/null +++ b/src/boards/sl1632.c @@ -0,0 +1,111 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * SL1632 2-in-1 protected board, similar to SL12 + * Samurai Spirits Rex (Full) + * + */ + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 chrcmd[8], prg0, prg1, bbrk, mirr, swap; +static SFORMAT StateRegs[] = +{ + { chrcmd, 8, "CHRC" }, + { &prg0, 1, "PRG0" }, + { &prg1, 1, "PRG1" }, + { &bbrk, 1, "BRK" }, + { &mirr, 1, "MIRR" }, + { &swap, 1, "SWAP" }, + { 0 } +}; + +static void Sync(void) { + int i; + setprg8(0x8000, prg0); + setprg8(0xA000, prg1); + setprg8(0xC000, ~1); + setprg8(0xE000, ~0); + for (i = 0; i < 8; i++) + setchr1(i << 10, chrcmd[i]); + setmirror(mirr ^ 1); +} + +static void UNLSL1632CW(uint32 A, uint8 V) { + int cbase = (MMC3_cmd & 0x80) << 5; + int page0 = (bbrk & 0x08) << 5; + int page1 = (bbrk & 0x20) << 3; + int page2 = (bbrk & 0x80) << 1; + setchr1(cbase ^ 0x0000, page0 | (DRegBuf[0] & (~1))); + setchr1(cbase ^ 0x0400, page0 | DRegBuf[0] | 1); + setchr1(cbase ^ 0x0800, page0 | (DRegBuf[1] & (~1))); + setchr1(cbase ^ 0x0C00, page0 | DRegBuf[1] | 1); + setchr1(cbase ^ 0x1000, page1 | DRegBuf[2]); + setchr1(cbase ^ 0x1400, page1 | DRegBuf[3]); + setchr1(cbase ^ 0x1800, page2 | DRegBuf[4]); + setchr1(cbase ^ 0x1c00, page2 | DRegBuf[5]); +} + +static DECLFW(UNLSL1632CMDWrite) { + if (A == 0xA131) { + bbrk = V; + } + if (bbrk & 2) { + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + if (A < 0xC000) + MMC3_CMDWrite(A, V); + else + MMC3_IRQWrite(A, V); + } else { + if ((A >= 0xB000) && (A <= 0xE003)) { + int ind = ((((A & 2) | (A >> 10)) >> 1) + 2) & 7; + int sar = ((A & 1) << 2); + chrcmd[ind] = (chrcmd[ind] & (0xF0 >> sar)) | ((V & 0x0F) << sar); + } else + switch (A & 0xF003) { + case 0x8000: prg0 = V; break; + case 0xA000: prg1 = V; break; + case 0x9000: mirr = V & 1; break; + } + Sync(); + } +} + +static void StateRestore(int version) { + if (bbrk & 2) { + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); + } else + Sync(); +} + +static void UNLSL1632Power(void) { + GenMMC3Power(); + SetWriteHandler(0x4100, 0xFFFF, UNLSL1632CMDWrite); +} + +void UNLSL1632_Init(CartInfo *info) { + GenMMC3_Init(info, 256, 512, 0, 0); + cwrap = UNLSL1632CW; + info->Power = UNLSL1632Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/subor.c b/src/boards/subor.c new file mode 100644 index 0000000..00d9a99 --- /dev/null +++ b/src/boards/subor.c @@ -0,0 +1,88 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 is167, regs[4]; + +static SFORMAT StateRegs[] = +{ + { regs, 4, "DREG" }, + { 0 } +}; + +static void Sync(void) { + int base, bank; + base = ((regs[0] ^ regs[1]) & 0x10) << 1; + bank = (regs[2] ^ regs[3]) & 0x1f; + + if (regs[1] & 0x08) { + bank &= 0xFE; + if (is167) { + setprg16(0x8000, base + bank + 1); + setprg16(0xC000, base + bank + 0); + } else { + setprg16(0x8000, base + bank + 0); + setprg16(0xC000, base + bank + 1); + } + } else { + if (regs[1] & 0x04) { + setprg16(0x8000, 0x1F); + setprg16(0xC000, base + bank); + } else { + setprg16(0x8000, base + bank); + if (is167) + setprg16(0xC000, 0x20); + else + setprg16(0xC000, 0x07); + } + } + setchr8(0); +} + +static DECLFW(M166Write) { + regs[(A >> 13) & 0x03] = V; + Sync(); +} + +static void M166Power(void) { + regs[0] = regs[1] = regs[2] = regs[3] = 0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M166Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper166_Init(CartInfo *info) { + is167 = 0; + info->Power = M166Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +void Mapper167_Init(CartInfo *info) { + is167 = 1; + info->Power = M166Power; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/super24.c b/src/boards/super24.c new file mode 100644 index 0000000..5805dcc --- /dev/null +++ b/src/boards/super24.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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/src/boards/supervision.c b/src/boards/supervision.c new file mode 100644 index 0000000..46be8ed --- /dev/null +++ b/src/boards/supervision.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 cmd0, cmd1; +static SFORMAT StateRegs[] = +{ + { &cmd0, 1, "L1" }, + { &cmd1, 1, "L2" }, + { 0 } +}; + +static void Sync(void) { + setchr8(0); + if (PRGptr[1]) + setprg8r((cmd0 & 0xC) >> 2, 0x6000, ((cmd0 & 0x3) << 4) | 0xF); + else + setprg8(0x6000, (((cmd0 & 0xF) << 4) | 0xF) + 4); + if (cmd0 & 0x10) { + if (PRGptr[1]) { + setprg16r((cmd0 & 0xC) >> 2, 0x8000, ((cmd0 & 0x3) << 3) | (cmd1 & 7)); + setprg16r((cmd0 & 0xC) >> 2, 0xc000, ((cmd0 & 0x3) << 3) | 7); + } else { + setprg16(0x8000, (((cmd0 & 0xF) << 3) | (cmd1 & 7)) + 2); + setprg16(0xc000, (((cmd0 & 0xF) << 3) | 7) + 2); + } + } else + if (PRGptr[4]) + setprg32r(4, 0x8000, 0); + else + setprg32(0x8000, 0); + setmirror(((cmd0 & 0x20) >> 5) ^ 1); +} + +static DECLFW(SuperWriteLo) { + if (!(cmd0 & 0x10)) { + cmd0 = V; + Sync(); + } +} + +static DECLFW(SuperWriteHi) { + cmd1 = V; + Sync(); +} + +static void SuperPower(void) { + SetWriteHandler(0x6000, 0x7FFF, SuperWriteLo); + SetWriteHandler(0x8000, 0xFFFF, SuperWriteHi); + SetReadHandler(0x6000, 0xFFFF, CartBR); + cmd0 = cmd1 = 0; + Sync(); +} + +static void SuperReset(void) { + cmd0 = cmd1 = 0; + Sync(); +} + +static void SuperRestore(int version) { + Sync(); +} + +void Supervision16_Init(CartInfo *info) { + info->Power = SuperPower; + info->Reset = SuperReset; + GameStateRestore = SuperRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/t-227-1.c b/src/boards/t-227-1.c new file mode 100644 index 0000000..ca99b6f --- /dev/null +++ b/src/boards/t-227-1.c @@ -0,0 +1,100 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2008 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +// T-227-1, 820632, MMC3 based, multimenu, 60000in1 (0010) dip switches + +#include "mapinc.h" +#include "mmc3.h" + +static uint8 reset_flag = 0x07; + +static void BMCT2271CW(uint32 A, uint8 V) { + uint32 va = V; + if (EXPREGS[0] & 0x20) { + va |= 0x200; + va |= (EXPREGS[0] & 0x10) << 4; + } else { + va &= 0x7F; + va |= (EXPREGS[0] & 0x18) << 4; + } + setchr1(A, va); +} + +static void BMCT2271PW(uint32 A, uint8 V) { + uint32 va = V & 0x3F; + if (EXPREGS[0] & 0x20) { + va &= 0x1F; + va |= 0x40; + va |= (EXPREGS[0] & 0x10) << 1; + } else { + va &= 0x0F; + va |= (EXPREGS[0] & 0x18) << 1; + } + switch (EXPREGS[0] & 3) { + case 0x00: setprg8(A, va); break; + case 0x02: + { + va = (va & 0xFD) | ((EXPREGS[0] & 4) >> 1); + if (A < 0xC000) { + setprg16(0x8000, va >> 1); + setprg16(0xC000, va >> 1); + } + break; + } + case 0x01: + case 0x03: if (A < 0xC000) setprg32(0x8000, va >> 2); break; + } +} + +static DECLFW(BMCT2271LoWrite) { + if (!(EXPREGS[0] & 0x80)) + EXPREGS[0] = A & 0xFF; + FixMMC3PRG(MMC3_cmd); + FixMMC3CHR(MMC3_cmd); +} + +static DECLFR(BMCT2271HiRead) { + uint32 av = A; + if (EXPREGS[0] & 0x40) av = (av & 0xFFF0) | reset_flag; + return CartBR(av); +} + +static void BMCT2271Reset(void) { + EXPREGS[0] = 0x00; + reset_flag++; + reset_flag &= 0x0F; + MMC3RegReset(); +} + +static void BMCT2271Power(void) { + EXPREGS[0] = 0x00; + GenMMC3Power(); + SetWriteHandler(0x6000, 0x7FFF, BMCT2271LoWrite); + SetReadHandler(0x8000, 0xFFFF, BMCT2271HiRead); +} + +void BMCT2271_Init(CartInfo *info) { + GenMMC3_Init(info, 128, 128, 8, 0); + pwrap = BMCT2271PW; + cwrap = BMCT2271CW; + info->Power = BMCT2271Power; + info->Reset = BMCT2271Reset; + AddExState(EXPREGS, 1, 0, "EXPR"); +} diff --git a/src/boards/t-262.c b/src/boards/t-262.c new file mode 100644 index 0000000..01b873b --- /dev/null +++ b/src/boards/t-262.c @@ -0,0 +1,73 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 bank, base, lock, mirr, mode; +static SFORMAT StateRegs[] = +{ + { &bank, 1, "BANK" }, + { &base, 1, "BASE" }, + { &lock, 1, "LOCK" }, + { &mirr, 1, "MIRR" }, + { &mode, 1, "MODE" }, + { 0 } +}; + +static void Sync(void) { + setchr8(0); + setprg16(0x8000, base | bank); + setprg16(0xC000, base | (mode ? bank : 7)); + setmirror(mirr); +} + +static DECLFW(BMCT262Write) { + if (!lock) { + base = ((A & 0x60) >> 2) | ((A & 0x100) >> 3); + mode = A & 0x80; + mirr = ((A & 2) >> 1) ^ 1; + lock = (A & 0x2000) >> 13; + } + bank = V & 7; + Sync(); +} + +static void BMCT262Power(void) { + lock = bank = base = mode = 0; + Sync(); + SetWriteHandler(0x8000, 0xFFFF, BMCT262Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void BMCT262Reset(void) { + lock = bank = base = mode = 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/src/boards/tengen.c b/src/boards/tengen.c new file mode 100644 index 0000000..70428b6 --- /dev/null +++ b/src/boards/tengen.c @@ -0,0 +1,139 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 cmd, mirr, regs[11]; +static uint8 rmode, IRQmode, IRQCount, IRQa, IRQLatch; + +static SFORMAT StateRegs[] = { + { regs, 11, "REGS" }, + { &cmd, 1, "CMDR" }, + { &mirr, 1, "MIRR" }, + { &rmode, 1, "RMOD" }, + { &IRQmode, 1, "IRQM" }, + { &IRQCount, 1, "IRQC" }, + { &IRQa, 1, "IRQA" }, + { &IRQLatch, 1, "IRQL" }, + { 0 } +}; + +static void FP_FASTAPASS(1) M64IRQHook(int a) { + static int32 smallcount; + if (IRQmode) { + smallcount += a; + while (smallcount >= 4) { + smallcount -= 4; + IRQCount--; + if (IRQCount == 0xFF) + if (IRQa) X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void M64HBHook(void) { + if ((!IRQmode) && (scanline != 240)) { + rmode = 0; + IRQCount--; + if (IRQCount == 0xFF) { + if (IRQa) { + rmode = 1; + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +static void Sync(void) { + if (cmd & 0x20) { + setchr1(0x0000, regs[0]); + setchr1(0x0400, regs[8]); + setchr1(0x0800, regs[1]); + setchr1(0x0C00, regs[9]); + } else { + setchr2(0x0000, regs[0] >> 1); + setchr2(0x0800, regs[1] >> 1); + } + setchr1(0x1000, regs[2]); + setchr1(0x1400, regs[3]); + setchr1(0x1800, regs[4]); + setchr1(0x1C00, regs[5]); + setprg8(0x8000, regs[6]); + setprg8(0xA000, regs[7]); + setprg8(0xC000, regs[10]); + setprg8(0xE000, ~0); + setmirror(mirr); +} + +static DECLFW(M64Write) { + switch (A & 0xF001) { + case 0xA000: mirr = (V & 1) ^ 1; Sync(); break; + case 0x8000: cmd = V; break; + case 0x8001: + if ((cmd & 0xF) < 10) + regs[cmd & 0xF] = V; + else if ((cmd & 0xF) == 0xF) + regs[10] = V; + Sync(); + 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 M64Power(void) { + cmd = mirr = 0; + regs[0] = regs[1] = regs[2] = regs[3] = regs[4] = regs[5] = ~0; + regs[6] = regs[7] = regs[8] = regs[9] = regs[10] = ~0; + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M64Write); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper64_Init(CartInfo *info) { + info->Power = M64Power; + GameHBIRQHook = M64HBHook; + MapIRQHook = M64IRQHook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/tf-1201.c b/src/boards/tf-1201.c new file mode 100644 index 0000000..24e8a77 --- /dev/null +++ b/src/boards/tf-1201.c @@ -0,0 +1,109 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Lethal Weapon (VRC4 mapper) + */ + +#include "mapinc.h" + +static uint8 prg0, prg1, mirr, swap; +static uint8 chr[8]; +static uint8 IRQCount; +static uint8 IRQPre; +static uint8 IRQa; + +static SFORMAT StateRegs[] = +{ + { &prg0, 1, "PRG0" }, + { &prg0, 1, "PRG1" }, + { &mirr, 1, "MIRR" }, + { &swap, 1, "SWAP" }, + { chr, 8, "CHR" }, + { &IRQCount, 1, "IRQC" }, + { &IRQPre, 1, "IRQP" }, + { &IRQa, 1, "IRQA" }, + { 0 } +}; + +static void SyncPrg(void) { + if (swap & 3) { + setprg8(0x8000, ~1); + setprg8(0xC000, prg0); + } else { + setprg8(0x8000, prg0); + setprg8(0xC000, ~1); + } + setprg8(0xA000, prg1); + setprg8(0xE000, ~0); +} + +static void SyncChr(void) { + int i; + for (i = 0; i < 8; i++) + setchr1(i << 10, chr[i]); + setmirror(mirr ^ 1); +} + +static void StateRestore(int version) { + SyncPrg(); + SyncChr(); +} + +static DECLFW(UNLTF1201Write) { + A = (A & 0xF003) | ((A & 0xC) >> 2); + if ((A >= 0xB000) && (A <= 0xE003)) { + int ind = (((A >> 11) - 6) | (A & 1)) & 7; + int sar = ((A & 2) << 1); + chr[ind] = (chr[ind] & (0xF0 >> sar)) | ((V & 0x0F) << sar); + SyncChr(); + } else switch (A & 0xF003) { + case 0x8000: prg0 = V; SyncPrg(); break; + case 0xA000: prg1 = V; SyncPrg(); break; + case 0x9000: mirr = V & 1; SyncChr(); break; + case 0x9001: swap = V & 3; SyncPrg(); break; + case 0xF000: IRQCount = ((IRQCount & 0xF0) | (V & 0xF)); break; + case 0xF002: IRQCount = ((IRQCount & 0x0F) | ((V & 0xF) << 4)); break; + case 0xF001: + case 0xF003: IRQa = V & 2; X6502_IRQEnd(FCEU_IQEXT); if (scanline < 240) IRQCount -= 8; break; + } +} + +static void UNLTF1201IRQCounter(void) { + if (IRQa) { + IRQCount++; + if (IRQCount == 237) { + X6502_IRQBegin(FCEU_IQEXT); + } + } +} + +static void UNLTF1201Power(void) { + IRQPre = IRQCount = IRQa = 0; + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, UNLTF1201Write); + SyncPrg(); + SyncChr(); +} + +void UNLTF1201_Init(CartInfo *info) { + info->Power = UNLTF1201Power; + GameHBIRQHook = UNLTF1201IRQCounter; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/transformer.c b/src/boards/transformer.c new file mode 100644 index 0000000..c57ac44 --- /dev/null +++ b/src/boards/transformer.c @@ -0,0 +1,96 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +char *GetKeyboard(void); + +static char *TransformerKeys, oldkeys[256]; +static int TransformerCycleCount, TransformerChar = 0; + +static void FP_FASTAPASS(1) TransformerIRQHook(int a) { + TransformerCycleCount += a; + if (TransformerCycleCount >= 1000) { + uint32 i; + TransformerCycleCount -= 1000; + TransformerKeys = GetKeyboard(); + + for (i = 0; i < 256; i++) { + if (oldkeys[i] != TransformerKeys[i]) { + if (oldkeys[i] == 0) + TransformerChar = i; + else + TransformerChar = i | 0x80; + X6502_IRQBegin(FCEU_IQEXT); + memcpy((void*)&oldkeys[0], (void*)TransformerKeys, 256); + break; + } + } + } +} + +static DECLFR(TransformerRead) { + uint8 ret = 0; + switch (A & 3) { + case 0: ret = TransformerChar & 15; break; + case 1: ret = (TransformerChar >> 4); break; + case 2: break; + case 4: break; + } + X6502_IRQEnd(FCEU_IQEXT); + return ret; +} + +static void TransformerPower(void) { + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, 0); + setprg16(0xC000, ~0); + setchr8(0); + + SetReadHandler(0x5000, 0x5004, TransformerRead); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + + MapIRQHook = TransformerIRQHook; +} + +static void TransformerClose(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +void Transformer_Init(CartInfo *info) { + info->Power = TransformerPower; + info->Close = TransformerClose; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); +} diff --git a/src/boards/vrc1.c b/src/boards/vrc1.c new file mode 100644 index 0000000..899bcfb --- /dev/null +++ b/src/boards/vrc1.c @@ -0,0 +1,70 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * VRC-1 + * + */ + +#include "mapinc.h" + +static uint8 preg[3], creg[2], mode; +static SFORMAT StateRegs[] = +{ + { &mode, 1, "MODE" }, + { creg, 2, "CREG" }, + { preg, 3, "PREG" }, + { 0 } +}; + +static void Sync(void) { + setprg8(0x8000, preg[0]); + setprg8(0xA000, preg[1]); + setprg8(0xC000, preg[2]); + setprg8(0xE000, ~0); + setchr4(0x0000, creg[0] | ((mode & 2) << 3)); + setchr4(0x1000, creg[1] | ((mode & 4) << 2)); + setmirror((mode & 1) ^ 1); +} + +static DECLFW(M75Write) { + switch (A & 0xF000) { + case 0x8000: preg[0] = V; Sync(); break; + case 0x9000: mode = V; Sync(); break; + case 0xA000: preg[1] = V; Sync(); break; + case 0xC000: preg[2] = V; Sync(); break; + case 0xE000: creg[0] = V & 0xF; Sync(); break; + case 0xF000: creg[1] = V & 0xF; Sync(); break; + } +} + +static void M75Power(void) { + Sync(); + SetWriteHandler(0x8000, 0xFFFF, M75Write); + SetReadHandler(0x8000, 0xFFFF, CartBR); +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper75_Init(CartInfo *info) { + info->Power = M75Power; + AddExState(&StateRegs, ~0, 0, 0); + GameStateRestore = StateRestore; +} diff --git a/src/boards/vrc2and4.c b/src/boards/vrc2and4.c new file mode 100644 index 0000000..69449c6 --- /dev/null +++ b/src/boards/vrc2and4.c @@ -0,0 +1,270 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * VRC-2/VRC-4 Konami + * VRC-4 Pirate + */ + +#include "mapinc.h" + +static uint8 isPirate, is22; +static uint16 IRQCount; +static uint8 IRQLatch, IRQa; +static uint8 prgreg[2], chrreg[8]; +static uint16 chrhi[8]; +static uint8 regcmd, irqcmd, mirr, big_bank; +static uint16 acount = 0; +static uint16 weirdo = 0; + +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { prgreg, 2, "PREG" }, + { chrreg, 8, "CREG" }, + { chrhi, 16, "CRGH" }, + { ®cmd, 1, "CMDR" }, + { &irqcmd, 1, "CMDI" }, + { &mirr, 1, "MIRR" }, + { &big_bank, 1, "BIGB" }, + { &IRQCount, 2, "IRQC" }, + { &IRQLatch, 1, "IRQL" }, + { &IRQa, 1, "IRQA" }, + { 0 } +}; + +static void Sync(void) { + if (regcmd & 2) { + setprg8(0xC000, prgreg[0] | big_bank); + setprg8(0x8000, ((~1) & 0x1F) | big_bank); + } else { + setprg8(0x8000, prgreg[0] | big_bank); + setprg8(0xC000, ((~1) & 0x1F) | big_bank); + } + setprg8(0xA000, prgreg[1] | big_bank); + setprg8(0xE000, ((~0) & 0x1F) | big_bank); + if (UNIFchrrama) + setchr8(0); + else { + uint8 i; + if (!weirdo) + for (i = 0; i < 8; i++) + setchr1(i << 10, (chrhi[i] | chrreg[i]) >> is22); + else { + setchr1(0x0000, 0xFC); + setchr1(0x0400, 0xFD); + setchr1(0x0800, 0xFF); + weirdo--; + } + } + switch (mirr & 0x3) { + 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 DECLFW(VRC24Write) { + A &= 0xF003; + if ((A >= 0xB000) && (A <= 0xE003)) { + if (UNIFchrrama) + big_bank = (V & 8) << 2; // my personally many-in-one feature ;) just for support pirate cart 2-in-1 + else { + uint16 i = ((A >> 1) & 1) | ((A - 0xB000) >> 11); + uint16 nibble = ((A & 1) << 2); + chrreg[i] = (chrreg[i] & (0xF0 >> nibble)) | ((V & 0xF) << nibble); + if (nibble) + chrhi[i] = (V & 0x10) << 4; // another one many in one feature from pirate carts + } + Sync(); + } else + switch (A & 0xF003) { + case 0x8000: + case 0x8001: + case 0x8002: + case 0x8003: + if (!isPirate) { + prgreg[0] = V & 0x1F; + Sync(); + } + break; + case 0xA000: + case 0xA001: + case 0xA002: + case 0xA003: + if (!isPirate) + prgreg[1] = V & 0x1F; + else { + prgreg[0] = (V & 0x1F) << 1; + prgreg[1] = ((V & 0x1F) << 1) | 1; + } + Sync(); + break; + case 0x9000: + case 0x9001: if (V != 0xFF) mirr = V; Sync(); break; + case 0x9002: + case 0x9003: regcmd = V; Sync(); break; + 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; irqcmd = V & 1; break; + case 0xF003: X6502_IRQEnd(FCEU_IQEXT); IRQa = irqcmd; break; + } +} + +static DECLFW(M21Write) { + A = (A & 0xF000) | ((A >> 1) & 0x3); // Ganbare Goemon Gaiden 2 - Tenka no Zaihou (J) [!] isn't mapper 21 actually, + // it's mapper 23 by wirings + VRC24Write(A, V); +} + +static DECLFW(M22Write) { + if (A == 0xC007) { // Ganbare Goemon Gaiden does strange things!!! at the end credits + weirdo = 8; // quick dirty hack, seems there is no other games with such PCB, so + // we never know if it will not work for something else lol + } + A |= ((A >> 2) & 0x3); // It's just swapped lines from 21 mapper + // + VRC24Write((A & 0xF000) | ((A >> 1) & 1) | ((A << 1) & 2), V); +} + +static DECLFW(M23Write) { + A |= ((A >> 2) & 0x3) | ((A >> 4) & 0x3) | ((A >> 6) & 0x3);// actually there is many-in-one mapper source, some pirate or + // licensed games use various address bits for registers + VRC24Write(A, V); +} + +static void M21Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M21Write); +} + +static void M22Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M22Write); +} + +static void M23Power(void) { + big_bank = 0x20; + Sync(); + setprg8r(0x10, 0x6000, 0); // Only two Goemon games are have battery backed RAM, three more shooters + // (Parodius Da!, Gradius 2 and Crisis Force uses 2k or SRAM at 6000-67FF only + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M23Write); +} + +static void M25Power(void) { + big_bank = 0x20; + Sync(); + setprg8r(0x10, 0x6000, 0); + SetReadHandler(0x6000, 0x7FFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, M22Write); +} + +void FP_FASTAPASS(1) VRC24IRQHook(int a) { + #define LCYCS 341 + if (IRQa) { + acount += a * 3; + if (acount >= LCYCS) { + while (acount >= LCYCS) { + acount -= LCYCS; + IRQCount++; + if (IRQCount & 0x100) { + X6502_IRQBegin(FCEU_IQEXT); + IRQCount = IRQLatch; + } + } + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +static void VRC24Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +void Mapper21_Init(CartInfo *info) { + isPirate = 0; + is22 = 0; + info->Power = M21Power; + MapIRQHook = VRC24IRQHook; + GameStateRestore = StateRestore; + + AddExState(&StateRegs, ~0, 0, 0); +} + +void Mapper22_Init(CartInfo *info) { + isPirate = 0; + is22 = 1; + info->Power = M22Power; + GameStateRestore = StateRestore; + + AddExState(&StateRegs, ~0, 0, 0); +} + +void VRC24_Init(CartInfo *info) { + info->Close = VRC24Close; + MapIRQHook = VRC24IRQHook; + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + + AddExState(&StateRegs, ~0, 0, 0); +} + +void Mapper23_Init(CartInfo *info) { + isPirate = 0; + is22 = 0; + info->Power = M23Power; + VRC24_Init(info); +} + +void Mapper25_Init(CartInfo *info) { + isPirate = 0; + is22 = 0; + info->Power = M25Power; + VRC24_Init(info); +} + +void UNLT230_Init(CartInfo *info) { + isPirate = 1; + is22 = 0; + info->Power = M23Power; + VRC24_Init(info); +} diff --git a/src/boards/vrc3.c b/src/boards/vrc3.c new file mode 100644 index 0000000..6826a9c --- /dev/null +++ b/src/boards/vrc3.c @@ -0,0 +1,133 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * VRC-3 + * + */ + +#include "mapinc.h" + +static uint8 preg; +static uint8 IRQx; //autoenable +static uint8 IRQm; //mode +static uint8 IRQa; +static uint16 IRQReload, IRQCount; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { &preg, 1, "PREG" }, + { &IRQa, 1, "IRQA" }, + { &IRQx, 1, "IRQX" }, + { &IRQm, 1, "IRQM" }, + { &IRQReload, 2, "IRQR" }, + { &IRQCount, 2, "IRQC" }, + { 0 } +}; + +static void Sync(void) { + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, preg); + setprg16(0xC000, ~0); + setchr8(0); +} + +static DECLFW(M73Write) { + switch (A & 0xF000) { + case 0x8000: IRQReload &= 0xFFF0; IRQReload |= (V & 0xF) << 0; break; + case 0x9000: IRQReload &= 0xFF0F; IRQReload |= (V & 0xF) << 4; break; + case 0xA000: IRQReload &= 0xF0FF; IRQReload |= (V & 0xF) << 8; break; + case 0xB000: IRQReload &= 0x0FFF; IRQReload |= (V & 0xF) << 12; break; + case 0xC000: + IRQm = V & 4; + IRQx = V & 1; + IRQa = V & 2; + if (IRQa) { + if (IRQm) { + IRQCount &= 0xFFFF; + IRQCount |= (IRQReload & 0xFF); + } else + IRQCount = IRQReload; + } + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xD000: X6502_IRQEnd(FCEU_IQEXT); IRQa = IRQx; break; + case 0xF000: preg = V; Sync(); break; + } +} + +static void M73IRQHook(int a) { + uint32 i; + if (!IRQa) return; + for (i = 0; i < a; i++) { + if (IRQm) { + uint16 temp = IRQCount; + temp &= 0xFF; + IRQCount &= 0xFF00; + if (temp == 0xFF) { + IRQCount = IRQReload; + IRQCount |= (uint16)(IRQReload & 0xFF); + X6502_IRQBegin(FCEU_IQEXT); + } else { + temp++; + IRQCount |= temp; + } + } else { + //16 bit mode + if (IRQCount == 0xFFFF) { + IRQCount = IRQReload; + X6502_IRQBegin(FCEU_IQEXT); + } else + IRQCount++; + } + } +} + +static void M73Power(void) { + IRQReload = IRQm = IRQx = 0; + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, M73Write); +} + +static void M73Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper73_Init(CartInfo *info) { + info->Power = M73Power; + info->Close = M73Close; + MapIRQHook = M73IRQHook; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + AddExState(&StateRegs, ~0, 0, 0); + GameStateRestore = StateRestore; +} diff --git a/src/boards/vrc5.c b/src/boards/vrc5.c new file mode 100644 index 0000000..d9e783b --- /dev/null +++ b/src/boards/vrc5.c @@ -0,0 +1,225 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * VRC-5 (CAI Shogakko no Sansu) + * + */ + +#include "mapinc.h" + +static uint8 QTAINTRAM[2048]; +static writefunc old2007wrap; + +static uint16 CHRSIZE = 8192; +static uint16 WRAMSIZE = 8192 + 4096; +static uint8 *CHRRAM = NULL; +static uint8 *WRAM = NULL; + +static uint8 IRQa, K4IRQ; +static uint32 IRQLatch, IRQCount; + +static uint8 regs[16]; +//static uint8 test[8]; +static SFORMAT StateRegs[] = +{ + { &IRQCount, 1, "IRQC" }, + { &IRQLatch, 1, "IRQL" }, + { &IRQa, 1, "IRQA" }, + { &K4IRQ, 1, "KIRQ" }, + { regs, 16, "REGS" }, + { 0 } +}; + +static void chrSync(void) { + setchr4r(0x10, 0x0000, regs[5] & 1); + setchr4r(0x10, 0x1000, 0); +} + +static void Sync(void) { + chrSync(); +// if(regs[0xA]&0x10) +// { +/* setchr1r(0x10,0x0000,(((regs[5]&1))<<2)+0); + setchr1r(0x10,0x0400,(((regs[5]&1))<<2)+1); + setchr1r(0x10,0x0800,(((regs[5]&1))<<2)+2); + setchr1r(0x10,0x0c00,(((regs[5]&1))<<2)+3); + setchr1r(0x10,0x1000,0); + setchr1r(0x10,0x1400,1); + setchr1r(0x10,0x1800,2); + setchr1r(0x10,0x1c00,3);*/ +/* setchr1r(0x10,0x0000,(((regs[5]&1))<<2)+0); + setchr1r(0x10,0x0400,(((regs[5]&1))<<2)+1); + setchr1r(0x10,0x0800,(((regs[5]&1))<<2)+2); + setchr1r(0x10,0x0c00,(((regs[5]&1))<<2)+3); + setchr1r(0x10,0x1000,(((regs[5]&1)^1)<<2)+4); + setchr1r(0x10,0x1400,(((regs[5]&1)^1)<<2)+5); + setchr1r(0x10,0x1800,(((regs[5]&1)^1)<<2)+6); + setchr1r(0x10,0x1c00,(((regs[5]&1)^1)<<2)+7); +*/ +// } +// else +// { +/* + setchr1r(0x10,0x0000,(((regs[5]&1)^1)<<2)+0); + setchr1r(0x10,0x0400,(((regs[5]&1)^1)<<2)+1); + setchr1r(0x10,0x0800,(((regs[5]&1)^1)<<2)+2); + setchr1r(0x10,0x0c00,(((regs[5]&1)^1)<<2)+3); + setchr1r(0x10,0x1000,(((regs[5]&1))<<2)+4); + setchr1r(0x10,0x1400,(((regs[5]&1))<<2)+5); + setchr1r(0x10,0x1800,(((regs[5]&1))<<2)+6); + setchr1r(0x10,0x1c00,(((regs[5]&1))<<2)+7); +// } +//*/ +/* setchr1r(1,0x0000,test[0]); + setchr1r(1,0x0400,test[1]); + setchr1r(1,0x0800,test[2]); + setchr1r(1,0x0c00,test[3]); + setchr1r(1,0x1000,test[4]); + setchr1r(1,0x1400,test[5]); + setchr1r(1,0x1800,test[6]); + setchr1r(1,0x1c00,test[7]); +*/ + setprg4r(0x10, 0x6000, regs[0] & 1); + if (regs[2] >= 0x40) + setprg8r(1, 0x8000, (regs[2] - 0x40)); + else + setprg8r(0, 0x8000, (regs[2] & 0x3F)); + if (regs[3] >= 0x40) + setprg8r(1, 0xA000, (regs[3] - 0x40)); + else + setprg8r(0, 0xA000, (regs[3] & 0x3F)); + if (regs[4] >= 0x40) + setprg8r(1, 0xC000, (regs[4] - 0x40)); + else + setprg8r(0, 0xC000, (regs[4] & 0x3F)); + + setprg8r(1, 0xE000, ~0); + setmirror(MI_V); +} + +/*static DECLFW(TestWrite) +{ + test[A&7] = V; + Sync(); +}*/ + +static DECLFW(M190Write) { +// FCEU_printf("write %04x:%04x %d, %d\n",A,V,scanline,timestamp); + regs[(A & 0x0F00) >> 8] = V; + switch (A) { + case 0xd600: IRQLatch &= 0xFF00; IRQLatch |= V; break; + case 0xd700: IRQLatch &= 0x00FF; IRQLatch |= V << 8; break; + case 0xd900: IRQCount = IRQLatch; IRQa = V & 2; K4IRQ = V & 1; X6502_IRQEnd(FCEU_IQEXT); break; + case 0xd800: IRQa = K4IRQ; X6502_IRQEnd(FCEU_IQEXT); break; + } + Sync(); +} + +static DECLFR(M190Read) { +// FCEU_printf("read %04x:%04x %d, %d\n",A,regs[(A&0x0F00)>>8],scanline,timestamp); + return regs[(A & 0x0F00) >> 8] + regs[0x0B]; +} +static void FP_FASTAPASS(1) VRC5IRQ(int a) { + if (IRQa) { + IRQCount += a; + if (IRQCount & 0x10000) { + X6502_IRQBegin(FCEU_IQEXT); + IRQCount = IRQLatch; + } + } +} + +//static void FP_FASTAPASS(1) Mapper190_PPU(uint32 A) +//{ +// if(A<0x2000) +// setchr4r(0x10,0x1000,QTAINTRAM[A&0x1FFF]&1); +// else +// chrSync(); +//} + +static DECLFW(M1902007Wrap) { + if (A >= 0x2000) { + if (regs[0xA] & 1) + QTAINTRAM[A & 0x1FFF] = V; + else + old2007wrap(A, V); + } +} + + +static void M190Power(void) { +/* test[0]=0; + test[1]=1; + test[2]=2; + test[3]=3; + test[4]=4; + test[5]=5; + test[6]=6; + test[7]=7; +*/ + setprg4r(0x10, 0x7000, 2); + + old2007wrap = GetWriteHandler(0x2007); + SetWriteHandler(0x2007, 0x2007, M1902007Wrap); + + SetReadHandler(0x6000, 0xFFFF, CartBR); +// SetWriteHandler(0x5000,0x5007,TestWrite); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, M190Write); + SetReadHandler(0xDC00, 0xDC00, M190Read); + SetReadHandler(0xDD00, 0xDD00, M190Read); + Sync(); +} + +static void M190Close(void) { + if (CHRRAM) + FCEU_gfree(CHRRAM); + CHRRAM = NULL; + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper190_Init(CartInfo *info) { + info->Power = M190Power; + info->Close = M190Close; + GameStateRestore = StateRestore; + + MapIRQHook = VRC5IRQ; +// PPU_hook=Mapper190_PPU; + + CHRRAM = (uint8*)FCEU_gmalloc(CHRSIZE); + SetupCartCHRMapping(0x10, CHRRAM, CHRSIZE, 1); + AddExState(CHRRAM, CHRSIZE, 0, "CRAM"); + + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE - 4096; + } + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/vrc6.c b/src/boards/vrc6.c new file mode 100644 index 0000000..531d4c5 --- /dev/null +++ b/src/boards/vrc6.c @@ -0,0 +1,376 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * VRC-6 + * + */ + +#include "mapinc.h" + +static uint8 is26; +static uint8 prg[2], chr[8], mirr; +static uint8 IRQLatch, IRQa, IRQd; +static int32 IRQCount, CycleCount; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { prg, 2, "PRG" }, + { chr, 8, "CHR" }, + { &mirr, 1, "MIRR" }, + { &IRQa, 1, "IRQA" }, + { &IRQd, 1, "IRQD" }, + { &IRQLatch, 1, "IRQL" }, + { &IRQCount, 4, "IRQC" }, + { &CycleCount, 4, "CYCC" }, + { 0 } +}; + +static void(*sfun[3]) (void); +static uint8 vpsg1[8]; +static uint8 vpsg2[4]; +static int32 cvbc[3]; +static int32 vcount[3]; +static int32 dcount[2]; + +static SFORMAT SStateRegs[] = +{ + { vpsg1, 8, "PSG1" }, + { vpsg2, 4, "PSG2" }, + { 0 } +}; + +static void Sync(void) { + uint8 i; + if (is26) + setprg8r(0x10, 0x6000, 0); + setprg16(0x8000, prg[0]); + setprg8(0xc000, prg[1]); + setprg8(0xe000, ~0); + for (i = 0; i < 8; i++) + setchr1(i << 10, chr[i]); + switch (mirr & 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 DECLFW(VRC6SW) { + A &= 0xF003; + if (A >= 0x9000 && A <= 0x9002) { + vpsg1[A & 3] = V; + if (sfun[0]) sfun[0](); + } else if (A >= 0xA000 && A <= 0xA002) { + vpsg1[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(VRC6Write) { + if (is26) + A = (A & 0xFFFC) | ((A >> 1) & 1) | ((A << 1) & 2); + if (A >= 0x9000 && A <= 0xB002) { + VRC6SW(A, V); + return; + } + switch (A & 0xF003) { + case 0x8000: prg[0] = V; Sync(); break; + case 0xB003: mirr = (V >> 2) & 3; Sync(); break; + case 0xC000: prg[1] = V; Sync(); break; + case 0xD000: chr[0] = V; Sync(); break; + case 0xD001: chr[1] = V; Sync(); break; + case 0xD002: chr[2] = V; Sync(); break; + case 0xD003: chr[3] = V; Sync(); break; + case 0xE000: chr[4] = V; Sync(); break; + case 0xE001: chr[5] = V; Sync(); break; + case 0xE002: chr[6] = V; Sync(); break; + case 0xE003: chr[7] = V; Sync(); break; + case 0xF000: IRQLatch = V; X6502_IRQEnd(FCEU_IQEXT); break; + case 0xF001: + IRQa = V & 2; + IRQd = V & 1; + if (V & 2) + IRQCount = IRQLatch; + CycleCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xF002: + IRQa = IRQd; + X6502_IRQEnd(FCEU_IQEXT); + } +} + +static void VRC6Power(void) { + Sync(); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetWriteHandler(0x8000, 0xFFFF, VRC6Write); +} + +static void VRC6IRQHook(int a) { + if (IRQa) { + CycleCount += a * 3; + while (CycleCount >= 341) { + CycleCount -= 341; + IRQCount++; + if (IRQCount == 0x100) { + IRQCount = IRQLatch; + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +static void VRC6Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void StateRestore(int version) { + Sync(); +} + +// VRC6 Sound + +static void DoSQV1(void); +static void DoSQV2(void); +static void DoSawV(void); + +static INLINE void DoSQV(int x) { + int32 V; + int32 amp = (((vpsg1[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 (vpsg1[(x << 2) | 0x2] & 0x80) { + if (vpsg1[x << 2] & 0x80) { + for (V = start; V < end; V++) + Wave[V >> 4] += amp; + } else { + int32 thresh = (vpsg1[x << 2] >> 4) & 7; + int32 freq = ((vpsg1[(x << 2) | 0x1] | ((vpsg1[(x << 2) | 0x2] & 15) << 8)) + 1) << 17; + for (V = start; V < end; V++) { + if (dcount[x] > thresh) + Wave[V >> 4] += amp; + vcount[x] -= nesincsize; + while (vcount[x] <= 0) { + 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 = ((vpsg1[x << 2] & 15) << 8) * 6 / 8; + + if (vpsg1[(x << 2) | 0x2] & 0x80) { + if (vpsg1[x << 2] & 0x80) { + for (V = cvbc[x]; V < SOUNDTS; V++) + WaveHi[V] += amp; + } else { + int32 thresh = (vpsg1[x << 2] >> 4) & 7; + for (V = cvbc[x]; V < SOUNDTS; V++) { + if (dcount[x] > thresh) + WaveHi[V] += amp; + vcount[x]--; + if (vcount[x] <= 0) { + vcount[x] = (vpsg1[(x << 2) | 0x1] | ((vpsg1[(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)); + AddExState(&SStateRegs, ~0, 0, 0); +} + +// VRC6 Sound + +void Mapper24_Init(CartInfo *info) { + is26 = 0; + info->Power = VRC6Power; + MapIRQHook = VRC6IRQHook; + VRC6_ESI(); + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +void Mapper26_Init(CartInfo *info) { + is26 = 1; + info->Power = VRC6Power; + info->Close = VRC6Close; + MapIRQHook = VRC6IRQHook; + VRC6_ESI(); + GameStateRestore = StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + + AddExState(&StateRegs, ~0, 0, 0); +} + +void NSFVRC6_Init(void) { + VRC6_ESI(); + SetWriteHandler(0x8000, 0xbfff, VRC6SW); +} diff --git a/src/boards/vrc7.c b/src/boards/vrc7.c new file mode 100644 index 0000000..9900222 --- /dev/null +++ b/src/boards/vrc7.c @@ -0,0 +1,201 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mapinc.h" + +static uint8 vrc7idx, preg[3], creg[8], mirr; +static uint8 IRQLatch, IRQa, IRQd; +static int32 IRQCount, CycleCount; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static SFORMAT StateRegs[] = +{ + { &vrc7idx, 1, "VRCI" }, + { preg, 3, "PREG" }, + { creg, 8, "CREG" }, + { &mirr, 1, "MIRR" }, + { &IRQa, 1, "IRQA" }, + { &IRQd, 1, "IRQD" }, + { &IRQLatch, 1, "IRQL" }, + { &IRQCount, 4, "IRQC" }, + { &CycleCount, 4, "CYCC" }, + { 0 } +}; + +// VRC7 Sound + +#include "emu2413.h" + +static int32 dwave = 0; +static OPLL *VRC7Sound = NULL; + +void DoVRC7Sound(void) { + int32 z, a; + if (FSettings.soundq >= 1) + return; + z = ((SOUNDTS << 16) / soundtsinc) >> 4; + a = z - dwave; + OPLL_fillbuf(VRC7Sound, &Wave[dwave], a, 1); + dwave += a; +} + +void UpdateOPLNEO(int32 *Wave, int Count) { + OPLL_fillbuf(VRC7Sound, Wave, Count, 4); +} + +void UpdateOPL(int Count) { + int32 z, a; + z = ((SOUNDTS << 16) / soundtsinc) >> 4; + a = z - dwave; + if (VRC7Sound && a) + OPLL_fillbuf(VRC7Sound, &Wave[dwave], a, 1); + dwave = 0; +} + +static void VRC7SC(void) { + if (VRC7Sound) + OPLL_set_rate(VRC7Sound, FSettings.SndRate); +} + +static void VRC7SKill(void) { + if (VRC7Sound) + OPLL_delete(VRC7Sound); + VRC7Sound = NULL; +} + +static void VRC7_ESI(void) { + GameExpSound.RChange = VRC7SC; + GameExpSound.Kill = VRC7SKill; + VRC7Sound = OPLL_new(3579545, FSettings.SndRate ? FSettings.SndRate : 44100); + OPLL_reset(VRC7Sound); + OPLL_reset(VRC7Sound); +} + +// VRC7 Sound + +static void Sync(void) { + uint8 i; + setprg8r(0x10, 0x6000, 0); + setprg8(0x8000, preg[0]); + setprg8(0xA000, preg[1]); + setprg8(0xC000, preg[2]); + setprg8(0xE000, ~0); + for (i = 0; i < 8; i++) + setchr1(i << 10, creg[i]); + switch (mirr & 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 DECLFW(VRC7SW) { + if (FSettings.SndRate) { + OPLL_writeReg(VRC7Sound, vrc7idx, V); + GameExpSound.Fill = UpdateOPL; + GameExpSound.NeoFill = UpdateOPLNEO; + } +} + +static DECLFW(VRC7Write) { + A |= (A & 8) << 1; // another two-in-oooone + if (A >= 0xA000 && A <= 0xDFFF) { + A &= 0xF010; + creg[((A >> 4) & 1) | ((A - 0xA000) >> 11)] = V; + Sync(); + } else if (A == 0x9030) { + VRC7SW(A, V); + } else switch (A & 0xF010) { + case 0x8000: preg[0] = V; Sync(); break; + case 0x8010: preg[1] = V; Sync(); break; + case 0x9000: preg[2] = V; Sync(); break; + case 0x9010: vrc7idx = V; break; + case 0xE000: mirr = V & 3; Sync(); break; + case 0xE010: IRQLatch = V; X6502_IRQEnd(FCEU_IQEXT); break; + case 0xF000: + IRQa = V & 2; + IRQd = V & 1; + if (V & 2) + IRQCount = IRQLatch; + CycleCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xF010: + IRQa = IRQd; + X6502_IRQEnd(FCEU_IQEXT); + break; + } +} + +static void VRC7Power(void) { + Sync(); + SetWriteHandler(0x6000, 0x7FFF, CartBW); + SetReadHandler(0x6000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, VRC7Write); +} + +static void VRC7Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void VRC7IRQHook(int a) { + if (IRQa) { + CycleCount += a * 3; + while (CycleCount >= 341) { + CycleCount -= 341; + IRQCount++; + if (IRQCount == 0x100) { + IRQCount = IRQLatch; + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void Mapper85_Init(CartInfo *info) { + info->Power = VRC7Power; + info->Close = VRC7Close; + MapIRQHook = VRC7IRQHook; + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + if (info->battery) { + info->SaveGame[0] = WRAM; + info->SaveGameLen[0] = WRAMSIZE; + } + GameStateRestore = StateRestore; + VRC7_ESI(); + AddExState(&StateRegs, ~0, 0, 0); +} + +void NSFVRC7_Init(void) { + SetWriteHandler(0x9010, 0x901F, VRC7Write); + SetWriteHandler(0x9030, 0x903F, VRC7Write); + VRC7_ESI(); +} diff --git a/src/boards/vrc7p.c b/src/boards/vrc7p.c new file mode 100644 index 0000000..5a886cb --- /dev/null +++ b/src/boards/vrc7p.c @@ -0,0 +1,120 @@ +/* FCE Ultra - NES/Famicom Emulator + * + * Copyright notice for this file: + * Copyright (C) 2009 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * YOKO Mortal Kombat V Pro, VRC7 pirate clone + */ + +#include "mapinc.h" + +static uint8 prg[3], chr[8], mirr; +static uint8 IRQLatch, IRQa, IRQd; +static int32 IRQCount, CycleCount; + +static SFORMAT StateRegs[] = +{ + { prg, 3, "PRG" }, + { chr, 8, "CHR" }, + { &mirr, 1, "MIRR" }, + { &IRQa, 1, "IRQA" }, + { &IRQd, 1, "IRQD" }, + { &IRQLatch, 1, "IRQL" }, + { &IRQCount, 4, "IRQC" }, + { &CycleCount, 4, "CYCC" }, + { 0 } +}; + +static void Sync(void) { + uint8 i; + setprg8(0x8000, prg[0]); + setprg8(0xa000, prg[1]); + setprg8(0xc000, prg[2]); + setprg8(0xe000, ~0); + for (i = 0; i < 8; i++) + setchr1(i << 10, chr[i]); + switch (mirr & 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 DECLFW(UNLVRC7Write) { + switch (A & 0xF008) { + case 0x8000: prg[0] = V; Sync(); break; + case 0x8008: prg[1] = V; Sync(); break; + case 0x9000: prg[2] = V; Sync(); break; + case 0xa000: chr[0] = V; Sync(); break; + case 0xa008: chr[1] = V; Sync(); break; + case 0xb000: chr[2] = V; Sync(); break; + case 0xb008: chr[3] = V; Sync(); break; + case 0xc000: chr[4] = V; Sync(); break; + case 0xc008: chr[5] = V; Sync(); break; + case 0xd000: chr[6] = V; Sync(); break; + case 0xd008: chr[7] = V; Sync(); break; + case 0xe000: mirr = V; Sync(); break; + case 0xe008: IRQLatch = V; X6502_IRQEnd(FCEU_IQEXT); break; + case 0xf000: + IRQa = V & 2; + IRQd = V & 1; + if (V & 2) + IRQCount = IRQLatch; + CycleCount = 0; + X6502_IRQEnd(FCEU_IQEXT); + break; + case 0xf008: + if (IRQd) + IRQa = 1; + else + IRQa = 0; + X6502_IRQEnd(FCEU_IQEXT); + break; + } +} + +static void UNLVRC7Power(void) { + Sync(); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, UNLVRC7Write); +} + +static void UNLVRC7IRQHook(int a) { + if (IRQa) { + CycleCount += a * 3; + while (CycleCount >= 341) { + CycleCount -= 341; + IRQCount++; + if (IRQCount == 248) { + IRQCount = IRQLatch; + X6502_IRQBegin(FCEU_IQEXT); + } + } + } +} + +static void StateRestore(int version) { + Sync(); +} + +void UNLVRC7_Init(CartInfo *info) { + info->Power = UNLVRC7Power; + MapIRQHook = UNLVRC7IRQHook; + GameStateRestore = StateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/boards/yoko.c b/src/boards/yoko.c new file mode 100644 index 0000000..1714f8a --- /dev/null +++ b/src/boards/yoko.c @@ -0,0 +1,236 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * YOKO mapper, almost the same as 83, TODO: figure out difference + * Mapper 83 - 30-in-1 mapper, two modes for single game carts, one mode for + * multigame Dragon Ball Z Party + * + * Mortal Kombat 2 YOKO + * N-CXX(M), XX - PRG+CHR, 12 - 128+256, 22 - 256+256, 14 - 128+512 + * + */ + +#include "mapinc.h" + +static uint8 mode, bank, reg[11], low[4], dip, IRQa; +static int32 IRQCount; +static uint8 *WRAM = NULL; +static uint32 WRAMSIZE; + +static uint8 is2kbank, isnot2kbank; + +static SFORMAT StateRegs[] = +{ + { &mode, 1, "MODE" }, + { &bank, 1, "BANK" }, + { &IRQCount, 4, "IRQC" }, + { &IRQa, 1, "IRQA" }, + { reg, 11, "REGS" }, + { low, 4, "LOWR" }, + { &is2kbank, 1, "IS2K" }, + { &isnot2kbank, 1, "NT2K" }, + { 0 } +}; + +static void UNLYOKOSync(void) { + setmirror((mode & 1) ^ 1); + setchr2(0x0000, reg[3]); + setchr2(0x0800, reg[4]); + setchr2(0x1000, reg[5]); + setchr2(0x1800, reg[6]); + if (mode & 0x10) { + uint32 base = (bank & 8) << 1; + setprg8(0x8000, (reg[0] & 0x0f) | base); + setprg8(0xA000, (reg[1] & 0x0f) | base); + setprg8(0xC000, (reg[2] & 0x0f) | base); + setprg8(0xE000, 0x0f | base); + } else { + if (mode & 8) + setprg32(0x8000, bank >> 1); + else { + setprg16(0x8000, bank); + setprg16(0xC000, ~0); + } + } +} + +static void M83Sync(void) { + switch (mode & 3) { // check if it is truth + case 0: setmirror(MI_V); break; + case 1: setmirror(MI_H); break; + case 2: setmirror(MI_0); break; + case 3: setmirror(MI_1); break; + } + if (is2kbank && !isnot2kbank) { + setchr2(0x0000, reg[0]); + setchr2(0x0800, reg[1]); + setchr2(0x1000, reg[6]); + setchr2(0x1800, reg[7]); + } else { + int x; + for (x = 0; x < 8; x++) + setchr1(x << 10, reg[x] | ((bank & 0x30) << 4)); + } + setprg8r(0x10, 0x6000, 0); + if (mode & 0x40) { + setprg16(0x8000, (bank & 0x3F)); // DBZ Party [p1] + setprg16(0xC000, (bank & 0x30) | 0xF); + } else { + setprg8(0x8000, reg[8]); + setprg8(0xA000, reg[9]); + setprg8(0xC000, reg[10]); + setprg8(0xE000, ~0); + } +} + +static DECLFW(UNLYOKOWrite) { + switch (A & 0x8C17) { + case 0x8000: bank = V; UNLYOKOSync(); break; + case 0x8400: mode = V; UNLYOKOSync(); break; + case 0x8800: IRQCount &= 0xFF00; IRQCount |= V; X6502_IRQEnd(FCEU_IQEXT); break; + case 0x8801: IRQa = mode & 0x80; IRQCount &= 0xFF; IRQCount |= V << 8; break; + case 0x8c00: reg[0] = V; UNLYOKOSync(); break; + case 0x8c01: reg[1] = V; UNLYOKOSync(); break; + case 0x8c02: reg[2] = V; UNLYOKOSync(); break; + case 0x8c10: reg[3] = V; UNLYOKOSync(); break; + case 0x8c11: reg[4] = V; UNLYOKOSync(); break; + case 0x8c16: reg[5] = V; UNLYOKOSync(); break; + case 0x8c17: reg[6] = V; UNLYOKOSync(); break; + } +} + +static DECLFW(M83Write) { + switch (A) { + case 0x8000: is2kbank = 1; + case 0xB000: // Dragon Ball Z Party [p1] BMC + case 0xB0FF: // Dragon Ball Z Party [p1] BMC + case 0xB1FF: bank = V; mode |= 0x40; M83Sync(); break; // Dragon Ball Z Party [p1] BMC + case 0x8100: mode = V | (mode & 0x40); M83Sync(); break; + case 0x8200: IRQCount &= 0xFF00; IRQCount |= V; X6502_IRQEnd(FCEU_IQEXT); break; + case 0x8201: IRQa = mode & 0x80; IRQCount &= 0xFF; IRQCount |= V << 8; break; + case 0x8300: reg[8] = V; mode &= 0xBF; M83Sync(); break; + case 0x8301: reg[9] = V; mode &= 0xBF; M83Sync(); break; + case 0x8302: reg[10] = V; mode &= 0xBF; M83Sync(); break; + case 0x8310: reg[0] = V; M83Sync(); break; + case 0x8311: reg[1] = V; M83Sync(); break; + case 0x8312: reg[2] = V; isnot2kbank = 1; M83Sync(); break; + case 0x8313: reg[3] = V; isnot2kbank = 1; M83Sync(); break; + case 0x8314: reg[4] = V; isnot2kbank = 1; M83Sync(); break; + case 0x8315: reg[5] = V; isnot2kbank = 1; M83Sync(); break; + case 0x8316: reg[6] = V; M83Sync(); break; + case 0x8317: reg[7] = V; M83Sync(); break; + } +} + +static DECLFR(UNLYOKOReadDip) { + return (X.DB & 0xFC) | dip; +} + +static DECLFR(UNLYOKOReadLow) { + return low[A & 3]; +} + +static DECLFW(UNLYOKOWriteLow) { + low[A & 3] = V; +} + +static void UNLYOKOPower(void) { + mode = bank = 0; + dip = 3; + UNLYOKOSync(); + SetReadHandler(0x5000, 0x53FF, UNLYOKOReadDip); + SetReadHandler(0x5400, 0x5FFF, UNLYOKOReadLow); + SetWriteHandler(0x5400, 0x5FFF, UNLYOKOWriteLow); + SetReadHandler(0x8000, 0xFFFF, CartBR); + SetWriteHandler(0x8000, 0xFFFF, UNLYOKOWrite); +} + +static void M83Power(void) { + is2kbank = 0; + isnot2kbank = 0; + mode = bank = 0; + dip = 0; + M83Sync(); + SetReadHandler(0x5000, 0x5000, UNLYOKOReadDip); + SetReadHandler(0x5100, 0x5103, UNLYOKOReadLow); + SetWriteHandler(0x5100, 0x5103, UNLYOKOWriteLow); + SetReadHandler(0x6000, 0x7fff, CartBR); + SetWriteHandler(0x6000, 0x7fff, CartBW);// Pirate Dragon Ball Z Party [p1] used if for saves instead of seraial EEPROM + SetReadHandler(0x8000, 0xffff, CartBR); + SetWriteHandler(0x8000, 0xffff, M83Write); +} + +static void UNLYOKOReset(void) { + dip = (dip + 1) & 3; + mode = bank = 0; + UNLYOKOSync(); +} + +static void M83Reset(void) { + dip ^= 1; + M83Sync(); +} + +static void M83Close(void) { + if (WRAM) + FCEU_gfree(WRAM); + WRAM = NULL; +} + +static void FP_FASTAPASS(1) UNLYOKOIRQHook(int a) { + if (IRQa) { + IRQCount -= a; + if (IRQCount < 0) { + X6502_IRQBegin(FCEU_IQEXT); + IRQa = 0; + IRQCount = 0xFFFF; + } + } +} + +static void UNLYOKOStateRestore(int version) { + UNLYOKOSync(); +} + +static void M83StateRestore(int version) { + M83Sync(); +} + +void UNLYOKO_Init(CartInfo *info) { + info->Power = UNLYOKOPower; + info->Reset = UNLYOKOReset; + MapIRQHook = UNLYOKOIRQHook; + GameStateRestore = UNLYOKOStateRestore; + AddExState(&StateRegs, ~0, 0, 0); +} + +void Mapper83_Init(CartInfo *info) { + info->Power = M83Power; + info->Reset = M83Reset; + info->Close = M83Close; + MapIRQHook = UNLYOKOIRQHook; + GameStateRestore = M83StateRestore; + + WRAMSIZE = 8192; + WRAM = (uint8*)FCEU_gmalloc(WRAMSIZE); + SetupCartPRGMapping(0x10, WRAM, WRAMSIZE, 1); + AddExState(WRAM, WRAMSIZE, 0, "WRAM"); + + AddExState(&StateRegs, ~0, 0, 0); +} diff --git a/src/cart.c b/src/cart.c new file mode 100644 index 0000000..104435e --- /dev/null +++ b/src/cart.c @@ -0,0 +1,556 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "fceu-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); + else + return Page[A >> 11][A]; +} + +void FASTAPASS(3) setprg2r(int r, uint32 A, uint32 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, uint32 A, uint32 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, uint32 A, uint32 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, uint32 A, uint32 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, uint32 A, uint32 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, uint32 A, uint32 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, uint32 A, uint32 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, uint32 A, uint32 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, uint32 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(uint32 A, uint32 V) { + setchr1r(0, A, V); +} + +void FASTAPASS(2) setchr2(uint32 A, uint32 V) { + setchr2r(0, A, V); +} + +void FASTAPASS(2) setchr4(uint32 A, uint32 V) { + setchr4r(0, A, V); +} + +void FASTAPASS(1) setchr8(uint32 V) { + setchr8r(0, V); +} + +/* 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 FCEU_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 FCEU_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 FCEU_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); + } +} + +void FCEU_LoadGameSave(CartInfo *LocalHWInfo) { + if (LocalHWInfo->battery && LocalHWInfo->SaveGame[0]) { + 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/src/cart.h b/src/cart.h new file mode 100644 index 0000000..2723b28 --- /dev/null +++ b/src/cart.h @@ -0,0 +1,90 @@ +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(2) setchr8(unsigned int V); + +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 FCEU_GeniePower(void); + +void FCEU_OpenGenie(void); +void FCEU_CloseGenie(void); +void FCEU_KillGenie(void); diff --git a/src/cheat.c b/src/cheat.c new file mode 100644 index 0000000..1f41f02 --- /dev/null +++ b/src/cheat.c @@ -0,0 +1,727 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include "fceu-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; + uint32 addr; + uint32 val; + uint32 status; + uint32 type; + uint32 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; + if (compare >= 0) + 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/src/cheat.h b/src/cheat.h new file mode 100644 index 0000000..c951d82 --- /dev/null +++ b/src/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/src/crc32.c b/src/crc32.c new file mode 100644 index 0000000..52fddfd --- /dev/null +++ b/src/crc32.c @@ -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "fceu-types.h" +#include "crc32.h" + +#include +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/src/crc32.h b/src/crc32.h new file mode 100644 index 0000000..892dac2 --- /dev/null +++ b/src/crc32.h @@ -0,0 +1 @@ +uint32 CalcCRC32(uint32 crc, uint8 *buf, uint32 len); diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 0000000..b25be0c --- /dev/null +++ b/src/debug.c @@ -0,0 +1,497 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "fceu-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 &= 0x3FFF; + end &= 0x3FFF; + 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; + uint32 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) +*/ + { + uint32 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, uint32 A); + uint32 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, uint32 A) { + BPOINT *tmp; + + tmp = BreakPoints; + while (tmp) { + if (who & BPOINT_EXCLUDE) { + if ((tmp->type & who) == who) { + if ((X->PC >= tmp->A[0]) && (X->PC <= tmp->A[1])) { + return(1); + } + } + } else { + if (tmp->type & who) { + if (tmp->type & BPOINT_PC) + if (X->PC != A) goto don; + if (tmp->type & BPOINT_EXCLUDE) goto don; + + if ((A >= tmp->A[0]) && (A <= tmp->A[1])) { + if (!FindBPoint(X, who | BPOINT_EXCLUDE, A)) { + tmp->Handler(X, tmp->type, A); + return(1); + } + } + } + } + don: + tmp = tmp->next; + } + return(0); +} + +static uint8 ReadHandler(X6502 *X, uint32 A) { + extern X6502 XSave; + + if (X->preexec) + FindBPoint(&XSave, BPOINT_READ, A); + return(ARead[A](A)); +} + +static void WriteHandler(X6502 *X, uint32 A, uint8 V) { + extern X6502 XSave; + + if (X->preexec) + FindBPoint(&XSave, BPOINT_WRITE, A); + else + BWrite[A](A, V); +} + +int FCEUI_AddBreakPoint(int type, uint32 A1, uint32 A2, + void (*Handler)(X6502 *, int type, uint32 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, uint32 A1, uint32 A2, + void (*Handler)(X6502 *, int type, uint32 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, uint32 *A1, uint32 *A2, + void(**Handler) (X6502 *, int type, uint32 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, uint32 A1, uint32 A2, + void (*Handler)(X6502 *, int type, uint32 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); + tmp = 0; + 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/src/debug.h b/src/debug.h new file mode 100644 index 0000000..3826d0f --- /dev/null +++ b/src/debug.h @@ -0,0 +1,25 @@ +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 +#define BPOINT_EXCLUDE 8 + +#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/src/drawing.h b/src/drawing.h new file mode 100644 index 0000000..5b6772e --- /dev/null +++ b/src/drawing.h @@ -0,0 +1,222 @@ +void DrawTextLineBG(uint8 *dest) { + int x, y; + static int otable[7] = { 81, 49, 30, 17, 8, 3, 0 }; + 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; + } +} + +static void DrawMessage(void) { + if (howlong) { + uint8 *t; + howlong--; + t = XBuf + (FSettings.LastSLine - 16) * 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; + } + } +} + diff --git a/src/driver.h b/src/driver.h new file mode 100644 index 0000000..de1ff96 --- /dev/null +++ b/src/driver.h @@ -0,0 +1,250 @@ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#include "fceu-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_UNSET -1 +#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 SI_MOUSE 6 + +#define SIFC_UNSET -1 +#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_PEC586KB 6 +#define SIFC_HYPERSHOT 7 +#define SIFC_MAHJONG 8 +#define SIFC_QUIZKING 9 +#define SIFC_FTRAINERA 10 +#define SIFC_FTRAINERB 11 +#define SIFC_OEKAKIDS 12 +#define SIFC_BWORLD 13 +#define SIFC_TOPRIDER 14 + +#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); + +#ifdef COPYFAMI +/* Fake UNIF board to start new CFHI instance */ +FCEUGI *FCEUI_CopyFamiStart(); +#endif + +/* 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 FCEUI_SelectState(int); + +/* "fname" overrides the default save state filename code if non-NULL. */ +void FCEUI_SaveState(char *fname); +void FCEUI_LoadState(char *fname); + +void FCEUI_SelectMovie(int); +void FCEUI_SaveMovie(char *fname); +void FCEUI_LoadMovie(char *fname); + +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_MOVIE 5 + +#define FCEUIOD__COUNT 6 + +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(int oride); +int FCEUI_FDSEject(void); +void FCEUI_FDSSelect(void); + +int FCEUI_DatachSet(const uint8 *rcode); + +#ifdef __cplusplus +} +#endif + diff --git a/src/drivers/common/args.c b/src/drivers/common/args.c new file mode 100644 index 0000000..52b0dc7 --- /dev/null +++ b/src/drivers/common/args.c @@ -0,0 +1,86 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/****************************************************************/ +/* FCE Ultra */ +/* */ +/* This file contains code for parsing command-line */ +/* options. */ +/* */ +/****************************************************************/ + +#include +#include +#include + +#include "../../fceu-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/src/drivers/common/args.h b/src/drivers/common/args.h new file mode 100644 index 0000000..c034349 --- /dev/null +++ b/src/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/src/drivers/common/cheat.c b/src/drivers/common/cheat.c new file mode 100644 index 0000000..4f9f6c7 --- /dev/null +++ b/src/drivers/common/cheat.c @@ -0,0 +1,467 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#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/src/drivers/common/cheat.h b/src/drivers/common/cheat.h new file mode 100644 index 0000000..9215b75 --- /dev/null +++ b/src/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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +void DoConsoleCheatConfig(void); diff --git a/src/drivers/common/config.c b/src/drivers/common/config.c new file mode 100644 index 0000000..aa2c6e1 --- /dev/null +++ b/src/drivers/common/config.c @@ -0,0 +1,134 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/****************************************************************/ +/* FCE Ultra */ +/* */ +/* This file contains routines for reading/writing the */ +/* configuration file. */ +/* */ +/****************************************************************/ + +#include +#include +#include + +#include "../../fceu-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/src/drivers/common/config.h b/src/drivers/common/config.h new file mode 100644 index 0000000..9bcf464 --- /dev/null +++ b/src/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/src/drivers/common/hq2x.c b/src/drivers/common/hq2x.c new file mode 100644 index 0000000..a82c01f --- /dev/null +++ b/src/drivers/common/hq2x.c @@ -0,0 +1,2434 @@ +//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 +#include + +#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/src/drivers/common/hq2x.h b/src/drivers/common/hq2x.h new file mode 100644 index 0000000..67868bd --- /dev/null +++ b/src/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/src/drivers/common/hq3x.c b/src/drivers/common/hq3x.c new file mode 100644 index 0000000..7cfb1ad --- /dev/null +++ b/src/drivers/common/hq3x.c @@ -0,0 +1,3318 @@ +//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 +#include + +#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/src/drivers/common/hq3x.h b/src/drivers/common/hq3x.h new file mode 100644 index 0000000..209c46c --- /dev/null +++ b/src/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/src/drivers/common/scale2x.c b/src/drivers/common/scale2x.c new file mode 100644 index 0000000..bd2df10 --- /dev/null +++ b/src/drivers/common/scale2x.c @@ -0,0 +1,911 @@ +/* + * 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 + +/***************************************************************************/ +/* Scale2x C implementation */ + +static inline void scale2x_8_def_single(scale2x_uint8* __restrict__ dst, const scale2x_uint8* __restrict__ src0, const scale2x_uint8* __restrict__ src1, const scale2x_uint8* __restrict__ src2, unsigned count) { + assert(count >= 2); + + /* first pixel */ + dst[0] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0]) + dst[1] = src0[0]; + else + dst[1] = src1[0]; + ++src0; + ++src1; + ++src2; + dst += 2; + + /* central pixels */ + count -= 2; + while (count) { + if (src0[0] != src2[0] && src1[-1] != src1[1]) { + dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; + dst[1] = src1[1] == src0[0] ? src0[0] : src1[0]; + } else { + dst[0] = src1[0]; + dst[1] = src1[0]; + } + + ++src0; + ++src1; + ++src2; + dst += 2; + --count; + } + + /* last pixel */ + if (src1[-1] == src0[0] && src2[0] != src0[0]) + dst[0] = src0[0]; + else + dst[0] = src1[0]; + dst[1] = src1[0]; +} + +static inline void scale2x_16_def_single(scale2x_uint16* __restrict__ dst, const scale2x_uint16* __restrict__ src0, const scale2x_uint16* __restrict__ src1, const scale2x_uint16* __restrict__ src2, unsigned count) { + assert(count >= 2); + + /* first pixel */ + dst[0] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0]) + dst[1] = src0[0]; + else + dst[1] = src1[0]; + ++src0; + ++src1; + ++src2; + dst += 2; + + /* central pixels */ + count -= 2; + while (count) { + if (src0[0] != src2[0] && src1[-1] != src1[1]) { + dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; + dst[1] = src1[1] == src0[0] ? src0[0] : src1[0]; + } else { + dst[0] = src1[0]; + dst[1] = src1[0]; + } + + ++src0; + ++src1; + ++src2; + dst += 2; + --count; + } + + /* last pixel */ + if (src1[-1] == src0[0] && src2[0] != src0[0]) + dst[0] = src0[0]; + else + dst[0] = src1[0]; + dst[1] = src1[0]; +} + +static inline void scale2x_32_def_single(scale2x_uint32* __restrict__ dst, const scale2x_uint32* __restrict__ src0, const scale2x_uint32* __restrict__ src1, const scale2x_uint32* __restrict__ src2, unsigned count) { + assert(count >= 2); + + /* first pixel */ + dst[0] = src1[0]; + if (src1[1] == src0[0] && src2[0] != src0[0]) + dst[1] = src0[0]; + else + dst[1] = src1[0]; + ++src0; + ++src1; + ++src2; + dst += 2; + + /* central pixels */ + count -= 2; + while (count) { + if (src0[0] != src2[0] && src1[-1] != src1[1]) { + dst[0] = src1[-1] == src0[0] ? src0[0] : src1[0]; + dst[1] = src1[1] == src0[0] ? src0[0] : src1[0]; + } else { + dst[0] = src1[0]; + dst[1] = src1[0]; + } + + ++src0; + ++src1; + ++src2; + dst += 2; + --count; + } + + /* last pixel */ + if (src1[-1] == src0[0] && src2[0] != src0[0]) + dst[0] = src0[0]; + else + dst[0] = src1[0]; + dst[1] = src1[0]; +} + +/** + * Scale by a factor of 2 a row of pixels of 8 bits. + * The function is implemented in C. + * The pixels over the left and right borders are assumed of the same color of + * the pixels on the border. + * \param src0 Pointer at the first pixel of the previous row. + * \param src1 Pointer at the first pixel of the current row. + * \param src2 Pointer at the first pixel of the next row. + * \param count Length in pixels of the src0, src1 and src2 rows. + * It must be at least 2. + * \param dst0 First destination row, double length in pixels. + * \param dst1 Second destination row, double length in pixels. + */ +void scale2x_8_def(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) { + assert(count >= 2); + + scale2x_8_def_single(dst0, src0, src1, src2, count); + scale2x_8_def_single(dst1, src2, src1, src0, count); +} + +/** + * Scale by a factor of 2 a row of pixels of 16 bits. + * This function operates like scale2x_8_def() but for 16 bits pixels. + * \param src0 Pointer at the first pixel of the previous row. + * \param src1 Pointer at the first pixel of the current row. + * \param src2 Pointer at the first pixel of the next row. + * \param count Length in pixels of the src0, src1 and src2 rows. + * It must be at least 2. + * \param dst0 First destination row, double length in pixels. + * \param dst1 Second destination row, double length in pixels. + */ +void scale2x_16_def(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) { + assert(count >= 2); + + scale2x_16_def_single(dst0, src0, src1, src2, count); + scale2x_16_def_single(dst1, src2, src1, src0, count); +} + +/** + * Scale by a factor of 2 a row of pixels of 32 bits. + * This function operates like scale2x_8_def() but for 32 bits pixels. + * \param src0 Pointer at the first pixel of the previous row. + * \param src1 Pointer at the first pixel of the current row. + * \param src2 Pointer at the first pixel of the next row. + * \param count Length in pixels of the src0, src1 and src2 rows. + * It must be at least 2. + * \param dst0 First destination row, double length in pixels. + * \param dst1 Second destination row, double length in pixels. + */ +void scale2x_32_def(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) { + assert(count >= 2); + + scale2x_32_def_single(dst0, src0, src1, src2, count); + scale2x_32_def_single(dst1, src2, src1, src0, count); +} + +/***************************************************************************/ +/* Scale2x MMX implementation */ + +#if defined(__GNUC__) && defined(__i386__) + +/* + * Apply the Scale2x effect at a single row. + * This function must be called only by the other scale2x functions. + * + * Considering the pixel map : + * + * ABC (src0) + * DEF (src1) + * GHI (src2) + * + * this functions compute 2 new pixels in substitution of the source pixel E + * like this map : + * + * ab (dst) + * + * with these variables : + * + * ¤t -> E + * ¤t_left -> D + * ¤t_right -> F + * ¤t_upper -> B + * ¤t_lower -> H + * + * %0 -> current_upper + * %1 -> current + * %2 -> current_lower + * %3 -> dst + * %4 -> counter + * + * %mm0 -> *current_left + * %mm1 -> *current_next + * %mm2 -> tmp0 + * %mm3 -> tmp1 + * %mm4 -> tmp2 + * %mm5 -> tmp3 + * %mm6 -> *current_upper + * %mm7 -> *current + */ +static inline void scale2x_8_mmx_single(scale2x_uint8* dst, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) { + assert(count >= 16); + assert(count % 8 == 0); + + /* always do the first and last run */ + count -= 2 * 8; + + __asm__ __volatile__ ( +/* first run */ + /* set the current, current_pre, current_next registers */ + "movq 0(%1), %%mm0\n" + "movq 0(%1), %%mm7\n" + "movq 8(%1), %%mm1\n" + "psllq $56, %%mm0\n" + "psllq $56, %%mm1\n" + "psrlq $56, %%mm0\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $8, %%mm2\n" + "psrlq $8, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqb %%mm6, %%mm2\n" + "pcmpeqb %%mm6, %%mm4\n" + "pcmpeqb (%2), %%mm3\n" + "pcmpeqb (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqb %%mm1, %%mm2\n" + "pcmpeqb %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpcklbw %%mm4, %%mm2\n" + "punpckhbw %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + /* next */ + "addl $8, %0\n" + "addl $8, %1\n" + "addl $8, %2\n" + "addl $16, %3\n" + +/* central runs */ + "shrl $3, %4\n" + "jz 1f\n" + + "0:\n" + + /* set the current, current_pre, current_next registers */ + "movq -8(%1), %%mm0\n" + "movq (%1), %%mm7\n" + "movq 8(%1), %%mm1\n" + "psrlq $56, %%mm0\n" + "psllq $56, %%mm1\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $8, %%mm2\n" + "psrlq $8, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqb %%mm6, %%mm2\n" + "pcmpeqb %%mm6, %%mm4\n" + "pcmpeqb (%2), %%mm3\n" + "pcmpeqb (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqb %%mm1, %%mm2\n" + "pcmpeqb %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpcklbw %%mm4, %%mm2\n" + "punpckhbw %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + /* next */ + "addl $8, %0\n" + "addl $8, %1\n" + "addl $8, %2\n" + "addl $16, %3\n" + + "decl %4\n" + "jnz 0b\n" + "1:\n" + +/* final run */ + /* set the current, current_pre, current_next registers */ + "movq (%1), %%mm1\n" + "movq (%1), %%mm7\n" + "movq -8(%1), %%mm0\n" + "psrlq $56, %%mm1\n" + "psrlq $56, %%mm0\n" + "psllq $56, %%mm1\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $8, %%mm2\n" + "psrlq $8, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqb %%mm6, %%mm2\n" + "pcmpeqb %%mm6, %%mm4\n" + "pcmpeqb (%2), %%mm3\n" + "pcmpeqb (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqb %%mm1, %%mm2\n" + "pcmpeqb %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpcklbw %%mm4, %%mm2\n" + "punpckhbw %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count) + : + : "cc" + ); +} + +static inline void scale2x_16_mmx_single(scale2x_uint16* dst, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) { + assert(count >= 8); + assert(count % 4 == 0); + + /* always do the first and last run */ + count -= 2 * 4; + + __asm__ __volatile__ ( +/* first run */ + /* set the current, current_pre, current_next registers */ + "movq 0(%1), %%mm0\n" + "movq 0(%1), %%mm7\n" + "movq 8(%1), %%mm1\n" + "psllq $48, %%mm0\n" + "psllq $48, %%mm1\n" + "psrlq $48, %%mm0\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $16, %%mm2\n" + "psrlq $16, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqw %%mm6, %%mm2\n" + "pcmpeqw %%mm6, %%mm4\n" + "pcmpeqw (%2), %%mm3\n" + "pcmpeqw (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqw %%mm1, %%mm2\n" + "pcmpeqw %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpcklwd %%mm4, %%mm2\n" + "punpckhwd %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + /* next */ + "addl $8, %0\n" + "addl $8, %1\n" + "addl $8, %2\n" + "addl $16, %3\n" + +/* central runs */ + "shrl $2, %4\n" + "jz 1f\n" + + "0:\n" + + /* set the current, current_pre, current_next registers */ + "movq -8(%1), %%mm0\n" + "movq (%1), %%mm7\n" + "movq 8(%1), %%mm1\n" + "psrlq $48, %%mm0\n" + "psllq $48, %%mm1\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $16, %%mm2\n" + "psrlq $16, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqw %%mm6, %%mm2\n" + "pcmpeqw %%mm6, %%mm4\n" + "pcmpeqw (%2), %%mm3\n" + "pcmpeqw (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqw %%mm1, %%mm2\n" + "pcmpeqw %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpcklwd %%mm4, %%mm2\n" + "punpckhwd %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + /* next */ + "addl $8, %0\n" + "addl $8, %1\n" + "addl $8, %2\n" + "addl $16, %3\n" + + "decl %4\n" + "jnz 0b\n" + "1:\n" + +/* final run */ + /* set the current, current_pre, current_next registers */ + "movq (%1), %%mm1\n" + "movq (%1), %%mm7\n" + "movq -8(%1), %%mm0\n" + "psrlq $48, %%mm1\n" + "psrlq $48, %%mm0\n" + "psllq $48, %%mm1\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $16, %%mm2\n" + "psrlq $16, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqw %%mm6, %%mm2\n" + "pcmpeqw %%mm6, %%mm4\n" + "pcmpeqw (%2), %%mm3\n" + "pcmpeqw (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqw %%mm1, %%mm2\n" + "pcmpeqw %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpcklwd %%mm4, %%mm2\n" + "punpckhwd %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count) + : + : "cc" + ); +} + +static inline void scale2x_32_mmx_single(scale2x_uint32* dst, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) { + assert(count >= 4); + assert(count % 2 == 0); + + /* always do the first and last run */ + count -= 2 * 2; + + __asm__ __volatile__ ( +/* first run */ + /* set the current, current_pre, current_next registers */ + "movq 0(%1), %%mm0\n" + "movq 0(%1), %%mm7\n" + "movq 8(%1), %%mm1\n" + "psllq $32, %%mm0\n" + "psllq $32, %%mm1\n" + "psrlq $32, %%mm0\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $32, %%mm2\n" + "psrlq $32, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqd %%mm6, %%mm2\n" + "pcmpeqd %%mm6, %%mm4\n" + "pcmpeqd (%2), %%mm3\n" + "pcmpeqd (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqd %%mm1, %%mm2\n" + "pcmpeqd %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpckldq %%mm4, %%mm2\n" + "punpckhdq %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + /* next */ + "addl $8, %0\n" + "addl $8, %1\n" + "addl $8, %2\n" + "addl $16, %3\n" + +/* central runs */ + "shrl $1, %4\n" + "jz 1f\n" + + "0:\n" + + /* set the current, current_pre, current_next registers */ + "movq -8(%1), %%mm0\n" + "movq (%1), %%mm7\n" + "movq 8(%1), %%mm1\n" + "psrlq $32, %%mm0\n" + "psllq $32, %%mm1\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $32, %%mm2\n" + "psrlq $32, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqd %%mm6, %%mm2\n" + "pcmpeqd %%mm6, %%mm4\n" + "pcmpeqd (%2), %%mm3\n" + "pcmpeqd (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqd %%mm1, %%mm2\n" + "pcmpeqd %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpckldq %%mm4, %%mm2\n" + "punpckhdq %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + /* next */ + "addl $8, %0\n" + "addl $8, %1\n" + "addl $8, %2\n" + "addl $16, %3\n" + + "decl %4\n" + "jnz 0b\n" + "1:\n" + +/* final run */ + /* set the current, current_pre, current_next registers */ + "movq (%1), %%mm1\n" + "movq (%1), %%mm7\n" + "movq -8(%1), %%mm0\n" + "psrlq $32, %%mm1\n" + "psrlq $32, %%mm0\n" + "psllq $32, %%mm1\n" + "movq %%mm7, %%mm2\n" + "movq %%mm7, %%mm3\n" + "psllq $32, %%mm2\n" + "psrlq $32, %%mm3\n" + "por %%mm2, %%mm0\n" + "por %%mm3, %%mm1\n" + + /* current_upper */ + "movq (%0), %%mm6\n" + + /* compute the upper-left pixel for dst on %%mm2 */ + /* compute the upper-right pixel for dst on %%mm4 */ + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "movq %%mm0, %%mm3\n" + "movq %%mm1, %%mm5\n" + "pcmpeqd %%mm6, %%mm2\n" + "pcmpeqd %%mm6, %%mm4\n" + "pcmpeqd (%2), %%mm3\n" + "pcmpeqd (%2), %%mm5\n" + "pandn %%mm2, %%mm3\n" + "pandn %%mm4, %%mm5\n" + "movq %%mm0, %%mm2\n" + "movq %%mm1, %%mm4\n" + "pcmpeqd %%mm1, %%mm2\n" + "pcmpeqd %%mm0, %%mm4\n" + "pandn %%mm3, %%mm2\n" + "pandn %%mm5, %%mm4\n" + "movq %%mm2, %%mm3\n" + "movq %%mm4, %%mm5\n" + "pand %%mm6, %%mm2\n" + "pand %%mm6, %%mm4\n" + "pandn %%mm7, %%mm3\n" + "pandn %%mm7, %%mm5\n" + "por %%mm3, %%mm2\n" + "por %%mm5, %%mm4\n" + + /* set *dst */ + "movq %%mm2, %%mm3\n" + "punpckldq %%mm4, %%mm2\n" + "punpckhdq %%mm4, %%mm3\n" + "movq %%mm2, (%3)\n" + "movq %%mm3, 8(%3)\n" + + : "+r" (src0), "+r" (src1), "+r" (src2), "+r" (dst), "+r" (count) + : + : "cc" + ); +} + +/** + * Scale by a factor of 2 a row of pixels of 8 bits. + * This is a very fast MMX implementation. + * The implementation uses a combination of cmp/and/not operations to + * completly remove the need of conditional jumps. This trick give the + * major speed improvement. + * Also, using the 8 bytes MMX registers more than one pixel are computed + * at the same time. + * Before calling this function you must ensure that the currenct CPU supports + * the MMX instruction set. After calling it you must be sure to call the EMMS + * instruction before any floating-point operation. + * The pixels over the left and right borders are assumed of the same color of + * the pixels on the border. + * \param src0 Pointer at the first pixel of the previous row. + * \param src1 Pointer at the first pixel of the current row. + * \param src2 Pointer at the first pixel of the next row. + * \param count Length in pixels of the src0, src1 and src2 rows. It must + * be at least 16 and a multiple of 8. + * \param dst0 First destination row, double length in pixels. + * \param dst1 Second destination row, double length in pixels. + */ +void scale2x_8_mmx(scale2x_uint8* dst0, scale2x_uint8* dst1, const scale2x_uint8* src0, const scale2x_uint8* src1, const scale2x_uint8* src2, unsigned count) { + if (count % 8 != 0 || count < 16) { + scale2x_8_def(dst0, dst1, src0, src1, src2, count); + } else { + assert(count >= 16); + assert(count % 8 == 0); + + scale2x_8_mmx_single(dst0, src0, src1, src2, count); + scale2x_8_mmx_single(dst1, src2, src1, src0, count); + } +} + +/** + * Scale by a factor of 2 a row of pixels of 16 bits. + * This function operates like scale2x_8_mmx() but for 16 bits pixels. + * \param src0 Pointer at the first pixel of the previous row. + * \param src1 Pointer at the first pixel of the current row. + * \param src2 Pointer at the first pixel of the next row. + * \param count Length in pixels of the src0, src1 and src2 rows. It must + * be at least 8 and a multiple of 4. + * \param dst0 First destination row, double length in pixels. + * \param dst1 Second destination row, double length in pixels. + */ +void scale2x_16_mmx(scale2x_uint16* dst0, scale2x_uint16* dst1, const scale2x_uint16* src0, const scale2x_uint16* src1, const scale2x_uint16* src2, unsigned count) { + if (count % 4 != 0 || count < 8) { + scale2x_16_def(dst0, dst1, src0, src1, src2, count); + } else { + assert(count >= 8); + assert(count % 4 == 0); + + scale2x_16_mmx_single(dst0, src0, src1, src2, count); + scale2x_16_mmx_single(dst1, src2, src1, src0, count); + } +} + +/** + * Scale by a factor of 2 a row of pixels of 32 bits. + * This function operates like scale2x_8_mmx() but for 32 bits pixels. + * \param src0 Pointer at the first pixel of the previous row. + * \param src1 Pointer at the first pixel of the current row. + * \param src2 Pointer at the first pixel of the next row. + * \param count Length in pixels of the src0, src1 and src2 rows. It must + * be at least 4 and a multiple of 2. + * \param dst0 First destination row, double length in pixels. + * \param dst1 Second destination row, double length in pixels. + */ +void scale2x_32_mmx(scale2x_uint32* dst0, scale2x_uint32* dst1, const scale2x_uint32* src0, const scale2x_uint32* src1, const scale2x_uint32* src2, unsigned count) { + if (count % 2 != 0 || count < 4) { + scale2x_32_def(dst0, dst1, src0, src1, src2, count); + } else { + assert(count >= 4); + assert(count % 2 == 0); + + scale2x_32_mmx_single(dst0, src0, src1, src2, count); + scale2x_32_mmx_single(dst1, src2, src1, src0, count); + } +} + +#endif + diff --git a/src/drivers/common/scale2x.h b/src/drivers/common/scale2x.h new file mode 100644 index 0000000..cc92b0c --- /dev/null +++ b/src/drivers/common/scale2x.h @@ -0,0 +1,51 @@ +/* + * 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/src/drivers/common/scale3x.c b/src/drivers/common/scale3x.c new file mode 100644 index 0000000..e98fbb4 --- /dev/null +++ b/src/drivers/common/scale3x.c @@ -0,0 +1,373 @@ +/* + * 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 + +/***************************************************************************/ +/* 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/src/drivers/common/scale3x.h b/src/drivers/common/scale3x.h new file mode 100644 index 0000000..14655d0 --- /dev/null +++ b/src/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/src/drivers/common/scalebit.c b/src/drivers/common/scalebit.c new file mode 100644 index 0000000..6c49e19 --- /dev/null +++ b/src/drivers/common/scalebit.c @@ -0,0 +1,376 @@ +/* + * 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 +#endif + +#include "scale2x.h" +#include "scale3x.h" + +#if HAVE_ALLOCA_H +#include +#endif + +#include +#include + +/** + * 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/src/drivers/common/scalebit.h b/src/drivers/common/scalebit.h new file mode 100644 index 0000000..dd46883 --- /dev/null +++ b/src/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/src/drivers/common/vidblit.c b/src/drivers/common/vidblit.c new file mode 100644 index 0000000..4b92596 --- /dev/null +++ b/src/drivers/common/vidblit.c @@ -0,0 +1,726 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "scalebit.h" +#include "hq2x.h" +#include "hq3x.h" + +#include "../../fceu-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 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/src/drivers/common/vidblit.h b/src/drivers/common/vidblit.h new file mode 100644 index 0000000..d4d3005 --- /dev/null +++ b/src/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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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/src/drivers/libretro/jni/Android.mk b/src/drivers/libretro/jni/Android.mk new file mode 100644 index 0000000..3f0bf66 --- /dev/null +++ b/src/drivers/libretro/jni/Android.mk @@ -0,0 +1,21 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libretro +FCEU_SRC_DIRS := ../../../../src ../../../../src/boards ../../../../src/input ../../../../src/mappers + +FCEU_SRC_FILES := $(wildcard $(LOCAL_PATH)/../../../../src/*.c) \ + $(wildcard $(LOCAL_PATH)/../../../../src/boards/*.c) \ + $(wildcard $(LOCAL_PATH)/../../../../src/input/*.c) \ + $(wildcard $(LOCAL_PATH)/../../../../src/mappers/*.c) + +FCEU_SRC_FILES := $(FCEU_SRC_FILES:$(LOCAL_PATH)/%=%) + +LOCAL_SRC_FILES = ../libretro/libretro.c \ + ../libretro/memstream.c \ + $(FCEU_SRC_FILES) + +LOCAL_CFLAGS = -DINLINE=inline -DSOUND_QUALITY=0 -DPATH_MAX=1024 -DPSS_STYLE=1 -DLSB_FIRST -D__LIBRETRO__ -DHAVE_ASPRINTF + +include $(BUILD_SHARED_LIBRARY) diff --git a/src/drivers/libretro/libretro.c b/src/drivers/libretro/libretro.c new file mode 100644 index 0000000..357e730 --- /dev/null +++ b/src/drivers/libretro/libretro.c @@ -0,0 +1,590 @@ +#ifdef __LIBRETRO__ +#define GENERAL_LIBRETRO +#endif + +#include +#include +#include +#include + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif + +#include "libretro.h" + +#include "fceu.h" +#include "fceu-endian.h" +#include "input.h" +#include "state.h" +#include "ppu.h" +#include "cart.h" +#include "x6502.h" +#include "git.h" +#include "palette.h" +#include "sound.h" +#include "file.h" +#include "cheat.h" +#include "ines.h" +#include "unif.h" +#include "fds.h" + +#include +#include "memstream.h" + +static retro_video_refresh_t video_cb = NULL; +static retro_input_poll_t poll_cb = NULL; +static retro_input_state_t input_cb = NULL; +static retro_audio_sample_batch_t audio_batch_cb = NULL; +static retro_environment_t environ_cb = NULL; + +/* emulator-specific variables */ + +static uint16_t palette[256]; + +static int32 *sound = 0; +static uint32 JSReturn[2]; +static uint32 current_palette = 0; + +int PPUViewScanline = 0; +int PPUViewer = 0; +int UpdatePPUView = 0; + +/* extern forward decls.*/ +extern FCEUGI *GameInfo; +extern uint8 *XBuf; +extern CartInfo iNESCart; +extern CartInfo UNIFCart; + +/* emulator-specific callback functions */ + +const char * GetKeyboard(void) { + return ""; +} + +int FCEUD_SendData(void *data, uint32 len) { + return 1; +} + +void FCEUD_SetPalette(unsigned char index, unsigned char r, unsigned char g, unsigned char b) { + r >>= 3; + g >>= 3; + b >>= 3; + palette[index] = (r << 10) | (g << 5) | (b << 0); +} + +bool FCEUD_ShouldDrawInputAids(void) { + return 1; +} + +void FCEUD_PrintError(char *c) { +} + +void FCEUD_Message(char *s) { +} + +void FCEUD_NetworkClose(void) { +} + +void FCEUD_GetPalette(uint8 i, uint8 *r, uint8 *g, uint8 *b) { +} + +void FCEUD_SoundToggle(void) { + FCEUI_SetSoundVolume(100); +} + +void FCEUD_VideoChanged(void) { +} + +FILE *FCEUD_UTF8fopen(const char *n, const char *m) { + return fopen(n, m); +} + +#define MAX_PAH 1024 + +/*palette for FCEU*/ +#define MAXPAL 13 + +struct st_palettes { + char name[32]; + char desc[32]; + unsigned int data[64]; +}; + +struct st_palettes palettes[] = { + { "asqrealc", "AspiringSquire's Real palette", + { 0x6c6c6c, 0x00268e, 0x0000a8, 0x400094, + 0x700070, 0x780040, 0x700000, 0x621600, + 0x442400, 0x343400, 0x005000, 0x004444, + 0x004060, 0x000000, 0x101010, 0x101010, + 0xbababa, 0x205cdc, 0x3838ff, 0x8020f0, + 0xc000c0, 0xd01474, 0xd02020, 0xac4014, + 0x7c5400, 0x586400, 0x008800, 0x007468, + 0x00749c, 0x202020, 0x101010, 0x101010, + 0xffffff, 0x4ca0ff, 0x8888ff, 0xc06cff, + 0xff50ff, 0xff64b8, 0xff7878, 0xff9638, + 0xdbab00, 0xa2ca20, 0x4adc4a, 0x2ccca4, + 0x1cc2ea, 0x585858, 0x101010, 0x101010, + 0xffffff, 0xb0d4ff, 0xc4c4ff, 0xe8b8ff, + 0xffb0ff, 0xffb8e8, 0xffc4c4, 0xffd4a8, + 0xffe890, 0xf0f4a4, 0xc0ffc0, 0xacf4f0, + 0xa0e8ff, 0xc2c2c2, 0x202020, 0x101010 } }, + { "loopy", "Loopy's palette", + { 0x757575, 0x271b8f, 0x0000ab, 0x47009f, + 0x8f0077, 0xab0013, 0xa70000, 0x7f0b00, + 0x432f00, 0x004700, 0x005100, 0x003f17, + 0x1b3f5f, 0x000000, 0x000000, 0x000000, + 0xbcbcbc, 0x0073ef, 0x233bef, 0x8300f3, + 0xbf00bf, 0xe7005b, 0xdb2b00, 0xcb4f0f, + 0x8b7300, 0x009700, 0x00ab00, 0x00933b, + 0x00838b, 0x000000, 0x000000, 0x000000, + 0xffffff, 0x3fbfff, 0x5f97ff, 0xa78bfd, + 0xf77bff, 0xff77b7, 0xff7763, 0xff9b3b, + 0xf3bf3f, 0x83d313, 0x4fdf4b, 0x58f898, + 0x00ebdb, 0x000000, 0x000000, 0x000000, + 0xffffff, 0xabe7ff, 0xc7d7ff, 0xd7cbff, + 0xffc7ff, 0xffc7db, 0xffbfb3, 0xffdbab, + 0xffe7a3, 0xe3ffa3, 0xabf3bf, 0xb3ffcf, + 0x9ffff3, 0x000000, 0x000000, 0x000000 } }, + { "quor", "Quor's palette", + { 0x3f3f3f, 0x001f3f, 0x00003f, 0x1f003f, + 0x3f003f, 0x3f0020, 0x3f0000, 0x3f2000, + 0x3f3f00, 0x203f00, 0x003f00, 0x003f20, + 0x003f3f, 0x000000, 0x000000, 0x000000, + 0x7f7f7f, 0x405f7f, 0x40407f, 0x5f407f, + 0x7f407f, 0x7f4060, 0x7f4040, 0x7f6040, + 0x7f7f40, 0x607f40, 0x407f40, 0x407f60, + 0x407f7f, 0x000000, 0x000000, 0x000000, + 0xbfbfbf, 0x809fbf, 0x8080bf, 0x9f80bf, + 0xbf80bf, 0xbf80a0, 0xbf8080, 0xbfa080, + 0xbfbf80, 0xa0bf80, 0x80bf80, 0x80bfa0, + 0x80bfbf, 0x000000, 0x000000, 0x000000, + 0xffffff, 0xc0dfff, 0xc0c0ff, 0xdfc0ff, + 0xffc0ff, 0xffc0e0, 0xffc0c0, 0xffe0c0, + 0xffffc0, 0xe0ffc0, 0xc0ffc0, 0xc0ffe0, + 0xc0ffff, 0x000000, 0x000000, 0x000000 } }, + { "chris", "Chris Covell's palette", + { 0x808080, 0x003DA6, 0x0012B0, 0x440096, + 0xA1005E, 0xC70028, 0xBA0600, 0x8C1700, + 0x5C2F00, 0x104500, 0x054A00, 0x00472E, + 0x004166, 0x000000, 0x050505, 0x050505, + 0xC7C7C7, 0x0077FF, 0x2155FF, 0x8237FA, + 0xEB2FB5, 0xFF2950, 0xFF2200, 0xD63200, + 0xC46200, 0x358000, 0x058F00, 0x008A55, + 0x0099CC, 0x212121, 0x090909, 0x090909, + 0xFFFFFF, 0x0FD7FF, 0x69A2FF, 0xD480FF, + 0xFF45F3, 0xFF618B, 0xFF8833, 0xFF9C12, + 0xFABC20, 0x9FE30E, 0x2BF035, 0x0CF0A4, + 0x05FBFF, 0x5E5E5E, 0x0D0D0D, 0x0D0D0D, + 0xFFFFFF, 0xA6FCFF, 0xB3ECFF, 0xDAABEB, + 0xFFA8F9, 0xFFABB3, 0xFFD2B0, 0xFFEFA6, + 0xFFF79C, 0xD7E895, 0xA6EDAF, 0xA2F2DA, + 0x99FFFC, 0xDDDDDD, 0x111111, 0x111111 } }, + { "matt", "Matthew Conte's palette", + { 0x808080, 0x0000bb, 0x3700bf, 0x8400a6, + 0xbb006a, 0xb7001e, 0xb30000, 0x912600, + 0x7b2b00, 0x003e00, 0x00480d, 0x003c22, + 0x002f66, 0x000000, 0x050505, 0x050505, + 0xc8c8c8, 0x0059ff, 0x443cff, 0xb733cc, + 0xff33aa, 0xff375e, 0xff371a, 0xd54b00, + 0xc46200, 0x3c7b00, 0x1e8415, 0x009566, + 0x0084c4, 0x111111, 0x090909, 0x090909, + 0xffffff, 0x0095ff, 0x6f84ff, 0xd56fff, + 0xff77cc, 0xff6f99, 0xff7b59, 0xff915f, + 0xffa233, 0xa6bf00, 0x51d96a, 0x4dd5ae, + 0x00d9ff, 0x666666, 0x0d0d0d, 0x0d0d0d, + 0xffffff, 0x84bfff, 0xbbbbff, 0xd0bbff, + 0xffbfea, 0xffbfcc, 0xffc4b7, 0xffccae, + 0xffd9a2, 0xcce199, 0xaeeeb7, 0xaaf7ee, + 0xb3eeff, 0xdddddd, 0x111111, 0x111111 } }, + { "pasofami", "PasoFami/99 palette", + { 0x7f7f7f, 0x0000ff, 0x0000bf, 0x472bbf, + 0x970087, 0xab0023, 0xab1300, 0x8b1700, + 0x533000, 0x007800, 0x006b00, 0x005b00, + 0x004358, 0x000000, 0x000000, 0x000000, + 0xbfbfbf, 0x0078f8, 0x0058f8, 0x6b47ff, + 0xdb00cd, 0xe7005b, 0xf83800, 0xe75f13, + 0xaf7f00, 0x00b800, 0x00ab00, 0x00ab47, + 0x008b8b, 0x000000, 0x000000, 0x000000, + 0xf8f8f8, 0x3fbfff, 0x6b88ff, 0x9878f8, + 0xf878f8, 0xf85898, 0xf87858, 0xffa347, + 0xf8b800, 0xb8f818, 0x5bdb57, 0x58f898, + 0x00ebdb, 0x787878, 0x000000, 0x000000, + 0xffffff, 0xa7e7ff, 0xb8b8f8, 0xd8b8f8, + 0xf8b8f8, 0xfba7c3, 0xf0d0b0, 0xffe3ab, + 0xfbdb7b, 0xd8f878, 0xb8f8b8, 0xb8f8d8, + 0x00ffff, 0xf8d8f8, 0x000000, 0x000000 } }, + { "crashman", "CrashMan's palette", + { 0x585858, 0x001173, 0x000062, 0x472bbf, + 0x970087, 0x910009, 0x6f1100, 0x4c1008, + 0x371e00, 0x002f00, 0x005500, 0x004d15, + 0x002840, 0x000000, 0x000000, 0x000000, + 0xa0a0a0, 0x004499, 0x2c2cc8, 0x590daa, + 0xae006a, 0xb00040, 0xb83418, 0x983010, + 0x704000, 0x308000, 0x207808, 0x007b33, + 0x1c6888, 0x000000, 0x000000, 0x000000, + 0xf8f8f8, 0x267be1, 0x5870f0, 0x9878f8, + 0xff73c8, 0xf060a8, 0xd07b37, 0xe09040, + 0xf8b300, 0x8cbc00, 0x40a858, 0x58f898, + 0x00b7bf, 0x787878, 0x000000, 0x000000, + 0xffffff, 0xa7e7ff, 0xb8b8f8, 0xd8b8f8, + 0xe6a6ff, 0xf29dc4, 0xf0c0b0, 0xfce4b0, + 0xe0e01e, 0xd8f878, 0xc0e890, 0x95f7c8, + 0x98e0e8, 0xf8d8f8, 0x000000, 0x000000 } }, + { "mess", "MESS palette", + { 0x747474, 0x24188c, 0x0000a8, 0x44009c, + 0x8c0074, 0xa80010, 0xa40000, 0x7c0800, + 0x402c00, 0x004400, 0x005000, 0x003c14, + 0x183c5c, 0x000000, 0x000000, 0x000000, + 0xbcbcbc, 0x0070ec, 0x2038ec, 0x8000f0, + 0xbc00bc, 0xe40058, 0xd82800, 0xc84c0c, + 0x887000, 0x009400, 0x00a800, 0x009038, + 0x008088, 0x000000, 0x000000, 0x000000, + 0xfcfcfc, 0x3cbcfc, 0x5c94fc, 0x4088fc, + 0xf478fc, 0xfc74b4, 0xfc7460, 0xfc9838, + 0xf0bc3c, 0x80d010, 0x4cdc48, 0x58f898, + 0x00e8d8, 0x000000, 0x000000, 0x000000, + 0xfcfcfc, 0xa8e4fc, 0xc4d4fc, 0xd4c8fc, + 0xfcc4fc, 0xfcc4d8, 0xfcbcb0, 0xfcd8a8, + 0xfce4a0, 0xe0fca0, 0xa8f0bc, 0xb0fccc, + 0x9cfcf0, 0x000000, 0x000000, 0x000000 } }, + { "zaphod-cv", "Zaphod's VS Castlevania palette", + { 0x7f7f7f, 0xffa347, 0x0000bf, 0x472bbf, + 0x970087, 0xf85898, 0xab1300, 0xf8b8f8, + 0xbf0000, 0x007800, 0x006b00, 0x005b00, + 0xffffff, 0x9878f8, 0x000000, 0x000000, + 0xbfbfbf, 0x0078f8, 0xab1300, 0x6b47ff, + 0x00ae00, 0xe7005b, 0xf83800, 0x7777ff, + 0xaf7f00, 0x00b800, 0x00ab00, 0x00ab47, + 0x008b8b, 0x000000, 0x000000, 0x472bbf, + 0xf8f8f8, 0xffe3ab, 0xf87858, 0x9878f8, + 0x0078f8, 0xf85898, 0xbfbfbf, 0xffa347, + 0xc800c8, 0xb8f818, 0x7f7f7f, 0x007800, + 0x00ebdb, 0x000000, 0x000000, 0xffffff, + 0xffffff, 0xa7e7ff, 0x5bdb57, 0xe75f13, + 0x004358, 0x0000ff, 0xe7005b, 0x00b800, + 0xfbdb7b, 0xd8f878, 0x8b1700, 0xffe3ab, + 0x00ffff, 0xab0023, 0x000000, 0x000000 } }, + { "zaphod-smb", "Zaphod's VS SMB palette", + { 0x626a00, 0x0000ff, 0x006a77, 0x472bbf, + 0x970087, 0xab0023, 0xab1300, 0xb74800, + 0xa2a2a2, 0x007800, 0x006b00, 0x005b00, + 0xffd599, 0xffff00, 0x009900, 0x000000, + 0xff66ff, 0x0078f8, 0x0058f8, 0x6b47ff, + 0x000000, 0xe7005b, 0xf83800, 0xe75f13, + 0xaf7f00, 0x00b800, 0x5173ff, 0x00ab47, + 0x008b8b, 0x000000, 0x91ff88, 0x000088, + 0xf8f8f8, 0x3fbfff, 0x6b0000, 0x4855f8, + 0xf878f8, 0xf85898, 0x595958, 0xff009d, + 0x002f2f, 0xb8f818, 0x5bdb57, 0x58f898, + 0x00ebdb, 0x787878, 0x000000, 0x000000, + 0xffffff, 0xa7e7ff, 0x590400, 0xbb0000, + 0xf8b8f8, 0xfba7c3, 0xffffff, 0x00e3e1, + 0xfbdb7b, 0xffae00, 0xb8f8b8, 0xb8f8d8, + 0x00ff00, 0xf8d8f8, 0xffaaaa, 0x004000 } }, + { "vs-drmar", "VS Dr. Mario palette", + { 0x5f97ff, 0x000000, 0x000000, 0x47009f, + 0x00ab00, 0xffffff, 0xabe7ff, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0xe7005b, 0x000000, 0x000000, 0x000000, + 0x5f97ff, 0x000000, 0x000000, 0x000000, + 0x000000, 0x8b7300, 0xcb4f0f, 0x000000, + 0xbcbcbc, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x00ebdb, 0x000000, 0x000000, 0x000000, + 0x000000, 0xff9b3b, 0x000000, 0x000000, + 0x83d313, 0x000000, 0x3fbfff, 0x000000, + 0x0073ef, 0x000000, 0x000000, 0x000000, + 0x00ebdb, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0xf3bf3f, 0x000000, + 0x005100, 0x000000, 0xc7d7ff, 0xffdbab, + 0x000000, 0x000000, 0x000000, 0x000000 } }, + { "vs-cv", "VS Castlevania palette", + { 0xaf7f00, 0xffa347, 0x008b8b, 0x472bbf, + 0x970087, 0xf85898, 0xab1300, 0xf8b8f8, + 0xf83800, 0x007800, 0x006b00, 0x005b00, + 0xffffff, 0x9878f8, 0x00ab00, 0x000000, + 0xbfbfbf, 0x0078f8, 0xab1300, 0x6b47ff, + 0x000000, 0xe7005b, 0xf83800, 0x6b88ff, + 0xaf7f00, 0x00b800, 0x6b88ff, 0x00ab47, + 0x008b8b, 0x000000, 0x000000, 0x472bbf, + 0xf8f8f8, 0xffe3ab, 0xf87858, 0x9878f8, + 0x0078f8, 0xf85898, 0xbfbfbf, 0xffa347, + 0x004358, 0xb8f818, 0x7f7f7f, 0x007800, + 0x00ebdb, 0x000000, 0x000000, 0xffffff, + 0xffffff, 0xa7e7ff, 0x5bdb57, 0x6b88ff, + 0x004358, 0x0000ff, 0xe7005b, 0x00b800, + 0xfbdb7b, 0xffa347, 0x8b1700, 0xffe3ab, + 0xb8f818, 0xab0023, 0x000000, 0x007800 } }, + { "vs-smb", "VS SMB/VS Ice Climber palette", + { 0xaf7f00, 0x0000ff, 0x008b8b, 0x472bbf, + 0x970087, 0xab0023, 0x0000ff, 0xe75f13, + 0xbfbfbf, 0x007800, 0x5bdb57, 0x005b00, + 0xf0d0b0, 0xffe3ab, 0x00ab00, 0x000000, + 0xbfbfbf, 0x0078f8, 0x0058f8, 0x6b47ff, + 0x000000, 0xe7005b, 0xf83800, 0xf87858, + 0xaf7f00, 0x00b800, 0x6b88ff, 0x00ab47, + 0x008b8b, 0x000000, 0x000000, 0x3fbfff, + 0xf8f8f8, 0x006b00, 0x8b1700, 0x9878f8, + 0x6b47ff, 0xf85898, 0x7f7f7f, 0xe7005b, + 0x004358, 0xb8f818, 0x0078f8, 0x58f898, + 0x00ebdb, 0xfbdb7b, 0x000000, 0x000000, + 0xffffff, 0xa7e7ff, 0xb8b8f8, 0xf83800, + 0xf8b8f8, 0xfba7c3, 0xffffff, 0x00ffff, + 0xfbdb7b, 0xffa347, 0xb8f8b8, 0xb8f8d8, + 0xb8f818, 0xf8d8f8, 0x000000, 0x007800 } } +}; + +unsigned retro_api_version(void) { + return RETRO_API_VERSION; +} + +void retro_set_video_refresh(retro_video_refresh_t cb) { + video_cb = cb; +} + +void retro_set_audio_sample(retro_audio_sample_t cb) { +} + +void retro_set_audio_sample_batch(retro_audio_sample_batch_t cb) { + audio_batch_cb = cb; +} + +void retro_set_input_poll(retro_input_poll_t cb) { + poll_cb = cb; +} + +void retro_set_input_state(retro_input_state_t cb) { + input_cb = cb; +} + +void retro_set_controller_port_device(unsigned a, unsigned b) { +} + + +void retro_set_environment(retro_environment_t cb) { + environ_cb = cb; +} + +void retro_get_system_info(struct retro_system_info *info) { + info->need_fullpath = true; + info->valid_extensions = "fds|FDS|zip|ZIP|nes|NES|unif|UNIF"; + info->library_version = "r88 (SVN)"; + info->library_name = "FCEUmm"; + info->block_extract = false; +} + +void retro_get_system_av_info(struct retro_system_av_info *info) { + info->geometry.base_width = 256; + info->geometry.base_height = 240; + info->geometry.max_width = 256; + info->geometry.max_height = 240; + info->timing.sample_rate = 32050.0; + if (FSettings.PAL) + info->timing.fps = 838977920.0 / 16777215.0; + else + info->timing.fps = 1008307711.0 / 16777215.0; + info->timing.sample_rate = 32040.5; +} + +void retro_init(void) { + PowerNES(); +} + +static void emulator_set_input(void) { + // ?!?!?!?! Why does this matter?! +#if defined(__CELLOS_LV2__) || defined(_XBOX) || defined(GEKKO) // <-- big endian + FCEUI_SetInput(0, SI_GAMEPAD, &JSReturn[0], 0); + FCEUI_SetInput(1, SI_GAMEPAD, &JSReturn[0], 0); +#else + FCEUI_SetInput(0, SI_GAMEPAD, &JSReturn[0], 0); + FCEUI_SetInput(1, SI_GAMEPAD, &JSReturn[1], 0); +#endif +} + +static void emulator_set_custom_palette(void) { + if (current_palette == 0) { + FCEU_ResetPalette(); /* Do palette reset*/ + } else { + /* Now setup this palette*/ + uint8 i, r, g, b; + + for (i = 0; i < 64; i++) { + r = palettes[current_palette - 1].data[i] >> 16; + g = (palettes[current_palette - 1].data[i] & 0xff00) >> 8; + b = (palettes[current_palette - 1].data[i] & 0xff); + FCEUD_SetPalette(i, r, g, b); + FCEUD_SetPalette(i + 64, r, g, b); + FCEUD_SetPalette(i + 128, r, g, b); + FCEUD_SetPalette(i + 192, r, g, b); + } + } +} + +static void fceu_init(const char * full_path) { + FCEUI_Initialize(); + + FCEUI_SetSoundVolume(256); + FCEUI_Sound(32050); + + GameInfo = FCEUI_LoadGame(full_path); + emulator_set_input(); + emulator_set_custom_palette(); + + FCEUD_SoundToggle(); +} + +void retro_deinit(void) { +} + +void retro_reset(void) { + ResetNES(); +} + + +typedef struct { + unsigned retro; + unsigned nes; +} keymap; + +static const keymap bindmap[] = { + { RETRO_DEVICE_ID_JOYPAD_A, JOY_A }, + { RETRO_DEVICE_ID_JOYPAD_B, JOY_B }, + { RETRO_DEVICE_ID_JOYPAD_SELECT, JOY_SELECT }, + { RETRO_DEVICE_ID_JOYPAD_START, JOY_START }, + { RETRO_DEVICE_ID_JOYPAD_UP, JOY_UP }, + { RETRO_DEVICE_ID_JOYPAD_DOWN, JOY_DOWN }, + { RETRO_DEVICE_ID_JOYPAD_LEFT, JOY_LEFT }, + { RETRO_DEVICE_ID_JOYPAD_RIGHT, JOY_RIGHT }, +}; + +static void update_input(void) { + unsigned i; + unsigned char pad[2]; + + pad[0] = 0; + pad[1] = 0; + + poll_cb(); + + for (i = 0; i < 8; i++) { + pad[0] |= input_cb(0, RETRO_DEVICE_JOYPAD, 0, bindmap[i].retro) ? bindmap[i].nes : 0; + pad[1] |= input_cb(1, RETRO_DEVICE_JOYPAD, 0, bindmap[i].retro) ? bindmap[i].nes : 0; + } + + // This shouldn't matter. Why? Something very weird is going on. +#if defined(__CELLOS_LV2__) || defined(_XBOX360) || defined(GEKKO) // <-- big endian + JSReturn[0] = pad[0] | (pad[1] << 8); +#else + JSReturn[0] = pad[0]; + JSReturn[1] = pad[1]; +#endif +} + +void retro_run(void) { + unsigned y, x; + uint8_t *gfx; + static uint16_t video_out[256 * 240]; + int32 ssize = 0; + + update_input(); + + FCEUI_Emulate(&gfx, &sound, &ssize, 0); + + gfx = XBuf; + for (y = 0; y < 240; y++) + for (x = 0; x < 256; x++, gfx++) + video_out[y * 256 + x] = palette[*gfx]; + + video_cb(video_out, 256, 240, 512); + + for (y = 0; y < ssize; y++) + sound[y] = (sound[y] << 16) | (sound[y] & 0xffff); + + audio_batch_cb((const int16_t*)sound, ssize); +} + +static unsigned serialize_size = 0; + +size_t retro_serialize_size(void) { + if (serialize_size == 0) { + /* Something arbitrarily big.*/ + uint8_t *buffer = (uint8_t*)malloc(1000000); + memstream_set_buffer(buffer, 1000000); + + FCEUSS_Save(""); + serialize_size = memstream_get_last_size(); + free(buffer); + } + + return serialize_size; +} + +bool retro_serialize(void *data, size_t size) { + if (size != retro_serialize_size()) + return FALSE; + + memstream_set_buffer((uint8_t*)data, size); + FCEUSS_Save(""); + return TRUE; +} + +bool retro_unserialize(const void * data, size_t size) { + if (size != retro_serialize_size()) + return FALSE; + + memstream_set_buffer((uint8_t*)data, size); + FCEUSS_Load(""); + return TRUE; +} + +void retro_cheat_reset(void) { +} + +void retro_cheat_set(unsigned a, bool b, const char* c) { +} + +bool retro_load_game(const struct retro_game_info *game) { + fceu_init(game->path); + + return TRUE; +} + +bool retro_load_game_special( + unsigned game_type, + const struct retro_game_info *info, size_t num_info + ) { + return false; +} + +void retro_unload_game(void) { + FCEUI_CloseGame(); +} + +unsigned retro_get_region(void) { + return FSettings.PAL ? RETRO_REGION_PAL : RETRO_REGION_NTSC; +} + +void *retro_get_memory_data(unsigned id) { + if (id != RETRO_MEMORY_SAVE_RAM) + return NULL; + + if (iNESCart.battery) + return iNESCart.SaveGame[0]; + if (UNIFCart.battery) + return UNIFCart.SaveGame[0]; + + return 0; +} + +size_t retro_get_memory_size(unsigned id) { + if (id != RETRO_MEMORY_SAVE_RAM) + return 0; + + if (iNESCart.battery) + return iNESCart.SaveGameLen[0]; + if (UNIFCart.battery) + return UNIFCart.SaveGameLen[0]; + + return 0; +} diff --git a/src/drivers/libretro/libretro.h b/src/drivers/libretro/libretro.h new file mode 100644 index 0000000..b7f3981 --- /dev/null +++ b/src/drivers/libretro/libretro.h @@ -0,0 +1,223 @@ +#ifndef LIBRETRO_H__ +#define LIBRETRO_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#elif defined(_MSC_VER) +#define false 0 +#define true 1 +typedef unsigned char bool; +#else +#include +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#define RETRO_API_VERSION 1 + +#define RETRO_DEVICE_MASK 0xff +#define RETRO_DEVICE_NONE 0 +#define RETRO_DEVICE_JOYPAD 1 +#define RETRO_DEVICE_MOUSE 2 +#define RETRO_DEVICE_KEYBOARD 3 +#define RETRO_DEVICE_LIGHTGUN 4 + +#define RETRO_DEVICE_JOYPAD_MULTITAP ((1 << 8) | RETRO_DEVICE_JOYPAD) +#define RETRO_DEVICE_LIGHTGUN_SUPER_SCOPE ((1 << 8) | RETRO_DEVICE_LIGHTGUN) +#define RETRO_DEVICE_LIGHTGUN_JUSTIFIER ((2 << 8) | RETRO_DEVICE_LIGHTGUN) +#define RETRO_DEVICE_LIGHTGUN_JUSTIFIERS ((3 << 8) | RETRO_DEVICE_LIGHTGUN) + +#define RETRO_DEVICE_ID_JOYPAD_B 0 +#define RETRO_DEVICE_ID_JOYPAD_Y 1 +#define RETRO_DEVICE_ID_JOYPAD_SELECT 2 +#define RETRO_DEVICE_ID_JOYPAD_START 3 +#define RETRO_DEVICE_ID_JOYPAD_UP 4 +#define RETRO_DEVICE_ID_JOYPAD_DOWN 5 +#define RETRO_DEVICE_ID_JOYPAD_LEFT 6 +#define RETRO_DEVICE_ID_JOYPAD_RIGHT 7 +#define RETRO_DEVICE_ID_JOYPAD_A 8 +#define RETRO_DEVICE_ID_JOYPAD_X 9 +#define RETRO_DEVICE_ID_JOYPAD_L 10 +#define RETRO_DEVICE_ID_JOYPAD_R 11 + +#define RETRO_DEVICE_ID_MOUSE_X 0 +#define RETRO_DEVICE_ID_MOUSE_Y 1 +#define RETRO_DEVICE_ID_MOUSE_LEFT 2 +#define RETRO_DEVICE_ID_MOUSE_RIGHT 3 + +#define RETRO_DEVICE_ID_LIGHTGUN_X 0 +#define RETRO_DEVICE_ID_LIGHTGUN_Y 1 +#define RETRO_DEVICE_ID_LIGHTGUN_TRIGGER 2 +#define RETRO_DEVICE_ID_LIGHTGUN_CURSOR 3 +#define RETRO_DEVICE_ID_LIGHTGUN_TURBO 4 +#define RETRO_DEVICE_ID_LIGHTGUN_PAUSE 5 +#define RETRO_DEVICE_ID_LIGHTGUN_START 6 + +#define RETRO_REGION_NTSC 0 +#define RETRO_REGION_PAL 1 + +#define RETRO_MEMORY_MASK 0xff +#define RETRO_MEMORY_SAVE_RAM 0 +#define RETRO_MEMORY_RTC 1 +#define RETRO_MEMORY_SYSTEM_RAM 2 + +#define RETRO_MEMORY_SNES_BSX_RAM ((1 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_BSX_PRAM ((2 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_SUFAMI_TURBO_A_RAM ((3 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_SUFAMI_TURBO_B_RAM ((4 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_GAME_BOY_RAM ((5 << 8) | RETRO_MEMORY_SAVE_RAM) +#define RETRO_MEMORY_SNES_GAME_BOY_RTC ((6 << 8) | RETRO_MEMORY_RTC) + +#define RETRO_GAME_TYPE_BSX 0x101 +#define RETRO_GAME_TYPE_BSX_SLOTTED 0x102 +#define RETRO_GAME_TYPE_SUFAMI_TURBO 0x103 +#define RETRO_GAME_TYPE_SUPER_GAME_BOY 0x104 + + +// Environment commands. +#define RETRO_ENVIRONMENT_SET_ROTATION 1 // const unsigned * -- + // Sets screen rotation of graphics. + // Is only implemented if rotation can be accelerated by hardware. + // Valid values are 0, 1, 2, 3, which rotates screen by 0, 90, 180, 270 degrees + // counter-clockwise respectively. + // +#define RETRO_ENVIRONMENT_GET_OVERSCAN 2 // bool * -- + // Boolean value whether or not the implementation should use overscan, or crop away overscan. + // +#define RETRO_ENVIRONMENT_GET_CAN_DUPE 3 // bool * -- + // Boolean value whether or not SSNES supports frame duping, + // passing NULL to video frame callback. + // +#define RETRO_ENVIRONMENT_GET_VARIABLE 4 // struct retro_variable * -- + // Interface to aquire user-defined information from environment + // that cannot feasibly be supported in a multi-system way. + // Mostly used for obscure, + // specific features that the user can tap into when neseccary. + // +#define RETRO_ENVIRONMENT_SET_VARIABLES 5 // const struct retro_variable * -- + // Allows an implementation to signal the environment + // which variables it might want to check for later using GET_VARIABLE. + // 'data' points to an array of retro_variable structs terminated by a { NULL, NULL } element. + // retro_variable::value should contain a human readable description of the key. + // +#define RETRO_ENVIRONMENT_SET_MESSAGE 6 // const struct retro_message * -- + // Sets a message to be displayed in implementation-specific manner for a certain amount of 'frames'. + +struct retro_message { + const char *msg; + unsigned frames; +}; + +struct retro_system_info { + const char *library_name; + const char *library_version; + const char *valid_extensions; + bool need_fullpath; + bool block_extract; +}; + +struct retro_game_geometry { + unsigned base_width; // Nominal video width of game. + unsigned base_height; // Nominal video height of game. + unsigned max_width; // Maximum possible width of game. + unsigned max_height; // Maximum possible height of game. + + float aspect_ratio; // Nominal aspect ratio of game. If aspect_ratio is <= 0.0, + // an aspect ratio of base_width / base_height is assumed. + // A frontend could override this setting if desired. +}; + +struct retro_system_timing { + double fps; // FPS of video content. + double sample_rate; // Sampling rate of audio. +}; + +struct retro_system_av_info { + struct retro_game_geometry geometry; + struct retro_system_timing timing; +}; + +struct retro_variable { + const char *key; // Variable to query in RETRO_ENVIRONMENT_GET_VARIABLE. + // If NULL, obtains the complete environment string if more complex parsing is necessary. + // The environment string is formatted as key-value pairs delimited by semicolons as so: + // "key1=value1;key2=value2;..." + const char *value; // Value to be obtained. If key does not exist, it is set to NULL. +}; + +struct retro_game_info { + const char *path; // Path to game, UTF-8 encoded. Usually used as a reference. + // May be NULL if rom was loaded from stdin or similar. + // SET_NEED_FULLPATH path guaranteed that this path is valid. + const void *data; // Memory buffer of loaded game. + // If the game is too big to load in one go. + // SET_NEED_FULLPATH should be used. + // In this case, data and size will be 0, + // and game can be loaded from path. + size_t size; // Size of memory buffer. + const char *meta; // String of implementation specific meta-data. +}; + +typedef bool (*retro_environment_t)(unsigned cmd, void *data); +typedef void (*retro_video_refresh_t)(const void *data, unsigned width, unsigned height, size_t pitch); +typedef void (*retro_audio_sample_t)(int16_t left, int16_t right); +typedef size_t (*retro_audio_sample_batch_t)(const int16_t *data, size_t frames); + +typedef void (*retro_input_poll_t)(void); +typedef int16_t (*retro_input_state_t)(unsigned port, unsigned device, unsigned index, unsigned id); + +void retro_init(void); +void retro_deinit(void); + +unsigned retro_api_version(void); + +void retro_get_system_info(struct retro_system_info *info); +void retro_get_system_av_info(struct retro_system_av_info *info); + +void retro_set_environment(retro_environment_t); +void retro_set_video_refresh(retro_video_refresh_t); +void retro_set_audio_sample(retro_audio_sample_t); +void retro_set_audio_sample_batch(retro_audio_sample_batch_t); +void retro_set_input_poll(retro_input_poll_t); +void retro_set_input_state(retro_input_state_t); + +void retro_set_controller_port_device(unsigned port, unsigned device); + +void retro_reset(void); +void retro_run(void); + +size_t retro_serialize_size(void); +bool retro_serialize(void *data, size_t size); +bool retro_unserialize(const void *data, size_t size); + +void retro_cheat_reset(void); +void retro_cheat_set(unsigned index, bool enabled, const char *code); + +bool retro_load_game(const struct retro_game_info *game); + +bool retro_load_game_special( + unsigned game_type, + const struct retro_game_info *info, size_t num_info + ); + +void retro_unload_game(void); + +unsigned retro_get_region(void); + +void *retro_get_memory_data(unsigned id); +size_t retro_get_memory_size(unsigned id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/drivers/libretro/link.T b/src/drivers/libretro/link.T new file mode 100644 index 0000000..b0c262d --- /dev/null +++ b/src/drivers/libretro/link.T @@ -0,0 +1,5 @@ +{ + global: retro_*; + local: *; +}; + diff --git a/src/drivers/libretro/memstream.c b/src/drivers/libretro/memstream.c new file mode 100644 index 0000000..b9e48a2 --- /dev/null +++ b/src/drivers/libretro/memstream.c @@ -0,0 +1,118 @@ +#include +#include +#include +#include +#include +#include "memstream.h" + +static uint8_t *g_buffer = NULL; +static size_t g_size = 0; +static size_t g_last_file_size = 0; + +struct memstream { + uint8_t *m_buf; + size_t m_size; + size_t m_ptr; + size_t m_max_ptr; + bool writing; +}; + +static void memstream_update_ptr(memstream_t *stream) { + if (stream->m_ptr > stream->m_max_ptr) + stream->m_max_ptr = stream->m_ptr; +} + +static void memstream_init(memstream_t *stream, uint8_t *buffer, size_t max_size, bool writing) { + stream->m_buf = buffer; + stream->m_size = max_size; + stream->m_ptr = 0; + stream->m_max_ptr = 0; + stream->writing = writing; +} + +void memstream_set_buffer(uint8_t *buffer, size_t size) { + g_buffer = buffer; + g_size = size; +} + +size_t memstream_get_last_size(void) { + return g_last_file_size; +} + +memstream_t *memstream_open(bool writing) { + memstream_t *stream; + if (!g_buffer || !g_size) + return NULL; + + stream = (memstream_t*)calloc(1, sizeof(*stream)); + memstream_init(stream, g_buffer, g_size, writing); + g_buffer = NULL; + g_size = 0; + return stream; +} + +void memstream_close(memstream_t *stream) { + g_last_file_size = stream->writing ? stream->m_max_ptr : stream->m_size; + free(stream); +} + +size_t memstream_read(memstream_t *stream, void *data, size_t bytes) { + size_t avail = stream->m_size - stream->m_ptr; + if (bytes > avail) + bytes = avail; + + memcpy(data, stream->m_buf + stream->m_ptr, bytes); + stream->m_ptr += bytes; + memstream_update_ptr(stream); + return bytes; +} + +size_t memstream_write(memstream_t *stream, const void *data, size_t bytes) { + size_t avail = stream->m_size - stream->m_ptr; + if (bytes > avail) + bytes = avail; + + memcpy(stream->m_buf + stream->m_ptr, data, bytes); + stream->m_ptr += bytes; + memstream_update_ptr(stream); + return bytes; +} + +int memstream_seek(memstream_t *stream, int offset, int whence) { + size_t ptr; + if (whence == SEEK_SET) + ptr = offset; + else if (whence == SEEK_CUR) + ptr = stream->m_ptr + offset; + else if (whence == SEEK_END) + ptr = (stream->writing ? stream->m_max_ptr : stream->m_size) + offset; + else + return -1; + + if (ptr <= stream->m_size) { + stream->m_ptr = ptr; + return 0; + } else + return -1; +} + +size_t memstream_pos(memstream_t *stream) { + return stream->m_ptr; +} + +int memstream_getc(memstream_t *stream) { + if (stream->m_ptr >= stream->m_size) + return EOF; + else + return stream->m_buf[stream->m_ptr++]; + + memstream_update_ptr(stream); +} + +void memstream_putc(memstream_t *stream, int c) { + if (stream->m_ptr < stream->m_size) + stream->m_buf[stream->m_ptr++] = c; + + memstream_update_ptr(stream); +} + diff --git a/src/drivers/libretro/memstream.h b/src/drivers/libretro/memstream.h new file mode 100644 index 0000000..de5424d --- /dev/null +++ b/src/drivers/libretro/memstream.h @@ -0,0 +1,30 @@ +#ifndef __MEMSTREAM_H +#define __MEMSTREAM_H + +#include +#include +#ifndef _MSC_VER +#include +#else +#define TRUE 1 +#define FALSE 0 +typedef unsigned char bool; +#endif + +typedef struct memstream memstream_t; + +memstream_t *memstream_open(bool writing); +void memstream_close(memstream_t *stream); + +size_t memstream_read(memstream_t *stream, void *data, size_t bytes); +size_t memstream_write(memstream_t *stream, const void *data, size_t bytes); +int memstream_getc(memstream_t *stream); +void memstream_putc(memstream_t *stream, int c); +char *memstream_gets(memstream_t *stream, char *buffer, size_t len); +size_t memstream_pos(memstream_t *stream); +int memstream_seek(memstream_t *stream, int offset, int whence); + +void memstream_set_buffer(uint8_t *buffer, size_t size); +size_t memstream_get_last_size(void); + +#endif diff --git a/src/drivers/libretro/msvc/msvc-2003-xbox1.sln b/src/drivers/libretro/msvc/msvc-2003-xbox1.sln new file mode 100644 index 0000000..4572323 --- /dev/null +++ b/src/drivers/libretro/msvc/msvc-2003-xbox1.sln @@ -0,0 +1,30 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msvc-2003-xbox1", "msvc-2003-xbox1/msvc-2003-xbox1.vcproj", "{14FEE388-B695-43E7-B8F4-BB463525D678}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Profile = Profile + Profile_FastCap = Profile_FastCap + Release = Release + Release_LTCG = Release_LTCG + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {14FEE388-B695-43E7-B8F4-BB463525D678}.Debug.ActiveCfg = Debug|Xbox + {14FEE388-B695-43E7-B8F4-BB463525D678}.Debug.Build.0 = Debug|Xbox + {14FEE388-B695-43E7-B8F4-BB463525D678}.Profile.ActiveCfg = Profile|Xbox + {14FEE388-B695-43E7-B8F4-BB463525D678}.Profile.Build.0 = Profile|Xbox + {14FEE388-B695-43E7-B8F4-BB463525D678}.Profile_FastCap.ActiveCfg = Profile_FastCap|Xbox + {14FEE388-B695-43E7-B8F4-BB463525D678}.Profile_FastCap.Build.0 = Profile_FastCap|Xbox + {14FEE388-B695-43E7-B8F4-BB463525D678}.Release.ActiveCfg = Release|Xbox + {14FEE388-B695-43E7-B8F4-BB463525D678}.Release.Build.0 = Release|Xbox + {14FEE388-B695-43E7-B8F4-BB463525D678}.Release_LTCG.ActiveCfg = Release_LTCG|Xbox + {14FEE388-B695-43E7-B8F4-BB463525D678}.Release_LTCG.Build.0 = Release_LTCG|Xbox + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/src/drivers/libretro/msvc/msvc-2003-xbox1/msvc-2003-xbox1.vcproj b/src/drivers/libretro/msvc/msvc-2003-xbox1/msvc-2003-xbox1.vcproj new file mode 100644 index 0000000..ac6251a --- /dev/null +++ b/src/drivers/libretro/msvc/msvc-2003-xbox1/msvc-2003-xbox1.vcproj @@ -0,0 +1,846 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/drivers/libretro/msvc/msvc-2003-xbox1/stdint.h b/src/drivers/libretro/msvc/msvc-2003-xbox1/stdint.h new file mode 100644 index 0000000..9d8fe7b --- /dev/null +++ b/src/drivers/libretro/msvc/msvc-2003-xbox1/stdint.h @@ -0,0 +1,249 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// +#ifndef __RARCH_STDINT_H +#define __RARCH_STDINT_H + +#if _MSC_VER && (_MSC_VER < 1600) +//pre-MSVC 2010 needs an implementation of stdint.h + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + +#else +//sanity for everything else +#include +#endif + +#endif diff --git a/src/drivers/libretro/msvc/msvc-2010-360.sln b/src/drivers/libretro/msvc/msvc-2010-360.sln new file mode 100644 index 0000000..5f479e8 --- /dev/null +++ b/src/drivers/libretro/msvc/msvc-2010-360.sln @@ -0,0 +1,32 @@ +п»ї +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msvc-2010-360", "msvc-2010-360/msvc-2010-360.vcxproj", "{3FF56BB8-80B9-4477-9B55-248DFEFF7469}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + CodeAnalysis|Xbox 360 = CodeAnalysis|Xbox 360 + Debug|Xbox 360 = Debug|Xbox 360 + Profile_FastCap|Xbox 360 = Profile_FastCap|Xbox 360 + Profile|Xbox 360 = Profile|Xbox 360 + Release_LTCG|Xbox 360 = Release_LTCG|Xbox 360 + Release|Xbox 360 = Release|Xbox 360 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3FF56BB8-80B9-4477-9B55-248DFEFF7469}.CodeAnalysis|Xbox 360.ActiveCfg = CodeAnalysis|Xbox 360 + {3FF56BB8-80B9-4477-9B55-248DFEFF7469}.CodeAnalysis|Xbox 360.Build.0 = CodeAnalysis|Xbox 360 + {3FF56BB8-80B9-4477-9B55-248DFEFF7469}.Debug|Xbox 360.ActiveCfg = Debug|Xbox 360 + {3FF56BB8-80B9-4477-9B55-248DFEFF7469}.Debug|Xbox 360.Build.0 = Debug|Xbox 360 + {3FF56BB8-80B9-4477-9B55-248DFEFF7469}.Profile_FastCap|Xbox 360.ActiveCfg = Profile_FastCap|Xbox 360 + {3FF56BB8-80B9-4477-9B55-248DFEFF7469}.Profile_FastCap|Xbox 360.Build.0 = Profile_FastCap|Xbox 360 + {3FF56BB8-80B9-4477-9B55-248DFEFF7469}.Profile|Xbox 360.ActiveCfg = Profile|Xbox 360 + {3FF56BB8-80B9-4477-9B55-248DFEFF7469}.Profile|Xbox 360.Build.0 = Profile|Xbox 360 + {3FF56BB8-80B9-4477-9B55-248DFEFF7469}.Release_LTCG|Xbox 360.ActiveCfg = Release_LTCG|Xbox 360 + {3FF56BB8-80B9-4477-9B55-248DFEFF7469}.Release_LTCG|Xbox 360.Build.0 = Release_LTCG|Xbox 360 + {3FF56BB8-80B9-4477-9B55-248DFEFF7469}.Release|Xbox 360.ActiveCfg = Release|Xbox 360 + {3FF56BB8-80B9-4477-9B55-248DFEFF7469}.Release|Xbox 360.Build.0 = Release|Xbox 360 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/drivers/libretro/msvc/msvc-2010-360/msvc-2010-360.vcxproj b/src/drivers/libretro/msvc/msvc-2010-360/msvc-2010-360.vcxproj new file mode 100644 index 0000000..50aa5db --- /dev/null +++ b/src/drivers/libretro/msvc/msvc-2010-360/msvc-2010-360.vcxproj @@ -0,0 +1,1935 @@ + + + + + CodeAnalysis + Xbox 360 + + + Debug + Xbox 360 + + + Profile + Xbox 360 + + + Profile_FastCap + Xbox 360 + + + Release + Xbox 360 + + + Release_LTCG + Xbox 360 + + + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + CompileAsC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {3FF56BB8-80B9-4477-9B55-248DFEFF7469} + Xbox360Proj + fceu-next-360 + + + + StaticLibrary + MultiByte + + + StaticLibrary + MultiByte + + + StaticLibrary + MultiByte + + + StaticLibrary + MultiByte + + + StaticLibrary + MultiByte + + + StaticLibrary + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + + + $(OutDir)libretro_xdk360$(TargetExt) + + + $(OutDir)libretro_xdk360$(TargetExt) + + + $(OutDir)libretro_xdk360$(TargetExt) + + + $(OutDir)libretro_xdk360$(TargetExt) + + + $(OutDir)libretro_xdk360$(TargetExt) + + + $(OutDir)libretro_xdk360$(TargetExt) + + + + NotUsing + Level3 + ProgramDatabase + Disabled + false + true + false + $(OutDir)$(ProjectName).pch + MultiThreadedDebug + _DEBUG;_XBOX;_XBOX360;_LIB;__LIBRETRO__;SOUND_QUALITY=0;INLINE=_inline;PSS_STYLE=2;PATH_MAX=1024;%(PreprocessorDefinitions) + Callcap + $(SolutionDir)\..\libretro-fceumm;$(SolutionDir)\..\src-fceumm;$(SolutionDir)\..\..\..\..\..\srcboards;$(SolutionDir)\..\..\..\..\..\srcinput;$(SolutionDir)\..\..\..\..\..\srcmappers;%(AdditionalIncludeDirectories) + + + true + + + + + NotUsing + Level4 + ProgramDatabase + Disabled + false + true + AnalyzeOnly + false + $(OutDir)$(ProjectName).pch + MultiThreadedDebug + _DEBUG;_XBOX;_XBOX360;_LIB;%(PreprocessorDefinitions) + Callcap + $(SolutionDir)\..\libretro-fceumm;$(SolutionDir)\..\src-fceumm;$(SolutionDir)\..\..\..\..\..\srcboards;$(SolutionDir)\..\..\..\..\..\srcinput;$(SolutionDir)\..\..\..\..\..\srcmappers;%(AdditionalIncludeDirectories) + + + true + + + + + Level3 + NotUsing + Full + true + false + true + ProgramDatabase + Size + false + $(OutDir)$(ProjectName).pch + MultiThreaded + NDEBUG;_XBOX;_XBOX360;PROFILE;_LIB;%(PreprocessorDefinitions) + Callcap + $(SolutionDir)\..\libretro-fceumm;$(SolutionDir)\..\src-fceumm;$(SolutionDir)\..\..\..\..\..\srcboards;$(SolutionDir)\..\..\..\..\..\srcinput;$(SolutionDir)\..\..\..\..\..\srcmappers;%(AdditionalIncludeDirectories) + + + true + false + xapilib.lib;%(IgnoreSpecificDefaultLibraries) + true + + + + + Level3 + NotUsing + Full + true + false + true + ProgramDatabase + Fastcap + Size + false + $(OutDir)$(ProjectName).pch + MultiThreaded + NDEBUG;_XBOX;_XBOX360;PROFILE;FASTCAP;_LIB;%(PreprocessorDefinitions) + $(SolutionDir)\..\libretro-fceumm;$(SolutionDir)\..\src-fceumm;$(SolutionDir)\..\..\..\..\..\srcboards;$(SolutionDir)\..\..\..\..\..\srcinput;$(SolutionDir)\..\..\..\..\..\srcmappers;%(AdditionalIncludeDirectories) + + + true + false + true + + + + + Level3 + NotUsing + Full + true + true + ProgramDatabase + Size + false + false + $(OutDir)$(ProjectName).pch + MultiThreaded + NDEBUG;_XBOX;_XBOX360;_LIB;__LIBRETRO__;SOUND_QUALITY=0;INLINE=_inline;PSS_STYLE=2;PATH_MAX=1024;%(PreprocessorDefinitions) + $(SolutionDir)\..\libretro-fceumm;$(SolutionDir)\..\src-fceumm;$(SolutionDir)\..\..\..\..\..\srcboards;$(SolutionDir)\..\..\..\..\..\srcinput;$(SolutionDir)\..\..\..\..\..\srcmappers;%(AdditionalIncludeDirectories) + + + true + true + true + + + + + Level3 + NotUsing + Full + true + true + ProgramDatabase + Size + false + false + $(OutDir)$(ProjectName).pch + MultiThreaded + NDEBUG;_XBOX;_XBOX360;LTCG;_LIB;__LIBRETRO__;SOUND_QUALITY=0;INLINE=_inline;PSS_STYLE=2;PATH_MAX=1024;%(PreprocessorDefinitions) + $(SolutionDir)\..\libretro-fceumm;$(SolutionDir)\..\src-fceumm;$(SolutionDir)\..\..\..\..\..\srcboards;$(SolutionDir)\..\..\..\..\..\srcinput;$(SolutionDir)\..\..\..\..\..\srcmappers;%(AdditionalIncludeDirectories) + + + true + true + true + + + + + + diff --git a/src/drivers/libretro/msvc/msvc-2010-360/msvc-2010-360.vcxproj.filters b/src/drivers/libretro/msvc/msvc-2010-360/msvc-2010-360.vcxproj.filters new file mode 100644 index 0000000..ce3df62 --- /dev/null +++ b/src/drivers/libretro/msvc/msvc-2010-360/msvc-2010-360.vcxproj.filters @@ -0,0 +1,788 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {7a67469c-e0f4-4ae6-bedf-80819b918821} + + + {df43a723-7ffc-4d09-ac93-e6776518a5ef} + + + {3e0d408c-7e29-4169-b0a2-fedbac18c1dc} + + + {0be626d6-22ae-486d-bae4-cf5ee5226f8a} + + + {2d852975-e01d-4961-9cf0-f004287e1405} + + + {ad3640f4-91ee-4e6c-ad75-30db0eeee52f} + + + {c75a1e3d-897a-4ab0-aa61-68af448cb2cc} + + + {d3554fb8-af5e-4dea-8282-ae02aae83e42} + + + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\libretro + + + Source Files\libretro + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files\input + + + Header Files\input + + + Header Files\input + + + Header Files\mappers + + + Header Files\mappers + + + Header Files\mappers + + + Header Files\mappers + + + Header Files\boards + + + Header Files\boards + + + Header Files\libretro + + + Header Files\libretro + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/src/drivers/libretro/msvc/msvc-2010.sln b/src/drivers/libretro/msvc/msvc-2010.sln new file mode 100644 index 0000000..103c8f6 --- /dev/null +++ b/src/drivers/libretro/msvc/msvc-2010.sln @@ -0,0 +1,20 @@ +п»ї +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fceu-next", "msvc-2010\msvc-2010.vcxproj", "{0CE28350-1810-43E8-BB42-EC5C562C1C66}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0CE28350-1810-43E8-BB42-EC5C562C1C66}.Debug|Win32.ActiveCfg = Debug|Win32 + {0CE28350-1810-43E8-BB42-EC5C562C1C66}.Debug|Win32.Build.0 = Debug|Win32 + {0CE28350-1810-43E8-BB42-EC5C562C1C66}.Release|Win32.ActiveCfg = Release|Win32 + {0CE28350-1810-43E8-BB42-EC5C562C1C66}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/drivers/libretro/msvc/msvc-2010/libretro.def b/src/drivers/libretro/msvc/msvc-2010/libretro.def new file mode 100644 index 0000000..2a71c09 --- /dev/null +++ b/src/drivers/libretro/msvc/msvc-2010/libretro.def @@ -0,0 +1,27 @@ +LIBRARY "libretro-prboom msvc2010" +EXPORTS +retro_set_environment +retro_set_video_refresh +retro_set_audio_sample +retro_set_audio_sample_batch +retro_set_input_poll +retro_set_input_state +retro_init +retro_deinit +retro_api_version +retro_get_system_info +retro_get_system_av_info +retro_set_controller_port_device +retro_reset +retro_run +retro_serialize_size +retro_serialize +retro_unserialize +retro_cheat_reset +retro_cheat_set +retro_load_game +retro_load_game_special +retro_unload_game +retro_get_region +retro_get_memory_data +retro_get_memory_size diff --git a/src/drivers/libretro/msvc/msvc-2010/msvc-2010.vcxproj b/src/drivers/libretro/msvc/msvc-2010/msvc-2010.vcxproj new file mode 100644 index 0000000..260dec3 --- /dev/null +++ b/src/drivers/libretro/msvc/msvc-2010/msvc-2010.vcxproj @@ -0,0 +1,944 @@ +п»ї + + + + Debug + Win32 + + + Release + Win32 + + + + {0CE28350-1810-43E8-BB42-EC5C562C1C66} + Win32Proj + msvc2010 + fceu-next + + + + DynamicLibrary + true + Unicode + + + DynamicLibrary + false + true + Unicode + + + + + + + + + + + + + true + libretro + + + false + libretro + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;MSVC2010_EXPORTS;__LIBRETRO__;LOCAL_LE;INLINE=_inline;SOUND_QUALITY=0;PSS_STYLE=2;PATH_MAX=1024;LSB_FIRST;_CRT_SECURE_NO_WARNINGS;ZLIB;%(PreprocessorDefinitions) + $(SolutionDir)\..\..\..\..\..\src;$(SolutionDir)\..\..\..\..\..\src\boards;$(SolutionDir)\..\..\..\..\..\src\fir;$(SolutionDir)\..\..\..\..\..\src\mappers;$(SolutionDir)\..\..\..\..\..\src\palettes;$(SolutionDir)\..\libretro;$(SolutionDir)\..\..\..\..\..\src\zlib;%(AdditionalIncludeDirectories) + + + Windows + true + libretro.def + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;MSVC2010_EXPORTS;__LIBRETRO__;INLINE=_inline;SOUND_QUALITY=0;LOCAL_LE;PSS_STYLE=2;PATH_MAX=1024;LSB_FIRST;_CRT_SECURE_NO_WARNINGS;ZLIB;%(PreprocessorDefinitions) + $(SolutionDir)\..\..\..\..\..\src;$(SolutionDir)\..\..\..\..\..\src\boards;$(SolutionDir)\..\..\..\..\..\src\fir;$(SolutionDir)\..\..\..\..\..\src\mappers;$(SolutionDir)\..\..\..\..\..\src\palettes;$(SolutionDir)\..\libretro;$(SolutionDir)\..\..\..\..\..\src\zlib;%(AdditionalIncludeDirectories) + + + Windows + true + true + true + libretro.def + + + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + CompileAsC + CompileAsC + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/drivers/libretro/msvc/msvc-2010/msvc-2010.vcxproj.filters b/src/drivers/libretro/msvc/msvc-2010/msvc-2010.vcxproj.filters new file mode 100644 index 0000000..47a8a08 --- /dev/null +++ b/src/drivers/libretro/msvc/msvc-2010/msvc-2010.vcxproj.filters @@ -0,0 +1,780 @@ +п»ї + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + {4fd15cd1-892b-4eb6-b6e1-188314172a26} + + + {3a88b405-de79-447d-81f2-81cc04cc0f99} + + + {c5290483-f888-41c4-a70b-90be26fcfe46} + + + {3bbdc429-62bb-4787-9846-ae96edf7cda7} + + + {c3ae3102-dcd0-45ac-89f7-4c10d6916994} + + + {b4b19633-6ff4-4f3f-9c27-5057a190bdc7} + + + {8ae4a17b-52df-4e85-9258-855de98b4a99} + + + {8a306150-9ba0-404c-aa2f-668430e786e5} + + + + + Source Files\libretro + + + Source Files\libretro + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\mappers + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\input + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files\boards + + + Source Files + + + + + Header Files\libretro + + + Header Files\libretro + + + Header Files\boards + + + Header Files\boards + + + Header Files\input + + + Header Files\input + + + Header Files\input + + + Header Files\mappers + + + Header Files\mappers + + + Header Files\mappers + + + Header Files\mappers + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/src/drivers/win/args.c b/src/drivers/win/args.c new file mode 100644 index 0000000..745a591 --- /dev/null +++ b/src/drivers/win/args.c @@ -0,0 +1,38 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "../common/args.h" + +char *ParseArgies(int argc, char *argv[]) { +// int x; + static ARGPSTRUCT FCEUArgs[] = { + { "-pal", 0, &palyo, 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/src/drivers/win/cheat.c b/src/drivers/win/cheat.c new file mode 100644 index 0000000..b062310 --- /dev/null +++ b/src/drivers/win/cheat.c @@ -0,0 +1,445 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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; +} + + +/* 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, "%03d", a); + 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/src/drivers/win/cheat.h b/src/drivers/win/cheat.h new file mode 100644 index 0000000..d6aa730 --- /dev/null +++ b/src/drivers/win/cheat.h @@ -0,0 +1,2 @@ +void ConfigCheats(HWND hParent); +void ConfigAddCheat(HWND wnd); diff --git a/src/drivers/win/common.h b/src/drivers/win/common.h new file mode 100644 index 0000000..dc4c3db --- /dev/null +++ b/src/drivers/win/common.h @@ -0,0 +1,43 @@ +#include +#include +#include + +#ifndef WIN32 +#define WIN32 +#endif +#undef WINNT +#define NONAMELESSUNION + +#define DIRECTSOUND_VERSION 0x0700 +#define DIRECTDRAW_VERSION 0x0700 +#define DIRECTINPUT_VERSION 0x700 +#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/src/drivers/win/config.c b/src/drivers/win/config.c new file mode 100644 index 0000000..a13268d --- /dev/null +++ b/src/drivers/win/config.c @@ -0,0 +1,122 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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), + + 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]), + + 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), + 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/src/drivers/win/debug.c b/src/drivers/win/debug.c new file mode 100644 index 0000000..9e85a10 --- /dev/null +++ b/src/drivers/win/debug.c @@ -0,0 +1,672 @@ +#ifdef FCEUDEF_DEBUGGER +#include "common.h" +#include "../../x6502.h" +#include "../../debug.h" +#include "../../ppuview.h" +#include "debug.h" +#include "../../ppu.h" +#include "../../fds.h" + +static void DoMemmo(HWND hParent); +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; + +extern uint32 RefreshAddr; + +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) { + 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)); + SetDlgItemText(dwin, 223, (LPTSTR)U16ToStr(RefreshAddr)); + SetDlgItemText(dwin, 224, (LPTSTR)U16ToStr(lastDiskPtrRead)); + SetDlgItemText(dwin, 225, (LPTSTR)U16ToStr(lastDiskPtrWrite)); +} + +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); +} + +int BlockingCheck(void); + +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%s $%04x - $%04x", (type & BPOINT_READ) ? "R" : " ", + (type & BPOINT_WRITE) ? "W" : " ", (type & BPOINT_PC) ? "P" : " ", (type & BPOINT_EXCLUDE) ? "X" : " ", 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; + *type |= (IsDlgButtonChecked(hwndDlg, 533) == BST_CHECKED) ? BPOINT_EXCLUDE : 0; +} + +static BOOL CALLBACK DebugCon(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { + int32 scrollindex = 0, ced = 0; + int type; + 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) && (LOWORD(wParam) == 0x64)) { + uint16 A1, A2; + type = BPOINT_READ | BPOINT_PC; + A1 = A2 = asavers[SendDlgItemMessage(hwndDlg, 100, LB_GETCURSEL, 0, 0)]; + FCEUI_AddBreakPoint(type, A1, A2, BPointHandler); + hWndCallB = hwndDlg; /* Hacky hacky. */ + RBPCallBack(type, A1, A2, 0); + } + 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); + if ((PPUViewer) && (scanline == PPUViewScanline)) UpdatePPUView(1); + 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 CreateDumpSaveVid(uint32 a1, uint32 a2) { + const char filter[] = "Raw dump(*.chr)\0*.chr\0"; + char nameo[2048]; + OPENFILENAME ofn; + + memset(&ofn, 0, sizeof(ofn)); + ofn.lStructSize = sizeof(ofn); + ofn.hInstance = fceu_hInstance; + ofn.lpstrTitle = "Dump Video 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_DumpVid(nameo, a1, a2); + return(1); + } + return 0; +} + +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 232: + { + uint16 a1; + uint16 a2; + GetDlgItemText(hwndDlg, 230, TempArray, 64); + a1 = StrToU16(TempArray); + GetDlgItemText(hwndDlg, 231, TempArray, 64); + a2 = StrToU16(TempArray); + CreateDumpSaveVid(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; +} + +static 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) { + instep = -1; + FCEUI_SetCPUCallback(0); + DestroyWindow(dwin); + } + dwin = mwin = 0; +} +#endif diff --git a/src/drivers/win/debug.h b/src/drivers/win/debug.h new file mode 100644 index 0000000..cabcf80 --- /dev/null +++ b/src/drivers/win/debug.h @@ -0,0 +1,5 @@ +#ifdef FCEUDEF_DEBUGGER +void KillDebugger(void); +void UpdateDebugger(void); +void BeginDSeq(HWND hParent); +#endif diff --git a/src/drivers/win/ffb.c b/src/drivers/win/ffb.c new file mode 100644 index 0000000..63130d0 --- /dev/null +++ b/src/drivers/win/ffb.c @@ -0,0 +1,303 @@ +#include "ffb.h" +#include + +#define MAX_JOYSTICKS 32 +#define kDI_MaxEffects 30 // Hard coded limit (not a DX limit) + +extern LPDIRECTINPUTDEVICE7 Joysticks[MAX_JOYSTICKS]; + +// Force Feedback Effect Data +// -------------------------- +REFGUID effectGUID[kMaxEffectSubTypes] = +{ + &GUID_ConstantForce, + &GUID_RampForce, + &GUID_CustomForce, + // period + &GUID_Square, + &GUID_Sine, + &GUID_Triangle, + &GUID_SawtoothUp, + &GUID_SawtoothDown, + // condition + &GUID_Spring, + &GUID_Damper, + &GUID_Inertia, + &GUID_Friction +}; + +typedef union { + DICONSTANTFORCE constant; + DIRAMPFORCE ramp; + DIPERIODIC period; + DICONDITION condition; + DICUSTOMFORCE custom; +} tEffectClasses; + +typedef struct tEffect { + DIEFFECT general; + tEffectClasses specific; + DIENVELOPE envelope; + LONG direction[2]; +} tEffect; + +static tEffect Effect[kDI_MaxEffects]; + +// DInput Data +// ----------- +static LPDIRECTINPUTEFFECT DIE_hEffect[kDI_MaxEffects]; +static int numEffects = 0; + +// --------- +// ffb_Pause +// ------------------------------------------------------------------- +// Purpose: +// Pause the FFB output on the given device. Use ffb_Continue to +// continue where you left off. +// ------------------------------------------------------------------- +void +ffb_Pause(short dev) { + IDirectInputDevice7_SendForceFeedbackCommand(Joysticks[dev], DISFFC_PAUSE); +} + +// ------------ +// ffb_Continue +// ------------------------------------------------------------------- +// Purpose: +// Unpause the FFB output on the given device. Complimentary to +// ffb_Pause. +// ------------------------------------------------------------------- +void +ffb_Continue(short dev) { + IDirectInputDevice7_SendForceFeedbackCommand(Joysticks[dev], DISFFC_CONTINUE); +} + +// ---------- +// ffb_Enable +// ------------------------------------------------------------------- +// Purpose: +// Must be called after initialization in order to activate the +// device. +// Use ffb_Pause & ffb_Continue if you want disable forces +// temporarily and resume later. +// ------------------------------------------------------------------- +void +ffb_Enable(short dev) { + IDirectInputDevice7_SendForceFeedbackCommand(Joysticks[dev], DISFFC_SETACTUATORSON); +} + +// ----------- +// ffb_Disable +// ------------------------------------------------------------------- +// Purpose: +// Turns off FFB, but effects still play on processor. +// ------------------------------------------------------------------- +void +ffb_Disable(short dev) { + IDirectInputDevice7_SendForceFeedbackCommand(Joysticks[dev], DISFFC_SETACTUATORSOFF); +} + +void +ffb_simpleJolt(short dev) { + tFFB_Effect effect; + short eID; + // Constant Effect (simple jolt) + // ----------------------------- + effect.Type = kConstant; + effect.TypeInfo.Constant.Mag = 10000; + effect.Duration = 1000000 >> 1; // half second + effect.Period = 1000; + effect.Gain = 10000; + effect.Trigger = kNoButton; + effect.TriggerRepeatTime = 0; + effect.Direction = 0; + + eID = ffb_effectCreate(dev, &effect); +} + +// ---------------- +// ffb_effectCreate +// ------------------------------------------------------------------- +// Purpose: +// Create a single effect for future playback. +// Effect is given a logical ID +// ------------------------------------------------------------------- +int +ffb_effectCreate(short dev, tFFB_Effect* eff) { + HRESULT hr; + + // Important stuff + Effect[numEffects].general.dwDuration = eff->Duration; + Effect[numEffects].general.dwSamplePeriod = eff->Period; + Effect[numEffects].general.dwGain = eff->Gain; + Effect[numEffects].general.dwTriggerButton = (eff->Trigger == kNoButton ? DIEB_NOTRIGGER : DIJOFS_BUTTON(eff->Trigger)); + Effect[numEffects].general.dwTriggerRepeatInterval = eff->TriggerRepeatTime; + Effect[numEffects].direction[0] = eff->Direction; + memcpy(&Effect[numEffects].specific, &eff->TypeInfo, sizeof(tEffectClasses)); + + // Wacky COM related overhead + Effect[numEffects].general.dwSize = sizeof(DIEFFECT); + Effect[numEffects].general.cAxes = 2; + Effect[numEffects].general.rgdwAxes = 0; + Effect[numEffects].general.dwFlags = DIEFF_POLAR | DIEFF_OBJECTOFFSETS; + Effect[numEffects].general.lpvTypeSpecificParams = &Effect[numEffects].specific; + Effect[numEffects].general.rglDirection = &Effect[numEffects].direction; + Effect[numEffects].direction[1] = 0L; + Effect[numEffects].general.lpEnvelope = NULL; + Effect[numEffects].general.lpvTypeSpecificParams = &Effect[numEffects].specific; + + + switch (eff->Type) { + case kConstant: + Effect[numEffects].general.cbTypeSpecificParams = sizeof(DICONSTANTFORCE); + break; + case kRamp: + Effect[numEffects].general.cbTypeSpecificParams = sizeof(DIRAMPFORCE); + break; + case kCustom: + Effect[numEffects].general.cbTypeSpecificParams = sizeof(DICUSTOMFORCE); + break; + case kWave_Square: + case kWave_Sine: + case kWave_Triange: + case kWave_SawUp: + case kWave_SawDown: + Effect[numEffects].general.cbTypeSpecificParams = sizeof(DIPERIODIC); + break; + case kCondition_Spring: + case kCondition_Damper: + case kCondition_Inertia: + case kCondition_Friction: + Effect[numEffects].general.cbTypeSpecificParams = sizeof(DICONDITION); + break; + default: + return(-1); + } + + + hr = IDirectInputDevice7_CreateEffect(Joysticks[dev], + effectGUID[eff->Type], + (LPCDIEFFECT)&Effect[numEffects], + (LPDIRECTINPUTEFFECT*)&DIE_hEffect[numEffects], 0); + switch (hr) { + case DI_OK: + ffb_effectUnload(numEffects); + ++numEffects; + return(numEffects - 1); + + case DIERR_DEVICENOTREG: + return(-1); + + case DIERR_DEVICEFULL: + return(-1); + } + return(-1); +} + +// -------------- +// ffb_effectPlay +// ------------------------------------------------------------------- +// Purpose: +// Play an effect that was previously created. +// ------------------------------------------------------------------- +void +ffb_effectPlay(short eID) { + IDirectInputEffect_Start(DIE_hEffect[eID], 1, 0); +} + +// -------------- +// ffb_effectStop +// ------------------------------------------------------------------- +// Purpose: +// Stop a single effect. +// ------------------------------------------------------------------- +void +ffb_effectStop(short eID) { + IDirectInputEffect_Stop(DIE_hEffect[eID]); +} + +// ----------------- +// ffb_effectStopAll +// ------------------------------------------------------------------- +// Purpose: +// Stops all forces on the given device. +// ------------------------------------------------------------------- +void +ffb_effectStopAll(short dev) { + IDirectInputDevice7_SendForceFeedbackCommand(Joysticks[dev], DISFFC_STOPALL); +} + +// ---------------- +// ffb_effectUnload +// ------------------------------------------------------------------- +// Purpose: +// Unload a single effect... Necessary to make room for other +// effects. +// ------------------------------------------------------------------- +void +ffb_effectUnload(short eID) { + IDirectInputEffect_Unload(DIE_hEffect[eID]); +} + + +// ---------------- +// ffb_effectModify +// ------------------------------------------------------------------- +// Purpose: +// Modifies a single effect, only if the given parameters are +// different from what's currently loaded. +// ------------------------------------------------------------------- +void +ffb_effectModify(short eID, int* Direction, int* Duration, int* Gain, + int* Period, tEffInfo* TypeInfo, tEffEnvelope* Envelope) { + int flags = 0; + + return; + if (Direction) { + if (Effect[eID].direction[0] != *Direction) { + Effect[eID].direction[0] = *Direction; + flags |= DIEP_DIRECTION; + } + } + if (Duration) { + if (Effect[eID].general.dwDuration != *Duration) { + Effect[eID].general.dwDuration = *Duration; + flags |= DIEP_DURATION; + } + } + if (Gain) { + if (Effect[eID].general.dwGain != *Gain) { + Effect[eID].general.dwGain = *Gain; + flags |= DIEP_GAIN; + } + } + if (Period) { + if (Effect[eID].general.dwSamplePeriod != *Period) { + Effect[eID].general.dwSamplePeriod = *Period; + flags |= DIEP_SAMPLEPERIOD; + } + } + if (TypeInfo) { + if (!memcmp(&Effect[eID].specific, TypeInfo, Effect[eID].general.cbTypeSpecificParams)) { + memcpy(&Effect[eID].specific, TypeInfo, Effect[eID].general.cbTypeSpecificParams); + flags |= DIEP_TYPESPECIFICPARAMS; + } + } + if (Envelope) { + if (Effect[eID].envelope.dwAttackLevel != Envelope->AttackLevel || + Effect[eID].envelope.dwAttackTime != Envelope->AttackTime || + Effect[eID].envelope.dwFadeLevel != Envelope->FadeLevel || + Effect[eID].envelope.dwFadeTime != Envelope->FadeTime) { + Effect[eID].envelope.dwAttackLevel = Envelope->AttackLevel; + Effect[eID].envelope.dwAttackTime = Envelope->AttackTime; + Effect[eID].envelope.dwFadeLevel = Envelope->FadeLevel; + Effect[eID].envelope.dwFadeTime = Envelope->FadeTime; + flags |= DIEP_ENVELOPE; + } + } + + if (!flags) + return; + + IDirectInputEffect_SetParameters(DIE_hEffect[eID], (LPCDIEFFECT)&Effect[eID], flags); +} diff --git a/src/drivers/win/ffb.h b/src/drivers/win/ffb.h new file mode 100644 index 0000000..2f8c233 --- /dev/null +++ b/src/drivers/win/ffb.h @@ -0,0 +1,195 @@ +#ifndef _DXINPUT_H_ +#define _DXINPUT_H_ + +#define kMAX_Str 80 +#define kMAX_Axis 8 +#define kMAX_Sliders 2 +#define kMAX_POVs 4 + +#define kInfinite_Duration 0xFFFFFF +#define HZ_to_uS(hz) ((int)(1000000.0 / (double)(hz) + 0.5)) + +typedef signed char tSC; +typedef signed int tSI; +typedef signed long tSL; + +typedef unsigned char tUC; +typedef unsigned int tUI; +typedef unsigned long tUL; + +typedef enum { + kJoy1 = 0, + kJoy2, + kJoy3, + kJoy4, + kJoy5, + kJoy6, + kJoy7, + kJoy8, + kJoy9, + kJoy10, + kJoy11, + kJoy12, + kJoy13, + kJoy14, + kJoy15, + kJoy16, + kMaxJoy, + kMouse, + kKeyBoard, + kAllDevices +} tDevice; + +typedef enum { + kNoButton = -1, + kButton0 = 0, + kButton1, + kButton2, + kButton3, + kButton4, + kButton5, + kButton6, + kButton7, + kButton8, + kButton9, + kButton10, + kButton31 = 31, + kButtonMax +} tJoyButtons; + +typedef enum { + kStick = 1 << 0, + kWheel = 1 << 1, + kGamePad = 1 << 2, +} tDeviceMask; + +typedef struct { + int ButtonMask; + int AxisMask; + tDeviceMask DevType; + char Name[kMAX_Str]; +} tJoyInfo; + +typedef struct { + int ButtonMask; + tSL X_pos; + tSL Y_pos; + tSL Z_pos; + + tSL X_rot; + tSL Y_rot; + tSL Z_rot; + + tSL Slide_pos[kMAX_Sliders]; + tUL POV_dir[kMAX_POVs]; +} tJoyData; + +typedef enum { + kDontPlayNow = 0, + kPlayNow, + kPlayNowIfModified, +} tLoadEffect; + +typedef enum { + kConstant, + kRamp, + kCustom, + + kWave_Square, + kWave_Sine, + kWave_Triange, + kWave_SawUp, + kWave_SawDown, + + kCondition_Spring, + kCondition_Damper, + kCondition_Inertia, + kCondition_Friction, + + kMaxEffectSubTypes +} tEffType; + +typedef struct tEffConstant { + long Mag; +} tEffConstant; + +typedef struct tEffRamp { + long Start; + long End; +} tEffRamp; + +typedef struct tEffWave { + int Mag; + long Offset; + int Phase; + int Period; +} tEffWave; + +typedef struct tEffCondition { + long Offset; + long PositiveCoefficient; + long NegativeCoefficient; + int PositiveSaturation; + int NegativeSaturation; + long DeadBand; +} tEffCondition; + +typedef struct tEffCustom { + int Channels; + int Period; + int Samples; + long *ForceData; +} tEffCustom; + +typedef union tEffectInfo { + tEffConstant Constant; + tEffRamp Ramp; + tEffWave Wave; + tEffCondition Condition; + tEffCustom Custom; +} tEffInfo; + +typedef struct tEffectEnvelope { + int AttackLevel; + int AttackTime; + int FadeLevel; + int FadeTime; +} tEffEnvelope; + +typedef struct tFFB_Effect { + tEffType Type; + tEffInfo TypeInfo; + int Duration; + int Period; + int Gain; + tJoyButtons Trigger; + int TriggerRepeatTime; + long Direction; + tEffEnvelope Envelope; +} tFFB_Effect; + + +// =================================================================== +// Function Prototypes +// =================================================================== +// Init +// ---- +int ffb_Init(void); + +// Use +// --- + +void ffb_Pause(short dev); +void ffb_Continue(short dev); + +void ffb_Enable(short dev); +void ffb_Disable(short dev); + +int ffb_effectCreate(short dev, tFFB_Effect* eff); +void ffb_effectPlay(short effectID); +void ffb_effectStop(short effectID); +void ffb_effectStopAll(short dev); +void ffb_effectModify(short effectID, int* Direction, int* Duration, int* Gain, + int* Period, tEffInfo* TypeInfo, tEffEnvelope* Envelope); + +#endif // _DXINPUT_H_ \ No newline at end of file diff --git a/src/drivers/win/input.c b/src/drivers/win/input.c new file mode 100644 index 0000000..3e1028b --- /dev/null +++ b/src/drivers/win/input.c @@ -0,0 +1,1038 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "common.h" +#include + +#include "input.h" +#include "keyboard.h" +#include "joystick.h" + +#define MAX_EXTENSIONS 7 +#define MAX_EXPANSIONS 15 + +LPDIRECTINPUT7 lpDI; + +/* 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]; +static int cspec; + +int gametype; + +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[x] == SI_MOUSE) + FCEUI_SetInput(x, SI_MOUSE, 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; +static uint8 HyperShotData; +static uint32 MahjongData; +static uint32 FTrainerData; +static uint8 TopRiderData; + +static uint8 BWorldData[1 + 13 + 1]; + +static void UpdateFKB(void); +static void UpdateSuborKB(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; +int NoWaiting = 1; + +#include "keyscan.h" +static char *keys; +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)) + +int cidisabled = 0; + +static void KeyboardCommands(void) { + int is_shift, is_alt; + + keys = GetKeyboard(); + + if ((InputType[2] == SIFC_FKB) || (InputType[2] == SIFC_SUBORKB) || (InputType[2] == SIFC_PEC586KB)) { + 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); + } + + { + static int nocount = 0; + + NoWaiting &= ~1; + if (KEY(GRAVE)) //&& nocount) + NoWaiting |= 1; + nocount = (nocount + 1) & 3; + } + + if (gametype == GIT_FDS) { + if (keyonly(F6)) FCEUI_FDSSelect(); + if (keyonly(F8)) FCEUI_FDSInsert(0); + } + + if (keyonly(F9)) FCEUI_SaveSnapshot(); + if (gametype != GIT_NSF) { + if (keyonly(F5)) { + if (is_shift) + FCEUI_SaveMovie(NULL); + else + FCEUI_SaveState(NULL); + } + if (keyonly(F7)) { + if (is_shift) + FCEUI_LoadMovie(NULL); + else + FCEUI_LoadState(NULL); + } + } + +// if(keyonly(F1)) FCEUI_ToggleTileView(); + + 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); \ + else FCEUI_SelectState(x); \ + } \ + } + + 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 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() +}; + + +static void UpdateGamepad(void) { + static int rapid = 0; + uint32 JS = 0; + int x; + int wg; + + rapid = (rapid + 1) & 3; + + for (wg = 0; wg < 4; wg++) { + for (x = 0; x < 8; x++) + if (DTestButton(&GamePadConfig[wg][x])) + JS |= (1 << x) << (wg << 3); + + if (rapid & 2) + 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]; + +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[0x65]; + +void GetMouseData(uint32 *); + +void FCEUD_UpdateInput(void) { + int x; + int t = 0; + + KeyboardUpdateState(); + UpdateJoysticks(); + + //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_MOUSE: 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_PEC586KB: + 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_MOUSE: 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_PEC586KB: + 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[0x65] = +{ + 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), MC(0x00), MC(0x00), MC(0x00), MC(0x00), MC(0x00), + MC(0x00), +}; + +static void UpdateFKB(void) { + int x; + + for (x = 0; x < sizeof(fkbkeys); x++) { + fkbkeys[x] = 0; + + if (DTestButton(&fkbmap[x])) + fkbkeys[x] = 1; + } +} + +static void UpdateSuborKB(void) { + int x; + + for (x = 0; x < sizeof(suborkbkeys); 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); + +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 < sizeof(fkbkeys); x++) + JoyClearBC(&fkbmap[x]); + + for (x = 0; x < sizeof(suborkbkeys); 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[13] = { "none", "arkanoid", "shadow", "4player", + "fkb", "suborkb", "pec586kb", "hypershot", + "mahjong", "quizking", "ftrainera", "ftrainerb", + "oekakids" }; + + static int fccortabi[13] = { SIFC_NONE, SIFC_ARKANOID, SIFC_SHADOW, SIFC_4PLAYER, + SIFC_FKB, SIFC_SUBORKB, SIFC_PEC586KB, SIFC_HYPERSHOT, + SIFC_MAHJONG, SIFC_QUIZKING, SIFC_FTRAINERA, SIFC_FTRAINERB, + SIFC_OEKAKIDS }; + int y; + for (y = 0; y < 13; y++) + if (!strcmp(fccortab[y], text)) + UsrInputType[2] = fccortabi[y]; +} + +static char *cortab[MAX_EXTENSIONS] = { "none", "gamepad", "zapper", "powerpada", "powerpadb", "arkanoid", "mouse" }; +static int cortabi[MAX_EXTENSIONS] = { SI_NONE, SI_GAMEPAD, SI_ZAPPER, SI_POWERPADA, SI_POWERPADB, SI_ARKANOID, SI_MOUSE }; + +static void Input1(char *text) { + int y; + for (y = 0; y < MAX_EXTENSIONS; y++) + if (!strcmp(cortab[y], text)) + UsrInputType[0] = cortabi[y]; +} + +static void Input2(char *text) { + int y; + for (y = 0; y < MAX_EXTENSIONS; 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[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)) + sprintf(tmpstr + strlen(tmpstr), "%02X", bc->ButtonNum[x]); + else + sprintf(tmpstr + strlen(tmpstr), " (%02X)", bc->ButtonNum[x]); + } 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); + return 0; +} + +static ButtConfig *DoTBButtons; +static const char *DoTBTitle; +static int DoTBMax; +static int DoTBType, DoTBPort; + +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[MAX_EXTENSIONS] = { "", "Gamepad", "Zapper", "Power Pad A", "Power Pad B", "Arkanoid Paddle", "Mouse" }; + static const char *strf[MAX_EXPANSIONS] = + { "", "Arkanoid Paddle", "Hyper Shot gun", "4-Player Adapter", + "Family Keyboard", "Subor Keyboard", "PEC586 Keyboard", "HyperShot Pads", "Mahjong", "Quiz King Buzzers", + "Family Trainer A", "Family Trainer B", "Oeka Kids Tablet", "Barcode World", + "Top Rider" }; + static const int haven[MAX_EXTENSIONS] = { 0, 1, 0, 1, 1, 0, 0 }; + static const int havef[MAX_EXPANSIONS] = { 0, 0, 0, 0, 1, 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 < MAX_EXTENSIONS - 1; y++) + SendDlgItemMessage(hwndDlg, 104, CB_ADDSTRING, 0, (LPARAM)(LPSTR)strn[y]); + SendDlgItemMessage(hwndDlg, 104, CB_SETCURSEL, UsrInputType[0], (LPARAM)(LPSTR)0); + EnableWindow(GetDlgItem(hwndDlg, 106), haven[InputType[0]]); + SetDlgItemText(hwndDlg, 200, (LPTSTR)strn[InputType[0]]); + } + { + int y; + for (y = 0; y < MAX_EXTENSIONS; y++) + SendDlgItemMessage(hwndDlg, 105, CB_ADDSTRING, 0, (LPARAM)(LPSTR)strn[y]); + SendDlgItemMessage(hwndDlg, 105, CB_SETCURSEL, UsrInputType[1], (LPARAM)(LPSTR)0); + EnableWindow(GetDlgItem(hwndDlg, 107), haven[InputType[1]]); + SetDlgItemText(hwndDlg, 201, (LPTSTR)strn[InputType[1]]); + } + + + { + int y; + for (y = 0; y < MAX_EXPANSIONS; 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]]); + } + + 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, sizeof(fkbkeys)); break; + case SIFC_PEC586KB: + case SIFC_SUBORKB: DoTBConfig(hwndDlg, text, "SUBORKBDIALOG", suborkbmap, sizeof(suborkbkeys)); 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 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); + } +} diff --git a/src/drivers/win/input.h b/src/drivers/win/input.h new file mode 100644 index 0000000..d250e9f --- /dev/null +++ b/src/drivers/win/input.h @@ -0,0 +1,46 @@ +void ConfigInput(HWND hParent); +int InitDInput(void); +void CreateInputStuff(void); +void InitInputStuff(void); +void DestroyInput(void); +void InputScreenChanged(int fs); + +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" + +#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 FCEUD_UpdateInput(void); +int DTestButton(ButtConfig *bc); +#endif + diff --git a/src/drivers/win/joystick.c b/src/drivers/win/joystick.c new file mode 100644 index 0000000..c5a8219 --- /dev/null +++ b/src/drivers/win/joystick.c @@ -0,0 +1,355 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#define MAX_JOYSTICKS 32 + +#include "common.h" +#include + +#include "input.h" +#include "joystick.h" + +//static LPDIRECTINPUTDEVICE7 Joysticks[MAX_JOYSTICKS]={0}; +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 = 0; + + 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_BACKGROUND | 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; + + IDirectInputDevice7_Acquire(Joysticks[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); +} diff --git a/src/drivers/win/joystick.h b/src/drivers/win/joystick.h new file mode 100644 index 0000000..3b2735a --- /dev/null +++ b/src/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/src/drivers/win/keyboard.c b/src/drivers/win/keyboard.c new file mode 100644 index 0000000..a5da535 --- /dev/null +++ b/src/drivers/win/keyboard.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "common.h" +#include + +#include "input.h" +#include "keyboard.h" + +HRESULT ddrval; + +static LPDIRECTINPUTDEVICE7 lpdid = 0; + +void KeyboardClose(void) { + if (lpdid) IDirectInputDevice7_Unacquire(lpdid); + lpdid = 0; +} + +static char keys[256]; +void KeyboardUpdateState(void) { + char tk[256]; + + ddrval = IDirectInputDevice7_GetDeviceState(lpdid, 256, tk); + switch (ddrval) { + case DI_OK: memcpy(keys, tk, 256); break; + case DIERR_INPUTLOST: + case DIERR_NOTACQUIRED: + memset(keys, 0, 256); + IDirectInputDevice7_Acquire(lpdid); + break; + } +} + +char *GetKeyboard(void) { + return(keys); +} + +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; +} diff --git a/src/drivers/win/keyboard.h b/src/drivers/win/keyboard.h new file mode 100644 index 0000000..c7bb8b3 --- /dev/null +++ b/src/drivers/win/keyboard.h @@ -0,0 +1,6 @@ +void KeyboardUpdateState(void); +void KeyboardClose(void); +int KeyboardInitialize(void); +void KeyboardUpdate(void); +char *GetKeyboard(void); + diff --git a/src/drivers/win/keyscan.h b/src/drivers/win/keyscan.h new file mode 100644 index 0000000..b9f4c4b --- /dev/null +++ b/src/drivers/win/keyscan.h @@ -0,0 +1,127 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 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_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/src/drivers/win/log.c b/src/drivers/win/log.c new file mode 100644 index 0000000..ef4d173 --- /dev/null +++ b/src/drivers/win/log.c @@ -0,0 +1,92 @@ +#include +#include "common.h" + +#define MAXLOGTEXT 1024 + +static HWND logwin = 0; + +static char *logtext[MAXLOGTEXT]; +static int logcount = 0; + +static void RedoText(void) { + char textbuf[65535]; + int x; + + textbuf[0] = 0; + if (logcount >= MAXLOGTEXT) { + x = logcount & (MAXLOGTEXT - 1); + for (;; ) { + strcat(textbuf, logtext[x]); + x = (x + 1) & (MAXLOGTEXT - 1); + if (x == (logcount & (MAXLOGTEXT - 1))) break; + } + } else + for (x = 0; x < logcount; x++) { + strcat(textbuf, logtext[x]); + } + SetDlgItemText(logwin, 100, textbuf); + SendDlgItemMessage(logwin, 100, EM_LINESCROLL, 0, 1024 * 4); +} + +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 >= MAXLOGTEXT) free(logtext[logcount & (MAXLOGTEXT - 1)]); + + x = 0; + t = text; + while (*t) { + if (*t == '\n') x++; + t++; + } + + if (!(logtext[logcount & (MAXLOGTEXT - 1)] = malloc(strlen(text) + 1 + x + newline * 2))) + return; + + t = logtext[logcount & (MAXLOGTEXT - 1)]; + + 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/src/drivers/win/log.h b/src/drivers/win/log.h new file mode 100644 index 0000000..9437f2e --- /dev/null +++ b/src/drivers/win/log.h @@ -0,0 +1,2 @@ +void MakeLogWindow(void); +void AddLogText(char *text, int newline); diff --git a/src/drivers/win/main.c b/src/drivers/win/main.c new file mode 100644 index 0000000..01e3a6f --- /dev/null +++ b/src/drivers/win/main.c @@ -0,0 +1,459 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "common.h" + +// I like hacks. +#define uint8 __UNO492032 +#include +#include +#undef LPCWAVEFORMATEX +#include +#include +#include +#include +#include // 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 "../common/vidblit.h" +#include "../../ppuview.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); +void RedoMenuGI(FCEUGI *gi); + +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", "gameinfo", "sav", "fcs", "snaps" }; + +static char TempArray[2048]; +static char BaseDirectory[2048]; + +void SetDirs(void) { + int x; + static int jlist[5] = + { FCEUIOD_CHEATS, FCEUIOD_MISC, FCEUIOD_NV, FCEUIOD_STATE, FCEUIOD_SNAPS }; + + FCEUI_SetSnapName(eoptions & EO_SNAPNAME); + + for (x = 0; x < 5; 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. */ +static int maxconbskip = 9; /* Maximum consecutive blit skips. */ +static int ffbskip = 9; /* Blit skips per blit when FF-ing */ + +static int fullscreen = 0; +//static int soundflush=0; +static int genie = 0; +static int palyo = 0; +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 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; + +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; +static 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\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; + + exiting = 1; + if (GI) { + GI = 0; + RedoMenuGI(GI); + #ifdef FCEUDEF_DEBUGGER + KillDebugger(); + #endif + FCEUI_CloseGame(); +//GI=0; +//RedoMenuGI(GI); + } +} + +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); + +int main(int argc, char *argv[]) { + char *t; + + if (timeBeginPeriod(1) != TIMERR_NOERROR) { + AddLogText("Error setting timer granularity to 1ms.", 1); + } + + if (!FCEUI_Initialize()) + goto doexito; + + 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; + int32 *sound; + int32 ssize; + + FCEUI_Emulate(&gfx, &sound, &ssize, 0); + xbsave = gfx; + FCEUD_Update(gfx, sound, ssize); + } + 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 maxskip = maxconbskip; + + if (NoWaiting & 1) + maxskip = ffbskip; + + if (Count) { + int32 can = GetWriteSound(); + static int uflow = 0; + int32 tmpcan; + extern int FCEUDnetplay; + + if (can >= GetMaxSound()) uflow = 1; /* Go into massive underflow mode. */ + + if (can > Count) can = Count; + else uflow = 0; + + FCEUD_WriteSoundData(Buffer, can); + + tmpcan = GetWriteSound(); + if (((tmpcan < Count * 0.90) && !uflow) || (skipcount >= maxskip)) { + if (XBuf && (!NoWaiting || skipcount >= maxskip)) { + skipcount = 0; + FCEUD_BlitScreen(XBuf); + } else { + skipcount++; + //FCEU_printf("Skipped0"); + } + Buffer += can; + Count -= can; + if (Count) { + if (NoWaiting) { + can = GetWriteSound(); + if (Count > can) Count = can; + } + FCEUD_WriteSoundData(Buffer, Count); + } + } 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, (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; + + if (!(eoptions & EO_NOTHROTTLE)) + if (!NoWaiting) + if (!soundo || (soundo && nofocus && !(soundoptions & SO_SECONDARY))) + skipthis = SpeedThrottle(); + + if (XBuf) { + if ((!skipthis && !NoWaiting) || (skipcount >= maxskip)) { + FCEUD_BlitScreen(XBuf); + skipcount = 0; + } else { + skipcount++; + } + } + } + UpdateFCEUWindow(); + FCEUD_UpdateInput(); + PPUViewDoBlit(); +} + +FILE *FCEUD_UTF8fopen(const char *n, const char *m) { + return(fopen(n, m)); +} diff --git a/src/drivers/win/netplay.c b/src/drivers/win/netplay.c new file mode 100644 index 0000000..388c34d --- /dev/null +++ b/src/drivers/win/netplay.c @@ -0,0 +1,434 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 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); +} + +int FCEUD_NetworkConnect(); + +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, (const char*)&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/src/drivers/win/netplay.h b/src/drivers/win/netplay.h new file mode 100644 index 0000000..c2f2f92 --- /dev/null +++ b/src/drivers/win/netplay.h @@ -0,0 +1 @@ +extern CFGSTRUCT NetplayConfig[]; diff --git a/src/drivers/win/ppuview.c b/src/drivers/win/ppuview.c new file mode 100644 index 0000000..b051c4a --- /dev/null +++ b/src/drivers/win/ppuview.c @@ -0,0 +1,347 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "common.h" +#include "..\..\ppuview.h" +#include "..\..\palette.h" //bbit edited: this line changed to include this instead of svga.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 +VOID *pattern0, *pattern1; //pattern table bitmap arrays +VOID *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 + memcpy(palcache, PALRAM, 32); //below that change 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/src/drivers/win/ppuview.h b/src/drivers/win/ppuview.h new file mode 100644 index 0000000..e69de29 diff --git a/src/drivers/win/res.rc b/src/drivers/win/res.rc new file mode 100644 index 0000000..348dd89 --- /dev/null +++ b/src/drivers/win/res.rc @@ -0,0 +1,738 @@ +/********************************************* +File: C:\DEV-CPP\PROJECTS\FCEU\SRC\DRIVERS\WIN\RES.RC +Generated by Resource Builder. +*********************************************/ +// Below are important 3 lines, don't change them! +/* +OutputExt=res +*/ + +#include +#include + +LANGUAGE LANG_NEUTRAL, 0 +ICON_1 ICON "src\\drivers\\win\\res\\EXE.ico" +ICON_2 ICON "src\\drivers\\win\\res\\NES.ico" +ICON_3 ICON "src\\drivers\\win\\res\\FDS.ico" +ICON_4 ICON "src\\drivers\\win\\res\\FAM.ico" + + +FCEUMENU MENU +MOVEABLE PURE LOADONCALL DISCARDABLE +BEGIN + POPUP "&File" + BEGIN + MENUITEM "&Open...", 100 + MENUITEM "&Close", 101 + MENUITEM "&Recent", 102 + MENUITEM "Recent &Directories", 103 + MENUITEM SEPARATOR + MENUITEM "Load State From...", 111 + MENUITEM "Save State As...", 110 + MENUITEM SEPARATOR + MENUITEM "Log &Sound As...", 120 + MENUITEM SEPARATOR + MENUITEM "Copifamiclone &Hardware Interface...", 140 + MENUITEM SEPARATOR + MENUITEM "E&xit F12", 130 + END + POPUP "&NES" + BEGIN + MENUITEM "&Reset F10", 200 + MENUITEM "&Power F11", 201 + MENUITEM SEPARATOR + MENUITEM "&Cheats...", 204 + MENUITEM "&Debugger...", 203 + MENUITEM "PPU View...", 205 + END + POPUP "&Config" + BEGIN + MENUITEM "Hide Menu F3", 300 + MENUITEM "Active While Focus Lost", 301 + MENUITEM SEPARATOR + MENUITEM "Game Genie", 310 + MENUITEM "PAL Emulation", 311 + MENUITEM SEPARATOR + MENUITEM "&Directories...", 320 + MENUITEM "&GUI...", 327 + MENUITEM "&Input...", 321 + MENUITEM "&Network Play...", 323 + MENUITEM "&Palette...", 324 + MENUITEM "&Sound...", 325 + MENUITEM "&Timing...", 322 + MENUITEM "&Video...", 326 + END + POPUP "&Help" + BEGIN + MENUITEM "&Message Log...", 401 + MENUITEM SEPARATOR + MENUITEM "&About...", 400 + END +END + +ADDCHEAT DIALOG 28, 53, 405, 239 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "Add Cheat" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "",108,"LISTBOX",LBS_WANTKEYBOARDINPUT |LBS_NOINTEGRALHEIGHT |LBS_HASSTRINGS |LBS_NOTIFY |WS_CHILD |WS_BORDER |WS_VISIBLE ,9,30,56,202 + CONTROL "V1:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_VISIBLE ,85,39,12,8 + CONTROL "V2:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_VISIBLE ,136,39,12,8 + CONTROL "",110,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,101,37,20,12 + CONTROL "",111,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,152,37,20,12 + CONTROL "&Reset Search",112,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,98,213,59,14 + CONTROL "&Do Search",113,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,93,194,49,14 + CONTROL "&Unhide Excluded",107,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,89,164,59,14 + CONTROL "Set Original to Current",114,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,82,139,80,14 + CONTROL "Cheat Search",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_VISIBLE ,5,17,172,219 + CONTROL "Parameters",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_VISIBLE ,80,26,97,103 + CONTROL "O==V1 &&&& C==V2",115,"BUTTON",BS_AUTORADIOBUTTON |WS_CHILD |WS_VISIBLE ,86,54,87,12 + CONTROL "O==V1 &&&& |O-C|==V2",116,"BUTTON",BS_AUTORADIOBUTTON |WS_CHILD |WS_VISIBLE ,86,66,87,12 + CONTROL "|O-C|==V2",117,"BUTTON",BS_AUTORADIOBUTTON |WS_CHILD |WS_VISIBLE ,86,102,48,12 + CONTROL "O!=C",118,"BUTTON",BS_AUTORADIOBUTTON |WS_CHILD |WS_VISIBLE ,86,114,48,12 + CONTROL "",120,"SCROLLBAR",SBS_VERT |WS_CHILD |WS_VISIBLE ,66,30,12,200 + CONTROL "Close",106,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,317,218,81,14 + CONTROL "Value decreased.",119,"BUTTON",BS_AUTORADIOBUTTON |WS_CHILD |WS_VISIBLE ,86,78,75,12 + CONTROL "Value increased.",120,"BUTTON",BS_AUTORADIOBUTTON |WS_CHILD |WS_VISIBLE ,86,90,75,12 + CONTROL "Name:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_VISIBLE ,300,31,23,8 + CONTROL "",200,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,328,30,65,12 + CONTROL "Address:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_VISIBLE ,304,47,31,8 + CONTROL "",201,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,340,46,27,12 + CONTROL "Value:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_VISIBLE ,309,63,26,8 + CONTROL "",202,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,340,62,27,12 + CONTROL "",203,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,340,78,27,12 + CONTROL "Add",250,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,329,116,50,14 + CONTROL "Cheats",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_VISIBLE ,182,17,217,188 + CONTROL "Compare:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_VISIBLE ,306,80,30,8 + CONTROL "Read Substitute",204,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,317,94,74,12 + CONTROL "Update",251,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,326,158,58,14 + CONTROL "",300,"LISTBOX",LBS_NOTIFY |WS_CHILD |WS_BORDER |WS_VSCROLL |WS_VISIBLE ,188,30,110,164 + CONTROL "Delete",252,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,326,187,58,14 + CONTROL "Add Game Genie",253,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,323,136,64,14 + CONTROL "To add a Game Genie code, type the code into the \x22Name\x22 field, and hit \x22Add Game Genie\x22.",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,10,4,387,8 +END + +DEBUGGER DIALOG 6, 51, 380, 227 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "Debugger" +FONT 8, "Fixedsys" +BEGIN + CONTROL "Close",1,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,317,206,56,14 + CONTROL "",100,"LISTBOX",LBS_NOTIFY |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,2,6,187,220 + CONTROL "",200,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,226,52,20,12 + CONTROL "PC:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,206,54,15,8 + CONTROL "",201,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,226,66,12,12 + CONTROL "SP:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,206,69,15,8 + CONTROL "",202,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,226,80,12,12 + CONTROL "P:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,206,82,15,8 + CONTROL "",210,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,351,53,12,12 + CONTROL "A:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,335,54,11,8 + CONTROL "X:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,335,67,11,8 + CONTROL "",211,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,351,67,12,12 + CONTROL "Y:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,336,81,10,8 + CONTROL "",212,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,351,81,12,12 + CONTROL "N V - - D I Z C",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,260,58,64,8 + CONTROL "",407,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,259,68,8,12 + CONTROL "",406,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,267,68,8,12 + CONTROL "",403,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,291,68,8,12 + CONTROL "",402,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,299,68,8,12 + CONTROL "",401,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,307,68,8,12 + CONTROL "",400,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,315,68,8,12 + CONTROL "Flags:",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,252,49,81,35 + CONTROL "",223,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,252,85,18,8 + CONTROL "",224,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,278,85,18,8 + CONTROL "",225,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,304,85,18,8 + CONTROL "&Run",301,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,207,25,40,14 + CONTROL "R&eset",310,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,256,4,37,14 + CONTROL "&Step",300,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,207,4,40,14 + CONTROL "&NMI",302,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,344,25,30,14 + CONTROL "&IRQ",303,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,344,4,30,14 + CONTROL "",101,"SCROLLBAR",SBS_VERT |WS_CHILD |WS_VISIBLE ,190,5,9,219 + CONTROL "&Memory...",311,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,207,206,51,14 + CONTROL "BreakPoints",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,201,105,176,84 + CONTROL "IRQ:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,296,9,16,8 + CONTROL "",220,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,313,9,18,8 + CONTROL "NMI:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,296,19,16,8 + CONTROL "",221,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,313,19,18,8 + CONTROL "Reset:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,285,29,27,8 + CONTROL "",222,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,313,29,18,8 + CONTROL "",510,"LISTBOX",LBS_NOTIFY |WS_CHILD |WS_BORDER |WS_VSCROLL |WS_VISIBLE ,205,114,100,51 + CONTROL "Delete",540,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,207,168,34,14 + CONTROL "",520,"EDIT",ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,308,114,23,12 + CONTROL "",521,"EDIT",ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,341,114,23,12 + CONTROL "Read",530,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,310,126,42,12 + CONTROL "Write",531,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,310,146,36,12 + CONTROL "PC Same",532,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,315,136,42,12 + CONTROL "Exclude",533,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,315,156,42,12 + CONTROL "Add",541,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,337,168,36,14 + CONTROL "Registers",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,201,42,171,54 + CONTROL "-",65535,"STATIC",SS_CENTER |WS_CHILD |WS_GROUP |WS_VISIBLE ,332,116,7,8 +END + +DIRCONFIG DIALOG 63, 7, 280, 331 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "Directories Configuration" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Close",1,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,215,311,56,14 + CONTROL "The settings in the \x22Individual Directory Overrides\x22 group will override the settings in the \x22Base Directory Override\x22 group. To delete an override, delete the text from the text edit control. Note that the directory the configuration file is in can not be overridden. Also, no override directories as specified here will be created; they must already exist.",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,15,3,254,50 + CONTROL "Cheats",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,21,110,235,32 + CONTROL "",100,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,30,122,150,12 + CONTROL "Browse...",200,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,191,121,56,14 + CONTROL "Miscellaneous(custom game palettes)",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,21,145,235,32 + CONTROL "",101,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,30,157,150,12 + CONTROL "Browse...",201,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,191,156,56,14 + CONTROL "Nonvolatile Game Data(battery-backed RAM)",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,21,180,235,32 + CONTROL "",102,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,30,192,150,12 + CONTROL "Browse...",202,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,191,191,56,14 + CONTROL "Save States",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,21,215,235,32 + CONTROL "",103,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,30,227,150,12 + CONTROL "Browse...",203,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,191,226,56,14 + CONTROL "Screen Snapshots",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,21,250,235,42 + CONTROL "",104,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,30,262,150,12 + CONTROL "Browse...",204,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,191,261,56,14 + CONTROL "Individual Directory Overrides",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,11,96,257,205 + CONTROL "Base Directory Override",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,11,57,235,32 + CONTROL "",105,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,20,71,150,12 + CONTROL "Browse...",205,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,182,70,56,14 + CONTROL "Save screen snapshots as \x22-.png\x22.",300,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,36,277,198,12 +END + +DWBDIALOG DIALOG 33, 99, 250, 56 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "DWB!" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Text",100,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,7,9,237,8 + CONTROL "Clear",200,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,64,32,50,14 + CONTROL "Close",201,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,188,33,50,14 +END + +FKBDIALOG DIALOG 13, 72, 402, 194 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "Family Keyboard Configuration" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Close",1,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,320,170,56,14 + CONTROL "Remember to push the \x22Scroll Lock\x22 key during emulation to enable Family Keyboard input.",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,18,6,370,12 + CONTROL "",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,11,22,380,133 + CONTROL "F1",300,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,22,43,32,12 + CONTROL "1",308,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,30,59,16,12 + CONTROL "F2",301,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,60,43,32,12 + CONTROL "F3",302,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,98,43,32,12 + CONTROL "F4",303,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,136,43,32,12 + CONTROL "F5",304,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,174,43,32,12 + CONTROL "F6",305,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,212,43,32,12 + CONTROL "F7",306,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,250,43,32,12 + CONTROL "F8",307,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,288,43,32,12 + CONTROL "2",309,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,49,59,16,12 + CONTROL "3",310,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,68,59,16,12 + CONTROL "4",311,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,87,59,16,12 + CONTROL "5",312,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,106,59,16,12 + CONTROL "6",313,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,125,59,16,12 + CONTROL "7",314,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,144,59,16,12 + CONTROL "8",315,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,163,59,16,12 + CONTROL "9",316,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,182,59,16,12 + CONTROL "0",317,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,201,59,16,12 + CONTROL "-",318,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,220,59,16,12 + CONTROL "^",319,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,239,59,16,12 + CONTROL "\\",320,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,258,59,16,12 + CONTROL "STP",321,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,277,59,16,12 + CONTROL "ESC",322,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,22,75,16,12 + CONTROL "Q",323,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,41,75,16,12 + CONTROL "W",324,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,60,75,16,12 + CONTROL "E",325,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,79,75,16,12 + CONTROL "R",326,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,98,75,16,12 + CONTROL "T",327,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,117,75,16,12 + CONTROL "Y",328,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,136,75,16,12 + CONTROL "U",329,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,155,75,16,12 + CONTROL "I",330,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,174,75,16,12 + CONTROL "O",331,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,193,75,16,12 + CONTROL "P",332,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,212,75,16,12 + CONTROL "@",333,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,231,75,16,12 + CONTROL "[",334,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,250,75,16,12 + CONTROL "RETURN",335,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,272,75,32,12 + CONTROL "CTR",336,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,26,91,16,12 + CONTROL "A",337,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,45,91,16,12 + CONTROL "S",338,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,64,91,16,12 + CONTROL "D",339,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,83,91,16,12 + CONTROL "F",340,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,102,91,16,12 + CONTROL "G",341,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,121,91,16,12 + CONTROL "H",342,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,140,91,16,12 + CONTROL "J",343,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,159,91,16,12 + CONTROL "K",344,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,178,91,16,12 + CONTROL "L",345,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,197,91,16,12 + CONTROL ";",346,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,216,91,16,12 + CONTROL ":",347,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,235,91,16,12 + CONTROL "]",348,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,254,91,16,12 + CONTROL "KANA",349,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,273,91,16,12 + CONTROL "Z",351,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,55,107,16,12 + CONTROL "X",352,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,74,107,16,12 + CONTROL "C",353,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,93,107,16,12 + CONTROL "V",354,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,112,107,16,12 + CONTROL "B",355,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,131,107,16,12 + CONTROL "N",356,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,150,107,16,12 + CONTROL "M",357,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,169,107,16,12 + CONTROL ",",358,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,188,107,16,12 + CONTROL ".",359,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,207,107,16,12 + CONTROL "/",360,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,226,107,16,12 + CONTROL "",361,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,245,107,16,12 + CONTROL "SHIFT",350,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,19,107,32,12 + CONTROL "SHIFT",362,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,265,107,32,12 + CONTROL "GRPH",363,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,74,123,16,12 + CONTROL "SPACE",364,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,93,123,149,12 + CONTROL "CLR",365,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,316,67,16,12 + CONTROL "INS",366,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,335,67,16,12 + CONTROL "DEL",367,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,354,67,16,12 + CONTROL "UP",368,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,327,83,32,12 + CONTROL "LEFT",369,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,310,99,32,12 + CONTROL "RIGHT",370,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,346,99,32,12 + CONTROL "DOWN",371,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,327,115,32,12 +END + +GAMEPADDIALOG DIALOG 4, 109, 243, 220 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "Gamepad Configuration" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Close",1,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,173,196,56,14 + CONTROL "",100,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,4,8,232,82 + CONTROL "Up",304,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,35,27,24,12 + CONTROL "Left",306,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,9,45,25,12 + CONTROL "Right",307,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,60,45,24,12 + CONTROL "Down",305,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,35,64,24,12 + CONTROL "Select",302,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,91,45,26,12 + CONTROL "Start",303,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,126,45,26,12 + CONTROL "B",301,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,169,45,16,12 + CONTROL "A",300,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,195,45,16,12 + CONTROL "Turbo B",309,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,154,29,32,12 + CONTROL "Turbo A",308,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,195,29,32,12 + CONTROL "",101,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,4,101,232,82 + CONTROL "Up",314,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,35,120,24,12 + CONTROL "Left",316,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,9,138,25,12 + CONTROL "Right",317,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,60,138,24,12 + CONTROL "Down",315,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,35,157,24,12 + CONTROL "Select",312,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,91,138,26,12 + CONTROL "Start",313,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,126,138,26,12 + CONTROL "B",311,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,169,138,16,12 + CONTROL "A",310,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,195,138,16,12 + CONTROL "Turbo B",319,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,154,122,32,12 + CONTROL "Turbo A",318,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,195,122,32,12 + CONTROL "Disable four-score emulation.",400,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_VISIBLE ,9,193,106,12 +END + +GUICONFIG DIALOG 16, 123, 216, 103 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "GUI Configuration" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Close",1,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,153,83,56,14 + CONTROL "Load \x22File Open\x22 dialog when FCE Ultra starts.",102,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,16,10,198,12 + CONTROL "Automatically hide menu on game load.",104,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,16,26,198,12 + CONTROL "Ask confirmation on exit attempt.",110,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,16,42,146,12 + CONTROL "Disable screen saver while game is loaded.",111,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,16,58,193,12 +END + +INPUTCONFIG DIALOG 122, 105, 350, 222 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "Input Configuration" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Close",1,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,266,194,56,14 + CONTROL "Select the device you want to be enabled on input ports 1 and 2, and the Famicom expansion port. You may configure the device listed above each drop-down list by pressing \x22Configure\x22, if applicable. The device currently being emulated on the each port is listed above the drop down list; loading certain games will override your settings, but only temporarily. If you select a device to be on the emulated Famicom Expansion Port, you should probably have emulated gamepads on the emulated NES-style input ports.",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,15,8,320,55 + CONTROL "Port 1:",102,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_VISIBLE ,18,80,152,55 + CONTROL "",104,"COMBOBOX",CBS_DROPDOWNLIST |WS_CHILD |WS_VSCROLL |WS_TABSTOP |WS_VISIBLE ,24,109,71,60 + CONTROL "Configure",106,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,106,95,56,14 + CONTROL "Port 2:",103,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_VISIBLE ,178,80,152,55 + CONTROL "",105,"COMBOBOX",CBS_DROPDOWNLIST |WS_CHILD |WS_VSCROLL |WS_TABSTOP |WS_VISIBLE ,184,109,71,60 + CONTROL "Configure",107,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,266,95,56,14 + CONTROL "NES-style Input Ports",108,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_VISIBLE ,10,66,328,79 + CONTROL "Famicom Expansion Port:",109,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_VISIBLE ,41,153,165,55 + CONTROL "",110,"COMBOBOX",CBS_DROPDOWNLIST |WS_CHILD |WS_VSCROLL |WS_TABSTOP |WS_VISIBLE ,47,182,84,60 + CONTROL "Configure",111,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,142,168,56,14 + CONTROL "",65535,"STATIC",SS_BLACKFRAME |WS_CHILD |WS_VISIBLE ,24,93,71,12 + CONTROL "",65535,"STATIC",SS_BLACKFRAME |WS_CHILD |WS_VISIBLE ,184,93,71,12 + CONTROL "",65535,"STATIC",SS_BLACKFRAME |WS_CHILD |WS_VISIBLE ,47,166,84,12 + CONTROL "",200,"STATIC",SS_CENTER |WS_CHILD |WS_GROUP |WS_VISIBLE ,27,94,65,10 + CONTROL "",201,"STATIC",SS_CENTER |WS_CHILD |WS_GROUP |WS_VISIBLE ,187,94,65,10 + CONTROL "",202,"STATIC",SS_CENTER |WS_CHILD |WS_GROUP |WS_VISIBLE ,50,167,78,10 +END + +MAHJONGDIALOG DIALOG 26, 106, 216, 91 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "mahjong" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Close",1,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,110,73,56,14 + CONTROL "",302,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,8,8,200,55 + CONTROL "1",300,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,72,40,16,12 + CONTROL "2",301,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,94,40,16,12 + CONTROL "3",302,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,116,40,16,12 + CONTROL "4",303,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,138,40,16,12 + CONTROL "5",304,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,160,40,16,12 + CONTROL "6",305,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,182,40,16,12 +END + +MEMVIEW DIALOG 48, 71, 263, 237 +STYLE DS_SETFONT |DS_MODALFRAME |WS_OVERLAPPED |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "Memory Viewer" +FONT 8, "Fixedsys" +BEGIN + CONTROL "Close",1,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,200,218,56,14 + CONTROL "",100,"EDIT",ES_READONLY |ES_MULTILINE |ES_CENTER |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,6,4,237,132 + CONTROL "",200,"EDIT",ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,14,167,19,12 + CONTROL "",201,"EDIT",ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,42,167,14,12 + CONTROL "Poke Me!",202,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,68,156,42,14 + CONTROL "Memory Poke",102,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,6,146,111,48 + CONTROL "",103,"SCROLLBAR",SBS_VERT |WS_CHILD |WS_VISIBLE ,244,4,9,132 + CONTROL "Memory File Dump",104,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,118,146,143,33 + CONTROL "",210,"EDIT",ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,133,160,19,12 + CONTROL "",211,"EDIT",ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,189,160,19,12 + CONTROL "through",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,156,162,29,8 + CONTROL "Dump Me!",212,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,213,159,42,14 + CONTROL "Memory File Load",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,6,200,102,33 + CONTROL "",220,"EDIT",ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,21,213,19,12 + CONTROL "Load!",222,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,56,211,42,14 + CONTROL "HL Store",203,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,68,176,42,14 + CONTROL "Video Memory File Dump",105,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,118,181,143,33 + CONTROL "",230,"EDIT",ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,134,194,19,12 + CONTROL "",231,"EDIT",ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,190,194,19,12 + CONTROL "through",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,156,194,29,8 + CONTROL "Dump Me!",232,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,212,192,42,14 +END + +MESSAGELOG DIALOG 33, 38, 370, 184 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "Message Log" +FONT 9, "Terminal" +BEGIN + CONTROL "Close",1,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,299,157,56,14 + CONTROL "",100,"EDIT",ES_READONLY |ES_AUTOVSCROLL |ES_MULTILINE |ES_LEFT |WS_CHILD |WS_BORDER |WS_VSCROLL |WS_TABSTOP |WS_VISIBLE ,19,15,339,130 +END + +NETMOO DIALOG 44, 59, 350, 202 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_OVERLAPPED |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "Network Play" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "",102,"EDIT",ES_WANTRETURN |ES_OEMCONVERT |ES_AUTOHSCROLL |ES_AUTOVSCROLL |ES_MULTILINE |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,0,129,350,12 + CONTROL "",101,"EDIT",ES_READONLY |ES_AUTOVSCROLL |ES_MULTILINE |ES_LEFT |WS_CHILD |WS_BORDER |WS_VSCROLL |WS_TABSTOP |WS_VISIBLE ,0,0,350,130 + CONTROL "Remote Host:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,3,157,48,8 + CONTROL "",200,"EDIT",ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,54,155,90,12 + CONTROL "",201,"EDIT",ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,145,155,27,12 + CONTROL "Settings",100,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,0,145,350,55 + CONTROL "Connect",250,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,290,153,56,14 + CONTROL "",203,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,276,172,70,12 + CONTROL "Local Players:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,181,157,46,8 + CONTROL "Nickname:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,232,175,40,8 + CONTROL "",204,"COMBOBOX",CBS_DROPDOWNLIST |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,232,155,28,51 + CONTROL "Game Key:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,121,174,39,8 + CONTROL "",205,"EDIT",ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,163,172,67,12 + CONTROL "Password:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,13,174,37,8 + CONTROL "",206,"EDIT",ES_PASSWORD |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,54,172,67,12 +END + +NETPLAYCONFIG DIALOG 33, 49, 230, 200 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "Netplay Configuration" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Close",1,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,163,173,56,14 + CONTROL "Network play will commence when a new game is loaded.",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,10,5,211,20 + CONTROL "",101,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,66,66,135,12 + CONTROL "Client",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_VISIBLE ,9,34,198,66 + CONTROL "",100,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,97,47,29,12 + CONTROL "Enable network play.",300,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,12,170,102,12 + CONTROL "Server",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_VISIBLE ,9,110,198,52 + CONTROL "Listen on TCP port:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,15,125,68,8 + CONTROL "",200,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,85,124,29,12 + CONTROL "Local UDP port:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,16,49,62,8 + CONTROL "Remote host:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,16,68,50,8 + CONTROL "Remote TCP Port:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,101,84,61,8 + CONTROL "",102,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,163,82,29,12 + CONTROL "",302,"BUTTON",BS_AUTORADIOBUTTON |WS_CHILD |WS_VISIBLE ,5,34,9,8 + CONTROL "",301,"BUTTON",BS_AUTORADIOBUTTON |WS_CHILD |WS_VISIBLE ,5,110,9,8 +END + +PALCONFIG DIALOG 16, 81, 216, 141 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "Palette Configuration" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Close",1,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,151,122,56,14 + CONTROL "The \x22NES Palette\x22 section's options will only affect NTSC NES games. NTSC Color Emulation will override any loaded custom palette.",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,5,6,207,28 + CONTROL "NES Palette",302,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,1,37,102,81 + CONTROL "&Load Palette...",200,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,12,55,58,14 + CONTROL "&Reset to Default Palette",201,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,12,78,85,14 + CONTROL "Enabled",100,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,113,51,87,12 + CONTROL "Tint",500,"msctls_trackbar32",WS_CHILD |WS_TABSTOP |WS_VISIBLE ,111,73,91,11 + CONTROL "NTSC Color Emulation",101,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,106,37,103,81 + CONTROL "Hue",501,"msctls_trackbar32",WS_CHILD |WS_TABSTOP |WS_VISIBLE ,112,98,91,11 + CONTROL "Hue",65535,"STATIC",SS_CENTER |WS_CHILD |WS_GROUP |WS_VISIBLE ,115,88,85,8 + CONTROL "Tint",65535,"STATIC",SS_CENTER |WS_CHILD |WS_GROUP |WS_VISIBLE ,114,63,85,8 +END + +POWERPADDIALOG DIALOG 30, 123, 131, 119 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "Power Pad Configuration" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Close",1,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,34,95,56,14 + CONTROL "",302,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,8,10,114,74 + CONTROL "1",300,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,21,23,16,12 + CONTROL "2",301,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,43,23,16,12 + CONTROL "3",302,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,70,23,16,12 + CONTROL "4",303,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,91,23,16,12 + CONTROL "5",304,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,21,41,16,12 + CONTROL "6",305,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,43,41,16,12 + CONTROL "7",306,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,70,41,16,12 + CONTROL "8",307,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,91,41,16,12 + CONTROL "9",308,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,21,59,16,12 + CONTROL "10",309,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,43,59,16,12 + CONTROL "11",310,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,70,59,16,12 + CONTROL "12",311,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,91,59,16,12 +END + +PPUVIEW DIALOG 44, 38, 355, 246 +STYLE DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "PPU Viewer" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Pattern Tables",101,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,2,-1,351,192 + CONTROL "Tile:",103,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,6,168,50,10 + CONTROL "Tile:",104,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,177,168,50,10 + CONTROL "",201,"msctls_trackbar32",WS_CHILD |WS_TABSTOP |WS_VISIBLE ,227,178,106,11 + CONTROL "Refresh: More",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,177,178,50,10 + CONTROL "Less",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,334,178,18,10 + CONTROL "Palettes",105,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,2,192,351,53 + CONTROL "Display on scanline:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,6,178,65,10 + CONTROL "",102,"EDIT",ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,72,176,27,12 +END + +QUIZKINGDIALOG DIALOG 30, 123, 160, 74 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "quiz king" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Close",1,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,54,56,56,14 + CONTROL "Buzzers",302,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,8,7,144,39 + CONTROL "1",300,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,16,23,16,12 + CONTROL "2",301,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,38,23,16,12 + CONTROL "3",302,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,60,23,16,12 + CONTROL "4",303,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,82,23,16,12 + CONTROL "5",304,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,104,23,16,12 + CONTROL "6",305,"BUTTON",BS_PUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,126,23,16,12 +END + +SOUNDCONFIG DIALOG 8, 95, 371, 152 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "Sound Configuration" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Close",1,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,304,132,56,14 + CONTROL "Set various sound options here. The default sound buffering length is rather conservative. Lower settings are probably possible and will reduce sound latency.",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,12,4,350,19 + CONTROL "Output/Output Format:",302,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,12,30,130,93 + CONTROL "Sound enabled.",126,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,20,48,117,12 + CONTROL "Force 8-bit sound.",122,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,20,63,117,11 + CONTROL "Rate:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,20,106,34,10 + CONTROL "Hz",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,118,107,15,9 + CONTROL "Buffering:",127,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,154,30,126,97 + CONTROL "Use secondary sound buffer...",123,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,162,44,112,12 + CONTROL "...with global focus.",124,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,170,56,100,12 + CONTROL "Length of Sound to Buffer:",65535,"STATIC",SS_CENTER |WS_CHILD |WS_GROUP |WS_VISIBLE ,164,73,107,8 + CONTROL "",128,"msctls_trackbar32",WS_CHILD |WS_TABSTOP |WS_VISIBLE ,164,98,107,13 + CONTROL "Volume",125,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,298,29,58,86 + CONTROL "",500,"msctls_trackbar32",WS_CHILD |WS_TABSTOP |WS_VISIBLE |0xB,312,38,28,75 + CONTROL "15 ms",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,161,112,20,8 + CONTROL "200 ms",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,252,112,25,8 + CONTROL "ms",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,217,86,19,8 + CONTROL "",666,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,195,86,20,8 + CONTROL "",200,"COMBOBOX",CBS_DROPDOWNLIST |WS_CHILD |WS_VSCROLL |WS_TABSTOP |WS_VISIBLE ,59,104,53,46 + CONTROL "",129,"COMBOBOX",CBS_DROPDOWNLIST |WS_CHILD |WS_VSCROLL |WS_TABSTOP |WS_VISIBLE ,59,79,77,46 + CONTROL "Quality:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,20,80,35,10 +END + +SUBORKBDIALOG DIALOGEX 13, 72, 478, 171 +STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU +CAPTION "Subor Keyboard Configuration" +FONT 8, "MS Sans Serif", 0, 0, 0x0 +BEGIN + DEFPUSHBUTTON "Close",1,405,151,56,14 + LTEXT "Remember to push the ""Scroll Lock"" key during emulation to enable Keyboard input.",-1,18,6,370,12 + GROUPBOX "",-1,9,22,461,123,WS_GROUP + PUSHBUTTON "Esc",300,20,36,16,12 + PUSHBUTTON "F1",301,58,37,16,12 + PUSHBUTTON "F2",302,78,37,16,12 + PUSHBUTTON "F3",303,98,37,16,12 + PUSHBUTTON "F4",304,118,37,16,12 + PUSHBUTTON "F5",305,143,37,16,12 + PUSHBUTTON "F6",306,163,37,16,12 + PUSHBUTTON "F7",307,183,37,16,12 + PUSHBUTTON "F8",308,203,37,16,12 + PUSHBUTTON "F9",309,229,37,16,12 + PUSHBUTTON "F10",310,249,37,16,12 + PUSHBUTTON "F11",311,268,37,16,12 + PUSHBUTTON "F12",312,288,37,16,12 + PUSHBUTTON "Pause",313,318,36,16,12 + PUSHBUTTON "`",314,20,60,16,12 + PUSHBUTTON "1",315,39,60,16,12 + PUSHBUTTON "2",316,58,60,16,12 + PUSHBUTTON "3",317,77,60,16,12 + PUSHBUTTON "4",318,96,60,16,12 + PUSHBUTTON "5",319,115,60,16,12 + PUSHBUTTON "6",320,134,60,16,12 + PUSHBUTTON "7",321,153,60,16,12 + PUSHBUTTON "8",322,172,60,16,12 + PUSHBUTTON "9",323,191,60,16,12 + PUSHBUTTON "0",324,210,60,16,12 + PUSHBUTTON "-",325,229,60,16,12 + PUSHBUTTON "=",326,248,60,16,12 + PUSHBUTTON "BS",327,286,60,16,12 + PUSHBUTTON "Ins",328,318,59,16,12 + PUSHBUTTON "Home",329,337,59,16,12 + PUSHBUTTON "NL",330,385,59,16,12 + PUSHBUTTON "/",331,405,59,16,12 + PUSHBUTTON "*",332,425,59,16,12 + PUSHBUTTON "-",333,444,59,16,12 + PUSHBUTTON "PUp",334,357,59,16,12 + PUSHBUTTON "TAB",335,20,76,24,12 + PUSHBUTTON "Q",336,47,76,16,12 + PUSHBUTTON "W",337,66,76,16,12 + PUSHBUTTON "E",338,85,76,16,12 + PUSHBUTTON "R",339,104,76,16,12 + PUSHBUTTON "T",340,123,76,16,12 + PUSHBUTTON "Y",341,142,76,16,12 + PUSHBUTTON "U",342,161,76,16,12 + PUSHBUTTON "I",343,180,76,16,12 + PUSHBUTTON "O",344,199,76,16,12 + PUSHBUTTON "P",345,218,76,16,12 + PUSHBUTTON "[",346,237,76,16,12 + PUSHBUTTON "]",347,256,76,16,12 + PUSHBUTTON "Enter",348,274,76,28,29 + PUSHBUTTON "Del",349,318,75,16,12 + PUSHBUTTON "End",350,338,75,16,12 + PUSHBUTTON "PDn",351,357,75,16,12 + PUSHBUTTON "7",352,385,75,16,12 + PUSHBUTTON "8",353,405,75,16,12 + PUSHBUTTON "9",354,425,75,16,12 + PUSHBUTTON "+",355,444,75,16,28 + PUSHBUTTON "CL",356,20,92,27,12 + PUSHBUTTON "A",357,52,92,16,12 + PUSHBUTTON "S",358,71,92,16,12 + PUSHBUTTON "D",359,90,92,16,12 + PUSHBUTTON "F",360,109,92,16,12 + PUSHBUTTON "G",361,128,92,16,12 + PUSHBUTTON "H",362,147,92,16,12 + PUSHBUTTON "J",363,166,92,16,12 + PUSHBUTTON "K",364,185,92,16,12 + PUSHBUTTON "L",365,204,92,16,12 + PUSHBUTTON ";",366,223,92,16,12 + PUSHBUTTON "'",367,242,92,16,12 + PUSHBUTTON "4",368,385,91,16,12 + PUSHBUTTON "5",369,405,91,16,12 + PUSHBUTTON "6",370,425,91,16,12 + PUSHBUTTON "SHIFT",371,20,108,37,12 + PUSHBUTTON "Z",372,62,108,16,12 + PUSHBUTTON "X",373,81,108,16,12 + PUSHBUTTON "C",374,100,108,16,12 + PUSHBUTTON "V",375,119,108,16,12 + PUSHBUTTON "B",376,138,108,16,12 + PUSHBUTTON "N",377,157,108,16,12 + PUSHBUTTON "M",378,176,108,16,12 + PUSHBUTTON ",",379,195,108,16,12 + PUSHBUTTON ".",380,214,108,16,12 + PUSHBUTTON "/",381,233,108,16,12 + PUSHBUTTON "\\",382,267,60,16,12 + PUSHBUTTON "Up",383,337,108,16,12 + PUSHBUTTON "1",384,385,107,16,12 + PUSHBUTTON "2",385,405,107,16,12 + PUSHBUTTON "3",386,425,107,16,12 + PUSHBUTTON "CTRL",387,20,123,28,12 + PUSHBUTTON "ALT",388,66,123,27,12 + PUSHBUTTON "SPACE",389,96,123,130,12 + PUSHBUTTON "Left",390,318,123,16,12 + PUSHBUTTON "Dn",391,337,123,16,12 + PUSHBUTTON "Right",392,357,123,16,12 + PUSHBUTTON "0",393,386,123,35,12 + PUSHBUTTON ".",394,425,123,16,12 + PUSHBUTTON "SHIFT",395,254,108,48,12 + PUSHBUTTON "ALT",396,229,123,29,12 + PUSHBUTTON "CTRL",397,274,123,28,12 + PUSHBUTTON "Break",398,337,36,16,12 + PUSHBUTTON "Reset",399,357,36,16,12 + PUSHBUTTON "Enter",400,444,107,16,28 +END + +TIMINGCONFIG DIALOG 23, 157, 198, 78 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "Timing Configuration" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "Close",1,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,126,54,56,14 + CONTROL "Disable speed throttling used when sound is disabled.",101,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,9,12,198,12 + CONTROL "Set high-priority thread.",105,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,9,28,146,12 +END + +VIDEOCONFIG DIALOG 16, 76, 378, 296 +STYLE DS_3DLOOK |DS_SETFONT |DS_MODALFRAME |WS_POPUP |WS_VISIBLE |WS_SYSMENU |WS_CAPTION +CAPTION "Video Configuration" +FONT 8, "MS Sans Serif" +BEGIN + CONTROL "For the custom video mode settings to be in effect, the \x22Custom\x22 video mode needs to be selected. If you select a sync method, and sound is disabled, you may want to disable speed throttling(in the \x22Timing\x22 window). If you use \x22wait for vblank\x22, you should use the \x22lazy\x22 form.\x0AAllowing more than 8 sprites per scanline can cause graphics corruption in some games, including \x22Solstice\x22.",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,11,4,347,43 + CONTROL "Full Screen Settings",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,13,50,346,112 + CONTROL "Full Screen",101,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,23,64,60,12 + CONTROL "Enter full screen mode after file is loaded.",102,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,23,79,141,12 + CONTROL "Sync Method:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,19,97,52,10 + CONTROL "",105,"COMBOBOX",CBS_DROPDOWNLIST |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,76,94,89,50 + CONTROL "Video Mode:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,19,113,42,10 + CONTROL "",100,"COMBOBOX",CBS_DROPDOWNLIST |WS_CHILD |WS_VSCROLL |WS_TABSTOP |WS_VISIBLE ,64,112,101,52 + CONTROL "Disable hardware acceleration.",131,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,20,142,147,12 + CONTROL "Custom Video Mode",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,169,60,190,99 + CONTROL "Mode:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,177,73,25,8 + CONTROL "",200,"EDIT",ES_RIGHT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,205,71,27,12 + CONTROL "by",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,236,73,11,8 + CONTROL "",201,"EDIT",ES_RIGHT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,249,71,27,12 + CONTROL "@",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,280,73,12,8 + CONTROL "",202,"COMBOBOX",CBS_DROPDOWNLIST |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,292,70,35,60 + CONTROL "bpp",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,332,72,24,8 + CONTROL "Image Size Transform",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,175,97,170,60 + CONTROL "Special scaler:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,183,112,60,8 + CONTROL "",304,"COMBOBOX",CBS_DROPDOWNLIST |WS_CHILD |WS_VSCROLL |WS_TABSTOP |WS_VISIBLE ,286,109,49,46 + CONTROL "Scale dimensions by:",300,"BUTTON",BS_AUTORADIOBUTTON |WS_CHILD |WS_VISIBLE ,184,127,85,12 + CONTROL "Stretch to Fill Screen",301,"BUTTON",BS_AUTORADIOBUTTON |WS_CHILD |WS_VISIBLE ,184,142,88,12 + CONTROL "X:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,273,130,10,8 + CONTROL "",302,"EDIT",ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,283,127,20,12 + CONTROL "Y:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,307,130,11,8 + CONTROL "",303,"EDIT",ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,317,127,20,12 + CONTROL "Windowed Settings",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,13,165,167,118 + CONTROL "Size Multiplier:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,18,192,60,8 + CONTROL "X:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,74,192,11,8 + CONTROL "Y:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,126,192,11,8 + CONTROL "",400,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,89,190,35,12 + CONTROL "",401,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,141,190,35,12 + CONTROL "Force integral scaling factors.",402,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,20,203,147,12 + CONTROL "Force aspect ratio correction.",403,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,20,217,147,12 + CONTROL "Sync Method:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,19,250,60,8 + CONTROL "",104,"COMBOBOX",CBS_DROPDOWNLIST |WS_CHILD |WS_VSCROLL |WS_TABSTOP |WS_VISIBLE ,83,248,88,47 + CONTROL "Disable hardware acceleration.",130,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,20,264,147,12 + CONTROL "Drawing Area",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,184,165,172,74 + CONTROL "First Line:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,201,189,39,8 + CONTROL "Last Line:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,201,209,43,8 + CONTROL "NTSC",65535,"STATIC",SS_CENTER |WS_CHILD |WS_GROUP |WS_VISIBLE ,244,176,26,8 + CONTROL "PAL",65535,"STATIC",SS_CENTER |WS_CHILD |WS_GROUP |WS_VISIBLE ,295,176,26,8 + CONTROL "",500,"EDIT",ES_RIGHT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,246,188,27,12 + CONTROL "",501,"EDIT",ES_RIGHT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,246,207,27,12 + CONTROL "",502,"EDIT",ES_RIGHT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,296,188,27,12 + CONTROL "",503,"EDIT",ES_RIGHT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,296,207,27,12 + CONTROL "Clip left and right sides(8 columns on each).",106,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,195,224,157,12 + CONTROL "Close",1,"BUTTON",BS_DEFPUSHBUTTON |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,321,282,56,14 + CONTROL "Current Pixel Aspect Ratio:",65535,"STATIC",SS_RIGHT |WS_CHILD |WS_GROUP |WS_VISIBLE ,21,232,92,8 + CONTROL "",404,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,120,231,23,12 + CONTROL ":",65535,"STATIC",SS_CENTER |WS_CHILD |WS_GROUP |WS_VISIBLE ,145,233,8,8 + CONTROL "",405,"EDIT",ES_AUTOHSCROLL |ES_LEFT |WS_CHILD |WS_BORDER |WS_TABSTOP |WS_VISIBLE ,154,231,22,12 + CONTROL "Allow more than 8 sprites per scanline.",600,"BUTTON",BS_AUTOCHECKBOX |WS_CHILD |WS_TABSTOP |WS_VISIBLE ,194,256,136,11 + CONTROL "Emulation",65535,"BUTTON",BS_GROUPBOX |WS_CHILD |WS_GROUP |WS_VISIBLE ,184,243,172,32 + CONTROL "Special Scaler:",65535,"STATIC",SS_LEFT |WS_CHILD |WS_GROUP |WS_VISIBLE ,18,177,60,8 + CONTROL "",406,"COMBOBOX",CBS_DROPDOWNLIST |WS_CHILD |WS_VSCROLL |WS_TABSTOP |WS_VISIBLE ,113,176,49,46 +END + diff --git a/src/drivers/win/res/EXE.ico b/src/drivers/win/res/EXE.ico new file mode 100644 index 0000000000000000000000000000000000000000..865158602718a516e6a26701433ea1b935de55ca GIT binary patch literal 8854 zcmeHLTTE0}6x|?g?FJ(sArfM^;xK|x3Z4+zqT$K#=8%a+lG4I602j2SdAFhCCHtFE&jzGf_=k@LnjV(MuNZp3~7o4PaK3CiUd2NkeW!a zUf@gNTn4{Yi+l6(ATEb|~!fh`7rWGVH3ahT1Mq znagFwb3EYyurB0;g5e32RT&Nkg2E02!)2Ai4u#9VsHzIV&2}JI9xjJB#PLudAZ_er zT-f5+CTuacAqL+9m#bQAoL`2?43Y7&gynJ#%TADE&-~?v$EXjrvKV$WTFw%RE~q4| z-!RKVVXPnh)oj_{p*CE)bQ9&ri9Q?7)(CbIr{f4W!4t=v-I#mm{Qx(Sw9<%+3V_B& z-eH7F@pzo#f5xfr>~FXq`Dps|=~P)+N%Q8-qw4BvTC`{pty;B;>gwuf)22-%u92NP zchc_NyX8Hkt*wm?A3jXSjvb?uCr`@j=fZ^xbp85ux_9p$_4fAC%aY z9T=q!^z{!=+rE9cjvK*<-y`vpgx@8(!zg~DMolYB(-B&Vsij>JEKD)4| zxZF})Q-q!C$E`q!-|zF|;lu9tPn_t76cqUVi0Au#le|T4caiYsQ@*D zTfVc{S6W(HTu-ac8lZoJH`t zi%Lo`fs`V*4fXg93l-<12_6qG$L+>rkma*Pqqq}i5P?a4o*4OkRy=bgo;4EB9vMm* z3y*bRtOFmZ1H-=0X0FecN{m!>8#F8bBAzsb;L`Hb#U18(4clSlJ5tGD+=2l~DxT+X zpa4Z9b@=qS-EL1CmpO7323I2AE_m}`Nxwh{RXS|=*&>?+h&75Dgh*Y$?f6+V;vzrS zfg(@_bb;36($19_1O@+)e7St&3l0%udywCV=Ngg}N0NmM=7Td=mY%Ejzz@b{%sl*u zaf{-I)W?0%QA7KeAuig6&gy@8aPj*2@ai$43w|^}o?$|@jH~l6ecXUq@4Ek2?}J|J zBH4?FzuMYbyx4u4LJ$G~FvicEITLSj-QC@%PMyLlqe?rmvl!6X1I zS+WFpjCj?(b?esa*RN3p#$CI1eIo_0z3<+=Lov^vKfitZc0)r0S_Jadt5;vXd>Qrk z^z=M_{1{)_@B)18+BKwOIS(E@fO6%^6~Me+FYs&DtO5STix*FxJOLE|;DkJS^ayw; z7_VNvx_0f_!oot}*R5N3{`~nHH*Vm2-S+LY^ypE%bK@}*CY%UiQ8<{)zj5P6 zEE6C4@E$*R?p%ytOM$|I(18O70Au|6_3MuxKfYtf4)LYVO7N`^030~R?lH;TdHx!!71R4Eke_kpz6Sqi36cB2iWC6<-pC1tea zqx0*H!ifo!$25L@?HTK5LKCx^0*Vra%*c-++G9KMPwW<1(j0dMKXA%M@W>3a* ze@y&(f4CJNJgTE<>JR*i6IG!+cyxg$jbG&=g{xKkd_>>}1|v*G%Q{A-a7cM{6HYK- zH1Pw2BaTt$X9g3GVuPZGpmT`%P3I4ye8hErMa8)~8IYzif_anq*`t{G+*W2r1?QE*pxR`9Q~e|1NBzvE_a8H2UeGE* zJY1X=TF6>`*q#KZ(>g7Pws%u U#=7nq4!`B3BX@Rx&Gj(3q}L`P3|6F^#m*Sx-ZNK=e;Btfvm z<<$%x%j?7MxK^vx-V%9zU7R)q+^ud=H~4+zHVCSaQu6xFItZ-SYn8zNp*{_}4dK@L zLxbaK@G1@#Ar-LDbj-|kJsd8K!VeF5&Y BP1FDY literal 0 HcmV?d00001 diff --git a/src/drivers/win/res/FDS.ico b/src/drivers/win/res/FDS.ico new file mode 100644 index 0000000000000000000000000000000000000000..dcfe3da00aba446de065084b6c6b800d4e286e33 GIT binary patch literal 8854 zcmeHL&2HO95FSaSnMkrNiV5JOMWsM`swkr8)?0I86ira% zA#|%z)Nc^j0eb1F$h`&FZ#d*|wM)_ZOBw_kle;@J-+a3}yCl6LYS94=1_RU{J!}y@ zA)?b$(f?`_{RkV}@ZX`QKG8Fe{i46TLv($&^qgtNFudf>-#Fb@Pg&D@fcr=>OSqMQrI){8Up$Cu8&mYCm z**=_59EV{HJ&s4iFt0!PR_f82)Z;1FXYshrJaJJ^4YZK;cJfh&ycT8 z?w`JwJe^_|U*f(kPn;vp59f(<#PjDoasHZQAy3PIt?@X4q*0WPhrIYu(@`>wrqg7a z>tT{$^3f0%^fvNc$S6JqK8(^rk`Vq*dhhE(&e93{E1mtf>x+CXUcXZEcqkY`zOJPX zWyqL9kHRPk8Bpj+`1yA^pwy#Bj}s11{TqKlxADwp;=@5}ncl`eLn10a;!2(K)k!No zDf=(*oUcw~_*pmc&^aF^pTzUZhGAZU&l2o`>-G-*Dc)BN?E-v0he{tWQ*zQYXjcth_pz39T<&83Gj*Exo|Wx3n`CziiwIoCHg zH}u)B8C_mp((%O$dh!Ra2GN5TydKid4f|rBfqe!(stg=#FM;p*o);8}PwE{K(EIf?( zt;WT}2(XJ^HW;zHcp*V)2CA_EuOVim885TYjsR}P18HXXRy5aqb?JV zKr8PeBAt+#kOmY}^HGavqwZ1#&m;6XyQto#A+wfx~a+$+3_b2Sz@Yl|FU49*; zjKnNu?JPn|y>e>x|M;5%V{@33F{sT1cf=U1Y literal 0 HcmV?d00001 diff --git a/src/drivers/win/res/NES.ico b/src/drivers/win/res/NES.ico new file mode 100644 index 0000000000000000000000000000000000000000..04f48b75fad5bb594e0b8bdabda1daa5a179a98b GIT binary patch literal 8854 zcmeHMy-wUf5T3Jr2f8ETAVi{y4njf7aDD)jGi@FtLOej~tMVKaQJ~-<+#nzlB~&R= zQbqJBoNspQ@!r{9eh$QsJhFG^_nYz9KD-N2i#jwI^f3o?@)qJCfG%@)xYpI|50 z=jm{s=v%;ck$2lf@89I|D(%Ae`*QBTN{0(Xf8P;p0uvAv;p99n`goMm@$oU8pPy5I z?}#ogE?n+vOVd>OdZx9cglj-GDlS#YmU)RCT5pF+pKN(F92WA{Fbp$!B{sA(8fEq^ z#BY5F;|-BBdmQhKwiz#%!#G^C@rSY4HGdczf0c(Kuf(XtP-yBYE>G&0a%2SlD4Df=Lz_n?2bRma~|-Wjfl4SzON81uY=Yio;P?l zkC)7!<87l~U&kzuNksBspzEAk#&cQd);u)sssG(m4D0eoIL6GoP4K5_|{Rfc^cy*2$u0!CX8SyNfJta zCv^Smr&-VB-+l0GsOdn{foI%->whWz*x$!{JVuqg=;0}q38SoM?zIN#Dw*r=_LRD; z=q)JqSdqzHXhqiW33&l(+aK3sA8Nu`2tlA`xhd(>AjZnS-v10oUgw4At z!j>L1GQt6j@G^=sc$fsI4j-NpZf7ZL1Q7d&np89x-S|?&R8$N| zHy{cRMoAo0Kb68=KR^^;c!= 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) { + 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); + + 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; + + 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]) { + 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(ppbufw, LockPtr[0], LockLen[0], LockPtr[1], LockLen[1]); + ToWritePos = (ToWritePos + curlen) % DSBufferSize; + + len -= curlen; + data = (void*)((uint8_t*)data + curlen); + if (len) + Sleep(1); + } // end while(len) loop + + + return(1); +} + +void FCEUD_WriteSoundData(int32 *Buffer, int Count) { + static int16 MBuffer[2 * 96000 / 50]; /* * 2 for safety. */ + int P; + + if (!bittage) { + for (P = 0; P < Count; P++) + *(((uint8*)MBuffer) + P) = ((int8)(Buffer[P] >> 8)) ^ 128; + RawWrite(MBuffer, Count); + } else { + for (P = 0; P < Count; P++) + MBuffer[P] = Buffer[P]; + //FCEU_printf("Pre: %d\n",RawCanWrite() / 2); + RawWrite(MBuffer, Count * 2); + //FCEU_printf("Post: %d\n",RawCanWrite() / 2); + } +} + +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); + 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 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); + } +} + +#include "wave.c" diff --git a/src/drivers/win/state.c b/src/drivers/win/state.c new file mode 100644 index 0000000..cc91f23 --- /dev/null +++ b/src/drivers/win/state.c @@ -0,0 +1,36 @@ +void SaveStateAs(void) { + const char filter[] = "FCE Ultra Save State(*.fc?)\0*.fc?\0"; + char nameo[2048]; + OPENFILENAME ofn; + + 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 LoadStateFrom(void) { + const char filter[] = "FCE Ultra Save State(*.fc?)\0*.fc?\0"; + char nameo[2048]; + OPENFILENAME ofn; + + 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/src/drivers/win/throttle.c b/src/drivers/win/throttle.c new file mode 100644 index 0000000..b9a4c04 --- /dev/null +++ b/src/drivers/win/throttle.c @@ -0,0 +1,84 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +static uint64 tmethod, tfreq; +static uint64 desiredfps; + +static void RefreshThrottleFPS(void) { + desiredfps = FCEUI_GetDesiredFPS() >> 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; + sleepy /= tfreq >> 16; + 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); +} + diff --git a/src/drivers/win/video.c b/src/drivers/win/video.c new file mode 100644 index 0000000..e72d3bc --- /dev/null +++ b/src/drivers/win/video.c @@ -0,0 +1,994 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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, 0, 0 }, { 0, 0, 0, 0 }, 0 }, //0 + { 320, 240, 8, 0, 1, 1, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0 }, //1 + { 512, 384, 8, 0, 1, 1, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0 }, //2 + { 640, 480, 8, 0, 1, 1, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0 }, //3 + { 640, 480, 8, 0, 1, 1, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0 }, //4 + { 640, 480, 8, 0, 1, 1, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0 }, //5 + { 640, 480, 8, VMDF_DXBLT, 2, 2, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0 }, //6 + { 1024, 768, 8, VMDF_DXBLT, 4, 3, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0 }, //7 + { 1280, 1024, 8, VMDF_DXBLT, 5, 4, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0 }, //8 + { 1600, 1200, 8, VMDF_DXBLT, 6, 5, { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0 }, //9 + { 800, 600, 8, VMDF_DXBLT | VMDF_STRFS, 0, 0, { 0, 0, 0, 0 }, { 0, 0, 0, 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; + +PALETTEENTRY color_palette[256]; +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) { + 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 = 1; // 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.DUMMYUNIONNAMEN(5).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((uint8*)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); + return TRUE; +} + +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[] = { "", "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)""); + SendDlgItemMessage(hwndDlg, 105, CB_ADDSTRING, 0, (LPARAM)(LPSTR)""); + + 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/src/drivers/win/wave.c b/src/drivers/win/wave.c new file mode 100644 index 0000000..eb5ba77 --- /dev/null +++ b/src/drivers/win/wave.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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/src/drivers/win/window.c b/src/drivers/win/window.c new file mode 100644 index 0000000..bb6652b --- /dev/null +++ b/src/drivers/win/window.c @@ -0,0 +1,1055 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include "state.c" // Save/Load state AS + +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); + +void ShowNetplayConsole(void); + +static HMENU fceumenu = 0; + +static int tog = 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, 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 + EnableMenuItem(fceumenu, simpled[x], MF_BYCOMMAND | (gi ? MF_ENABLED : MF_GRAYED)); + x++; + } +} + +void UpdateMenu(void) { + static int *polo[2] = { &genie, &palyo }; + static int polo2[2] = { 310, 311 }; + int x; + + for (x = 0; x < 2; 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); +} + +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) { + if (!fullscreen) { + tog ^= 1; + HideMenu(tog); + SetMainWindowStuff(); + } +} + +static void ALoad(char *nameo) { + if ((GI = FCEUI_LoadGame(nameo))) { + 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.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); + } +} + +#ifdef COPYFAMI +void CopyFamiStart(HWND hParent, char *initialdir) { + if (GI = FCEUI_CopyFamiStart()) { + FixFL(); + SetMainWindowStuff(); + RefreshThrottleFPS(); + if (eoptions & EO_HIDEMENU && !tog) + ToggleHideMenu(); + if (eoptions & EO_FSAFTERLOAD) + SetFSVideoMode(); + } else + StopSound(); + ParseGIInput(GI); + RedoMenuGI(GI); +} +#endif + +static uint32 mousex, mousey, mouseb; +void GetMouseData(uint32 *md) { + 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 vchanged = 0; + +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 = 0; + + 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; + } + 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 300: ToggleHideMenu(); break; + case 301: eoptions ^= EO_BGRUN; UpdateMenu(); break; + + case 310: genie ^= 1; FCEUI_SetGameGenie(genie); UpdateMenu(); break; + case 311: palyo ^= 1; + FCEUI_SetVidSystem(palyo); + RefreshThrottleFPS(); + UpdateMenu(); + FixFL(); + SetMainWindowStuff(); + 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 200: FCEUI_ResetNES(); break; + case 201: FCEUI_PowerNES(); break; + +#ifdef FCEUDEF_DEBUGGER + case 203: BeginDSeq(hWnd); break; +#endif + + case 204: ConfigAddCheat(hWnd); break; + case 205: DoPPUView(); break; + case 100: StopSound(); + LoadNewGamey(hWnd, 0); + break; +#ifdef COPYFAMI + case 140: StopSound(); + CopyFamiStart(hWnd, 0); + break; +#endif + case 101: DoFCEUExit(); break; + case 110: SaveStateAs(); break; + case 111: 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 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 (GI && InputType[2] == SIFC_SUBORKB && cidisabled) + break; + if (GI && InputType[2] == SIFC_PEC586KB && 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 (GI && InputType[2] == SIFC_SUBORKB && cidisabled) + break; + if (GI && InputType[2] == SIFC_PEC586KB && cidisabled) + break; + + if (fullscreen || tog) { + if (wParam == VK_MENU) + break; + } + if (wParam == VK_F10) { + 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 (InputType[2] == SIFC_SUBORKB) { + if (wParam == VK_SCROLL) { + cidisabled ^= 1; + FCEUI_DispMessage("Subor Keyboard %sabled.", cidisabled ? "en" : "dis"); + } + if (cidisabled) + break; // Hopefully this won't break DInput... + } + if (InputType[2] == SIFC_PEC586KB) { + if (wParam == VK_SCROLL) { + cidisabled ^= 1; + FCEUI_DispMessage("PEC586 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_ESCAPE: + 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; + } + 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) { + 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.lpszClassName = "FCEULTRA"; + + if (!RegisterClassEx(&winclass)) + return FALSE; + + AdjustWindowRectEx(&tmp, WS_OVERLAPPEDWINDOW, 1, 0); + + fceumenu = LoadMenu(fceu_hInstance, "FCEUMENU"); +#ifndef COPYFAMI + DeleteMenu(fceumenu, 140, MF_BYCOMMAND); +#endif + 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); +} + diff --git a/src/endian.c b/src/endian.c new file mode 100644 index 0000000..2479f25 --- /dev/null +++ b/src/endian.c @@ -0,0 +1,95 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Contains file I/O functions that write/read data */ +/* LSB first. */ + + +#include +#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/src/endian.h b/src/endian.h new file mode 100644 index 0000000..db3a7b1 --- /dev/null +++ b/src/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/src/fceu-endian.c b/src/fceu-endian.c new file mode 100644 index 0000000..8e5fbf9 --- /dev/null +++ b/src/fceu-endian.c @@ -0,0 +1,99 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Contains file I/O functions that write/read data */ +/* LSB first. */ + +#ifdef __LIBRETRO__ +#define ENDIAN_LIBRETRO +#endif + +#include +#include "memory.h" +#include "fceu-types.h" +#include "fceu-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, MEM_TYPE *fp) { + uint8 s[2]; + s[0] = b; + s[1] = b >> 8; + return((fwrite(s, 1, 2, fp) < 2) ? 0 : 2); +} + +int write32le(uint32 b, MEM_TYPE *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, MEM_TYPE *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, MEM_TYPE *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/src/fceu-endian.h b/src/fceu-endian.h new file mode 100644 index 0000000..dc908a0 --- /dev/null +++ b/src/fceu-endian.h @@ -0,0 +1,14 @@ +#ifndef FCEU_ENDIAN_H_ +#define FCEU_ENDIAN_H_ + +#include "memory.h" + +int write16le(uint16 b, MEM_TYPE *fp); +int write32le(uint32 b, MEM_TYPE *fp); +int read32le(uint32 *Bufo, MEM_TYPE *fp); +void FlipByteOrder(uint8 *src, uint32 count); + +void FCEU_en32lsb(uint8 *, uint32); +uint32 FCEU_de32lsb(uint8 *); + +#endif diff --git a/src/fceu-types.h b/src/fceu-types.h new file mode 100644 index 0000000..4f914df --- /dev/null +++ b/src/fceu-types.h @@ -0,0 +1,94 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __FCEU_TYPES +#define __FCEU_TYPES + +#include +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; + +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t 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? +#else +typedef unsigned long long uint64; +typedef long long int64; +#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/src/fceu.c b/src/fceu.c new file mode 100644 index 0000000..9254c02 --- /dev/null +++ b/src/fceu.c @@ -0,0 +1,525 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include "fceu-types.h" +#include "x6502.h" +#include "fceu.h" +#include "ppu.h" +#include "sound.h" +#include "netplay.h" +#include "general.h" +#include "fceu-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" + +uint64 timestampbase; + + +FCEUGI *GameInfo = 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 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 COPYFAMI +uint8 RAM[0x4000]; +#else +uint8 RAM[0x800]; +#endif + +uint8 PAL = 0; + +static DECLFW(BRAML) { + RAM[A] = V; +} + +static DECLFR(ARAML) { + return RAM[A]; +} + +#ifndef COPYFAMI +static DECLFW(BRAMH) { + RAM[A & 0x7FF] = V; +} + +static DECLFR(ARAMH) { + return RAM[A & 0x7FF]; +} +#endif + +static void CloseGame(void) { + if (GameInfo) { + if (FCEUnetplay) + FCEUD_NetworkClose(); + if (GameInfo->name) { + free(GameInfo->name); + GameInfo->name = 0; + } + if (GameInfo->type != GIT_NSF) + FCEU_FlushGameCheats(0, 0); + GameInterface(GI_CLOSE); + ResetExState(0, 0); + FCEU_CloseGenie(); + free(GameInfo); + GameInfo = 0; + } +} + +void ResetGameLoaded(void) { + if (GameInfo) CloseGame(); + GameStateRestore = NULL; + PPU_hook = NULL; + GameHBIRQHook = NULL; + if (GameExpSound.Kill) + GameExpSound.Kill(); + memset(&GameExpSound, 0, sizeof(GameExpSound)); + MapIRQHook = NULL; + MMC5Hack = 0; + PEC586Hack = 0; + PAL &= 1; + pale = 0; +} + +int UNIFLoad(const char *name, FCEUFILE *fp); +int iNESLoad(const char *name, FCEUFILE *fp); +int FDSLoad(const char *name, FCEUFILE *fp); +int NSFLoad(FCEUFILE *fp); + +FCEUGI *FCEUI_LoadGame(const char *name) { + FCEUFILE *fp; + char *ipsfn; + + ResetGameLoaded(); + + GameInfo = malloc(sizeof(FCEUGI)); + memset(GameInfo, 0, sizeof(FCEUGI)); + + GameInfo->soundchan = 0; + GameInfo->soundrate = 0; + GameInfo->name = 0; + GameInfo->type = GIT_CART; + GameInfo->vidsys = GIV_USER; + GameInfo->input[0] = GameInfo->input[1] = -1; + GameInfo->inputfc = -1; + GameInfo->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)) + 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."); + FCEU_fclose(fp); + return 0; + + endlseq: + FCEU_fclose(fp); + + FCEU_ResetVidSys(); + if (GameInfo->type != GIT_NSF) + if (FSettings.GameGenie) + FCEU_OpenGenie(); + + PowerNES(); + FCEUSS_CheckStates(); + FCEUMOV_CheckMovies(); + + if (GameInfo->type != GIT_NSF) { + FCEU_LoadGamePalette(); + FCEU_LoadGameCheats(0); + } + + FCEU_ResetPalette(); + FCEU_ResetMessages(); // Save state, status messages, etc. + + return(GameInfo); +} + +int CopyFamiLoad(void); + +FCEUGI *FCEUI_CopyFamiStart(void) { + ResetGameLoaded(); + + GameInfo = malloc(sizeof(FCEUGI)); + memset(GameInfo, 0, sizeof(FCEUGI)); + + GameInfo->soundchan = 0; + GameInfo->soundrate = 0; + GameInfo->name = "copyfami"; + GameInfo->type = GIT_CART; + GameInfo->vidsys = GIV_USER; + GameInfo->input[0] = GameInfo->input[1] = -1; + GameInfo->inputfc = -1; + GameInfo->cspecial = 0; + + FCEU_printf("Starting CopyFamicom...\n\n"); + + if (!CopyFamiLoad()) { + FCEU_PrintError("An error occurred while starting CopyFamicom."); + return 0; + } + + FCEU_ResetVidSys(); + if (GameInfo->type != GIT_NSF) + if (FSettings.GameGenie) + FCEU_OpenGenie(); + + PowerNES(); + FCEUSS_CheckStates(); + FCEUMOV_CheckMovies(); + + if (GameInfo->type != GIT_NSF) { + FCEU_LoadGamePalette(); + FCEU_LoadGameCheats(0); + } + + FCEU_ResetPalette(); + FCEU_ResetMessages(); // Save state, status messages, etc. + + return(GameInfo); +} + +int FCEUI_Initialize(void) { + 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(); +} + +void FCEUI_Emulate(uint8 **pXBuf, int32 **SoundBuf, int32 *SoundBufSize, int skip) { + int r, ssize; + + FCEU_UpdateInput(); + if (geniestage != 1) FCEU_ApplyPeriodicCheats(); + r = FCEUPPU_Loop(skip); + + ssize = FlushEmulateSound(); + + timestampbase += timestamp; + + timestamp = 0; + + *pXBuf = skip ? 0 : XBuf; + *SoundBuf = WaveFinal; + *SoundBufSize = ssize; +} + +void FCEUI_CloseGame(void) { + CloseGame(); +} + +void ResetNES(void) { + FCEUMOV_AddCommand(FCEUNPCMD_RESET); + if (!GameInfo) return; + GameInterface(GI_RESETM2); + FCEUSND_Reset(); + FCEUPPU_Reset(); + X6502_Reset(); +} + +void FCEU_MemoryRand(uint8 *ptr, uint32 size) { + int x = 0; + while (size) { +// *ptr = (x & 4) ? 0xFF : 0x00; // Huang Di DEBUG MODE enabled by default + // Cybernoid NO MUSIC by default +// *ptr = (x & 4) ? 0x7F : 0x00; // Huang Di DEBUG MODE enabled by default + // Minna no Taabou no Nakayoshi Daisakusen DOESN'T BOOT + // Cybernoid NO MUSIC by default +// *ptr = (x & 1) ? 0x55 : 0xAA; // F-15 Sity War HISCORE is screwed... + // 1942 SCORE/HISCORE is screwed... + *ptr = 0xFF; + x++; + size--; + ptr++; + } +} + +void hand(X6502 *X, int type, uint32 A) { +} + +void PowerNES(void) { + FCEUMOV_AddCommand(FCEUNPCMD_POWER); + if (!GameInfo) return; + + FCEU_CheatResetRAM(); + FCEU_CheatAddRAM(2, 0, RAM); + + FCEU_GeniePower(); + +#ifndef COPYFAMI + FCEU_MemoryRand(RAM, 0x800); +#endif + + SetReadHandler(0x0000, 0xFFFF, ANull); + SetWriteHandler(0x0000, 0xFFFF, BNull); + +#ifdef COPYFAMI + SetReadHandler(0, 0x3FFF, ARAML); + SetWriteHandler(0, 0x3FFF, BRAML); +#else + 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. */ +#endif + 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 (GameInfo->type == GIT_VSUNI) + FCEU_VSUniPower(); + + + timestampbase = 0; + X6502_Power(); + FCEU_PowerCheats(); +} + +void FCEU_ResetVidSys(void) { + int w; + + if (GameInfo->vidsys == GIV_NTSC) + w = 0; + else if (GameInfo->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); + + FILE *ofile; + ofile = fopen("stdout.txt", "ab"); + fwrite(temp, 1, strlen(temp), ofile); + fclose(ofile); + + 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 (GameInfo) { + 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 +} diff --git a/src/fceu.h b/src/fceu.h new file mode 100644 index 0000000..1f2f2c2 --- /dev/null +++ b/src/fceu.h @@ -0,0 +1,108 @@ +#ifndef _FCEUH + +#include "fceu-types.h" + +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); + + +extern uint64 timestampbase; +extern uint32 MMC5HackVROMMask; +extern uint8 *MMC5HackExNTARAMPtr; +extern int MMC5Hack, PEC586Hack; +extern uint8 *MMC5HackVROMPTR; +extern uint8 MMC5HackCHRMode; +extern uint8 MMC5HackSPMode; +extern uint8 MMC5HackSPScroll; +extern uint8 MMC5HackSPPage; + +#ifdef COPYFAMI +extern uint8 RAM[0x4000]; +#else +extern uint8 RAM[0x800]; +#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 *GameInfo; +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 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 +#else +#define _FCEUH +#endif diff --git a/src/fceustr.c b/src/fceustr.c new file mode 100644 index 0000000..1dbd181 --- /dev/null +++ b/src/fceustr.c @@ -0,0 +1,29 @@ +#include +#include + +#include "fceu-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); + str->data = 0; + } + free(str); + str = 0; +} diff --git a/src/fceustr.h b/src/fceustr.h new file mode 100644 index 0000000..aedb289 --- /dev/null +++ b/src/fceustr.h @@ -0,0 +1,4 @@ +typedef struct { + uint8 *data; + uint32 len; /* Not including extra NULL character. */ +} fceustr; diff --git a/src/fcoeffs.h b/src/fcoeffs.h new file mode 100644 index 0000000..d4b9ddc --- /dev/null +++ b/src/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/src/fds.c b/src/fds.c new file mode 100644 index 0000000..9c49a7d --- /dev/null +++ b/src/fds.c @@ -0,0 +1,772 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "fceu-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 void FDSInit(void); +static void FDSClose(void); + +static void FP_FASTAPASS(1) FDSFix(int a); + +static uint8 FDSRegs[6]; +static int32 IRQLatch, IRQCount; +static uint8 IRQa; + +static uint8 *FDSRAM = NULL; +static uint32 FDSRAMSize; +static uint8 *FDSBIOS = NULL; +static uint32 FDSBIOSsize; +static uint8 *CHRRAM = NULL; +static uint32 CHRRAMSize; + +/* 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 uint32 TotalSides; +static uint8 DiskWritten = 0; /* Set to 1 if disk was written to. */ +static uint8 writeskip; +static int32 DiskPtr; +static int32 DiskSeekIRQ; +static uint8 SelectDisk, InDisk; + +uint32 lastDiskPtrRead, lastDiskPtrWrite; + +#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)); + lastDiskPtrRead = lastDiskPtrWrite = writeskip = DiskPtr = DiskSeekIRQ = 0; + + setmirror(1); + setprg8(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, CartBW); + SetReadHandler(0x6000, 0xFFFF, CartBR); + + IRQCount = IRQLatch = IRQa = 0; + + FDSSoundReset(); + InDisk = 0; + SelectDisk = 0; +} + +void FCEU_FDSInsert(int oride) { + 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 (InDisk != 255) { + FCEU_DispMessage("Eject disk before selecting."); + return; + } + SelectDisk = ((SelectDisk + 1) % TotalSides) & 3; + FCEU_DispMessage("Disk %d Side %s 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; + X6502_IRQBegin(FCEU_IQEXT); + } + } + 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; + + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + { + X6502_IRQEnd(FCEU_IQEXT); + X6502_IRQEnd(FCEU_IQEXT2); + } + return ret; +} + +static DECLFR(FDSRead4031) { + static uint8 z = 0; + if (InDisk != 255) { + z = diskdata[InDisk][DiskPtr]; + lastDiskPtrRead = DiskPtr; + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + { + 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 +} + +/* 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; + break; + case 0x7: + b17latch76 = 0; + SPSG[0x5] = 0; + break; + case 0x8: + b17latch76 = 0; + fdso.mwave[SPSG[0x5] & 0x1F] = V & 0x7; + SPSG[0x5] = (SPSG[0x5] + 1) & 0x1F; + break; + } + 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) { + 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; + b8shiftreg88 = 0x80 + adj; + } else { + b8shiftreg88 = 0x80; + } + } else { + b19shiftreg60 <<= 1; + b8shiftreg88 >>= 1; + } + b24adder66 = (b24latch68 + b19shiftreg60) & 0x1FFFFFF; +} + +static INLINE void ClockFall(void) { + if ((b8shiftreg88 & 1)) + b24latch68 = b24adder66; + clockcount = (clockcount + 1) & 7; +} + +static INLINE int32 FDSDoSound(void) { + fdso.count += fdso.cycles; + if (fdso.count >= ((int64)1 << 40)) { + dogk: + fdso.count -= (int64)1 << 40; + ClockRise(); + ClockFall(); + 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) { + uint32 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 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; + } + } + SetReadHandler(0x4040, 0x407f, FDSWaveRead); + SetWriteHandler(0x4040, 0x407f, FDSWaveWrite); + SetWriteHandler(0x4080, 0x408A, FDSSWrite); + SetReadHandler(0x4090, 0x4092, FDSSRead); +} + +void FDSSoundReset(void) { + memset(&fdso, 0, sizeof(fdso)); + FDS_ESI(); + GameExpSound.HiSync = HQSync; + GameExpSound.HiFill = RenderSoundHQ; + GameExpSound.Fill = FDSSound; + GameExpSound.RChange = FDS_ESI; +} + +static DECLFW(FDSWrite) { + switch (A) { + case 0x4020: + X6502_IRQEnd(FCEU_IQEXT); + IRQLatch &= 0xFF00; + IRQLatch |= V; + break; + case 0x4021: + X6502_IRQEnd(FCEU_IQEXT); + IRQLatch &= 0xFF; + IRQLatch |= V << 8; + break; + case 0x4022: + X6502_IRQEnd(FCEU_IQEXT); + IRQCount = IRQLatch; + IRQa = V & 3; + 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; + lastDiskPtrWrite = DiskPtr - 2; + } + } + } + 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, GameInfo->MD5); + return(1); +} + +static void PreSave(void) { + int x; + 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; + 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_MakeFName(FCEUMKF_FDSROM, 0, 0); + + if (!(zp = FCEUD_UTF8fopen(fn, "rb"))) { + FCEU_PrintError("FDS BIOS ROM image missing!"); + free(fn); + return 0; + } + + free(fn); + + ResetCartMapping(); + + if (FDSBIOS) + free(FDSBIOS); + FDSBIOS = NULL; + if (FDSRAM) + free(FDSRAM); + FDSRAM = NULL; + if (CHRRAM) + free(CHRRAM); + CHRRAM = NULL; + + FDSBIOSsize = 8192; + FDSBIOS = (uint8*)FCEU_gmalloc(FDSBIOSsize); + SetupCartPRGMapping(0, FDSBIOS, FDSBIOSsize, 0); + + if (fread(FDSBIOS, 1, FDSBIOSsize, zp) != FDSBIOSsize) { + if (FDSBIOS) + free(FDSBIOS); + FDSBIOS = NULL; + fclose(zp); + FCEU_PrintError("Error reading FDS BIOS ROM image."); + return 0; + } + + fclose(zp); + + FCEU_fseek(fp, 0, SEEK_SET); + + FreeFDSMemory(); + if (!SubLoad(fp)) { + if (FDSBIOS) + free(FDSBIOS); + FDSBIOS = NULL; + return(0); + } + + { + 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))) { + FCEU_printf("Disk was written. Auxillary FDS file open \"%s\".\n", fn); + FreeFDSMemory(); + if (!SubLoad(tp)) { + FCEU_PrintError("Error reading auxillary FDS file."); + if (FDSBIOS) + free(FDSBIOS); + FDSBIOS = NULL; + free(fn); + return(0); + } + FCEU_fclose(tp); + DiskWritten = 1; /* For save state handling. */ + } + free(fn); + } + + GameInfo->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(FDSRegs, sizeof(FDSRegs), 0, "FREG"); + 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"); + + CHRRAMSize = 8192; + CHRRAM = (uint8*)FCEU_gmalloc(CHRRAMSize); + memset(CHRRAM, 0, CHRRAMSize); + SetupCartCHRMapping(0, CHRRAM, CHRRAMSize, 1); + AddExState(CHRRAM, CHRRAMSize, 0, "CHRR"); + + FDSRAMSize = 32768; + FDSRAM = (uint8*)FCEU_gmalloc(FDSRAMSize); + memset(FDSRAM, 0, FDSRAMSize); + SetupCartPRGMapping(1, FDSRAM, FDSRAMSize, 1); + AddExState(FDSRAM, FDSRAMSize, 0, "FDSR"); + + SetupCartMirroring(0, 0, 0); + + FCEU_printf(" Sides: %d\n\n", TotalSides); + 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; + } + FCEU_printf("FDS Save \"%s\"\n", fn); + 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; + } + } + + for (x = 0; x < TotalSides; x++) + if (diskdatao[x]) { + free(diskdatao[x]); + diskdatao[x] = 0; + } + + FreeFDSMemory(); + if (FDSBIOS) + free(FDSBIOS); + FDSBIOS = NULL; + if (FDSRAM) + free(FDSRAM); + FDSRAM = NULL; + if (CHRRAM) + free(CHRRAM); + CHRRAM = NULL; + fclose(fp); +} diff --git a/src/fds.h b/src/fds.h new file mode 100644 index 0000000..2f9744d --- /dev/null +++ b/src/fds.h @@ -0,0 +1,7 @@ +void FDSSoundReset(void); + +void FCEU_FDSInsert(int oride); +void FCEU_FDSEject(void); +void FCEU_FDSSelect(void); + +extern uint32 lastDiskPtrRead, lastDiskPtrWrite; diff --git a/src/file.c b/src/file.c new file mode 100644 index 0000000..9794ced --- /dev/null +++ b/src/file.c @@ -0,0 +1,514 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include "zlib.h" +#include "unzip.h" + +#include "fceu-types.h" +#include "file.h" +#include "fceu-endian.h" +#include "memory.h" +#include "driver.h" +#include "general.h" + +#ifndef __LIBRETRO__ +#define SUPPORTS_UNZIP_AND_GZIP +#endif + +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); + } +#ifdef SUPPORTS_UNZIP_AND_GZIP + 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); + } +#endif + + doret: + if (type == 0) { + fclose((FILE*)tz); + } +#ifdef SUPPORTS_UNZIP_AND_GZIP + else if (type == 1) { + gzclose(tz); + } else if (type == 2) { + unzCloseCurrentFile(tz); + unzClose(tz); + } +#endif + 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)); + + { +#ifdef SUPPORTS_UNZIP_AND_GZIP + 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); + } +#endif + } + + 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) { +#ifdef SUPPORTS_UNZIP_AND_GZIP + if (fp->type == 1) { + gzclose(fp->fp); + } else if (fp->type >= 2) { + free(((MEMWRAP*)(fp->fp))->data); + ((MEMWRAP*)(fp->fp))->data = 0; + free(fp->fp); + fp->fp = 0; + } else +#endif + { + fclose((FILE*)fp->fp); + } + free(fp); + fp = 0; + return 1; +} + +uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp) { +#ifdef SUPPORTS_UNZIP_AND_GZIP + 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 +#endif + { + return fread(ptr, size, nmemb, (FILE*)fp->fp); + } +} + +uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp) { +#ifdef SUPPORTS_UNZIP_AND_GZIP + if (fp->type == 1) { + return gzwrite(fp->fp, ptr, size * nmemb); + } else if (fp->type >= 2) { + return 0; + } else +#endif + return fwrite(ptr, size, nmemb, (FILE*)fp->fp); +} + +int FCEU_fseek(FCEUFILE *fp, long offset, int whence) { +#ifdef SUPPORTS_UNZIP_AND_GZIP + 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 +#endif + return fseek((FILE*)fp->fp, offset, whence); +} + +uint64 FCEU_ftell(FCEUFILE *fp) { +#ifdef SUPPORTS_UNZIP_AND_GZIP + if (fp->type == 1) { + return gztell(fp->fp); + } else if (fp->type >= 2) { + return(((MEMWRAP*)(fp->fp))->location); + } else +#endif + return ftell((FILE*)fp->fp); +} + +void FCEU_rewind(FCEUFILE *fp) { +#ifdef SUPPORTS_UNZIP_AND_GZIP + if (fp->type == 1) { + gzrewind(fp->fp); + } else if (fp->type >= 2) { + ((MEMWRAP*)(fp->fp))->location = 0; + } else +#endif + /* Rewind */ + fseek(fp->fp, 0, SEEK_SET); +} + +int FCEU_read16le(uint16 *val, FCEUFILE *fp) { + uint8 t[2]; + +#ifdef SUPPORTS_UNZIP_AND_GZIP + 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 +#endif + { + 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) { +#ifdef SUPPORTS_UNZIP_AND_GZIP + 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 +#endif + { + return read32le(Bufo, (FILE*)fp->fp); + } +} + +int FCEU_fgetc(FCEUFILE *fp) { +#ifdef SUPPORTS_UNZIP_AND_GZIP + 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 +#endif + return fgetc((FILE*)fp->fp); +} + +uint64 FCEU_fgetsize(FCEUFILE *fp) { +#ifdef SUPPORTS_UNZIP_AND_GZIP + 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 +#endif + { + 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) { +#ifdef SUPPORTS_UNZIP_AND_GZIP + if (fp->type == 2) + return 1; +#endif + return 0; +} diff --git a/src/file.h b/src/file.h new file mode 100644 index 0000000..4196327 --- /dev/null +++ b/src/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/src/filter.c b/src/filter.c new file mode 100644 index 0000000..7508ceb --- /dev/null +++ b/src/filter.c @@ -0,0 +1,190 @@ +#include +#include +#include "fceu-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;xmva) { 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; + uint32 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; + uint32 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/src/filter.h b/src/filter.h new file mode 100644 index 0000000..90a7cd7 --- /dev/null +++ b/src/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/src/fir/Makefile b/src/fir/Makefile new file mode 100644 index 0000000..a74f918 --- /dev/null +++ b/src/fir/Makefile @@ -0,0 +1,15 @@ +CC = gcc +%.h: %.coef + cat $< | ./toh > $@ || true + +all: floogie c44100ntsc.h c48000ntsc.h c96000ntsc.h c44100pal.h c48000pal.h c96000pal.h + +#c44100ntsc.h: c44100ntsc.coef +#c48000ntsc.h: c48000ntsc.coef +#c96000ntsc.h: c96000ntsc.coef +#c44100pal.h: c44100pal.coef +#c48000pal.h: c48000pal.coef +#c96000pal.h: c96000pal.coef + +floogie: toh.o + gcc -o toh toh.o diff --git a/src/fir/c44100ntsc.coef b/src/fir/c44100ntsc.coef new file mode 100644 index 0000000..8f3faed --- /dev/null +++ b/src/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/src/fir/c44100ntsc.h b/src/fir/c44100ntsc.h new file mode 100644 index 0000000..0ac08ef --- /dev/null +++ b/src/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/src/fir/c44100ntsc.scm b/src/fir/c44100ntsc.scm new file mode 100644 index 0000000..0810944 --- /dev/null +++ b/src/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/src/fir/c44100pal.coef b/src/fir/c44100pal.coef new file mode 100644 index 0000000..0398f00 --- /dev/null +++ b/src/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/src/fir/c44100pal.h b/src/fir/c44100pal.h new file mode 100644 index 0000000..b9f0132 --- /dev/null +++ b/src/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/src/fir/c44100pal.scm b/src/fir/c44100pal.scm new file mode 100644 index 0000000..7bd4cc1 --- /dev/null +++ b/src/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/src/fir/c48000ntsc.coef b/src/fir/c48000ntsc.coef new file mode 100644 index 0000000..ba8beb4 --- /dev/null +++ b/src/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/src/fir/c48000ntsc.h b/src/fir/c48000ntsc.h new file mode 100644 index 0000000..c48926f --- /dev/null +++ b/src/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/src/fir/c48000ntsc.scm b/src/fir/c48000ntsc.scm new file mode 100644 index 0000000..8ec2a39 --- /dev/null +++ b/src/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/src/fir/c48000pal.coef b/src/fir/c48000pal.coef new file mode 100644 index 0000000..4a8a5f9 --- /dev/null +++ b/src/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/src/fir/c48000pal.h b/src/fir/c48000pal.h new file mode 100644 index 0000000..c72849f --- /dev/null +++ b/src/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/src/fir/c48000pal.scm b/src/fir/c48000pal.scm new file mode 100644 index 0000000..4722b8d --- /dev/null +++ b/src/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/src/fir/c96000ntsc.coef b/src/fir/c96000ntsc.coef new file mode 100644 index 0000000..a6b9201 --- /dev/null +++ b/src/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/src/fir/c96000ntsc.h b/src/fir/c96000ntsc.h new file mode 100644 index 0000000..e9b003f --- /dev/null +++ b/src/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/src/fir/c96000ntsc.scm b/src/fir/c96000ntsc.scm new file mode 100644 index 0000000..9111e96 --- /dev/null +++ b/src/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/src/fir/c96000pal.coef b/src/fir/c96000pal.coef new file mode 100644 index 0000000..0295f76 --- /dev/null +++ b/src/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/src/fir/c96000pal.h b/src/fir/c96000pal.h new file mode 100644 index 0000000..dd0f917 --- /dev/null +++ b/src/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/src/fir/c96000pal.scm b/src/fir/c96000pal.scm new file mode 100644 index 0000000..e8901ed --- /dev/null +++ b/src/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/src/fir/toh.c b/src/fir/toh.c new file mode 100644 index 0000000..409eea3 --- /dev/null +++ b/src/fir/toh.c @@ -0,0 +1,24 @@ +#include + +#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/src/general.c b/src/general.c new file mode 100644 index 0000000..e3d06f6 --- /dev/null +++ b/src/general.c @@ -0,0 +1,208 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "fceu-types.h" +#include "fceu.h" + +#include "general.h" +#include "state.h" +#include "movie.h" + +#include "driver.h" + +#include "md5.h" + +static char BaseDirectory[2048]; +static 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, 0 }; // odirs, odors. ^_^ + +void FCEUI_SetDirOverride(int which, char *n) { + odirs[which] = n; + + if (GameInfo) { /* Rebuild cache of present states/movies. */ + if (which == FCEUIOD_STATE) + FCEUSS_CheckStates(); + else if (which == FCEUIOD_MOVIE) + 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_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 (odirs[FCEUIOD_STATE]) + asprintf(&ret, "%s"PSS "%s.%d.fcm", odirs[FCEUIOD_STATE], FileBase, id1); + else + asprintf(&ret, "%s"PSS "fcs"PSS "%s.%d.fcm", BaseDirectory, FileBase, id1); + if (stat(ret, &tmpstat) == -1) { + if (odirs[FCEUIOD_STATE]) + asprintf(&ret, "%s"PSS "%s.%s.%d.fcm", odirs[FCEUIOD_STATE], FileBase, md5_asciistr(GameInfo->MD5), id1); + else + asprintf(&ret, "%s"PSS "fcs"PSS "%s.%s.%d.fcm", BaseDirectory, FileBase, md5_asciistr(GameInfo->MD5), id1); + } + 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.%s.fc%d",odirs[FCEUIOD_STATE],FileBase,md5_asciistr(GameInfo->MD5),id1); +// else +// asprintf(&ret,"%s"PSS"fcs"PSS"%s.%s.fc%d",BaseDirectory,FileBase,md5_asciistr(GameInfo->MD5),id1); + 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.%s.fds", odirs[FCEUIOD_NV], FileBase, md5_asciistr(GameInfo->MD5)); + else + asprintf(&ret, "%s"PSS "sav"PSS "%s.%s.fds", BaseDirectory, FileBase, md5_asciistr(GameInfo->MD5)); + 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.%s", odirs[FCEUIOD_NV], FileBase, md5_asciistr(GameInfo->MD5), cd1); + else + asprintf(&ret, "%s"PSS "sav"PSS "%s.%s.%s", BaseDirectory, FileBase, md5_asciistr(GameInfo->MD5), cd1); + } + 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 "gameinfo"PSS "%s.pal", 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/src/general.h b/src/general.h new file mode 100644 index 0000000..880623c --- /dev/null +++ b/src/general.h @@ -0,0 +1,17 @@ +void GetFileBase(const char *f); +extern uint32 uppow2(uint32 n); + +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 FCEUCOPY_FAMI 12 diff --git a/src/git.h b/src/git.h new file mode 100644 index 0000000..8b9bdd4 --- /dev/null +++ b/src/git.h @@ -0,0 +1,28 @@ +#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/src/ines-bad.h b/src/ines-bad.h new file mode 100644 index 0000000..179ab01 --- /dev/null +++ b/src/ines-bad.h @@ -0,0 +1,40 @@ +{ 0xecf78d8a13a030a6LL, "Ai Sensei no Oshiete", INESB_HACKED }, +{ 0x4712856d3e12f21fLL, "Akumajou Densetsu", INESB_HACKED }, +{ 0x10f90ba5bd55c22eLL, "Alien Syndrome", 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 }, +{ 0x6c2a2f95c2fe4b6eLL, "Dragon Ball", INESB_HACKED }, +{ 0x767aaff62963c58fLL, "Dragon Ball", INESB_HACKED }, +{ 0x97f133d8bc1c28dbLL, "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 }, +{ 0xb470bfb90e2b1049LL, "Fire Emblem Gaiden", INESB_HACKED }, +{ 0x27da2b0c500dc346LL, "Fire Emblem", 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 }, +{ 0x1895afc6eef26c7dLL, "Super Mario Bros.", INESB_HACKED }, +{ 0x3716c4bebf885344LL, "Super Mario Bros.", INESB_HACKED }, +{ 0xfffda4407d80885aLL, "Sweet Home", INESB_CORRUPT }, +{ 0x103fc85d978b861bLL, "Sweet Home", INESB_CORRUPT }, +{ 0x7979dc51da86f19fLL, "110-in-1", INESB_CORRUPT }, +{ 0x001c0bb9c358252aLL, "110-in-1", INESB_CORRUPT }, +{ 0, 0, 0 } diff --git a/src/ines-correct.h b/src/ines-correct.h new file mode 100644 index 0000000..15931f8 --- /dev/null +++ b/src/ines-correct.h @@ -0,0 +1,260 @@ + + {0xaf5d7aa2, -1, 0}, /* Clu Clu Land */ + {0xcfb224e6, -1, 1}, /* Dragon Ninja (J) [p1][!].nes */ + {0x4f2f1846, -1, 1}, /* Famista '89 - Kaimaku Han!! (J) */ + {0x82f204ae, -1, 1}, /* Liang Shan Ying Xiong (NJ023) (Ch) [!] */ + {0x684afccd, -1, 1}, /* Space Hunter (J) */ + {0xad9c63e2, -1, 1}, /* Space Shadow (J) */ + {0xe1526228, -1, 1}, /* Quest of Ki */ + {0xaf5d7aa2, -1, 0}, /* Clu Clu Land */ + {0xcfb224e6, -1, 1}, /* Dragon Ninja (J) [p1][!].nes */ + {0x4f2f1846, -1, 1}, /* Famista '89 - Kaimaku Han!! (J) */ + {0xfcdaca80, 0, 0}, /* Elevator Action */ + {0xc05a365b, 0, 0}, /* Exed Exes (J) */ + {0x32fa246f, 0, 0}, /* Tag Team Pro Wrestling */ + {0xb3c30bea, 0, 0}, /* Xevious (J) */ + {0xe492d45a, 0, 0}, /* Zippy Race */ + {0xe28f2596, 0, 1}, /* Pac Land (J) */ + {0xd8ee7669, 1, 8}, /* Adventures of Rad Gravity */ + {0x5b837e8d, 1, 8}, /* Alien Syndrome */ + {0x37ba3261, 1, 8}, /* Back to the Future 2 and 3 */ + {0x5b6ca654, 1, 8}, /* Barbie rev X*/ + {0x61a852ea, 1, 8}, /* Battle Stadium - Senbatsu Pro Yakyuu */ + {0xf6fa4453, 1, 8}, /* Bigfoot */ + {0x391aa1b8, 1, 8}, /* Bloody Warriors (J) */ + {0xa5e8d2cd, 1, 8}, /* Breakthru */ + {0x3f56a392, 1, 8}, /* Captain Ed (J) */ + {0x078ced30, 1, 8}, /* Choujin - Ultra Baseball */ + {0xfe364be5, 1, 8}, /* Deep Dungeon 4 */ + {0x57c12280, 1, 8}, /* Demon Sword */ + {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 */ + {0xe94d5181, 1, 8}, /* Mirai Senshi - Lios */ + {0x7156cb4d, 1, 8}, /* Muppet Adventure Carnival thingy */ + {0x70f67ab7, 1, 8}, /* Musashi no Bouken */ + {0x291bcd7d, 1, 8}, /* Pachio Kun 2 */ + {0xa9a4ea4c, 1, 8}, /* Satomi Hakkenden */ + {0xcc3544b0, 1, 8}, /* Triathron */ + {0x934db14a, 1, -1}, /* All-Pro Basketball */ + {0xf74dfc91, 1, -1}, /* Win, Lose, or Draw */ + {0x9ea1dc76, 2, 0}, /* Rainbow Islands */ + {0x6d65cac6, 2, 0}, /* Terra Cresta */ + {0xe1b260da, 2, 1}, /* Argos no Senshi */ + {0x1d0f4d6b, 2, 1}, /* Black Bass thinging */ + {0x266ce198, 2, 1}, /* City Adventure Touch */ + {0x804f898a, 2, 1}, /* Dragon Unit */ + {0x55773880, 2, 1}, /* Gilligan's Island */ + {0x6e0eb43e, 2, 1}, /* Puss n Boots */ + {0x2bb6a0f8, 2, 1}, /* Sherlock Holmes */ + {0x28c11d24, 2, 1}, /* Sukeban Deka */ + {0x02863604, 2, 1}, /* Sukeban Deka */ + {0x419461d0, 2, 1}, /* Super Cars */ + {0xdbf90772, 3, 0}, /* Alpha Mission */ + {0xd858033d, 3, 0}, /* Armored Scrum Object */ + {0x9bde3267, 3, 1}, /* Adventures of Dino Riki */ + {0xd8eff0df, 3, 1}, /* Gradius (J) */ + {0x1d41cc8c, 3, 1}, /* Gyruss */ + {0xcf322bb3, 3, 1}, /* John Elway's Quarterback */ + {0xb5d28ea2, 3, 1}, /* Mystery Quest - mapper 3?*/ + {0x02cc3973, 3, 1}, /* Ninja Kid */ + {0xbc065fc3, 3, 1}, /* Pipe Dream */ + {0xc9ee15a7, 3, -1}, /* 3 is probably best. 41 WILL NOT WORK. */ + {0x22d6d5bd, 4, 1}, + {0xd97c31b0, 4, 1}, //Rasaaru Ishii no Childs Quest (J) + {0x404b2e8b, 4, 2}, /* Rad Racer 2 */ + {0x15141401, 4, 8}, /* Asmik Kun Land */ + {0x4cccd878, 4, 8}, /* Cat Ninden Teyandee */ + {0x59280bec, 4, 8}, /* Jackie Chan */ + {0x7474ac92, 4, 8}, /* Kabuki: Quantum Fighter */ + {0x5337f73c, 4, 8}, /* Niji no Silk Road */ + {0x9eefb4b4, 4, 8}, /* Pachi Slot Adventure 2 */ + {0x21a653c7, 4, -1}, /* Super Sky Kid */ + {0x9cbadc25, 5, 8}, /* JustBreed */ + {0xf518dd58, 7, 8}, /* Captain Skyhawk */ + {0x84382231, 9, 0}, /* Punch Out (J) */ + {0xbe939fce, 9, 1}, /* Punchout*/ + {0x345d3a1a, 11, 1}, /* Castle of Deceit */ + {0x5e66eaea, 13, 1}, /* Videomation */ + {0xcd373baa, 14, -1}, /* Samurai Spirits (Rex Soft) */ + {0xbfc7a2e9, 16, 8}, + {0x6e68e31a, 16, 8}, /* Dragon Ball 3*/ + {0x33b899c9, 16, -1}, /* Dragon Ball - Dai Maou Fukkatsu (J) [!] */ + {0xa262a81f, 16, -1}, /* Rokudenashi Blues (J) */ + {0x286fcd20, 23, -1}, /* Ganbare Goemon Gaiden 2 - Tenka no Zaihou (J) [!] */ + {0xe4a291ce, 23, -1}, /* World Hero (Unl) [!] */ + {0x51e9cd33, 23, -1}, /* World Hero (Unl) [b1] */ + {0x105dd586, 27, -1}, /* Mi Hun Che variations... */ + {0xbc9bb6c1, 27, -1}, /* -- */ + {0x43753886, 27, -1}, /* -- */ + {0x5b3de3d1, 27, -1}, /* -- */ + {0x511e73f8, 27, -1}, /* -- */ + {0x5555fca3, 32, 8}, + {0x283ad224, 32, 8}, /* Ai Sensei no Oshiete */ + {0x243a8735, 32, 0x10|4}, /* Major League */ + {0xbc7b1d0f, 33, -1}, /* Bakushou!! Jinsei Gekijou 2 (J) [!] */ + {0xc2730c30, 34, 0}, /* Deadly Towers */ + {0x4c7c1af3, 34, 1}, /* Caesar's Palace */ + {0x932ff06e, 34, 1}, /* Classic Concentration */ + {0xf46ef39a, 37, -1}, /* Super Mario Bros. + Tetris + Nintendo World Cup (E) [!] */ + {0x7ccb12a3, 43, -1}, /* SMB2j */ + {0x6c71feae, 45, -1}, /* Kunio 8-in-1 */ + {0xe2c94bc2, 48, -1}, /* Super Bros 8 (Unl) [!] */ + {0xaebd6549, 48, 8}, /* Bakushou!! Jinsei Gekijou 3 */ + {0x6cdc0cd9, 48, 8}, /* Bubble Bobble 2 */ + {0x99c395f9, 48, 8}, /* Captain Saver */ + {0xa7b0536c, 48, 8}, /* Don Doko Don 2 */ + {0x40c0ad47, 48, 8}, /* Flintstones 2 */ + {0x1500e835, 48, 8}, /* Jetsons (J) */ + {0xa912b064, 51|0x800, 8}, /* 11-in-1 Ball Games(has CHR ROM when it shouldn't) */ + {0xb19a55dd, 64, 8}, /* Road Runner */ + {0xf92be3ec, 64, -1}, /* Rolling Thunder */ + {0xe84274c5, 66, 1}, + {0xbde3ae9b, 66, 1}, /* Doraemon */ + {0x9552e8df, 66, 1}, /* Dragon Ball */ + {0x811f06d9, 66, 1}, /* Dragon Power */ + {0xd26efd78, 66, 1}, /* SMB Duck Hunt */ + {0xdd8ed0f7, 70, 1}, /* Kamen Rider Club */ + {0xbba58be5, 70, -1}, /* Family Trainer - Manhattan Police */ + {0x370ceb65, 70, -1}, /* Family Trainer - Meiro Dai Sakusen */ + {0xe62e3382, 71, -1}, /* Mig-29 Soviet Fighter */ + {0xac7b0742, 71, -1}, /* Golden KTV (Ch) [!], not actually 71, but UNROM without BUS conflict */ + {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) */ + {0xba51ac6f, 78, 2}, + {0x3d1c3137, 78, 8}, /* Uchuusen - Cosmo Carrier */ + {0xa4fbb438, 79, 0}, + {0xd4a76b07, 79, 0}, /* F-15 City Wars*/ + {0x1eb4a920, 79, 1}, /* Double Strike */ + {0x3e1271d5, 79, 1}, /* Tiles of Fate */ + {0xd2699893, 88, 0}, /* Dragon Spirit */ + {0xbb7c5f7a, 89, 8}, /* Mito Koumon or something similar */ + {0x0da5e32e, 101, -1}, /* new Uruusey Yatsura */ + {0x8eab381c, 113, 1}, /* Death Bots */ + {0x6a03d3f3, 114, -1}, + {0x0d98db53, 114, -1}, /* Pocahontas */ + {0x4e7729ff, 114, -1}, /* Super Donkey Kong */ + {0xc5e5c5b2, 115, -1}, /* Bao Qing Tian (As).nes */ + {0xa1dc16c0, 116, -1}, + {0xe40dfb7e, 116, -1}, /* Somari (P conf.) */ + {0xc9371ebb, 116, -1}, /* Somari (W conf.) */ + {0xcbf4366f, 118, 8}, /* Alien Syndrome (U.S. unlicensed) */ + {0x78b657ac, 118, -1}, /* Armadillo */ + {0x90c773c1, 118, -1}, /* Goal! 2 */ + {0xb9b4d9e0, 118, -1}, /* NES Play Action Football */ + {0x07d92c31, 118, -1}, /* RPG Jinsei Game */ + {0x37b62d04, 118, -1}, /* Ys 3 */ + {0x318e5502, 121, -1}, /* Sonic 3D Blast 6 (Unl) */ + {0xddcfb058, 121, -1}, /* Street Fighter Zero 2 '97 (Unl) [!] */ + {0x5aefbc94, 133, -1}, /* Jovial Race (Sachen) [a1][!] */ + {0xc2df0a00, 140, 1}, /* Bio Senshi Dan(hacked) */ + {0xe46b1c5d, 140, 1}, /* Mississippi Satsujin Jiken */ + {0x3293afea, 140, 1}, /* Mississippi Satsujin Jiken */ + {0x6bc65d7e, 140, 1}, /* Youkai Club*/ + {0x5caa3e61, 144, 1}, /* Death Race */ + {0x48239b42, 146, -1}, /* Mahjong Companion (Sachen) [!] */ + {0xb6a727fa, 146, -1}, /* Papillion (As) [!] */ + {0xa62b79e1, 146, -1}, /* Side Winder (HES) [!] */ + {0xcc868d4e, 149, -1}, /* 16 Mahjong [p1][!] */ + {0x29582ca1, 150, -1}, + {0x40dbf7a2, 150, -1}, + {0x73fb55ac, 150, -1}, /* 2-in-1 Cosmo Cop + Cyber Monster (Sachen) [!] */ + {0xddcbda16, 150, -1}, /* 2-in-1 Tough Cop + Super Tough Cop (Sachen) [!] */ + {0x47918d84, 150, -1}, /* auto-upturn */ + {0x0f141525, 152, 8}, /* Arkanoid 2 (Japanese) */ + {0xbda8f8e4, 152, 8}, /* Gegege no Kitarou 2 */ + {0xb1a94b82, 152, 8}, /* Pocket Zaurus */ + {0x026c5fca, 152, 8}, /* Saint Seiya Ougon Densetsu */ + {0x3f15d20d, 153, 8}, /* Famicom Jump 2 */ + {0xd1691028, 154, 8}, /* Devil Man */ + {0xcfd4a281, 155, 8}, /* Money Game. Yay for money! */ + {0x2f27cdef, 155, 8}, /* Tatakae!! Rahmen Man */ + {0xccc03440, 156, -1}, + {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 */ + {0xe170404c, 159, -1}, /* SD Gundam Gaiden - Knight Gundam Monogatari (J) (V1.0) [!] */ + {0x276ac722, 159, -1}, /* SD Gundam Gaiden - Knight Gundam Monogatari (J) (V1.1) [!] */ + {0x0cf42e69, 159, -1}, /* Magical Taruruuto-kun - Fantastic World!! (J) (V1.0) [!] */ + {0xdcb972ce, 159, -1}, /* Magical Taruruuto-kun - Fantastic World!! (J) (V1.1) [!] */ + {0xb7f28915, 159, -1}, /* Magical Taruruuto-kun 2 - Mahou Daibouken (J) */ + {0x183859d2, 159, -1}, /* Dragon Ball Z - Kyoushuu! Saiya Jin (J) [!] */ + {0x58152b42, 160, 1}, /* Pipe 5 (Sachen) */ + {0x1c098942, 162, -1}, /* Xi You Ji Hou Zhuan (Ch) */ + {0x081caaff, 163, -1}, /* Commandos (Ch) */ + {0x02c41438, 176, -1}, /* Xing He Zhan Shi (C) */ + {0x558c0dc3, 178, -1}, /* Super 2in1 (unl)[!] {mapper unsupported} */ + {0xc68363f6, 180, 0}, /* Crazy Climber */ + {0x0f05ff0a, 181, -1}, /* Seicross (redump) */ + {0x96ce586e, 189, 8}, /* Street Fighter 2 YOKO */ + {0x555a555e, 191, -1}, + {0x2cc381f6, 191, -1}, /* Sugoro Quest - Dice no Senshitachi (As) */ + {0xa145fae6, 192, -1}, + {0xa9115bc1, 192, -1}, + {0x4c7bbb0e, 192, -1}, + {0x98c1cd4b, 192, -1}, /* Ying Lie Qun Xia Zhuan (Chinese) */ + {0xee810d55, 192, -1}, /* You Ling Xing Dong (Ch) */ + {0x442f1a29, 192, -1}, /* Young chivalry */ + {0x637134e8, 193, 1}, /* Fighting Hero */ + {0xa925226c, 194, -1}, /* Dai-2-Ji - Super Robot Taisen (As) */ + {0x7f3dbf1b, 195, 0}, + {0xb616885c, 195, 0}, /* CHaos WOrld (Ch)*/ + {0x33c5df92, 195, -1}, + {0x1bc0be6c, 195, -1}, /* Captain Tsubasa Vol 2 - Super Striker (C) */ + {0xd5224fde, 195, -1}, /* Crystalis (c) */ + {0xfdec419f, 196, -1}, /* Street Fighter VI 16 Peoples (Unl) [!] */ + {0x700705f4, 198, -1}, + {0x9a2cf02c, 198, -1}, + {0xd8b401a7, 198, -1}, + {0x28192599, 198, -1}, + {0x19b9e732, 198, -1}, + {0xdd431ba7, 198, -1}, /* Tenchi wo kurau 2 (c) */ + {0xd871d3e6, 199, -1}, /* Dragon Ball Z 2 - Gekishin Freeza! (C) */ + {0xed481b7c, 199, -1}, /* Dragon Ball Z Gaiden - Saiya Jin Zetsumetsu Keikaku (C) */ + {0x44c20420, 199, -1}, /* San Guo Zhi 2 (C) */ + {0x4e1c1e3c, 206, 0}, /* Karnov */ + {0x276237b3, 206, 0}, /* Karnov */ + {0x7678f1d5, 207, 8}, /* Fudou Myouou Den */ + {0x07eb2c12, 208, -1}, /* Street Fighter IV */ + {0xdd8ced31, 209, -1}, /* Power Rangers 3 */ + {0x063b1151, 209, -1}, /* Power Rangers 4 */ + {0xdd4d9a62, 209, -1}, /* Shin Samurai Spirits 2 */ + {0x0c47946d, 210, 1}, /* Chibi Maruko Chan */ + {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 */ + {0xbd523011, 210, 0}, /* Dream Master */ + {0x5daae69a, 211, -1}, /* Aladdin - Return of Jaffar, The (Unl) [!] */ + {0x1ec1dfeb, 217, -1}, /* 255-in-1 (Cut version) [p1] */ + {0x046d70cc, 217, -1}, /* 500-in-1 (Anim Splash, Alt Mapper)[p1][!] */ + {0x12f86a4d, 217, -1}, /* 500-in-1 (Static Splash, Alt Mapper)[p1][!] */ + {0xd09f778d, 217, -1}, /* 9999999-in-1 (Static Splash, Alt Mapper)[p1][!] */ + {0x62ef6c79, 232, 8}, /* Quattro Sports -Aladdin */ + {0x2705eaeb, 234, -1}, /* Maxi 15 */ + {0x6f12afc5, 235, -1}, /* Golden Game 150-in-1 */ + {0xfb2b6b10, 241, -1}, /* Fan Kong Jing Ying (Ch) */ + {0xb5e83c9a, 241, -1}, /* Xing Ji Zheng Ba (Ch) */ + {0x2537b3e6, 241, -1}, /* Dance Xtreme - Prima (Unl) */ + {0x11611e89, 241, -1}, /* Darkseed (Unl) [p1] */ + {0x81a37827, 241, -1}, /* Darkseed (Unl) [p1][b1] */ + {0xc2730c30, 241, -1}, /* Deadly Towers (U) [!] */ + {0x368c19a8, 241, -1}, /* LIKO Study Cartridge 3-in-1 (Unl) [!] */ + {0xa21e675c, 241, -1}, /* Mashou (J) [!] */ + {0x54d98b79, 241, -1}, /* Titanic 1912 (Unl) */ + {0x6bea1235, 245, -1}, /* MMC3 cart, but with nobanking applied to CHR-RAM, so let it be there */ + {0x345ee51a, 245, -1}, /* DQ4c */ + {0x57514c6c, 245, -1}, /* Yong Zhe Dou E Long - Dragon Quest VI (Ch) */ + + {0x00000000, -1, -1} diff --git a/src/ines.c b/src/ines.c new file mode 100644 index 0000000..15939d5 --- /dev/null +++ b/src/ines.c @@ -0,0 +1,842 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "fceu-types.h" +#include "x6502.h" +#include "fceu.h" +#include "cart.h" +#include "ppu.h" + +#include "ines.h" +#include "unif.h" +#include "state.h" +#include "file.h" +#include "general.h" +#include "memory.h" +#include "crc32.h" +#include "md5.h" +#include "cheat.h" +#include "vsuni.h" + +extern SFORMAT FCEUVSUNI_STATEINFO[]; + +uint8 *trainerpoo = NULL; +uint8 *ROM = NULL; +uint8 *VROM = NULL; +uint8 *ExtraNTARAM = NULL; +iNES_HEADER head; + +#ifdef __LIBRETRO__ +CartInfo iNESCart; +#else +static CartInfo iNESCart; +#endif + +uint8 Mirroring = 0; +uint32 ROM_size = 0; +uint32 VROM_size = 0; + +static int CHRRAMSize = -1; +static int iNES_Init(int num); + +static int MapperNo = 0; + +static DECLFR(TrainerRead) { + return(trainerpoo[A & 0x1FF]); +} + +static void iNES_ExecPower() { + 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; + } + } + } +} + +static void iNESGI(int h) { + switch (h) { + case GI_RESETM2: + if (iNESCart.Reset) + iNESCart.Reset(); + break; + case GI_POWER: + iNES_ExecPower(); + break; + case GI_CLOSE: + { + FCEU_SaveGameSave(&iNESCart); + if (iNESCart.Close) + iNESCart.Close(); + if (ROM) { + free(ROM); + ROM = NULL; + } + if (VROM) { + free(VROM); + VROM = NULL; + } + if (trainerpoo) { + free(trainerpoo); + trainerpoo = NULL; + } + if (ExtraNTARAM) { + free(ExtraNTARAM); + ExtraNTARAM = NULL; + } + } + break; + } +} + +uint32 iNESGameCRC32 = 0; + +struct CRCMATCH { + uint32 crc; + char *name; +}; + +struct INPSEL { + uint32 crc32; + int input1; + int input2; + int inputfc; +}; + +static void SetInput(void) { + static struct INPSEL moo[] = + { + {0x19b0a9f1, SI_GAMEPAD, SI_ZAPPER, SIFC_NONE }, // 6-in-1 (MGC-023)(Unl)[!] + {0x29de87af, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Aerobics Studio + {0xd89e5a67, SI_UNSET, SI_UNSET, SIFC_ARKANOID }, // Arkanoid (J) + {0x0f141525, SI_UNSET, SI_UNSET, SIFC_ARKANOID }, // Arkanoid 2(J) + {0x32fb0583, SI_UNSET, SI_ARKANOID, SIFC_NONE }, // Arkanoid(NES) + {0x60ad090a, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERA }, // Athletic World + {0x48ca0ee1, SI_GAMEPAD, SI_GAMEPAD, SIFC_BWORLD }, // Barcode World + {0x4318a2f8, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Barker Bill's Trick Shooting + {0x6cca1c1f, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Dai Undoukai + {0x24598791, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Duck Hunt + {0xd5d6eac4, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Edu (As) + {0xe9a7fe9e, SI_UNSET, SI_MOUSE, SIFC_NONE }, // Educational Computer 2000 + {0x8f7b1669, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // FP BASIC 3.3 by maxzhou88 + {0xf7606810, SI_UNSET, SI_UNSET, SIFC_FKB }, // Family BASIC 2.0A + {0x895037bc, SI_UNSET, SI_UNSET, SIFC_FKB }, // Family BASIC 2.1a + {0xb2530afc, SI_UNSET, SI_UNSET, SIFC_FKB }, // Family BASIC 3.0 + {0xea90f3e2, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Family Trainer: Running Stadium + {0xbba58be5, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Family Trainer: Manhattan Police + {0x3e58a87e, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Freedom Force + {0xd9f45be9, SI_GAMEPAD, SI_GAMEPAD, SIFC_QUIZKING }, // Gimme a Break ... + {0x1545bd13, SI_GAMEPAD, SI_GAMEPAD, SIFC_QUIZKING }, // Gimme a Break ... 2 + {0x4e959173, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Gotcha! - The Sport! + {0xbeb8ab01, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Gumshoe + {0xff24d794, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Hogan's Alley + {0x21f85681, SI_GAMEPAD, SI_GAMEPAD, SIFC_HYPERSHOT }, // Hyper Olympic (Gentei Ban) + {0x980be936, SI_GAMEPAD, SI_GAMEPAD, SIFC_HYPERSHOT }, // Hyper Olympic + {0x915a53a7, SI_GAMEPAD, SI_GAMEPAD, SIFC_HYPERSHOT }, // Hyper Sports + {0x9fae4d46, SI_GAMEPAD, SI_GAMEPAD, SIFC_MAHJONG }, // Ide Yousuke Meijin no Jissen Mahjong + {0x7b44fb2a, SI_GAMEPAD, SI_GAMEPAD, SIFC_MAHJONG }, // Ide Yousuke Meijin no Jissen Mahjong 2 + {0x2f128512, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERA }, // Jogging Race + {0xbb33196f, SI_UNSET, SI_UNSET, SIFC_FKB }, // Keyboard Transformer + {0x8587ee00, SI_UNSET, SI_UNSET, SIFC_FKB }, // Keyboard Transformer + {0x543ab532, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // LIKO Color Lines + {0x368c19a8, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // LIKO Study Cartridge + {0x5ee6008e, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Mechanized Attack + {0x370ceb65, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Meiro Dai Sakusen + {0x3a1694f9, SI_GAMEPAD, SI_GAMEPAD, SIFC_4PLAYER }, // Nekketsu Kakutou Densetsu + {0x9d048ea4, SI_GAMEPAD, SI_GAMEPAD, SIFC_OEKAKIDS }, // Oeka Kids + {0x2a6559a1, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Operation Wolf (J) + {0xedc3662b, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Operation Wolf + {0x912989dc, SI_UNSET, SI_UNSET, SIFC_FKB }, // Playbox BASIC + {0x9044550e, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERA }, // Rairai Kyonshizu + {0xea90f3e2, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Running Stadium + {0x851eb9be, SI_GAMEPAD, SI_ZAPPER, SIFC_NONE }, // Shooting Range + {0x6435c095, SI_GAMEPAD, SI_POWERPADB, SIFC_UNSET }, // Short Order/Eggsplode + {0xc043a8df, SI_UNSET, SI_MOUSE, SIFC_NONE }, // Shu Qi Yu - Shu Xue Xiao Zhuan Yuan (Ch) + {0x2cf5db05, SI_UNSET, SI_MOUSE, SIFC_NONE }, // Shu Qi Yu - Zhi Li Xiao Zhuan Yuan (Ch) + {0xad9c63e2, SI_GAMEPAD, SI_UNSET, SIFC_SHADOW }, // Space Shadow + {0x61d86167, SI_GAMEPAD, SI_POWERPADB, SIFC_UNSET }, // Street Cop + {0xabb2f974, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Study and Game 32-in-1 + {0x41ef9ac4, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Subor + {0x8b265862, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Subor + {0x82f1fb96, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Subor 1.0 Russian + {0x9f8f200a, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERA }, // Super Mogura Tataki!! - Pokkun Moguraa + {0xd74b2719, SI_GAMEPAD, SI_POWERPADB, SIFC_UNSET }, // Super Team Games + {0x74bea652, SI_GAMEPAD, SI_ZAPPER, SIFC_NONE }, // Supergun 3-in-1 + {0x5e073a1b, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // Supor English (Chinese) + {0x589b6b0d, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // SuporV20 + {0x41401c6d, SI_UNSET, SI_UNSET, SIFC_SUBORKB }, // SuporV40 + {0x23d17f5e, SI_GAMEPAD, SI_ZAPPER, SIFC_NONE }, // The Lone Ranger + {0xc3c0811d, SI_GAMEPAD, SI_GAMEPAD, SIFC_OEKAKIDS }, // The two "Oeka Kids" games + {0xde8fd935, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // To the Earth + {0x47232739, SI_GAMEPAD, SI_GAMEPAD, SIFC_TOPRIDER }, // Top Rider + {0x8a12a7d9, SI_GAMEPAD, SI_GAMEPAD, SIFC_FTRAINERB }, // Totsugeki Fuuun Takeshi Jou + {0xb8b9aca3, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Wild Gunman + {0x5112dc21, SI_UNSET, SI_ZAPPER, SIFC_NONE }, // Wild Gunman + {0xaf4010ea, SI_GAMEPAD, SI_POWERPADB, SIFC_UNSET }, // World Class Track Meet + {0x00000000, SI_UNSET, SI_UNSET, SIFC_UNSET } + }; + int x = 0; + + while (moo[x].input1 >= 0 || moo[x].input2 >= 0 || moo[x].inputfc >= 0) { + if (moo[x].crc32 == iNESGameCRC32) { + GameInfo->input[0] = moo[x].input1; + GameInfo->input[1] = moo[x].input2; + GameInfo->inputfc = moo[x].inputfc; + break; + } + x++; + } +} + +#define INESB_INCOMPLETE 1 +#define INESB_CORRUPT 2 +#define INESB_HACKED 4 + +struct BADINF { + uint64 md5partial; + uint8 *name; + uint32 type; +}; + +static struct BADINF BadROMImages[] = +{ + #include "ines-bad.h" +}; + +void CheckBad(uint64 md5partial) { + int32 x = 0; + 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 in 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[] = + { + 0xc04361e499748382LL, /* AD&D Heroes of the Lance */ + 0xb72ee2337ced5792LL, /* AD&D Hillsfar */ + 0x2b7103b7a27bd72fLL, /* AD&D Pool of Radiance */ + 0x498c10dc463cfe95LL, /* Battle Fleet */ + 0x854d7947a3177f57LL, /* Crystalis */ + 0x4a1f5336b86851b6LL, /* DW */ + 0xb0bcc02c843c1b79LL, /* DW */ + 0x2dcf3a98c7937c22LL, /* DW 2 */ + 0x98e55e09dfcc7533LL, /* DW 4*/ + 0x733026b6b72f2470LL, /* Dw 3 */ + 0x6917ffcaca2d8466LL, /* Famista '90 */ + 0x8da46db592a1fcf4LL, /* Faria */ + 0xedba17a2c4608d20LL, /* Final Fantasy */ + 0x91a6846d3202e3d6LL, /* Final Fantasy */ + 0x012df596e2b31174LL, /* Final Fantasy 1+2 */ + 0xf6b359a720549ecdLL, /* Final Fantasy 2 */ + 0x5a30da1d9b4af35dLL, /* Final Fantasy 3 */ + 0xd63dcc68c2b20adcLL, /* Final Fantasy J */ + 0x2ee3417ba8b69706LL, /* Hydlide 3*/ + 0xebbce5a54cf3ecc0LL, /* Justbreed */ + 0x6a858da551ba239eLL, /* Kaijuu Monogatari */ + 0x2db8f5d16c10b925LL, /* Kyonshiizu 2 */ + 0x04a31647de80fdabLL, /* Legend of Zelda */ + 0x94b9484862a26cbaLL, /* Legend of Zelda */ + 0xa40666740b7d22feLL, /* Mindseeker */ + 0x82000965f04a71bbLL, /* Mirai Shinwa Jarvas */ + 0x77b811b2760104b9LL, /* Mouryou Senki Madara */ + 0x11b69122efe86e8cLL, /* RPG Jinsei Game */ + 0x9aa1dc16c05e7de5LL, /* Startropics */ + 0x1b084107d0878bd0LL, /* Startropics 2*/ + 0xa70b495314f4d075LL, /* Ys 3 */ + 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" + }; + int32 tofix = 0, x; + uint64 partialmd5 = 0; + + for (x = 0; x < 8; x++) + partialmd5 |= (uint64)iNESCart.MD5[15 - x] << (x * 8); + CheckBad(partialmd5); + + x = 0; + do { + if (moo[x].crc32 == iNESGameCRC32) { + if (moo[x].mapper >= 0) { + if (moo[x].mapper & 0x800 && VROM_size) { + VROM_size = 0; + free(VROM); + VROM = NULL; + 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) { + uint8 *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 { + int32 mapper; + void (*init)(CartInfo *); +} NewMI; + +typedef struct { + uint8 *name; + int32 number; + void (*init)(CartInfo *); +} BMAPPINGLocal; + +static BMAPPINGLocal bmap[] = { + {"NROM", 0, NROM_Init}, + {"MMC1", 1, Mapper1_Init}, + {"UNROM", 2, UNROM_Init}, + {"CNROM", 3, CNROM_Init}, + {"MMC3", 4, Mapper4_Init}, + {"MMC5", 5, Mapper5_Init}, + {"FFE Rev. A", 6, Mapper6_Init}, + {"ANROM", 7, ANROM_Init}, + {"", 8, Mapper8_Init}, // Nogaems, it's worthless + {"MMC2", 9, Mapper9_Init}, + {"MMC4", 10, Mapper10_Init}, + {"Color Dreams", 11, Mapper11_Init}, + {"REX DBZ 5", 12, Mapper12_Init}, + {"CPROM", 13, CPROM_Init}, + {"REX SL-1632", 14, UNLSL1632_Init}, + {"100-in-1", 15, Mapper15_Init}, + {"BANDAI 24C02", 16, Mapper16_Init}, + {"FFE Rev. B", 17, Mapper17_Init}, + {"JALECO SS880006", 18, Mapper18_Init}, // JF-NNX (EB89018-30007) boards + {"Namcot 106", 19, Mapper19_Init}, +// {"", 20, Mapper20_Init}, + {"Konami VRC2/VRC4 A", 21, Mapper21_Init}, + {"Konami VRC2/VRC4 B", 22, Mapper22_Init}, + {"Konami VRC2/VRC4 C", 23, Mapper23_Init}, + {"Konami VRC6 Rev. A", 24, Mapper24_Init}, + {"Konami VRC2/VRC4 D", 25, Mapper25_Init}, + {"Konami VRC6 Rev. B", 26, Mapper26_Init}, + {"CC-21 MI HUN CHE", 27, UNLCC21_Init}, // Former dupe for VRC2/VRC4 mapper, redefined with crc to mihunche boards +// {"", 28, Mapper28_Init}, // Custom Multidiscrete mapper for PDs +// {"", 29, Mapper29_Init}, +// {"", 30, Mapper30_Init}, +// {"", 31, Mapper31_Init}, + {"IREM G-101", 32, Mapper32_Init}, + {"TC0190FMC/TC0350FMR", 33, Mapper33_Init}, + {"IREM I-IM/BNROM", 34, Mapper34_Init}, + {"Wario Land 2", 35, UNLSC127_Init}, + {"TXC Policeman", 36, Mapper36_Init}, + {"PAL-ZZ SMB/TETRIS/NWC",37, Mapper37_Init}, + {"Bit Corp.", 38, Mapper38_Init}, // Crime Busters +// {"", 39, Mapper39_Init}, + {"SMB2j FDS", 40, Mapper40_Init}, + {"CALTRON 6-in-1", 41, Mapper41_Init}, + {"BIO MIRACLE FDS", 42, Mapper42_Init}, + {"FDS SMB2j LF36", 43, Mapper43_Init}, + {"MMC3 BMC PIRATE A", 44, Mapper44_Init}, + {"MMC3 BMC PIRATE B", 45, Mapper45_Init}, + {"RUMBLESTATION 15-in-1",46, Mapper46_Init}, + {"NES-QJ SSVB/NWC", 47, Mapper47_Init}, + {"TAITO TCxxx", 48, Mapper48_Init}, + {"MMC3 BMC PIRATE C", 49, Mapper49_Init}, + {"SMB2j FDS Rev. A", 50, Mapper50_Init}, + {"11-in-1 BALL SERIES", 51, Mapper51_Init}, // 1993 year version + {"MMC3 BMC PIRATE D", 52, Mapper52_Init}, + {"SUPERVISION 16-in-1", 53, Supervision16_Init}, +// {"", 54, Mapper54_Init}, +// {"", 55, Mapper55_Init}, +// {"", 56, Mapper56_Init}, + {"SIMBPLE BMC PIRATE A", 57, Mapper57_Init}, + {"SIMBPLE BMC PIRATE B", 58, BMCGK192_Init}, + {"", 59, Mapper59_Init}, // Check this out + {"SIMBPLE BMC PIRATE C", 60, BMCD1038_Init}, + {"20-in-1 KAISER Rev. A",61, Mapper61_Init}, + {"700-in-1", 62, Mapper62_Init}, +// {"", 63, Mapper63_Init}, + {"TENGEN RAMBO1", 64, Mapper64_Init}, + {"IREM-H3001", 65, Mapper65_Init}, + {"MHROM", 66, MHROM_Init}, + {"SUNSOFT-FZII", 67, Mapper67_Init}, + {"Sunsoft Mapper #4", 68, Mapper68_Init}, + {"SUNSOFT-5/FME-7", 69, Mapper69_Init}, + {"BA KAMEN DISCRETE", 70, Mapper70_Init}, + {"CAMERICA BF9093", 71, Mapper71_Init}, + {"JALECO JF-17", 72, Mapper72_Init}, + {"KONAMI VRC3", 73, Mapper73_Init}, + {"TW MMC3+VRAM Rev. A", 74, Mapper74_Init}, + {"KONAMI VRC1", 75, Mapper75_Init}, + {"NAMCOT 108 Rev. A", 76, Mapper76_Init}, + {"IREM LROG017", 77, Mapper77_Init}, + {"Irem 74HC161/32", 78, Mapper78_Init}, + {"AVE/C&E/TXC BOARD", 79, Mapper79_Init}, + {"TAITO X1-005 Rev. A", 80, Mapper80_Init}, +// {"", 81, Mapper81_Init}, + {"TAITO X1-017", 82, Mapper82_Init}, + {"YOKO VRC Rev. B", 83, Mapper83_Init}, +// {"", 84, Mapper84_Init}, + {"KONAMI VRC7", 85, Mapper85_Init}, + {"JALECO JF-13", 86, Mapper86_Init}, + {"74*139/74 DISCRETE", 87, Mapper87_Init}, + {"NAMCO 3433", 88, Mapper88_Init}, + {"SUNSOFT-3", 89, Mapper89_Init}, // SUNSOFT-2 mapper + {"HUMMER/JY BOARD", 90, Mapper90_Init}, + {"EARLY HUMMER/JY BOARD",91, Mapper91_Init}, + {"JALECO JF-19", 92, Mapper92_Init}, + {"SUNSOFT-3R", 93, SUNSOFT_UNROM_Init},// SUNSOFT-2 mapper with VRAM, different wiring + {"HVC-UN1ROM", 94, Mapper94_Init}, + {"NAMCOT 108 Rev. B", 95, Mapper95_Init}, + {"BANDAI OEKAKIDS", 96, Mapper96_Init}, + {"IREM TAM-S1", 97, Mapper97_Init}, +// {"", 98, Mapper98_Init}, + {"VS Uni/Dual- system", 99, Mapper99_Init}, +// {"", 100, Mapper100_Init}, + {"", 101, Mapper101_Init}, +// {"", 102, Mapper102_Init}, + {"FDS DOKIDOKI FULL", 103, Mapper103_Init}, +// {"", 104, Mapper104_Init}, + {"NES-EVENT NWC1990", 105, Mapper105_Init}, + {"SMB3 PIRATE A", 106, Mapper106_Init}, + {"MAGIC CORP A", 107, Mapper107_Init}, + {"FDS UNROM BOARD", 108, Mapper108_Init}, +// {"", 109, Mapper109_Init}, +// {"", 110, Mapper110_Init}, +// {"", 111, Mapper111_Init}, + {"ASDER/NTDEC BOARD", 112, Mapper112_Init}, + {"HACKER/SACHEN BOARD", 113, Mapper113_Init}, + {"MMC3 SG PROT. A", 114, Mapper114_Init}, + {"MMC3 PIRATE A", 115, Mapper115_Init}, + {"MMC1/MMC3/VRC PIRATE",116, UNLSL12_Init}, + {"FUTURE MEDIA BOARD", 117, Mapper117_Init}, + {"TSKROM", 118, TKSROM_Init}, + {"NES-TQROM", 119, Mapper119_Init}, + {"FDS TOBIDASE", 120, Mapper120_Init}, + {"MMC3 PIRATE PROT. A", 121, Mapper121_Init}, +// {"", 122, Mapper122_Init}, + {"MMC3 PIRATE H2288", 123, UNLH2288_Init}, +// {"", 124, Mapper124_Init}, + {"FDS LH32", 125, LH32_Init}, +// {"", 126, Mapper126_Init}, +// {"", 127, Mapper127_Init}, +// {"", 128, Mapper128_Init}, +// {"", 129, Mapper129_Init}, +// {"", 130, Mapper130_Init}, +// {"", 131, Mapper131_Init}, + {"TXC/MGENIUS 22111", 132, UNL22211_Init}, + {"SA72008", 133, SA72008_Init}, + {"MMC3 BMC PIRATE", 134, Mapper134_Init}, +// {"", 135, Mapper135_Init}, + {"TCU02", 136, TCU02_Init}, + {"S8259D", 137, S8259D_Init}, + {"S8259B", 138, S8259B_Init}, + {"S8259C", 139, S8259C_Init}, + {"JALECO JF-11/14", 140, Mapper140_Init}, + {"S8259A", 141, S8259A_Init}, + {"UNLKS7032", 142, UNLKS7032_Init}, + {"TCA01", 143, TCA01_Init}, + {"AGCI 50282", 144, Mapper144_Init}, + {"SA72007", 145, SA72007_Init}, + {"SA0161M", 146, SA0161M_Init}, + {"TCU01", 147, TCU01_Init}, + {"SA0037", 148, SA0037_Init}, + {"SA0036", 149, SA0036_Init}, + {"S74LS374N", 150, S74LS374N_Init}, + {"", 151, Mapper151_Init}, + {"", 152, Mapper152_Init}, + {"BANDAI SRAM", 153, Mapper153_Init}, // Bandai board 16 with SRAM instead of EEPROM + {"", 154, Mapper154_Init}, + {"", 155, Mapper155_Init}, + {"", 156, Mapper156_Init}, + {"BANDAI BARCODE", 157, Mapper157_Init}, +// {"", 158, Mapper158_Init}, + {"BANDAI 24C01", 159, Mapper159_Init}, // Different type of EEPROM on the bandai board + {"SA009", 160, SA009_Init}, +// {"", 161, Mapper161_Init}, + {"", 162, UNLFS304_Init}, + {"", 163, Mapper163_Init}, + {"", 164, Mapper164_Init}, + {"", 165, Mapper165_Init}, + {"SUBOR Rev. A", 166, Mapper166_Init}, + {"SUBOR Rev. B", 167, Mapper167_Init}, + {"", 168, Mapper168_Init}, +// {"", 169, Mapper169_Init}, + {"", 170, Mapper170_Init}, + {"", 171, Mapper171_Init}, + {"", 172, Mapper172_Init}, + {"", 173, Mapper173_Init}, +// {"", 174, Mapper174_Init}, + {"", 175, Mapper175_Init}, + {"BMCFK23C", 176, BMCFK23C_Init}, // zero 26-may-2012 - well, i have some WXN junk games that use 176 for instance ????. i dont know what game uses this BMCFK23C as mapper 176. we'll have to make a note when we find it. + {"", 177, Mapper177_Init}, + {"", 178, Mapper178_Init}, +// {"", 179, Mapper179_Init}, + {"", 180, Mapper180_Init}, + {"", 181, Mapper181_Init}, +// {"", 182, Mapper182_Init}, // Deprecated, dupe + {"", 183, Mapper183_Init}, + {"", 184, Mapper184_Init}, + {"", 185, Mapper185_Init}, + {"", 186, Mapper186_Init}, + {"", 187, Mapper187_Init}, + {"", 188, Mapper188_Init}, + {"", 189, Mapper189_Init}, +// {"", 190, Mapper190_Init}, + {"", 191, Mapper191_Init}, + {"TW MMC3+VRAM Rev. B", 192, Mapper192_Init}, + {"NTDEC TC-112", 193, Mapper193_Init}, // War in the Gulf + {"TW MMC3+VRAM Rev. C", 194, Mapper194_Init}, + {"TW MMC3+VRAM Rev. D", 195, Mapper195_Init}, + {"", 196, Mapper196_Init}, + {"", 197, Mapper197_Init}, + {"TW MMC3+VRAM Rev. E", 198, Mapper198_Init}, + {"", 199, Mapper199_Init}, + {"", 200, Mapper200_Init}, + {"", 201, Mapper201_Init}, + {"", 202, Mapper202_Init}, + {"", 203, Mapper203_Init}, + {"", 204, Mapper204_Init}, + {"", 205, Mapper205_Init}, + {"NAMCOT 108 Rev. C", 206, Mapper206_Init}, // Deprecated, Used to be "DEIROM" whatever it means, but actually simple version of MMC3 + {"TAITO X1-005 Rev. B", 207, Mapper207_Init}, + {"", 208, Mapper208_Init}, + {"", 209, Mapper209_Init}, + {"", 210, Mapper210_Init}, + {"", 211, Mapper211_Init}, + {"", 212, Mapper212_Init}, + {"", 213, Mapper213_Init}, + {"", 214, Mapper214_Init}, + {"", 215, UNL8237_Init}, + {"", 216, Mapper216_Init}, + {"", 217, Mapper217_Init}, // Redefined to a new Discrete BMC mapper +// {"", 218, Mapper218_Init}, + {"UNLA9746", 219, UNLA9746_Init}, + {"Debug Mapper", 220, UNLPEC586Init}, // UNLKS7057_Init}, + {"UNLN625092", 221, UNLN625092_Init}, + {"", 222, Mapper222_Init}, +// {"", 223, Mapper223_Init}, +// {"", 224, Mapper224_Init}, + {"", 225, Mapper225_Init}, + {"BMC 22+20-in-1", 226, Mapper226_Init}, + {"", 227, Mapper227_Init}, + {"", 228, Mapper228_Init}, + {"", 229, Mapper229_Init}, + {"BMC Contra+22-in-1", 230, Mapper230_Init}, + {"", 231, Mapper231_Init}, + {"BMC QUATTRO", 232, Mapper232_Init}, + {"BMC 22+20-in-1 RST", 233, Mapper233_Init}, + {"BMC MAXI", 234, Mapper234_Init}, + {"", 235, Mapper235_Init}, +// {"", 236, Mapper236_Init}, +// {"", 237, Mapper237_Init}, + {"UNL6035052", 238, UNL6035052_Init}, +// {"", 239, Mapper239_Init}, + {"", 240, Mapper240_Init}, + {"", 241, Mapper241_Init}, + {"", 242, Mapper242_Init}, + {"S74LS374NA", 243, S74LS374NA_Init}, + {"DECATHLON", 244, Mapper244_Init}, + {"", 245, Mapper245_Init}, + {"FONG SHEN BANG", 246, Mapper246_Init}, +// {"", 247, Mapper247_Init}, +// {"", 248, Mapper248_Init}, + {"", 249, Mapper249_Init}, + {"", 250, Mapper250_Init}, +// {"", 251, Mapper251_Init}, // No good dumps for this mapper, use UNIF version + {"SAN GUO ZHI PIRATE", 252, Mapper252_Init}, + {"DRAGON BALL PIRATE", 253, Mapper253_Init}, + {"", 254, Mapper254_Init}, +// {"", 255, Mapper255_Init}, // No good dumps for this mapper + {"", 0, NULL} +}; + +int iNESLoad(const uint8 *name, FCEUFILE *fp) { + struct md5_context md5; + + if (FCEU_fread(&head, 1, 16, fp) != 16) + return 0; + + if (memcmp(&head, "NES\x1a", 4)) + return 0; + + memset(&iNESCart, 0, sizeof(iNESCart)); + + if (!memcmp((char*)(&head) + 0x7, "DiskDude", 8)) { + memset((char*)(&head) + 0x7, 0, 0x9); + } + + if (!memcmp((char*)(&head) + 0x7, "demiforce", 9)) { + memset((char*)(&head) + 0x7, 0, 0x9); + } + + if (!memcmp((char*)(&head) + 0xA, "Ni03", 4)) { + if (!memcmp((char*)(&head) + 0x7, "Dis", 3)) + memset((char*)(&head) + 0x7, 0, 0x9); + else + memset((char*)(&head) + 0xA, 0, 0x6); + } + + MapperNo = (head.ROM_type >> 4); + MapperNo |= (head.ROM_type2 & 0xF0); + if (head.ROM_type & 8) { + Mirroring = 2; + } else + Mirroring = (head.ROM_type & 1); + + if (!head.ROM_size) + ROM_size = 256; + else + ROM_size = uppow2(head.ROM_size); + + VROM_size = uppow2(head.VROM_size); + + + if ((ROM = (uint8*)FCEU_malloc(ROM_size << 14)) == NULL) + return 0; + memset(ROM, 0xFF, ROM_size << 14); + + if (VROM_size) { + if ((VROM = (uint8*)FCEU_malloc(VROM_size << 13)) == NULL) { + free(ROM); + ROM = NULL; + return 0; + } + 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 << 14, 0); + + if (head.ROM_size) + FCEU_fread(ROM, 0x4000, head.ROM_size, fp); + else + FCEU_fread(ROM, 0x4000, ROM_size, fp); + + if (VROM_size) + FCEU_fread(VROM, 0x2000, 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(&GameInfo->MD5, &iNESCart.MD5, sizeof(iNESCart.MD5)); + + iNESCart.CRC32 = iNESGameCRC32; + + FCEU_printf(" PRG ROM: %3d x 16KiB\n", ROM_size); + FCEU_printf(" CHR ROM: %3d x 8KiB\n", head.VROM_size); + FCEU_printf(" ROM CRC32: 0x%08lx\n", iNESGameCRC32); + FCEU_printf(" ROM MD5: 0x%s\n", md5_asciistr(iNESCart.MD5)); + char* mappername = "Not Listed"; + + uint32 mappertest; + for (mappertest = 0; mappertest < (sizeof bmap / sizeof bmap[0]) - 1; mappertest++) { + if (bmap[mappertest].number == MapperNo) { + mappername = bmap[mappertest].name; + break; + } + } + + FCEU_printf(" Mapper #: %d\n", MapperNo); + FCEU_printf(" Mapper name: %s\n", mappername); + FCEU_printf(" Mirroring: %s\n", Mirroring == 2 ? "None (Four-screen)" : Mirroring ? "Vertical" : "Horizontal"); + FCEU_printf(" Battery-backed: %s\n", (head.ROM_type & 2) ? "Yes" : "No"); + FCEU_printf(" Trained: %s\n", (head.ROM_type & 4) ? "Yes" : "No"); + + 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) { + ExtraNTARAM = (uint8*)FCEU_gmalloc(2048); + 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 (!iNES_Init(MapperNo)) + FCEU_PrintError("iNES mapper #%d is not supported at all.", MapperNo); + + FCEU_LoadGameSave(&iNESCart); + + GameInterface = iNESGI; + FCEU_printf("\n"); + + if (strstr(name, "(E)") || strstr(name, "(e)") + || strstr(name, "(Europe)") || strstr(name, "(PAL)") + || strstr(name, "(F)") || strstr(name, "(f)") + || strstr(name, "(G)") || strstr(name, "(g)") + || strstr(name, "(I)") || strstr(name, "(i)")) + GameInfo->vidsys = GIV_PAL; + + return 1; +} + +static int iNES_Init(int num) { + BMAPPINGLocal *tmp = bmap; + + CHRRAMSize = -1; + + if (GameInfo->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) { + switch (num) { // FIXME, mapper or game data base with the board parameters and ROM/RAM sizes + case 13: CHRRAMSize = 16 * 1024; break; + case 6: + case 96: CHRRAMSize = 32 * 1024; break; + case 176: CHRRAMSize = 256 * 1024; break; + default: CHRRAMSize = 8 * 1024; break; + } + if ((VROM = (uint8*)malloc(CHRRAMSize)) == NULL) return 0; + 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/src/ines.h b/src/ines.h new file mode 100644 index 0000000..3862657 --- /dev/null +++ b/src/ines.h @@ -0,0 +1,211 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +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 NSFVRC6_Init(void); +void NSFMMC5_Init(void); +void NSFAY_Init(void); +void NSFN106_Init(void); +void NSFVRC7_Init(void); + +void Mapper1_Init(CartInfo *); +void Mapper4_Init(CartInfo *); +void Mapper5_Init(CartInfo *); +void Mapper6_Init(CartInfo *); +void Mapper8_Init(CartInfo *); +void Mapper9_Init(CartInfo *); +void Mapper10_Init(CartInfo *); +void Mapper11_Init(CartInfo *); +void Mapper12_Init(CartInfo *); +void Mapper15_Init(CartInfo *); +void Mapper16_Init(CartInfo *); +void Mapper17_Init(CartInfo *); +void Mapper18_Init(CartInfo *); +void Mapper19_Init(CartInfo *); +void Mapper21_Init(CartInfo *); +void Mapper22_Init(CartInfo *); +void Mapper23_Init(CartInfo *); +void Mapper24_Init(CartInfo *); +void Mapper25_Init(CartInfo *); +void Mapper26_Init(CartInfo *); +void Mapper32_Init(CartInfo *); +void Mapper33_Init(CartInfo *); +void Mapper34_Init(CartInfo *); +void Mapper36_Init(CartInfo *); +void Mapper37_Init(CartInfo *); +void Mapper38_Init(CartInfo *); +void Mapper40_Init(CartInfo *); +void Mapper41_Init(CartInfo *); +void Mapper42_Init(CartInfo *); +void Mapper43_Init(CartInfo *); +void Mapper44_Init(CartInfo *); +void Mapper45_Init(CartInfo *); +void Mapper46_Init(CartInfo *); +void Mapper47_Init(CartInfo *); +void Mapper48_Init(CartInfo *); +void Mapper49_Init(CartInfo *); +void Mapper50_Init(CartInfo *); +void Mapper51_Init(CartInfo *); +void Mapper52_Init(CartInfo *); +void Mapper57_Init(CartInfo *); +void Mapper59_Init(CartInfo *); +void Mapper61_Init(CartInfo *); +void Mapper62_Init(CartInfo *); +void Mapper64_Init(CartInfo *); +void Mapper65_Init(CartInfo *); +void Mapper67_Init(CartInfo *); +void Mapper68_Init(CartInfo *); +void Mapper69_Init(CartInfo *); +void Mapper70_Init(CartInfo *); +void Mapper71_Init(CartInfo *); +void Mapper72_Init(CartInfo *); +void Mapper73_Init(CartInfo *); +void Mapper74_Init(CartInfo *); +void Mapper75_Init(CartInfo *); +void Mapper76_Init(CartInfo *); +void Mapper77_Init(CartInfo *); +void Mapper78_Init(CartInfo *); +void Mapper79_Init(CartInfo *); +void Mapper80_Init(CartInfo *); +void Mapper82_Init(CartInfo *); +void Mapper83_Init(CartInfo *); +void Mapper85_Init(CartInfo *); +void Mapper86_Init(CartInfo *); +void Mapper87_Init(CartInfo *); +void Mapper88_Init(CartInfo *); +void Mapper89_Init(CartInfo *); +void Mapper90_Init(CartInfo *); +void Mapper91_Init(CartInfo *); +void Mapper92_Init(CartInfo *); +void Mapper93_Init(CartInfo *); +void Mapper94_Init(CartInfo *); +void Mapper95_Init(CartInfo *); +void Mapper96_Init(CartInfo *); +void Mapper97_Init(CartInfo *); +void Mapper99_Init(CartInfo *); +void Mapper101_Init(CartInfo *); +void Mapper103_Init(CartInfo *); +void Mapper105_Init(CartInfo *); +void Mapper106_Init(CartInfo *); +void Mapper107_Init(CartInfo *); +void Mapper108_Init(CartInfo *); +void Mapper112_Init(CartInfo *); +void Mapper113_Init(CartInfo *); +void Mapper114_Init(CartInfo *); +void Mapper115_Init(CartInfo *); +void Mapper117_Init(CartInfo *); +void Mapper119_Init(CartInfo *); +void Mapper120_Init(CartInfo *); +void Mapper121_Init(CartInfo *); +void Mapper125_Init(CartInfo *); +void Mapper134_Init(CartInfo *); +void Mapper140_Init(CartInfo *); +void Mapper144_Init(CartInfo *); +void Mapper151_Init(CartInfo *); +void Mapper152_Init(CartInfo *); +void Mapper153_Init(CartInfo *); +void Mapper154_Init(CartInfo *); +void Mapper155_Init(CartInfo *); +void Mapper156_Init(CartInfo *); +void Mapper157_Init(CartInfo *); +void Mapper159_Init(CartInfo *); +void Mapper163_Init(CartInfo *); +void Mapper164_Init(CartInfo *); +void Mapper165_Init(CartInfo *); +void Mapper166_Init(CartInfo *); +void Mapper167_Init(CartInfo *); +void Mapper168_Init(CartInfo *); +void Mapper170_Init(CartInfo *); +void Mapper171_Init(CartInfo *); +void Mapper172_Init(CartInfo *); +void Mapper173_Init(CartInfo *); +void Mapper175_Init(CartInfo *); +void Mapper177_Init(CartInfo *); +void Mapper178_Init(CartInfo *); +void Mapper180_Init(CartInfo *); +void Mapper181_Init(CartInfo *); +void Mapper183_Init(CartInfo *); +void Mapper184_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 Mapper193_Init(CartInfo *); +void Mapper194_Init(CartInfo *); +void Mapper195_Init(CartInfo *); +void Mapper196_Init(CartInfo *); +void Mapper197_Init(CartInfo *); +void Mapper198_Init(CartInfo *); +void Mapper199_Init(CartInfo *); +void Mapper200_Init(CartInfo *); +void Mapper201_Init(CartInfo *); +void Mapper202_Init(CartInfo *); +void Mapper203_Init(CartInfo *); +void Mapper204_Init(CartInfo *); +void Mapper205_Init(CartInfo *); +void Mapper206_Init(CartInfo *); +void Mapper207_Init(CartInfo *); +void Mapper208_Init(CartInfo *); +void Mapper209_Init(CartInfo *); +void Mapper210_Init(CartInfo *); +void Mapper211_Init(CartInfo *); +void Mapper212_Init(CartInfo *); +void Mapper213_Init(CartInfo *); +void Mapper214_Init(CartInfo *); +void Mapper216_Init(CartInfo *); +void Mapper217_Init(CartInfo *); +void Mapper220_Init(CartInfo *); +void Mapper222_Init(CartInfo *); +void Mapper225_Init(CartInfo *); +void Mapper226_Init(CartInfo *); +void Mapper227_Init(CartInfo *); +void Mapper228_Init(CartInfo *); +void Mapper229_Init(CartInfo *); +void Mapper230_Init(CartInfo *); +void Mapper231_Init(CartInfo *); +void Mapper232_Init(CartInfo *); +void Mapper233_Init(CartInfo *); +void Mapper234_Init(CartInfo *); +void Mapper235_Init(CartInfo *); +void Mapper236_Init(CartInfo *); +void Mapper237_Init(CartInfo *); +void Mapper240_Init(CartInfo *); +void Mapper241_Init(CartInfo *); +void Mapper242_Init(CartInfo *); +void Mapper244_Init(CartInfo *); +void Mapper245_Init(CartInfo *); +void Mapper246_Init(CartInfo *); +void Mapper249_Init(CartInfo *); +void Mapper250_Init(CartInfo *); +void Mapper252_Init(CartInfo *); +void Mapper253_Init(CartInfo *); +void Mapper254_Init(CartInfo *); diff --git a/src/input.c b/src/input.c new file mode 100644 index 0000000..815e26e --- /dev/null +++ b/src/input.c @@ -0,0 +1,425 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include + +#include "fceu-types.h" +#include "x6502.h" + +#include "fceu.h" +#include "netplay.h" +#include "movie.h" + +#include "input.h" +#include "vsuni.h" +#include "fds.h" + +extern INPUTC *FCEU_InitJoyPad(int w); +extern INPUTC *FCEU_InitZapper(int w); +extern INPUTC *FCEU_InitMouse(int w); +extern INPUTC *FCEU_InitPowerpadA(int w); +extern INPUTC *FCEU_InitPowerpadB(int w); +extern INPUTC *FCEU_InitArkanoid(int w); + +extern INPUTCFC *FCEU_InitFami4(void); +extern INPUTCFC *FCEU_InitArkanoidFC(void); +extern INPUTCFC *FCEU_InitSpaceShadow(void); +extern INPUTCFC *FCEU_InitFKB(void); +extern INPUTCFC *FCEU_InitSuborKB(void); +extern INPUTCFC *FCEU_InitPEC586KB(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); + +extern uint8 coinon; + +static void *InputDataPtr[2]; +uint8 LastStrobe; + +static int JPAttrib[2] = { 0, 0 }; +static int JPType[2] = { 0, 0 }; +static INPUTC DummyJPort = { 0, 0, 0, 0, 0 }; +static INPUTC *JPorts[2] = { &DummyJPort, &DummyJPort }; + +static int JPAttribFC = 0; +static int JPTypeFC = 0; +static void *InputDataPtrFC; +static INPUTCFC *FCExp = 0; + +void (*InputScanlineHook)(uint8 *bg, uint8 *spr, uint32 linets, int final); + +/* +#define DI 01 +#define CLK 02 +#define CS 04 +#define OUT0 01 +#define D3 01 +#define D4 02 + +typedef struct { + uint8 state; + uint8 cmd; + uint8 addr; + uint8 iswritable; + uint16 acc; + uint16 data[128]; +} EEPROM; + +EEPROM serialROM[2]; +uint8 oldCLK, bankFlip, DIFlip, OUT0state; + +uint8 serialROMautomat(uint8 chip, uint16 data) { + uint8 resp = 1; + chip &= 1; + if (!(data & CS)) { + if (!(data & CLK)) { + uint8 state = serialROM[chip].state; + uint8 mask, i; + FCEU_printf("> state = %02x\n", serialROM[chip].state); + switch (serialROM[chip].cmd) { + case 0x00: + mask = ~(1 << (state & 7)); + if (state < 8) { + serialROM[chip].addr &= mask; + serialROM[chip].addr |= ((data & 1) << (state & 7)); + if (state == 7) + FCEU_printf("> addr = %02x\n", serialROM[chip].addr); + } else if (state < 15) { + serialROM[chip].acc &= mask; + serialROM[chip].acc |= ((data & 1) << (state & 7)); + } else { + serialROM[chip].acc &= mask; + serialROM[chip].acc |= ((data & 1) << (state & 7)); + serialROM[chip].cmd = serialROM[chip].acc; + FCEU_printf("> cmd = %02x\n", serialROM[chip].cmd); + } + break; + case 0x01: + if (state < 30) + resp = (serialROM[chip].data[serialROM[chip].addr] >> (state & 15)) & 1; + else { + resp = (serialROM[chip].data[serialROM[chip].addr] >> (state & 15)) & 1; + serialROM[chip].cmd = 0; + } + break; + case 0x06: + mask = ~(1 << (state & 15)); + if (state < 30) { + serialROM[chip].acc &= mask; + serialROM[chip].acc |= ((data & 1) << (state & 15)); + } else { + serialROM[chip].acc &= mask; + serialROM[chip].acc |= ((data & 1) << (state & 15)); + if (serialROM[chip].iswritable) + serialROM[chip].data[serialROM[chip].addr] = serialROM[chip].acc; + serialROM[chip].cmd = 0; + } + break; + case 0x0C: + for (i = 0; i < 128; i++) + serialROM[chip].data[i] = 0xFFFF; + serialROM[chip].cmd = 0; + resp = 1; + break; + case 0x0D: + serialROM[chip].cmd = 0; + resp = 1; + break; + case 0x09: + serialROM[chip].cmd = 0; + serialROM[chip].iswritable = 1; + break; + case 0x0B: + serialROM[chip].cmd = 0; + serialROM[chip].iswritable = 0; + break; + default: + serialROM[chip].cmd = 0; + serialROM[chip].state = 0; + break; + } + } else { + if (serialROM[chip].cmd == 0) { + if (serialROM[chip].state > 15) + serialROM[chip].state = 0; + } else + serialROM[chip].state++; + } + } else { + serialROM[chip].cmd = 0; + serialROM[chip].state = 0; + } + return resp; +} + +uint8 serialROMstate(uint8 linestate) { + uint8 answ = 0, newCLK = linestate & CLK; + if ((!oldCLK) && newCLK) { + DIFlip ^= 1; + if (linestate && OUT0) { + serialROMautomat(bankFlip, 04 + DIFlip); + bankFlip ^= 1; + serialROMautomat(bankFlip, 02 + DIFlip); + } + } + answ = DIFlip ^ 1; + answ |= (serialROMautomat(bankFlip, newCLK + DIFlip) << 1); + oldCLK = newCLK; + return answ << 3; +}*/ + +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; + +// if(A==0x4017) +//{ +// ret |= serialROMstate(OUT0); +// serialROMstate(OUT0|CLK); +// FCEU_printf("> 4017 read %02x\n",ret); +// } + + return(ret); +} + +static DECLFW(B4016) { +// OUT0state = V; +// serialROMstate(OUT0state|CLK); +// FCEU_printf("> 4016 write %02x\n",V); + + 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))) { +// FCEUD_UpdateInput(); + 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; +} + +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_UpdateInput(void) { + int x; + + for (x = 0; x < 2; x++) { + if (JPorts[x]->Update) + JPorts[x]->Update(x, InputDataPtr[x], JPAttrib[x]); + } + if (FCExp) + if (FCExp->Update) + FCExp->Update(InputDataPtrFC, JPAttribFC); + + if (GameInfo->type == GIT_VSUNI) + if (coinon) coinon--; +} + +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_NONE: JPorts[x] = &DummyJPort; break; + case SI_GAMEPAD: JPorts[x] = FCEU_InitJoyPad(x); break; + case SI_ARKANOID: JPorts[x] = FCEU_InitArkanoid(x); break; + case SI_MOUSE: JPorts[x] = FCEU_InitMouse(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; + } + CheckSLHook(); +} + +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 = FCEU_InitFami4(); break; + case SIFC_FKB: FCExp = FCEU_InitFKB(); break; + case SIFC_SUBORKB: FCExp = FCEU_InitSuborKB(); break; + case SIFC_PEC586KB: FCExp = FCEU_InitPEC586KB(); 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) { + LastStrobe = 0; + if (GameInfo->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_SetInputFC(int type, void *ptr, int attrib) { + JPAttribFC = attrib; + JPTypeFC = type; + InputDataPtrFC = ptr; + SetInputStuffFC(); +} + +void FCEU_DoSimpleCommand(int cmd) { + switch (cmd) { + case FCEUNPCMD_FDSINSERT: FCEU_FDSInsert(-1); 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) { +#ifdef NETWORK + if (FCEUnetplay) + FCEUNET_SendCommand(cmd, 0); + else +#endif + { + if (!FCEUMOV_IsPlaying()) + FCEU_DoSimpleCommand(cmd); + else + FCEUMOV_AddCommand(cmd); + } +} + +void FCEUI_FDSSelect(void) { + FCEU_QSimpleCommand(FCEUNPCMD_FDSSELECT); +} + +int FCEUI_FDSInsert(int oride) { + 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); +} + diff --git a/src/input.h b/src/input.h new file mode 100644 index 0000000..1c80afc --- /dev/null +++ b/src/input.h @@ -0,0 +1,26 @@ +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); +void InitializeInput(void); +extern void (*PStrobe[2])(void); +extern void (*InputScanlineHook)(uint8 *bg, uint8 *spr, uint32 linets, int final); + +void FCEU_DoSimpleCommand(int cmd); + diff --git a/src/input/arkanoid.c b/src/input/arkanoid.c new file mode 100644 index 0000000..453dfdf --- /dev/null +++ b/src/input/arkanoid.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#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; + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + 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; + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + 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/src/input/bbox.c b/src/input/bbox.c new file mode 100644 index 0000000..c236b55 --- /dev/null +++ b/src/input/bbox.c @@ -0,0 +1,194 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +/* +#include +#include +#include "share.h" + +#define DI 01 +#define CLK 02 +#define CS 04 +#define OUT0 01 +#define D3 01 +#define D4 02 + +typedef struct +{ + uint8 state; + uint8 cmd; + uint8 addr; + uint8 iswritable; + uint16 acc; + uint16 data[128]; +} EEPROM; + +EEPROM serialROM[2]; +uint8 oldCLK, bankFlip, DIFlip, OUT0state; + +uint8 serialROMautomat(uint8 chip, uint16 data) +{ + uint8 resp = 1; + chip &= 1; + if(!(data & CS)) + { + if(!(data & CLK)) + { + uint8 state = serialROM[chip].state; + uint8 mask, i; + switch (serialROM[chip].cmd) + { + case 0x00: + mask = ~(1<<(state&7)); + if(state<8) + { + serialROM[chip].addr &= mask; + serialROM[chip].addr |= ((data&1)<<(state&7)); + } + else if(state<15) + { + serialROM[chip].acc &= mask; + serialROM[chip].acc |= ((data&1)<<(state&7)); + } + else + { + serialROM[chip].acc &= mask; + serialROM[chip].acc |= ((data&1)<<(state&7)); + serialROM[chip].cmd = serialROM[chip].acc; + } + break; + case 0x01: + if(state<30) + resp = (serialROM[chip].data[serialROM[chip].addr]>>(state&15))&1; + else + { + resp = (serialROM[chip].data[serialROM[chip].addr]>>(state&15))&1; + serialROM[chip].cmd = 0; + } + break; + case 0x06: + mask = ~(1<<(state&15)); + if(state<30) + { + serialROM[chip].acc &= mask; + serialROM[chip].acc |= ((data&1)<<(state&15)); + } + else + { + serialROM[chip].acc &= mask; + serialROM[chip].acc |= ((data&1)<<(state&15)); + if(serialROM[chip].iswritable) + serialROM[chip].data[serialROM[chip].addr] = serialROM[chip].acc; + serialROM[chip].cmd = 0; + } + break; + case 0x0C: + for(i=0;i<128;i++) + serialROM[chip].data[i] = 0xFFFF; + serialROM[chip].cmd = 0; + resp = 1; + break; + case 0x0D: + serialROM[chip].cmd = 0; + resp = 1; + break; + case 0x09: + serialROM[chip].cmd = 0; + serialROM[chip].iswritable = 1; + break; + case 0x0B: + serialROM[chip].cmd = 0; + serialROM[chip].iswritable = 0; + break; + default: + serialROM[chip].cmd = 0; + serialROM[chip].state = 0; + break; + } + } + else + { + if(serialROM[chip].cmd == 0) + { + if(serialROM[chip].state>15) + serialROM[chip].state = 0; + } + else + serialROM[chip].cmd++; + } + } + else + { + serialROM[chip].cmd = 0; + serialROM[chip].state = 0; + } + return resp; +} + +uint8 serialROMstate(uint8 linestate) +{ + uint8 answ = 0, newCLK = linestate & CLK; + if((!oldCLK)&&newCLK) + { + DIFlip^=1; + if(linestate&&OUT0) + { + serialROMautomat(bankFlip, 04+DIFlip); + bankFlip^=1; + serialROMautomat(bankFlip, 02+DIFlip); + } + } + answ = DIFlip^1; + answ |= (serialROMautomat(bankFlip, newCLK+DIFlip)<<1); + oldCLK = newCLK; + return answ; +} + +static uint8 FP_FASTAPASS(2) BBRead(int w, uint8 ret) +{ + if(w) + { + serialROMstate(OUT0); + ret |= serialROMstate(OUT0|CLK); + } + return(ret); +} + +static void FP_FASTAPASS(1) BBWrite(uint8 V) +{ + OUT0state = V; + serialROMstate(OUT0state?OUT0:0); +} + +static INPUTCFC BattleBox={BBRead,BBWrite,0,0,0,0}; + +INPUTCFC *FCEU_InitBattleBox(void) +{ + oldCLK = 1; + bankFlip = 0; + DIFlip = 0; + serialROM[0].iswritable = 1; + serialROMautomat(0, 4); + serialROM[1].iswritable = 1; + serialROMautomat(1, 4); + serialROMautomat(bankFlip, 02+DIFlip); + return(&BattleBox); +} + +*/ diff --git a/src/input/bworld.c b/src/input/bworld.c new file mode 100644 index 0000000..d1bf57c --- /dev/null +++ b/src/input/bworld.c @@ -0,0 +1,65 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#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/src/input/cursor.c b/src/input/cursor.c new file mode 100644 index 0000000..7f88573 --- /dev/null +++ b/src/input/cursor.c @@ -0,0 +1,79 @@ +#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/src/input/fkb.c b/src/input/fkb.c new file mode 100644 index 0000000..1f39619 --- /dev/null +++ b/src/input/fkb.c @@ -0,0 +1,89 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "share.h" +#include "fkb.h" +#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) { + 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; +} + +static void FP_FASTAPASS(2) FKB_Update(void *data, int arg) { + memcpy(bufit + 1, data, sizeof(bufit) - 1); +} + +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/src/input/fkb.h b/src/input/fkb.h new file mode 100644 index 0000000..d635d9d --- /dev/null +++ b/src/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/src/input/ftrainer.c b/src/input/ftrainer.c new file mode 100644 index 0000000..b6c71ac --- /dev/null +++ b/src/input/ftrainer.c @@ -0,0 +1,69 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#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/src/input/hypershot.c b/src/input/hypershot.c new file mode 100644 index 0000000..d62c623 --- /dev/null +++ b/src/input/hypershot.c @@ -0,0 +1,46 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#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/src/input/mahjong.c b/src/input/mahjong.c new file mode 100644 index 0000000..9c4c383 --- /dev/null +++ b/src/input/mahjong.c @@ -0,0 +1,71 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#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; + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + 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/src/input/mouse.c b/src/input/mouse.c new file mode 100644 index 0000000..6f7cd83 --- /dev/null +++ b/src/input/mouse.c @@ -0,0 +1,86 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include "share.h" + +typedef struct { + int32 mzx, mzy, mzxold, mzyold; + uint32 readbit; + uint32 data; +} MOUSE; + +static MOUSE Mouse; + +static void FP_FASTAPASS(1) StrobeMOUSE(int w) { + Mouse.readbit = 0; + if ((Mouse.mzxold - Mouse.mzx) > 0) + Mouse.data |= 0x0C; + else if ((Mouse.mzxold - Mouse.mzx) < 0) + Mouse.data |= 0x04; + if ((Mouse.mzyold - Mouse.mzy) > 0) + Mouse.data |= 0x30; + else if ((Mouse.mzyold - Mouse.mzy) < 0) + Mouse.data |= 0x10; +} + +static uint8 FP_FASTAPASS(1) ReadMOUSE(int w) { + uint8 ret = 0; + if (Mouse.readbit >= 8) + ret |= 1; + else { + ret |= (Mouse.data >> Mouse.readbit) & 1; + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + Mouse.readbit++; + } + return(ret); +} + +static void FP_FASTAPASS(3) UpdateMOUSE(int w, void *data, int arg) { + uint32 *ptr = (uint32*)data; + Mouse.data = 0; + Mouse.mzxold = Mouse.mzx; + Mouse.mzyold = Mouse.mzy; + Mouse.mzx = ptr[0]; + Mouse.mzy = ptr[1]; + Mouse.data |= ptr[2]; + if ((Mouse.mzxold - Mouse.mzx) > 0) + Mouse.data |= 0x0C; + else if ((Mouse.mzxold - Mouse.mzx) < 0) + Mouse.data |= 0x04; + if ((Mouse.mzyold - Mouse.mzy) > 0) + Mouse.data |= 0x30; + else if ((Mouse.mzyold - Mouse.mzy) < 0) + Mouse.data |= 0x10; +} + +static INPUTC MOUSEC = { ReadMOUSE, 0, StrobeMOUSE, UpdateMOUSE, 0, 0 }; + +INPUTC *FCEU_InitMouse(int w) { + Mouse.mzx = 0; + Mouse.mzy = 0; + Mouse.mzxold = 0; + Mouse.mzyold = 0; + Mouse.data = 0; + return(&MOUSEC); +} diff --git a/src/input/oekakids.c b/src/input/oekakids.c new file mode 100644 index 0000000..e806f15 --- /dev/null +++ b/src/input/oekakids.c @@ -0,0 +1,85 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#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/src/input/pads.c b/src/input/pads.c new file mode 100644 index 0000000..ae07636 --- /dev/null +++ b/src/input/pads.c @@ -0,0 +1,136 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "share.h" +#include "../movie.h" +#include "../vsuni.h" + +static uint8 joy_readbit[2]; +static uint8 joy[4] = { 0, 0, 0, 0 }; + +static int FSDisable = 0; /* Set to 1 if NES-style four-player adapter is disabled. */ +void FCEUI_DisableFourScore(int s) { + FSDisable = s; +} + +extern uint8 LastStrobe; + +SFORMAT FCEUCTRL_STATEINFO[] = { + { joy_readbit, 2, "JYRB" }, + { joy, 4, "JOYS" }, + { &LastStrobe, 1, "LSTS" }, + { 0 } +}; + +/* This function is a quick hack to get the NSF player to use emulated gamepad + input. +*/ +uint8 FCEU_GetJoyJoy(void) { + return(joy[0] | joy[1] | joy[2] | joy[3]); +} + +static void FP_FASTAPASS(1) StrobeGP(int w) { + joy_readbit[w] = 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); + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + 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; + } + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + joy_readbit[w]++; + return ret; +} + +static void FP_FASTAPASS(3) UpdateGP(int w, void *data, int arg) { + uint32 *ptr = (uint32*)data; + if (!w) { + joy[0] = *(uint32*)ptr; + joy[2] = *(uint32*)ptr >> 16; + } else { + joy[1] = *(uint32*)ptr >> 8; + joy[3] = *(uint32*)ptr >> 24; + } +#ifdef NETWORK + if (FCEUnetplay) NetplayUpdate(joy); +#endif + FCEUMOV_AddJoy(joy); + if (GameInfo->type == GIT_VSUNI) + FCEU_VSUniSwap(&joy[0], &joy[1]); +} + +static INPUTC GPC = { ReadGP, 0, StrobeGP, UpdateGP, 0, 0 }; +static INPUTC GPCVS = { ReadGPVS, 0, StrobeGP, UpdateGP, 0, 0 }; + +INPUTC *FCEU_InitJoyPad(int w) { + joy_readbit[w] = 0; + joy[w] = 0; + joy[w + 2] = 0; + if (GameInfo->type == GIT_VSUNI) + return(&GPCVS); + else + return(&GPC); +} + +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 }; +INPUTCFC *FCEU_InitFami4(int w) { + memset(&F4ReadBit, 0, sizeof(F4ReadBit)); + return(&FAMI4C); +} diff --git a/src/input/pec586kb.c b/src/input/pec586kb.c new file mode 100644 index 0000000..356d837 --- /dev/null +++ b/src/input/pec586kb.c @@ -0,0 +1,96 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "share.h" +#include "suborkb.h" + +#define AK(x) FKB_ ## x + +static uint8 bufit[0x66]; +static uint8 kspos, kstrobe; +static uint8 ksindex; + +//TODO: check all keys, some of the are wrong + +static uint16 matrix[13][8] = +{ + { AK(ESCAPE),AK(SPACE),AK(LMENU),AK(LCONTROL),AK(LSHIFT),AK(GRAVE),AK(TAB),AK(CAPITAL) }, + { AK(F6),AK(F7),AK(F5),AK(F4),AK(F8),AK(F2),AK(F1),AK(F3) }, + { AK(EQUALS), AK(NUMPAD0),AK(PERIOD),AK(A),AK(RETURN),AK(1),AK(Q),AK(Z) }, + { 0, AK(NUMPAD3),AK(NUMPAD6),AK(S),AK(NUMPAD9),AK(2),AK(W),AK(X) }, + { AK(SLASH), AK(NUMPAD2),AK(NUMPAD5),AK(D),AK(NUMPAD8),AK(3),AK(E),AK(C) }, + { AK(BREAK), AK(NUMPAD1),AK(NUMPAD4),AK(F),AK(NUMPAD7),AK(4),AK(R),AK(V) }, + { AK(BACK),AK(BACKSLASH),AK(GRETURN),AK(G),AK(RBRACKET),AK(5),AK(T),AK(B) }, + { AK(9),AK(PERIOD),AK(L),AK(K),AK(O),AK(8),AK(I),AK(COMMA) }, + { AK(0),AK(SLASH),AK(SEMICOLON),AK(J),AK(P),AK(7),AK(U),AK(M) }, + { AK(MINUS),AK(MINUS),AK(APOSTROPHE),AK(H),AK(LBRACKET),AK(6),AK(Y),AK(N) }, + { AK(F11),AK(F12),AK(F10),0,AK(MINUS),AK(F9),0,0 }, + { AK(UP),AK(RIGHT),AK(DOWN),AK(DIVIDE),AK(LEFT),AK(MULTIPLY),AK(SUBTRACT),AK(ADD) }, + { AK(INSERT),AK(NUMPAD1),AK(HOME),AK(PRIOR),AK(DELETE),AK(END),AK(NEXT),AK(NUMLOCK) }, +}; + +static void FP_FASTAPASS(1) PEC586KB_Write(uint8 v) { + if (!(kstrobe & 2) && (v & 2)) { + kspos = 0; + } + if ((kstrobe & 1) && !(v & 1)) { + ksindex = 0; + } + if ((kstrobe & 4) && !(v & 4)) { + kspos++; + kspos %= 13; + } + kstrobe = v; +} + +static uint8 FP_FASTAPASS(2) PEC586KB_Read(int w, uint8 ret) { +#ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) { +#endif + if (w) { + ret &= ~2; + if(bufit[matrix[kspos][7-ksindex]]) + ret |= 2; + ksindex++; + ksindex&=7; + } +#ifdef FCEUDEF_DEBUGGER + } +#endif + return(ret); +} + +static void PEC586KB_Strobe(void) { +// kstrobe = 0; +// ksindex = 0; +} + +static void FP_FASTAPASS(2) PEC586KB_Update(void *data, int arg) { + memcpy(bufit + 1, data, sizeof(bufit) - 1); +} + +static INPUTCFC PEC586KB = { PEC586KB_Read, PEC586KB_Write, PEC586KB_Strobe, PEC586KB_Update, 0, 0 }; + +INPUTCFC *FCEU_InitPEC586KB(void) { + memset(bufit, 0, sizeof(bufit)); + kspos = ksindex = kstrobe = 0; + return(&PEC586KB); +} diff --git a/src/input/powerpad.c b/src/input/powerpad.c new file mode 100644 index 0000000..62bed8e --- /dev/null +++ b/src/input/powerpad.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#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; + } + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + 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/src/input/quiz.c b/src/input/quiz.c new file mode 100644 index 0000000..d20305d --- /dev/null +++ b/src/input/quiz.c @@ -0,0 +1,66 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#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/src/input/shadow.c b/src/input/shadow.c new file mode 100644 index 0000000..3d74402 --- /dev/null +++ b/src/input/shadow.c @@ -0,0 +1,136 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#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 { + if (ZD.zap_readbit == 1) { + ret &= ~2; + 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_DrawGunSight(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/src/input/share.h b/src/input/share.h new file mode 100644 index 0000000..36cf1fa --- /dev/null +++ b/src/input/share.h @@ -0,0 +1,12 @@ +#include "../fceu-types.h" +#include "../input.h" +#include "../fceu.h" +#include "../ppu.h" +#include "../x6502.h" +#include "../palette.h" +#include "../state.h" +#include "../netplay.h" + + +void FCEU_DrawCursor(uint8 *buf, int xc, int yc); +void FCEU_DrawGunSight(uint8 *buf, int xc, int yc); diff --git a/src/input/suborkb.c b/src/input/suborkb.c new file mode 100644 index 0000000..2102d55 --- /dev/null +++ b/src/input/suborkb.c @@ -0,0 +1,84 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "share.h" +#include "suborkb.h" +#define AK(x) FKB_ ## x + +static uint8 bufit[0x66]; +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) } }, + { { AK(NUMPAD6), AK(GRETURN), AK(NUMPAD4), AK(NUMPAD8) }, { AK(NUMPAD2), 0, 0, 0 } }, // baibaidino actually uses diferent layot + { { 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; + for (x = 0; x < 4; x++) + if (bufit[matrix[ksindex][ksmode & 1][x]]) + 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, sizeof(bufit) - 1); +} + +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/src/input/suborkb.h b/src/input/suborkb.h new file mode 100644 index 0000000..db01bd4 --- /dev/null +++ b/src/input/suborkb.h @@ -0,0 +1,102 @@ +#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 +#define FKB_RSHIFT 0x60 +#define FKB_RMENU 0x61 +#define FKB_RCONTROL 0x62 +#define FKB_BREAK 0x63 +#define FKB_RESET 0x64 +#define FKB_GRETURN 0x65 + diff --git a/src/input/toprider.c b/src/input/toprider.c new file mode 100644 index 0000000..e05bbe2 --- /dev/null +++ b/src/input/toprider.c @@ -0,0 +1,52 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#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; + } + return(ret); +} + +static void FP_FASTAPASS(1) Write(uint8 V) { + bs = bss; +} + +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/src/input/zapper.c b/src/input/zapper.c new file mode 100644 index 0000000..0553a82 --- /dev/null +++ b/src/input/zapper.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#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; + } + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + 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; + + 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 (GameInfo->type == GIT_VSUNI) + return(&ZAPVSC); + else + return(&ZAPC); +} + + diff --git a/src/md5.c b/src/md5.c new file mode 100644 index 0000000..f674bbc --- /dev/null +++ b/src/md5.c @@ -0,0 +1,237 @@ +/* + * RFC 1321 compliant MD5 implementation, + * by Christophe Devine ; + * this program is licensed under the GPL. + */ + +/* Modified October 3, 2003, to remove testing code, and add + include of "fceu-types.h". + + Added simple MD5 to ASCII string conversion function. + -Xodnizel +*/ + +#include +#include "fceu-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] >> 4]; + str[x * 2 + 1] = trans[digest[x] & 0x0F]; + } + return(str); +} diff --git a/src/md5.h b/src/md5.h new file mode 100644 index 0000000..dfe7330 --- /dev/null +++ b/src/md5.h @@ -0,0 +1,17 @@ +#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/src/memory.c b/src/memory.c new file mode 100644 index 0000000..de7a90e --- /dev/null +++ b/src/memory.c @@ -0,0 +1,88 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "fceu-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/src/memory.h b/src/memory.h new file mode 100644 index 0000000..b0808e3 --- /dev/null +++ b/src/memory.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* Various macros for faster memory stuff + (at least that's the idea) +*/ + +#ifndef _FCEU_MEMORY_H_ +#define _FCEU_MEMORY_H_ + +#include "fceu-types.h" + +#define FCEU_dwmemset(d, c, n) { int _x; for (_x = n - 4; _x >= 0; _x -= 4) *(uint32*)& (d)[_x] = c; } + +#if defined(STATE_LIBRETRO) || defined(ENDIAN_LIBRETRO) || defined(GENERAL_LIBRETRO) +#include "drivers/libretro/memstream.h" + +#define HAVE_MEMSTREAM +#define MEM_TYPE memstream_t + +#define fwrite(ptr, size, nmemb, stream) memstream_write((stream), (ptr), (nmemb)) +#define fclose(fp) memstream_close((fp)) +#define fgetc(stream) memstream_getc((stream)) +#define fputc(c, stream) memstream_putc((stream), (c)) +#define ftell(a) memstream_pos((a)) +#define fread(ptr, size, nmemb, stream) memstream_read((stream), (ptr), (nmemb)) +#define fseek(stream, offset, whence) memstream_seek((stream), (offset), (whence)) +#else +#define MEM_TYPE FILE +#endif + +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); + +#endif diff --git a/src/movie.c b/src/movie.c new file mode 100644 index 0000000..e9a5851 --- /dev/null +++ b/src/movie.c @@ -0,0 +1,253 @@ +#include +#include +#include + +#include "fceu-types.h" +#include "input.h" +#include "fceu.h" +#include "driver.h" +#include "state.h" +#include "general.h" +#include "video.h" + +static int current = 0; // > 0 for recording, < 0 for playback +static FILE *slots[10] = { 0 }; +static uint8 joop[4]; +static uint32 framets; + +/* Cache variables used for playback. */ +static uint32 nextts; +static int nextd; + + +static int CurrentMovie = 0; +static int MovieShow = 0; + +static int MovieStatus[10]; + +static void DoEncode(int joy, int button, int); + +int FCEUMOV_IsPlaying(void) { + if (current < 0) return(1); + else return(0); +} + +void FCEUI_SaveMovie(char *fname) { + FILE *fp; + char *fn; + + if (current < 0) /* Can't interrupt playback.*/ + return; + + if (current > 0) { /* Stop saving. */ + DoEncode(0, 0, 1); /* Write a dummy timestamp value so that the movie will keep + "playing" after user input has stopped. */ + fclose(slots[current - 1]); + MovieStatus[current - 1] = 1; + current = 0; + FCEU_DispMessage("Movie recording stopped."); + return; + } + + current = CurrentMovie; + + if (fname) + fp = FCEUD_UTF8fopen(fname, "wb"); + else { + fp = FCEUD_UTF8fopen(fn = FCEU_MakeFName(FCEUMKF_MOVIE, CurrentMovie, 0), "wb"); + free(fn); + } + + if (!fp) return; + + FCEUSS_SaveFP(fp); + fseek(fp, 0, SEEK_END); + slots[current] = fp; + memset(joop, 0, sizeof(joop)); + current++; + framets = 0; + FCEUI_SelectMovie(CurrentMovie); /* Quick hack to display status. */ +} + +static void StopPlayback(void) { + fclose(slots[-1 - current]); + current = 0; + FCEU_DispMessage("Movie playback stopped."); +} + +void FCEUMOV_Stop(void) { + if (current < 0) StopPlayback(); +} + +void FCEUI_LoadMovie(char *fname) { + FILE *fp; + char *fn; + + if (current > 0) /* Can't interrupt recording.*/ + return; + + if (current < 0) { /* Stop playback. */ + StopPlayback(); + return; + } + + if (fname) + fp = FCEUD_UTF8fopen(fname, "rb"); + else { + fp = FCEUD_UTF8fopen(fn = FCEU_MakeFName(FCEUMKF_MOVIE, CurrentMovie, 0), "rb"); + free(fn); + } + if (!fp) return; + + if (!FCEUSS_LoadFP(fp)) return; + + current = CurrentMovie; + slots[current] = fp; + + memset(joop, 0, sizeof(joop)); + current = -1 - current; + framets = 0; + nextts = 0; + nextd = -1; + MovieStatus[CurrentMovie] = 1; + FCEUI_SelectMovie(CurrentMovie); /* Quick hack to display status. */ +} + + +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; + + fputc(d, slots[current - 1]); + //printf("Wr: %02x, %d\n",d,slots[current-1]); + while (framets) { + fputc(framets & 0xff, slots[current - 1]); + //printf("Wrts: %02x\n",framets & 0xff); + framets >>= 8; + } +} + +void FCEUMOV_AddJoy(uint8 *js) { + int x, y; + + if (!current) return; /* Not playback nor recording. */ + + if (current < 0) { /* Playback */ + while (nextts == framets) { + 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 = fgetc(slots[-1 - current]); + d = tmp; + + if (tmp < 0) { + StopPlayback(); + return; + } + + nextts = 0; + tmp >>= 5; + tmp &= 0x3; + ti = 0; + + { + int tmpfix = tmp; + while (tmp--) { + nextts |= fgetc(slots[-1 - current]) << (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 |= fgetc(slots[-1 - current]) << 8; + } else if (tmpfix == 2 && !nextts) { + nextts |= fgetc(slots[-1 - current]) << 16; + } + + framets = 0; + nextd = d; + } + } + memcpy(js, joop, 4); + } else { /* Recording */ + 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. */ + } + } + framets++; +} + +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_SelectMovie(int w) { + if (w == -1) { + MovieShow = 0; return; + } + FCEUI_SelectState(-1); + + CurrentMovie = w; + 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-"); +} + +void FCEU_DrawMovies(uint8 *XBuf) { + if (!MovieShow) return; + + FCEU_DrawNumberRow(XBuf, MovieStatus, CurrentMovie); + MovieShow--; +} + diff --git a/src/movie.h b/src/movie.h new file mode 100644 index 0000000..5742d0d --- /dev/null +++ b/src/movie.h @@ -0,0 +1,7 @@ +void FCEUMOV_AddJoy(uint8 *); +void FCEUMOV_CheckMovies(void); +void FCEUMOV_Stop(void); +void FCEUMOV_AddCommand(int cmd); +void FCEU_DrawMovies(uint8 *); +int FCEUMOV_IsPlaying(void); + diff --git a/src/netplay.c b/src/netplay.c new file mode 100644 index 0000000..772f9a5 --- /dev/null +++ b/src/netplay.c @@ -0,0 +1,307 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "fceu-types.h" +#include "netplay.h" +#include "fceu.h" +#include "general.h" +#include "state.h" +#include "cheat.h" +#include "input.h" +#include "endian.h" + +#ifndef __LIBRETRO__ +#define NETPLAY_ENABLED +#endif + +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) { +#ifdef NETPLAY_ENABLED + 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); +#endif + return(1); +} + +static FILE *FetchFile(uint32 remlen) { +#ifdef NETPLAY_ENABLED + 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); +#endif + 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)) { + 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/src/netplay.h b/src/netplay.h new file mode 100644 index 0000000..5c319a9 --- /dev/null +++ b/src/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/src/nsf.c b/src/nsf.c new file mode 100644 index 0000000..39b069f --- /dev/null +++ b/src/nsf.c @@ -0,0 +1,519 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include + +#include "fceu-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]; + + GameInfo->type = GIT_NSF; + GameInfo->input[0] = GameInfo->input[1] = SI_GAMEPAD; + GameInfo->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) + GameInfo->vidsys = GIV_NTSC; + else if (NSFHeader.VideoSystem == 1) + GameInfo->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); + 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; + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + SongReload = 0; + return x; + case 0x3ff1: + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + { + 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/src/nsf.h b/src/nsf.h new file mode 100644 index 0000000..37af219 --- /dev/null +++ b/src/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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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/src/ops.h b/src/ops.h new file mode 100644 index 0000000..7f30c60 --- /dev/null +++ b/src/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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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; + uint32 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/src/palette.c b/src/palette.c new file mode 100644 index 0000000..f24145f --- /dev/null +++ b/src/palette.c @@ -0,0 +1,326 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "fceu-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 (GameInfo) { + ChoosePalette(); + WritePalette(); + } +} + +static void ChoosePalette(void) { + if (GameInfo->type == GIT_NSF) + palo = 0; + else if (ipalette) + palo = palettei; + else if (ntsccol && !PAL && GameInfo->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 (GameInfo->type == GIT_NSF) { + } 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 && GameInfo->type != GIT_VSUNI && !PAL && GameInfo->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 && GameInfo->type != GIT_VSUNI && !PAL && GameInfo->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 && GameInfo->type != GIT_VSUNI && !PAL && GameInfo->type != GIT_NSF) { + controlselect = 1; controllength = 360; + } +} + +void FCEUI_NTSCSELTINT(void) { + if (ntsccol && GameInfo->type != GIT_VSUNI && !PAL && GameInfo->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/src/palette.h b/src/palette.h new file mode 100644 index 0000000..a6b16d2 --- /dev/null +++ b/src/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/src/palettes/conv.c b/src/palettes/conv.c new file mode 100644 index 0000000..07c9820 --- /dev/null +++ b/src/palettes/conv.c @@ -0,0 +1,72 @@ +/* Quick conversion stuff for MAME->FCE Ultra */ + +#include +#include "../fceu-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/src/palettes/palettes.h b/src/palettes/palettes.h new file mode 100644 index 0000000..53c7faa --- /dev/null +++ b/src/palettes/palettes.h @@ -0,0 +1,93 @@ +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] = { + { 0x1D << 2, 0x1D << 2, 0x1D << 2 }, /* Value 0 */ + { 0x09 << 2, 0x06 << 2, 0x23 << 2 }, /* Value 1 */ + { 0x00 << 2, 0x00 << 2, 0x2A << 2 }, /* Value 2 */ + { 0x11 << 2, 0x00 << 2, 0x27 << 2 }, /* Value 3 */ + { 0x23 << 2, 0x00 << 2, 0x1D << 2 }, /* Value 4 */ + { 0x2A << 2, 0x00 << 2, 0x04 << 2 }, /* Value 5 */ + { 0x29 << 2, 0x00 << 2, 0x00 << 2 }, /* Value 6 */ + { 0x1F << 2, 0x02 << 2, 0x00 << 2 }, /* Value 7 */ + { 0x10 << 2, 0x0B << 2, 0x00 << 2 }, /* Value 8 */ + { 0x00 << 2, 0x11 << 2, 0x00 << 2 }, /* Value 9 */ + { 0x00 << 2, 0x14 << 2, 0x00 << 2 }, /* Value 10 */ + { 0x00 << 2, 0x0F << 2, 0x05 << 2 }, /* Value 11 */ + { 0x06 << 2, 0x0F << 2, 0x17 << 2 }, /* Value 12 */ + { 0x00 << 2, 0x00 << 2, 0x00 << 2 }, /* Value 13 */ + { 0x00 << 2, 0x00 << 2, 0x00 << 2 }, /* Value 14 */ + { 0x00 << 2, 0x00 << 2, 0x00 << 2 }, /* Value 15 */ + { 0x2F << 2, 0x2F << 2, 0x2F << 2 }, /* Value 16 */ + { 0x00 << 2, 0x1C << 2, 0x3B << 2 }, /* Value 17 */ + { 0x08 << 2, 0x0E << 2, 0x3B << 2 }, /* Value 18 */ + { 0x20 << 2, 0x00 << 2, 0x3C << 2 }, /* Value 19 */ + { 0x2F << 2, 0x00 << 2, 0x2F << 2 }, /* Value 20 */ + { 0x39 << 2, 0x00 << 2, 0x16 << 2 }, /* Value 21 */ + { 0x36 << 2, 0x0A << 2, 0x00 << 2 }, /* Value 22 */ + { 0x32 << 2, 0x13 << 2, 0x03 << 2 }, /* Value 23 */ + { 0x22 << 2, 0x1C << 2, 0x00 << 2 }, /* Value 24 */ + { 0x00 << 2, 0x25 << 2, 0x00 << 2 }, /* Value 25 */ + { 0x00 << 2, 0x2A << 2, 0x00 << 2 }, /* Value 26 */ + { 0x00 << 2, 0x24 << 2, 0x0E << 2 }, /* Value 27 */ + { 0x00 << 2, 0x20 << 2, 0x22 << 2 }, /* Value 28 */ + { 0x00 << 2, 0x00 << 2, 0x00 << 2 }, /* Value 29 */ + { 0x00 << 2, 0x00 << 2, 0x00 << 2 }, /* Value 30 */ + { 0x00 << 2, 0x00 << 2, 0x00 << 2 }, /* Value 31 */ + { 0x3F << 2, 0x3F << 2, 0x3F << 2 }, /* Value 32 */ + { 0x0F << 2, 0x2F << 2, 0x3F << 2 }, /* Value 33 */ + { 0x17 << 2, 0x25 << 2, 0x3F << 2 }, /* Value 34 */ + { 0x10 << 2, 0x22 << 2, 0x3F << 2 }, /* Value 35 */ + { 0x3D << 2, 0x1E << 2, 0x3F << 2 }, /* Value 36 */ + { 0x3F << 2, 0x1D << 2, 0x2D << 2 }, /* Value 37 */ + { 0x3F << 2, 0x1D << 2, 0x18 << 2 }, /* Value 38 */ + { 0x3F << 2, 0x26 << 2, 0x0E << 2 }, /* Value 39 */ + { 0x3C << 2, 0x2F << 2, 0x0F << 2 }, /* Value 40 */ + { 0x20 << 2, 0x34 << 2, 0x04 << 2 }, /* Value 41 */ + { 0x13 << 2, 0x37 << 2, 0x12 << 2 }, /* Value 42 */ + { 0x16 << 2, 0x3E << 2, 0x26 << 2 }, /* Value 43 */ + { 0x00 << 2, 0x3A << 2, 0x36 << 2 }, /* Value 44 */ + { 0x1E << 2, 0x1E << 2, 0x1E << 2 }, /* Value 45 */ + { 0x00 << 2, 0x00 << 2, 0x00 << 2 }, /* Value 46 */ + { 0x00 << 2, 0x00 << 2, 0x00 << 2 }, /* Value 47 */ + { 0x3F << 2, 0x3F << 2, 0x3F << 2 }, /* Value 48 */ + { 0x2A << 2, 0x39 << 2, 0x3F << 2 }, /* Value 49 */ + { 0x31 << 2, 0x35 << 2, 0x3F << 2 }, /* Value 50 */ + { 0x35 << 2, 0x32 << 2, 0x3F << 2 }, /* Value 51 */ + { 0x3F << 2, 0x31 << 2, 0x3F << 2 }, /* Value 52 */ + { 0x3F << 2, 0x31 << 2, 0x36 << 2 }, /* Value 53 */ + { 0x3F << 2, 0x2F << 2, 0x2C << 2 }, /* Value 54 */ + { 0x3F << 2, 0x36 << 2, 0x2A << 2 }, /* Value 55 */ + { 0x3F << 2, 0x39 << 2, 0x28 << 2 }, /* Value 56 */ + { 0x38 << 2, 0x3F << 2, 0x28 << 2 }, /* Value 57 */ + { 0x2A << 2, 0x3C << 2, 0x2F << 2 }, /* Value 58 */ + { 0x2C << 2, 0x3F << 2, 0x33 << 2 }, /* Value 59 */ + { 0x27 << 2, 0x3F << 2, 0x3C << 2 }, /* Value 60 */ + { 0x31 << 2, 0x31 << 2, 0x31 << 2 }, /* Value 61 */ + { 0x00 << 2, 0x00 << 2, 0x00 << 2 }, /* Value 62 */ + { 0x00 << 2, 0x00 << 2, 0x00 << 2 }, /* Value 63 */ +}; diff --git a/src/palettes/rp2c04001.h b/src/palettes/rp2c04001.h new file mode 100644 index 0000000..afcf799 --- /dev/null +++ b/src/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/src/palettes/rp2c04002.h b/src/palettes/rp2c04002.h new file mode 100644 index 0000000..6694949 --- /dev/null +++ b/src/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/src/palettes/rp2c04003.h b/src/palettes/rp2c04003.h new file mode 100644 index 0000000..1024604 --- /dev/null +++ b/src/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/src/palettes/rp2c05004.h b/src/palettes/rp2c05004.h new file mode 100644 index 0000000..32f390f --- /dev/null +++ b/src/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/src/ppu.c b/src/ppu.c new file mode 100644 index 0000000..9962ff8 --- /dev/null +++ b/src/ppu.c @@ -0,0 +1,1278 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "fceu-types.h" +#include "x6502.h" +#include "fceu.h" +#include "ppu.h" +#include "nsf.h" +#include "sound.h" +#include "general.h" +#include "fceu-endian.h" +#include "memory.h" +#include "ppuview.h" + +#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 GRAYSCALE (PPU[1] & 0x01) //Grayscale (AND palette entries with 0x30) + +#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; + int cc, xo, pixel; + + + 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; + } + + 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); + } + } + } +} + +static int ppudead = 1; +static int kook = 0; +int fceuindbg = 0; + +int MMC5Hack = 0, PEC586Hack = 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]; +uint8 UPALRAM[0x03];//for 0x4/0x8/0xC addresses in palette, the ones in + //0x20 are 0 to not break fceu rendering. + +#define MMC5SPRVRAMADR(V) &MMC5SPRVPage[(V) >> 10][(V)] +#define VRAMADR(V) &VPage[(V) >> 10][(V)] + +uint8 * MMC5BGVRAMADR(uint32 V) { + if (!Sprite16) { + extern uint8 mmc5ABMode; /* A=0, B=1 */ + if (mmc5ABMode == 0) + return MMC5SPRVRAMADR(V); + else + return &MMC5BGVPage[(V) >> 10][(V)]; + } else return &MMC5BGVPage[(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(A2007) { + uint8 ret; + uint32 tmp = RefreshAddr & 0x3FFF; + + FCEUPPU_LineUpdate(); + + if (tmp >= 0x3F00) { // Palette RAM tied directly to the output data, without VRAM buffer + if (!(tmp & 3)) { + if (!(tmp & 0xC)) + ret = PALRAM[0x00]; + else + ret = UPALRAM[((tmp & 0xC) >> 2) - 1]; + } else + ret = PALRAM[tmp & 0x1F]; + if (GRAYSCALE) + ret &= 0x30; + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + { + if ((tmp - 0x1000) < 0x2000) + VRAMBuffer = VPage[(tmp - 0x1000) >> 10][tmp - 0x1000]; + else + VRAMBuffer = vnapage[((tmp - 0x1000) >> 10) & 0x3][(tmp - 0x1000) & 0x3FF]; + if (PPU_hook) PPU_hook(tmp); + } + } else { + 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 if (tmp < 0x3F00) + VRAMBuffer = vnapage[(tmp >> 10) & 0x3][tmp & 0x3FF]; + } + } + + #ifdef FCEUDEF_DEBUGGER + if (!fceuindbg) + #endif + { + if ((ScreenON || SpriteON) && (scanline < 240)) { + uint32 rad = RefreshAddr; + if ((rad & 0x7000) == 0x7000) { + rad ^= 0x7000; + if ((rad & 0x3E0) == 0x3A0) + rad ^= 0xBA0; + else if ((rad & 0x3E0) == 0x3e0) + rad ^= 0x3e0; + else + rad += 0x20; + } else + rad += 0x1000; + RefreshAddr = rad; + } else { + if (INC32) + RefreshAddr += 32; + else + RefreshAddr++; + } + if (PPU_hook) PPU_hook(RefreshAddr & 0x3fff); + } + return ret; +} + +static DECLFW(B2000) { + FCEUPPU_LineUpdate(); + PPUGenLatch = V; + + if (!(PPU[0] & 0x80) && (V & 0x80) && (PPU_status & 0x80)) + TriggerNMI2(); + + PPU[0] = V; + TempAddr &= 0xF3FF; + TempAddr |= (V & 3) << 10; +} + +static DECLFW(B2001) { + FCEUPPU_LineUpdate(); + PPUGenLatch = V; + PPU[1] = V; + if (V & 0xE0) + deemp = V >> 5; +} + +static DECLFW(B2002) { + PPUGenLatch = V; +} + +static DECLFW(B2003) { + PPUGenLatch = V; + PPU[3] = V; + PPUSPL = V & 0x7; +} + +static DECLFW(B2004) { + PPUGenLatch = V; + if (PPUSPL >= 8) { + if (PPU[3] >= 8) + SPRAM[PPU[3]] = V; + } else { + 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); + } + vtoggle ^= 1; +} + +static DECLFW(B2007) { + uint32 tmp = RefreshAddr & 0x3FFF; + PPUGenLatch = V; + if (tmp < 0x2000) { + if (PPUCHRRAM & (1 << (tmp >> 10))) + VPage[tmp >> 10][tmp] = V; + } else if (tmp < 0x3F00) { + if (PPUNTARAM & (1 << ((tmp & 0xF00) >> 10))) + vnapage[((tmp & 0xF00) >> 10)][tmp & 0x3FF] = V; + } else { + if (!(tmp & 3)) { + if (!(tmp & 0xC)) + PALRAM[0x00] = PALRAM[0x04] = PALRAM[0x08] = PALRAM[0x0C] = V & 0x3F; + else + UPALRAM[((tmp & 0xC) >> 2) - 1] = V & 0x3F; + } else + PALRAM[tmp & 0x1F] = V & 0x3F; + } + 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 ADDCYC(x) \ + { \ + int __x = x; \ + X.tcount += __x; \ + X.count -= __x * 48; \ + timestamp += __x; \ + } + ADDCYC(1); +#undef ADDCYC +} + +#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) { + 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 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) && x < 255) { + PPU_status |= 0x40; + sphitx = 0x100; + break; + } + } +} + +//spork the world. Any sprites on this line? Then this will be set to 1. +//Needed for zapper emulation and *gasp* sprite emulation. +static int spork = 0; + +// 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))) + lasttile++; + } + + if (lasttile > 34) lasttile = 34; + numtiles = lasttile - firsttile; + + if (numtiles <= 0) return; + + P = Pline; + + vofs = 0; + + if(PEC586Hack) + vofs = ((RefreshAddr & 0x200) << 3) | ((RefreshAddr >> 12) & 7); + else + 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 + if (PEC586Hack) { + #define PPU_BGFETCH + for (X1 = firsttile; X1 < lasttile; X1++) { + #include "pputile.h" + } + #undef PPU_BGFETCH + } else { + for (X1 = firsttile; X1 < lasttile; X1++) { + #include "pputile.h" + } + } + #undef PPUT_HOOK + norecurse = 0; + } else { + if (PEC586Hack) { + #define PPU_BGFETCH + for (X1 = firsttile; X1 < lasttile; X1++) { + #include "pputile.h" + } + #undef PPU_BGFETCH + } 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) { + Fixit1(); + tofix = 0; + } + + //This only works right because of a hack earlier in this function. + CheckSpriteHit(lastpixel); + + 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; + } +} + +static void Fixit1(void) { + if (ScreenON || SpriteON) { + uint32 rad = RefreshAddr; + + if ((rad & 0x7000) == 0x7000) { + rad ^= 0x7000; + if ((rad & 0x3E0) == 0x3A0) + rad ^= 0xBA0; + else if ((rad & 0x3E0) == 0x3e0) + rad ^= 0x3e0; + else + rad += 0x20; + } else + rad += 0x1000; + RefreshAddr = rad; + } +} + +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 = (uint32)(P0 & 0x8 & (((P0 & 0x20) ^ 0x20) >> 2)) << 9; + H += (P0 & 0x20) >> 2; + + if (!PPU_hook) + for (n = 63; n >= 0; n--, spr++) { + if ((uint32)(scanline - spr->y) >= H) continue; + if (ns < maxsprites) { + if (n == 63) sb = 1; + + { + SPRB dst; + uint8 *C; + int t; + uint32 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 ((uint32)(scanline - spr->y) >= H) continue; + + if (ns < maxsprites) { + if (n == 63) sb = 1; + + { + SPRB dst; + uint8 *C; + int t; + uint32 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; + } + } + + //Handle case when >8 sprites per scanline option is enabled. + if (ns > 8) PPU_status |= 0x20; + 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--) { + register uint32 pixdata; + register uint8 J, atr; + + 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; +} + +void FCEUPPU_Power(void) { + int x; + + memset(NTARAM, 0x00, 0x800); + memset(PALRAM, 0x00, 0x20); + memset(UPALRAM, 0x00, 0x03); + memset(SPRAM, 0x00, 0x100); + FCEUPPU_Reset(); +#ifdef COPYFAMI + for (x = 0x2000; x < 0x2010; 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; + } +#else + 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; + } +#endif + BWrite[0x4014] = B4014; +} + + +int FCEUPPU_Loop(int skip) { + //Needed for Knight Rider, possibly others. + if (ppudead) { + memset(XBuf, 0x80, 256 * 240); + X6502_Run(scanlines_per_frame * (256 + 85)); + ppudead--; + } else { + X6502_Run(256 + 85); + PPU_status |= 0x80; + + //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. + PPU[3] = PPUSPL = 0; + + //I need to figure out the true nature and length of this delay. + X6502_Run(12); + if (GameInfo->type == GIT_NSF) + DoNSFFrame(); + else { + if (VBlankON) + TriggerNMI(); + } + X6502_Run((scanlines_per_frame - 242) * (256 + 85) - 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 (GameInfo->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]++; + if ((PPUViewer) && (scanline == PPUViewScanline)) UpdatePPUView(1); + 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; + } + SetNESDeemph(maxref, 0); + } + } + + #ifdef FRAMESKIP + if (skip) { + FCEU_PutImageDummy(); + return(0); + } else + #endif + { + 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, "VTGL" }, + { &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/src/ppu.h b/src/ppu.h new file mode 100644 index 0000000..42f112c --- /dev/null +++ b/src/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 (*GameHBIRQHook)(void), (*GameHBIRQHook2)(void); +extern void FP_FASTAPASS(1) (*PPU_hook)(uint32 A); + +/* 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/src/pputile.h b/src/pputile.h new file mode 100644 index 0000000..b31c3ba --- /dev/null +++ b/src/pputile.h @@ -0,0 +1,109 @@ +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)]; + + 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]; + 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 + +#ifdef PPU_BGFETCH + if (RefreshAddr & 1) { + pshift[0] |= C[8]; + pshift[1] |= C[8]; + } else { + pshift[0] |= C[0]; + pshift[1] |= C[0]; + } +#else + pshift[0] |= C[0]; + pshift[1] |= C[8]; +#endif + +if ((RefreshAddr & 0x1f) == 0x1f) + RefreshAddr ^= 0x41F; +else + RefreshAddr++; + +#ifdef PPUT_HOOK + PPU_hook(0x2000 | (RefreshAddr & 0xfff)); +#endif + diff --git a/src/ppuview.h b/src/ppuview.h new file mode 100644 index 0000000..f072e30 --- /dev/null +++ b/src/ppuview.h @@ -0,0 +1,8 @@ +extern int PPUViewScanline; +extern int PPUViewer; +extern int scanline; + +void PPUViewDoBlit(); +void DoPPUView(); +void UpdatePPUView(int refreshchr); + diff --git a/src/sound.c b/src/sound.c new file mode 100644 index 0000000..f07794a --- /dev/null +++ b/src/sound.c @@ -0,0 +1,1145 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include + +#include "fceu-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] = +{ + 0x0A, 0xFE, 0x14, 0x02, 0x28, 0x04, 0x50, 0x06, + 0xa0, 0x08, 0x3c, 0x0a, 0x0e, 0x0c, 0x1a, 0x0e, + 0x0c, 0x10, 0x18, 0x12, 0x30, 0x14, 0x60, 0x16, + 0xc0, 0x18, 0x48, 0x1a, 0x10, 0x1c, 0x20, 0x1E +}; + +static const uint32 NTSCNoiseFreqTable[0x10] = +{ + 0x004, 0x008, 0x010, 0x020, 0x040, 0x060, 0x080, 0x0A0, + 0x0CA, 0x0FE, 0x17C, 0x1FC, 0x2FA, 0x3F8, 0x7F2, 0xFE4 +}; + +static const uint32 PALNoiseFreqTable[0x10] = +{ + 0x004, 0x007, 0x00E, 0x01E, 0x03C, 0x058, 0x076, 0x094, + 0x0BC, 0x0EC, 0x162, 0x1D8, 0x2C4, 0x3B0, 0x762, 0xEC2 +}; + +static const uint32 NTSCDMCTable[0x10] = +{ + 0x1AC, 0x17C, 0x154, 0x140, 0x11E, 0x0FE, 0x0E2, 0x0D6, + 0x0BE, 0x0A0, 0x08E, 0x080, 0x06A, 0x054, 0x048, 0x036 +}; + +static const uint32 PALDMCTable[0x10] = +{ + 0x18E, 0x162, 0x13C, 0x12A, 0x114, 0x0EC, 0x0D2, 0x0C6, + 0x0B0, 0x094, 0x084, 0x076, 0x062, 0x04E, 0x042, 0x032 +}; + +// $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) { +// FCEU_printf("APU1 %04x:%04x\n",A,V); + 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) { +// FCEU_printf("APU1 %04x:%04x\n",A,V); + 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; +// FCEU_printf("APU1 %04x:%04x\n",A,V); + + 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) { + uint32 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]> 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> 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: + //used to added <<(16+2) when the noise table + //values were half. + if (PAL) + noiseacc += PALNoiseFreqTable[PSG[0xE] & 0xF] << (16 + 1); + else + noiseacc += NTSCNoiseFreqTable[PSG[0xE] & 0xF] << (16 + 1); + nreg = (nreg << 1) + (((nreg >> nshift) ^ (nreg >> 14)) & 1); + nreg &= 0x7fff; + noiseout = amptab[(nreg >> 0xe) & 1]; + 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: + //used to be added <<(16+2) when the noise table + //values were half. + if (PAL) + noiseacc += PALNoiseFreqTable[PSG[0xE] & 0xF] << (16 + 1); + else + noiseacc += NTSCNoiseFreqTable[PSG[0xE] & 0xF] << (16 + 1); + nreg = (nreg << 1) + (((nreg >> nshift) ^ (nreg >> 14)) & 1); + nreg &= 0x7fff; + noiseout = amptab[(nreg >> 0xe) & 1]; + 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) { + uint32 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 >> 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; + if (PAL) + wlcount[3] = PALNoiseFreqTable[PSG[0xE] & 0xF]; + else + wlcount[3] = NTSCNoiseFreqTable[PSG[0xE] & 0xF]; + 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; + if (PAL) + wlcount[3] = PALNoiseFreqTable[PSG[0xE] & 0xF]; + else + wlcount[3] = NTSCNoiseFreqTable[PSG[0xE] & 0xF]; + 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 & 2) + 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; +} + +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, "5VDM" }, + { &DMCHaveSample, 1, "5VSP" }, + + { &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/src/sound.h b/src/sound.h new file mode 100644 index 0000000..70183f1 --- /dev/null +++ b/src/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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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/src/state.c b/src/state.c new file mode 100644 index 0000000..a0dc249 --- /dev/null +++ b/src/state.c @@ -0,0 +1,437 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* TODO: Add (better) file io error checking */ +/* TODO: Change save state file format. */ + +#ifdef __LIBRETRO__ +#define STATE_LIBRETRO +#endif + +#include +#include +#include +#include + +#include "fceu-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" + +static void (*SPreSave)(void); +static void (*SPostSave)(void); + +static int SaveStateStatus[10]; +static int StateShow; + + +static SFORMAT SFMDATA[64]; +static int SFEXINDEX; + +#define RLSB FCEUSTATE_RLSB //0x80000000 + + +extern SFORMAT FCEUPPU_STATEINFO[]; +extern SFORMAT FCEUSND_STATEINFO[]; +extern SFORMAT FCEUCTRL_STATEINFO[]; + + +SFORMAT SFCPU[] = { + { &X.PC, 2 | RLSB, "PC\0" }, + { &X.A, 1, "A\0\0" }, + { &X.X, 1, "X\0\0" }, + { &X.Y, 1, "Y\0\0" }, + { &X.S, 1, "S\0\0" }, + { &X.P, 1, "P\0\0" }, + { &X.DB, 1, "DB"}, +#ifdef COPYFAMI + { RAM, 0x4000, "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" }, + { ×tampbase, sizeof(timestampbase) | RLSB, "TSBS" }, + { 0 } +}; + +static int SubWrite(MEM_TYPE *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(MEM_TYPE *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 (!strncmp(desc, sf->desc, 4)) { + if (tsize != (sf->s & (~RLSB))) + return(0); + return(sf); + } + sf++; + } + return(0); +} + +static int ReadStateChunk(MEM_TYPE *st, SFORMAT *sf, int size) { + 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 ReadStateChunks(MEM_TYPE *st, int32 totalsize) { + int t; + uint32 size; + int ret = 1; + + 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 2: + if (!ReadStateChunk(st, SFCPUC, size)) + ret = 0; + else { + X.mooPI = X.P; // Quick and dirty hack. + } + break; + case 3: if (!ReadStateChunk(st, FCEUPPU_STATEINFO, size)) ret = 0; break; + case 4: if (!ReadStateChunk(st, FCEUCTRL_STATEINFO, size)) ret = 0; break; + case 5: if (!ReadStateChunk(st, FCEUSND_STATEINFO, size)) ret = 0; break; + case 0x10: if (!ReadStateChunk(st, SFMDATA, size)) ret = 0; + break; + default: if (fseek(st, size, SEEK_CUR) < 0) goto endo; break; + } + } + endo: + return ret; +} + + +int CurrentState = 0; +extern int geniestage; + +int FCEUSS_SaveFP(MEM_TYPE *st) { + static uint32 totalsize; + uint8 header[16] = { 0 }; + + header[0] = 'F'; + header[1] = 'C'; + header[2] = 'S'; + header[3] = 0xFF; + + 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 (SPreSave) SPreSave(); + totalsize += WriteStateChunk(st, 0x10, SFMDATA); + if (SPreSave) SPostSave(); + + fseek(st, 4, SEEK_SET); + write32le(totalsize, st); + return(1); +} + +void FCEUSS_Save(char *fname) { + MEM_TYPE *st = NULL; + char *fn; + + if (geniestage == 1) { + FCEU_DispMessage("Cannot save FCS in GG screen."); + return; + } + +#ifdef HAVE_MEMSTREAM + st = memstream_open(1); +#else + if (fname) + st = FCEUD_UTF8fopen(fname, "wb"); + else { + st = FCEUD_UTF8fopen(fn = FCEU_MakeFName(FCEUMKF_STATE, CurrentState, 0), "wb"); + free(fn); + } + + if (st == NULL) { + FCEU_DispMessage("State %d save error.", CurrentState); + return; + } +#endif + + FCEUSS_SaveFP(st); + + SaveStateStatus[CurrentState] = 1; + fclose(st); +#ifndef HAVE_MEMSTREAM + FCEU_DispMessage("State %d saved.", CurrentState); +#endif +} + +int FCEUSS_LoadFP(MEM_TYPE *st) { + int x; + uint8 header[16]; + int stateversion; + + 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; + + x = ReadStateChunks(st, *(uint32*)(header + 4)); + if (stateversion < 9500) X.IRQlow = 0; + + if (GameStateRestore) GameStateRestore(stateversion); + if (x) { + FCEUPPU_LoadState(stateversion); + FCEUSND_LoadState(stateversion); + } + return(x); +} + +int FCEUSS_Load(char *fname) { + MEM_TYPE *st; + char *fn; + +#ifdef HAVE_MEMSTREAM + st = memstream_open(0); +#else + 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); + } +#endif + + if (FCEUSS_LoadFP(st)) { +#ifndef HAVE_MEMSTREAM + SaveStateStatus[CurrentState] = 1; + FCEU_DispMessage("State %d loaded.", CurrentState); +#endif + SaveStateStatus[CurrentState] = 1; + fclose(st); + return(1); + } else { + SaveStateStatus[CurrentState] = 1; +#ifndef HAVE_MEMSTREAM + FCEU_DispMessage("Error(s) reading state %d!", CurrentState); +#endif + fclose(st); + return(0); + } +} + +void FCEUSS_CheckStates(void) { + MEM_TYPE *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 = 0; + StateShow = 0; +} + +void ResetExState(void (*PreSave)(void), void (*PostSave)(void)) { + SPreSave = PreSave; + SPostSave = PostSave; + SFEXINDEX = 0; +} + +void AddExState(void *v, uint32 s, int type, char *desc) { + memset(SFMDATA[SFEXINDEX].desc, 0, sizeof(SFMDATA[SFEXINDEX].desc)); + if (desc) + strncpy(SFMDATA[SFEXINDEX].desc, desc, sizeof(SFMDATA[SFEXINDEX].desc)); + SFMDATA[SFEXINDEX].v = v; + SFMDATA[SFEXINDEX].s = s; + if (type) SFMDATA[SFEXINDEX].s |= RLSB; + if (SFEXINDEX < 63) SFEXINDEX++; + SFMDATA[SFEXINDEX].v = 0; // End marker. +} + +void FCEUI_SelectState(int w) { + if (w == -1) { + StateShow = 0; return; + } + FCEUI_SelectMovie(-1); + + CurrentState = w; + StateShow = 180; + FCEU_DispMessage("-select state-"); +} + +void FCEUI_SaveState(char *fname) { + StateShow = 0; + FCEUSS_Save(fname); +} + +void FCEUI_LoadState(char *fname) { + StateShow = 0; + + FCEUMOV_Stop(); + + /* 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); + MEM_TYPE *fp; + + if ((fp = fopen(fn, "wb"))) { + if (FCEUSS_SaveFP(fp)) { + fclose(fp); + FCEUNET_SendFile(FCEUNPCMD_LOADSTATE, fn); + } else fclose(fp); + unlink(fn); + } + free(fn); + } +} + +void FCEU_DrawSaveStates(uint8 *XBuf) { + if (!StateShow) return; + + FCEU_DrawNumberRow(XBuf, SaveStateStatus, CurrentState); + StateShow--; +} + diff --git a/src/state.h b/src/state.h new file mode 100644 index 0000000..b9a0529 --- /dev/null +++ b/src/state.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FCEU_STATE_H_ +#define _FCEU_STATE_H_ + +#include "memory.h" + +void FCEUSS_Save(char *); +int FCEUSS_Load(char *); +int FCEUSS_SaveFP(MEM_TYPE *); +int FCEUSS_LoadFP(MEM_TYPE *); + +extern int CurrentState; +void FCEUSS_CheckStates(void); + +typedef struct { + void *v; + uint32 s; + char desc[4]; +} 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); + +#endif diff --git a/src/unif.c b/src/unif.c new file mode 100644 index 0000000..142860f --- /dev/null +++ b/src/unif.c @@ -0,0 +1,622 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* TODO: Battery backup file saving, mirror force */ +/* **INCOMPLETE** */ +/* Override stuff: CHR RAM instead of CHR ROM, mirroring. */ + +#include +#include +#include + + +#include "fceu-types.h" +#include "fceu.h" +#include "cart.h" +#include "unif.h" +#include "ines.h" +#include "general.h" +#include "state.h" +#include "fceu-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; + +#ifdef __LIBRETRO__ +CartInfo UNIFCart; +#else +static CartInfo UNIFCart; +#endif + +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) { + uint32 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) { + int t; + uint32 i; + if (uchead.info == 1) { + if ((t = FCEU_fgetc(fp)) == EOF) + return(0); + 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]); + } + } else { + FCEU_printf(" Incorrect Mirroring Chunk Size (%d). Data is:", uchead.info); + for (i = 0; i < uchead.info; i++) { + if ((t = FCEU_fgetc(fp)) == EOF) + return(0); + FCEU_printf(" %02x", t); + } + FCEU_printf("\n Default Name/Attribute Table Mirroring: Horizontal\n", uchead.info); + mirrortodo = 0; + } + 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 (!GameInfo->name) { + GameInfo->name = malloc(strlen(namebuf) + 1); + strcpy(GameInfo->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; + uint32 i; + if (uchead.info == 1) { + 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) + GameInfo->input[0] = GameInfo->input[1] = SI_GAMEPAD; + else + GameInfo->input[0] = GameInfo->input[1] = SI_NONE; + if (t & 2) + GameInfo->input[1] = SI_ZAPPER; + } else { + FCEU_printf(" Incorrect Control Chunk Size (%d). Data is:", uchead.info); + for (i = 0; i < uchead.info; i++) { + t = FCEU_fgetc(fp); + FCEU_printf(" %02x", t); + } + FCEU_printf("\n"); + GameInfo->input[0] = GameInfo->input[1] = SI_GAMEPAD; + } + 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) + GameInfo->vidsys = GIV_NTSC; + else if (t == 1) + GameInfo->vidsys = GIV_PAL; + 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 +#define BMCFLAG_EXPCHRR 8 + +static BMAPPING bmap[] = { + { "11160", BMC11160_Init, 0 }, + { "12-IN-1", BMC12IN1_Init, 0 }, + { "13in1JY110", BMC13in1JY110_Init, 0 }, + { "190in1", BMC190in1_Init, 0 }, + { "22211", UNL22211_Init, 0 }, + { "3D-BLOCK", UNL3DBlock_Init, 0 }, + { "411120-C", BMC411120C_Init, 0 }, + { "42in1ResetSwitch", Mapper226_Init, 0 }, + { "43272", UNL43272_Init, 0 }, + { "603-5052", UNL6035052_Init, 0 }, + { "64in1NoRepeat", BMC64in1nr_Init, 0 }, + { "70in1", BMC70in1_Init, 0 }, + { "70in1B", BMC70in1B_Init, 0 }, + { "810544-C-A1", BMC810544CA1_Init, 0 }, + { "8157", UNL8157_Init, 0 }, + { "8237", UNL8237_Init, 0 }, + { "8237A", UNL8237A_Init, 0 }, + { "830118C", BMC830118C_Init, 0 }, + { "A65AS", BMCA65AS_Init, 0 }, + { "AC08", AC08_Init, 0 }, + { "ANROM", ANROM_Init, 0 }, + { "AX5705", UNLAX5705_Init, 0 }, + { "BB", UNLBB_Init, 0 }, + { "BS-5", BMCBS5_Init, 0 }, + { "CC-21", UNLCC21_Init, 0 }, + { "CITYFIGHT", UNLCITYFIGHT_Init, 0 }, + { "CNROM", CNROM_Init, 0 }, + { "CPROM", CPROM_Init, BMCFLAG_16KCHRR }, + { "D1038", BMCD1038_Init, 0 }, + { "DANCE", UNLOneBus_Init, 0 }, // redundant + { "DANCE2000", UNLD2000_Init, 0 }, + { "DREAMTECH01", DreamTech01_Init, 0 }, + { "EDU2000", UNLEDU2000_Init, 0 }, + { "EKROM", EKROM_Init, 0 }, + { "ELROM", ELROM_Init, 0 }, + { "ETROM", ETROM_Init, 0 }, + { "EWROM", EWROM_Init, 0 }, + { "FK23C", BMCFK23C_Init, BMCFLAG_EXPCHRR }, + { "FK23CA", BMCFK23CA_Init, BMCFLAG_EXPCHRR }, + { "FS304", UNLFS304_Init, 0 }, + { "G-146", BMCG146_Init, 0 }, + { "GK-192", BMCGK192_Init, 0 }, + { "GS-2004", BMCGS2004_Init, 0 }, + { "GS-2013", BMCGS2013_Init, 0 }, + { "Ghostbusters63in1", BMCGhostbusters63in1_Init, 0 }, + { "H2288", UNLH2288_Init, 0 }, + { "HKROM", HKROM_Init, 0 }, + { "KOF97", UNLKOF97_Init, 0 }, + { "KONAMI-QTAI", Mapper190_Init, 0 }, + { "KS7012", UNLKS7012_Init, 0 }, + { "KS7013B", UNLKS7013B_Init, 0 }, + { "KS7017", UNLKS7017_Init, 0 }, + { "KS7030", UNLKS7030_Init, 0 }, + { "KS7031", UNLKS7031_Init, 0 }, + { "KS7032", UNLKS7032_Init, 0 }, + { "KS7037", UNLKS7037_Init, 0 }, + { "KS7057", UNLKS7057_Init, 0 }, + { "LE05", LE05_Init, 0 }, + { "LH10", LH10_Init, 0 }, + { "LH32", LH32_Init, 0 }, + { "LH53", LH53_Init, 0 }, + { "MALISB", UNLMaliSB_Init, 0 }, + { "MARIO1-MALEE2", MALEE_Init, 0 }, + { "MHROM", MHROM_Init, 0 }, + { "N625092", UNLN625092_Init, 0 }, + { "NROM", NROM_Init, 0 }, + { "NROM-128", NROM_Init, 0 }, + { "NROM-256", NROM_Init, 0 }, + { "NTBROM", Mapper68_Init, 0 }, + { "NTD-03", BMCNTD03_Init, 0 }, + { "NovelDiamond9999999in1", Novel_Init, 0 }, + { "OneBus", UNLOneBus_Init, 0 }, + { "PEC-586", UNLPEC586Init, 0 }, + { "RROM", NROM_Init, 0 }, + { "RROM-128", NROM_Init, 0 }, + { "SA-002", TCU02_Init, 0 }, + { "SA-0036", SA0036_Init, 0 }, + { "SA-0037", SA0037_Init, 0 }, + { "SA-009", SA009_Init, 0 }, + { "SA-016-1M", SA0161M_Init, 0 }, + { "SA-72007", SA72007_Init, 0 }, + { "SA-72008", SA72008_Init, 0 }, + { "SA-9602B", SA9602B_Init, BMCFLAG_32KCHRR }, + { "SA-NROM", TCA01_Init, 0 }, + { "SAROM", SAROM_Init, 0 }, + { "SBROM", SBROM_Init, 0 }, + { "SC-127", UNLSC127_Init, 0 }, + { "SCROM", SCROM_Init, 0 }, + { "SEROM", SEROM_Init, 0 }, + { "SGROM", SGROM_Init, 0 }, + { "SHERO", UNLSHeroes_Init, 0 }, + { "SKROM", SKROM_Init, 0 }, + { "SL12", UNLSL12_Init, 0 }, + { "SL1632", UNLSL1632_Init, 0 }, + { "SL1ROM", SL1ROM_Init, 0 }, + { "SLROM", SLROM_Init, 0 }, + { "SMB2J", UNLSMB2J_Init, 0 }, + { "SNROM", SNROM_Init, 0 }, + { "SOROM", SOROM_Init, 0 }, + { "SSS-NROM-256", SSSNROM_Init, 0 }, + { "SUNSOFT_UNROM", SUNSOFT_UNROM_Init, 0 }, // fix me, real pcb name, real pcb type + { "Sachen-74LS374N", S74LS374N_Init, 0 }, + { "Sachen-74LS374NA", S74LS374NA_Init, 0 }, //seems to be custom mapper + { "Sachen-8259A", S8259A_Init, 0 }, + { "Sachen-8259B", S8259B_Init, 0 }, + { "Sachen-8259C", S8259C_Init, 0 }, + { "Sachen-8259D", S8259D_Init, 0 }, + { "Super24in1SC03", Super24_Init, 0 }, + { "SuperHIK8in1", Mapper45_Init, 0 }, + { "Supervision16in1", Supervision16_Init, 0 }, + { "T-227-1", BMCT2271_Init, 0 }, + { "T-230", UNLT230_Init, 0 }, + { "T-262", BMCT262_Init, 0 }, + { "TBROM", TBROM_Init, 0 }, + { "TC-U01-1.5M", TCU01_Init, 0 }, + { "TEK90", Mapper90_Init, 0 }, + { "TEROM", TEROM_Init, 0 }, + { "TF1201", UNLTF1201_Init, 0 }, + { "TFROM", TFROM_Init, 0 }, + { "TGROM", TGROM_Init, 0 }, + { "TKROM", TKROM_Init, 0 }, + { "TKSROM", TKSROM_Init, 0 }, + { "TLROM", TLROM_Init, 0 }, + { "TLSROM", TLSROM_Init, 0 }, + { "TQROM", TQROM_Init, 0 }, + { "TR1ROM", TFROM_Init, BMCFLAG_FORCE4 }, + { "TSROM", TSROM_Init, 0 }, + { "TVROM", TLROM_Init, BMCFLAG_FORCE4 }, + { "Transformer", Transformer_Init, 0 }, + { "UNROM", UNROM_Init, 0 }, + { "UOROM", UNROM_Init, 0 }, + { "VRC7", UNLVRC7_Init, 0 }, + { "YOKO", UNLYOKO_Init, 0 }, + +#ifdef COPYFAMI + { "COPYFAMI_MMC3", MapperCopyFamiMMC3_Init, 0 }, + { "COPYFAMI", MapperCopyFami_Init, 0 }, +#endif + + { NULL, NULL, 0 } +}; + +static BFMAPPING bfunc[] = { + { "CTRL", CTRL }, + { "TVCI", TVCI }, + { "BATR", EnableBattery }, + { "MIRR", DoMirroring }, + { "PRG", LoadPRG }, + { "CHR", LoadCHR }, + { "NAME", NAME }, + { "MAPR", SetBoardName }, + { "DINF", DINF }, + { NULL, NULL } +}; + +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; + 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 if (bmap[x].flags & BMCFLAG_32KCHRR) + CHRRAMSize = 32768; + else if (bmap[x].flags & BMCFLAG_EXPCHRR) + CHRRAMSize = 256 * 1024; + 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%s\n", md5_asciistr(UNIFCart.MD5)); + memcpy(GameInfo->MD5, UNIFCart.MD5, sizeof(UNIFCart.MD5)); + } + + if (!InitializeBoard()) + goto aborto; + + FCEU_LoadGameSave(&UNIFCart); + GameInterface = UNIFGI; + return 1; + + aborto: + + FreeUNIF(); + ResetUNIF(); + return 0; +} + +int CopyFamiLoad() { + ResetCartMapping(); + ResetExState(0, 0); + + sboardname = "COPYFAMI"; + if (!InitializeBoard()) + goto aborto; + + FCEU_LoadGameSave(&UNIFCart); + GameInterface = UNIFGI; + return 1; + + aborto: + + FreeUNIF(); + ResetUNIF(); + return 0; +} diff --git a/src/unif.h b/src/unif.h new file mode 100644 index 0000000..7f53983 --- /dev/null +++ b/src/unif.h @@ -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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +void AC08_Init(CartInfo *info); +void ANROM_Init(CartInfo *info); +void BMC11160_Init(CartInfo *info); +void BMC12IN1_Init(CartInfo *info); +void BMC13in1JY110_Init(CartInfo *info); +void BMC190in1_Init(CartInfo *info); +void BMC411120C_Init(CartInfo *info); +void BMC64in1nr_Init(CartInfo *info); +void BMC70in1B_Init(CartInfo *info); +void BMC70in1_Init(CartInfo *info); +void BMC810544CA1_Init(CartInfo *info); +void BMC830118C_Init(CartInfo *info); +void BMCA65AS_Init(CartInfo *info); +void BMCBS5_Init(CartInfo *info); +void BMCD1038_Init(CartInfo *info); +void BMCFK23CA_Init(CartInfo *info); +void BMCFK23C_Init(CartInfo *info); +void BMCG146_Init(CartInfo *info); +void BMCGK192_Init(CartInfo *info); +void BMCGS2004_Init(CartInfo *info); +void BMCGS2013_Init(CartInfo *info); +void BMCGhostbusters63in1_Init(CartInfo *info); +void BMCNTD03_Init(CartInfo *info); +void BMCT2271_Init(CartInfo *info); +void BMCT262_Init(CartInfo *info); +void CNROM_Init(CartInfo *info); +void CPROM_Init(CartInfo *info); +void DreamTech01_Init(CartInfo *info); +void EKROM_Init(CartInfo *info); +void ELROM_Init(CartInfo *info); +void ETROM_Init(CartInfo *info); +void EWROM_Init(CartInfo *info); +void GNROM_Init(CartInfo *info); +void HKROM_Init(CartInfo *info); +void LE05_Init(CartInfo *info); +void LH10_Init(CartInfo *info); +void LH32_Init(CartInfo *info); +void LH53_Init(CartInfo *info); +void MALEE_Init(CartInfo *info); +void MHROM_Init(CartInfo *info); +void Mapper190_Init(CartInfo *info); +void NROM_Init(CartInfo *info); +void Novel_Init(CartInfo *info); +void S74LS374NA_Init(CartInfo *info); +void S74LS374N_Init(CartInfo *info); +void S8259A_Init(CartInfo *info); +void S8259B_Init(CartInfo *info); +void S8259C_Init(CartInfo *info); +void S8259D_Init(CartInfo *info); +void SA0036_Init(CartInfo *info); +void SA0037_Init(CartInfo *info); +void SA009_Init(CartInfo *info); +void SA0161M_Init(CartInfo *info); +void SA72007_Init(CartInfo *info); +void SA72008_Init(CartInfo *info); +void SA9602B_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 SL1ROM_Init(CartInfo *info); +void SLROM_Init(CartInfo *info); +void SNROM_Init(CartInfo *info); +void SOROM_Init(CartInfo *info); +void SSSNROM_Init(CartInfo *info); +void SUNSOFT_UNROM_Init(CartInfo *info); // "Shanghi" original version mapper +void Super24_Init(CartInfo *info); +void Supervision16_Init(CartInfo *info); +void TBROM_Init(CartInfo *info); +void TCA01_Init(CartInfo *info); +void TCU01_Init(CartInfo *info); +void TCU02_Init(CartInfo *info); +void TEROM_Init(CartInfo *info); +void TFROM_Init(CartInfo *info); +void TGROM_Init(CartInfo *info); +void TKROM_Init(CartInfo *info); +void TKSROM_Init(CartInfo *info); +void TLROM_Init(CartInfo *info); +void TLSROM_Init(CartInfo *info); +void TQROM_Init(CartInfo *info); +void TQROM_Init(CartInfo *info); +void TSROM_Init(CartInfo *info); +void Transformer_Init(CartInfo *info); +void UNL22211_Init(CartInfo *info); +void UNL3DBlock_Init(CartInfo *info); +void UNL43272_Init(CartInfo *info); +void UNL6035052_Init(CartInfo *info); +void UNL8157_Init(CartInfo *info); +void UNL8237A_Init(CartInfo *info); +void UNL8237_Init(CartInfo *info); +void UNLA9746_Init(CartInfo *info); +void UNLAX5705_Init(CartInfo *info); +void UNLBB_Init(CartInfo *info); +void UNLCC21_Init(CartInfo *info); +void UNLCITYFIGHT_Init(CartInfo *info); +void UNLD2000_Init(CartInfo *info); +void UNLEDU2000_Init(CartInfo *info); +void UNLFS304_Init(CartInfo *info); +void UNLH2288_Init(CartInfo *info); +void UNLKOF97_Init(CartInfo *info); +void UNLKS7012_Init(CartInfo *info); +void UNLKS7013B_Init(CartInfo *info); +void UNLKS7017_Init(CartInfo *info); +void UNLKS7030_Init(CartInfo *info); +void UNLKS7031_Init(CartInfo *info); +void UNLKS7032_Init(CartInfo *info); +void UNLKS7037_Init(CartInfo *info); +void UNLKS7057_Init(CartInfo *info); +void UNLN625092_Init(CartInfo *info); +void UNLMaliSB_Init(CartInfo *info); +void UNLOneBus_Init(CartInfo *info); +void UNLPEC586Init(CartInfo *info); +void UNLSC127_Init(CartInfo *info); +void UNLSHeroes_Init(CartInfo *info); +void UNLSL12_Init(CartInfo *info); +void UNLSL1632_Init(CartInfo *info); +void UNLSMB2J_Init(CartInfo *info); +void UNLT230_Init(CartInfo *info); +void UNLTF1201_Init(CartInfo *info); +void UNLVRC7_Init(CartInfo *info); +void UNLYOKO_Init(CartInfo *info); +void UNROM_Init(CartInfo *info); + +#ifdef COPYFAMI +void MapperCopyFamiMMC3_Init(CartInfo *info); +void MapperCopyFami_Init(CartInfo *info); +#endif + +extern uint8 *UNIFchrrama; // Meh. So I can stop CHR RAM + // bank switcherooing with certain boards... diff --git a/src/unzip.h b/src/unzip.h new file mode 100644 index 0000000..818ff60 --- /dev/null +++ b/src/unzip.h @@ -0,0 +1,272 @@ +/* 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 + +#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/src/video.c b/src/video.c new file mode 100644 index 0000000..b68b232 --- /dev/null +++ b/src/video.c @@ -0,0 +1,299 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include + +#include "fceu-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; +static uint8 *xbsave = NULL; + +#ifndef __LIBRETRO__ +#define SNAPSHOTS_ENABLED +#endif + +void FCEU_KillVirtualVideo(void) { + if (xbsave) { + free(xbsave); + xbsave = 0; + } +} + +int FCEU_InitVirtualVideo(void) { + if (!XBuf) // Some driver code may allocate XBuf externally. + // 256 bytes per scanline, * 240 scanline maximum, +8 for alignment, + if (!(XBuf = (uint8*)(FCEU_malloc(256 * 256 + 8)))) + return 0; + xbsave = XBuf; + + if (sizeof(uint8*) == 4) { + uint32 m; + m = (uint32)XBuf; + m = (4 - m) & 3; + XBuf += m; + } + memset(XBuf, 128, 256 * 256); + return 1; +} + +static 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 (GameInfo->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 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 + if (GameInfo->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 { + // Save snapshot before overlay stuff is written. + if (dosnapsave) { + ReallySnap(); + dosnapsave = 0; + } + if (GameInfo->type == GIT_VSUNI) + FCEU_VSUniDraw(XBuf); + FCEU_DrawSaveStates(XBuf); + FCEU_DrawMovies(XBuf); + FCEU_DrawNTSCControlBars(XBuf); + } + DrawMessage(); + FCEU_DrawInput(XBuf); +} + +void FCEU_DispMessage(char *format, ...) { + va_list ap; + + va_start(ap, format); + vsprintf(errmsg, format, ap); + va_end(ap); + + howlong = 180; +} + +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) { +#ifdef SNAPSHOTS_ENABLED + static uint32 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); +#endif + 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/src/video.h b/src/video.h new file mode 100644 index 0000000..5e74910 --- /dev/null +++ b/src/video.h @@ -0,0 +1,5 @@ +int FCEU_InitVirtualVideo(void); +void FCEU_KillVirtualVideo(void); +int SaveSnapshot(void); +extern uint8 *XBuf; +void FCEU_DrawNumberRow(uint8 *XBuf, int *nstatus, int cur); diff --git a/src/vsuni.c b/src/vsuni.c new file mode 100644 index 0000000..a3a6912 --- /dev/null +++ b/src/vsuni.c @@ -0,0 +1,370 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "fceu-types.h" +#include "x6502.h" +#include "fceu.h" +#include "input.h" +#include "netplay.h" +#include "vsuni.h" +#include "state.h" + +#define IOPTION_GUN 0x01 +#define IOPTION_SWAPDIRAB 0x02 +#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) { + 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", 0xb4032d694e1d2733LL, 151, 1, RP2C04_003, 0 }, + { "Gradius", 0x50687ae63bdad976LL, 151, 1, RP2C04_001, IOPTION_SWAPDIRAB }, + { "Gumshoe", 0x87161f8ee37758d3LL, 99, 2, RC2C05_03, IOPTION_GUN }, + { "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 Super Mario Bros [a1]", 0xfc182e5aefbce14dLL, 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; + *MapperNo = vs->mapper; + *Mirroring = vs->mirroring; + GameInfo->type = GIT_VSUNI; + GameInfo->cspecial = SIS_VSUNISYSTEM; + GameInfo->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) { + GameInfo->input[0] = SI_ZAPPER; + GameInfo->input[1] = SI_NONE; + } else { + GameInfo->input[0] = GameInfo->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/src/vsuni.h b/src/vsuni.h new file mode 100644 index 0000000..28e89ae --- /dev/null +++ b/src/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/src/wave.c b/src/wave.c new file mode 100644 index 0000000..d055f26 --- /dev/null +++ b/src/wave.c @@ -0,0 +1,104 @@ +#include + +#include "fceu-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; + + if (!soundlog) return; + + dest = temp; + x = Count; + + while (x--) { + int16 tmp = *Buffer; + + *(uint8*)dest = (((uint16)tmp) & 255); + *(((uint8*)dest) + 1) = (((uint16)tmp) >> 8); + dest++; + Buffer++; + } + wsize += fwrite(temp, 1, Count * sizeof(int16), soundlog); +} + +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/src/wave.h b/src/wave.h new file mode 100644 index 0000000..791b407 --- /dev/null +++ b/src/wave.h @@ -0,0 +1 @@ +void FCEU_WriteWaveData(int32 *Buffer, int Count); diff --git a/src/x6502.c b/src/x6502.c new file mode 100644 index 0000000..bf1e49d --- /dev/null +++ b/src/x6502.c @@ -0,0 +1,635 @@ +/* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "fceu-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(uint32 A) { + return(_DB = ARead[A](A)); +} + +static INLINE void WrMemNorm(uint32 A, uint8 V) { + BWrite[A](A, V); +} + +#ifdef FCEUDEF_DEBUGGER +X6502 XSave; // This is getting ugly. + +static INLINE uint8 RdMemHook(uint32 A) { + if (X.ReadHook) + return(_DB = X.ReadHook(&X, A)); + else + return(_DB = ARead[A](A)); +} + +static INLINE void WrMemHook(uint32 A, uint8 V) { + if (X.WriteHook) + X.WriteHook(&X, A, V); + else + BWrite[A](A, V); +} +#endif + +static INLINE uint8 RdRAMFast(uint32 A) { + return(_DB = RAM[A]); +} + +static INLINE void WrRAMFast(uint32 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) { \ + uint32 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) { \ + uint32 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) { \ + uint32 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) { \ + uint32 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) { uint32 A; uint8 x; GetAB(A); x = RdMem(A); WrMem(A, x); op; WrMem(A, x); break; } +#define RMW_ABI(reg, op) { uint32 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) { uint32 A; uint8 x; GetIX(A); x = RdMem(A); WrMem(A, x); op; WrMem(A, x); break; } +#define RMW_IY(op) { uint32 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) { uint32 A; uint8 x; GetAB(A); x = RdMem(A); op; break; } +#define LD_ABI(reg, op) { uint32 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) { uint32 A; uint8 x; GetIX(A); x = RdMem(A); op; break; } +#define LD_IY(op) { uint32 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) { uint32 A; GetAB(A); WrMem(A, r); break; } +#define ST_ABI(reg, r) { uint32 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) { uint32 A; GetIX(A); WrMem(A, r); break; } +#define ST_IY(r) { uint32 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, 2, 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 = _P = _PI = _DB = _jammed = 0; + _S = 0xFD; + 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; + + 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); + 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 *, uint32), void (*WriteHook)(X6502 *, uint32, 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/src/x6502.h b/src/x6502.h new file mode 100644 index 0000000..a259ac2 --- /dev/null +++ b/src/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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _X6502H + +#include "x6502struct.h" + +#ifdef FCEUDEF_DEBUGGER +void X6502_Debug(void (*CPUHook)(X6502 *), + uint8 (*ReadHook)(X6502 *, uint32), + void (*WriteHook)(X6502 *, uint32, 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/src/x6502struct.h b/src/x6502struct.h new file mode 100644 index 0000000..e8a3094 --- /dev/null +++ b/src/x6502struct.h @@ -0,0 +1,25 @@ +#ifndef _X6502STRUCTH + +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 *, uint32); + void (*WriteHook)(struct __X6502 *, uint32, uint8); + #endif +} X6502; +#define _X6502STRUCTH +#endif diff --git a/src/zlib/adler32.c b/src/zlib/adler32.c new file mode 100644 index 0000000..a250f3f --- /dev/null +++ b/src/zlib/adler32.c @@ -0,0 +1,48 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: adler32.c,v 1.2 2002/03/13 17:45:56 xodnizel Exp $ */ + +#include "zlib.h" + +#define BASE 65521L /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + unsigned long s1 = adler & 0xffff; + unsigned long s2 = (adler >> 16) & 0xffff; + int k; + + if (buf == Z_NULL) return 1L; + + while (len > 0) { + k = len < NMAX ? len : NMAX; + len -= k; + while (k >= 16) { + DO16(buf); + buf += 16; + k -= 16; + } + if (k != 0) do { + s1 += *buf++; + s2 += s1; + } while (--k); + s1 %= BASE; + s2 %= BASE; + } + return (s2 << 16) | s1; +} diff --git a/src/zlib/compress.c b/src/zlib/compress.c new file mode 100644 index 0000000..c0eecda --- /dev/null +++ b/src/zlib/compress.c @@ -0,0 +1,68 @@ +/* compress.c -- compress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: compress.c,v 1.2 2002/03/13 17:45:56 xodnizel Exp $ */ + +#include "zlib.h" + +/* =========================================================================== + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ +int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; + int level; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; +#endif + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + stream.opaque = (voidpf)0; + + err = deflateInit(&stream, level); + if (err != Z_OK) return err; + + err = deflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + deflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = deflateEnd(&stream); + return err; +} + +/* =========================================================================== + */ +int ZEXPORT compress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); +} diff --git a/src/zlib/crc32.c b/src/zlib/crc32.c new file mode 100644 index 0000000..558f6f6 --- /dev/null +++ b/src/zlib/crc32.c @@ -0,0 +1,162 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: crc32.c,v 1.2 2002/03/13 17:45:56 xodnizel Exp $ */ + +#include "zlib.h" + +#define local static + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local uLongf crc_table[256]; +local void make_crc_table OF((void)); + +/* + Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all + the information needed to generate CRC's on data a byte at a time for all + combinations of CRC register values and incoming bytes. +*/ +local void make_crc_table() +{ + uLong c; + int n, k; + uLong poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320L) */ + poly = 0L; + for (n = 0; n < sizeof(p)/sizeof(Byte); n++) + poly |= 1L << (31 - p[n]); + + for (n = 0; n < 256; n++) + { + c = (uLong)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[n] = c; + } + crc_table_empty = 0; +} +#else +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by make_crc_table) + */ +local const uLongf crc_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; +#endif + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const uLongf * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif + return (const uLongf *)crc_table; +} + +/* ========================================================================= */ +#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); + +/* ========================================================================= */ +uLong ZEXPORT crc32(crc, buf, len) + uLong crc; + const Bytef *buf; + uInt len; +{ + if (buf == Z_NULL) return 0L; +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif + crc = crc ^ 0xffffffffL; + while (len >= 8) + { + DO8(buf); + len -= 8; + } + if (len) do { + DO1(buf); + } while (--len); + return crc ^ 0xffffffffL; +} diff --git a/src/zlib/deflate.c b/src/zlib/deflate.c new file mode 100644 index 0000000..0b79a14 --- /dev/null +++ b/src/zlib/deflate.c @@ -0,0 +1,1350 @@ +/* deflate.c -- compress data using the deflation algorithm + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process depends on being able to identify portions + * of the input text which are identical to earlier input (within a + * sliding window trailing behind the input currently being processed). + * + * The most straightforward technique turns out to be the fastest for + * most input files: try all possible matches and select the longest. + * The key feature of this algorithm is that insertions into the string + * dictionary are very simple and thus fast, and deletions are avoided + * completely. Insertions are performed at each input character, whereas + * string matches are performed only when the previous match ends. So it + * is preferable to spend more time in matches to allow very fast string + * insertions and avoid deletions. The matching algorithm for small + * strings is inspired from that of Rabin & Karp. A brute force approach + * is used to find longer strings when a small match has been found. + * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze + * (by Leonid Broukhis). + * A previous version of this file used a more sophisticated algorithm + * (by Fiala and Greene) which is guaranteed to run in linear amortized + * time, but has a larger average cost, uses more memory and is patented. + * However the F&G algorithm may be faster for some highly redundant + * files if the parameter max_chain_length (described below) is too large. + * + * ACKNOWLEDGEMENTS + * + * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and + * I found it in 'freeze' written by Leonid Broukhis. + * Thanks to many people for bug reports and testing. + * + * REFERENCES + * + * Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". + * Available in ftp://ds.internic.net/rfc/rfc1951.txt + * + * A description of the Rabin and Karp algorithm is given in the book + * "Algorithms" by R. Sedgewick, Addison-Wesley, p252. + * + * Fiala,E.R., and Greene,D.H. + * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595 + * + */ + +/* @(#) $Id: deflate.c,v 1.2 2002/03/13 17:45:56 xodnizel Exp $ */ + +#include "deflate.h" + +const char deflate_copyright[] = + " deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* =========================================================================== + * Function prototypes. + */ +typedef enum { + need_more, /* block not completed, need more input or more output */ + block_done, /* block flush performed */ + finish_started, /* finish started, need only more output at next deflate */ + finish_done /* finish done, accept no more input or output */ +} block_state; + +typedef block_state (*compress_func) OF((deflate_state *s, int flush)); +/* Compression function. Returns the block state after the call. */ + +local void fill_window OF((deflate_state *s)); +local block_state deflate_stored OF((deflate_state *s, int flush)); +local block_state deflate_fast OF((deflate_state *s, int flush)); +local block_state deflate_slow OF((deflate_state *s, int flush)); +local void lm_init OF((deflate_state *s)); +local void putShortMSB OF((deflate_state *s, uInt b)); +local void flush_pending OF((z_streamp strm)); +local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); +#ifdef ASMV + void match_init OF((void)); /* asm code initialization */ + uInt longest_match OF((deflate_state *s, IPos cur_match)); +#else +local uInt longest_match OF((deflate_state *s, IPos cur_match)); +#endif + +#ifdef DEBUG +local void check_match OF((deflate_state *s, IPos start, IPos match, + int length)); +#endif + +/* =========================================================================== + * Local data + */ + +#define NIL 0 +/* Tail of hash chains */ + +#ifndef TOO_FAR +# define TOO_FAR 4096 +#endif +/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +/* Values for max_lazy_match, good_match and max_chain_length, depending on + * the desired pack level (0..9). The values given below have been tuned to + * exclude worst case performance for pathological files. Better values may be + * found for specific files. + */ +typedef struct config_s { + ush good_length; /* reduce lazy search above this match length */ + ush max_lazy; /* do not perform lazy search above this match length */ + ush nice_length; /* quit search above this match length */ + ush max_chain; + compress_func func; +} config; + +local const config configuration_table[10] = { +/* good lazy nice chain */ +/* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ +/* 1 */ {4, 4, 8, 4, deflate_fast}, /* maximum speed, no lazy matches */ +/* 2 */ {4, 5, 16, 8, deflate_fast}, +/* 3 */ {4, 6, 32, 32, deflate_fast}, + +/* 4 */ {4, 4, 16, 16, deflate_slow}, /* lazy matches */ +/* 5 */ {8, 16, 32, 32, deflate_slow}, +/* 6 */ {8, 16, 128, 128, deflate_slow}, +/* 7 */ {8, 32, 128, 256, deflate_slow}, +/* 8 */ {32, 128, 258, 1024, deflate_slow}, +/* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ + +/* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 + * For deflate_fast() (levels <= 3) good is ignored and lazy has a different + * meaning. + */ + +#define EQUAL 0 +/* result of memcmp for equal strings */ + +struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ + +/* =========================================================================== + * Update a hash value with the given input byte + * IN assertion: all calls to to UPDATE_HASH are made with consecutive + * input characters, so that a running hash key can be computed from the + * previous key instead of complete recalculation each time. + */ +#define UPDATE_HASH(s,h,c) (h = (((h)<hash_shift) ^ (c)) & s->hash_mask) + + +/* =========================================================================== + * Insert string str in the dictionary and set match_head to the previous head + * of the hash chain (the most recent string with same hash key). Return + * the previous length of the hash chain. + * If this file is compiled with -DFASTEST, the compression level is forced + * to 1, and no hash chains are maintained. + * IN assertion: all calls to to INSERT_STRING are made with consecutive + * input characters and the first MIN_MATCH bytes of str are valid + * (except for the last MIN_MATCH-1 bytes of the input file). + */ +#ifdef FASTEST +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#else +#define INSERT_STRING(s, str, match_head) \ + (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ + s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ + s->head[s->ins_h] = (Pos)(str)) +#endif + +/* =========================================================================== + * Initialize the hash table (avoiding 64K overflow for 16 bit systems). + * prev[] will be initialized on the fly. + */ +#define CLEAR_HASH(s) \ + s->head[s->hash_size-1] = NIL; \ + zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); + +/* ========================================================================= */ +int ZEXPORT deflateInit_(strm, level, version, stream_size) + z_streamp strm; + int level; + const char *version; + int stream_size; +{ + return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, + Z_DEFAULT_STRATEGY, version, stream_size); + /* To do: ignore strm->next_in if we use it as window */ +} + +/* ========================================================================= */ +int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, + version, stream_size) + z_streamp strm; + int level; + int method; + int windowBits; + int memLevel; + int strategy; + const char *version; + int stream_size; +{ + deflate_state *s; + int noheader = 0; + static const char* my_version = ZLIB_VERSION; + + ushf *overlay; + /* We overlay pending_buf and d_buf+l_buf. This works since the average + * output size for (length,distance) codes is <= 24 bits. + */ + + if (version == Z_NULL || version[0] != my_version[0] || + stream_size != sizeof(z_stream)) { + return Z_VERSION_ERROR; + } + if (strm == Z_NULL) return Z_STREAM_ERROR; + + strm->msg = Z_NULL; + if (strm->zalloc == Z_NULL) { + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; + } + if (strm->zfree == Z_NULL) strm->zfree = zcfree; + + if (level == Z_DEFAULT_COMPRESSION) level = 6; +#ifdef FASTEST + level = 1; +#endif + + if (windowBits < 0) { /* undocumented feature: suppress zlib header */ + noheader = 1; + windowBits = -windowBits; + } + if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || + windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || + strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); + if (s == Z_NULL) return Z_MEM_ERROR; + strm->state = (struct internal_state FAR *)s; + s->strm = strm; + + s->noheader = noheader; + s->w_bits = windowBits; + s->w_size = 1 << s->w_bits; + s->w_mask = s->w_size - 1; + + s->hash_bits = memLevel + 7; + s->hash_size = 1 << s->hash_bits; + s->hash_mask = s->hash_size - 1; + s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); + + s->window = (Bytef *) ZALLOC(strm, s->w_size, 2*sizeof(Byte)); + s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); + s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); + + s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ + + overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); + s->pending_buf = (uchf *) overlay; + s->pending_buf_size = (ulg)s->lit_bufsize * (sizeof(ush)+2L); + + if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || + s->pending_buf == Z_NULL) { + strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); + deflateEnd (strm); + return Z_MEM_ERROR; + } + s->d_buf = overlay + s->lit_bufsize/sizeof(ush); + s->l_buf = s->pending_buf + (1+sizeof(ush))*s->lit_bufsize; + + s->level = level; + s->strategy = strategy; + s->method = (Byte)method; + + return deflateReset(strm); +} + +/* ========================================================================= */ +int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) + z_streamp strm; + const Bytef *dictionary; + uInt dictLength; +{ + deflate_state *s; + uInt length = dictLength; + uInt n; + IPos hash_head = 0; + + if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || + strm->state->status != INIT_STATE) return Z_STREAM_ERROR; + + s = strm->state; + strm->adler = adler32(strm->adler, dictionary, dictLength); + + if (length < MIN_MATCH) return Z_OK; + if (length > MAX_DIST(s)) { + length = MAX_DIST(s); +#ifndef USE_DICT_HEAD + dictionary += dictLength - length; /* use the tail of the dictionary */ +#endif + } + zmemcpy(s->window, dictionary, length); + s->strstart = length; + s->block_start = (long)length; + + /* Insert all strings in the hash table (except for the last two bytes). + * s->lookahead stays null, so s->ins_h will be recomputed at the next + * call of fill_window. + */ + s->ins_h = s->window[0]; + UPDATE_HASH(s, s->ins_h, s->window[1]); + for (n = 0; n <= length - MIN_MATCH; n++) { + INSERT_STRING(s, n, hash_head); + } + if (hash_head) hash_head = 0; /* to make compiler happy */ + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateReset (strm) + z_streamp strm; +{ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; + + strm->total_in = strm->total_out = 0; + strm->msg = Z_NULL; /* use zfree if we ever allocate msg dynamically */ + strm->data_type = Z_UNKNOWN; + + s = (deflate_state *)strm->state; + s->pending = 0; + s->pending_out = s->pending_buf; + + if (s->noheader < 0) { + s->noheader = 0; /* was set to -1 by deflate(..., Z_FINISH); */ + } + s->status = s->noheader ? BUSY_STATE : INIT_STATE; + strm->adler = 1; + s->last_flush = Z_NO_FLUSH; + + _tr_init(s); + lm_init(s); + + return Z_OK; +} + +/* ========================================================================= */ +int ZEXPORT deflateParams(strm, level, strategy) + z_streamp strm; + int level; + int strategy; +{ + deflate_state *s; + compress_func func; + int err = Z_OK; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + s = strm->state; + + if (level == Z_DEFAULT_COMPRESSION) { + level = 6; + } + if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { + return Z_STREAM_ERROR; + } + func = configuration_table[s->level].func; + + if (func != configuration_table[level].func && strm->total_in != 0) { + /* Flush the last buffer: */ + err = deflate(strm, Z_PARTIAL_FLUSH); + } + if (s->level != level) { + s->level = level; + s->max_lazy_match = configuration_table[level].max_lazy; + s->good_match = configuration_table[level].good_length; + s->nice_match = configuration_table[level].nice_length; + s->max_chain_length = configuration_table[level].max_chain; + } + s->strategy = strategy; + return err; +} + +/* ========================================================================= + * Put a short in the pending buffer. The 16-bit value is put in MSB order. + * IN assertion: the stream state is correct and there is enough room in + * pending_buf. + */ +local void putShortMSB (s, b) + deflate_state *s; + uInt b; +{ + put_byte(s, (Byte)(b >> 8)); + put_byte(s, (Byte)(b & 0xff)); +} + +/* ========================================================================= + * Flush as much pending output as possible. All deflate() output goes + * through this function so some applications may wish to modify it + * to avoid allocating a large strm->next_out buffer and copying into it. + * (See also read_buf()). + */ +local void flush_pending(strm) + z_streamp strm; +{ + unsigned len = strm->state->pending; + + if (len > strm->avail_out) len = strm->avail_out; + if (len == 0) return; + + zmemcpy(strm->next_out, strm->state->pending_out, len); + strm->next_out += len; + strm->state->pending_out += len; + strm->total_out += len; + strm->avail_out -= len; + strm->state->pending -= len; + if (strm->state->pending == 0) { + strm->state->pending_out = strm->state->pending_buf; + } +} + +/* ========================================================================= */ +int ZEXPORT deflate (strm, flush) + z_streamp strm; + int flush; +{ + int old_flush; /* value of flush param for previous deflate call */ + deflate_state *s; + + if (strm == Z_NULL || strm->state == Z_NULL || + flush > Z_FINISH || flush < 0) { + return Z_STREAM_ERROR; + } + s = strm->state; + + if (strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0) || + (s->status == FINISH_STATE && flush != Z_FINISH)) { + ERR_RETURN(strm, Z_STREAM_ERROR); + } + if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); + + s->strm = strm; /* just in case */ + old_flush = s->last_flush; + s->last_flush = flush; + + /* Write the zlib header */ + if (s->status == INIT_STATE) { + + uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; + uInt level_flags = (s->level-1) >> 1; + + if (level_flags > 3) level_flags = 3; + header |= (level_flags << 6); + if (s->strstart != 0) header |= PRESET_DICT; + header += 31 - (header % 31); + + s->status = BUSY_STATE; + putShortMSB(s, header); + + /* Save the adler32 of the preset dictionary: */ + if (s->strstart != 0) { + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + } + strm->adler = 1L; + } + + /* Flush as much pending output as possible */ + if (s->pending != 0) { + flush_pending(strm); + if (strm->avail_out == 0) { + /* Since avail_out is 0, deflate will be called again with + * more output space, but possibly with both pending and + * avail_in equal to zero. There won't be anything to do, + * but this is not an error situation so make sure we + * return OK instead of BUF_ERROR at next call of deflate: + */ + s->last_flush = -1; + return Z_OK; + } + + /* Make sure there is something to do and avoid duplicate consecutive + * flushes. For repeated and useless calls with Z_FINISH, we keep + * returning Z_STREAM_END instead of Z_BUFF_ERROR. + */ + } else if (strm->avail_in == 0 && flush <= old_flush && + flush != Z_FINISH) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* User must not provide more input after the first FINISH: */ + if (s->status == FINISH_STATE && strm->avail_in != 0) { + ERR_RETURN(strm, Z_BUF_ERROR); + } + + /* Start a new block or continue the current one. + */ + if (strm->avail_in != 0 || s->lookahead != 0 || + (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { + block_state bstate; + + bstate = (*(configuration_table[s->level].func))(s, flush); + + if (bstate == finish_started || bstate == finish_done) { + s->status = FINISH_STATE; + } + if (bstate == need_more || bstate == finish_started) { + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ + } + return Z_OK; + /* If flush != Z_NO_FLUSH && avail_out == 0, the next call + * of deflate should use the same flush parameter to make sure + * that the flush is complete. So we don't have to output an + * empty block here, this will be done at next call. This also + * ensures that for a very small output buffer, we emit at most + * one empty block. + */ + } + if (bstate == block_done) { + if (flush == Z_PARTIAL_FLUSH) { + _tr_align(s); + } else { /* FULL_FLUSH or SYNC_FLUSH */ + _tr_stored_block(s, (char*)0, 0L, 0); + /* For a full flush, this empty block will be recognized + * as a special marker by inflate_sync(). + */ + if (flush == Z_FULL_FLUSH) { + CLEAR_HASH(s); /* forget history */ + } + } + flush_pending(strm); + if (strm->avail_out == 0) { + s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ + return Z_OK; + } + } + } + Assert(strm->avail_out > 0, "bug2"); + + if (flush != Z_FINISH) return Z_OK; + if (s->noheader) return Z_STREAM_END; + + /* Write the zlib trailer (adler32) */ + putShortMSB(s, (uInt)(strm->adler >> 16)); + putShortMSB(s, (uInt)(strm->adler & 0xffff)); + flush_pending(strm); + /* If avail_out is zero, the application will call deflate again + * to flush the rest. + */ + s->noheader = -1; /* write the trailer only once! */ + return s->pending != 0 ? Z_OK : Z_STREAM_END; +} + +/* ========================================================================= */ +int ZEXPORT deflateEnd (strm) + z_streamp strm; +{ + int status; + + if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; + + status = strm->state->status; + if (status != INIT_STATE && status != BUSY_STATE && + status != FINISH_STATE) { + return Z_STREAM_ERROR; + } + + /* Deallocate in reverse order of allocations: */ + TRY_FREE(strm, strm->state->pending_buf); + TRY_FREE(strm, strm->state->head); + TRY_FREE(strm, strm->state->prev); + TRY_FREE(strm, strm->state->window); + + ZFREE(strm, strm->state); + strm->state = Z_NULL; + + return status == BUSY_STATE ? Z_DATA_ERROR : Z_OK; +} + +/* ========================================================================= + * Copy the source state to the destination state. + * To simplify the source, this is not supported for 16-bit MSDOS (which + * doesn't have enough memory anyway to duplicate compression states). + */ +int ZEXPORT deflateCopy (dest, source) + z_streamp dest; + z_streamp source; +{ +#ifdef MAXSEG_64K + return Z_STREAM_ERROR; +#else + deflate_state *ds; + deflate_state *ss; + ushf *overlay; + + + if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { + return Z_STREAM_ERROR; + } + + ss = source->state; + + *dest = *source; + + ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); + if (ds == Z_NULL) return Z_MEM_ERROR; + dest->state = (struct internal_state FAR *) ds; + *ds = *ss; + ds->strm = dest; + + ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); + ds->prev = (Posf *) ZALLOC(dest, ds->w_size, sizeof(Pos)); + ds->head = (Posf *) ZALLOC(dest, ds->hash_size, sizeof(Pos)); + overlay = (ushf *) ZALLOC(dest, ds->lit_bufsize, sizeof(ush)+2); + ds->pending_buf = (uchf *) overlay; + + if (ds->window == Z_NULL || ds->prev == Z_NULL || ds->head == Z_NULL || + ds->pending_buf == Z_NULL) { + deflateEnd (dest); + return Z_MEM_ERROR; + } + /* following zmemcpy do not work for 16-bit MSDOS */ + zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); + zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); + zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); + zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); + + ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); + ds->d_buf = overlay + ds->lit_bufsize/sizeof(ush); + ds->l_buf = ds->pending_buf + (1+sizeof(ush))*ds->lit_bufsize; + + ds->l_desc.dyn_tree = ds->dyn_ltree; + ds->d_desc.dyn_tree = ds->dyn_dtree; + ds->bl_desc.dyn_tree = ds->bl_tree; + + return Z_OK; +#endif +} + +/* =========================================================================== + * Read a new buffer from the current input stream, update the adler32 + * and total number of bytes read. All deflate() input goes through + * this function so some applications may wish to modify it to avoid + * allocating a large strm->next_in buffer and copying from it. + * (See also flush_pending()). + */ +local int read_buf(strm, buf, size) + z_streamp strm; + Bytef *buf; + unsigned size; +{ + unsigned len = strm->avail_in; + + if (len > size) len = size; + if (len == 0) return 0; + + strm->avail_in -= len; + + if (!strm->state->noheader) { + strm->adler = adler32(strm->adler, strm->next_in, len); + } + zmemcpy(buf, strm->next_in, len); + strm->next_in += len; + strm->total_in += len; + + return (int)len; +} + +/* =========================================================================== + * Initialize the "longest match" routines for a new zlib stream + */ +local void lm_init (s) + deflate_state *s; +{ + s->window_size = (ulg)2L*s->w_size; + + CLEAR_HASH(s); + + /* Set the default configuration parameters: + */ + s->max_lazy_match = configuration_table[s->level].max_lazy; + s->good_match = configuration_table[s->level].good_length; + s->nice_match = configuration_table[s->level].nice_length; + s->max_chain_length = configuration_table[s->level].max_chain; + + s->strstart = 0; + s->block_start = 0L; + s->lookahead = 0; + s->match_length = s->prev_length = MIN_MATCH-1; + s->match_available = 0; + s->ins_h = 0; +#ifdef ASMV + match_init(); /* initialize the asm code */ +#endif +} + +/* =========================================================================== + * Set match_start to the longest match starting at the given string and + * return its length. Matches shorter or equal to prev_length are discarded, + * in which case the result is equal to prev_length and match_start is + * garbage. + * IN assertions: cur_match is the head of the hash chain for the current + * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1 + * OUT assertion: the match length is not greater than s->lookahead. + */ +#ifndef ASMV +/* For 80x86 and 680x0, an optimized version will be provided in match.asm or + * match.S. The code will be functionally equivalent. + */ +#ifndef FASTEST +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + unsigned chain_length = s->max_chain_length;/* max hash chain length */ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + int best_len = s->prev_length; /* best match length so far */ + int nice_match = s->nice_match; /* stop if match long enough */ + IPos limit = s->strstart > (IPos)MAX_DIST(s) ? + s->strstart - (IPos)MAX_DIST(s) : NIL; + /* Stop when cur_match becomes <= limit. To simplify the code, + * we prevent matches with the string of window index 0. + */ + Posf *prev = s->prev; + uInt wmask = s->w_mask; + +#ifdef UNALIGNED_OK + /* Compare two bytes at a time. Note: this is not always beneficial. + * Try with and without -DUNALIGNED_OK to check. + */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1; + register ush scan_start = *(ushf*)scan; + register ush scan_end = *(ushf*)(scan+best_len-1); +#else + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + register Byte scan_end1 = scan[best_len-1]; + register Byte scan_end = scan[best_len]; +#endif + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + /* Do not waste too much time if we already have a good match: */ + if (s->prev_length >= s->good_match) { + chain_length >>= 2; + } + /* Do not look for matches beyond the end of the input. This is necessary + * to make deflate deterministic. + */ + if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + do { + Assert(cur_match < s->strstart, "no future"); + match = s->window + cur_match; + + /* Skip to next match if the match length cannot increase + * or if the match length is less than 2: + */ +#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) + /* This code assumes sizeof(unsigned short) == 2. Do not use + * UNALIGNED_OK if your compiler uses a different size. + */ + if (*(ushf*)(match+best_len-1) != scan_end || + *(ushf*)match != scan_start) continue; + + /* It is not necessary to compare scan[2] and match[2] since they are + * always equal when the other bytes match, given that the hash keys + * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at + * strstart+3, +5, ... up to strstart+257. We check for insufficient + * lookahead only every 4th comparison; the 128th check will be made + * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is + * necessary to put more guard bytes at the end of the window, or + * to check more often for insufficient lookahead. + */ + Assert(scan[2] == match[2], "scan[2]?"); + scan++, match++; + do { + } while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + *(ushf*)(scan+=2) == *(ushf*)(match+=2) && + scan < strend); + /* The funny "do {}" generates better code on most compilers */ + + /* Here, scan <= window+strstart+257 */ + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + if (*scan == *match) scan++; + + len = (MAX_MATCH - 1) - (int)(strend-scan); + scan = strend - (MAX_MATCH-1); + +#else /* UNALIGNED_OK */ + + if (match[best_len] != scan_end || + match[best_len-1] != scan_end1 || + *match != *scan || + *++match != scan[1]) continue; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match++; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + scan = strend - MAX_MATCH; + +#endif /* UNALIGNED_OK */ + + if (len > best_len) { + s->match_start = cur_match; + best_len = len; + if (len >= nice_match) break; +#ifdef UNALIGNED_OK + scan_end = *(ushf*)(scan+best_len-1); +#else + scan_end1 = scan[best_len-1]; + scan_end = scan[best_len]; +#endif + } + } while ((cur_match = prev[cur_match & wmask]) > limit + && --chain_length != 0); + + if ((uInt)best_len <= s->lookahead) return (uInt)best_len; + return s->lookahead; +} + +#else /* FASTEST */ +/* --------------------------------------------------------------------------- + * Optimized version for level == 1 only + */ +local uInt longest_match(s, cur_match) + deflate_state *s; + IPos cur_match; /* current match */ +{ + register Bytef *scan = s->window + s->strstart; /* current string */ + register Bytef *match; /* matched string */ + register int len; /* length of current match */ + register Bytef *strend = s->window + s->strstart + MAX_MATCH; + + /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. + * It is easy to get rid of this optimization if necessary. + */ + Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); + + Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); + + Assert(cur_match < s->strstart, "no future"); + + match = s->window + cur_match; + + /* Return failure if the match length is less than 2: + */ + if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; + + /* The check at best_len-1 can be removed because it will be made + * again later. (This heuristic is not always a win.) + * It is not necessary to compare scan[2] and match[2] since they + * are always equal when the other bytes match, given that + * the hash keys are equal and that HASH_BITS >= 8. + */ + scan += 2, match += 2; + Assert(*scan == *match, "match[2]?"); + + /* We check for insufficient lookahead only every 8th comparison; + * the 256th check will be made at strstart+258. + */ + do { + } while (*++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + *++scan == *++match && *++scan == *++match && + scan < strend); + + Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); + + len = MAX_MATCH - (int)(strend - scan); + + if (len < MIN_MATCH) return MIN_MATCH - 1; + + s->match_start = cur_match; + return len <= s->lookahead ? len : s->lookahead; +} +#endif /* FASTEST */ +#endif /* ASMV */ + +#ifdef DEBUG +/* =========================================================================== + * Check that the match at match_start is indeed a match. + */ +local void check_match(s, start, match, length) + deflate_state *s; + IPos start, match; + int length; +{ + /* check that the match is indeed a match */ + if (zmemcmp(s->window + match, + s->window + start, length) != EQUAL) { + fprintf(stderr, " start %u, match %u, length %d\n", + start, match, length); + do { + fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); + } while (--length != 0); + z_error("invalid match"); + } + if (z_verbose > 1) { + fprintf(stderr,"\\[%d,%d]", start-match, length); + do { putc(s->window[start++], stderr); } while (--length != 0); + } +} +#else +# define check_match(s, start, match, length) +#endif + +/* =========================================================================== + * Fill the window when the lookahead becomes insufficient. + * Updates strstart and lookahead. + * + * IN assertion: lookahead < MIN_LOOKAHEAD + * OUT assertions: strstart <= window_size-MIN_LOOKAHEAD + * At least one byte has been read, or avail_in == 0; reads are + * performed for at least two bytes (required for the zip translate_eol + * option -- not supported here). + */ +local void fill_window(s) + deflate_state *s; +{ + register unsigned n, m; + register Posf *p; + unsigned more; /* Amount of free space at the end of the window. */ + uInt wsize = s->w_size; + + do { + more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); + + /* Deal with !@#$% 64K limit: */ + if (more == 0 && s->strstart == 0 && s->lookahead == 0) { + more = wsize; + + } else if (more == (unsigned)(-1)) { + /* Very unlikely, but possible on 16 bit machine if strstart == 0 + * and lookahead == 1 (input done one byte at time) + */ + more--; + + /* If the window is almost full and there is insufficient lookahead, + * move the upper half to the lower one to make room in the upper half. + */ + } else if (s->strstart >= wsize+MAX_DIST(s)) { + + zmemcpy(s->window, s->window+wsize, (unsigned)wsize); + s->match_start -= wsize; + s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ + s->block_start -= (long) wsize; + + /* Slide the hash table (could be avoided with 32 bit values + at the expense of memory usage). We slide even when level == 0 + to keep the hash table consistent if we switch back to level > 0 + later. (Using level 0 permanently is not an optimal usage of + zlib, so we don't care about this pathological case.) + */ + n = s->hash_size; + p = &s->head[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + } while (--n); + + n = wsize; +#ifndef FASTEST + p = &s->prev[n]; + do { + m = *--p; + *p = (Pos)(m >= wsize ? m-wsize : NIL); + /* If n is not on any hash chain, prev[n] is garbage but + * its value will never be used. + */ + } while (--n); +#endif + more += wsize; + } + if (s->strm->avail_in == 0) return; + + /* If there was no sliding: + * strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && + * more == window_size - lookahead - strstart + * => more >= window_size - (MIN_LOOKAHEAD-1 + WSIZE + MAX_DIST-1) + * => more >= window_size - 2*WSIZE + 2 + * In the BIG_MEM or MMAP case (not yet supported), + * window_size == input_size + MIN_LOOKAHEAD && + * strstart + s->lookahead <= input_size => more >= MIN_LOOKAHEAD. + * Otherwise, window_size == 2*WSIZE so more >= 2. + * If there was sliding, more >= WSIZE. So in all cases, more >= 2. + */ + Assert(more >= 2, "more < 2"); + + n = read_buf(s->strm, s->window + s->strstart + s->lookahead, more); + s->lookahead += n; + + /* Initialize the hash value now that we have some input: */ + if (s->lookahead >= MIN_MATCH) { + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + } + /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, + * but this is not important since only literal bytes will be emitted. + */ + + } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); +} + +/* =========================================================================== + * Flush the current block, with given end-of-file flag. + * IN assertion: strstart is set to the end of the current match. + */ +#define FLUSH_BLOCK_ONLY(s, eof) { \ + _tr_flush_block(s, (s->block_start >= 0L ? \ + (charf *)&s->window[(unsigned)s->block_start] : \ + (charf *)Z_NULL), \ + (ulg)((long)s->strstart - s->block_start), \ + (eof)); \ + s->block_start = s->strstart; \ + flush_pending(s->strm); \ + Tracev((stderr,"[FLUSH]")); \ +} + +/* Same but force premature exit if necessary. */ +#define FLUSH_BLOCK(s, eof) { \ + FLUSH_BLOCK_ONLY(s, eof); \ + if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ +} + +/* =========================================================================== + * Copy without compression as much as possible from the input stream, return + * the current block state. + * This function does not insert new strings in the dictionary since + * uncompressible data is probably not useful. This function is used + * only for the level=0 compression option. + * NOTE: this function should be optimized to avoid extra copying from + * window to pending_buf. + */ +local block_state deflate_stored(s, flush) + deflate_state *s; + int flush; +{ + /* Stored blocks are limited to 0xffff bytes, pending_buf is limited + * to pending_buf_size, and each stored block has a 5 byte header: + */ + ulg max_block_size = 0xffff; + ulg max_start; + + if (max_block_size > s->pending_buf_size - 5) { + max_block_size = s->pending_buf_size - 5; + } + + /* Copy as much as possible from input to output: */ + for (;;) { + /* Fill the window as much as possible: */ + if (s->lookahead <= 1) { + + Assert(s->strstart < s->w_size+MAX_DIST(s) || + s->block_start >= (long)s->w_size, "slide too late"); + + fill_window(s); + if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; + + if (s->lookahead == 0) break; /* flush the current block */ + } + Assert(s->block_start >= 0L, "block gone"); + + s->strstart += s->lookahead; + s->lookahead = 0; + + /* Emit a stored block if pending_buf will be full: */ + max_start = s->block_start + max_block_size; + if (s->strstart == 0 || (ulg)s->strstart >= max_start) { + /* strstart == 0 is possible when wraparound on 16-bit machine */ + s->lookahead = (uInt)(s->strstart - max_start); + s->strstart = (uInt)max_start; + FLUSH_BLOCK(s, 0); + } + /* Flush if we may have to slide, otherwise block_start may become + * negative and the data will be gone: + */ + if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { + FLUSH_BLOCK(s, 0); + } + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Compress as much as possible from the input stream, return the current + * block state. + * This function does not perform lazy evaluation of matches and inserts + * new strings in the dictionary only for unmatched strings or for short + * matches. It is used only for the fast compression options. + */ +local block_state deflate_fast(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of the hash chain */ + int bflush; /* set if current block must be flushed */ + + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + * At this point we have always match_length < MIN_MATCH + */ + if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + } + if (s->match_length >= MIN_MATCH) { + check_match(s, s->strstart, s->match_start, s->match_length); + + _tr_tally_dist(s, s->strstart - s->match_start, + s->match_length - MIN_MATCH, bflush); + + s->lookahead -= s->match_length; + + /* Insert new strings in the hash table only if the match length + * is not too large. This saves time but degrades compression. + */ +#ifndef FASTEST + if (s->match_length <= s->max_insert_length && + s->lookahead >= MIN_MATCH) { + s->match_length--; /* string at strstart already in hash table */ + do { + s->strstart++; + INSERT_STRING(s, s->strstart, hash_head); + /* strstart never exceeds WSIZE-MAX_MATCH, so there are + * always MIN_MATCH bytes ahead. + */ + } while (--s->match_length != 0); + s->strstart++; + } else +#endif + { + s->strstart += s->match_length; + s->match_length = 0; + s->ins_h = s->window[s->strstart]; + UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +#if MIN_MATCH != 3 + Call UPDATE_HASH() MIN_MATCH-3 more times +#endif + /* If lookahead < MIN_MATCH, ins_h is garbage, but it does not + * matter since it will be recomputed at next deflate call. + */ + } + } else { + /* No match, output a literal byte */ + Tracevv((stderr,"%c", s->window[s->strstart])); + _tr_tally_lit (s, s->window[s->strstart], bflush); + s->lookahead--; + s->strstart++; + } + if (bflush) FLUSH_BLOCK(s, 0); + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} + +/* =========================================================================== + * Same as above, but achieves better compression. We use a lazy + * evaluation for matches: a match is finally adopted only if there is + * no better match at the next window position. + */ +local block_state deflate_slow(s, flush) + deflate_state *s; + int flush; +{ + IPos hash_head = NIL; /* head of hash chain */ + int bflush; /* set if current block must be flushed */ + + /* Process the input block. */ + for (;;) { + /* Make sure that we always have enough lookahead, except + * at the end of the input file. We need MAX_MATCH bytes + * for the next match, plus MIN_MATCH bytes to insert the + * string following the next match. + */ + if (s->lookahead < MIN_LOOKAHEAD) { + fill_window(s); + if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { + return need_more; + } + if (s->lookahead == 0) break; /* flush the current block */ + } + + /* Insert the string window[strstart .. strstart+2] in the + * dictionary, and set hash_head to the head of the hash chain: + */ + if (s->lookahead >= MIN_MATCH) { + INSERT_STRING(s, s->strstart, hash_head); + } + + /* Find the longest match, discarding those <= prev_length. + */ + s->prev_length = s->match_length, s->prev_match = s->match_start; + s->match_length = MIN_MATCH-1; + + if (hash_head != NIL && s->prev_length < s->max_lazy_match && + s->strstart - hash_head <= MAX_DIST(s)) { + /* To simplify the code, we prevent matches with the string + * of window index 0 (in particular we have to avoid a match + * of the string with itself at the start of the input file). + */ + if (s->strategy != Z_HUFFMAN_ONLY) { + s->match_length = longest_match (s, hash_head); + } + /* longest_match() sets match_start */ + + if (s->match_length <= 5 && (s->strategy == Z_FILTERED || + (s->match_length == MIN_MATCH && + s->strstart - s->match_start > TOO_FAR))) { + + /* If prev_match is also MIN_MATCH, match_start is garbage + * but we will ignore the current match anyway. + */ + s->match_length = MIN_MATCH-1; + } + } + /* If there was a match at the previous step and the current + * match is not better, output the previous match: + */ + if (s->prev_length >= MIN_MATCH && s->match_length <= s->prev_length) { + uInt max_insert = s->strstart + s->lookahead - MIN_MATCH; + /* Do not insert strings in hash table beyond this. */ + + check_match(s, s->strstart-1, s->prev_match, s->prev_length); + + _tr_tally_dist(s, s->strstart -1 - s->prev_match, + s->prev_length - MIN_MATCH, bflush); + + /* Insert in hash table all strings up to the end of the match. + * strstart-1 and strstart are already inserted. If there is not + * enough lookahead, the last two strings are not inserted in + * the hash table. + */ + s->lookahead -= s->prev_length-1; + s->prev_length -= 2; + do { + if (++s->strstart <= max_insert) { + INSERT_STRING(s, s->strstart, hash_head); + } + } while (--s->prev_length != 0); + s->match_available = 0; + s->match_length = MIN_MATCH-1; + s->strstart++; + + if (bflush) FLUSH_BLOCK(s, 0); + + } else if (s->match_available) { + /* If there was no match at the previous position, output a + * single literal. If there was a match but the current match + * is longer, truncate the previous match to a single literal. + */ + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + if (bflush) { + FLUSH_BLOCK_ONLY(s, 0); + } + s->strstart++; + s->lookahead--; + if (s->strm->avail_out == 0) return need_more; + } else { + /* There is no previous match to compare with, wait for + * the next step to decide. + */ + s->match_available = 1; + s->strstart++; + s->lookahead--; + } + } + Assert (flush != Z_NO_FLUSH, "no flush?"); + if (s->match_available) { + Tracevv((stderr,"%c", s->window[s->strstart-1])); + _tr_tally_lit(s, s->window[s->strstart-1], bflush); + s->match_available = 0; + } + FLUSH_BLOCK(s, flush == Z_FINISH); + return flush == Z_FINISH ? finish_done : block_done; +} diff --git a/src/zlib/deflate.h b/src/zlib/deflate.h new file mode 100644 index 0000000..9bd8cb0 --- /dev/null +++ b/src/zlib/deflate.h @@ -0,0 +1,318 @@ +/* deflate.h -- internal compression state + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: deflate.h,v 1.2 2002/03/13 17:45:56 xodnizel Exp $ */ + +#ifndef _DEFLATE_H +#define _DEFLATE_H + +#include "zutil.h" + +/* =========================================================================== + * Internal compression state. + */ + +#define LENGTH_CODES 29 +/* number of length codes, not counting the special END_BLOCK code */ + +#define LITERALS 256 +/* number of literal bytes 0..255 */ + +#define L_CODES (LITERALS+1+LENGTH_CODES) +/* number of Literal or Length codes, including the END_BLOCK code */ + +#define D_CODES 30 +/* number of distance codes */ + +#define BL_CODES 19 +/* number of codes used to transfer the bit lengths */ + +#define HEAP_SIZE (2*L_CODES+1) +/* maximum heap size */ + +#define MAX_BITS 15 +/* All codes must not exceed MAX_BITS bits */ + +#define INIT_STATE 42 +#define BUSY_STATE 113 +#define FINISH_STATE 666 +/* Stream status */ + + +/* Data structure describing a single value and its code string. */ +typedef struct ct_data_s { + union { + ush freq; /* frequency count */ + ush code; /* bit string */ + } fc; + union { + ush dad; /* father node in Huffman tree */ + ush len; /* length of bit string */ + } dl; +} FAR ct_data; + +#define Freq fc.freq +#define Code fc.code +#define Dad dl.dad +#define Len dl.len + +typedef struct static_tree_desc_s static_tree_desc; + +typedef struct tree_desc_s { + ct_data *dyn_tree; /* the dynamic tree */ + int max_code; /* largest code with non zero frequency */ + static_tree_desc *stat_desc; /* the corresponding static tree */ +} FAR tree_desc; + +typedef ush Pos; +typedef Pos FAR Posf; +typedef unsigned IPos; + +/* A Pos is an index in the character window. We use short instead of int to + * save space in the various tables. IPos is used only for parameter passing. + */ + +typedef struct internal_state { + z_streamp strm; /* pointer back to this zlib stream */ + int status; /* as the name implies */ + Bytef *pending_buf; /* output still pending */ + ulg pending_buf_size; /* size of pending_buf */ + Bytef *pending_out; /* next pending byte to output to the stream */ + int pending; /* nb of bytes in the pending buffer */ + int noheader; /* suppress zlib header and adler32 */ + Byte data_type; /* UNKNOWN, BINARY or ASCII */ + Byte method; /* STORED (for zip only) or DEFLATED */ + int last_flush; /* value of flush param for previous deflate call */ + + /* used by deflate.c: */ + + uInt w_size; /* LZ77 window size (32K by default) */ + uInt w_bits; /* log2(w_size) (8..16) */ + uInt w_mask; /* w_size - 1 */ + + Bytef *window; + /* Sliding window. Input bytes are read into the second half of the window, + * and move to the first half later to keep a dictionary of at least wSize + * bytes. With this organization, matches are limited to a distance of + * wSize-MAX_MATCH bytes, but this ensures that IO is always + * performed with a length multiple of the block size. Also, it limits + * the window size to 64K, which is quite useful on MSDOS. + * To do: use the user input buffer as sliding window. + */ + + ulg window_size; + /* Actual size of window: 2*wSize, except when the user input buffer + * is directly used as sliding window. + */ + + Posf *prev; + /* Link to older string with same hash index. To limit the size of this + * array to 64K, this link is maintained only for the last 32K strings. + * An index in this array is thus a window index modulo 32K. + */ + + Posf *head; /* Heads of the hash chains or NIL. */ + + uInt ins_h; /* hash index of string to be inserted */ + uInt hash_size; /* number of elements in hash table */ + uInt hash_bits; /* log2(hash_size) */ + uInt hash_mask; /* hash_size-1 */ + + uInt hash_shift; + /* Number of bits by which ins_h must be shifted at each input + * step. It must be such that after MIN_MATCH steps, the oldest + * byte no longer takes part in the hash key, that is: + * hash_shift * MIN_MATCH >= hash_bits + */ + + long block_start; + /* Window position at the beginning of the current output block. Gets + * negative when the window is moved backwards. + */ + + uInt match_length; /* length of best match */ + IPos prev_match; /* previous match */ + int match_available; /* set if previous match exists */ + uInt strstart; /* start of string to insert */ + uInt match_start; /* start of matching string */ + uInt lookahead; /* number of valid bytes ahead in window */ + + uInt prev_length; + /* Length of the best match at previous step. Matches not greater than this + * are discarded. This is used in the lazy match evaluation. + */ + + uInt max_chain_length; + /* To speed up deflation, hash chains are never searched beyond this + * length. A higher limit improves compression ratio but degrades the + * speed. + */ + + uInt max_lazy_match; + /* Attempt to find a better match only when the current match is strictly + * smaller than this value. This mechanism is used only for compression + * levels >= 4. + */ +# define max_insert_length max_lazy_match + /* Insert new strings in the hash table only if the match length is not + * greater than this length. This saves time but degrades compression. + * max_insert_length is used only for compression levels <= 3. + */ + + int level; /* compression level (1..9) */ + int strategy; /* favor or force Huffman coding*/ + + uInt good_match; + /* Use a faster search when the previous match is longer than this */ + + int nice_match; /* Stop searching when current match exceeds this */ + + /* used by trees.c: */ + /* Didn't use ct_data typedef below to supress compiler warning */ + struct ct_data_s dyn_ltree[HEAP_SIZE]; /* literal and length tree */ + struct ct_data_s dyn_dtree[2*D_CODES+1]; /* distance tree */ + struct ct_data_s bl_tree[2*BL_CODES+1]; /* Huffman tree for bit lengths */ + + struct tree_desc_s l_desc; /* desc. for literal tree */ + struct tree_desc_s d_desc; /* desc. for distance tree */ + struct tree_desc_s bl_desc; /* desc. for bit length tree */ + + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + int heap[2*L_CODES+1]; /* heap used to build the Huffman trees */ + int heap_len; /* number of elements in the heap */ + int heap_max; /* element of largest frequency */ + /* The sons of heap[n] are heap[2*n] and heap[2*n+1]. heap[0] is not used. + * The same heap array is used to build all trees. + */ + + uch depth[2*L_CODES+1]; + /* Depth of each subtree used as tie breaker for trees of equal frequency + */ + + uchf *l_buf; /* buffer for literals or lengths */ + + uInt lit_bufsize; + /* Size of match buffer for literals/lengths. There are 4 reasons for + * limiting lit_bufsize to 64K: + * - frequencies can be kept in 16 bit counters + * - if compression is not successful for the first block, all input + * data is still in the window so we can still emit a stored block even + * when input comes from standard input. (This can also be done for + * all blocks if lit_bufsize is not greater than 32K.) + * - if compression is not successful for a file smaller than 64K, we can + * even emit a stored file instead of a stored block (saving 5 bytes). + * This is applicable only for zip (not gzip or zlib). + * - creating new Huffman trees less frequently may not provide fast + * adaptation to changes in the input data statistics. (Take for + * example a binary file with poorly compressible code followed by + * a highly compressible string table.) Smaller buffer sizes give + * fast adaptation but have of course the overhead of transmitting + * trees more frequently. + * - I can't count above 4 + */ + + uInt last_lit; /* running index in l_buf */ + + ushf *d_buf; + /* Buffer for distances. To simplify the code, d_buf and l_buf have + * the same number of elements. To use different lengths, an extra flag + * array would be necessary. + */ + + ulg opt_len; /* bit length of current block with optimal trees */ + ulg static_len; /* bit length of current block with static trees */ + uInt matches; /* number of string matches in current block */ + int last_eob_len; /* bit length of EOB code for last block */ + +#ifdef DEBUG + ulg compressed_len; /* total bit length of compressed file mod 2^32 */ + ulg bits_sent; /* bit length of compressed data sent mod 2^32 */ +#endif + + ush bi_buf; + /* Output buffer. bits are inserted starting at the bottom (least + * significant bits). + */ + int bi_valid; + /* Number of valid bits in bi_buf. All bits above the last valid bit + * are always zero. + */ + +} FAR deflate_state; + +/* Output a byte on the stream. + * IN assertion: there is enough room in pending_buf. + */ +#define put_byte(s, c) {s->pending_buf[s->pending++] = (c);} + + +#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) +/* Minimum amount of lookahead, except at the end of the input file. + * See deflate.c for comments about the MIN_MATCH+1. + */ + +#define MAX_DIST(s) ((s)->w_size-MIN_LOOKAHEAD) +/* In order to simplify the code, particularly on 16 bit machines, match + * distances are limited to MAX_DIST instead of WSIZE. + */ + + /* in trees.c */ +void _tr_init OF((deflate_state *s)); +int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); +void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); +void _tr_align OF((deflate_state *s)); +void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, + int eof)); + +#define d_code(dist) \ + ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) +/* Mapping from a distance to a distance code. dist is the distance - 1 and + * must not have side effects. _dist_code[256] and _dist_code[257] are never + * used. + */ + +#ifndef DEBUG +/* Inline versions of _tr_tally for speed: */ + +#if defined(GEN_TREES_H) || !defined(STDC) + extern uch _length_code[]; + extern uch _dist_code[]; +#else + extern const uch _length_code[]; + extern const uch _dist_code[]; +#endif + +# define _tr_tally_lit(s, c, flush) \ + { uch cc = (c); \ + s->d_buf[s->last_lit] = 0; \ + s->l_buf[s->last_lit++] = cc; \ + s->dyn_ltree[cc].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +# define _tr_tally_dist(s, distance, length, flush) \ + { uch len = (length); \ + ush dist = (distance); \ + s->d_buf[s->last_lit] = dist; \ + s->l_buf[s->last_lit++] = len; \ + dist--; \ + s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ + s->dyn_dtree[d_code(dist)].Freq++; \ + flush = (s->last_lit == s->lit_bufsize-1); \ + } +#else +# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) +# define _tr_tally_dist(s, distance, length, flush) \ + flush = _tr_tally(s, distance, length) +#endif + +#endif diff --git a/src/zlib/gzio.c b/src/zlib/gzio.c new file mode 100644 index 0000000..6142b0a --- /dev/null +++ b/src/zlib/gzio.c @@ -0,0 +1,875 @@ +/* gzio.c -- IO on .gz files + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Compile this file with -DNO_DEFLATE to avoid the compression code. + */ + +/* @(#) $Id: gzio.c,v 1.2 2002/03/13 17:45:56 xodnizel Exp $ */ + +#include + +#include "zutil.h" + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#ifndef Z_BUFSIZE +# ifdef MAXSEG_64K +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ +# else +# define Z_BUFSIZE 16384 +# endif +#endif +#ifndef Z_PRINTF_BUFSIZE +# define Z_PRINTF_BUFSIZE 4096 +#endif + +#define ALLOC(size) malloc(size) +#define TRYFREE(p) {if (p) free(p);} + +static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ + +/* gzip flag byte */ +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +#define COMMENT 0x10 /* bit 4 set: file comment present */ +#define RESERVED 0xE0 /* bits 5..7: reserved */ + +typedef struct gz_stream { + z_stream stream; + int z_err; /* error code for last stream operation */ + int z_eof; /* set if end of input file */ + FILE *file; /* .gz file */ + Byte *inbuf; /* input buffer */ + Byte *outbuf; /* output buffer */ + uLong crc; /* crc32 of uncompressed data */ + char *msg; /* error message */ + char *path; /* path name for debugging only */ + int transparent; /* 1 if input file is not a .gz file */ + char mode; /* 'w' or 'r' */ + long startpos; /* start of compressed data in file (header skipped) */ +} gz_stream; + + +local gzFile gz_open OF((const char *path, const char *mode, int fd)); +local int do_flush OF((gzFile file, int flush)); +local int get_byte OF((gz_stream *s)); +local void check_header OF((gz_stream *s)); +local int destroy OF((gz_stream *s)); +local void putLong OF((FILE *file, uLong x)); +local uLong getLong OF((gz_stream *s)); + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb"). The file is given either by file descriptor + or path name (if fd == -1). + gz_open return NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). +*/ +local gzFile gz_open (path, mode, fd) + const char *path; + const char *mode; + int fd; +{ + int err; + int level = Z_DEFAULT_COMPRESSION; /* compression level */ + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ + char *p = (char*)mode; + gz_stream *s; + char fmode[80]; /* copy of mode, without the compression level */ + char *m = fmode; + + if (!path || !mode) return Z_NULL; + + s = (gz_stream *)ALLOC(sizeof(gz_stream)); + if (!s) return Z_NULL; + + s->stream.zalloc = (alloc_func)0; + s->stream.zfree = (free_func)0; + s->stream.opaque = (voidpf)0; + s->stream.next_in = s->inbuf = Z_NULL; + s->stream.next_out = s->outbuf = Z_NULL; + s->stream.avail_in = s->stream.avail_out = 0; + s->file = NULL; + s->z_err = Z_OK; + s->z_eof = 0; + s->crc = crc32(0L, Z_NULL, 0); + s->msg = NULL; + s->transparent = 0; + + s->path = (char*)ALLOC(strlen(path)+1); + if (s->path == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + strcpy(s->path, path); /* do this early for debugging */ + + s->mode = '\0'; + do { + if (*p == 'r') s->mode = 'r'; + if (*p == 'w' || *p == 'a') s->mode = 'w'; + if (*p >= '0' && *p <= '9') { + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else { + *m++ = *p; /* copy the mode */ + } + } while (*p++ && m != fmode + sizeof(fmode)); + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + err = Z_STREAM_ERROR; +#else + err = deflateInit2(&(s->stream), level, + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); + /* windowBits is passed < 0 to suppress zlib header */ + + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); +#endif + if (err != Z_OK || s->outbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } else { + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); + + err = inflateInit2(&(s->stream), -MAX_WBITS); + /* 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. Here the gzip CRC32 ensures that 4 bytes are + * present after the compressed stream. + */ + if (err != Z_OK || s->inbuf == Z_NULL) { + return destroy(s), (gzFile)Z_NULL; + } + } + s->stream.avail_out = Z_BUFSIZE; + + errno = 0; + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); + + if (s->file == NULL) { + return destroy(s), (gzFile)Z_NULL; + } + if (s->mode == 'w') { + /* Write a very simple .gz header: + */ + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); + s->startpos = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an + * fflush on some systems. This version of the library doesn't use + * startpos anyway in write mode, so this initialization is not + * necessary. + */ + } else { + check_header(s); /* skip the .gz header */ + s->startpos = (ftell(s->file) - s->stream.avail_in); + } + + return (gzFile)s; +} + +/* =========================================================================== + Opens a gzip (.gz) file for reading or writing. +*/ +gzFile ZEXPORT gzopen (path, mode) + const char *path; + const char *mode; +{ + return gz_open (path, mode, -1); +} + +/* =========================================================================== + Associate a gzFile with the file descriptor fd. fd is not dup'ed here + to mimic the behavio(u)r of fdopen. +*/ +gzFile ZEXPORT gzdopen (fd, mode) + int fd; + const char *mode; +{ + char name[20]; + + if (fd < 0) return (gzFile)Z_NULL; + sprintf(name, "", fd); /* for debugging */ + + return gz_open (name, mode, fd); +} + +/* =========================================================================== + * Update the compression level and strategy + */ +int ZEXPORT gzsetparams (file, level, strategy) + gzFile file; + int level; + int strategy; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + /* Make room to allow flushing */ + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; + } + + return deflateParams (&(s->stream), level, strategy); +} + +/* =========================================================================== + 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 get_byte(s) + gz_stream *s; +{ + if (s->z_eof) return EOF; + if (s->stream.avail_in == 0) { + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; + } + s->stream.avail_in--; + return *(s->stream.next_in)++; +} + +/* =========================================================================== + Check the gzip header of a gz_stream opened for reading. Set the stream + mode to transparent if the gzip magic header is not present; set s->err + to Z_DATA_ERROR if the magic header is present but the rest of the header + is incorrect. + IN assertion: the stream s has already been created sucessfully; + s->stream.avail_in is zero for the first time, but may be non-zero + for concatenated .gz files. +*/ +local void check_header(s) + gz_stream *s; +{ + int method; /* method byte */ + int flags; /* flags byte */ + uInt len; + int c; + + /* Check the gzip magic header */ + for (len = 0; len < 2; len++) { + c = get_byte(s); + if (c != gz_magic[len]) { + if (len != 0) s->stream.avail_in++, s->stream.next_in--; + if (c != EOF) { + s->stream.avail_in++, s->stream.next_in--; + s->transparent = 1; + } + s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END; + return; + } + } + method = get_byte(s); + flags = get_byte(s); + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { + s->z_err = Z_DATA_ERROR; + return; + } + + /* Discard time, xflags and OS code: */ + for (len = 0; len < 6; len++) (void)get_byte(s); + + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; + } + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ + while ((c = get_byte(s)) != 0 && c != EOF) ; + } + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ + for (len = 0; len < 2; len++) (void)get_byte(s); + } + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; +} + + /* =========================================================================== + * Cleanup then free the given gz_stream. Return a zlib error code. + Try freeing in the reverse order of allocations. + */ +local int destroy (s) + gz_stream *s; +{ + int err = Z_OK; + + if (!s) return Z_STREAM_ERROR; + + TRYFREE(s->msg); + + if (s->stream.state != NULL) { + if (s->mode == 'w') { +#ifdef NO_DEFLATE + err = Z_STREAM_ERROR; +#else + err = deflateEnd(&(s->stream)); +#endif + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } + } + if (s->file != NULL && fclose(s->file)) { +#ifdef ESPIPE + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ +#endif + err = Z_ERRNO; + } + if (s->z_err < 0) err = s->z_err; + + TRYFREE(s->inbuf); + TRYFREE(s->outbuf); + TRYFREE(s->path); + TRYFREE(s); + return err; +} + +/* =========================================================================== + Reads the given number of uncompressed bytes from the compressed file. + gzread returns the number of bytes actually read (0 for end of file). +*/ +int ZEXPORT gzread (file, buf, len) + gzFile file; + voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ + + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; + + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ + + next_out = (Byte*)buf; + s->stream.next_out = (Bytef*)buf; + s->stream.avail_out = len; + + while (s->stream.avail_out != 0) { + + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, + s->file); + } + len -= s->stream.avail_out; + s->stream.total_in += (uLong)len; + s->stream.total_out += (uLong)len; + if (len == 0) s->z_eof = 1; + return (int)len; + } + if (s->stream.avail_in == 0 && !s->z_eof) { + + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } + } + s->stream.next_in = s->inbuf; + } + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may + * be different from s->stream.total_out) in case of + * concatenated .gz files. Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + uLong total_in = s->stream.total_in; + uLong total_out = s->stream.total_out; + + inflateReset(&(s->stream)); + s->stream.total_in = total_in; + s->stream.total_out = total_out; + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; + } + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + + return (int)(len - s->stream.avail_out); +} + + +/* =========================================================================== + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ +int ZEXPORT gzgetc(file) + gzFile file; +{ + unsigned char c; + + return gzread(file, &c, 1) == 1 ? c : -1; +} + + +/* =========================================================================== + Reads bytes from the compressed file until len-1 characters are + read, or a newline character is read and transferred to buf, or an + end-of-file condition is encountered. The string is then terminated + with a null character. + gzgets returns buf, or Z_NULL in case of error. + + The current implementation is not optimized at all. +*/ +char * ZEXPORT gzgets(file, buf, len) + gzFile file; + char *buf; + int len; +{ + char *b = buf; + if (buf == Z_NULL || len <= 0) return Z_NULL; + + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; + *buf = '\0'; + return b == buf && len > 0 ? Z_NULL : b; +} + + +#ifndef NO_DEFLATE +/* =========================================================================== + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of bytes actually written (0 in case of error). +*/ +int ZEXPORT gzwrite (file, buf, len) + gzFile file; + const voidp buf; + unsigned len; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.next_in = (Bytef*)buf; + s->stream.avail_in = len; + + while (s->stream.avail_in != 0) { + + if (s->stream.avail_out == 0) { + + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + break; + } + s->stream.avail_out = Z_BUFSIZE; + } + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + if (s->z_err != Z_OK) break; + } + s->crc = crc32(s->crc, (const Bytef *)buf, len); + + return (int)(len - s->stream.avail_in); +} + +/* =========================================================================== + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ +#ifdef STDC +#include + +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) +{ + char buf[Z_PRINTF_BUFSIZE]; + va_list va; + int len; + + va_start(va, format); +#ifdef HAS_vsnprintf + (void)vsnprintf(buf, sizeof(buf), format, va); +#else + (void)vsprintf(buf, format, va); +#endif + va_end(va); + len = strlen(buf); /* some *sprintf don't return the nb of bytes written */ + if (len <= 0) return 0; + + return gzwrite(file, buf, (unsigned)len); +} +#else /* not ANSI C */ + +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + gzFile file; + const char *format; + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; +{ + char buf[Z_PRINTF_BUFSIZE]; + int len; + +#ifdef HAS_snprintf + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +#else + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +#endif + len = strlen(buf); /* old sprintf doesn't return the nb of bytes written */ + if (len <= 0) return 0; + + return gzwrite(file, buf, len); +} +#endif + +/* =========================================================================== + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ +int ZEXPORT gzputc(file, c) + gzFile file; + int c; +{ + unsigned char cc = (unsigned char) c; /* required for big endian systems */ + + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; +} + + +/* =========================================================================== + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ +int ZEXPORT gzputs(file, s) + gzFile file; + const char *s; +{ + return gzwrite(file, (char*)s, (unsigned)strlen(s)); +} + + +/* =========================================================================== + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. +*/ +local int do_flush (file, flush) + gzFile file; + int flush; +{ + uInt len; + int done = 0; + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; + + s->stream.avail_in = 0; /* should be zero already anyway */ + + for (;;) { + len = Z_BUFSIZE - s->stream.avail_out; + + if (len != 0) { + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { + s->z_err = Z_ERRNO; + return Z_ERRNO; + } + s->stream.next_out = s->outbuf; + s->stream.avail_out = Z_BUFSIZE; + } + if (done) break; + s->z_err = deflate(&(s->stream), flush); + + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + + /* deflate has finished flushing only when it hasn't used up + * all the available space in the output buffer: + */ + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); + + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; + } + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} + +int ZEXPORT gzflush (file, flush) + gzFile file; + int flush; +{ + gz_stream *s = (gz_stream*)file; + int err = do_flush (file, flush); + + if (err) return err; + fflush(s->file); + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; +} +#endif /* NO_DEFLATE */ + +/* =========================================================================== + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error. + SEEK_END is not implemented, returns error. + In this version of the library, gzseek can be extremely slow. +*/ +z_off_t ZEXPORT gzseek (file, offset, whence) + gzFile file; + z_off_t offset; + int whence; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || whence == SEEK_END || + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; + } + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + return -1L; +#else + if (whence == SEEK_SET) { + offset -= s->stream.total_in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return (z_off_t)s->stream.total_in; +#endif + } + /* Rest of function is for reading only */ + + /* compute absolute position */ + if (whence == SEEK_CUR) { + offset += s->stream.total_out; + } + if (offset < 0) return -1L; + + if (s->transparent) { + /* map to fseek */ + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; + + s->stream.total_in = s->stream.total_out = (uLong)offset; + return offset; + } + + /* For a negative seek, rewind and use positive seek */ + if ((uLong)offset >= s->stream.total_out) { + offset -= s->stream.total_out; + } else if (gzrewind(file) < 0) { + return -1L; + } + /* offset is now the number of bytes to skip. */ + + if (offset != 0 && s->outbuf == Z_NULL) { + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + } + while (offset > 0) { + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; + + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; + } + return (z_off_t)s->stream.total_out; +} + +/* =========================================================================== + Rewinds input file. +*/ +int ZEXPORT gzrewind (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r') return -1; + + s->z_err = Z_OK; + s->z_eof = 0; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; + s->crc = crc32(0L, Z_NULL, 0); + + if (s->startpos == 0) { /* not a compressed file */ + rewind(s->file); + return 0; + } + + (void) inflateReset(&s->stream); + return fseek(s->file, s->startpos, SEEK_SET); +} + +/* =========================================================================== + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. +*/ +z_off_t ZEXPORT gztell (file) + gzFile file; +{ + return gzseek(file, 0L, SEEK_CUR); +} + +/* =========================================================================== + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ +int ZEXPORT gzeof (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + return (s == NULL || s->mode != 'r') ? 0 : s->z_eof; +} + +/* =========================================================================== + Outputs a long in LSB order to the given file +*/ +local void putLong (file, x) + FILE *file; + uLong x; +{ + int n; + for (n = 0; n < 4; n++) { + fputc((int)(x & 0xff), file); + x >>= 8; + } +} + +/* =========================================================================== + Reads a long in LSB order from the given gz_stream. Sets z_err in case + of error. +*/ +local uLong getLong (s) + gz_stream *s; +{ + uLong x = (uLong)get_byte(s); + int c; + + x += ((uLong)get_byte(s))<<8; + x += ((uLong)get_byte(s))<<16; + c = get_byte(s); + if (c == EOF) s->z_err = Z_DATA_ERROR; + x += ((uLong)c)<<24; + return x; +} + +/* =========================================================================== + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. +*/ +int ZEXPORT gzclose (file) + gzFile file; +{ + int err; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return Z_STREAM_ERROR; + + if (s->mode == 'w') { +#ifdef NO_DEFLATE + return Z_STREAM_ERROR; +#else + err = do_flush (file, Z_FINISH); + if (err != Z_OK) return destroy((gz_stream*)file); + + putLong (s->file, s->crc); + putLong (s->file, s->stream.total_in); +#endif + } + return destroy((gz_stream*)file); +} + +/* =========================================================================== + Returns the error message for the last error which occured on the + given compressed file. errnum is set to zlib error number. If an + error occured in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ +const char* ZEXPORT gzerror (file, errnum) + gzFile file; + int *errnum; +{ + char *m; + gz_stream *s = (gz_stream*)file; + + if (s == NULL) { + *errnum = Z_STREAM_ERROR; + return (const char*)ERR_MSG(Z_STREAM_ERROR); + } + *errnum = s->z_err; + if (*errnum == Z_OK) return (const char*)""; + + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); + + TRYFREE(s->msg); + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + strcpy(s->msg, s->path); + strcat(s->msg, ": "); + strcat(s->msg, m); + return (const char*)s->msg; +} diff --git a/src/zlib/infblock.c b/src/zlib/infblock.c new file mode 100644 index 0000000..dd7a6d4 --- /dev/null +++ b/src/zlib/infblock.c @@ -0,0 +1,403 @@ +/* infblock.c -- interpret and process block types to last block + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* Table for deflate from PKZIP's appnote.txt. */ +local const uInt border[] = { /* Order of the bit length code lengths */ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + +/* + Notes beyond the 1.93a appnote.txt: + + 1. Distance pointers never point before the beginning of the output + stream. + 2. Distance pointers can point back across blocks, up to 32k away. + 3. There is an implied maximum of 7 bits for the bit length table and + 15 bits for the actual data. + 4. If only one code exists, then it is encoded using one bit. (Zero + would be more efficient, but perhaps a little confusing.) If two + codes exist, they are coded using one bit each (0 and 1). + 5. There is no way of sending zero distance codes--a dummy must be + sent if there are none. (History: a pre 2.0 version of PKZIP would + store blocks with no distance codes, but this was discovered to be + too harsh a criterion.) Valid only for 1.93a. 2.04c does allow + zero distance codes, which is sent as one code of zero bits in + length. + 6. There are up to 286 literal/length codes. Code 256 represents the + end-of-block. Note however that the static length tree defines + 288 codes just to fill out the Huffman codes. Codes 286 and 287 + cannot be used though, since there is no length base or extra bits + defined for them. Similarily, there are up to 30 distance codes. + However, static trees define 32 codes (all 5 bits) to fill out the + Huffman codes, but the last two had better not show up in the data. + 7. Unzip can check dynamic Huffman blocks for complete code sets. + The exception is that a single code would not be complete (see #4). + 8. The five bits following the block type is really the number of + literal codes sent minus 257. + 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits + (1+6+6). Therefore, to output three times the length, you output + three codes (1+1+1), whereas to output four times the same length, + you only need two codes (1+3). Hmm. + 10. In the tree reconstruction algorithm, Code = Code + Increment + only if BitLength(i) is not zero. (Pretty obvious.) + 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) + 12. Note: length code 284 can represent 227-258, but length code 285 + really is 258. The last length deserves its own, short code + since it gets used a lot in very redundant files. The length + 258 is special since 258 - 3 (the min match length) is 255. + 13. The literal/length and distance code bit lengths are read as a + single stream of lengths. It is possible (and advantageous) for + a repeat code (16, 17, or 18) to go across the boundary between + the two sets of lengths. + */ + + +void inflate_blocks_reset(s, z, c) +inflate_blocks_statef *s; +z_streamp z; +uLongf *c; +{ + if (c != Z_NULL) + *c = s->check; + if (s->mode == BTREE || s->mode == DTREE) + ZFREE(z, s->sub.trees.blens); + if (s->mode == CODES) + inflate_codes_free(s->sub.decode.codes, z); + s->mode = TYPE; + s->bitk = 0; + s->bitb = 0; + s->read = s->write = s->window; + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(0L, (const Bytef *)Z_NULL, 0); + Tracev((stderr, "inflate: blocks reset\n")); +} + + +inflate_blocks_statef *inflate_blocks_new(z, c, w) +z_streamp z; +check_func c; +uInt w; +{ + inflate_blocks_statef *s; + + if ((s = (inflate_blocks_statef *)ZALLOC + (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL) + return s; + if ((s->hufts = + (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL) + { + ZFREE(z, s); + return Z_NULL; + } + if ((s->window = (Bytef *)ZALLOC(z, 1, w)) == Z_NULL) + { + ZFREE(z, s->hufts); + ZFREE(z, s); + return Z_NULL; + } + s->end = s->window + w; + s->checkfn = c; + s->mode = TYPE; + Tracev((stderr, "inflate: blocks allocated\n")); + inflate_blocks_reset(s, z, Z_NULL); + return s; +} + + +int inflate_blocks(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt t; /* temporary storage */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input based on current state */ + while (1) switch (s->mode) + { + case TYPE: + NEEDBITS(3) + t = (uInt)b & 7; + s->last = t & 1; + switch (t >> 1) + { + case 0: /* stored */ + Tracev((stderr, "inflate: stored block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + t = k & 7; /* go to byte boundary */ + DUMPBITS(t) + s->mode = LENS; /* get length of stored block */ + break; + case 1: /* fixed */ + Tracev((stderr, "inflate: fixed codes block%s\n", + s->last ? " (last)" : "")); + { + uInt bl, bd; + inflate_huft *tl, *td; + + inflate_trees_fixed(&bl, &bd, &tl, &td, z); + s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z); + if (s->sub.decode.codes == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + } + DUMPBITS(3) + s->mode = CODES; + break; + case 2: /* dynamic */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + s->last ? " (last)" : "")); + DUMPBITS(3) + s->mode = TABLE; + break; + case 3: /* illegal */ + DUMPBITS(3) + s->mode = BAD; + z->msg = (char*)"invalid block type"; + r = Z_DATA_ERROR; + LEAVE + } + break; + case LENS: + NEEDBITS(32) + if ((((~b) >> 16) & 0xffff) != (b & 0xffff)) + { + s->mode = BAD; + z->msg = (char*)"invalid stored block lengths"; + r = Z_DATA_ERROR; + LEAVE + } + s->sub.left = (uInt)b & 0xffff; + b = k = 0; /* dump bits */ + Tracev((stderr, "inflate: stored length %u\n", s->sub.left)); + s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE); + break; + case STORED: + if (n == 0) + LEAVE + NEEDOUT + t = s->sub.left; + if (t > n) t = n; + if (t > m) t = m; + zmemcpy(q, p, t); + p += t; n -= t; + q += t; m -= t; + if ((s->sub.left -= t) != 0) + break; + Tracev((stderr, "inflate: stored end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + s->mode = s->last ? DRY : TYPE; + break; + case TABLE: + NEEDBITS(14) + s->sub.trees.table = t = (uInt)b & 0x3fff; +#ifndef PKZIP_BUG_WORKAROUND + if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) + { + s->mode = BAD; + z->msg = (char*)"too many length or distance symbols"; + r = Z_DATA_ERROR; + LEAVE + } +#endif + t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); + if ((s->sub.trees.blens = (uIntf*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + DUMPBITS(14) + s->sub.trees.index = 0; + Tracev((stderr, "inflate: table sizes ok\n")); + s->mode = BTREE; + case BTREE: + while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10)) + { + NEEDBITS(3) + s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7; + DUMPBITS(3) + } + while (s->sub.trees.index < 19) + s->sub.trees.blens[border[s->sub.trees.index++]] = 0; + s->sub.trees.bb = 7; + t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb, + &s->sub.trees.tb, s->hufts, z); + if (t != Z_OK) + { + r = t; + if (r == Z_DATA_ERROR) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + } + LEAVE + } + s->sub.trees.index = 0; + Tracev((stderr, "inflate: bits tree ok\n")); + s->mode = DTREE; + case DTREE: + while (t = s->sub.trees.table, + s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) + { + inflate_huft *h; + uInt i, j, c; + + t = s->sub.trees.bb; + NEEDBITS(t) + h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]); + t = h->bits; + c = h->base; + if (c < 16) + { + DUMPBITS(t) + s->sub.trees.blens[s->sub.trees.index++] = c; + } + else /* c == 16..18 */ + { + i = c == 18 ? 7 : c - 14; + j = c == 18 ? 11 : 3; + NEEDBITS(t + i) + DUMPBITS(t) + j += (uInt)b & inflate_mask[i]; + DUMPBITS(i) + i = s->sub.trees.index; + t = s->sub.trees.table; + if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || + (c == 16 && i < 1)) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + z->msg = (char*)"invalid bit length repeat"; + r = Z_DATA_ERROR; + LEAVE + } + c = c == 16 ? s->sub.trees.blens[i - 1] : 0; + do { + s->sub.trees.blens[i++] = c; + } while (--j); + s->sub.trees.index = i; + } + } + s->sub.trees.tb = Z_NULL; + { + uInt bl, bd; + inflate_huft *tl, *td; + inflate_codes_statef *c; + + bl = 9; /* must be <= 9 for lookahead assumptions */ + bd = 6; /* must be <= 9 for lookahead assumptions */ + t = s->sub.trees.table; + t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), + s->sub.trees.blens, &bl, &bd, &tl, &td, + s->hufts, z); + if (t != Z_OK) + { + if (t == (uInt)Z_DATA_ERROR) + { + ZFREE(z, s->sub.trees.blens); + s->mode = BAD; + } + r = t; + LEAVE + } + Tracev((stderr, "inflate: trees ok\n")); + if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL) + { + r = Z_MEM_ERROR; + LEAVE + } + s->sub.decode.codes = c; + } + ZFREE(z, s->sub.trees.blens); + s->mode = CODES; + case CODES: + UPDATE + if ((r = inflate_codes(s, z, r)) != Z_STREAM_END) + return inflate_flush(s, z, r); + r = Z_OK; + inflate_codes_free(s->sub.decode.codes, z); + LOAD + Tracev((stderr, "inflate: codes end, %lu total out\n", + z->total_out + (q >= s->read ? q - s->read : + (s->end - s->read) + (q - s->window)))); + if (!s->last) + { + s->mode = TYPE; + break; + } + s->mode = DRY; + case DRY: + FLUSH + if (s->read != s->write) + LEAVE + s->mode = DONE; + case DONE: + r = Z_STREAM_END; + LEAVE + case BAD: + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +} + + +int inflate_blocks_free(s, z) +inflate_blocks_statef *s; +z_streamp z; +{ + inflate_blocks_reset(s, z, Z_NULL); + ZFREE(z, s->window); + ZFREE(z, s->hufts); + ZFREE(z, s); + Tracev((stderr, "inflate: blocks freed\n")); + return Z_OK; +} + + +void inflate_set_dictionary(s, d, n) +inflate_blocks_statef *s; +const Bytef *d; +uInt n; +{ + zmemcpy(s->window, d, n); + s->read = s->write = s->window + n; +} + + +/* Returns true if inflate is currently at the end of a block generated + * by Z_SYNC_FLUSH or Z_FULL_FLUSH. + * IN assertion: s != Z_NULL + */ +int inflate_blocks_sync_point(s) +inflate_blocks_statef *s; +{ + return s->mode == LENS; +} diff --git a/src/zlib/infblock.h b/src/zlib/infblock.h new file mode 100644 index 0000000..173b226 --- /dev/null +++ b/src/zlib/infblock.h @@ -0,0 +1,39 @@ +/* infblock.h -- header to use infblock.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_blocks_state; +typedef struct inflate_blocks_state FAR inflate_blocks_statef; + +extern inflate_blocks_statef * inflate_blocks_new OF(( + z_streamp z, + check_func c, /* check function */ + uInt w)); /* window size */ + +extern int inflate_blocks OF(( + inflate_blocks_statef *, + z_streamp , + int)); /* initial return code */ + +extern void inflate_blocks_reset OF(( + inflate_blocks_statef *, + z_streamp , + uLongf *)); /* check value on output */ + +extern int inflate_blocks_free OF(( + inflate_blocks_statef *, + z_streamp)); + +extern void inflate_set_dictionary OF(( + inflate_blocks_statef *s, + const Bytef *d, /* dictionary */ + uInt n)); /* dictionary length */ + +extern int inflate_blocks_sync_point OF(( + inflate_blocks_statef *s)); diff --git a/src/zlib/infcodes.c b/src/zlib/infcodes.c new file mode 100644 index 0000000..9abe541 --- /dev/null +++ b/src/zlib/infcodes.c @@ -0,0 +1,251 @@ +/* infcodes.c -- process literals and length/distance pairs + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "infblock.h" +#include "infcodes.h" +#include "infutil.h" +#include "inffast.h" + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + START, /* x: set up for LEN */ + LEN, /* i: get length/literal/eob next */ + LENEXT, /* i: getting length extra (have base) */ + DIST, /* i: get distance next */ + DISTEXT, /* i: getting distance extra */ + COPY, /* o: copying bytes in window, waiting for space */ + LIT, /* o: got literal, waiting for output space */ + WASH, /* o: got eob, possibly still output waiting */ + END, /* x: got eob and all data flushed */ + BADCODE} /* x: got error */ +inflate_codes_mode; + +/* inflate codes private state */ +struct inflate_codes_state { + + /* mode */ + inflate_codes_mode mode; /* current inflate_codes mode */ + + /* mode dependent information */ + uInt len; + union { + struct { + inflate_huft *tree; /* pointer into tree */ + uInt need; /* bits needed */ + } code; /* if LEN or DIST, where in tree */ + uInt lit; /* if LIT, literal */ + struct { + uInt get; /* bits to get for extra */ + uInt dist; /* distance back to copy from */ + } copy; /* if EXT or COPY, where and how much */ + } sub; /* submode */ + + /* mode independent information */ + Byte lbits; /* ltree bits decoded per branch */ + Byte dbits; /* dtree bits decoder per branch */ + inflate_huft *ltree; /* literal/length/eob tree */ + inflate_huft *dtree; /* distance tree */ + +}; + + +inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z) +uInt bl, bd; +inflate_huft *tl; +inflate_huft *td; /* need separate declaration for Borland C++ */ +z_streamp z; +{ + inflate_codes_statef *c; + + if ((c = (inflate_codes_statef *) + ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL) + { + c->mode = START; + c->lbits = (Byte)bl; + c->dbits = (Byte)bd; + c->ltree = tl; + c->dtree = td; + Tracev((stderr, "inflate: codes new\n")); + } + return c; +} + + +int inflate_codes(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt j; /* temporary storage */ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + Bytef *f; /* pointer to copy strings from */ + inflate_codes_statef *c = s->sub.decode.codes; /* codes state */ + + /* copy input/output information to locals (UPDATE macro restores) */ + LOAD + + /* process input and output based on current state */ + while (1) switch (c->mode) + { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */ + case START: /* x: set up for LEN */ +#ifndef SLOW + if (m >= 258 && n >= 10) + { + UPDATE + r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z); + LOAD + if (r != Z_OK) + { + c->mode = r == Z_STREAM_END ? WASH : BADCODE; + break; + } + } +#endif /* !SLOW */ + c->sub.code.need = c->lbits; + c->sub.code.tree = c->ltree; + c->mode = LEN; + case LEN: /* i: get length/literal/eob next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e == 0) /* literal */ + { + c->sub.lit = t->base; + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", t->base)); + c->mode = LIT; + break; + } + if (e & 16) /* length */ + { + c->sub.copy.get = e & 15; + c->len = t->base; + c->mode = LENEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + if (e & 32) /* end of block */ + { + Tracevv((stderr, "inflate: end of block\n")); + c->mode = WASH; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = (char*)"invalid literal/length code"; + r = Z_DATA_ERROR; + LEAVE + case LENEXT: /* i: getting length extra (have base) */ + j = c->sub.copy.get; + NEEDBITS(j) + c->len += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + c->sub.code.need = c->dbits; + c->sub.code.tree = c->dtree; + Tracevv((stderr, "inflate: length %u\n", c->len)); + c->mode = DIST; + case DIST: /* i: get distance next */ + j = c->sub.code.need; + NEEDBITS(j) + t = c->sub.code.tree + ((uInt)b & inflate_mask[j]); + DUMPBITS(t->bits) + e = (uInt)(t->exop); + if (e & 16) /* distance */ + { + c->sub.copy.get = e & 15; + c->sub.copy.dist = t->base; + c->mode = DISTEXT; + break; + } + if ((e & 64) == 0) /* next table */ + { + c->sub.code.need = e; + c->sub.code.tree = t + t->base; + break; + } + c->mode = BADCODE; /* invalid code */ + z->msg = (char*)"invalid distance code"; + r = Z_DATA_ERROR; + LEAVE + case DISTEXT: /* i: getting distance extra */ + j = c->sub.copy.get; + NEEDBITS(j) + c->sub.copy.dist += (uInt)b & inflate_mask[j]; + DUMPBITS(j) + Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist)); + c->mode = COPY; + case COPY: /* o: copying bytes in window, waiting for space */ + f = q - c->sub.copy.dist; + while (f < s->window) /* modulo window size-"while" instead */ + f += s->end - s->window; /* of "if" handles invalid distances */ + while (c->len) + { + NEEDOUT + OUTBYTE(*f++) + if (f == s->end) + f = s->window; + c->len--; + } + c->mode = START; + break; + case LIT: /* o: got literal, waiting for output space */ + NEEDOUT + OUTBYTE(c->sub.lit) + c->mode = START; + break; + case WASH: /* o: got eob, possibly more output */ + if (k > 7) /* return unused byte, if any */ + { + Assert(k < 16, "inflate_codes grabbed too many bytes") + k -= 8; + n++; + p--; /* can always return one */ + } + FLUSH + if (s->read != s->write) + LEAVE + c->mode = END; + case END: + r = Z_STREAM_END; + LEAVE + case BADCODE: /* x: got error */ + r = Z_DATA_ERROR; + LEAVE + default: + r = Z_STREAM_ERROR; + LEAVE + } +#ifdef NEED_DUMMY_RETURN + return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ +#endif +} + + +void inflate_codes_free(c, z) +inflate_codes_statef *c; +z_streamp z; +{ + ZFREE(z, c); + Tracev((stderr, "inflate: codes free\n")); +} diff --git a/src/zlib/infcodes.h b/src/zlib/infcodes.h new file mode 100644 index 0000000..46821a0 --- /dev/null +++ b/src/zlib/infcodes.h @@ -0,0 +1,27 @@ +/* infcodes.h -- header to use infcodes.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +struct inflate_codes_state; +typedef struct inflate_codes_state FAR inflate_codes_statef; + +extern inflate_codes_statef *inflate_codes_new OF(( + uInt, uInt, + inflate_huft *, inflate_huft *, + z_streamp )); + +extern int inflate_codes OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +extern void inflate_codes_free OF(( + inflate_codes_statef *, + z_streamp )); + diff --git a/src/zlib/inffast.c b/src/zlib/inffast.c new file mode 100644 index 0000000..aa7f1d4 --- /dev/null +++ b/src/zlib/inffast.c @@ -0,0 +1,183 @@ +/* inffast.c -- process literals and length/distance pairs fast + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "infblock.h" +#include "infcodes.h" +#include "infutil.h" +#include "inffast.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + +/* macros for bit input with no checking and for returning unused bytes */ +#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<avail_in-n;c=(k>>3)>3:c;n+=c;p-=c;k-=c<<3;} + +/* Called with number of bytes left to write in window at least 258 + (the maximum string length) and number of input bytes available + at least ten. The ten bytes are six bytes for the longest length/ + distance pair plus four bytes for overloading the bit buffer. */ + +int inflate_fast(bl, bd, tl, td, s, z) +uInt bl, bd; +inflate_huft *tl; +inflate_huft *td; /* need separate declaration for Borland C++ */ +inflate_blocks_statef *s; +z_streamp z; +{ + inflate_huft *t; /* temporary pointer */ + uInt e; /* extra bits or operation */ + uLong b; /* bit buffer */ + uInt k; /* bits in bit buffer */ + Bytef *p; /* input data pointer */ + uInt n; /* bytes available there */ + Bytef *q; /* output window write pointer */ + uInt m; /* bytes to end of window or read pointer */ + uInt ml; /* mask for literal/length tree */ + uInt md; /* mask for distance tree */ + uInt c; /* bytes to copy */ + uInt d; /* distance back to copy from */ + Bytef *r; /* copy source pointer */ + + /* load input, output, bit values */ + LOAD + + /* initialize masks */ + ml = inflate_mask[bl]; + md = inflate_mask[bd]; + + /* do until not enough input or output space for fast loop */ + do { /* assume called with m >= 258 && n >= 10 */ + /* get literal/length code */ + GRABBITS(20) /* max bits for literal/length code */ + if ((e = (t = tl + ((uInt)b & ml))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + continue; + } + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits for length */ + e &= 15; + c = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * length %u\n", c)); + + /* decode distance base of block to copy */ + GRABBITS(15); /* max bits for distance code */ + e = (t = td + ((uInt)b & md))->exop; + do { + DUMPBITS(t->bits) + if (e & 16) + { + /* get extra bits to add to distance base */ + e &= 15; + GRABBITS(e) /* get extra bits (up to 13) */ + d = t->base + ((uInt)b & inflate_mask[e]); + DUMPBITS(e) + Tracevv((stderr, "inflate: * distance %u\n", d)); + + /* do the copy */ + m -= c; + r = q - d; + if (r < s->window) /* wrap if needed */ + { + do { + r += s->end - s->window; /* force pointer in window */ + } while (r < s->window); /* covers invalid distances */ + e = s->end - r; + if (c > e) + { + c -= e; /* wrapped copy */ + do { + *q++ = *r++; + } while (--e); + r = s->window; + do { + *q++ = *r++; + } while (--c); + } + else /* normal copy */ + { + *q++ = *r++; c--; + *q++ = *r++; c--; + do { + *q++ = *r++; + } while (--c); + } + } + else /* normal copy */ + { + *q++ = *r++; c--; + *q++ = *r++; c--; + do { + *q++ = *r++; + } while (--c); + } + break; + } + else if ((e & 64) == 0) + { + t += t->base; + e = (t += ((uInt)b & inflate_mask[e]))->exop; + } + else + { + z->msg = (char*)"invalid distance code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + break; + } + if ((e & 64) == 0) + { + t += t->base; + if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0) + { + DUMPBITS(t->bits) + Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ? + "inflate: * literal '%c'\n" : + "inflate: * literal 0x%02x\n", t->base)); + *q++ = (Byte)t->base; + m--; + break; + } + } + else if (e & 32) + { + Tracevv((stderr, "inflate: * end of block\n")); + UNGRAB + UPDATE + return Z_STREAM_END; + } + else + { + z->msg = (char*)"invalid literal/length code"; + UNGRAB + UPDATE + return Z_DATA_ERROR; + } + } while (1); + } while (m >= 258 && n >= 10); + + /* not enough input or output--restore pointers and return */ + UNGRAB + UPDATE + return Z_OK; +} diff --git a/src/zlib/inffast.h b/src/zlib/inffast.h new file mode 100644 index 0000000..a31a4bb --- /dev/null +++ b/src/zlib/inffast.h @@ -0,0 +1,17 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +extern int inflate_fast OF(( + uInt, + uInt, + inflate_huft *, + inflate_huft *, + inflate_blocks_statef *, + z_streamp )); diff --git a/src/zlib/inffixed.h b/src/zlib/inffixed.h new file mode 100644 index 0000000..77f7e76 --- /dev/null +++ b/src/zlib/inffixed.h @@ -0,0 +1,151 @@ +/* inffixed.h -- table for decoding fixed codes + * Generated automatically by the maketree.c program + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +local uInt fixed_bl = 9; +local uInt fixed_bd = 5; +local inflate_huft fixed_tl[] = { + {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, + {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192}, + {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160}, + {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224}, + {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144}, + {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208}, + {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176}, + {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240}, + {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, + {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200}, + {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168}, + {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232}, + {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152}, + {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216}, + {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184}, + {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248}, + {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, + {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196}, + {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164}, + {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228}, + {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148}, + {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212}, + {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180}, + {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244}, + {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204}, + {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172}, + {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236}, + {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156}, + {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220}, + {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188}, + {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252}, + {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, + {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194}, + {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162}, + {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226}, + {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146}, + {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210}, + {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178}, + {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242}, + {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, + {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202}, + {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170}, + {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234}, + {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154}, + {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218}, + {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186}, + {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250}, + {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, + {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198}, + {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166}, + {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230}, + {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150}, + {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214}, + {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182}, + {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246}, + {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206}, + {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174}, + {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238}, + {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158}, + {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222}, + {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190}, + {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254}, + {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115}, + {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193}, + {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161}, + {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225}, + {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145}, + {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209}, + {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177}, + {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241}, + {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227}, + {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201}, + {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169}, + {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233}, + {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153}, + {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217}, + {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185}, + {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249}, + {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163}, + {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197}, + {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165}, + {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229}, + {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149}, + {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213}, + {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181}, + {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245}, + {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205}, + {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173}, + {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237}, + {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157}, + {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221}, + {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189}, + {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253}, + {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131}, + {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195}, + {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163}, + {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227}, + {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147}, + {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211}, + {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179}, + {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243}, + {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258}, + {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203}, + {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171}, + {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235}, + {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155}, + {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219}, + {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187}, + {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251}, + {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195}, + {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199}, + {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167}, + {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231}, + {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151}, + {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215}, + {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183}, + {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247}, + {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0}, + {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207}, + {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175}, + {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239}, + {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159}, + {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223}, + {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191}, + {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255} + }; +local inflate_huft fixed_td[] = { + {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097}, + {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385}, + {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193}, + {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577}, + {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145}, + {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577}, + {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289}, + {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577} + }; diff --git a/src/zlib/inflate.c b/src/zlib/inflate.c new file mode 100644 index 0000000..dfb2e86 --- /dev/null +++ b/src/zlib/inflate.c @@ -0,0 +1,366 @@ +/* inflate.c -- zlib interface to inflate modules + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" + +struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ + +typedef enum { + METHOD, /* waiting for method byte */ + FLAG, /* waiting for flag byte */ + DICT4, /* four dictionary check bytes to go */ + DICT3, /* three dictionary check bytes to go */ + DICT2, /* two dictionary check bytes to go */ + DICT1, /* one dictionary check byte to go */ + DICT0, /* waiting for inflateSetDictionary */ + BLOCKS, /* decompressing blocks */ + CHECK4, /* four check bytes to go */ + CHECK3, /* three check bytes to go */ + CHECK2, /* two check bytes to go */ + CHECK1, /* one check byte to go */ + DONE, /* finished check, done */ + BAD} /* got an error--stay here */ +inflate_mode; + +/* inflate private state */ +struct internal_state { + + /* mode */ + inflate_mode mode; /* current inflate mode */ + + /* mode dependent information */ + union { + uInt method; /* if FLAGS, method byte */ + struct { + uLong was; /* computed check value */ + uLong need; /* stream check value */ + } check; /* if CHECK, check values to compare */ + uInt marker; /* if BAD, inflateSync's marker bytes count */ + } sub; /* submode */ + + /* mode independent information */ + int nowrap; /* flag for no wrapper */ + uInt wbits; /* log2(window size) (8..15, defaults to 15) */ + inflate_blocks_statef + *blocks; /* current inflate_blocks state */ + +}; + + +int ZEXPORT inflateReset(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + z->total_in = z->total_out = 0; + z->msg = Z_NULL; + z->state->mode = z->state->nowrap ? BLOCKS : METHOD; + inflate_blocks_reset(z->state->blocks, z, Z_NULL); + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + + +int ZEXPORT inflateEnd(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->blocks != Z_NULL) + inflate_blocks_free(z->state->blocks, z); + ZFREE(z, z->state); + z->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + + +int ZEXPORT inflateInit2_(z, w, version, stream_size) +z_streamp z; +int w; +const char *version; +int stream_size; +{ + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != sizeof(z_stream)) + return Z_VERSION_ERROR; + + /* initialize state */ + if (z == Z_NULL) + return Z_STREAM_ERROR; + z->msg = Z_NULL; + if (z->zalloc == Z_NULL) + { + z->zalloc = zcalloc; + z->opaque = (voidpf)0; + } + if (z->zfree == Z_NULL) z->zfree = zcfree; + if ((z->state = (struct internal_state FAR *) + ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) + return Z_MEM_ERROR; + z->state->blocks = Z_NULL; + + /* handle undocumented nowrap option (no zlib header or check) */ + z->state->nowrap = 0; + if (w < 0) + { + w = - w; + z->state->nowrap = 1; + } + + /* set window size */ + if (w < 8 || w > 15) + { + inflateEnd(z); + return Z_STREAM_ERROR; + } + z->state->wbits = (uInt)w; + + /* create inflate_blocks state */ + if ((z->state->blocks = + inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w)) + == Z_NULL) + { + inflateEnd(z); + return Z_MEM_ERROR; + } + Tracev((stderr, "inflate: allocated\n")); + + /* reset state */ + inflateReset(z); + return Z_OK; +} + + +int ZEXPORT inflateInit_(z, version, stream_size) +z_streamp z; +const char *version; +int stream_size; +{ + return inflateInit2_(z, DEF_WBITS, version, stream_size); +} + + +#define NEEDBYTE {if(z->avail_in==0)return r;r=f;} +#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) + +int ZEXPORT inflate(z, f) +z_streamp z; +int f; +{ + int r; + uInt b; + + if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL) + return Z_STREAM_ERROR; + f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; + r = Z_BUF_ERROR; + while (1) switch (z->state->mode) + { + case METHOD: + NEEDBYTE + if (((z->state->sub.method = NEXTBYTE) & 0xf) != Z_DEFLATED) + { + z->state->mode = BAD; + z->msg = (char*)"unknown compression method"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + if ((z->state->sub.method >> 4) + 8 > z->state->wbits) + { + z->state->mode = BAD; + z->msg = (char*)"invalid window size"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + z->state->mode = FLAG; + case FLAG: + NEEDBYTE + b = NEXTBYTE; + if (((z->state->sub.method << 8) + b) % 31) + { + z->state->mode = BAD; + z->msg = (char*)"incorrect header check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Tracev((stderr, "inflate: zlib header ok\n")); + if (!(b & PRESET_DICT)) + { + z->state->mode = BLOCKS; + break; + } + z->state->mode = DICT4; + case DICT4: + NEEDBYTE + z->state->sub.check.need = (uLong)NEXTBYTE << 24; + z->state->mode = DICT3; + case DICT3: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 16; + z->state->mode = DICT2; + case DICT2: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 8; + z->state->mode = DICT1; + case DICT1: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE; + z->adler = z->state->sub.check.need; + z->state->mode = DICT0; + return Z_NEED_DICT; + case DICT0: + z->state->mode = BAD; + z->msg = (char*)"need dictionary"; + z->state->sub.marker = 0; /* can try inflateSync */ + return Z_STREAM_ERROR; + case BLOCKS: + r = inflate_blocks(z->state->blocks, z, r); + if (r == Z_DATA_ERROR) + { + z->state->mode = BAD; + z->state->sub.marker = 0; /* can try inflateSync */ + break; + } + if (r == Z_OK) + r = f; + if (r != Z_STREAM_END) + return r; + r = f; + inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was); + if (z->state->nowrap) + { + z->state->mode = DONE; + break; + } + z->state->mode = CHECK4; + case CHECK4: + NEEDBYTE + z->state->sub.check.need = (uLong)NEXTBYTE << 24; + z->state->mode = CHECK3; + case CHECK3: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 16; + z->state->mode = CHECK2; + case CHECK2: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE << 8; + z->state->mode = CHECK1; + case CHECK1: + NEEDBYTE + z->state->sub.check.need += (uLong)NEXTBYTE; + + if (z->state->sub.check.was != z->state->sub.check.need) + { + z->state->mode = BAD; + z->msg = (char*)"incorrect data check"; + z->state->sub.marker = 5; /* can't try inflateSync */ + break; + } + Tracev((stderr, "inflate: zlib check ok\n")); + z->state->mode = DONE; + case DONE: + return Z_STREAM_END; + case BAD: + return Z_DATA_ERROR; + default: + return Z_STREAM_ERROR; + } +#ifdef NEED_DUMMY_RETURN + return Z_STREAM_ERROR; /* Some dumb compilers complain without this */ +#endif +} + + +int ZEXPORT inflateSetDictionary(z, dictionary, dictLength) +z_streamp z; +const Bytef *dictionary; +uInt dictLength; +{ + uInt length = dictLength; + + if (z == Z_NULL || z->state == Z_NULL || z->state->mode != DICT0) + return Z_STREAM_ERROR; + + if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR; + z->adler = 1L; + + if (length >= ((uInt)1<state->wbits)) + { + length = (1<state->wbits)-1; + dictionary += dictLength - length; + } + inflate_set_dictionary(z->state->blocks, dictionary, length); + z->state->mode = BLOCKS; + return Z_OK; +} + + +int ZEXPORT inflateSync(z) +z_streamp z; +{ + uInt n; /* number of bytes to look at */ + Bytef *p; /* pointer to bytes */ + uInt m; /* number of marker bytes found in a row */ + uLong r, w; /* temporaries to save total_in and total_out */ + + /* set up */ + if (z == Z_NULL || z->state == Z_NULL) + return Z_STREAM_ERROR; + if (z->state->mode != BAD) + { + z->state->mode = BAD; + z->state->sub.marker = 0; + } + if ((n = z->avail_in) == 0) + return Z_BUF_ERROR; + p = z->next_in; + m = z->state->sub.marker; + + /* search */ + while (n && m < 4) + { + static const Byte mark[4] = {0, 0, 0xff, 0xff}; + if (*p == mark[m]) + m++; + else if (*p) + m = 0; + else + m = 4 - m; + p++, n--; + } + + /* restore */ + z->total_in += p - z->next_in; + z->next_in = p; + z->avail_in = n; + z->state->sub.marker = m; + + /* return no joy or set up to restart on a new block */ + if (m != 4) + return Z_DATA_ERROR; + r = z->total_in; w = z->total_out; + inflateReset(z); + z->total_in = r; z->total_out = w; + z->state->mode = BLOCKS; + return Z_OK; +} + + +/* Returns true if inflate is currently at the end of a block generated + * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH + * but removes the length bytes of the resulting empty stored block. When + * decompressing, PPP checks that at the end of input packet, inflate is + * waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(z) +z_streamp z; +{ + if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL) + return Z_STREAM_ERROR; + return inflate_blocks_sync_point(z->state->blocks); +} diff --git a/src/zlib/inftrees.c b/src/zlib/inftrees.c new file mode 100644 index 0000000..4c32ca3 --- /dev/null +++ b/src/zlib/inftrees.c @@ -0,0 +1,454 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#if !defined(BUILDFIXED) && !defined(STDC) +# define BUILDFIXED /* non ANSI compilers may not accept inffixed.h */ +#endif + +const char inflate_copyright[] = + " inflate 1.1.4 Copyright 1995-2002 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ +struct internal_state {int dummy;}; /* for buggy compilers */ + +/* simplify the use of the inflate_huft type with some defines */ +#define exop word.what.Exop +#define bits word.what.Bits + + +local int huft_build OF(( + uIntf *, /* code lengths in bits */ + uInt, /* number of codes */ + uInt, /* number of "simple" codes */ + const uIntf *, /* list of base values for non-simple codes */ + const uIntf *, /* list of extra bits for non-simple codes */ + inflate_huft * FAR*,/* result: starting table */ + uIntf *, /* maximum lookup bits (returns actual) */ + inflate_huft *, /* space for trees */ + uInt *, /* hufts used in space */ + uIntf * )); /* space for values */ + +/* Tables for deflate from PKZIP's appnote.txt. */ +local const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + /* see note #13 above about 258 */ +local const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */ +local const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577}; +local const uInt cpdext[30] = { /* Extra bits for distance codes */ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, + 12, 12, 13, 13}; + +/* + Huffman code decoding is performed using a multi-level table lookup. + The fastest way to decode is to simply build a lookup table whose + size is determined by the longest code. However, the time it takes + to build this table can also be a factor if the data being decoded + is not very long. The most common codes are necessarily the + shortest codes, so those codes dominate the decoding time, and hence + the speed. The idea is you can have a shorter table that decodes the + shorter, more probable codes, and then point to subsidiary tables for + the longer codes. The time it costs to decode the longer codes is + then traded against the time it takes to make longer tables. + + This results of this trade are in the variables lbits and dbits + below. lbits is the number of bits the first level table for literal/ + length codes can decode in one step, and dbits is the same thing for + the distance codes. Subsequent tables are also less than or equal to + those sizes. These values may be adjusted either when all of the + codes are shorter than that, in which case the longest code length in + bits is used, or when the shortest code is *longer* than the requested + table size, in which case the length of the shortest code in bits is + used. + + There are two different values for the two tables, since they code a + different number of possibilities each. The literal/length table + codes 286 possible values, or in a flat code, a little over eight + bits. The distance table codes 30 possible values, or a little less + than five bits, flat. The optimum values for speed end up being + about one bit more than those, so lbits is 8+1 and dbits is 5+1. + The optimum values may differ though from machine to machine, and + possibly even between compilers. Your mileage may vary. + */ + + +/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */ +#define BMAX 15 /* maximum bit length of any code */ + +local int huft_build(b, n, s, d, e, t, m, hp, hn, v) +uIntf *b; /* code lengths in bits (all assumed <= BMAX) */ +uInt n; /* number of codes (assumed <= 288) */ +uInt s; /* number of simple-valued codes (0..s-1) */ +const uIntf *d; /* list of base values for non-simple codes */ +const uIntf *e; /* list of extra bits for non-simple codes */ +inflate_huft * FAR *t; /* result: starting table */ +uIntf *m; /* maximum lookup bits, returns actual */ +inflate_huft *hp; /* space for trees */ +uInt *hn; /* hufts used in space */ +uIntf *v; /* working area: values in order of bit length */ +/* Given a list of code lengths and a maximum table size, make a set of + tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR + if the given code set is incomplete (the tables are still built in this + case), or Z_DATA_ERROR if the input is invalid. */ +{ + + uInt a; /* counter for codes of length k */ + uInt c[BMAX+1]; /* bit length count table */ + uInt f; /* i repeats in table every f entries */ + int g; /* maximum code length */ + int h; /* table level */ + register uInt i; /* counter, current code */ + register uInt j; /* counter */ + register int k; /* number of bits in current code */ + int l; /* bits per table (returned in m) */ + uInt mask; /* (1 << w) - 1, to avoid cc -O bug on HP */ + register uIntf *p; /* pointer into c[], b[], or v[] */ + inflate_huft *q; /* points to current table */ + struct inflate_huft_s r; /* table entry for structure assignment */ + inflate_huft *u[BMAX]; /* table stack */ + register int w; /* bits before this table == (l * h) */ + uInt x[BMAX+1]; /* bit offsets, then code stack */ + uIntf *xp; /* pointer into x */ + int y; /* number of dummy codes added */ + uInt z; /* number of entries in current table */ + + + /* Generate counts for each bit length */ + p = c; +#define C0 *p++ = 0; +#define C2 C0 C0 C0 C0 +#define C4 C2 C2 C2 C2 + C4 /* clear c[]--assume BMAX+1 is 16 */ + p = b; i = n; + do { + c[*p++]++; /* assume all entries <= BMAX */ + } while (--i); + if (c[0] == n) /* null input--all zero length codes */ + { + *t = (inflate_huft *)Z_NULL; + *m = 0; + return Z_OK; + } + + + /* Find minimum and maximum length, bound *m by those */ + l = *m; + for (j = 1; j <= BMAX; j++) + if (c[j]) + break; + k = j; /* minimum code length */ + if ((uInt)l < j) + l = j; + for (i = BMAX; i; i--) + if (c[i]) + break; + g = i; /* maximum code length */ + if ((uInt)l > i) + l = i; + *m = l; + + + /* Adjust last length count to fill out codes, if needed */ + for (y = 1 << j; j < i; j++, y <<= 1) + if ((y -= c[j]) < 0) + return Z_DATA_ERROR; + if ((y -= c[i]) < 0) + return Z_DATA_ERROR; + c[i] += y; + + + /* Generate starting offsets into the value table for each length */ + x[1] = j = 0; + p = c + 1; xp = x + 2; + while (--i) { /* note that i == g from above */ + *xp++ = (j += *p++); + } + + + /* Make a table of values in order of bit lengths */ + p = b; i = 0; + do { + if ((j = *p++) != 0) + v[x[j]++] = i; + } while (++i < n); + n = x[g]; /* set n to length of v */ + + + /* Generate the Huffman codes and for each, make the table entries */ + x[0] = i = 0; /* first Huffman code is zero */ + p = v; /* grab values in bit order */ + h = -1; /* no tables yet--level -1 */ + w = -l; /* bits decoded == (l * h) */ + u[0] = (inflate_huft *)Z_NULL; /* just to keep compilers happy */ + q = (inflate_huft *)Z_NULL; /* ditto */ + z = 0; /* ditto */ + + /* go through the bit lengths (k already is bits in shortest code) */ + for (; k <= g; k++) + { + a = c[k]; + while (a--) + { + /* here i is the Huffman code of length k bits for value *p */ + /* make tables up to required level */ + while (k > w + l) + { + h++; + w += l; /* previous table always l bits */ + + /* compute minimum size table less than or equal to l bits */ + z = g - w; + z = z > (uInt)l ? l : z; /* table size upper limit */ + if ((f = 1 << (j = k - w)) > a + 1) /* try a k-w bit table */ + { /* too few codes for k-w bit table */ + f -= a + 1; /* deduct codes from patterns left */ + xp = c + k; + if (j < z) + while (++j < z) /* try smaller tables up to z bits */ + { + if ((f <<= 1) <= *++xp) + break; /* enough codes to use up j bits */ + f -= *xp; /* else deduct codes from patterns */ + } + } + z = 1 << j; /* table entries for j-bit table */ + + /* allocate new table */ + if (*hn + z > MANY) /* (note: doesn't matter for fixed) */ + return Z_DATA_ERROR; /* overflow of MANY */ + u[h] = q = hp + *hn; + *hn += z; + + /* connect to last table, if there is one */ + if (h) + { + x[h] = i; /* save pattern for backing up */ + r.bits = (Byte)l; /* bits to dump before this table */ + r.exop = (Byte)j; /* bits in this table */ + j = i >> (w - l); + r.base = (uInt)(q - u[h-1] - j); /* offset to this table */ + u[h-1][j] = r; /* connect to last table */ + } + else + *t = q; /* first table is returned result */ + } + + /* set up table entry in r */ + r.bits = (Byte)(k - w); + if (p >= v + n) + r.exop = 128 + 64; /* out of values--invalid code */ + else if (*p < s) + { + r.exop = (Byte)(*p < 256 ? 0 : 32 + 64); /* 256 is end-of-block */ + r.base = *p++; /* simple code is just the value */ + } + else + { + r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */ + r.base = d[*p++ - s]; + } + + /* fill code-like entries with r */ + f = 1 << (k - w); + for (j = i >> w; j < z; j += f) + q[j] = r; + + /* backwards increment the k-bit code i */ + for (j = 1 << (k - 1); i & j; j >>= 1) + i ^= j; + i ^= j; + + /* backup over finished tables */ + mask = (1 << w) - 1; /* needed on HP, cc -O bug */ + while ((i & mask) != x[h]) + { + h--; /* don't need to update q */ + w -= l; + mask = (1 << w) - 1; + } + } + } + + + /* Return Z_BUF_ERROR if we were given an incomplete table */ + return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK; +} + + +int inflate_trees_bits(c, bb, tb, hp, z) +uIntf *c; /* 19 code lengths */ +uIntf *bb; /* bits tree desired/actual depth */ +inflate_huft * FAR *tb; /* bits tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + uIntf *v; /* work area for huft_build */ + + if ((v = (uIntf*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + r = huft_build(c, 19, 19, (uIntf*)Z_NULL, (uIntf*)Z_NULL, + tb, bb, hp, &hn, v); + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed dynamic bit lengths tree"; + else if (r == Z_BUF_ERROR || *bb == 0) + { + z->msg = (char*)"incomplete dynamic bit lengths tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; +} + + +int inflate_trees_dynamic(nl, nd, c, bl, bd, tl, td, hp, z) +uInt nl; /* number of literal/length codes */ +uInt nd; /* number of distance codes */ +uIntf *c; /* that many (total) code lengths */ +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +inflate_huft *hp; /* space for trees */ +z_streamp z; /* for messages */ +{ + int r; + uInt hn = 0; /* hufts used in space */ + uIntf *v; /* work area for huft_build */ + + /* allocate work area */ + if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + + /* build literal/length tree */ + r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v); + if (r != Z_OK || *bl == 0) + { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed literal/length tree"; + else if (r != Z_MEM_ERROR) + { + z->msg = (char*)"incomplete literal/length tree"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; + } + + /* build distance tree */ + r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v); + if (r != Z_OK || (*bd == 0 && nl > 257)) + { + if (r == Z_DATA_ERROR) + z->msg = (char*)"oversubscribed distance tree"; + else if (r == Z_BUF_ERROR) { +#ifdef PKZIP_BUG_WORKAROUND + r = Z_OK; + } +#else + z->msg = (char*)"incomplete distance tree"; + r = Z_DATA_ERROR; + } + else if (r != Z_MEM_ERROR) + { + z->msg = (char*)"empty distance tree with lengths"; + r = Z_DATA_ERROR; + } + ZFREE(z, v); + return r; +#endif + } + + /* done */ + ZFREE(z, v); + return Z_OK; +} + + +/* build fixed tables only once--keep them here */ +#ifdef BUILDFIXED +local int fixed_built = 0; +#define FIXEDH 544 /* number of hufts used by fixed tables */ +local inflate_huft fixed_mem[FIXEDH]; +local uInt fixed_bl; +local uInt fixed_bd; +local inflate_huft *fixed_tl; +local inflate_huft *fixed_td; +#else +#include "inffixed.h" +#endif + + +int inflate_trees_fixed(bl, bd, tl, td, z) +uIntf *bl; /* literal desired/actual bit depth */ +uIntf *bd; /* distance desired/actual bit depth */ +inflate_huft * FAR *tl; /* literal/length tree result */ +inflate_huft * FAR *td; /* distance tree result */ +z_streamp z; /* for memory allocation */ +{ +#ifdef BUILDFIXED + /* build fixed tables if not already */ + if (!fixed_built) + { + int k; /* temporary variable */ + uInt f = 0; /* number of hufts used in fixed_mem */ + uIntf *c; /* length list for huft_build */ + uIntf *v; /* work area for huft_build */ + + /* allocate memory */ + if ((c = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + return Z_MEM_ERROR; + if ((v = (uIntf*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL) + { + ZFREE(z, c); + return Z_MEM_ERROR; + } + + /* literal table */ + for (k = 0; k < 144; k++) + c[k] = 8; + for (; k < 256; k++) + c[k] = 9; + for (; k < 280; k++) + c[k] = 7; + for (; k < 288; k++) + c[k] = 8; + fixed_bl = 9; + huft_build(c, 288, 257, cplens, cplext, &fixed_tl, &fixed_bl, + fixed_mem, &f, v); + + /* distance table */ + for (k = 0; k < 30; k++) + c[k] = 5; + fixed_bd = 5; + huft_build(c, 30, 0, cpdist, cpdext, &fixed_td, &fixed_bd, + fixed_mem, &f, v); + + /* done */ + ZFREE(z, v); + ZFREE(z, c); + fixed_built = 1; + } +#endif + *bl = fixed_bl; + *bd = fixed_bd; + *tl = fixed_tl; + *td = fixed_td; + return Z_OK; +} diff --git a/src/zlib/inftrees.h b/src/zlib/inftrees.h new file mode 100644 index 0000000..04b73b7 --- /dev/null +++ b/src/zlib/inftrees.h @@ -0,0 +1,58 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Huffman code lookup table entry--this entry is four bytes for machines + that have 16-bit pointers (e.g. PC's in the small or medium model). */ + +typedef struct inflate_huft_s FAR inflate_huft; + +struct inflate_huft_s { + union { + struct { + Byte Exop; /* number of extra bits or operation */ + Byte Bits; /* number of bits in this code or subcode */ + } what; + uInt pad; /* pad structure to a power of 2 (4 bytes for */ + } word; /* 16-bit, 8 bytes for 32-bit int's) */ + uInt base; /* literal, length base, distance base, + or table offset */ +}; + +/* Maximum size of dynamic tree. The maximum found in a long but non- + exhaustive search was 1004 huft structures (850 for length/literals + and 154 for distances, the latter actually the result of an + exhaustive search). The actual maximum is not known, but the + value below is more than safe. */ +#define MANY 1440 + +extern int inflate_trees_bits OF(( + uIntf *, /* 19 code lengths */ + uIntf *, /* bits tree desired/actual depth */ + inflate_huft * FAR *, /* bits tree result */ + inflate_huft *, /* space for trees */ + z_streamp)); /* for messages */ + +extern int inflate_trees_dynamic OF(( + uInt, /* number of literal/length codes */ + uInt, /* number of distance codes */ + uIntf *, /* that many (total) code lengths */ + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *, /* distance tree result */ + inflate_huft *, /* space for trees */ + z_streamp)); /* for messages */ + +extern int inflate_trees_fixed OF(( + uIntf *, /* literal desired/actual bit depth */ + uIntf *, /* distance desired/actual bit depth */ + inflate_huft * FAR *, /* literal/length tree result */ + inflate_huft * FAR *, /* distance tree result */ + z_streamp)); /* for memory allocation */ diff --git a/src/zlib/infutil.c b/src/zlib/infutil.c new file mode 100644 index 0000000..9a07622 --- /dev/null +++ b/src/zlib/infutil.c @@ -0,0 +1,87 @@ +/* inflate_util.c -- data and routines common to blocks and codes + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "infblock.h" +#include "inftrees.h" +#include "infcodes.h" +#include "infutil.h" + +struct inflate_codes_state {int dummy;}; /* for buggy compilers */ + +/* And'ing with mask[n] masks the lower n bits */ +uInt inflate_mask[17] = { + 0x0000, + 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, + 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff +}; + + +/* copy as much as possible from the sliding window to the output area */ +int inflate_flush(s, z, r) +inflate_blocks_statef *s; +z_streamp z; +int r; +{ + uInt n; + Bytef *p; + Bytef *q; + + /* local copies of source and destination pointers */ + p = z->next_out; + q = s->read; + + /* compute number of bytes to copy as far as end of window */ + n = (uInt)((q <= s->write ? s->write : s->end) - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy as far as end of window */ + zmemcpy(p, q, n); + p += n; + q += n; + + /* see if more to copy at beginning of window */ + if (q == s->end) + { + /* wrap pointers */ + q = s->window; + if (s->write == s->end) + s->write = s->window; + + /* compute bytes to copy */ + n = (uInt)(s->write - q); + if (n > z->avail_out) n = z->avail_out; + if (n && r == Z_BUF_ERROR) r = Z_OK; + + /* update counters */ + z->avail_out -= n; + z->total_out += n; + + /* update check information */ + if (s->checkfn != Z_NULL) + z->adler = s->check = (*s->checkfn)(s->check, q, n); + + /* copy */ + zmemcpy(p, q, n); + p += n; + q += n; + } + + /* update pointers */ + z->next_out = p; + s->read = q; + + /* done */ + return r; +} diff --git a/src/zlib/infutil.h b/src/zlib/infutil.h new file mode 100644 index 0000000..4401df8 --- /dev/null +++ b/src/zlib/infutil.h @@ -0,0 +1,98 @@ +/* infutil.h -- types and macros common to blocks and codes + * Copyright (C) 1995-2002 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +#ifndef _INFUTIL_H +#define _INFUTIL_H + +typedef enum { + TYPE, /* get type bits (3, including end bit) */ + LENS, /* get lengths for stored */ + STORED, /* processing stored block */ + TABLE, /* get table lengths */ + BTREE, /* get bit lengths tree for a dynamic block */ + DTREE, /* get length, distance trees for a dynamic block */ + CODES, /* processing fixed or dynamic block */ + DRY, /* output remaining window bytes */ + DONE, /* finished last block, done */ + BAD} /* got a data error--stuck here */ +inflate_block_mode; + +/* inflate blocks semi-private state */ +struct inflate_blocks_state { + + /* mode */ + inflate_block_mode mode; /* current inflate_block mode */ + + /* mode dependent information */ + union { + uInt left; /* if STORED, bytes left to copy */ + struct { + uInt table; /* table lengths (14 bits) */ + uInt index; /* index into blens (or border) */ + uIntf *blens; /* bit lengths of codes */ + uInt bb; /* bit length tree depth */ + inflate_huft *tb; /* bit length decoding tree */ + } trees; /* if DTREE, decoding info for trees */ + struct { + inflate_codes_statef + *codes; + } decode; /* if CODES, current state */ + } sub; /* submode */ + uInt last; /* true if this block is the last block */ + + /* mode independent information */ + uInt bitk; /* bits in bit buffer */ + uLong bitb; /* bit buffer */ + inflate_huft *hufts; /* single malloc for tree space */ + Bytef *window; /* sliding window */ + Bytef *end; /* one byte after sliding window */ + Bytef *read; /* window read pointer */ + Bytef *write; /* window write pointer */ + check_func checkfn; /* check function */ + uLong check; /* check on output */ + +}; + + +/* defines for inflate input/output */ +/* update pointers and return */ +#define UPDBITS {s->bitb=b;s->bitk=k;} +#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;} +#define UPDOUT {s->write=q;} +#define UPDATE {UPDBITS UPDIN UPDOUT} +#define LEAVE {UPDATE return inflate_flush(s,z,r);} +/* get bytes and bits */ +#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;} +#define NEEDBYTE {if(n)r=Z_OK;else LEAVE} +#define NEXTBYTE (n--,*p++) +#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<>=(j);k-=(j);} +/* output bytes */ +#define WAVAIL (uInt)(qread?s->read-q-1:s->end-q) +#define LOADOUT {q=s->write;m=(uInt)WAVAIL;} +#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}} +#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT} +#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;} +#define OUTBYTE(a) {*q++=(Byte)(a);m--;} +/* load local pointers */ +#define LOAD {LOADIN LOADOUT} + +/* masks for lower bits (size given to avoid silly warnings with Visual C++) */ +extern uInt inflate_mask[17]; + +/* copy as much as possible from the sliding window to the output area */ +extern int inflate_flush OF(( + inflate_blocks_statef *, + z_streamp , + int)); + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#endif diff --git a/src/zlib/trees.c b/src/zlib/trees.c new file mode 100644 index 0000000..c98b000 --- /dev/null +++ b/src/zlib/trees.c @@ -0,0 +1,1214 @@ +/* trees.c -- output deflated data using Huffman coding + * Copyright (C) 1995-2002 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * ALGORITHM + * + * The "deflation" process uses several Huffman trees. The more + * common source values are represented by shorter bit sequences. + * + * Each code tree is stored in a compressed form which is itself + * a Huffman encoding of the lengths of all the code strings (in + * ascending order by source values). The actual code strings are + * reconstructed from the lengths in the inflate process, as described + * in the deflate specification. + * + * REFERENCES + * + * Deutsch, L.P.,"'Deflate' Compressed Data Format Specification". + * Available in ftp.uu.net:/pub/archiving/zip/doc/deflate-1.1.doc + * + * Storer, James A. + * Data Compression: Methods and Theory, pp. 49-50. + * Computer Science Press, 1988. ISBN 0-7167-8156-5. + * + * Sedgewick, R. + * Algorithms, p290. + * Addison-Wesley, 1983. ISBN 0-201-06672-6. + */ + +/* @(#) $Id: trees.c,v 1.2 2002/03/13 17:45:56 xodnizel Exp $ */ + +/* #define GEN_TREES_H */ + +#include "deflate.h" + +#ifdef DEBUG +# include +#endif + +/* =========================================================================== + * Constants + */ + +#define MAX_BL_BITS 7 +/* Bit length codes must not exceed MAX_BL_BITS bits */ + +#define END_BLOCK 256 +/* end of block literal code */ + +#define REP_3_6 16 +/* repeat previous bit length 3-6 times (2 bits of repeat count) */ + +#define REPZ_3_10 17 +/* repeat a zero length 3-10 times (3 bits of repeat count) */ + +#define REPZ_11_138 18 +/* repeat a zero length 11-138 times (7 bits of repeat count) */ + +local const int extra_lbits[LENGTH_CODES] /* extra bits for each length code */ + = {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0}; + +local const int extra_dbits[D_CODES] /* extra bits for each distance code */ + = {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; + +local const int extra_blbits[BL_CODES]/* extra bits for each bit length code */ + = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7}; + +local const uch bl_order[BL_CODES] + = {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15}; +/* The lengths of the bit length codes are sent in order of decreasing + * probability, to avoid transmitting the lengths for unused bit length codes. + */ + +#define Buf_size (8 * 2*sizeof(char)) +/* Number of bits used within bi_buf. (bi_buf might be implemented on + * more than 16 bits on some systems.) + */ + +/* =========================================================================== + * Local data. These are initialized only once. + */ + +#define DIST_CODE_LEN 512 /* see definition of array dist_code below */ + +#if defined(GEN_TREES_H) || !defined(STDC) +/* non ANSI compilers may not accept trees.h */ + +local ct_data static_ltree[L_CODES+2]; +/* The static literal tree. Since the bit lengths are imposed, there is no + * need for the L_CODES extra codes used during heap construction. However + * The codes 286 and 287 are needed to build a canonical tree (see _tr_init + * below). + */ + +local ct_data static_dtree[D_CODES]; +/* The static distance tree. (Actually a trivial tree since all codes use + * 5 bits.) + */ + +uch _dist_code[DIST_CODE_LEN]; +/* Distance codes. The first 256 values correspond to the distances + * 3 .. 258, the last 256 values correspond to the top 8 bits of + * the 15 bit distances. + */ + +uch _length_code[MAX_MATCH-MIN_MATCH+1]; +/* length code for each normalized match length (0 == MIN_MATCH) */ + +local int base_length[LENGTH_CODES]; +/* First normalized length for each code (0 = MIN_MATCH) */ + +local int base_dist[D_CODES]; +/* First normalized distance for each code (0 = distance of 1) */ + +#else +# include "trees.h" +#endif /* GEN_TREES_H */ + +struct static_tree_desc_s { + const ct_data *static_tree; /* static tree or NULL */ + const intf *extra_bits; /* extra bits for each code or NULL */ + int extra_base; /* base index for extra_bits */ + int elems; /* max number of elements in the tree */ + int max_length; /* max bit length for the codes */ +}; + +local static_tree_desc static_l_desc = +{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; + +local static_tree_desc static_d_desc = +{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; + +local static_tree_desc static_bl_desc = +{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; + +/* =========================================================================== + * Local (static) routines in this file. + */ + +local void tr_static_init OF((void)); +local void init_block OF((deflate_state *s)); +local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); +local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); +local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); +local void build_tree OF((deflate_state *s, tree_desc *desc)); +local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); +local int build_bl_tree OF((deflate_state *s)); +local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, + int blcodes)); +local void compress_block OF((deflate_state *s, ct_data *ltree, + ct_data *dtree)); +local void set_data_type OF((deflate_state *s)); +local unsigned bi_reverse OF((unsigned value, int length)); +local void bi_windup OF((deflate_state *s)); +local void bi_flush OF((deflate_state *s)); +local void copy_block OF((deflate_state *s, charf *buf, unsigned len, + int header)); + +#ifdef GEN_TREES_H +local void gen_trees_header OF((void)); +#endif + +#ifndef DEBUG +# define send_code(s, c, tree) send_bits(s, tree[c].Code, tree[c].Len) + /* Send a code of the given tree. c and tree must not have side effects */ + +#else /* DEBUG */ +# define send_code(s, c, tree) \ + { if (z_verbose>2) fprintf(stderr,"\ncd %3d ",(c)); \ + send_bits(s, tree[c].Code, tree[c].Len); } +#endif + +/* =========================================================================== + * Output a short LSB first on the stream. + * IN assertion: there is enough room in pendingBuf. + */ +#define put_short(s, w) { \ + put_byte(s, (uch)((w) & 0xff)); \ + put_byte(s, (uch)((ush)(w) >> 8)); \ +} + +/* =========================================================================== + * Send a value on a given number of bits. + * IN assertion: length <= 16 and value fits in length bits. + */ +#ifdef DEBUG +local void send_bits OF((deflate_state *s, int value, int length)); + +local void send_bits(s, value, length) + deflate_state *s; + int value; /* value to send */ + int length; /* number of bits */ +{ + Tracevv((stderr," l %2d v %4x ", length, value)); + Assert(length > 0 && length <= 15, "invalid length"); + s->bits_sent += (ulg)length; + + /* If not enough room in bi_buf, use (valid) bits from bi_buf and + * (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) + * unused bits in value. + */ + if (s->bi_valid > (int)Buf_size - length) { + s->bi_buf |= (value << s->bi_valid); + put_short(s, s->bi_buf); + s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); + s->bi_valid += length - Buf_size; + } else { + s->bi_buf |= value << s->bi_valid; + s->bi_valid += length; + } +} +#else /* !DEBUG */ + +#define send_bits(s, value, length) \ +{ int len = length;\ + if (s->bi_valid > (int)Buf_size - len) {\ + int val = value;\ + s->bi_buf |= (val << s->bi_valid);\ + put_short(s, s->bi_buf);\ + s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ + s->bi_valid += len - Buf_size;\ + } else {\ + s->bi_buf |= (value) << s->bi_valid;\ + s->bi_valid += len;\ + }\ +} +#endif /* DEBUG */ + + +#define MAX(a,b) (a >= b ? a : b) +/* the arguments must not have side effects */ + +/* =========================================================================== + * Initialize the various 'constant' tables. + */ +local void tr_static_init() +{ +#if defined(GEN_TREES_H) || !defined(STDC) + static int static_init_done = 0; + int n; /* iterates over tree elements */ + int bits; /* bit counter */ + int length; /* length value */ + int code; /* code value */ + int dist; /* distance index */ + ush bl_count[MAX_BITS+1]; + /* number of codes at each bit length for an optimal tree */ + + if (static_init_done) return; + + /* For some embedded targets, global variables are not initialized: */ + static_l_desc.static_tree = static_ltree; + static_l_desc.extra_bits = extra_lbits; + static_d_desc.static_tree = static_dtree; + static_d_desc.extra_bits = extra_dbits; + static_bl_desc.extra_bits = extra_blbits; + + /* Initialize the mapping length (0..255) -> length code (0..28) */ + length = 0; + for (code = 0; code < LENGTH_CODES-1; code++) { + base_length[code] = length; + for (n = 0; n < (1< dist code (0..29) */ + dist = 0; + for (code = 0 ; code < 16; code++) { + base_dist[code] = dist; + for (n = 0; n < (1<>= 7; /* from now on, all distances are divided by 128 */ + for ( ; code < D_CODES; code++) { + base_dist[code] = dist << 7; + for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { + _dist_code[256 + dist++] = (uch)code; + } + } + Assert (dist == 256, "tr_static_init: 256+dist != 512"); + + /* Construct the codes of the static literal tree */ + for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; + n = 0; + while (n <= 143) static_ltree[n++].Len = 8, bl_count[8]++; + while (n <= 255) static_ltree[n++].Len = 9, bl_count[9]++; + while (n <= 279) static_ltree[n++].Len = 7, bl_count[7]++; + while (n <= 287) static_ltree[n++].Len = 8, bl_count[8]++; + /* Codes 286 and 287 do not exist, but we must include them in the + * tree construction to get a canonical Huffman tree (longest code + * all ones) + */ + gen_codes((ct_data *)static_ltree, L_CODES+1, bl_count); + + /* The static distance tree is trivial: */ + for (n = 0; n < D_CODES; n++) { + static_dtree[n].Len = 5; + static_dtree[n].Code = bi_reverse((unsigned)n, 5); + } + static_init_done = 1; + +# ifdef GEN_TREES_H + gen_trees_header(); +# endif +#endif /* defined(GEN_TREES_H) || !defined(STDC) */ +} + +/* =========================================================================== + * Genererate the file trees.h describing the static trees. + */ +#ifdef GEN_TREES_H +# ifndef DEBUG +# include +# endif + +# define SEPARATOR(i, last, width) \ + ((i) == (last)? "\n};\n\n" : \ + ((i) % (width) == (width)-1 ? ",\n" : ", ")) + +void gen_trees_header() +{ + FILE *header = fopen("trees.h", "w"); + int i; + + Assert (header != NULL, "Can't open trees.h"); + fprintf(header, + "/* header created automatically with -DGEN_TREES_H */\n\n"); + + fprintf(header, "local const ct_data static_ltree[L_CODES+2] = {\n"); + for (i = 0; i < L_CODES+2; i++) { + fprintf(header, "{{%3u},{%3u}}%s", static_ltree[i].Code, + static_ltree[i].Len, SEPARATOR(i, L_CODES+1, 5)); + } + + fprintf(header, "local const ct_data static_dtree[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "{{%2u},{%2u}}%s", static_dtree[i].Code, + static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); + } + + fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); + for (i = 0; i < DIST_CODE_LEN; i++) { + fprintf(header, "%2u%s", _dist_code[i], + SEPARATOR(i, DIST_CODE_LEN-1, 20)); + } + + fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); + for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { + fprintf(header, "%2u%s", _length_code[i], + SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); + } + + fprintf(header, "local const int base_length[LENGTH_CODES] = {\n"); + for (i = 0; i < LENGTH_CODES; i++) { + fprintf(header, "%1u%s", base_length[i], + SEPARATOR(i, LENGTH_CODES-1, 20)); + } + + fprintf(header, "local const int base_dist[D_CODES] = {\n"); + for (i = 0; i < D_CODES; i++) { + fprintf(header, "%5u%s", base_dist[i], + SEPARATOR(i, D_CODES-1, 10)); + } + + fclose(header); +} +#endif /* GEN_TREES_H */ + +/* =========================================================================== + * Initialize the tree data structures for a new zlib stream. + */ +void _tr_init(s) + deflate_state *s; +{ + tr_static_init(); + + s->l_desc.dyn_tree = s->dyn_ltree; + s->l_desc.stat_desc = &static_l_desc; + + s->d_desc.dyn_tree = s->dyn_dtree; + s->d_desc.stat_desc = &static_d_desc; + + s->bl_desc.dyn_tree = s->bl_tree; + s->bl_desc.stat_desc = &static_bl_desc; + + s->bi_buf = 0; + s->bi_valid = 0; + s->last_eob_len = 8; /* enough lookahead for inflate */ +#ifdef DEBUG + s->compressed_len = 0L; + s->bits_sent = 0L; +#endif + + /* Initialize the first block of the first file: */ + init_block(s); +} + +/* =========================================================================== + * Initialize a new block. + */ +local void init_block(s) + deflate_state *s; +{ + int n; /* iterates over tree elements */ + + /* Initialize the trees. */ + for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0; + for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0; + for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0; + + s->dyn_ltree[END_BLOCK].Freq = 1; + s->opt_len = s->static_len = 0L; + s->last_lit = s->matches = 0; +} + +#define SMALLEST 1 +/* Index within the heap array of least frequent node in the Huffman tree */ + + +/* =========================================================================== + * Remove the smallest element from the heap and recreate the heap with + * one less element. Updates heap and heap_len. + */ +#define pqremove(s, tree, top) \ +{\ + top = s->heap[SMALLEST]; \ + s->heap[SMALLEST] = s->heap[s->heap_len--]; \ + pqdownheap(s, tree, SMALLEST); \ +} + +/* =========================================================================== + * Compares to subtrees, using the tree depth as tie breaker when + * the subtrees have equal frequency. This minimizes the worst case length. + */ +#define smaller(tree, n, m, depth) \ + (tree[n].Freq < tree[m].Freq || \ + (tree[n].Freq == tree[m].Freq && depth[n] <= depth[m])) + +/* =========================================================================== + * Restore the heap property by moving down the tree starting at node k, + * exchanging a node with the smallest of its two sons if necessary, stopping + * when the heap property is re-established (each father smaller than its + * two sons). + */ +local void pqdownheap(s, tree, k) + deflate_state *s; + ct_data *tree; /* the tree to restore */ + int k; /* node to move down */ +{ + int v = s->heap[k]; + int j = k << 1; /* left son of k */ + while (j <= s->heap_len) { + /* Set j to the smallest of the two sons: */ + if (j < s->heap_len && + smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { + j++; + } + /* Exit if v is smaller than both sons */ + if (smaller(tree, v, s->heap[j], s->depth)) break; + + /* Exchange v with the smallest son */ + s->heap[k] = s->heap[j]; k = j; + + /* And continue down the tree, setting j to the left son of k */ + j <<= 1; + } + s->heap[k] = v; +} + +/* =========================================================================== + * Compute the optimal bit lengths for a tree and update the total bit length + * for the current block. + * IN assertion: the fields freq and dad are set, heap[heap_max] and + * above are the tree nodes sorted by increasing frequency. + * OUT assertions: the field len is set to the optimal bit length, the + * array bl_count contains the frequencies for each bit length. + * The length opt_len is updated; static_len is also updated if stree is + * not null. + */ +local void gen_bitlen(s, desc) + deflate_state *s; + tree_desc *desc; /* the tree descriptor */ +{ + ct_data *tree = desc->dyn_tree; + int max_code = desc->max_code; + const ct_data *stree = desc->stat_desc->static_tree; + const intf *extra = desc->stat_desc->extra_bits; + int base = desc->stat_desc->extra_base; + int max_length = desc->stat_desc->max_length; + int h; /* heap index */ + int n, m; /* iterate over the tree elements */ + int bits; /* bit length */ + int xbits; /* extra bits */ + ush f; /* frequency */ + int overflow = 0; /* number of elements with bit length too large */ + + for (bits = 0; bits <= MAX_BITS; bits++) s->bl_count[bits] = 0; + + /* In a first pass, compute the optimal bit lengths (which may + * overflow in the case of the bit length tree). + */ + tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ + + for (h = s->heap_max+1; h < HEAP_SIZE; h++) { + n = s->heap[h]; + bits = tree[tree[n].Dad].Len + 1; + if (bits > max_length) bits = max_length, overflow++; + tree[n].Len = (ush)bits; + /* We overwrite tree[n].Dad which is no longer needed */ + + if (n > max_code) continue; /* not a leaf node */ + + s->bl_count[bits]++; + xbits = 0; + if (n >= base) xbits = extra[n-base]; + f = tree[n].Freq; + s->opt_len += (ulg)f * (bits + xbits); + if (stree) s->static_len += (ulg)f * (stree[n].Len + xbits); + } + if (overflow == 0) return; + + Trace((stderr,"\nbit length overflow\n")); + /* This happens for example on obj2 and pic of the Calgary corpus */ + + /* Find the first bit length which could increase: */ + do { + bits = max_length-1; + while (s->bl_count[bits] == 0) bits--; + s->bl_count[bits]--; /* move one leaf down the tree */ + s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ + s->bl_count[max_length]--; + /* The brother of the overflow item also moves one step up, + * but this does not affect bl_count[max_length] + */ + overflow -= 2; + } while (overflow > 0); + + /* Now recompute all bit lengths, scanning in increasing frequency. + * h is still equal to HEAP_SIZE. (It is simpler to reconstruct all + * lengths instead of fixing only the wrong ones. This idea is taken + * from 'ar' written by Haruhiko Okumura.) + */ + for (bits = max_length; bits != 0; bits--) { + n = s->bl_count[bits]; + while (n != 0) { + m = s->heap[--h]; + if (m > max_code) continue; + if (tree[m].Len != (unsigned) bits) { + Trace((stderr,"code %d bits %d->%d\n", m, tree[m].Len, bits)); + s->opt_len += ((long)bits - (long)tree[m].Len) + *(long)tree[m].Freq; + tree[m].Len = (ush)bits; + } + n--; + } + } +} + +/* =========================================================================== + * Generate the codes for a given tree and bit counts (which need not be + * optimal). + * IN assertion: the array bl_count contains the bit length statistics for + * the given tree and the field len is set for all tree elements. + * OUT assertion: the field code is set for all tree elements of non + * zero code length. + */ +local void gen_codes (tree, max_code, bl_count) + ct_data *tree; /* the tree to decorate */ + int max_code; /* largest code with non zero frequency */ + ushf *bl_count; /* number of codes at each bit length */ +{ + ush next_code[MAX_BITS+1]; /* next code value for each bit length */ + ush code = 0; /* running code value */ + int bits; /* bit index */ + int n; /* code index */ + + /* The distribution counts are first used to generate the code values + * without bit reversal. + */ + for (bits = 1; bits <= MAX_BITS; bits++) { + next_code[bits] = code = (code + bl_count[bits-1]) << 1; + } + /* Check that the bit counts in bl_count are consistent. The last code + * must be all ones. + */ + Assert (code + bl_count[MAX_BITS]-1 == (1<dyn_tree; + const ct_data *stree = desc->stat_desc->static_tree; + int elems = desc->stat_desc->elems; + int n, m; /* iterate over heap elements */ + int max_code = -1; /* largest code with non zero frequency */ + int node; /* new node being created */ + + /* Construct the initial heap, with least frequent element in + * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. + * heap[0] is not used. + */ + s->heap_len = 0, s->heap_max = HEAP_SIZE; + + for (n = 0; n < elems; n++) { + if (tree[n].Freq != 0) { + s->heap[++(s->heap_len)] = max_code = n; + s->depth[n] = 0; + } else { + tree[n].Len = 0; + } + } + + /* The pkzip format requires that at least one distance code exists, + * and that at least one bit should be sent even if there is only one + * possible code. So to avoid special checks later on we force at least + * two codes of non zero frequency. + */ + while (s->heap_len < 2) { + node = s->heap[++(s->heap_len)] = (max_code < 2 ? ++max_code : 0); + tree[node].Freq = 1; + s->depth[node] = 0; + s->opt_len--; if (stree) s->static_len -= stree[node].Len; + /* node is 0 or 1 so it does not have extra bits */ + } + desc->max_code = max_code; + + /* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, + * establish sub-heaps of increasing lengths: + */ + for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); + + /* Construct the Huffman tree by repeatedly combining the least two + * frequent nodes. + */ + node = elems; /* next internal node of the tree */ + do { + pqremove(s, tree, n); /* n = node of least frequency */ + m = s->heap[SMALLEST]; /* m = node of next least frequency */ + + s->heap[--(s->heap_max)] = n; /* keep the nodes sorted by frequency */ + s->heap[--(s->heap_max)] = m; + + /* Create a new node father of n and m */ + tree[node].Freq = tree[n].Freq + tree[m].Freq; + s->depth[node] = (uch) (MAX(s->depth[n], s->depth[m]) + 1); + tree[n].Dad = tree[m].Dad = (ush)node; +#ifdef DUMP_BL_TREE + if (tree == s->bl_tree) { + fprintf(stderr,"\nnode %d(%d), sons %d(%d) %d(%d)", + node, tree[node].Freq, n, tree[n].Freq, m, tree[m].Freq); + } +#endif + /* and insert the new node in the heap */ + s->heap[SMALLEST] = node++; + pqdownheap(s, tree, SMALLEST); + + } while (s->heap_len >= 2); + + s->heap[--(s->heap_max)] = s->heap[SMALLEST]; + + /* At this point, the fields freq and dad are set. We can now + * generate the bit lengths. + */ + gen_bitlen(s, (tree_desc *)desc); + + /* The field len is now set, we can generate the bit codes */ + gen_codes ((ct_data *)tree, max_code, s->bl_count); +} + +/* =========================================================================== + * Scan a literal or distance tree to determine the frequencies of the codes + * in the bit length tree. + */ +local void scan_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + if (nextlen == 0) max_count = 138, min_count = 3; + tree[max_code+1].Len = (ush)0xffff; /* guard */ + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + s->bl_tree[curlen].Freq += count; + } else if (curlen != 0) { + if (curlen != prevlen) s->bl_tree[curlen].Freq++; + s->bl_tree[REP_3_6].Freq++; + } else if (count <= 10) { + s->bl_tree[REPZ_3_10].Freq++; + } else { + s->bl_tree[REPZ_11_138].Freq++; + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Send a literal or distance tree in compressed form, using the codes in + * bl_tree. + */ +local void send_tree (s, tree, max_code) + deflate_state *s; + ct_data *tree; /* the tree to be scanned */ + int max_code; /* and its largest code of non zero frequency */ +{ + int n; /* iterates over all tree elements */ + int prevlen = -1; /* last emitted length */ + int curlen; /* length of current code */ + int nextlen = tree[0].Len; /* length of next code */ + int count = 0; /* repeat count of the current code */ + int max_count = 7; /* max repeat count */ + int min_count = 4; /* min repeat count */ + + /* tree[max_code+1].Len = -1; */ /* guard already set */ + if (nextlen == 0) max_count = 138, min_count = 3; + + for (n = 0; n <= max_code; n++) { + curlen = nextlen; nextlen = tree[n+1].Len; + if (++count < max_count && curlen == nextlen) { + continue; + } else if (count < min_count) { + do { send_code(s, curlen, s->bl_tree); } while (--count != 0); + + } else if (curlen != 0) { + if (curlen != prevlen) { + send_code(s, curlen, s->bl_tree); count--; + } + Assert(count >= 3 && count <= 6, " 3_6?"); + send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); + + } else if (count <= 10) { + send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); + + } else { + send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); + } + count = 0; prevlen = curlen; + if (nextlen == 0) { + max_count = 138, min_count = 3; + } else if (curlen == nextlen) { + max_count = 6, min_count = 3; + } else { + max_count = 7, min_count = 4; + } + } +} + +/* =========================================================================== + * Construct the Huffman tree for the bit lengths and return the index in + * bl_order of the last bit length code to send. + */ +local int build_bl_tree(s) + deflate_state *s; +{ + int max_blindex; /* index of last bit length code of non zero freq */ + + /* Determine the bit length frequencies for literal and distance trees */ + scan_tree(s, (ct_data *)s->dyn_ltree, s->l_desc.max_code); + scan_tree(s, (ct_data *)s->dyn_dtree, s->d_desc.max_code); + + /* Build the bit length tree: */ + build_tree(s, (tree_desc *)(&(s->bl_desc))); + /* opt_len now includes the length of the tree representations, except + * the lengths of the bit lengths codes and the 5+5+4 bits for the counts. + */ + + /* Determine the number of bit length codes to send. The pkzip format + * requires that at least 4 bit length codes be sent. (appnote.txt says + * 3 but the actual value used is 4.) + */ + for (max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--) { + if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; + } + /* Update opt_len to include the bit length tree and counts */ + s->opt_len += 3*(max_blindex+1) + 5+5+4; + Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", + s->opt_len, s->static_len)); + + return max_blindex; +} + +/* =========================================================================== + * Send the header for a block using dynamic Huffman trees: the counts, the + * lengths of the bit length codes, the literal tree and the distance tree. + * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. + */ +local void send_all_trees(s, lcodes, dcodes, blcodes) + deflate_state *s; + int lcodes, dcodes, blcodes; /* number of codes for each tree */ +{ + int rank; /* index in bl_order */ + + Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); + Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, + "too many codes"); + Tracev((stderr, "\nbl counts: ")); + send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ + send_bits(s, dcodes-1, 5); + send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ + for (rank = 0; rank < blcodes; rank++) { + Tracev((stderr, "\nbl code %2d ", bl_order[rank])); + send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); + } + Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ + Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); + + send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ + Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); +} + +/* =========================================================================== + * Send a stored block + */ +void _tr_stored_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ +#ifdef DEBUG + s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; + s->compressed_len += (stored_len + 4) << 3; +#endif + copy_block(s, buf, (unsigned)stored_len, 1); /* with header */ +} + +/* =========================================================================== + * Send one empty static block to give enough lookahead for inflate. + * This takes 10 bits, of which 7 may remain in the bit buffer. + * The current inflate code requires 9 bits of lookahead. If the + * last two codes for the previous block (real code plus EOB) were coded + * on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode + * the last real code. In this case we send two empty static blocks instead + * of one. (There are no problems if the previous block is stored or fixed.) + * To simplify the code, we assume the worst case of last real code encoded + * on one bit only. + */ +void _tr_align(s) + deflate_state *s; +{ + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ +#endif + bi_flush(s); + /* Of the 10 bits for the empty block, we have already sent + * (10 - bi_valid) bits. The lookahead for the last real code (before + * the EOB of the previous block) was thus at least one plus the length + * of the EOB plus what we have just sent of the empty static block. + */ + if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { + send_bits(s, STATIC_TREES<<1, 3); + send_code(s, END_BLOCK, static_ltree); +#ifdef DEBUG + s->compressed_len += 10L; +#endif + bi_flush(s); + } + s->last_eob_len = 7; +} + +/* =========================================================================== + * Determine the best encoding for the current block: dynamic trees, static + * trees or store, and output the encoded block to the zip file. + */ +void _tr_flush_block(s, buf, stored_len, eof) + deflate_state *s; + charf *buf; /* input block, or NULL if too old */ + ulg stored_len; /* length of input block */ + int eof; /* true if this is the last block for a file */ +{ + ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ + int max_blindex = 0; /* index of last bit length code of non zero freq */ + + /* Build the Huffman trees unless a stored block is forced */ + if (s->level > 0) { + + /* Check if the file is ascii or binary */ + if (s->data_type == Z_UNKNOWN) set_data_type(s); + + /* Construct the literal and distance trees */ + build_tree(s, (tree_desc *)(&(s->l_desc))); + Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + + build_tree(s, (tree_desc *)(&(s->d_desc))); + Tracev((stderr, "\ndist data: dyn %ld, stat %ld", s->opt_len, + s->static_len)); + /* At this point, opt_len and static_len are the total bit lengths of + * the compressed block data, excluding the tree representations. + */ + + /* Build the bit length tree for the above two trees, and get the index + * in bl_order of the last bit length code to send. + */ + max_blindex = build_bl_tree(s); + + /* Determine the best encoding. Compute first the block length in bytes*/ + opt_lenb = (s->opt_len+3+7)>>3; + static_lenb = (s->static_len+3+7)>>3; + + Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", + opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, + s->last_lit)); + + if (static_lenb <= opt_lenb) opt_lenb = static_lenb; + + } else { + Assert(buf != (char*)0, "lost buf"); + opt_lenb = static_lenb = stored_len + 5; /* force a stored block */ + } + +#ifdef FORCE_STORED + if (buf != (char*)0) { /* force stored block */ +#else + if (stored_len+4 <= opt_lenb && buf != (char*)0) { + /* 4: two words for the lengths */ +#endif + /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. + * Otherwise we can't have processed more than WSIZE input bytes since + * the last block flush, because compression would have been + * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to + * transform a block into a stored block. + */ + _tr_stored_block(s, buf, stored_len, eof); + +#ifdef FORCE_STATIC + } else if (static_lenb >= 0) { /* force static trees */ +#else + } else if (static_lenb == opt_lenb) { +#endif + send_bits(s, (STATIC_TREES<<1)+eof, 3); + compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->static_len; +#endif + } else { + send_bits(s, (DYN_TREES<<1)+eof, 3); + send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, + max_blindex+1); + compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); +#ifdef DEBUG + s->compressed_len += 3 + s->opt_len; +#endif + } + Assert (s->compressed_len == s->bits_sent, "bad compressed size"); + /* The above check is made mod 2^32, for files larger than 512 MB + * and uLong implemented on 32 bits. + */ + init_block(s); + + if (eof) { + bi_windup(s); +#ifdef DEBUG + s->compressed_len += 7; /* align on byte boundary */ +#endif + } + Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, + s->compressed_len-7*eof)); +} + +/* =========================================================================== + * Save the match info and tally the frequency counts. Return true if + * the current block must be flushed. + */ +int _tr_tally (s, dist, lc) + deflate_state *s; + unsigned dist; /* distance of matched string */ + unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ +{ + s->d_buf[s->last_lit] = (ush)dist; + s->l_buf[s->last_lit++] = (uch)lc; + if (dist == 0) { + /* lc is the unmatched char */ + s->dyn_ltree[lc].Freq++; + } else { + s->matches++; + /* Here, lc is the match length - MIN_MATCH */ + dist--; /* dist = match distance - 1 */ + Assert((ush)dist < (ush)MAX_DIST(s) && + (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && + (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); + + s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; + s->dyn_dtree[d_code(dist)].Freq++; + } + +#ifdef TRUNCATE_BLOCK + /* Try to guess if it is profitable to stop the current block here */ + if ((s->last_lit & 0x1fff) == 0 && s->level > 2) { + /* Compute an upper bound for the compressed length */ + ulg out_length = (ulg)s->last_lit*8L; + ulg in_length = (ulg)((long)s->strstart - s->block_start); + int dcode; + for (dcode = 0; dcode < D_CODES; dcode++) { + out_length += (ulg)s->dyn_dtree[dcode].Freq * + (5L+extra_dbits[dcode]); + } + out_length >>= 3; + Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ", + s->last_lit, in_length, out_length, + 100L - out_length*100L/in_length)); + if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1; + } +#endif + return (s->last_lit == s->lit_bufsize-1); + /* We avoid equality with lit_bufsize because of wraparound at 64K + * on 16 bit machines and because stored blocks are restricted to + * 64K-1 bytes. + */ +} + +/* =========================================================================== + * Send the block data compressed using the given Huffman trees + */ +local void compress_block(s, ltree, dtree) + deflate_state *s; + ct_data *ltree; /* literal tree */ + ct_data *dtree; /* distance tree */ +{ + unsigned dist; /* distance of matched string */ + int lc; /* match length or unmatched char (if dist == 0) */ + unsigned lx = 0; /* running index in l_buf */ + unsigned code; /* the code to send */ + int extra; /* number of extra bits to send */ + + if (s->last_lit != 0) do { + dist = s->d_buf[lx]; + lc = s->l_buf[lx++]; + if (dist == 0) { + send_code(s, lc, ltree); /* send a literal byte */ + Tracecv(isgraph(lc), (stderr," '%c' ", lc)); + } else { + /* Here, lc is the match length - MIN_MATCH */ + code = _length_code[lc]; + send_code(s, code+LITERALS+1, ltree); /* send the length code */ + extra = extra_lbits[code]; + if (extra != 0) { + lc -= base_length[code]; + send_bits(s, lc, extra); /* send the extra length bits */ + } + dist--; /* dist is now the match distance - 1 */ + code = d_code(dist); + Assert (code < D_CODES, "bad d_code"); + + send_code(s, code, dtree); /* send the distance code */ + extra = extra_dbits[code]; + if (extra != 0) { + dist -= base_dist[code]; + send_bits(s, dist, extra); /* send the extra distance bits */ + } + } /* literal or match pair ? */ + + /* Check that the overlay between pending_buf and d_buf+l_buf is ok: */ + Assert(s->pending < s->lit_bufsize + 2*lx, "pendingBuf overflow"); + + } while (lx < s->last_lit); + + send_code(s, END_BLOCK, ltree); + s->last_eob_len = ltree[END_BLOCK].Len; +} + +/* =========================================================================== + * Set the data type to ASCII or BINARY, using a crude approximation: + * binary if more than 20% of the bytes are <= 6 or >= 128, ascii otherwise. + * IN assertion: the fields freq of dyn_ltree are set and the total of all + * frequencies does not exceed 64K (to fit in an int on 16 bit machines). + */ +local void set_data_type(s) + deflate_state *s; +{ + int n = 0; + unsigned ascii_freq = 0; + unsigned bin_freq = 0; + while (n < 7) bin_freq += s->dyn_ltree[n++].Freq; + while (n < 128) ascii_freq += s->dyn_ltree[n++].Freq; + while (n < LITERALS) bin_freq += s->dyn_ltree[n++].Freq; + s->data_type = (Byte)(bin_freq > (ascii_freq >> 2) ? Z_BINARY : Z_ASCII); +} + +/* =========================================================================== + * Reverse the first len bits of a code, using straightforward code (a faster + * method would use a table) + * IN assertion: 1 <= len <= 15 + */ +local unsigned bi_reverse(code, len) + unsigned code; /* the value to invert */ + int len; /* its bit length */ +{ + register unsigned res = 0; + do { + res |= code & 1; + code >>= 1, res <<= 1; + } while (--len > 0); + return res >> 1; +} + +/* =========================================================================== + * Flush the bit buffer, keeping at most 7 bits in it. + */ +local void bi_flush(s) + deflate_state *s; +{ + if (s->bi_valid == 16) { + put_short(s, s->bi_buf); + s->bi_buf = 0; + s->bi_valid = 0; + } else if (s->bi_valid >= 8) { + put_byte(s, (Byte)s->bi_buf); + s->bi_buf >>= 8; + s->bi_valid -= 8; + } +} + +/* =========================================================================== + * Flush the bit buffer and align the output on a byte boundary + */ +local void bi_windup(s) + deflate_state *s; +{ + if (s->bi_valid > 8) { + put_short(s, s->bi_buf); + } else if (s->bi_valid > 0) { + put_byte(s, (Byte)s->bi_buf); + } + s->bi_buf = 0; + s->bi_valid = 0; +#ifdef DEBUG + s->bits_sent = (s->bits_sent+7) & ~7; +#endif +} + +/* =========================================================================== + * Copy a stored block, storing first the length and its + * one's complement if requested. + */ +local void copy_block(s, buf, len, header) + deflate_state *s; + charf *buf; /* the input data */ + unsigned len; /* its length */ + int header; /* true if block header must be written */ +{ + bi_windup(s); /* align on byte boundary */ + s->last_eob_len = 8; /* enough lookahead for inflate */ + + if (header) { + put_short(s, (ush)len); + put_short(s, (ush)~len); +#ifdef DEBUG + s->bits_sent += 2*16; +#endif + } +#ifdef DEBUG + s->bits_sent += (ulg)len<<3; +#endif + while (len--) { + put_byte(s, *buf++); + } +} diff --git a/src/zlib/trees.h b/src/zlib/trees.h new file mode 100644 index 0000000..72facf9 --- /dev/null +++ b/src/zlib/trees.h @@ -0,0 +1,128 @@ +/* header created automatically with -DGEN_TREES_H */ + +local const ct_data static_ltree[L_CODES+2] = { +{{ 12},{ 8}}, {{140},{ 8}}, {{ 76},{ 8}}, {{204},{ 8}}, {{ 44},{ 8}}, +{{172},{ 8}}, {{108},{ 8}}, {{236},{ 8}}, {{ 28},{ 8}}, {{156},{ 8}}, +{{ 92},{ 8}}, {{220},{ 8}}, {{ 60},{ 8}}, {{188},{ 8}}, {{124},{ 8}}, +{{252},{ 8}}, {{ 2},{ 8}}, {{130},{ 8}}, {{ 66},{ 8}}, {{194},{ 8}}, +{{ 34},{ 8}}, {{162},{ 8}}, {{ 98},{ 8}}, {{226},{ 8}}, {{ 18},{ 8}}, +{{146},{ 8}}, {{ 82},{ 8}}, {{210},{ 8}}, {{ 50},{ 8}}, {{178},{ 8}}, +{{114},{ 8}}, {{242},{ 8}}, {{ 10},{ 8}}, {{138},{ 8}}, {{ 74},{ 8}}, +{{202},{ 8}}, {{ 42},{ 8}}, {{170},{ 8}}, {{106},{ 8}}, {{234},{ 8}}, +{{ 26},{ 8}}, {{154},{ 8}}, {{ 90},{ 8}}, {{218},{ 8}}, {{ 58},{ 8}}, +{{186},{ 8}}, {{122},{ 8}}, {{250},{ 8}}, {{ 6},{ 8}}, {{134},{ 8}}, +{{ 70},{ 8}}, {{198},{ 8}}, {{ 38},{ 8}}, {{166},{ 8}}, {{102},{ 8}}, +{{230},{ 8}}, {{ 22},{ 8}}, {{150},{ 8}}, {{ 86},{ 8}}, {{214},{ 8}}, +{{ 54},{ 8}}, {{182},{ 8}}, {{118},{ 8}}, {{246},{ 8}}, {{ 14},{ 8}}, +{{142},{ 8}}, {{ 78},{ 8}}, {{206},{ 8}}, {{ 46},{ 8}}, {{174},{ 8}}, +{{110},{ 8}}, {{238},{ 8}}, {{ 30},{ 8}}, {{158},{ 8}}, {{ 94},{ 8}}, +{{222},{ 8}}, {{ 62},{ 8}}, {{190},{ 8}}, {{126},{ 8}}, {{254},{ 8}}, +{{ 1},{ 8}}, {{129},{ 8}}, {{ 65},{ 8}}, {{193},{ 8}}, {{ 33},{ 8}}, +{{161},{ 8}}, {{ 97},{ 8}}, {{225},{ 8}}, {{ 17},{ 8}}, {{145},{ 8}}, +{{ 81},{ 8}}, {{209},{ 8}}, {{ 49},{ 8}}, {{177},{ 8}}, {{113},{ 8}}, +{{241},{ 8}}, {{ 9},{ 8}}, {{137},{ 8}}, {{ 73},{ 8}}, {{201},{ 8}}, +{{ 41},{ 8}}, {{169},{ 8}}, {{105},{ 8}}, {{233},{ 8}}, {{ 25},{ 8}}, +{{153},{ 8}}, {{ 89},{ 8}}, {{217},{ 8}}, {{ 57},{ 8}}, {{185},{ 8}}, +{{121},{ 8}}, {{249},{ 8}}, {{ 5},{ 8}}, {{133},{ 8}}, {{ 69},{ 8}}, +{{197},{ 8}}, {{ 37},{ 8}}, {{165},{ 8}}, {{101},{ 8}}, {{229},{ 8}}, +{{ 21},{ 8}}, {{149},{ 8}}, {{ 85},{ 8}}, {{213},{ 8}}, {{ 53},{ 8}}, +{{181},{ 8}}, {{117},{ 8}}, {{245},{ 8}}, {{ 13},{ 8}}, {{141},{ 8}}, +{{ 77},{ 8}}, {{205},{ 8}}, {{ 45},{ 8}}, {{173},{ 8}}, {{109},{ 8}}, +{{237},{ 8}}, {{ 29},{ 8}}, {{157},{ 8}}, {{ 93},{ 8}}, {{221},{ 8}}, +{{ 61},{ 8}}, {{189},{ 8}}, {{125},{ 8}}, {{253},{ 8}}, {{ 19},{ 9}}, +{{275},{ 9}}, {{147},{ 9}}, {{403},{ 9}}, {{ 83},{ 9}}, {{339},{ 9}}, +{{211},{ 9}}, {{467},{ 9}}, {{ 51},{ 9}}, {{307},{ 9}}, {{179},{ 9}}, +{{435},{ 9}}, {{115},{ 9}}, {{371},{ 9}}, {{243},{ 9}}, {{499},{ 9}}, +{{ 11},{ 9}}, {{267},{ 9}}, {{139},{ 9}}, {{395},{ 9}}, {{ 75},{ 9}}, +{{331},{ 9}}, {{203},{ 9}}, {{459},{ 9}}, {{ 43},{ 9}}, {{299},{ 9}}, +{{171},{ 9}}, {{427},{ 9}}, {{107},{ 9}}, {{363},{ 9}}, {{235},{ 9}}, +{{491},{ 9}}, {{ 27},{ 9}}, {{283},{ 9}}, {{155},{ 9}}, {{411},{ 9}}, +{{ 91},{ 9}}, {{347},{ 9}}, {{219},{ 9}}, {{475},{ 9}}, {{ 59},{ 9}}, +{{315},{ 9}}, {{187},{ 9}}, {{443},{ 9}}, {{123},{ 9}}, {{379},{ 9}}, +{{251},{ 9}}, {{507},{ 9}}, {{ 7},{ 9}}, {{263},{ 9}}, {{135},{ 9}}, +{{391},{ 9}}, {{ 71},{ 9}}, {{327},{ 9}}, {{199},{ 9}}, {{455},{ 9}}, +{{ 39},{ 9}}, {{295},{ 9}}, {{167},{ 9}}, {{423},{ 9}}, {{103},{ 9}}, +{{359},{ 9}}, {{231},{ 9}}, {{487},{ 9}}, {{ 23},{ 9}}, {{279},{ 9}}, +{{151},{ 9}}, {{407},{ 9}}, {{ 87},{ 9}}, {{343},{ 9}}, {{215},{ 9}}, +{{471},{ 9}}, {{ 55},{ 9}}, {{311},{ 9}}, {{183},{ 9}}, {{439},{ 9}}, +{{119},{ 9}}, {{375},{ 9}}, {{247},{ 9}}, {{503},{ 9}}, {{ 15},{ 9}}, +{{271},{ 9}}, {{143},{ 9}}, {{399},{ 9}}, {{ 79},{ 9}}, {{335},{ 9}}, +{{207},{ 9}}, {{463},{ 9}}, {{ 47},{ 9}}, {{303},{ 9}}, {{175},{ 9}}, +{{431},{ 9}}, {{111},{ 9}}, {{367},{ 9}}, {{239},{ 9}}, {{495},{ 9}}, +{{ 31},{ 9}}, {{287},{ 9}}, {{159},{ 9}}, {{415},{ 9}}, {{ 95},{ 9}}, +{{351},{ 9}}, {{223},{ 9}}, {{479},{ 9}}, {{ 63},{ 9}}, {{319},{ 9}}, +{{191},{ 9}}, {{447},{ 9}}, {{127},{ 9}}, {{383},{ 9}}, {{255},{ 9}}, +{{511},{ 9}}, {{ 0},{ 7}}, {{ 64},{ 7}}, {{ 32},{ 7}}, {{ 96},{ 7}}, +{{ 16},{ 7}}, {{ 80},{ 7}}, {{ 48},{ 7}}, {{112},{ 7}}, {{ 8},{ 7}}, +{{ 72},{ 7}}, {{ 40},{ 7}}, {{104},{ 7}}, {{ 24},{ 7}}, {{ 88},{ 7}}, +{{ 56},{ 7}}, {{120},{ 7}}, {{ 4},{ 7}}, {{ 68},{ 7}}, {{ 36},{ 7}}, +{{100},{ 7}}, {{ 20},{ 7}}, {{ 84},{ 7}}, {{ 52},{ 7}}, {{116},{ 7}}, +{{ 3},{ 8}}, {{131},{ 8}}, {{ 67},{ 8}}, {{195},{ 8}}, {{ 35},{ 8}}, +{{163},{ 8}}, {{ 99},{ 8}}, {{227},{ 8}} +}; + +local const ct_data static_dtree[D_CODES] = { +{{ 0},{ 5}}, {{16},{ 5}}, {{ 8},{ 5}}, {{24},{ 5}}, {{ 4},{ 5}}, +{{20},{ 5}}, {{12},{ 5}}, {{28},{ 5}}, {{ 2},{ 5}}, {{18},{ 5}}, +{{10},{ 5}}, {{26},{ 5}}, {{ 6},{ 5}}, {{22},{ 5}}, {{14},{ 5}}, +{{30},{ 5}}, {{ 1},{ 5}}, {{17},{ 5}}, {{ 9},{ 5}}, {{25},{ 5}}, +{{ 5},{ 5}}, {{21},{ 5}}, {{13},{ 5}}, {{29},{ 5}}, {{ 3},{ 5}}, +{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} +}; + +const uch _dist_code[DIST_CODE_LEN] = { + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, + 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, +10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, +11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, +12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, +13, 13, 13, 13, 13, 13, 13, 13, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, +14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, +15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 0, 0, 16, 17, +18, 18, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, +28, 28, 28, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, +29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +}; + +const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { + 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, +13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, +17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, +19, 19, 19, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, +21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 22, 22, 22, 22, +22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 23, 23, 23, 23, 23, 23, 23, 23, +23, 23, 23, 23, 23, 23, 23, 23, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, +25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, +26, 26, 26, 26, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, +27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 28 +}; + +local const int base_length[LENGTH_CODES] = { +0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 32, 40, 48, 56, +64, 80, 96, 112, 128, 160, 192, 224, 0 +}; + +local const int base_dist[D_CODES] = { + 0, 1, 2, 3, 4, 6, 8, 12, 16, 24, + 32, 48, 64, 96, 128, 192, 256, 384, 512, 768, + 1024, 1536, 2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576 +}; + diff --git a/src/zlib/uncompr.c b/src/zlib/uncompr.c new file mode 100644 index 0000000..3a71259 --- /dev/null +++ b/src/zlib/uncompr.c @@ -0,0 +1,58 @@ +/* uncompr.c -- decompress a memory buffer + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: uncompr.c,v 1.2 2002/03/13 17:45:56 xodnizel Exp $ */ + +#include "zlib.h" + +/* =========================================================================== + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ +int ZEXPORT uncompress (dest, destLen, source, sourceLen) + Bytef *dest; + uLongf *destLen; + const Bytef *source; + uLong sourceLen; +{ + z_stream stream; + int err; + + stream.next_in = (Bytef*)source; + stream.avail_in = (uInt)sourceLen; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR; + + stream.next_out = dest; + stream.avail_out = (uInt)*destLen; + if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR; + + stream.zalloc = (alloc_func)0; + stream.zfree = (free_func)0; + + err = inflateInit(&stream); + if (err != Z_OK) return err; + + err = inflate(&stream, Z_FINISH); + if (err != Z_STREAM_END) { + inflateEnd(&stream); + return err == Z_OK ? Z_BUF_ERROR : err; + } + *destLen = stream.total_out; + + err = inflateEnd(&stream); + return err; +} diff --git a/src/zlib/unzip.c b/src/zlib/unzip.c new file mode 100644 index 0000000..d156fae --- /dev/null +++ b/src/zlib/unzip.c @@ -0,0 +1,1301 @@ +/* unzip.c -- IO on .zip files using zlib + Version 0.15 beta, Mar 19th, 1998, + + Read unzip.h for more info +*/ + + +#include +#include +#include +#include "zlib.h" +#include "unzip.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + + +#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 (c1c2) + 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 (uBackReaduMaxBack) + 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=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_pospfile_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_filename0) && (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_extrafile,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_commentfile,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_compressedrest_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;istream.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/src/zlib/unzip.h b/src/zlib/unzip.h new file mode 100644 index 0000000..76692cb --- /dev/null +++ b/src/zlib/unzip.h @@ -0,0 +1,275 @@ +/* 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 + +#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/src/zlib/zconf.h b/src/zlib/zconf.h new file mode 100644 index 0000000..68a9f9c --- /dev/null +++ b/src/zlib/zconf.h @@ -0,0 +1,279 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zconf.h,v 1.2 2002/03/13 17:45:56 xodnizel Exp $ */ + +#ifndef _ZCONF_H +#define _ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + */ +#ifdef Z_PREFIX +# define deflateInit_ z_deflateInit_ +# define deflate z_deflate +# define deflateEnd z_deflateEnd +# define inflateInit_ z_inflateInit_ +# define inflate z_inflate +# define inflateEnd z_inflateEnd +# define deflateInit2_ z_deflateInit2_ +# define deflateSetDictionary z_deflateSetDictionary +# define deflateCopy z_deflateCopy +# define deflateReset z_deflateReset +# define deflateParams z_deflateParams +# define inflateInit2_ z_inflateInit2_ +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateReset z_inflateReset +# define compress z_compress +# define compress2 z_compress2 +# define uncompress z_uncompress +# define adler32 z_adler32 +# define crc32 z_crc32 +# define get_crc_table z_get_crc_table + +# define Byte z_Byte +# define uInt z_uInt +# define uLong z_uLong +# define Bytef z_Bytef +# define charf z_charf +# define intf z_intf +# define uIntf z_uIntf +# define uLongf z_uLongf +# define voidpf z_voidpf +# define voidp z_voidp +#endif + +#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) +# define WIN32 +#endif +#if defined(__GNUC__) || defined(WIN32) || defined(__386__) || defined(i386) +# ifndef __32BIT__ +# define __32BIT__ +# endif +#endif +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#if defined(MSDOS) && !defined(__32BIT__) +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#if (defined(MSDOS) || defined(_WINDOWS) || defined(WIN32)) && !defined(STDC) +# define STDC +#endif +#if defined(__STDC__) || defined(__cplusplus) || defined(__OS2__) +# ifndef STDC +# define STDC +# endif +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const +# endif +#endif + +/* Some Mac compilers merge all .h files incorrectly: */ +#if defined(__MWERKS__) || defined(applec) ||defined(THINK_C) ||defined(__SC__) +# define NO_DUMMY_DECL +#endif + +/* Old Borland C incorrectly complains about missing returns: */ +#if defined(__BORLANDC__) && (__BORLANDC__ < 0x500) +# define NEED_DUMMY_RETURN +#endif + + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus a few kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#if (defined(M_I86SM) || defined(M_I86MM)) && !defined(__32BIT__) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +#endif +#if defined(__BORLANDC__) && (defined(__SMALL__) || defined(__MEDIUM__)) +# ifndef __32BIT__ +# define SMALL_MEDIUM +# define FAR _far +# endif +#endif + +/* Compile with -DZLIB_DLL for Windows DLL support */ +#if defined(ZLIB_DLL) +# if defined(_WINDOWS) || defined(WINDOWS) +# ifdef FAR +# undef FAR +# endif +# include +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR _cdecl _export +# endif +# endif +# if defined (__BORLANDC__) +# if (__BORLANDC__ >= 0x0500) && defined (WIN32) +# include +# define ZEXPORT __declspec(dllexport) WINAPI +# define ZEXPORTRVA __declspec(dllexport) WINAPIV +# else +# if defined (_Windows) && defined (__DLL__) +# define ZEXPORT _export +# define ZEXPORTVA _export +# endif +# endif +# endif +#endif + +#if defined (__BEOS__) +# if defined (ZLIB_DLL) +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +#endif + +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif +#ifndef ZEXTERN +# define ZEXTERN extern +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(MACOS) && !defined(TARGET_OS_MAC) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#ifdef HAVE_UNISTD_H +# include /* for off_t */ +# include /* for SEEK_* and off_t */ +# define z_off_t off_t +#endif +#ifndef SEEK_SET +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif +#ifndef z_off_t +# define z_off_t long +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) +# pragma map(deflateInit_,"DEIN") +# pragma map(deflateInit2_,"DEIN2") +# pragma map(deflateEnd,"DEEND") +# pragma map(inflateInit_,"ININ") +# pragma map(inflateInit2_,"ININ2") +# pragma map(inflateEnd,"INEND") +# pragma map(inflateSync,"INSY") +# pragma map(inflateSetDictionary,"INSEDI") +# pragma map(inflate_blocks,"INBL") +# pragma map(inflate_blocks_new,"INBLNE") +# pragma map(inflate_blocks_free,"INBLFR") +# pragma map(inflate_blocks_reset,"INBLRE") +# pragma map(inflate_codes_free,"INCOFR") +# pragma map(inflate_codes,"INCO") +# pragma map(inflate_fast,"INFA") +# pragma map(inflate_flush,"INFLU") +# pragma map(inflate_mask,"INMA") +# pragma map(inflate_set_dictionary,"INSEDI2") +# pragma map(inflate_copyright,"INCOPY") +# pragma map(inflate_trees_bits,"INTRBI") +# pragma map(inflate_trees_dynamic,"INTRDY") +# pragma map(inflate_trees_fixed,"INTRFI") +# pragma map(inflate_trees_free,"INTRFR") +#endif + +#endif /* _ZCONF_H */ diff --git a/src/zlib/zlib.h b/src/zlib/zlib.h new file mode 100644 index 0000000..52cb529 --- /dev/null +++ b/src/zlib/zlib.h @@ -0,0 +1,893 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.1.4, March 11th, 2002 + + Copyright (C) 1995-2002 Jean-loup Gailly and Mark Adler + + 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. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt + (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format). +*/ + +#ifndef _ZLIB_H +#define _ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.1.4" + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed + data. This version of the library supports only one compression method + (deflation) but other algorithms will be added later and will have the same + stream interface. + + Compression can be done in a single step if the buffers are large + enough (for example if an input file is mmap'ed), or can be done by + repeated calls of the compression function. In the latter case, the + application must provide more input and/or consume the output + (providing more output space) before each call. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never + crash even in case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total nb of input bytes read so far */ + + Bytef *next_out; /* next output byte should be put there */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total nb of bytes output so far */ + + char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: ascii or binary */ + uLong adler; /* adler32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + The application must update next_in and avail_in when avail_in has + dropped to zero. It must update next_out and avail_out when avail_out + has dropped to zero. The application must initialize zalloc, zfree and + opaque before calling the init function. All other fields are set by the + compression library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this + if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, + pointers returned by zalloc for objects of exactly 65536 bytes *must* + have their offset normalized to zero. The default allocation function + provided by this library ensures this (see zutil.c). To reduce memory + requirements and avoid any allocation of 64K objects, at the expense of + compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or + progress reports. After compression, total_in holds the total size of + the uncompressed data and may be saved for use in the decompressor + (particularly if the decompressor wants to decompress everything in + a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +/* Allowed flush values; see deflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative + * values are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_ASCII 1 +#define Z_UNKNOWN 2 +/* Possible values of the data_type field */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is + not compatible with the zlib.h header file used by the application. + This check is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. + If zalloc and zfree are set to Z_NULL, deflateInit updates them to + use default allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at + all (the input data is simply copied a block at a time). + Z_DEFAULT_COMPRESSION requests a default compromise between speed and + compression (currently equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if level is not a valid compression level, + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). + msg is set to null if there is no error message. deflateInit does not + perform any compression: this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce some + output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary (in interactive applications). + Some output may be provided even if flush is not set. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating avail_in or avail_out accordingly; avail_out + should never be zero before the call. The application can consume the + compressed output when it wants, for example when the output buffer is full + (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK + and with zero avail_out, it must be called again after making room in the + output buffer because there might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In particular + avail_in is zero after the call if enough output space has been provided + before the call.) Flushing may degrade compression for some compression + algorithms and so it should be used only when necessary. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + the compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there + was enough output space; if deflate returns with Z_OK, this function must be + called again with Z_FINISH and more output space (updated avail_out) but no + more input data, until it returns with Z_STREAM_END or an error. After + deflate has returned Z_STREAM_END, the only possible operations on the + stream are deflateReset or deflateEnd. + + Z_FINISH can be used immediately after deflateInit if all the compression + is to be done in a single step. In this case, avail_out must be at least + 0.1% larger than avail_in plus 12 bytes. If deflate does not return + Z_STREAM_END, then it must be called again as described above. + + deflate() sets strm->adler to the adler32 checksum of all input read + so far (that is, total_in bytes). + + deflate() may update data_type if it can make a good guess about + the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered + binary. This field is only for information purposes and does not affect + the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible + (for example avail_in or avail_out was zero). +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, + msg may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. If next_in is not Z_NULL and avail_in is large enough (the exact + value depends on the compression method), inflateInit determines the + compression method from the zlib header and allocates all data structures + accordingly; otherwise the allocation will be deferred to the first call of + inflate. If zalloc and zfree are set to Z_NULL, inflateInit updates them to + use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller. msg is set to null if there is no error + message. inflateInit does not perform any decompression apart from reading + the zlib header if present: this will be done by inflate(). (So next_in and + avail_in may be modified, but next_out and avail_out are unchanged.) +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may some + introduce some output latency (reading input without producing any output) + except when forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in is updated and processing + will resume at this point for the next call of inflate(). + + - Provide more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there + is no more input data or no more space in the output buffer (see below + about the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming + more output, and updating the next_* and avail_* values accordingly. + The application can consume the uncompressed output when it wants, for + example when the output buffer is full (avail_out == 0), or after each + call of inflate(). If inflate returns Z_OK and with zero avail_out, it + must be called again after making room in the output buffer because there + might be more output pending. + + If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much + output as possible to the output buffer. The flushing behavior of inflate is + not specified for values of the flush parameter other than Z_SYNC_FLUSH + and Z_FINISH, but the current implementation actually flushes as much output + as possible anyway. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step + (a single call of inflate), the parameter flush should be set to + Z_FINISH. In this case all pending input is processed and all pending + output is flushed; avail_out must be large enough to hold all the + uncompressed data. (The size of the uncompressed data may have been saved + by the compressor for this purpose.) The next operation on this stream must + be inflateEnd to deallocate the decompression state. The use of Z_FINISH + is never required, but can be used to inform inflate that a faster routine + may be used for the single inflate() call. + + If a preset dictionary is needed at this point (see inflateSetDictionary + below), inflate sets strm-adler to the adler32 checksum of the + dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise + it sets strm->adler to the adler32 checksum of all output produced + so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or + an error code as described below. At the end of the stream, inflate() + checks that its computed adler32 checksum is equal to that saved by the + compressor and returns Z_STREAM_END only if the checksum is correct. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect + adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent + (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if no progress is possible or if there was not + enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR + case, the application may then call inflateSync to look for a good + compression block. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any + pending output. + + inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state + was inconsistent. In the error case, msg may be set but then points to a + static string (which must not be deallocated). +*/ + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by + the caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but + is slow and reduces compression ratio; memLevel=9 uses maximum memory + for optimal speed. The default value is 8. See zconf.h for total memory + usage as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match). Filtered data consists mostly of small values with a + somewhat random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of Z_FILTERED is to force more + Huffman coding and less string matching; it is somewhat intermediate + between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects + the compression ratio but not the correctness of the compressed output even + if it is not set appropriately. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid + method). msg is set to null if there is no error message. deflateInit2 does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. This function must be called + immediately after deflateInit, deflateInit2 or deflateReset, before any + call of deflate. The compressor and decompressor must use exactly the same + dictionary (see inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size in + deflate or deflate2. Thus the strings most likely to be useful should be + put at the end of the dictionary, not at the front. + + Upon return of this function, strm->adler is set to the Adler32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if the compression method is bsort). deflateSetDictionary does not + perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and + can consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, + but does not free and reallocate all the internal compression state. + The stream will keep the same compression level and any other attributes + that may have been set by deflateInit2. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2. This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different + strategy. If the compression level is changed, the input available so far + is compressed with the old level (and may be flushed); the new level will + take effect only at the next call of deflate(). + + Before the call of deflateParams, the stream state must be set as for + a call of deflate(), since the currently available input may have to + be compressed and flushed. In particular, strm->avail_out must be non-zero. + + deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source + stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR + if strm->avail_out was zero. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. If a compressed stream with a larger window size is given as + input, inflate() will return with the error code Z_DATA_ERROR instead of + trying to allocate a larger window. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative + memLevel). msg is set to null if there is no error message. inflateInit2 + does not perform any decompression apart from reading the zlib header if + present: this will be done by inflate(). (So next_in and avail_in may be + modified, but next_out and avail_out are unchanged.) +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate + if this call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler32 value returned by this call of + inflate. The compressor and decompressor must use exactly the same + dictionary (see deflateSetDictionary). + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (such as NULL dictionary) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a full flush point (see above the + description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR + if no more input was provided, Z_DATA_ERROR if no flush point has been found, + or Z_STREAM_ERROR if the stream structure was inconsistent. In the success + case, the application may save the current current value of total_in which + indicates where valid compressed data was found. In the error case, the + application may repeatedly call inflateSync, providing more input each time, + until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being NULL). +*/ + + + /* utility functions */ + +/* + The following utility functions are implemented on top of the + basic stream-oriented functions. To simplify the interface, some + default options are assumed (compression level and memory usage, + standard memory allocation functions). The source code of these + utility functions can easily be modified if you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be at least 0.1% larger than + sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the + compressed buffer. + This function can be used to compress a whole file at once if the + input file is mmap'ed. + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least 0.1% larger than sourceLen plus + 12 bytes. Upon exit, destLen is the actual size of the compressed buffer. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total + size of the destination buffer, which must be large enough to hold the + entire uncompressed data. (The size of the uncompressed data must have + been saved previously by the compressor and transmitted to the decompressor + by some mechanism outside the scope of this compression library.) + Upon exit, destLen is the actual size of the compressed buffer. + This function can be used to decompress a whole file at once if the + input file is mmap'ed. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted. +*/ + + +typedef voidp gzFile; + +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); +/* + Opens a gzip (.gz) file for reading or writing. The mode parameter + is as in fopen ("rb" or "wb") but can also include a compression level + ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for + Huffman only compression as in "wb1h". (See the description + of deflateInit2 for more information about the strategy parameter.) + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. + + gzopen returns NULL if the file could not be opened or if there was + insufficient memory to allocate the (de)compression state; errno + can be checked to distinguish the two cases (if errno is zero, the + zlib error is Z_MEM_ERROR). */ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen() associates a gzFile with the file descriptor fd. File + descriptors are obtained from calls like open, dup, creat, pipe or + fileno (in the file has been previously opened with fopen). + The mode parameter is as in gzopen. + The next call of gzclose on the returned gzFile will also close the + file descriptor fd, just like fclose(fdopen(fd), mode) closes the file + descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode). + gzdopen returns NULL if there was insufficient memory to allocate + the (de)compression state. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. + gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not + opened for writing. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. + If the input file was not in gzip format, gzread copies the given number + of bytes into the buffer. + gzread returns the number of uncompressed bytes actually read (0 for + end of file, -1 for error). */ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + const voidp buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes actually written + (0 in case of error). +*/ + +ZEXTERN int ZEXPORTVA gzprintf OF((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the args to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written (0 in case of error). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or + a newline character is read and transferred to buf, or an end-of-file + condition is encountered. The string is then terminated with a null + character. + gzgets returns buf, or Z_NULL in case of error. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. + gzputc returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte + or -1 in case of end of file or error. +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter + flush is as in the deflate() function. The return value is the zlib + error number (see function gzerror below). gzflush returns Z_OK if + the flush parameter is Z_FINISH and all output could be flushed. + gzflush should be called only when strictly necessary because it can + degrade compression. +*/ + +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); +/* + Sets the starting position for the next gzread or gzwrite on the + given compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); +/* + Returns the starting position for the next gzread or gzwrite on the + given compressed file. This position represents a number of bytes in the + uncompressed data stream. + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns 1 when EOF has previously been detected reading the given + input stream, otherwise zero. +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file + and deallocates all the (de)compression state. The return value is the zlib + error number (see function gzerror below). +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the + given compressed file. errnum is set to zlib error number. If an + error occurred in the file system and not in the compression library, + errnum is set to Z_ERRNO and the application may consult errno + to get the exact error code. +*/ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the + compression library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); + +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is NULL, this function returns + the required initial value for the checksum. + An Adler-32 checksum is almost as reliable as a CRC32 but can be computed + much faster. Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running crc with the bytes buf[0..len-1] and return the updated + crc. If buf is NULL, this function returns the required initial value + for the crc. Pre- and post-conditioning (one's complement) is performed + within this function so it shouldn't be done by the application. + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +#define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, sizeof(z_stream)) +#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, sizeof(z_stream)) +#define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream)) + + +#if !defined(_Z_UTIL_H) && !defined(NO_DUMMY_DECL) + struct internal_state {int dummy;}; /* hack for buggy compilers */ +#endif + +ZEXTERN const char * ZEXPORT zError OF((int err)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp z)); +ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); + +#ifdef __cplusplus +} +#endif + +#endif /* _ZLIB_H */ diff --git a/src/zlib/zutil.c b/src/zlib/zutil.c new file mode 100644 index 0000000..08166c0 --- /dev/null +++ b/src/zlib/zutil.c @@ -0,0 +1,225 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id: zutil.c,v 1.2 2002/03/13 17:45:56 xodnizel Exp $ */ + +#include "zutil.h" + +struct internal_state {int dummy;}; /* for buggy compilers */ + +#ifndef STDC +extern void exit OF((int)); +#endif + +const char *z_errmsg[10] = { +"need dictionary", /* Z_NEED_DICT 2 */ +"stream end", /* Z_STREAM_END 1 */ +"", /* Z_OK 0 */ +"file error", /* Z_ERRNO (-1) */ +"stream error", /* Z_STREAM_ERROR (-2) */ +"data error", /* Z_DATA_ERROR (-3) */ +"insufficient memory", /* Z_MEM_ERROR (-4) */ +"buffer error", /* Z_BUF_ERROR (-5) */ +"incompatible version",/* Z_VERSION_ERROR (-6) */ +""}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +#ifdef DEBUG + +# ifndef verbose +# define verbose 0 +# endif +int z_verbose = verbose; + +void z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + + +#ifndef HAVE_MEMCPY + +void zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + +#ifdef __TURBOC__ +#if (defined( __BORLANDC__) || !defined(SMALL_MEDIUM)) && !defined(__32BIT__) +/* Small and medium model in Turbo C are for now limited to near allocation + * with reduced MAX_WBITS and MAX_MEM_LEVEL + */ +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf = opaque; /* just to make some compilers happy */ + ulg bsize = (ulg)items*size; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + int n; + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + ptr = opaque; /* just to make some compilers happy */ + Assert(0, "zcfree: ptr not found"); +} +#endif +#endif /* __TURBOC__ */ + + +#if defined(M_I86) && !defined(__32BIT__) +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + return _halloc((long)items, size); +} + +void zcfree (voidpf opaque, voidpf ptr) +{ + if (opaque) opaque = 0; /* to make compiler happy */ + _hfree(ptr); +} + +#endif /* MSC */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + if (opaque) items += size - size; /* make compiler happy */ + return (voidpf)calloc(items, size); +} + +void zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + free(ptr); + if (opaque) return; /* make compiler happy */ +} + +#endif /* MY_ZCALLOC */ diff --git a/src/zlib/zutil.h b/src/zlib/zutil.h new file mode 100644 index 0000000..507cab9 --- /dev/null +++ b/src/zlib/zutil.h @@ -0,0 +1,220 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2002 Jean-loup Gailly. + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id: zutil.h,v 1.2 2002/03/13 17:45:56 xodnizel Exp $ */ + +#ifndef _Z_UTIL_H +#define _Z_UTIL_H + +#include "zlib.h" + +#ifdef STDC +# include +# include +# include +#endif +#ifdef NO_ERRNO_H + extern int errno; +#else +# include +#endif + +#ifndef local +# define local static +#endif +/* compile with -Dlocal if your debugger can't find static symbols */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = (char*)ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#ifdef MSDOS +# define OS_CODE 0x00 +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +#endif + +#ifdef OS2 +# define OS_CODE 0x06 +#endif + +#ifdef WIN32 /* Window 95 & Windows NT */ +# define OS_CODE 0x0b +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 0x02 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#ifdef AMIGA +# define OS_CODE 0x01 +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 0x05 +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 0x07 +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +#endif + +#ifdef __50SERIES /* Prime/PRIMOS */ +# define OS_CODE 0x0F +#endif + +#ifdef TOPS20 +# define OS_CODE 0x0a +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) +# define fdopen(fd,type) _fdopen(fd,type) +#endif + + + /* Common defaults */ + +#ifndef OS_CODE +# define OS_CODE 0x03 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#ifdef HAVE_STRERROR + extern char *strerror OF((int)); +# define zstrerror(errnum) strerror(errnum) +#else +# define zstrerror(errnum) "" +#endif + +#if defined(pyr) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + extern void zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef DEBUG +# include + extern int z_verbose; + extern void z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + + +typedef uLong (ZEXPORT *check_func) OF((uLong check, const Bytef *buf, + uInt len)); +voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); +void zcfree OF((voidpf opaque, voidpf ptr)); + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +#endif /* _Z_UTIL_H */ diff --git a/whatsnew.txt b/whatsnew.txt new file mode 100644 index 0000000..58ed5de --- /dev/null +++ b/whatsnew.txt @@ -0,0 +1,186 @@ +16.06.06 + + 068 mapper - (...) wrapper to NTBROM UNIF board without Double Casette System support + NES-NTBROM - new UNIF board for mapper Sunsoft mapper 68 with Double Casette System support + +29.05.06 + + 060 mapper - (...) defined as BMC-D1038 UNIF board with capability to change hardware dip switch to select game number in menu by pressing Reset. + 209 mapper - (...) fixed chr bankswitching in 4k mode, almost fixes "Power Rangers 3,4" and "Punch Out" + 113 mapper - (...) cleaned source, Sachen games redefined to normal sachen mappers, "deadboots" probably won't work ;). + 132 mapper - (...) UNL-22211 UNIF board wrapper + 158 mapper - (...) removed, redefined to 118 + 195 mapper - (...) defined for "Crystalis (C)", "Captain Tsubasa Vol 2 - Super Striker (C)" + 198 mapper - (...) defined for "Tenchi o Kurau II - Shokatsu Koumei Den (J) (C)" + 199 mapper - (Martin) defined for new dumps "Dragon Ball Z 2 - Gekishin Freeza! (C)", "Dragon Ball Z Gaiden - Saiya Jin Zetsumetsu Keikaku (C)" + BMC-70in1 - fixed UNIF board for supporting menu selecting by pressing Reset + BMC-FK23C - fixed UNIF board for dump "4-in-1 (FK23C8244) [p1][U][!].nes" + UNL-22211 - new UNIF board for dump "Qi Wang - Chinese Chess (MGC-001) [U][!].nes" + BMC-D1038 - UNIF board for mapper 60. + BMC-A65AS - new UNIF board for dump "3-in-1 (N068) [p1][U][!].nes" + BMC-GF1004 - new UNIF board for dump "4-in-1 (JY-066) [p1][U][!].nes" + UNL-6035052 - new UNIF board for dump "Contra Fighter (Unl) [U][!].nes" + + +10.04.06 + + 045 mapper - (...) fixed, correct emulation of some dumps. + 115 mapper - (...) fixed, looks like logic of this mapper little different than we has know. + 188 mapper - (...) fixed, additional songs are selectable. + 189 mapper - (...) fixed for new dump "Master Fighter II (As)[!].nes" + 235 mapper - (...) modified iNES loader source to allow loading iNES ROMS with 256 PRG banks. + board S74LS374N fixes for supporting new dumps... + boadr SHero new Sachen dump + board T-262 new multigame cart dump + DInput device mode changed to BACKGROUND. Now with enabled flag "Acvive while focus lost" it can be used for playing two or more FCEUs with one keyboard or joystic at same time. + "Fixed" low quality sound, broken "High" ;) + +19.03.06 + + 004 mapper - (...) "Yong Zhe Dou E Long - Dragon Quest VI (As).nes" fixed CHR glitch (probably others). + (Nestopia) forced to MMC3 RevB board IRQ, fixes map mode "My Life My Love - Boku no Yume - Watashi no Negai (J).nes", + wave effect at level start for "Mickey Mouse 3 - Yume Fuusen (J).nes", "Kid Klown (U).nes", probaly crashes others non-RevB games... + Small fix to mapper source to allow to run "Colour 2001 Streetfighter II (Unl) [!].nes", + "King of Fighters 99 [p1].nes" and "Super HIK 7-in-1 (Multicart k7006) [p1][!].nes" + 037 mapper - (...) "Super Mario Bros. + Tetris + Nintendo World Cup (E) [!]" redefined from 47 by CRC check. + 057 mapper - (...) small modification for switching menu mode by pressing reset button, moved to UNIF borads source + 058 mapper - (...) small mirroring fix, moved to UNIF boards source + 074 mapper - (...) defined for "Di 4 Ci - Ji Qi Ren Dai Zhan (As).nes" and "Ji Jia Zhan Shi (As).nes", "Jia A Fung Yun (Chinese).nes" now fully playable. + 090 mapper - (Kevin Horton) another IRQ source mode 00 (M2 CPU Cycles), now "45-in-1 (Unl) (As)[U][!].nes" emulated perfectly ;) + (...) fixed nametable handling bug, fixed 211 mapper too + (...) fixed register initialization, now "Super Contra 3 (Unl) [p1].nes" starts properly, fixed "black boxes" instead players + in "Goal!!" at "45-in-1 (JY-120A)(As) [U][!].nes" multigame cart while they crossing bottom part of playing screen. + 163 mapper - (TPU) fixed screen error in "Harvest Moon (C).nes" + 211 mapper - (...) removed old source, concatenated with main 90 mapper source after fixing nametable problem + mapper have hardware nametable ROM mapping enabled by default indepentantly from nametable mode + 181 mapper - (...) defined for "Seicross (J)(Redump) [!].nes", this mapper have opposite protection bits values than normal 185. + 185 mapper - (...) now supports all different mapper board in one mapper source without hacks (little dirty ;)) + 187 mapper - (Nestopia) "King of Fighters 96 [p1].nes", "Sonic 3D Blast 6 (Unl) [h1].nes", + "Street Fighter Alpha Zero 97 [!].nes" now playable, + "Street Fighter Zero 2 [p1].nes" background fixed + 192 mapper - (...) defined for "Ying Lie Qun Xia Zhuan (Chinese)" instead 74 mapper. + 194 mapper - (...) defined for "Dai-2-Ji - Super Robot Taisen (As)" instead 74 mapper. + 222 mapper - (...) "Dragon Ninja (J) [p1][!].nes" works properly + UNL-KOF97 board - new UNIF board for "King of Fighters 97 (Rex Soft.) [U][!].nes" + UNL-Super24 board - fixed again, now fixed mirroring problem finally + UNL-8157 board - small fix allows to see another game menu after reset + BMC-42in1ResetSwitch - new UNIF board for "42-in-1 (Reset Switch) [U][p1][!].nes" + BMC-64in1NoRepeat - new UNIF board for "64-in-1 (No Repeat) [U][p1][!].nes" + BMC-70in1 - new UNIF board for "70-in-1 [U][p1][!].nes" + BMC-70in1B - new UNIF board for "800-in-1 [U][p1][!].nes" + +18.11.05 + + 137 mapper - (...) Sachen S8259 board, 1K CHR bank mode "The Great Wall (72 pin cart).nes" + 138 mapper - (...) Sachen S8259 board, 2K CHR bank planar mode + 139 mapper - (...) Sachen S8259 board, 8K CHR bank mode + 141 mapper - (...) Sachen S8259 board, 4K CHR bank mode + 143 mapper - (...) Sachen TCA01 board + 145 mapper - (...) Sachen SA72007 board + 146 mapper - (...) Sachen SA0161M board + 147 mapper - (...) Sachen TCU01 board ("pathetic copy protection" ;)) + 148 mapper - (...) Sachen SA0037 board ("Q-Boy" now mapper 148) + 149 mapper - (...) Sachen SA0036 board + 150 mapper - (...) Sachen S74LS374N board + 191 mapper - (...) old mapper code removed, old mapper 148 code moved to + PowerShot Gun - right mouse button click throws grenade. + UNL-SuperHIK8in1 unif board - (...) UNIF wrapper for "Super 8-in-1 99 King Fighter [p1].nes" converted to UNIF format with correct CHR banks order. + +23.01.05 + + 114 mapper - (...) source rewritten and moved to MMC3 shared source file + 215 mapper - (...) source rewritten and moved to MMC3 shared source file, new dump "3-in-1 Super 308 (Super Game)[!].nes" + 217 mapper - (...) source rewritten and moved to MMC3 shared source file, new dump "Golden Card 6-in-1 (SPC009) (Super Game)[!].nes" + debugger - disasm window double click handlig reworked, now it adds new breakpoint for selected instruction + +02.07.05 + + 042 mapper - (...) small mapper fix allow play "Ai Senshi Nicol (As).nes" + 090 mapper - (...) hardware selection flag now advanced to 4 different values, allow enable more game title inside by pressing reset button + (...) added new IRQ counting mode that allow to run normally pirate hack of "Astyanax" - "Aladdin - Return of Jaffar, The [p1].nes" + 163 mapper - (...) new TPU's dump + 191 mapper - (VNES) "Sachen Q-Bert.nes" + 211 mapper - (...) new dump "Tiny Toon Adentures 6 (Pirate Original) [!].nes" now work fine + 212 mapper - (...) playable again "Super HIK 300-in-1 (1994).nes" + 216 mapper - (...) debug mapper for cart with SIM reader aboard "Bonza" + 245 mapper - (...) fixed old CHR switching bug + Super24 board - (Nintencer) now works fine. + Fixed PPUView according to FCEUexD source code. + +02.01.05 + + added 214 mapper - debug "Super Gun 24-in-1 [p2].nes" + fixed 113 mapper - (VNES) "Mind Blower Pak [p1].nes" displays correct CHR page + added debugger function to dump video memory + +24.08.04 + + fixed 060 mapper - (...) redefined to simple multicart board, similar to 58-62,200-204, works now "Super 35-in-1 (6-in-1 VT5201) [p1].nes","TN 95-in-1 (6-in-1) [p1].nes", reset based "Reset Based 4-in-1 [p1].nes" no longer supports + fixed 165 mapper - (TPU) "Fire Emblem (Unl).nes" now works (almost fine) + added 167 mapper - (TPU) "SuporV40.nes", "Supor English (Chinese).nes" + added 166 mapper - (TPU) redefined by CRC check "Suborv10 (Russian).nes" from 015 mapper + fixed 015 mapper - (...) original mapper code is back + added 213 mapper - mapper for new dump "9999999-in-1 [p2].nes" + added Subor V1.0,V3.0,V4.0 keyboard support (based on Family Keyboard source) + added CRC check for games that supports Subor keyboard + added PPU memory Viewer (from FCEUd sources by Dragon-Eye Studio) + fixed "Study and Game 32-in-1 [p1][!].nes" redefined CRC check from 058 to 241 mapper + +09.06.04 + + fixed 164 mapper - (...) "San Guo Zhi 2 (Chinese).nes" now works + +21.04.04 + + added 164 mapper - (Xod) "Final Fantasy V (Unl).nes" + added 165 mapper - (...) partially supports "Fire Emblem (Unl).nes" + added 212 mapper - (...) mapper for new dump "Super HIK 300-in-1 (1994).nes" + added 215 mapper - (...) mapper for new dump "Mortal Combat 3 (Extra 60).nes" + added exit by pressing ESCAPE button + +23.12.03 + + 201 mapper - (...) mapper corrections + 202 mapper - (...) mapper corrections + 204 mapper - (...) mapper for new dump "64-in-1 [p1].nes" + 208 mapper - (FCEU) "Street Fighter 4 (GOUDER).nes" now playable. (thx Xodnizel) + 211 mapper - (...) debug mapper code for new dumps "MK2.nes" и "DKC1.nes" + +10.11.03 + + fixed 060 mapper (...) Almost nothing... + added 186 mapper (Thanx Scrybe and others), "Street Fighter IV.nes" (still work unproperly). + + fixed 200 mapper (...) mapper for new dump now works properly + added 203 mapper (...) mapper for new dump "35-in-1 [p1].nes" + added 205 mapper (...) mapper for new dumps "15-in-1 [p2].nes", "3-in-1 [p2].nes" + +23.10.03 + + added 231 mapper (VirtuaNES source), "20-in-1 (Mapper 231) [p1][!].nes" + fixed 115 mapper (VirtuaNES source), "Yuu Yuu Hakusho Final - Makai Saikyou Retsuden [T-Chi].nes" glitches + + added debug 200 mapper for new dump "1200-in-1.nes" + added debug 201 mapper for new dump "21-in-1 [2006-CA].nes" + added debug 202 mapper for new dump "150-in-1.nes" + +18.10.03 + + added 254 mapper (VirtuaNES source), "Pikachu Y2k [decrypted].nes + added 111 mapper (...), "Ninja Ryuukenden (J) [T-Chi] [mapper 111].nes + fixed 113 mapper (VirtuaNES source), "16 Mahjang [!].nes" works again + +14.10.03: + + added 012 mapper (VirtuaNES source) + fixed 045 mapper (NESten source), "Super 8-in-1 [p1][!].nes" some glitches + added 058 mapper (... source), "68-in-1 (Game Star - HKX5268) [!].nes" + added 060 mapper (...), "Reset Based 4-in-1.nes" + added 062 mapper (NESten source), "Super 700-in-1 [!].nes" + fixed 090 mapper (...), "Final Fight 3 [!].nes" reset mode + fixed 113 mapper "16 Mahjang [!].nes" some glitches + added 133 mapper (FCEU UNIF Code), "Jovial Race (Sachen) [!].nes" + added 188 mapper (VirtuaNES source) + added 230 mapper (... source) + added 243 mapper (...), "Mei Nu Quan (Honey Peach).nes" + added 244 mapper (VirtuaNES source) diff --git a/zzz_todo.txt b/zzz_todo.txt new file mode 100644 index 0000000..2bb7e07 --- /dev/null +++ b/zzz_todo.txt @@ -0,0 +1,282 @@ +N - Маппер взят из Nestopia +V - Маппер взят из VirtuaNES (Большая часть кода мапперов взята из JJJNester) +F - Добавлено в процессе разработки самим автором FCEUltra Xodnizel'ом +T - Маппер взят из NESten +D - Маппер взят из Nintendulator + +Сделать: + + исправить эмуляцию FDS звука. + проверка наличия банков данных в UNIF файле. + слить код мапперов и UNIF драйверов. + переписать загрузчик iNES под внутрнний формат загрузчика UNIF, добавить список дайверов с контрольными суммами всех известных ромов и избавиться от потребности в iNES заголовках. + +N 004 mapper - "Long Zhu Ying Xiong (As) [p1].nes" не работает из-за повторного включения NMI во время текущего. + 016 mapper - as like 157, добавить EEPROM эмуляцию. + 126 mapper - "PowerJoy 84-in-1 (PJ-008) (Unl) [!]" не эмулируется (Nestopia) + 253 mapper - плохая синхронизация IRQ, проблема в вычислениях тайминга или в ядре? + +Готово: + + 003 mapper - "Hanafuda Yuukyou Den - Nagarebana Oryuu (Hacker)" - need redump + 253 mapper - "Dragon Ball Z - Kyoushuu! Saiya Jin (Ch)" срывает грышу графике в середине начального диалога + 002 mapper - "Golden KTV (Ch) [!]" не работает после титула + переписать весь код мапперов под новый загрузчик iNES. + 004 mapper - "Hero on Devil Lands (Ch)" - вторая половина палитры произвольно чистится в черный или заполняется рандомными цветами, персонажи то видны нормально, то ходят ерными тенями + 001 mapper - "Mechanized Attack" holds at the demo sequence + 019 mapper - проблемы мирроринга в Dream Master + 004 mapper - Проверить, как работает Close функция, если она переназначена в отдельном сорсе, но используется глобальный параметрв WRAM в инит функции, скорее всего остается невысвобожденная память +V 252 mapper - неправильно работает "San Guo Zhi (As).nes" + 226 mapper - добавить переключение резетом двух частей картриджа, удалить лишний UNIF драйвер для дубликата дампа в UNIF формате... + 115 mapper - Bao Qing Tian (Unl) испорчена палитра + 003 mapper - "Minna no Taabou no Nakayoshi Daisakusen (J)" doesn't work + 012 mapper - check + 048 mapper - проверить, нужен ли регистр переключения мирроринга 9000. + 003 mapper - "Hayauchi Super Igo (J).nes" don't work properly + 163 mapper - Lei Dian Huang Bi Ka Qiu Chuan Shuo (NJ046) вылет на улице при поппытке скролла вправо, защита 163 маппера + 015 mapper - fixed, "Phantasy Star 2" now work fine + 036 mapper - new dump "Policeman (Unl) [!].nes", "Strike Wolf (Unl) [!].nes" + 038 mapper - new dump "Crime Busters (Unl) [!].nes" + 045 mapper - fixed again (?) + 083 mapper - hacked for supporting two CHR bankswitching modes, dip switch for changing title screen + 103 mapper - (Kevtris) "Doki Doki Panic" FDS port + 106 mapper - (Kevtris) "Super Mario Bros 3 (Unl)" pirate version + 108 mapper - new FDS hack "Meikyuu Jiin Dababa" + 112 mapper - "Fighting Hero III (Unl)" now supported + 117 mapper - (tpu) fixed "Crayon Shin-Chan" problems + 120 mapper - (Kevtris) "3D World Runner" FDS port version + 121 mapper - (Kevtris) "Panda Prince (Unl)[!].nes" now works fine + 134 mapper - (Kevtris) "2-in1 - Family Kid & Aladdin 4 (T)" problems + 136 mapper - (Nestopia) UNIF board SA-002 with copy protection by Sachen + 142 mapper - wrapper to KS7032 UNIF board, now emulated SMB2j Kaiser Pirate + 160 mapper - redefined from 90 to UNL-SA009 board + 163 mapper - (tpu) fixed some Nanjing games graphics, (...) added protection register + 171 mapper - derived from MMC1 board with hardwired mirroring + 172 mapper - (nestopia) derived from UNL-22211 board + 173 mapper - Idea tec. another board (UNL-22211) with different protection bit + 175 mapper - "15-in-1 (Kaiser - KS-122) (Unl)" + 176 mapper - "Shu Qi Yu - Shu Xue Xiao Zhuan Yuan (Ch)", "Shu Qi Yu - Zhi Li Xiao Zhuan Yuan (Ch)", "Xing He Zhan Shi (Ch)" + 177 mapper - new HENGGEDIANZI dumps + 178 mapper - new dump "San Guo Zhong Lie Zhuan (Ch)" by Waxing (some roms unemulated due to emu problems) + 179 mapper - removed, redefined to 176 + 196 mapper - new dumps "SBM11", SMB Jurassic", "SMB17" + 222 mapper - fixed mirror register to allow to run "Super Mario Bros 8 (Unl) [!].nes" dump, + have been trying to compensate IRQ timing for famiclone with counter playing + UNL-TF1201 - new UNIF board for dump "Lethal Weapon (Tw)" + UNL-SL1632 - new UNIF board for dump "Samurai Spirits (Rex)" + UNL-TCU0.1 - Sachen board fixed + UNL-MALEE - fixed, now working properly (?) + BMC-FK23C - updated with new info + Opcode timing fixed. + UNL-3D-BLOCK - (debug) new UNIF board for "3D Block" dump + UNL-A9711 - (debug) new UNIF board for dump "Sonic 5" + UNL-CN22M - (debug) new UNIF board for dump "Mortal Kombat II (YOKO) [U][!].nes" + UNL-SMB2j - new UNIF board + UNL-SA009 - new UNIF Sachen board "Pipe 5 (Sachen)" bad dump + BMC-SG-2004 - new UNIF board for dump "Tetris Family 6-in-1" + BMC-SG-2013 - new UNIF board for dump "Tetris Family 12-in-1" + UNL-KS7032 - new UNIF board for dump "Bubble Bobble (FDS Hack) (Unl) [U][!].nes" + UNL-T-230 - new UNIF board derived from mapper 23 for Datach "Dragon Ball Z IV (Unl)[!].nes" hack + BMC-190in1 - new UNIF board for fun + UNL-AX5705 - new VRC4 type mapper for dump "Super Bros. Pocker Mali (Unl) [U][!].nes" + BMC-Ghostbusters63in1 - (Mad Dumper) new UNIF board for "63-in-1 (Ghostbusters63in1)[p1][U][!].nes" + BMC-N625092 - (debug) new UNIF board for BMC 700in1 dump, 400in1 too + UNL-KS7017 - new UNIF board for dump "Armana no Kiseki (Unl) (FDS Conversion)[U][!].nes" + debugger excluding breakpoint addresses. + +16.06.06 + + 068 mapper - (...) wrapper to NTBROM UNIF board without Double Casette System support + NES-NTBROM - new UNIF board for mapper Sunsoft mapper 68 with Double Casette System support + +29.05.06 + + 060 mapper - (...) defined as BMC-D1038 UNIF board with capability to change hardware dip switch to select game number in menu by pressing Reset. + 209 mapper - (...) fixed chr bankswitching in 4k mode, almost fixes "Power Rangers 3,4" and "Punch Out" + 113 mapper - (...) cleaned source, Sachen games redefined to normal sachen mappers, "deadboots" probably won't work ;). + 132 mapper - (...) UNL-22211 UNIF board wrapper + 158 mapper - (...) removed, redefined to 118 + 195 mapper - (...) defined for "Crystalis (C)", "Captain Tsubasa Vol 2 - Super Striker (C)" + 198 mapper - (...) defined for "Tenchi o Kurau II - Shokatsu Koumei Den (J) (C)" + 199 mapper - (Martin) defined for new dumps "Dragon Ball Z 2 - Gekishin Freeza! (C)", "Dragon Ball Z Gaiden - Saiya Jin Zetsumetsu Keikaku (C)" + BMC-70in1 - fixed UNIF board for supporting menu selecting by pressing Reset + BMC-FK23C - fixed UNIF board for dump "4-in-1 (FK23C8244) [p1][U][!].nes" + UNL-22211 - new UNIF board for dump "Qi Wang - Chinese Chess (MGC-001) [U][!].nes" + BMC-D1038 - UNIF board for mapper 60. + BMC-A65AS - new UNIF board for dump "3-in-1 (N068) [p1][U][!].nes" + BMC-GF1004 - new UNIF board for dump "4-in-1 (JY-066) [p1][U][!].nes" + UNL-6035052 - new UNIF board for dump "Contra Fighter (Unl) [U][!].nes" + +10.04.06 + + 045 mapper - (...) fixed, correct emulation of some dumps. + 115 mapper - (...) fixed, looks like logic of this mapper little different than we has know. + 188 mapper - (...) fixed, additional songs are selectable. + 189 mapper - (...) fixed for new dump "Master Fighter II (As)[!].nes" + 235 mapper - (...) modified iNES loader source to allow loading iNES ROMS with 256 PRG banks. + board S74LS374N fixes for supporting new dumps... + boadr SHero new Sachen dump + board T-262 new multigame cart dump + DInput device mode changed to BACKGROUND. Now with enabled flag "Acvive while focus lost" it can be used for playing two or more FCEUs with one keyboard or joystic at same time. + +19.03.06 + + 004 mapper - (...) "Yong Zhe Dou E Long - Dragon Quest VI (As).nes" fixed CHR glitch (probably others). + (Nestopia) forced to MMC3 RevB board IRQ, fixes map mode "My Life My Love - Boku no Yume - Watashi no Negai (J).nes", + wave effect at level start for "Mickey Mouse 3 - Yume Fuusen (J).nes", "Kid Klown (U).nes", probaly crashes others non-RevB games... + Small fix to mapper source to allow to run "Colour 2001 Streetfighter II (Unl) [!].nes", + "King of Fighters 99 [p1].nes" and "Super HIK 7-in-1 (Multicart k7006) [p1][!].nes" + 037 mapper - (...) "Super Mario Bros. + Tetris + Nintendo World Cup (E) [!]" redefined from 47 by CRC check. + 057 mapper - (...) small modification for switching menu mode by pressing reset button, moved to UNIF borads source + 058 mapper - (...) small mirroring fix, moved to UNIF boards source + 074 mapper - (...) defined for "Di 4 Ci - Ji Qi Ren Dai Zhan (As).nes" and "Ji Jia Zhan Shi (As).nes", "Jia A Fung Yun (Chinese).nes" now fully playable. + 090 mapper - (Kevin Horton) another IRQ source mode 00 (M2 CPU Cycles), now "45-in-1 (Unl) (As)[U][!].nes" emulated perfectly ;) + (...) fixed nametable handling bug, fixed 211 mapper too + (...) fixed register initialization, now "Super Contra 3 (Unl) [p1].nes" starts properly, fixed "black boxes" instead players + in "Goal!!" at "45-in-1 (JY-120A)(As) [U][!].nes" multigame cart while they crossing bottom part of playing screen. + 163 mapper - (TPU) fixed screen error in "Harvest Moon (C).nes" + 211 mapper - (...) removed old source, concatenated with main 90 mapper source after fixing nametable problem + mapper have hardware nametable ROM mapping enabled by default indepentantly from nametable mode + 181 mapper - (...) defined for "Seicross (J)(Redump) [!].nes", this mapper have opposite protection bits values than normal 185. + 185 mapper - (...) now supports all different mapper board in one mapper source without hacks (little dirty ;)) + 187 mapper - (Nestopia) "King of Fighters 96 [p1].nes", "Sonic 3D Blast 6 (Unl) [h1].nes", + "Street Fighter Alpha Zero 97 [!].nes" now playable, + "Street Fighter Zero 2 [p1].nes" background fixed + 192 mapper - (...) defined for "Ying Lie Qun Xia Zhuan (Chinese)" instead 74 mapper. + 194 mapper - (...) defined for "Dai-2-Ji - Super Robot Taisen (As)" instead 74 mapper. + 222 mapper - (...) "Dragon Ninja (J) [p1][!].nes" works properly + UNL-KOF97 board - new UNIF board for "King of Fighters 97 (Rex Soft.) [U][!].nes" + UNL-Super24 board - fixed again, now fixed mirroring problem finally + UNL-8157 board - small fix allows to see another game menu after reset + BMC-42in1ResetSwitch - new UNIF board for "42-in-1 (Reset Switch) [U][p1][!].nes" + BMC-64in1NoRepeat - new UNIF board for "64-in-1 (No Repeat) [U][p1][!].nes" + BMC-70in1 - new UNIF board for "70-in-1 [U][p1][!].nes" + BMC-70in1B - new UNIF board for "800-in-1 [U][p1][!].nes" + +19.11.05 + + "Q-Boy" moved to mapper 141 + mapper 148 moved to 191 + added sachen mappers 137,138,139,141,143,145,147,148,149,150 + PowerShot Gun - работает кнопка кидания гранат. + UNL-SuperHIK8in1 unif board - (...) UNIF wrapper for "Super 8-in-1 99 King Fighter [p1].nes" converted to UNIF format with correct CHR banks order. + +31.10.05 + + 006 mapper - (...) добавлен дополнительынй режим в FFE маппер, позволяющий запускать "Mi Hun Che (As) [hFFE].nes" + 090 mapper - (...) код маппера скорректирован для поддержки нового дампа "45-in-1 (Unl) (As) [b1].nes" + 148 mapper - (...) переназначен с 74 маппера для игры "Sugoro Quest - Dice no Senshitachi (As) [a1].nes" + 133 mapper - (...) старый код маппера удален, новый использует UNIF код. + 183 mapper - (...) новый дамп "Suikan Pipe (Gimmick bootleg)[p1][!].nes" + 186 mapper - (...) новый дамп "Famicom Study Box.nes" + 248 mapper - удален, "Bao Qing Tian (As).nes" переназначен на 115 mapper. + KONAMI-QTAI unif board - (...) частичная поддержка CAI by Konami. + DREAMTECH01 unif board - (...) новый дамп "Korean Igo (Unl) [U][!].nes" + UNL-H2288 unif board - (Nintendulator) заработал "Earth Worm Jim 2 (Pirate Original).nes", черт бы побрал эту защиту. + +23.01.05 + + 114 mapper - (...) код маппера переписан и перенесен в общий код ММС3 + 215 mapper - (...) код маппера переписан и перенесен в общий код ММС3, новый дамп "3-in-1 Super 308 (Super Game)[!].nes" + 217 mapper - (...) код маппера переписан и перенесен в общий код ММС3, новый дамп "Golden Card 6-in-1 (SPC009) (Super Game)[!].nes" + debugger - двойной клик по окну дизассемблера добавляет точку остановка на текущую инструкцию + +02.01.05 + + 042 mapper - (...) маленькая коррекция маппера, позволяющая нормально играть ромке "Ai Senshi Nicol (As).nes" + 090 mapper - (...) небольшой апдейт, позволяющий увидеть аппаратно преключаемые варианты игры на одном картридже нажатием резета. + (...) дополнения в систему отсчета IRQ, позволившие правильно показать рафику в "Aladdin - Return of Jaffar, The [p1].nes" + 163 mapper - (...) новый дамп от TPU. + 191 mapper - (VNES) "Sachen Q-Bert.nes" + 211 mapper - (...) небольшая корректировка для правильной работы нового дампа "Tiny Toon Adentures 6 (Pirate Original) [!].nes" + 212 mapper - (...) снова работает "Super HIK 300-in-1 (1994).nes" + 216 mapper - (...) новый дамп с дополнительным устройством для чтения SIM карт на картридже - "Bonza" + 245 mapper - (...) исправлен старый баг, из-за которого не отображались банки графического ПЗУ. + Super24 board - (Nintencer) теперь работает. + Исправлен PPUView в соответствии с кодом FCEUexD + +02.01.05 + + 214 mapper - debug "Super Gun 24-in-1 [p2].nes" + 113 mapper - (VNES) "Mind Blower Pak [p1].nes" displays correct CHR page + Переназначен с 160 маппера на 90 через проверку CRC ром "Aladdin (E) [p1].nes" + Добавлена функция сохранения дампа видеопамяти в файл + +30.08.04 + + 060 mapper - переопределен на совершенно иную плату простых многоигровок, подобную 61,62,200-204, + теперь работают "Super 35-in-1 (6-in-1 VT5201) [p1].nes","TN 95-in-1 (6-in-1) [p1].nes" + "Reset Based 4-in-1 [p1].nes" больше не поддерживается + 165 mapper - плохо эмулируется "Fire Emblem (Unl).nes" (почти корректная эмуляция) + 167 mapper - не эмулируются "SuporV40.nes", "Supor English (Chinese).nes" + 166 mapper - переназначен с 15 (и 167) для "Suborv10 (Russian).nes" + 015 mapper - возвращен в исходное состояние + 213 mapper - новый дамп "9999999-in-1 [p2].nes" + Добавлена поддержка клавиатуры Subor. Теперь работают "Subor" V1.0,V2.0,V4.0, "Study and Game 31-in-1", "Edu (As)" + Добавлено автоматическое включение клавиатуры Subor для соответствующих игр + Добавлено окно просмотрщика видеопамяти (Исходный код взят из FCEUd от Dragon Eye Studio) + Переопределен через проверку CRC 58 маппер ("Study and Game") на 241 + +09.05.04 + + 164 mapper - (...) fixed "San Guo Zhi 2 (Chinese).nes" now works + +21.04.04 + + 164 mapper - (Xod) "Final Fantasy V (Unl).nes" + 165 mapper - хреново эмулируется "Fire Emblem (Unl).nes" +! 212 mapper - новый дамп "Super HIK 300-in-1 (1994).nes" + 215 mapper - новый дамп "Mortal Combat 3 (Extra 60).nes" + Добавлен выход кнопкой Escape + Добавлена проверка на наличие в имени файла кода (E) и включение режима PAL. + +23.12.03 + +! 201 mapper - код исправлен +! 202 mapper - код исправлен +! 204 mapper - отладка "64-in-1 [p1].nes" (simple) +! 208 mapper - переназначен с 186 маппера +! 211 mapper - отладочный код для "MK2.nes" и "DKC1.nes" + +10.11.03 + +! 060 mapper - код переписан +! 186 mapper - все еще не работает правильно +! 200 mapper - код исправлен +! 203 mapper - отладка "35-in-1 [p1].nes" (simple) +! 205 mapper - отладка "15-in-1 [p2].nes" (mapper #004 based) + +23.10.03 + +! 200 mapper - "1200-in-1.nes" +! 201 mapper - "21-in-1 [2006-CA].nes" +! 202 mapper - "150-in-1.nes" +!V231 mapper - не эмулируется ("20-in-1 (Mapper 231) [p1][!].nes") +!V115 mapper - неверная видеостраница "Yuu Yuu Hakusho Final - Makai Saikyou Retsuden [T-Chi].nes" + +18.10.03 + +! 254 mapper - не эмулируется ("Pikachu Y2k [decrypted].nes") +! 111 mapper - не эмулируется "Ninja Ryuukenden (J) [T-Chi] [mapper 111].nes" +!V113 mapper - неверная видеостраница в "16 Mahjang [!].nes" теперь точно пашет. + +14.10.03: + +V 012 mapper - некорректный банк видеопамяти при отображении спрайтов игроков "Dragon Ball Z 5 (Chinese).nes" +!T045 mapper - "Super 8-in-1 [p1][!].nes" некорректная видеостраница +!F050 mapper - не эмулируется +! 058 mapper - не эмулируется ("68-in-1 (Game Star - HKX5268) [!].nes") +! 060 mapper - не эмулируется ("Reset Based 4-in-1.nes") +!T062 mapper - не эмулируется ("Super 700-in-1 [!].nes") +! 090 mapper - не работает переключение режимов в "Final Fight 3 [!].nes" +!F091 mapper - некорректно эмулируется "Street Fighter 3.nes","Street Fighter 2 Pro.nes" +!V113 mapper - неверная видеостраница в "16 Mahjang [!].nes". +!F158 mapper - не эмулируется +! 133 mapper - не эмулируется ("Jovial Race (Sachen) [!].nes") +! 188 mapper - не эмулируется +!F193 mapper - не эмулируется +! 230 mapper - не эмулируется (Неверно определяется Мирроринг) +! 243 mapper - не эмулируется ("Mei Nu Quan (Honey Peach).nes") +V 244 mapper - не эмулируется + +